Skip to content

Commit 63748ae

Browse files
xiao-lixmayurkale22
authored andcommitted
feat: implement named meter (#700)
* feat: implement named meter * chore: update name provider to registry, remove 'default' name on MeterProvider * chore: remove duplicated types import * chore: address comments
1 parent 2aa5399 commit 63748ae

File tree

23 files changed

+242
-68
lines changed

23 files changed

+242
-68
lines changed

examples/prometheus/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"use strict";
22

3-
const { Meter } = require("@opentelemetry/metrics");
4-
const { PrometheusExporter } = require("@opentelemetry/exporter-prometheus");
3+
const { MeterRegistry } = require('@opentelemetry/metrics');
4+
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
55

6-
const meter = new Meter();
6+
const meter = new MeterRegistry().getMeter('example-prometheus');
77

88
const exporter = new PrometheusExporter(
99
{

getting-started/README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -238,19 +238,19 @@ Create a file named `monitoring.js` and add the following code:
238238
```javascript
239239
'use strict';
240240
241-
const { Meter } = require("@opentelemetry/metrics");
241+
const { MeterRegistry } = require('@opentelemetry/metrics');
242242
243-
const meter = new Meter();
243+
const meter = new MeterRegistry().getMeter('your-meter-name');
244244
```
245245

246246
Now, you can require this file from your application code and use the `Meter` to create and manage metrics. The simplest of these metrics is a counter. Let's create and export from our `monitoring.js` file a middleware function that express can use to count all requests by route. Modify the `monitoring.js` file so that it looks like this:
247247

248248
```javascript
249249
'use strict';
250250
251-
const { Meter } = require("@opentelemetry/metrics");
251+
const { MeterRegistry } = require('@opentelemetry/metrics');
252252
253-
const meter = new Meter();
253+
const meter = new MeterRegistry().getMeter('your-meter-name');
254254
255255
const requestCount = meter.createCounter("requests", {
256256
monotonic: true,
@@ -301,10 +301,10 @@ Next, modify your `monitoring.js` file to look like this:
301301
```javascript
302302
"use strict";
303303
304-
const { Meter } = require("@opentelemetry/metrics");
305-
const { PrometheusExporter } = require("@opentelemetry/exporter-prometheus");
304+
const { MeterRegistry } = require('@opentelemetry/metrics');
305+
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
306306
307-
const meter = new Meter();
307+
const meter = new MeterRegistry().getMeter('your-meter-name');
308308
309309
meter.addExporter(
310310
new PrometheusExporter(

getting-started/monitored-example/monitoring.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"use strict";
22

3-
const { Meter } = require("@opentelemetry/metrics");
4-
const { PrometheusExporter } = require("@opentelemetry/exporter-prometheus");
3+
const { MeterRegistry } = require('@opentelemetry/metrics');
4+
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
55

6-
const meter = new Meter();
6+
const meter = new MeterRegistry().getMeter('example-monitored');
77

88
meter.addExporter(
99
new PrometheusExporter(

getting-started/ts-example/README.md

+16-16
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ All tracing initialization should happen before your application’s code runs.
7272
Create a file named `tracing.ts` and add the following code:
7373

7474
```typescript
75-
import * as opentelemetry from "@opentelemetry/core";
76-
import { NodeTracer } from "@opentelemetry/node";
75+
import * as opentelemetry from '@opentelemetry/core';
76+
import { NodeTracer } from '@opentelemetry/node';
7777

7878
const tracer: NodeTracer = new NodeTracer({
7979
logLevel: opentelemetry.LogLevel.ERROR
@@ -106,13 +106,13 @@ $ # npm install @opentelemetry/exporter-jaeger
106106
After these dependencies are installed, we will need to initialize and register them. Modify `tracing.ts` so that it matches the following code snippet, replacing the service name `"getting-started"` with your own service name if you wish.
107107

108108
```typescript
109-
import * as opentelemetry from "@opentelemetry/core";
110-
import { NodeTracer } from "@opentelemetry/node";
109+
import * as opentelemetry from '@opentelemetry/core';
110+
import { NodeTracer } from '@opentelemetry/node';
111111

112-
import { SimpleSpanProcessor } from "@opentelemetry/tracing";
113-
import { ZipkinExporter } from "@opentelemetry/exporter-zipkin";
112+
import { SimpleSpanProcessor } from '@opentelemetry/tracing';
113+
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
114114
// For Jaeger, use the following line instead:
115-
// import { JaegerExporter } from "@opentelemetry/exporter-jaeger";
115+
// import { JaegerExporter } from '@opentelemetry/exporter-jaeger';
116116

117117
const tracer: NodeTracer = new NodeTracer({
118118
logLevel: opentelemetry.LogLevel.ERROR
@@ -236,18 +236,18 @@ In order to create and monitor metrics, we will need a `Meter`. In OpenTelemetry
236236
Create a file named `monitoring.ts` and add the following code:
237237

238238
```typescript
239-
import { Meter } from "@opentelemetry/metrics";
239+
import { MeterRegistry } from '@opentelemetry/metrics';
240240
241-
const meter = new Meter();
241+
const meter = new MeterRegistry().getMeter('your-meter-name');
242242
```
243243

244244
Now, you can require this file from your application code and use the `Meter` to create and manage metrics. The simplest of these metrics is a counter. Let's create and export from our `monitoring.ts` file a middleware function that express can use to count all requests by route. Modify the `monitoring.ts` file so that it looks like this:
245245

246246
```typescript
247-
import { Meter } from "@opentelemetry/metrics";
248-
import { Metric, BoundCounter } from "@opentelemetry/types";
247+
import { MeterRegistry } from '@opentelemetry/metrics';
248+
import { Metric, BoundCounter } from '@opentelemetry/types';
249249
250-
const meter = new Meter();
250+
const meter = new MeterRegistry().getMeter('your-meter-name');
251251
252252
const requestCount: Metric<BoundCounter> = meter.createCounter("requests", {
253253
monotonic: true,
@@ -296,11 +296,11 @@ $ npm install @opentelemetry/exporter-prometheus
296296
Next, modify your `monitoring.ts` file to look like this:
297297

298298
```typescript
299-
import { Meter } from "@opentelemetry/metrics";
300-
import { Metric, BoundCounter } from "@opentelemetry/types";
301-
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
299+
import { MeterRegistry } from '@opentelemetry/metrics';
300+
import { Metric, BoundCounter } from '@opentelemetry/types';
301+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
302302
303-
const meter = new Meter();
303+
const meter = new MeterRegistry().getMeter('your-meter-name');
304304
305305
meter.addExporter(
306306
new PrometheusExporter({ startServer: true }, () => {

getting-started/ts-example/monitoring.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Meter } from "@opentelemetry/metrics";
2-
import { Metric, BoundCounter } from "@opentelemetry/types";
3-
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
1+
import { MeterRegistry } from '@opentelemetry/metrics';
2+
import { Metric, BoundCounter } from '@opentelemetry/types';
3+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
44

5-
const meter = new Meter();
5+
const meter = new MeterRegistry().getMeter('example-ts');
66

77
meter.addExporter(
88
new PrometheusExporter({ startServer: true }, () => {

packages/opentelemetry-core/src/metrics/NoopMeter.ts

+2
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ export class NoopBoundMeasure implements BoundMeasure {
165165
}
166166
}
167167

168+
export const noopMeter = new NoopMeter();
169+
168170
export const NOOP_BOUND_GAUGE = new NoopBoundGauge();
169171
export const NOOP_GAUGE_METRIC = new NoopGaugeMetric(NOOP_BOUND_GAUGE);
170172

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*!
2+
* Copyright 2019, OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as types from '@opentelemetry/types';
18+
import { noopMeter } from './NoopMeter';
19+
20+
/**
21+
* An implementation of the {@link MeterRegistry} which returns an impotent Meter
22+
* for all calls to `getMeter`
23+
*/
24+
export class NoopMeterRegistry implements types.MeterRegistry {
25+
getMeter(_name?: string, _version?: string): types.Meter {
26+
return noopMeter;
27+
}
28+
}

packages/opentelemetry-core/src/trace/NoopSpan.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616

1717
import * as types from '@opentelemetry/types';
18-
import { SpanContext } from '@opentelemetry/types';
1918
import { INVALID_SPAN_CONTEXT } from '../trace/spancontext-utils';
2019

2120
/**
@@ -25,7 +24,7 @@ import { INVALID_SPAN_CONTEXT } from '../trace/spancontext-utils';
2524
*/
2625
export class NoopSpan implements types.Span {
2726
constructor(
28-
private readonly _spanContext: SpanContext = INVALID_SPAN_CONTEXT
27+
private readonly _spanContext: types.SpanContext = INVALID_SPAN_CONTEXT
2928
) {}
3029

3130
// Returns a SpanContext.

packages/opentelemetry-core/test/metrics/NoopMeter.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import * as assert from 'assert';
1818
import {
19-
NoopMeter,
2019
NOOP_BOUND_GAUGE,
2120
NOOP_GAUGE_METRIC,
2221
NOOP_BOUND_COUNTER,
@@ -25,10 +24,11 @@ import {
2524
NOOP_MEASURE_METRIC,
2625
} from '../../src/metrics/NoopMeter';
2726
import { Labels } from '@opentelemetry/types';
27+
import { NoopMeterRegistry } from '../../src/metrics/NoopMeterRegistry';
2828

2929
describe('NoopMeter', () => {
3030
it('should not crash', () => {
31-
const meter = new NoopMeter();
31+
const meter = new NoopMeterRegistry().getMeter('test-noop');
3232
const counter = meter.createCounter('some-name');
3333
const labels = {} as Labels;
3434
const labelSet = meter.labels(labels);

packages/opentelemetry-core/test/trace/globaltracer-utils.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
initGlobalTracerRegistry,
2222
} from '../../src/trace/globaltracer-utils';
2323
import { NoopTracer, NoopSpan } from '../../src';
24-
import { TraceFlags } from '@opentelemetry/types';
2524
import { NoopTracerRegistry } from '../../src/trace/NoopTracerRegistry';
2625

2726
describe('globaltracer-utils', () => {
@@ -43,7 +42,7 @@ describe('globaltracer-utils', () => {
4342
const spanContext = {
4443
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
4544
spanId: '6e0c63257de34c92',
46-
traceFlags: TraceFlags.UNSAMPLED,
45+
traceFlags: types.TraceFlags.UNSAMPLED,
4746
};
4847
const dummySpan = new NoopSpan(spanContext);
4948

packages/opentelemetry-exporter-prometheus/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ Create & register the exporter on your application.
2222

2323
```js
2424
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
25-
const { Meter } = require('@opentelemetry/metrics');
25+
const { MeterRegistry } = require('@opentelemetry/metrics');
2626

2727
// Add your port and startServer to the Prometheus options
2828
const options = {port: 9464, startServer: true};
2929
const exporter = new PrometheusExporter(options);
3030

3131
// Register the exporter
32-
const meter = new Meter();
32+
const meter = new MeterRegistry().getMeter('exporter-prometheus');
3333
meter.addExporter(exporter);
3434

3535
// Now, start recording data

packages/opentelemetry-exporter-prometheus/test/prometheus.test.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { CounterMetric, GaugeMetric, Meter } from '@opentelemetry/metrics';
17+
import {
18+
CounterMetric,
19+
GaugeMetric,
20+
Meter,
21+
MeterRegistry,
22+
} from '@opentelemetry/metrics';
1823
import * as assert from 'assert';
1924
import * as http from 'http';
2025
import { PrometheusExporter } from '../src';
@@ -166,7 +171,7 @@ describe('PrometheusExporter', () => {
166171

167172
beforeEach(done => {
168173
exporter = new PrometheusExporter();
169-
meter = new Meter();
174+
meter = new MeterRegistry().getMeter('test-prometheus');
170175
exporter.startServer(done);
171176
});
172177

@@ -382,7 +387,7 @@ describe('PrometheusExporter', () => {
382387
let exporter: PrometheusExporter | undefined;
383388

384389
beforeEach(() => {
385-
meter = new Meter();
390+
meter = new MeterRegistry().getMeter('test-prometheus');
386391
gauge = meter.createGauge('gauge') as GaugeMetric;
387392
gauge.bind(meter.labels({ key1: 'labelValue1' })).set(10);
388393
});

packages/opentelemetry-metrics/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ npm install --save @opentelemetry/metrics
1919
Choose this kind of metric when the value is a quantity, the sum is of primary interest, and the event count and value distribution are not of primary interest. Counters are defined as `Monotonic = true` by default, meaning that positive values are expected.
2020

2121
```js
22-
const { Meter } = require('@opentelemetry/metrics');
22+
const { MeterRegistry } = require('@opentelemetry/metrics');
2323

2424
// Initialize the Meter to capture measurements in various ways.
25-
const meter = new Meter();
25+
const meter = new MeterRegistry().getMeter('your-meter-name');
2626

2727
const counter = meter.createCounter('metric_name', {
2828
labelKeys: ["pid"],
@@ -40,10 +40,10 @@ boundCounter.add(10);
4040
Gauge metrics express a pre-calculated value. Generally, this kind of metric should be used when the metric cannot be expressed as a sum or because the measurement interval is arbitrary. Use this kind of metric when the measurement is not a quantity, and the sum and event count are not of interest. Gauges are defined as `Monotonic = false` by default, meaning that new values are permitted to make positive or negative changes to the gauge. There is no restriction on the sign of the input for gauges.
4141

4242
```js
43-
const { Meter } = require('@opentelemetry/metrics');
43+
const { MeterRegistry } = require('@opentelemetry/metrics');
4444

4545
// Initialize the Meter to capture measurements in various ways.
46-
const meter = new Meter();
46+
const meter = new MeterRegistry().getMeter('your-meter-name');
4747

4848
const gauge = meter.createGauge('metric_name', {
4949
labelKeys: ["pid"],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*!
2+
* Copyright 2019, OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { ConsoleLogger } from '@opentelemetry/core';
18+
import * as types from '@opentelemetry/types';
19+
import { Meter } from '.';
20+
import { DEFAULT_CONFIG, MeterConfig } from './types';
21+
22+
/**
23+
* This class represents a meter registry which platform libraries can extend
24+
*/
25+
export class MeterRegistry implements types.MeterRegistry {
26+
private readonly _meters: Map<string, Meter> = new Map();
27+
readonly logger: types.Logger;
28+
29+
constructor(private _config: MeterConfig = DEFAULT_CONFIG) {
30+
this.logger = _config.logger || new ConsoleLogger(_config.logLevel);
31+
}
32+
33+
/**
34+
* Returns a Meter, creating one if one with the given name and version is not already created
35+
*
36+
* @returns Meter A Meter with the given name and version
37+
*/
38+
getMeter(name: string, version = '*', config?: MeterConfig): Meter {
39+
const key = `${name}@${version}`;
40+
if (!this._meters.has(key)) {
41+
this._meters.set(key, new Meter(config || this._config));
42+
}
43+
44+
return this._meters.get(key)!;
45+
}
46+
}

packages/opentelemetry-metrics/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
export * from './BoundInstrument';
1818
export * from './Meter';
1919
export * from './Metric';
20+
export * from './MeterRegistry';
2021
export * from './export/ConsoleMetricExporter';
2122
export * from './export/types';

packages/opentelemetry-metrics/test/Meter.test.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
hrTimeToMilliseconds,
3232
} from '@opentelemetry/core';
3333
import { NoopExporter } from './mocks/Exporter';
34+
import { MeterRegistry } from '../src/MeterRegistry';
3435

3536
const performanceTimeOrigin = hrTime();
3637

@@ -43,9 +44,9 @@ describe('Meter', () => {
4344
const hrTime: types.HrTime = [22, 400000000];
4445

4546
beforeEach(() => {
46-
meter = new Meter({
47+
meter = new MeterRegistry({
4748
logger: new NoopLogger(),
48-
});
49+
}).getMeter('test-meter');
4950
labelSet = meter.labels(labels);
5051
});
5152

0 commit comments

Comments
 (0)