A simple metrics (invocation count, run-time) tool in JavaScript/TypeScript/GoogleAppsScript
Tags: typescript, javascript, googleappsscript
Published: 2020-07-26 14:01:19

I was wanting a simple way of keeping invocation/usage counts and function run-times. The example below also demonstrates the use of the `Me()` function that I wrote about recently in [A Me() function for JavaScript and Google Apps Script](https://dev.to/bugmagnet/a-me-function-for-javascript-and-google-apps-script-299g).

The TypeScript code is very similar to the JavaScript so I'll just post the JavaScript and you can annotate it as necessary should you want to use it in a TypeScript project. 
```javascript
var metrics = {
    Counts: {},
    Times: {},
    count: function (func) {
        if (void 0 === this.Counts[func]) {
            this.Counts[func] = 1;
        }
        else {
            this.Counts[func] = this.Counts[func] + 1;
        }
    },
    report: function (func) {
        if (void 0 !== this.Counts[func]) {
            console.log("%s: %s Times", func, this.Counts[func]);
        }
        if (void 0 !== this.Times[func]) {
            console.log("%s: %s msec", func, this.Times[func][1] - this.Times[func][0]);
        }
    },
    start: function (func) {
        this.Times[func] = [new Date().valueOf(), 0];
    },
    stop: function (func) {
        this.Times[func][1] = new Date().valueOf();
    },
    reportAll: function () {
        var _this = this;
        var keys = new Set();
        Object.keys(this.Counts).forEach(function (key) { return keys.add(key); });
        Object.keys(this.Times).forEach(function (key) { return keys.add(key); });
        keys.forEach(function (key) { return _this.report(key); });
    }
};
```
So from this metrics object we expose the following methods: `count`, `report`, `start`, `stop` and `reportAll`. We also expose two dictionaries but we leave the above methods to interact with them. By encapsulating them in the `metrics` object we save ourselves having to pollute the global namespace.

`start` and `stop` are used to record the start and stop times of a given function or block of code. `count` is used to log that a particular function or block has been executed.

`report` reports a named run-time and/or named count, and `reportAll` reports all the run-times and named counts.

On the assumption that the `Me()` function is also available, a possible usage might be:
```javascript
function foo() {
    var me = Me();
    metrics.count(me);
    metrics.start(me);
    var accum = 0;
    for (var i_1 = 0; i_1 < 100; i_1++) {
        accum += Math.pow(2, i_1);
    }
    metrics.stop(me);
}
function bar() {
    var me = Me();
    metrics.count(me);
    metrics.start(me);
    foo();
    metrics.stop(me);
}
foo();
for (var i = 0; i < 10; i++)
    bar();
metrics.reportAll();
```
This might then show something like this:
```
foo: 11 Times
foo: 0 msec
bar: 10 Times
bar: 2 msec
```
Some weaknesses with this approach are immediately visible, most notably that the run-time is the last run, not (perhaps more helpfully) an average of all runs. 

The other weakness, and this is also an acknowledged issue with `Me()` is that this isn't particularly performant code. However, it was put together as a Development tool to help me find performance bottle-necks.