This repository has been archived by the owner on Dec 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add metrics submission support (#41)
* Add metrics submission support. * Bump version number in reporting. * Add and adjust existing unit tests. Fix version number. Rework how sessions are handled in this package. * Use axios for sending session metric events. * correct application.version * fix app version and name in metrics * simplify application name and version passing * add unknown string if application name or version are not found * Provide default unkown value for app name and version if it cannot be found. * Update token in tests * Metrics client linter + support for full URLs to Backtrace instances * Use NODE_ENV to pass console or no to metrics instance Co-authored-by: Stone <[email protected]> Co-authored-by: kdysput <[email protected]>
- Loading branch information
1 parent
5fd4773
commit ba69393
Showing
17 changed files
with
1,907 additions
and
51 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "backtrace-node", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "Backtrace error reporting tool", | ||
"main": "./lib/index.js", | ||
"types": "./lib/index.d.ts", | ||
|
@@ -24,7 +24,7 @@ | |
"url": "[email protected]:backtrace-labs/backtrace-node.git" | ||
}, | ||
"scripts": { | ||
"test": "mocha --require ts-node/register -r ./tsconfig.json --project tsconfig.json test/**/*.ts", | ||
"test": "NODE_ENV=test mocha --require ts-node/register -r ./tsconfig.json --project tsconfig.json test/**/*.ts", | ||
"lint": "tslint -p ./tsconfig.json", | ||
"format": "prettier --write \"source/**/*.ts\" \"source/**/*.js\"", | ||
"build": "tsc" | ||
|
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const APP_NAME = 'backtrace-node'; | ||
export const VERSION = '1.2.0'; | ||
export const LANG = 'nodejs'; | ||
export const THREAD = 'main'; |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import { BacktraceClientOptions } from '..'; | ||
import { currentTimestamp, getEndpointParams, post, uuid } from '../utils'; | ||
|
||
/** | ||
* Handles Backtrace Metrics. | ||
*/ | ||
export class BacktraceMetrics { | ||
private readonly universe: string; | ||
private readonly token: string; | ||
private readonly hostname: string; | ||
|
||
private summedEndpoint: string; | ||
private uniqueEndpoint: string; | ||
|
||
private sessionId: string = uuid(); | ||
|
||
constructor( | ||
configuration: BacktraceClientOptions, | ||
private readonly attributeProvider: () => object, | ||
private readonly _logger: { error(...data: any[]): void } | undefined, | ||
) { | ||
if (!configuration.endpoint) { | ||
throw new Error(`Backtrace: missing 'endpoint' option.`); | ||
} | ||
const endpointParameters = getEndpointParams(configuration.endpoint, configuration.token); | ||
if (!endpointParameters) { | ||
throw new Error(`Invalid Backtrace submission parameters. Cannot create a submission URL to metrics support`); | ||
} | ||
const { universe, token } = endpointParameters; | ||
|
||
if (!universe) { | ||
throw new Error(`Backtrace: 'universe' could not be parsed from the endpoint.`); | ||
} | ||
|
||
if (!token) { | ||
throw new Error(`Backtrace: missing 'token' option or it could not be parsed from the endpoint.`); | ||
} | ||
|
||
this.universe = universe; | ||
this.token = token; | ||
this.hostname = configuration.metricsSubmissionUrl ?? 'https://events.backtrace.io'; | ||
|
||
this.summedEndpoint = `${this.hostname}/api/summed-events/submit?universe=${this.universe}&token=${this.token}`; | ||
this.uniqueEndpoint = `${this.hostname}/api/unique-events/submit?universe=${this.universe}&token=${this.token}`; | ||
|
||
this.handleSession(); | ||
} | ||
|
||
/** | ||
* Handle persisting of session. When called, will create a new session. | ||
*/ | ||
private handleSession(): void { | ||
// If sessionId is not set, create new session. Send unique and app launch events. | ||
this.sendUniqueEvent(); | ||
this.sendSummedEvent('Application Launches'); | ||
} | ||
|
||
/** | ||
* Send POST to unique-events API endpoint | ||
*/ | ||
public async sendUniqueEvent(): Promise<void> { | ||
const attributes = this.getEventAttributes(); | ||
const payload = { | ||
application: attributes.application, | ||
appversion: attributes['application.version'], | ||
metadata: { | ||
dropped_events: 0, | ||
}, | ||
unique_events: [ | ||
{ | ||
timestamp: currentTimestamp(), | ||
unique: ['guid'], | ||
attributes: this.getEventAttributes(), | ||
}, | ||
], | ||
}; | ||
|
||
try { | ||
await post(this.uniqueEndpoint, payload); | ||
} catch (e) { | ||
this._logger?.error(`Encountered error sending unique event: ${e?.message}`); | ||
} | ||
} | ||
|
||
/** | ||
* Send POST to summed-events API endpoint | ||
*/ | ||
public async sendSummedEvent(metricGroup: string): Promise<void> { | ||
const attributes = this.getEventAttributes(); | ||
|
||
const payload = { | ||
application: attributes.application, | ||
appversion: attributes['application.version'], | ||
metadata: { | ||
dropped_events: 0, | ||
}, | ||
summed_events: [ | ||
{ | ||
timestamp: currentTimestamp(), | ||
metric_group: metricGroup, | ||
attributes: this.getEventAttributes(), | ||
}, | ||
], | ||
}; | ||
|
||
try { | ||
await post(this.summedEndpoint, payload); | ||
} catch (e) { | ||
this._logger?.error(`Encountered error sending summed event: ${e?.message}`); | ||
} | ||
} | ||
|
||
private getEventAttributes(): { [index: string]: any } { | ||
const clientAttributes = this.attributeProvider() as { | ||
[index: string]: any; | ||
}; | ||
const result: { [index: string]: string } = { | ||
'application.session': this.sessionId, | ||
}; | ||
|
||
for (const attributeName in clientAttributes) { | ||
if (Object.prototype.hasOwnProperty.call(clientAttributes, attributeName)) { | ||
const element = clientAttributes[attributeName]; | ||
const elementType = typeof element; | ||
|
||
if (elementType === 'string' || elementType === 'boolean' || elementType === 'number') { | ||
const attributeValue = element.toString(); | ||
if (attributeValue) { | ||
result[attributeName] = attributeValue; | ||
} | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
} |
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
Oops, something went wrong.