From 43b27b6e39f8014a251e7d4cf54842dd2e8b1c70 Mon Sep 17 00:00:00 2001 From: Prathamesh Sonpatki Date: Fri, 8 Mar 2024 22:54:00 +0530 Subject: [PATCH 01/21] Remove deprecated code --- src/OpenAPM.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 5492a76..b64cc55 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -53,10 +53,6 @@ export interface OpenAPMOptions { requestDurationHistogramConfig?: HistogramConfiguration; /** Extract labels from URL params, subdomain, header */ extractLabels?: Record; - /** - * @deprecated This option is deprecated and won't have any impact on masking the pathnames. - * */ - customPathsToMask?: Array; /** Skip mentioned labels */ excludeDefaultLabels?: Array; /** Levitate Config */ @@ -84,7 +80,6 @@ export class OpenAPM extends LevitateEvents { private requestsCounter?: Counter; private requestsDurationHistogram?: Histogram; private extractLabels?: Record; - private customPathsToMask?: Array; private excludeDefaultLabels?: Array; public metricsServer?: Server; @@ -121,7 +116,6 @@ export class OpenAPM extends LevitateEvents { }; this.extractLabels = options?.extractLabels ?? {}; - this.customPathsToMask = options?.customPathsToMask; this.excludeDefaultLabels = options?.excludeDefaultLabels; this.initiateMetricsRoute(); @@ -266,7 +260,7 @@ export class OpenAPM extends LevitateEvents { // Skip the OPTIONS requests not to blow up cardinality. Express does not provide // information about the route for OPTIONS requests, which makes it very // hard to detect correct PATH. Until we fix it properly, the requests are skipped - // to not blow up the cardinality. + // to not blow up the cardinality. if (!req.route && req.method === 'OPTIONS') { return; } From 413ac80ecb9bf754d18cc48e093fe040b9e17c2a Mon Sep 17 00:00:00 2001 From: Prathamesh Sonpatki Date: Fri, 8 Mar 2024 23:12:32 +0530 Subject: [PATCH 02/21] Introduce mode for openapm - It can be either openmetrics or opentelemetry. --- playground/app.js | 1 + src/OpenAPM.ts | 53 ++++++++++++++++++++++++++----------------- src/clients/mysql2.ts | 18 +++++++++++---- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/playground/app.js b/playground/app.js index 7c4f52f..38a0a07 100644 --- a/playground/app.js +++ b/playground/app.js @@ -9,6 +9,7 @@ var { OpenAPM } = require('../dist/index.js'); var mysql2 = require('mysql2'); const openapm = new OpenAPM({ + // mode: 'opentelemetry', extractLabels: { tenant: { from: 'params', diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index b64cc55..a3963cd 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -32,7 +32,13 @@ export type DefaultLabels = | 'version' | 'host'; +export type OpenAPMMode = 'openmetrics' | 'opentelemetry'; + export interface OpenAPMOptions { + /** Mode - openmetrics or opentelemetry + * @default "openmetrics" + */ + mode?: OpenAPMMode; /** Route where the metrics will be exposed * @default "/metrics" */ @@ -70,6 +76,7 @@ const moduleNames = { const packageJson = getPackageJson(); export class OpenAPM extends LevitateEvents { + private mode: string; private path: string; private metricsServerPort: number; readonly environment: string; @@ -86,6 +93,9 @@ export class OpenAPM extends LevitateEvents { constructor(options?: OpenAPMOptions) { super(options); + + this.mode = options?.mode ?? 'openmetrics'; + // Initializing all the options this.path = options?.path ?? '/metrics'; this.metricsServerPort = options?.metricsServerPort ?? 9097; @@ -118,8 +128,12 @@ export class OpenAPM extends LevitateEvents { this.extractLabels = options?.extractLabels ?? {}; this.excludeDefaultLabels = options?.excludeDefaultLabels; - this.initiateMetricsRoute(); - this.initiatePromClient(); + if (this.mode === 'openmetrics') { + this.initiateMetricsRoute(); + this.initiatePromClient(); + } else { + console.log(this.mode + ' not supported'); + } } private getDefaultLabels = () => { @@ -274,29 +288,26 @@ export class OpenAPM extends LevitateEvents { ...parsedLabelsFromPathname }; - // Create an array of arguments in the same sequence as label names - const requestsCounterArgs = this.requestsCounterConfig.labelNames?.map( - (labelName) => { - return labels[labelName] ?? ''; - } - ); + if (this.mode === 'openmetrics') { + // Create an array of arguments in the same sequence as label names + const requestsCounterArgs = this.requestsCounterConfig.labelNames?.map( + (labelName) => { + return labels[labelName] ?? ''; + } + ); - if (requestsCounterArgs) { - this.requestsCounter?.labels(...requestsCounterArgs).inc(); - this.requestsDurationHistogram - ?.labels(...requestsCounterArgs) - .observe(time); + if (requestsCounterArgs) { + this.requestsCounter?.labels(...requestsCounterArgs).inc(); + this.requestsDurationHistogram + ?.labels(...requestsCounterArgs) + .observe(time); + } + } else { + console.log(this.mode + ' is not supported'); } } ); - /** - * Middleware Function, which is essentially the response-time middleware with a callback that captures the - * metrics - * @deprecated - */ - public REDMiddleware = this._REDMiddleware; - public instrument(moduleName: SupportedModules) { try { if (moduleName === 'express') { @@ -305,7 +316,7 @@ export class OpenAPM extends LevitateEvents { } if (moduleName === 'mysql') { const mysql2 = require('mysql2'); - instrumentMySQL(mysql2); + instrumentMySQL(mysql2, this.mode); } if (moduleName === 'nestjs') { const { NestFactory } = require('@nestjs/core'); diff --git a/src/clients/mysql2.ts b/src/clients/mysql2.ts index bc2c2bd..5407ebe 100644 --- a/src/clients/mysql2.ts +++ b/src/clients/mysql2.ts @@ -287,11 +287,19 @@ export const wrapPoolCluster = (poolCluster: PoolCluster, ctx: Context) => { return poolCluster; }; -export const instrumentMySQL = (mysql: { - createConnection: typeof createConnection; - createPool: typeof createPool; - createPoolCluster: typeof createPoolCluster; -}) => { +export const instrumentMySQL = ( + mysql: { + createConnection: typeof createConnection; + createPool: typeof createPool; + createPoolCluster: typeof createPoolCluster; + }, + mode: OpenAPMMode +) => { + if (mode === 'opentelemetry') { + console.log('opentelemetry is not supported for mysql instrumentation'); + return; + } + // Default histogram metrics const histogram = new promClient.Histogram({ name: 'db_requests_duration_milliseconds', From 09a5d96ca4f992dbbdb57c411ae6ec88dddc3a94 Mon Sep 17 00:00:00 2001 From: Prathamesh Sonpatki Date: Sun, 10 Mar 2024 23:45:46 +0530 Subject: [PATCH 03/21] Initial patch for opentelemetry support --- package-lock.json | 556 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 9 +- playground/app.js | 4 +- src/OpenAPM.ts | 81 +++++-- 4 files changed, 591 insertions(+), 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccfa7b0..f1494a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,26 @@ { "name": "@last9/openapm", -<<<<<<< HEAD - "version": "0.5.2-alpha-1", -======= - "version": "0.5.1-alpha.2", ->>>>>>> fef21961797c357f05cdc70919ce3330ba1f8c70 + "version": "0.6.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", -<<<<<<< HEAD - "version": "0.5.2-alpha-1", -======= - "version": "0.5.1-alpha.2", ->>>>>>> fef21961797c357f05cdc70919ce3330ba1f8c70 + "version": "0.6.1", "license": "Apache-2.0", "dependencies": { + "@opentelemetry/api": "^1.8.0", + "@opentelemetry/core": "^1.22.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.49.1", + "@opentelemetry/resources": "^1.22.0", + "@opentelemetry/sdk-metrics": "^1.22.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "chalk": "^4.1.2", "prom-client": "^14.2.0", "response-time": "^2.3.2", "undici": "^5.27.2", - "url-value-parser": "^2.2.0" + "url-value-parser": "^2.2.0", + "uuid": "^9.0.1" }, "devDependencies": { "@babel/core": "^7.22.5", @@ -2476,12 +2475,257 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/@opentelemetry/api": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.49.1.tgz", + "integrity": "sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.22.0.tgz", + "integrity": "sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.49.1.tgz", + "integrity": "sha512-t/sWYqfcwn81SvYHIyYJDlJD2CjFz3/h2t4j+XCtdoHAfu+WVJQmwLsGYJPlCDp3UXQfFpMJMWvLlvtD2SL+rg==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/otlp-exporter-base": "0.49.1", + "@opentelemetry/otlp-transformer": "0.49.1", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-metrics": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.49.1.tgz", + "integrity": "sha512-xKI6aCRY+STxbF7PA+6YNNYWFf6IS065rZZeqlqvqQsp0HaFUqpPEzMJn0OmQMGuy40o7wWtmZ9/bSu4jlhfYw==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.49.1", + "@opentelemetry/otlp-exporter-base": "0.49.1", + "@opentelemetry/otlp-proto-exporter-base": "0.49.1", + "@opentelemetry/otlp-transformer": "0.49.1", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-metrics": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.49.1.tgz", + "integrity": "sha512-z6sHliPqDgJU45kQatAettY9/eVF58qVPaTuejw9YWfSRqid9pXPYeegDCSdyS47KAUgAtm+nC28K3pfF27HWg==", + "dependencies": { + "@opentelemetry/core": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/otlp-proto-exporter-base": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-proto-exporter-base/-/otlp-proto-exporter-base-0.49.1.tgz", + "integrity": "sha512-x1qB4EUC7KikUl2iNuxCkV8yRzrSXSyj4itfpIO674H7dhI7Zv37SFaOJTDN+8Z/F50gF2ISFH9CWQ4KCtGm2A==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/otlp-exporter-base": "0.49.1", + "protobufjs": "^7.2.3" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.49.1.tgz", + "integrity": "sha512-Z+koA4wp9L9e3jkFacyXTGphSWTbOKjwwXMpb0CxNb0kjTHGUxhYRN8GnkLFsFo5NbZPjP07hwAqeEG/uCratQ==", + "dependencies": { + "@opentelemetry/api-logs": "0.49.1", + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-logs": "0.49.1", + "@opentelemetry/sdk-metrics": "1.22.0", + "@opentelemetry/sdk-trace-base": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", + "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.49.1.tgz", + "integrity": "sha512-gCzYWsJE0h+3cuh3/cK+9UwlVFyHvj3PReIOCDOmdeXOp90ZjKRoDOJBc3mvk1LL6wyl1RWIivR8Rg9OToyesw==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.9.0", + "@opentelemetry/api-logs": ">=0.39.1" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.22.0.tgz", + "integrity": "sha512-k6iIx6H3TZ+BVMr2z8M16ri2OxWaljg5h8ihGJxi/KQWcjign6FEaEzuigXt5bK9wVEhqAcWLCfarSftaNWkkg==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "lodash.merge": "^4.6.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.22.0.tgz", + "integrity": "sha512-pfTuSIpCKONC6vkTpv6VmACxD+P1woZf4q0K46nSUvXFvOFqjBYKFaAMkKD3M1mlKUUh0Oajwj35qNjMl80m1Q==", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", + "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==", + "engines": { + "node": ">=14" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", "dev": true }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2823,7 +3067,6 @@ "version": "20.8.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -5240,9 +5483,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true, "funding": [ { @@ -6187,8 +6430,7 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.sortby": { "version": "4.7.0", @@ -6199,8 +6441,7 @@ "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", - "dev": true + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "node_modules/loupe": { "version": "2.3.7", @@ -6986,6 +7227,29 @@ "node": ">=10" } }, + "node_modules/protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -8294,9 +8558,9 @@ } }, "node_modules/undici": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", - "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -8307,8 +8571,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -8415,6 +8678,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -8431,9 +8706,9 @@ } }, "node_modules/vite": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", - "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -10307,12 +10582,187 @@ } } }, + "@opentelemetry/api": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==" + }, + "@opentelemetry/api-logs": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.49.1.tgz", + "integrity": "sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q==", + "requires": { + "@opentelemetry/api": "^1.0.0" + } + }, + "@opentelemetry/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.22.0.tgz", + "integrity": "sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==", + "requires": { + "@opentelemetry/semantic-conventions": "1.22.0" + } + }, + "@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.49.1.tgz", + "integrity": "sha512-t/sWYqfcwn81SvYHIyYJDlJD2CjFz3/h2t4j+XCtdoHAfu+WVJQmwLsGYJPlCDp3UXQfFpMJMWvLlvtD2SL+rg==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/otlp-exporter-base": "0.49.1", + "@opentelemetry/otlp-transformer": "0.49.1", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-metrics": "1.22.0" + } + }, + "@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.49.1.tgz", + "integrity": "sha512-xKI6aCRY+STxbF7PA+6YNNYWFf6IS065rZZeqlqvqQsp0HaFUqpPEzMJn0OmQMGuy40o7wWtmZ9/bSu4jlhfYw==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.49.1", + "@opentelemetry/otlp-exporter-base": "0.49.1", + "@opentelemetry/otlp-proto-exporter-base": "0.49.1", + "@opentelemetry/otlp-transformer": "0.49.1", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-metrics": "1.22.0" + } + }, + "@opentelemetry/otlp-exporter-base": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.49.1.tgz", + "integrity": "sha512-z6sHliPqDgJU45kQatAettY9/eVF58qVPaTuejw9YWfSRqid9pXPYeegDCSdyS47KAUgAtm+nC28K3pfF27HWg==", + "requires": { + "@opentelemetry/core": "1.22.0" + } + }, + "@opentelemetry/otlp-proto-exporter-base": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-proto-exporter-base/-/otlp-proto-exporter-base-0.49.1.tgz", + "integrity": "sha512-x1qB4EUC7KikUl2iNuxCkV8yRzrSXSyj4itfpIO674H7dhI7Zv37SFaOJTDN+8Z/F50gF2ISFH9CWQ4KCtGm2A==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/otlp-exporter-base": "0.49.1", + "protobufjs": "^7.2.3" + } + }, + "@opentelemetry/otlp-transformer": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.49.1.tgz", + "integrity": "sha512-Z+koA4wp9L9e3jkFacyXTGphSWTbOKjwwXMpb0CxNb0kjTHGUxhYRN8GnkLFsFo5NbZPjP07hwAqeEG/uCratQ==", + "requires": { + "@opentelemetry/api-logs": "0.49.1", + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-logs": "0.49.1", + "@opentelemetry/sdk-metrics": "1.22.0", + "@opentelemetry/sdk-trace-base": "1.22.0" + } + }, + "@opentelemetry/resources": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", + "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + } + }, + "@opentelemetry/sdk-logs": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.49.1.tgz", + "integrity": "sha512-gCzYWsJE0h+3cuh3/cK+9UwlVFyHvj3PReIOCDOmdeXOp90ZjKRoDOJBc3mvk1LL6wyl1RWIivR8Rg9OToyesw==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0" + } + }, + "@opentelemetry/sdk-metrics": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.22.0.tgz", + "integrity": "sha512-k6iIx6H3TZ+BVMr2z8M16ri2OxWaljg5h8ihGJxi/KQWcjign6FEaEzuigXt5bK9wVEhqAcWLCfarSftaNWkkg==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "lodash.merge": "^4.6.2" + } + }, + "@opentelemetry/sdk-trace-base": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.22.0.tgz", + "integrity": "sha512-pfTuSIpCKONC6vkTpv6VmACxD+P1woZf4q0K46nSUvXFvOFqjBYKFaAMkKD3M1mlKUUh0Oajwj35qNjMl80m1Q==", + "requires": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", + "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==" + }, "@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", "dev": true }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -10544,7 +10994,6 @@ "version": "20.8.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", - "dev": true, "requires": { "undici-types": "~5.26.4" } @@ -12341,9 +12790,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true }, "for-each": { @@ -13000,8 +13449,7 @@ "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "lodash.sortby": { "version": "4.7.0", @@ -13012,8 +13460,7 @@ "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", - "dev": true + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "loupe": { "version": "2.3.7", @@ -13566,6 +14013,25 @@ "tdigest": "^0.1.1" } }, + "protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -14521,9 +14987,9 @@ } }, "undici": { - "version": "5.27.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", - "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", "requires": { "@fastify/busboy": "^2.0.0" } @@ -14531,8 +14997,7 @@ "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -14598,6 +15063,11 @@ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -14611,9 +15081,9 @@ "dev": true }, "vite": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", - "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dev": true, "requires": { "esbuild": "^0.18.10", diff --git a/package.json b/package.json index 0a2c8ee..0843139 100644 --- a/package.json +++ b/package.json @@ -58,11 +58,18 @@ "vitest": "^0.32.4" }, "dependencies": { + "@opentelemetry/api": "^1.8.0", + "@opentelemetry/core": "^1.22.0", + "@opentelemetry/exporter-metrics-otlp-proto": "^0.49.1", + "@opentelemetry/resources": "^1.22.0", + "@opentelemetry/sdk-metrics": "^1.22.0", + "@opentelemetry/semantic-conventions": "^1.22.0", "chalk": "^4.1.2", "prom-client": "^14.2.0", "response-time": "^2.3.2", "undici": "^5.27.2", - "url-value-parser": "^2.2.0" + "url-value-parser": "^2.2.0", + "uuid": "^9.0.1" }, "peerDependenciesMeta": { "@nestjs/core": { diff --git a/playground/app.js b/playground/app.js index 38a0a07..ec2e3b3 100644 --- a/playground/app.js +++ b/playground/app.js @@ -9,7 +9,7 @@ var { OpenAPM } = require('../dist/index.js'); var mysql2 = require('mysql2'); const openapm = new OpenAPM({ - // mode: 'opentelemetry', + mode: 'opentelemetry', extractLabels: { tenant: { from: 'params', @@ -29,7 +29,7 @@ const openapm = new OpenAPM({ }); openapm.instrument('express'); -openapm.instrument('mysql'); +// openapm.instrument('mysql'); const app = express(); diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index a3963cd..fb8a003 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -2,6 +2,26 @@ import * as os from 'os'; import http from 'http'; import ResponseTime from 'response-time'; import promClient from 'prom-client'; +import opentelemetry from '@opentelemetry/api'; +const { + DiagConsoleLogger, + DiagLogLevel, + diag, + metrics +} = require('@opentelemetry/api'); +const { + OTLPMetricExporter +} = require('@opentelemetry/exporter-metrics-otlp-http'); +const { + MeterProvider, + PeriodicExportingMetricReader, + ConsoleMetricExporter +} = require('@opentelemetry/sdk-metrics'); +import { Resource } from '@opentelemetry/resources'; +import { + SEMRESATTRS_SERVICE_NAME, + SEMRESATTRS_SERVICE_VERSION +} from '@opentelemetry/semantic-conventions'; import type { Counter, @@ -53,9 +73,9 @@ export interface OpenAPMOptions { environment?: string; /** Any default labels you want to include */ defaultLabels?: Record; - /** Accepts configuration for Prometheus Counter */ + /** Accepts configuration for Requests Counter */ requestsCounterConfig?: CounterConfiguration; - /** Accepts configuration for Prometheus Histogram */ + /** Accepts configuration for Requests Histogram */ requestDurationHistogramConfig?: HistogramConfiguration; /** Extract labels from URL params, subdomain, header */ extractLabels?: Record; @@ -67,6 +87,9 @@ export interface OpenAPMOptions { export type SupportedModules = 'express' | 'mysql' | 'nestjs'; +// Optional and only needed to see the internal diagnostic logging (during development) +diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG); + const moduleNames = { express: 'express', mysql: 'mysql2', @@ -82,9 +105,10 @@ export class OpenAPM extends LevitateEvents { readonly environment: string; readonly program: string; private defaultLabels?: Record; - private requestsCounterConfig: CounterConfiguration; + private openMetricsRequestsCounterConfig: CounterConfiguration; private requestDurationHistogramConfig: HistogramConfiguration; - private requestsCounter?: Counter; + private openMetricsRequestsCounter?: Counter; + private otelRequestsCounter?: any; private requestsDurationHistogram?: Histogram; private extractLabels?: Record; private excludeDefaultLabels?: Array; @@ -102,7 +126,7 @@ export class OpenAPM extends LevitateEvents { this.environment = options?.environment ?? 'production'; this.program = packageJson?.name ?? ''; this.defaultLabels = options?.defaultLabels; - this.requestsCounterConfig = options?.requestsCounterConfig ?? { + this.openMetricsRequestsCounterConfig = options?.requestsCounterConfig ?? { name: 'http_requests_total', help: 'Total number of requests', labelNames: [ @@ -131,6 +155,32 @@ export class OpenAPM extends LevitateEvents { if (this.mode === 'openmetrics') { this.initiateMetricsRoute(); this.initiatePromClient(); + } else if (this.mode === 'opentelemetry') { + const resource = Resource.default().merge( + new Resource({ + [SEMRESATTRS_SERVICE_NAME]: this.program, + [SEMRESATTRS_SERVICE_VERSION]: packageJson.version + }) + ); + + const metricReader = new PeriodicExportingMetricReader({ + exporter: new ConsoleMetricExporter(), + // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. + exportIntervalMillis: 10000 + }); + + const meterProvider = new MeterProvider({ + resource: resource, + readers: [metricReader] + }); + + // Set this MeterProvider to be global to the app being instrumented. + metrics.setGlobalMeterProvider(meterProvider); + const meter = meterProvider.getMeter('openapm-collector'); + + this.otelRequestsCounter = meter.createCounter('http_requests_total', { + description: 'Total number of requests' + }); } else { console.log(this.mode + ' not supported'); } @@ -163,7 +213,9 @@ export class OpenAPM extends LevitateEvents { }); // Initiate the Counter for the requests - this.requestsCounter = new promClient.Counter(this.requestsCounterConfig); + this.openMetricsRequestsCounter = new promClient.Counter( + this.openMetricsRequestsCounterConfig + ); // Initiate the Duration Histogram for the requests this.requestsDurationHistogram = new promClient.Histogram( this.requestDurationHistogramConfig @@ -290,18 +342,21 @@ export class OpenAPM extends LevitateEvents { if (this.mode === 'openmetrics') { // Create an array of arguments in the same sequence as label names - const requestsCounterArgs = this.requestsCounterConfig.labelNames?.map( - (labelName) => { + const openMetricsRequestsCounterArgs = + this.openMetricsRequestsCounterConfig.labelNames?.map((labelName) => { return labels[labelName] ?? ''; - } - ); + }); - if (requestsCounterArgs) { - this.requestsCounter?.labels(...requestsCounterArgs).inc(); + if (openMetricsRequestsCounterArgs) { + this.openMetricsRequestsCounter + ?.labels(...openMetricsRequestsCounterArgs) + .inc(); this.requestsDurationHistogram - ?.labels(...requestsCounterArgs) + ?.labels(...openMetricsRequestsCounterArgs) .observe(time); } + } else if (this.mode === 'opentelemetry') { + this.otelRequestsCounter.add(1, labels); } else { console.log(this.mode + ' is not supported'); } From 6386d598cbb4ea0e9e5e7c59c2b8adac096c3ebd Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 20 Mar 2024 16:18:19 +0530 Subject: [PATCH 04/21] Add setup for Custom Prometheus Remote Write Exporter --- package-lock.json | 1 + package.json | 1 + src/OpenAPM.ts | 15 +++--- src/exporter/prometheus-remote-write.ts | 68 +++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 src/exporter/prometheus-remote-write.ts diff --git a/package-lock.json b/package-lock.json index f1494a7..ead9673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@opentelemetry/semantic-conventions": "^1.22.0", "chalk": "^4.1.2", "prom-client": "^14.2.0", + "protobufjs": "^7.2.6", "response-time": "^2.3.2", "undici": "^5.27.2", "url-value-parser": "^2.2.0", diff --git a/package.json b/package.json index 0843139..adfb8e7 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@opentelemetry/semantic-conventions": "^1.22.0", "chalk": "^4.1.2", "prom-client": "^14.2.0", + "protobufjs": "^7.2.6", "response-time": "^2.3.2", "undici": "^5.27.2", "url-value-parser": "^2.2.0", diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index fb8a003..b0f2db7 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -2,21 +2,17 @@ import * as os from 'os'; import http from 'http'; import ResponseTime from 'response-time'; import promClient from 'prom-client'; -import opentelemetry from '@opentelemetry/api'; -const { +import { DiagConsoleLogger, DiagLogLevel, diag, metrics -} = require('@opentelemetry/api'); -const { - OTLPMetricExporter -} = require('@opentelemetry/exporter-metrics-otlp-http'); -const { +} from '@opentelemetry/api'; +import { MeterProvider, PeriodicExportingMetricReader, ConsoleMetricExporter -} = require('@opentelemetry/sdk-metrics'); +} from '@opentelemetry/sdk-metrics'; import { Resource } from '@opentelemetry/resources'; import { SEMRESATTRS_SERVICE_NAME, @@ -38,6 +34,7 @@ import { instrumentExpress } from './clients/express'; import { instrumentMySQL } from './clients/mysql2'; import { instrumentNestFactory } from './clients/nestjs'; import { LevitateConfig, LevitateEvents } from './levitate/events'; +import { PrometheusRemoteWriteExporter } from './exporter/prometheus-remote-write'; export type ExtractFromParams = { from: 'params'; @@ -164,7 +161,7 @@ export class OpenAPM extends LevitateEvents { ); const metricReader = new PeriodicExportingMetricReader({ - exporter: new ConsoleMetricExporter(), + exporter: new PrometheusRemoteWriteExporter(), // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. exportIntervalMillis: 10000 }); diff --git a/src/exporter/prometheus-remote-write.ts b/src/exporter/prometheus-remote-write.ts new file mode 100644 index 0000000..ccad9da --- /dev/null +++ b/src/exporter/prometheus-remote-write.ts @@ -0,0 +1,68 @@ +import { ExportResult, ExportResultCode } from '@opentelemetry/core'; +import { + AggregationTemporality, + AggregationTemporalitySelector, + InstrumentType, + PushMetricExporter, + ResourceMetrics +} from '@opentelemetry/sdk-metrics'; +import { DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR } from '@opentelemetry/sdk-metrics/build/src/export/AggregationSelector'; + +export class PrometheusRemoteWriteExporter implements PushMetricExporter { + protected _shutdown = false; + protected _temporalitySelector: AggregationTemporalitySelector; + + constructor(options?: { + temporalitySelector?: AggregationTemporalitySelector; + }) { + this._temporalitySelector = + options?.temporalitySelector ?? DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR; + } + export( + metrics: ResourceMetrics, + resultCallback: (result: ExportResult) => void + ): void { + if (this._shutdown) { + // If the exporter is shutting down, by spec, we need to return FAILED as export result + setImmediate(resultCallback, { code: ExportResultCode.FAILED }); + return; + } + + return PrometheusRemoteWriteExporter._sendMetrics(metrics, resultCallback); + } + + forceFlush(): Promise { + return Promise.resolve(); + } + + selectAggregationTemporality( + _instrumentType: InstrumentType + ): AggregationTemporality { + return this._temporalitySelector(_instrumentType); + } + + shutdown(): Promise { + this._shutdown = true; + return Promise.resolve(); + } + + private static _sendMetrics( + metrics: ResourceMetrics, + done: (result: ExportResult) => void + ): void { + for (const scopeMetrics of metrics.scopeMetrics) { + for (const metric of scopeMetrics.metrics) { + console.dir( + { + descriptor: metric.descriptor, + dataPointType: metric.dataPointType, + dataPoints: metric.dataPoints + }, + { depth: null } + ); + } + } + + done({ code: ExportResultCode.SUCCESS }); + } +} From bce4aac59f1da33aedbab42a23f881f03d4338c8 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Thu, 21 Mar 2024 22:59:24 +0530 Subject: [PATCH 05/21] Add histogram for express red middleware --- src/OpenAPM.ts | 49 ++++++++++++------ src/exporter/prometheus-remote-write.ts | 68 ------------------------- 2 files changed, 34 insertions(+), 83 deletions(-) delete mode 100644 src/exporter/prometheus-remote-write.ts diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index b0f2db7..4e2149e 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -5,6 +5,7 @@ import promClient from 'prom-client'; import { DiagConsoleLogger, DiagLogLevel, + Meter, diag, metrics } from '@opentelemetry/api'; @@ -34,7 +35,6 @@ import { instrumentExpress } from './clients/express'; import { instrumentMySQL } from './clients/mysql2'; import { instrumentNestFactory } from './clients/nestjs'; import { LevitateConfig, LevitateEvents } from './levitate/events'; -import { PrometheusRemoteWriteExporter } from './exporter/prometheus-remote-write'; export type ExtractFromParams = { from: 'params'; @@ -104,9 +104,14 @@ export class OpenAPM extends LevitateEvents { private defaultLabels?: Record; private openMetricsRequestsCounterConfig: CounterConfiguration; private requestDurationHistogramConfig: HistogramConfiguration; - private openMetricsRequestsCounter?: Counter; - private otelRequestsCounter?: any; - private requestsDurationHistogram?: Histogram; + private openMetricsMeters: { + requestsCounter?: Counter; + requestsDurationHistogram?: Histogram; + }; + private openTelemetryMeters?: { + requestsCounter?: ReturnType; + requestsDurationHistogram?: ReturnType; + }; private extractLabels?: Record; private excludeDefaultLabels?: Array; @@ -146,6 +151,9 @@ export class OpenAPM extends LevitateEvents { buckets: promClient.exponentialBuckets(0.25, 1.5, 31) }; + this.openMetricsMeters = {}; + this.openTelemetryMeters = {}; + this.extractLabels = options?.extractLabels ?? {}; this.excludeDefaultLabels = options?.excludeDefaultLabels; @@ -161,7 +169,7 @@ export class OpenAPM extends LevitateEvents { ); const metricReader = new PeriodicExportingMetricReader({ - exporter: new PrometheusRemoteWriteExporter(), + exporter: new ConsoleMetricExporter(), // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. exportIntervalMillis: 10000 }); @@ -175,9 +183,17 @@ export class OpenAPM extends LevitateEvents { metrics.setGlobalMeterProvider(meterProvider); const meter = meterProvider.getMeter('openapm-collector'); - this.otelRequestsCounter = meter.createCounter('http_requests_total', { - description: 'Total number of requests' - }); + this.openTelemetryMeters['requestsCounter'] = meter.createCounter( + 'http_requests_total', + { + description: 'Total number of requests' + } + ); + + this.openTelemetryMeters['requestsDurationHistogram'] = + meter.createHistogram('http_requests_duration_milliseconds', { + description: 'Duration of HTTP requests in milliseconds' + }); } else { console.log(this.mode + ' not supported'); } @@ -210,13 +226,12 @@ export class OpenAPM extends LevitateEvents { }); // Initiate the Counter for the requests - this.openMetricsRequestsCounter = new promClient.Counter( + this.openMetricsMeters['requestsCounter'] = new promClient.Counter( this.openMetricsRequestsCounterConfig ); // Initiate the Duration Histogram for the requests - this.requestsDurationHistogram = new promClient.Histogram( - this.requestDurationHistogramConfig - ); + this.openMetricsMeters['requestsDurationHistogram'] = + new promClient.Histogram(this.requestDurationHistogramConfig); }; private gracefullyShutdownMetricsServer = () => { @@ -345,15 +360,19 @@ export class OpenAPM extends LevitateEvents { }); if (openMetricsRequestsCounterArgs) { - this.openMetricsRequestsCounter + this.openMetricsMeters.requestsCounter ?.labels(...openMetricsRequestsCounterArgs) .inc(); - this.requestsDurationHistogram + this.openMetricsMeters.requestsDurationHistogram ?.labels(...openMetricsRequestsCounterArgs) .observe(time); } } else if (this.mode === 'opentelemetry') { - this.otelRequestsCounter.add(1, labels); + this.openTelemetryMeters?.['requestsCounter']?.add(1, labels); + this.openTelemetryMeters?.['requestsDurationHistogram']?.record( + time, + labels + ); } else { console.log(this.mode + ' is not supported'); } diff --git a/src/exporter/prometheus-remote-write.ts b/src/exporter/prometheus-remote-write.ts deleted file mode 100644 index ccad9da..0000000 --- a/src/exporter/prometheus-remote-write.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { ExportResult, ExportResultCode } from '@opentelemetry/core'; -import { - AggregationTemporality, - AggregationTemporalitySelector, - InstrumentType, - PushMetricExporter, - ResourceMetrics -} from '@opentelemetry/sdk-metrics'; -import { DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR } from '@opentelemetry/sdk-metrics/build/src/export/AggregationSelector'; - -export class PrometheusRemoteWriteExporter implements PushMetricExporter { - protected _shutdown = false; - protected _temporalitySelector: AggregationTemporalitySelector; - - constructor(options?: { - temporalitySelector?: AggregationTemporalitySelector; - }) { - this._temporalitySelector = - options?.temporalitySelector ?? DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR; - } - export( - metrics: ResourceMetrics, - resultCallback: (result: ExportResult) => void - ): void { - if (this._shutdown) { - // If the exporter is shutting down, by spec, we need to return FAILED as export result - setImmediate(resultCallback, { code: ExportResultCode.FAILED }); - return; - } - - return PrometheusRemoteWriteExporter._sendMetrics(metrics, resultCallback); - } - - forceFlush(): Promise { - return Promise.resolve(); - } - - selectAggregationTemporality( - _instrumentType: InstrumentType - ): AggregationTemporality { - return this._temporalitySelector(_instrumentType); - } - - shutdown(): Promise { - this._shutdown = true; - return Promise.resolve(); - } - - private static _sendMetrics( - metrics: ResourceMetrics, - done: (result: ExportResult) => void - ): void { - for (const scopeMetrics of metrics.scopeMetrics) { - for (const metric of scopeMetrics.metrics) { - console.dir( - { - descriptor: metric.descriptor, - dataPointType: metric.dataPointType, - dataPoints: metric.dataPoints - }, - { depth: null } - ); - } - } - - done({ code: ExportResultCode.SUCCESS }); - } -} From 310f5d474ea70110daa3d05afbc0c63b47a583da Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Fri, 22 Mar 2024 09:57:50 +0530 Subject: [PATCH 06/21] Add otlp exporter --- src/OpenAPM.ts | 17 ++++++++++++++--- src/clients/mysql2.ts | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 4e2149e..57fa0ee 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -11,9 +11,12 @@ import { } from '@opentelemetry/api'; import { MeterProvider, - PeriodicExportingMetricReader, - ConsoleMetricExporter + PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; +import { + OTLPMetricExporter, + OTLPMetricExporterOptions +} from '@opentelemetry/exporter-metrics-otlp-http'; import { Resource } from '@opentelemetry/resources'; import { SEMRESATTRS_SERVICE_NAME, @@ -56,6 +59,10 @@ export interface OpenAPMOptions { * @default "openmetrics" */ mode?: OpenAPMMode; + /** + * + */ + otlpMetricExporterOptions?: OTLPMetricExporterOptions; /** Route where the metrics will be exposed * @default "/metrics" */ @@ -97,6 +104,7 @@ const packageJson = getPackageJson(); export class OpenAPM extends LevitateEvents { private mode: string; + private otlpMetricExporterOptions?: OTLPMetricExporterOptions; private path: string; private metricsServerPort: number; readonly environment: string; @@ -122,6 +130,9 @@ export class OpenAPM extends LevitateEvents { this.mode = options?.mode ?? 'openmetrics'; + if (this.mode === 'opentelemetry') { + this.otlpMetricExporterOptions = options?.otlpMetricExporterOptions; + } // Initializing all the options this.path = options?.path ?? '/metrics'; this.metricsServerPort = options?.metricsServerPort ?? 9097; @@ -169,7 +180,7 @@ export class OpenAPM extends LevitateEvents { ); const metricReader = new PeriodicExportingMetricReader({ - exporter: new ConsoleMetricExporter(), + exporter: new OTLPMetricExporter(this.otlpMetricExporterOptions), // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. exportIntervalMillis: 10000 }); diff --git a/src/clients/mysql2.ts b/src/clients/mysql2.ts index 5407ebe..a2554d5 100644 --- a/src/clients/mysql2.ts +++ b/src/clients/mysql2.ts @@ -293,7 +293,7 @@ export const instrumentMySQL = ( createPool: typeof createPool; createPoolCluster: typeof createPoolCluster; }, - mode: OpenAPMMode + mode: string ) => { if (mode === 'opentelemetry') { console.log('opentelemetry is not supported for mysql instrumentation'); From d976eea60bd8d102512aa94f2c53da918b1707aa Mon Sep 17 00:00:00 2001 From: Prathamesh Sonpatki Date: Fri, 29 Mar 2024 15:32:53 +0530 Subject: [PATCH 07/21] Use otlp proto to push metrics --- src/OpenAPM.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 57fa0ee..43249da 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -13,10 +13,7 @@ import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; -import { - OTLPMetricExporter, - OTLPMetricExporterOptions -} from '@opentelemetry/exporter-metrics-otlp-http'; +import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'; import { Resource } from '@opentelemetry/resources'; import { SEMRESATTRS_SERVICE_NAME, @@ -59,10 +56,6 @@ export interface OpenAPMOptions { * @default "openmetrics" */ mode?: OpenAPMMode; - /** - * - */ - otlpMetricExporterOptions?: OTLPMetricExporterOptions; /** Route where the metrics will be exposed * @default "/metrics" */ @@ -104,7 +97,6 @@ const packageJson = getPackageJson(); export class OpenAPM extends LevitateEvents { private mode: string; - private otlpMetricExporterOptions?: OTLPMetricExporterOptions; private path: string; private metricsServerPort: number; readonly environment: string; @@ -130,9 +122,6 @@ export class OpenAPM extends LevitateEvents { this.mode = options?.mode ?? 'openmetrics'; - if (this.mode === 'opentelemetry') { - this.otlpMetricExporterOptions = options?.otlpMetricExporterOptions; - } // Initializing all the options this.path = options?.path ?? '/metrics'; this.metricsServerPort = options?.metricsServerPort ?? 9097; @@ -180,7 +169,7 @@ export class OpenAPM extends LevitateEvents { ); const metricReader = new PeriodicExportingMetricReader({ - exporter: new OTLPMetricExporter(this.otlpMetricExporterOptions), + exporter: new OTLPMetricExporter({ url: process.env.OTLP_ENDPOINT }), // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. exportIntervalMillis: 10000 }); From 1067caddefa0db9ec397c1c1937e07aa4bc3c472 Mon Sep 17 00:00:00 2001 From: Prathamesh Sonpatki Date: Fri, 29 Mar 2024 15:40:52 +0530 Subject: [PATCH 08/21] Change the time range to 60 seconds --- src/OpenAPM.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 43249da..d748b9f 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -170,8 +170,8 @@ export class OpenAPM extends LevitateEvents { const metricReader = new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter({ url: process.env.OTLP_ENDPOINT }), - // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. - exportIntervalMillis: 10000 + // 60 seconds + exportIntervalMillis: 60000 }); const meterProvider = new MeterProvider({ From d3317079764b56a6b2d61f3975cf043fcb60863a Mon Sep 17 00:00:00 2001 From: Prathamesh Sonpatki Date: Fri, 29 Mar 2024 15:42:10 +0530 Subject: [PATCH 09/21] 0.8.0-alpha.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ead9673..8017533 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.6.1", + "version": "0.8.0-alpha.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.6.1", + "version": "0.8.0-alpha.2", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/package.json b/package.json index adfb8e7..c23cbf6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.6.1", + "version": "0.8.0-alpha.2", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From a17e0468a83fb9e5d5904f0c7343e6c5db69709a Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 14:37:50 +0530 Subject: [PATCH 10/21] Configure otlp timeout from environment variable --- src/OpenAPM.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index d748b9f..03e8510 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -169,9 +169,11 @@ export class OpenAPM extends LevitateEvents { ); const metricReader = new PeriodicExportingMetricReader({ - exporter: new OTLPMetricExporter({ url: process.env.OTLP_ENDPOINT }), - // 60 seconds - exportIntervalMillis: 60000 + exporter: new OTLPMetricExporter(this.otlpMetricExporterOptions), + // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. + exportIntervalMillis: process.env.OTLP_EXPORT_TIMEOUT + ? parseInt(process.env.OTLP_EXPORT_TIMEOUT) + : 10000 }); const meterProvider = new MeterProvider({ From d38e918df0ad4ef034a297e8e26e6c18a27b0880 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 14:40:54 +0530 Subject: [PATCH 11/21] 0.8.0-alpha.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8017533..ad2a3ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.8.0-alpha.2", + "version": "0.8.0-alpha.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.8.0-alpha.2", + "version": "0.8.0-alpha.3", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/package.json b/package.json index c23cbf6..5b891d4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.8.0-alpha.2", + "version": "0.8.0-alpha.3", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From 12b39b34ce4582383cb2ed2ab558d51778d430c5 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 14:43:51 +0530 Subject: [PATCH 12/21] Add option for otlp exporter options --- src/OpenAPM.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 03e8510..8a106c8 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -35,6 +35,7 @@ import { instrumentExpress } from './clients/express'; import { instrumentMySQL } from './clients/mysql2'; import { instrumentNestFactory } from './clients/nestjs'; import { LevitateConfig, LevitateEvents } from './levitate/events'; +import { OTLPMetricExporterOptions } from '@opentelemetry/exporter-metrics-otlp-http'; export type ExtractFromParams = { from: 'params'; @@ -80,6 +81,8 @@ export interface OpenAPMOptions { excludeDefaultLabels?: Array; /** Levitate Config */ levitateConfig?: LevitateConfig; + /** OTLP Metrics exporter option */ + otlpMetricExporterOptions?: OTLPMetricExporterOptions; } export type SupportedModules = 'express' | 'mysql' | 'nestjs'; @@ -114,6 +117,7 @@ export class OpenAPM extends LevitateEvents { }; private extractLabels?: Record; private excludeDefaultLabels?: Array; + private otlpMetricExporterOptions?: OTLPMetricExporterOptions; public metricsServer?: Server; @@ -154,6 +158,8 @@ export class OpenAPM extends LevitateEvents { this.openMetricsMeters = {}; this.openTelemetryMeters = {}; + this.otlpMetricExporterOptions = options?.otlpMetricExporterOptions; + this.extractLabels = options?.extractLabels ?? {}; this.excludeDefaultLabels = options?.excludeDefaultLabels; From 25b16ecc59ee2377a7b07e9f47c8435c1808c39b Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 15:17:56 +0530 Subject: [PATCH 13/21] Add the export timeout millis option --- src/OpenAPM.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 8a106c8..aa421be 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -177,7 +177,8 @@ export class OpenAPM extends LevitateEvents { const metricReader = new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter(this.otlpMetricExporterOptions), // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. - exportIntervalMillis: process.env.OTLP_EXPORT_TIMEOUT + exportIntervalMillis: 10000, + exportTimeoutMillis: process.env.OTLP_EXPORT_TIMEOUT ? parseInt(process.env.OTLP_EXPORT_TIMEOUT) : 10000 }); From c827ece418dbfb3caf6d993295210df9f2a8394a Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 15:23:08 +0530 Subject: [PATCH 14/21] 0.8.0-alpha.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad2a3ff..b413dac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.8.0-alpha.3", + "version": "0.8.0-alpha.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.8.0-alpha.3", + "version": "0.8.0-alpha.4", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/package.json b/package.json index 5b891d4..84a57a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.8.0-alpha.3", + "version": "0.8.0-alpha.4", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From 66327e70f6d06518b33383588b5c6c1426dce2d1 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 15:49:29 +0530 Subject: [PATCH 15/21] 0.8.0-alpha.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b413dac..9cb0b08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.8.0-alpha.4", + "version": "0.8.0-alpha.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.8.0-alpha.4", + "version": "0.8.0-alpha.5", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/package.json b/package.json index 84a57a6..9d1d0c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.8.0-alpha.4", + "version": "0.8.0-alpha.5", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From ea5433c7f922657bb5cb43e0c9fc855498320d05 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 16:04:25 +0530 Subject: [PATCH 16/21] Handle otel in shutdown function --- src/OpenAPM.ts | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index b6895c7..c9f22d9 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -245,18 +245,22 @@ export class OpenAPM extends LevitateEvents { public shutdown = async () => { return new Promise((resolve, reject) => { - console.log('Shutting down metrics server gracefully.'); - this.metricsServer?.close((err) => { - promClient.register.clear(); - - if (err) { - reject(err); - return; - } - + if (this.mode === 'opentelemetry') { + this.openMetricsMeters.requestsCounter?.reset(); + this.openMetricsMeters.requestsDurationHistogram?.reset(); resolve(undefined); - console.log('Metrics server shut down gracefully.'); - }); + } else { + console.log('Shutting down metrics server gracefully.'); + this.metricsServer?.close((err) => { + promClient.register.clear(); + + if (err) { + reject(err); + return; + } + resolve(undefined); + }); + } }); }; From e55921b65f938c2d5689d3d02d4ee7cf5d2c9c21 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 16:11:39 +0530 Subject: [PATCH 17/21] Use shutdown from opentelemetry meter provider --- src/OpenAPM.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index c9f22d9..4324183 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -111,6 +111,7 @@ export class OpenAPM extends LevitateEvents { requestsCounter?: Counter; requestsDurationHistogram?: Histogram; }; + private otelMeterProvider?: MeterProvider; private openTelemetryMeters?: { requestsCounter?: ReturnType; requestsDurationHistogram?: ReturnType; @@ -183,14 +184,14 @@ export class OpenAPM extends LevitateEvents { : 10000 }); - const meterProvider = new MeterProvider({ + this.otelMeterProvider = new MeterProvider({ resource: resource, readers: [metricReader] }); // Set this MeterProvider to be global to the app being instrumented. - metrics.setGlobalMeterProvider(meterProvider); - const meter = meterProvider.getMeter('openapm-collector'); + metrics.setGlobalMeterProvider(this.otelMeterProvider); + const meter = this.otelMeterProvider.getMeter('openapm-collector'); this.openTelemetryMeters['requestsCounter'] = meter.createCounter( 'http_requests_total', @@ -246,9 +247,10 @@ export class OpenAPM extends LevitateEvents { public shutdown = async () => { return new Promise((resolve, reject) => { if (this.mode === 'opentelemetry') { - this.openMetricsMeters.requestsCounter?.reset(); - this.openMetricsMeters.requestsDurationHistogram?.reset(); - resolve(undefined); + this.otelMeterProvider?.shutdown().then(() => { + console.log('Shutting down OpenTelemetry gracefully.'); + resolve(undefined); + }); } else { console.log('Shutting down metrics server gracefully.'); this.metricsServer?.close((err) => { From 323c54703736dc8b000ad7df24093a1d45ac09bc Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Mon, 1 Apr 2024 16:13:02 +0530 Subject: [PATCH 18/21] 0.8.0-alpha.6 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cb0b08..de78ece 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.8.0-alpha.5", + "version": "0.8.0-alpha.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.8.0-alpha.5", + "version": "0.8.0-alpha.6", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/package.json b/package.json index 9d1d0c9..f518486 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.8.0-alpha.5", + "version": "0.8.0-alpha.6", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From dd19f50911403b477e9eac90d265085f4d280026 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 10 Apr 2024 13:19:31 +0530 Subject: [PATCH 19/21] Add periodicExportingMetricReaderOptions option for OpenAPM --- playground/app.js | 5 ++++- src/OpenAPM.ts | 22 +++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/playground/app.js b/playground/app.js index 4b5288a..7571d9e 100644 --- a/playground/app.js +++ b/playground/app.js @@ -25,7 +25,10 @@ const openapm = new OpenAPM({ } }, customPathsToMask: [/\b\d+(?:,\d+)*\b/gm], - excludeDefaultLabels: ['host', 'program'] + excludeDefaultLabels: ['host', 'program'], + periodicExportingMetricReaderOptions: { + exportTimeoutMillis: 60000 + } }); openapm.instrument('express'); diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 4324183..eaa2124 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -11,7 +11,8 @@ import { } from '@opentelemetry/api'; import { MeterProvider, - PeriodicExportingMetricReader + PeriodicExportingMetricReader, + PeriodicExportingMetricReaderOptions } from '@opentelemetry/sdk-metrics'; import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'; import { Resource } from '@opentelemetry/resources'; @@ -83,6 +84,11 @@ export interface OpenAPMOptions { levitateConfig?: LevitateConfig; /** OTLP Metrics exporter option */ otlpMetricExporterOptions?: OTLPMetricExporterOptions; + /** Periodic Exporting Metric Reader Options */ + periodicExportingMetricReaderOptions?: Omit< + PeriodicExportingMetricReaderOptions, + 'exporter' + >; } export type SupportedModules = 'express' | 'mysql' | 'nestjs'; @@ -119,6 +125,10 @@ export class OpenAPM extends LevitateEvents { private extractLabels?: Record; private excludeDefaultLabels?: Array; private otlpMetricExporterOptions?: OTLPMetricExporterOptions; + private periodicExportingMetricReaderOptions?: Omit< + PeriodicExportingMetricReaderOptions, + 'exporter' + >; public metricsServer?: Server; @@ -160,6 +170,8 @@ export class OpenAPM extends LevitateEvents { this.openTelemetryMeters = {}; this.otlpMetricExporterOptions = options?.otlpMetricExporterOptions; + this.periodicExportingMetricReaderOptions = + options?.periodicExportingMetricReaderOptions ?? {}; this.extractLabels = options?.extractLabels ?? {}; this.excludeDefaultLabels = options?.excludeDefaultLabels; @@ -176,12 +188,8 @@ export class OpenAPM extends LevitateEvents { ); const metricReader = new PeriodicExportingMetricReader({ - exporter: new OTLPMetricExporter(this.otlpMetricExporterOptions), - // Default is 60000ms (60 seconds). Set to 10 seconds for demonstrative purposes only. - exportIntervalMillis: 10000, - exportTimeoutMillis: process.env.OTLP_EXPORT_TIMEOUT - ? parseInt(process.env.OTLP_EXPORT_TIMEOUT) - : 10000 + ...this.periodicExportingMetricReaderOptions, + exporter: new OTLPMetricExporter(this.otlpMetricExporterOptions) }); this.otelMeterProvider = new MeterProvider({ From a3cdf391e065d3f6b0d4feda9358c1454911e9bd Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 10 Apr 2024 13:21:14 +0530 Subject: [PATCH 20/21] 0.8.0-alpha.7 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index de78ece..8632a61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.8.0-alpha.6", + "version": "0.8.0-alpha.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.8.0-alpha.6", + "version": "0.8.0-alpha.7", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/package.json b/package.json index f518486..a226f7f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.8.0-alpha.6", + "version": "0.8.0-alpha.7", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From 80783bf50dd5db986ed68f59c910aa65146c82b2 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Tue, 14 May 2024 18:16:05 +0530 Subject: [PATCH 21/21] Add .next in .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9738884..c3e50f4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules dist .DS_Store .idea -.env \ No newline at end of file +.env +.next \ No newline at end of file