diff --git a/src/metrics/decorators/counter.ts b/src/metrics/decorators/counter.ts deleted file mode 100644 index 3ea7fa0..0000000 --- a/src/metrics/decorators/counter.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createParamDecorator } from '@nestjs/common'; -import { getOrCreateCounter } from '../metric-data'; -import { OtelMetricOptions } from '../../interfaces/metric-options.interface'; - -export const OtelCounter = createParamDecorator((name: string, options?: OtelMetricOptions) => { - if (!name || name.length === 0) { - throw new Error('OtelCounter need a name argument'); - } - return getOrCreateCounter(name, options); -}); - -export const OtelUpDownCounter = createParamDecorator( - (name: string, options?: OtelMetricOptions) => { - if (!name || name.length === 0) { - throw new Error('OtelUpDownCounter need a name argument'); - } - return getOrCreateCounter(name, options); - } -); diff --git a/src/metrics/decorators/histogram.ts b/src/metrics/decorators/histogram.ts deleted file mode 100644 index c38e1e7..0000000 --- a/src/metrics/decorators/histogram.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createParamDecorator } from '@nestjs/common'; -import { getOrCreateHistogram } from '../metric-data'; -import { OtelMetricOptions } from '../../interfaces/metric-options.interface'; - -export const OtelHistogram = createParamDecorator((name: string, options?: OtelMetricOptions) => { - if (!name || name.length === 0) { - throw new Error('OtelHistogram need a name argument'); - } - return getOrCreateHistogram(name, options); -}); diff --git a/src/metrics/decorators/index.ts b/src/metrics/decorators/index.ts index 7c5961e..a5dc50a 100644 --- a/src/metrics/decorators/index.ts +++ b/src/metrics/decorators/index.ts @@ -1,4 +1,2 @@ export * from './common'; -export * from './counter'; -export * from './histogram'; -export * from './observable'; +export * from './param'; diff --git a/src/metrics/decorators/observable.ts b/src/metrics/decorators/observable.ts deleted file mode 100644 index 979b368..0000000 --- a/src/metrics/decorators/observable.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { createParamDecorator } from '@nestjs/common'; -import { - getOrCreateObservableCounter, - getOrCreateObservableGauge, - getOrCreateObservableUpDownCounter, -} from '../metric-data'; -import { OtelMetricOptions } from '../../interfaces/metric-options.interface'; - -export const OtelObservableGauge = createParamDecorator( - (name: string, options?: OtelMetricOptions) => { - if (!name || name.length === 0) { - throw new Error('OtelObservableGauge need a name argument'); - } - return getOrCreateObservableGauge(name, options); - } -); - -export const OtelObservableCounter = createParamDecorator( - (name: string, options?: OtelMetricOptions) => { - if (!name || name.length === 0) { - throw new Error('OtelObservableCounter need a name argument'); - } - return getOrCreateObservableCounter(name, options); - } -); - -export const OtelObservableUpDownCounter = createParamDecorator( - (name: string, options?: OtelMetricOptions) => { - if (!name || name.length === 0) { - throw new Error('OtelObservableUpDownCounter need a name argument'); - } - return getOrCreateObservableUpDownCounter(name, options); - } -); diff --git a/src/metrics/decorators/param.ts b/src/metrics/decorators/param.ts new file mode 100644 index 0000000..371dd5a --- /dev/null +++ b/src/metrics/decorators/param.ts @@ -0,0 +1,49 @@ +import { createParamDecorator } from '@nestjs/common'; +import { OtelMetricOptions } from '../../interfaces/metric-options.interface'; +import { + getOrCreateCounter, + getOrCreateHistogram, + getOrCreateObservableCounter, + getOrCreateObservableGauge, + getOrCreateObservableUpDownCounter, +} from '../metric-data'; + +export type MetricParamDecorator = ( + name: string, + options?: OtelMetricOptions +) => ParameterDecorator; + +function createMetricParamDecorator( + type: string, + getOrCreateMetric: (name: string, options?: OtelMetricOptions) => T +): MetricParamDecorator { + return (name: string, options?: OtelMetricOptions): ParameterDecorator => { + return createParamDecorator(() => { + if (!name || name.length === 0) { + throw new Error(`${type} need a name argument`); + } + return getOrCreateMetric(name, options); + })(); + }; +} + +export const OtelCounter = createMetricParamDecorator('OtelCounter', getOrCreateCounter); +export const OtelUpDownCounter = createMetricParamDecorator( + 'OtelUpDownCounter', + getOrCreateCounter +); + +export const OtelHistogram = createMetricParamDecorator('OtelHistogram', getOrCreateHistogram); + +export const OtelObservableGauge = createMetricParamDecorator( + 'OtelObservableGauge', + getOrCreateObservableGauge +); +export const OtelObservableCounter = createMetricParamDecorator( + 'OtelObservableCounter', + getOrCreateObservableCounter +); +export const OtelObservableUpDownCounter = createMetricParamDecorator( + 'OtelObservableUpDownCounter', + getOrCreateObservableUpDownCounter +); diff --git a/tests/e2e/metrics/decorators/common.spec.ts b/tests/e2e/metrics/decorators/common.spec.ts index cf2133b..511c72c 100644 --- a/tests/e2e/metrics/decorators/common.spec.ts +++ b/tests/e2e/metrics/decorators/common.spec.ts @@ -15,8 +15,9 @@ describe('Common Decorators', () => { beforeEach(done => { exporter = new PrometheusExporter({}, () => { - meterProvider = new MeterProvider(); - meterProvider.addMetricReader(exporter); + meterProvider = new MeterProvider({ + readers: [exporter], + }); metrics.setGlobalMeterProvider(meterProvider); done(); }); @@ -34,7 +35,7 @@ describe('Common Decorators', () => { } }); - describe('Instance counter & Method counter', () => { + describe('Instance counter, method counter & param counter', () => { it('creates an instance counter and increase counter when new instance is created', async () => { const testingModule = await Test.createTestingModule({ imports: [ @@ -61,6 +62,9 @@ describe('Common Decorators', () => { expect(/app_AppController_instances_total 1/.test(text)).toBeTruthy(); expect(/app_AppController_example_calls_total 1/.test(text)).toBeTruthy(); + + expect(/# HELP example_counter_total An example counter/.test(text)).toBeTruthy(); + expect(/example_counter_total 1/.test(text)).toBeTruthy(); }); }); }); diff --git a/tests/fixture-app/app.controller.ts b/tests/fixture-app/app.controller.ts index 1e14699..d1e509f 100644 --- a/tests/fixture-app/app.controller.ts +++ b/tests/fixture-app/app.controller.ts @@ -1,5 +1,7 @@ import { Get, Controller } from '@nestjs/common'; +import { Counter } from '@opentelemetry/api'; import { OtelInstanceCounter, OtelMethodCounter } from '../../src/metrics/decorators/common'; +import { OtelCounter } from '../../src/metrics/decorators/param'; @OtelInstanceCounter() @Controller('example') @@ -11,7 +13,8 @@ export class AppController { @Get(':id') @OtelMethodCounter() - example() { + example(@OtelCounter('example_counter', { description: 'An example counter' }) counter: Counter) { + counter.add(1); return 'example'; } }