Last active
September 17, 2019 21:04
-
-
Save micwehrle/a363510b0f2627f5b3e5386a3bf35d5e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ClientConfig } from '../Core/types'; | |
import Http from '../utils/Http'; | |
import Url from '../utils/Url'; | |
import { ResourceResult, AutofiServices } from './types'; | |
import Resource from './AbstractResource'; | |
export interface MetricOpts extends ClientConfig { | |
autofiService: string; | |
metadata: any; | |
processInterval: number; | |
} | |
interface TimeEvent { | |
readonly key: string; | |
readonly duration: number; | |
readonly metadata: object; | |
} | |
export default class Metric extends Resource { | |
public metadata: any; | |
private autofiService: AutofiServices | string; | |
private processing = false; | |
private processInterval: number; | |
private queue: TimeEvent[] = []; | |
private statsMap: Map<string, number> = new Map(); | |
public constructor(opts: MetricOpts) { | |
super('metric'); | |
this.autofiService = opts.autofiService; | |
this.baseUri = opts.uris.METRIC_SERVICE_URI; | |
this.metadata = opts.metadata; | |
this.processInterval = opts.processInterval || 5000; | |
} | |
private formatKey(key: string): string { | |
return `${this.autofiService}:${key}`; | |
} | |
private initializeQueue(): void { | |
setInterval(this.processQueue.bind(this), this.processInterval); | |
this.processing = true; | |
} | |
private processQueue(): void { | |
if (this.queue.length === 0) { | |
return; | |
} | |
Http.fetch(Url.stringify(this.baseUri, `/metrics/stats`), { | |
method: 'POST', | |
body: JSON.stringify({ data: this.queue }), | |
headers: { 'Content-Type': 'application/json' }, | |
}); | |
this.queue = []; | |
} | |
/** | |
* Mark the start of a performance timer | |
* | |
* @param {string} key <scope:event> e.g., scraper:ui-handoff | |
* @returns {void} | |
* @memberof Metric | |
*/ | |
public mark(key: string): void { | |
this.statsMap.set(this.formatKey(key), Date.now()); | |
} | |
/** | |
* Time a performance event | |
* | |
* @param {string} key <scope:event> e.g., scraper:ui-handoff | |
* @param {object?} metadata | |
* @returns {void} | |
* @memberof Metric | |
*/ | |
public timing(key: string, metadata?: object): void { | |
const now = Date.now(); | |
const formattedKey = this.formatKey(key); | |
const startTime = this.statsMap.get(formattedKey); | |
if (!startTime) { | |
return; | |
} | |
const duration = now - startTime; | |
if (!this.processing) { | |
this.initializeQueue(); | |
} | |
const combinedMetadata = { ...this.metadata, ...metadata }; | |
this.queue.push({ key: formattedKey, duration, metadata: combinedMetadata }); | |
this.statsMap.delete(formattedKey); | |
} | |
/** | |
* Create a heartbeat | |
* | |
* @param {AutofiServices} [key] | |
* @param {any} data | |
* @returns {Promise<ResourceResult>} | |
* @memberof Metric | |
*/ | |
public async heartbeat( | |
key: AutofiServices | string = AutofiServices.None, | |
data?: any | |
): Promise<ResourceResult> { | |
return Http.fetch(Url.stringify(this.baseUri, `/metrics/heartbeat`), { | |
method: 'POST', | |
body: JSON.stringify({ | |
data, | |
key, | |
}), | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
}); | |
} | |
/** | |
* Returns metric data | |
* | |
* @param {any} data | |
* @returns {Promise<ResourceResult>} | |
* @memberof Metric | |
*/ | |
public async data(): Promise<ResourceResult> { | |
return Http.fetch(Url.stringify(this.baseUri, `/metrics/data`)); | |
} | |
} | |
/*************************************************************************/ | |
// express endpoint | |
const Metric = require('...'); | |
... | |
app.get('/', () => { | |
metricsClient = Metric.create({ | |
autofiService: 'Service Name', | |
... other config options | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment