<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*jslint sub: true */

Date.now = (Date.now || function () {  // thanks IE8
    return new Date().getTime();
});

/**
 * @description The storage service implementation
 * @constructor
 * @param {Object} config The configuration describing the characteristics of the storage to be created.
 */
var MetricsService = function MetricsService(config) {
    this.collector                 = {"default": []};
    this.globalHandlers            = {"transactionEnd": []};
    this.bootstrap                 = {};
    this.registeredPlugins         = {};
    this.pluginInstances           = {};
    this.beaconProviders           = {};
    this.transactions              = {};
    this.doneBootstrap             = false;
    this.clearCompleteTransactions = true; //In PTEST Mode this is set to false (see initialize method)

    // #if {"excludeModes" : ["PRODUCTION"]}
    this["collector"] = this.collector; // Protected API to access the raw marks
    // #end
};

MetricsService.TIMER   = (window.performance && window.performance.now) ? window.performance.now.bind(performance) : Date.now.bind(Date);
MetricsService.START   = 'start';
MetricsService.END     = 'end';
MetricsService.STAMP   = 'stamp';
MetricsService.DEFAULT = 'default';

MetricsService.prototype = {
    initialize: function() {
        this.getPageStartTime();
        this.transactionStart('bootstrap','app');
        this.initializePlugins();
        // #if {"modes" : ["PTEST"]}
            this.setClearCompletedTransactions(false);
        // #end

    },
    instrument: function (instance, method, ns, async, before, after, override) {
        var self     = this,
            original = instance[method],
            beforeFn = typeof before === 'function',
            afterFn  = typeof after === 'function';

        instance[method] = function () {
            var mark = self.markStart(ns, method),
                ret;

            if (beforeFn) {
                before.apply(this, Array.prototype.concat.apply(mark, arguments));
            }

            if (override) {
                ret = override.apply(this, Array.prototype.concat.apply(original, arguments));
            } else {
                ret = original.apply(this, arguments);
            }

            if (async) {
                return ret;
            }

            mark = self.markEnd(ns, method);

            if (afterFn) {
                after.apply(this, Array.prototype.concat.apply(mark, arguments));
            }

            return ret;
        };

        instance[method]["__original"] = original;
    },
    unInstrument: function (instance, method) {
        var original = instance[method]["__original"];
        delete instance[method]["__original"];
        instance[method] = original;
    },
    initializePlugins: function () {
        for (var plugin in this.registeredPlugins) {
            this.initializePlugin(plugin, this.registeredPlugins[plugin]);
        }
    },
    initializePlugin: function (pluginName, PluginContructor) {
        var pluginInstance = typeof PluginContructor === 'function' ? new PluginContructor() : PluginContructor;
        this.pluginInstances[pluginName] = pluginInstance;
        this.collector[pluginName] = [];
        pluginInstance["initialize"](this);
    },
    applicationReady: function () {
        this.bootstrapMark("applicationReady");
        this.doneBootstrap = true;

        var bootstrap = this.getBootstrapMetrics();
        this.transactionEnd('bootstrap','app', function (transaction, callback) {
            transaction["marks"]["bootstrap"] = bootstrap;
            callback();
        });

        // #if {"modes" : ["PRODUCTION"]}
        var beacons = this.beaconProviders;
        if ($A.util.isEmpty(beacons)) {
            this.disablePlugins();
            this.clearMarks();
        }
        // #end        
    },
    onTransactionEnd: function (callback) {
        this.globalHandlers["transactionEnd"].push(callback);
        this.hasGlobalHandlers = true;
    },
    inTransaction: function () {
        return !$A.util.isEmpty(this.transactions);
    },
    transaction: function (ns, name, config) {
        this.createTransaction(ns, name, config);
        return this.transactionEnd(ns, name, function (t) {
            t["duration"] = 0; // STAMP so no duration
        });
    },
    transactionUpdate: function (ns, name, config) {
        config = config || {};
        var id          = (ns || MetricsService.DEFAULT) + ':' + name,
            transaction = this.transactions[id];
        if (transaction) {
            transaction["config"] = $A.util.apply(transaction["config"], config, true, true);
        }
    },
    transactionStart: function (ns, name, config) {
        return this.createTransaction(ns, name, config);
    },
    transactionEnd: function (ns, name, config) {
        config = config || {};
        var id             = (ns || MetricsService.DEFAULT) + ':' + name,
            transaction    = this.transactions[id],
            transactionCfg = (transaction && transaction["config"]) || {},
            beacon         = this.beaconProviders[ns] ? this.beaconProviders[ns] : this.beaconProviders[MetricsService.DEFAULT],
            postProcess    = typeof config === 'function' ? config : (config["postProcess"] || transactionCfg["postProcess"]);

        if (transaction && (beacon || postProcess || !this.clearCompleteTransactions)) {
            var skipPluginPostProcessing = config["skipPluginPostProcessing"] || transactionCfg["skipPluginPostProcessing"],
                context = transactionCfg["context"] || {},
                parsedTransaction = {
                    "id"            : id,
                    "ts"            : transaction["ts"],
                    "duration"      : this.time() - transaction["ts"],
                    "pageStartTime" : this.pageStartTime,
                    "marks"         : {},
                    "context"       : $A.util.apply(context, config["context"], true, true)
                };

            for (var plugin in this.pluginInstances) {
                var instance = this.pluginInstances[plugin];

                if (this.collector[plugin].length) { // If we have marks for that plugin
                    var pluginCollector = this.collector[plugin],
                        initialOffset   = transaction["offsets"][plugin],
                        tMarks          = pluginCollector.slice(initialOffset),
                        parsedMarks     = instance.postProcess && !skipPluginPostProcessing ? instance.postProcess(tMarks) : tMarks;

                    if (parsedMarks && parsedMarks.length) {
                        parsedTransaction["marks"][plugin] = parsedMarks;
                    }
                }
            }

            if (postProcess) {
                postProcess(parsedTransaction, this.signalBeacon.bind(this, beacon, parsedTransaction));
            } else {
                this.signalBeacon(beacon, parsedTransaction);
            }

            //#if {"excludeModes" : ["PRODUCTION"]}
                if (this.hasGlobalHandlers) {
                    this.callHandlers("transactionEnd", parsedTransaction);
                }
            //#end
<commit_msg>fixing metricsService collector<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*jslint sub: true */

Date.now = (Date.now || function () {  // thanks IE8
    return new Date().getTime();
});

/**
 * @description The storage service implementation
 * @constructor
 * @param {Object} config The configuration describing the characteristics of the storage to be created.
 */
var MetricsService = function MetricsService(config) {
    this.collector                 = {"default": []};
    this.globalHandlers            = {"transactionEnd": []};
    this.bootstrap                 = {};
    this.registeredPlugins         = {};
    this.pluginInstances           = {};
    this.beaconProviders           = {};
    this.transactions              = {};
    this.doneBootstrap             = false;
    this.clearCompleteTransactions = true; //In PTEST Mode this is set to false (see initialize method)

    // #if {"excludeModes" : ["PRODUCTION"]}
    this["collector"] = this.collector; // Protected API to access the raw marks
    // #end
};

MetricsService.TIMER   = (window.performance && window.performance.now) ? window.performance.now.bind(performance) : Date.now.bind(Date);
MetricsService.START   = 'start';
MetricsService.END     = 'end';
MetricsService.STAMP   = 'stamp';
MetricsService.DEFAULT = 'default';

MetricsService.prototype = {
    initialize: function() {
        this.getPageStartTime();
        this.transactionStart('bootstrap','app');
        this.initializePlugins();
        // #if {"modes" : ["PTEST"]}
            this.setClearCompletedTransactions(false);
        // #end

    },
    instrument: function (instance, method, ns, async, before, after, override) {
        var self     = this,
            original = instance[method],
            beforeFn = typeof before === 'function',
            afterFn  = typeof after === 'function';

        instance[method] = function () {
            var mark = self.markStart(ns, method),
                ret;

            if (beforeFn) {
                before.apply(this, Array.prototype.concat.apply(mark, arguments));
            }

            if (override) {
                ret = override.apply(this, Array.prototype.concat.apply(original, arguments));
            } else {
                ret = original.apply(this, arguments);
            }

            if (async) {
                return ret;
            }

            mark = self.markEnd(ns, method);

            if (afterFn) {
                after.apply(this, Array.prototype.concat.apply(mark, arguments));
            }

            return ret;
        };

        instance[method]["__original"] = original;
    },
    unInstrument: function (instance, method) {
        var original = instance[method]["__original"];
        delete instance[method]["__original"];
        instance[method] = original;
    },
    initializePlugins: function () {
        for (var plugin in this.registeredPlugins) {
            this.initializePlugin(plugin, this.registeredPlugins[plugin]);
        }
    },
    initializePlugin: function (pluginName, PluginContructor) {
        var pluginInstance = typeof PluginContructor === 'function' ? new PluginContructor() : PluginContructor;
        this.pluginInstances[pluginName] = pluginInstance;
        this.collector[pluginName] = [];
        pluginInstance["initialize"](this);
    },
    applicationReady: function () {
        this.bootstrapMark("applicationReady");
        this.doneBootstrap = true;

        var bootstrap = this.getBootstrapMetrics();
        this.transactionEnd('bootstrap','app', function (transaction, callback) {
            transaction["marks"]["bootstrap"] = bootstrap;
            callback();
        });

        // #if {"modes" : ["PRODUCTION"]}
        var beacons = this.beaconProviders;
        if ($A.util.isEmpty(beacons)) {
            this.disablePlugins();
            this.clearMarks();
        }
        // #end        
    },
    onTransactionEnd: function (callback) {
        this.globalHandlers["transactionEnd"].push(callback);
        this.hasGlobalHandlers = true;
    },
    inTransaction: function () {
        return !$A.util.isEmpty(this.transactions);
    },
    transaction: function (ns, name, config) {
        this.createTransaction(ns, name, config);
        return this.transactionEnd(ns, name, function (t) {
            t["duration"] = 0; // STAMP so no duration
        });
    },
    transactionUpdate: function (ns, name, config) {
        config = config || {};
        var id          = (ns || MetricsService.DEFAULT) + ':' + name,
            transaction = this.transactions[id];
        if (transaction) {
            transaction["config"] = $A.util.apply(transaction["config"], config, true, true);
        }
    },
    transactionStart: function (ns, name, config) {
        return this.createTransaction(ns, name, config);
    },
    transactionEnd: function (ns, name, config) {
        config = config || {};
        var id             = (ns || MetricsService.DEFAULT) + ':' + name,
            transaction    = this.transactions[id],
            transactionCfg = (transaction && transaction["config"]) || {},
            beacon         = this.beaconProviders[ns] ? this.beaconProviders[ns] : this.beaconProviders[MetricsService.DEFAULT],
            postProcess    = typeof config === 'function' ? config : (config["postProcess"] || transactionCfg["postProcess"]);

        if (transaction && (beacon || postProcess || !this.clearCompleteTransactions)) {
            var skipPluginPostProcessing = config["skipPluginPostProcessing"] || transactionCfg["skipPluginPostProcessing"],
                context = transactionCfg["context"] || {},
                parsedTransaction = {
                    "id"            : id,
                    "ts"            : transaction["ts"],
                    "duration"      : this.time() - transaction["ts"],
                    "pageStartTime" : this.pageStartTime,
                    "marks"         : {},
                    "context"       : $A.util.apply(context, config["context"], true, true)
                };

            for (var plugin in this.collector) {
                var instance = this.pluginInstances[plugin];

                if (this.collector[plugin].length) { // If we have marks for that plugin
                    var pluginCollector = this.collector[plugin],
                        initialOffset   = transaction["offsets"][plugin] || 0,
                        tMarks          = pluginCollector.slice(initialOffset),
                        parsedMarks     = (instance && instance.postProcess && !skipPluginPostProcessing) ? instance.postProcess(tMarks) : tMarks;

                    if (parsedMarks && parsedMarks.length) {
                        parsedTransaction["marks"][plugin] = parsedMarks;
                    }
                }
            }

            if (postProcess) {
                postProcess(parsedTransaction, this.signalBeacon.bind(this, beacon, parsedTransaction));
            } else {
                this.signalBeacon(beacon, parsedTransaction);
            }

            //#if {"excludeModes" : ["PRODUCTION"]}
                if (this.hasGlobalHandlers) {
                    this.callHandlers("transactionEnd", parsedTransaction);
                }
            //#end

{'fraction_non_alphanumeric': 0.12170488471066505, 'fraction_numerical': 0.0013339261894175188, 'mean_word_length': 2.0780058651026394, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5526472', 'n_tokens_mistral': 4055, 'n_tokens_neox': 3910, 'n_words': 938}