Skip to content

Commit

Permalink
feat: add defaultLabels support
Browse files Browse the repository at this point in the history
  • Loading branch information
pragmaticivan committed Sep 26, 2021
1 parent 28a9310 commit 6efb0a5
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 6 deletions.
5 changes: 2 additions & 3 deletions src/interfaces/opentelemetry-options.interface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ModuleMetadata, Type, Abstract } from '@nestjs/common';
import { Labels } from '@opentelemetry/api-metrics';

export type OpenTelemetryModuleOptions = {
/**
Expand Down Expand Up @@ -50,8 +51,6 @@ export type OpenTelemetryMetrics = {
timeBuckets?: number[],
requestSizeBuckets?: number[],
responseSizeBuckets?: number[],
},
defaultLabels?: {
[key: string]: string | number
defaultLabels?: Labels,
},
};
12 changes: 9 additions & 3 deletions src/middleware/api-metrics.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Inject, Injectable, NestMiddleware } from '@nestjs/common';
import * as responseTime from 'response-time';
import * as urlParser from 'url';
import { Counter, ValueRecorder } from '@opentelemetry/api-metrics';
import { Counter, Labels, ValueRecorder } from '@opentelemetry/api-metrics';
import { OpenTelemetryModuleOptions } from '../interfaces';
import { MetricService } from '../metrics/metric.service';
import { OPENTELEMETRY_MODULE_OPTIONS } from '../opentelemetry.constants';
Expand Down Expand Up @@ -43,6 +43,8 @@ export class ApiMetricsMiddleware implements NestMiddleware {

private responseSizeValueRecorder: ValueRecorder;

private defaultLabels: Labels;

constructor(
@Inject(OPENTELEMETRY_MODULE_OPTIONS) private readonly options: OpenTelemetryModuleOptions = {},
@Inject(MetricService) private readonly metricService: MetricService,
Expand Down Expand Up @@ -76,9 +78,11 @@ export class ApiMetricsMiddleware implements NestMiddleware {
});

const {
timeBuckets = [], requestSizeBuckets = [], responseSizeBuckets = [],
timeBuckets = [], requestSizeBuckets = [], responseSizeBuckets = [], defaultLabels = {},
} = options?.metrics?.apiMetrics;

this.defaultLabels = defaultLabels;

this.requestDuration = this.metricService.getValueRecorder('http_request_duration_seconds', {
boundaries: timeBuckets.length > 0 ? timeBuckets : this.defaultLongRunningRequestBuckets,
description: 'HTTP latency value recorder in seconds',
Expand Down Expand Up @@ -125,7 +129,9 @@ export class ApiMetricsMiddleware implements NestMiddleware {
const responseLength: number = parseInt(res.get('Content-Length'), 10) || 0;

const status = res.statusCode || 500;
const labels = { method, status, path };
const labels: Labels = {
method, status, path, ...this.defaultLabels,
};

this.requestSizeValueRecorder.bind(labels).record(requestLength);
this.responseSizeValueRecorder.bind(labels).record(responseLength);
Expand Down
35 changes: 35 additions & 0 deletions tests/e2e/middleware/api-metrics.middleware.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,41 @@ describe('Api Metrics Middleware', () => {
expect(/http_server_error_total 1/.test(text)).toBeTruthy();
});

it('registers requests with custom labels', async () => {
const testingModule = await Test.createTestingModule({
imports: [OpenTelemetryModule.forRoot({
metrics: {
apiMetrics: {
enable: true,
defaultLabels: {
custom: 'label',
},
},
},
})],
controllers: [AppController],
}).compile();
testingModule.useLogger(new EmptyLogger());

app = testingModule.createNestApplication();
await app.init();

const agent = request(app.getHttpServer());
await agent.get('/example/internal-error');

// Workaround for delay of metrics going to prometheus
await new Promise(resolve => setTimeout(resolve, 200));

// TODO: OpenTelemetry exporter does not expose server in a public function.
// @ts-ignore
// eslint-disable-next-line no-underscore-dangle
const { text } = await request(exporter._server)
.get('/metrics')
.expect(200);

expect(/custom/.test(text)).toBeTruthy();
});

afterEach(async () => {
metrics.disable();
if (exporter) {
Expand Down

0 comments on commit 6efb0a5

Please sign in to comment.