Skip to content

Commit

Permalink
feat: implement named meter (open-telemetry#700)
Browse files Browse the repository at this point in the history
* feat: implement named meter

* chore: update name provider to registry, remove 'default' name on MeterProvider

* chore: remove duplicated types import

* chore: address comments
  • Loading branch information
xiao-lix authored and mayurkale22 committed Jan 21, 2020
1 parent 2aa5399 commit 63748ae
Show file tree
Hide file tree
Showing 23 changed files with 242 additions and 68 deletions.
6 changes: 3 additions & 3 deletions examples/prometheus/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use strict";

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

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

const exporter = new PrometheusExporter(
{
Expand Down
14 changes: 7 additions & 7 deletions getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,19 +238,19 @@ Create a file named `monitoring.js` and add the following code:
```javascript
'use strict';
const { Meter } = require("@opentelemetry/metrics");
const { MeterRegistry } = require('@opentelemetry/metrics');
const meter = new Meter();
const meter = new MeterRegistry().getMeter('your-meter-name');
```

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:

```javascript
'use strict';
const { Meter } = require("@opentelemetry/metrics");
const { MeterRegistry } = require('@opentelemetry/metrics');
const meter = new Meter();
const meter = new MeterRegistry().getMeter('your-meter-name');
const requestCount = meter.createCounter("requests", {
monotonic: true,
Expand Down Expand Up @@ -301,10 +301,10 @@ Next, modify your `monitoring.js` file to look like this:
```javascript
"use strict";
const { Meter } = require("@opentelemetry/metrics");
const { PrometheusExporter } = require("@opentelemetry/exporter-prometheus");
const { MeterRegistry } = require('@opentelemetry/metrics');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
const meter = new Meter();
const meter = new MeterRegistry().getMeter('your-meter-name');
meter.addExporter(
new PrometheusExporter(
Expand Down
6 changes: 3 additions & 3 deletions getting-started/monitored-example/monitoring.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use strict";

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

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

meter.addExporter(
new PrometheusExporter(
Expand Down
32 changes: 16 additions & 16 deletions getting-started/ts-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ All tracing initialization should happen before your application’s code runs.
Create a file named `tracing.ts` and add the following code:

```typescript
import * as opentelemetry from "@opentelemetry/core";
import { NodeTracer } from "@opentelemetry/node";
import * as opentelemetry from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';

const tracer: NodeTracer = new NodeTracer({
logLevel: opentelemetry.LogLevel.ERROR
Expand Down Expand Up @@ -106,13 +106,13 @@ $ # npm install @opentelemetry/exporter-jaeger
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.

```typescript
import * as opentelemetry from "@opentelemetry/core";
import { NodeTracer } from "@opentelemetry/node";
import * as opentelemetry from '@opentelemetry/core';
import { NodeTracer } from '@opentelemetry/node';

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

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

```typescript
import { Meter } from "@opentelemetry/metrics";
import { MeterRegistry } from '@opentelemetry/metrics';
const meter = new Meter();
const meter = new MeterRegistry().getMeter('your-meter-name');
```

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:

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

```typescript
import { Meter } from "@opentelemetry/metrics";
import { Metric, BoundCounter } from "@opentelemetry/types";
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
import { MeterRegistry } from '@opentelemetry/metrics';
import { Metric, BoundCounter } from '@opentelemetry/types';
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
const meter = new Meter();
const meter = new MeterRegistry().getMeter('your-meter-name');
meter.addExporter(
new PrometheusExporter({ startServer: true }, () => {
Expand Down
8 changes: 4 additions & 4 deletions getting-started/ts-example/monitoring.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Meter } from "@opentelemetry/metrics";
import { Metric, BoundCounter } from "@opentelemetry/types";
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
import { MeterRegistry } from '@opentelemetry/metrics';
import { Metric, BoundCounter } from '@opentelemetry/types';
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';

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

meter.addExporter(
new PrometheusExporter({ startServer: true }, () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/opentelemetry-core/src/metrics/NoopMeter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ export class NoopBoundMeasure implements BoundMeasure {
}
}

export const noopMeter = new NoopMeter();

export const NOOP_BOUND_GAUGE = new NoopBoundGauge();
export const NOOP_GAUGE_METRIC = new NoopGaugeMetric(NOOP_BOUND_GAUGE);

Expand Down
28 changes: 28 additions & 0 deletions packages/opentelemetry-core/src/metrics/NoopMeterRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*!
* Copyright 2019, OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as types from '@opentelemetry/types';
import { noopMeter } from './NoopMeter';

/**
* An implementation of the {@link MeterRegistry} which returns an impotent Meter
* for all calls to `getMeter`
*/
export class NoopMeterRegistry implements types.MeterRegistry {
getMeter(_name?: string, _version?: string): types.Meter {
return noopMeter;
}
}
3 changes: 1 addition & 2 deletions packages/opentelemetry-core/src/trace/NoopSpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

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

/**
Expand All @@ -25,7 +24,7 @@ import { INVALID_SPAN_CONTEXT } from '../trace/spancontext-utils';
*/
export class NoopSpan implements types.Span {
constructor(
private readonly _spanContext: SpanContext = INVALID_SPAN_CONTEXT
private readonly _spanContext: types.SpanContext = INVALID_SPAN_CONTEXT
) {}

// Returns a SpanContext.
Expand Down
4 changes: 2 additions & 2 deletions packages/opentelemetry-core/test/metrics/NoopMeter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import * as assert from 'assert';
import {
NoopMeter,
NOOP_BOUND_GAUGE,
NOOP_GAUGE_METRIC,
NOOP_BOUND_COUNTER,
Expand All @@ -25,10 +24,11 @@ import {
NOOP_MEASURE_METRIC,
} from '../../src/metrics/NoopMeter';
import { Labels } from '@opentelemetry/types';
import { NoopMeterRegistry } from '../../src/metrics/NoopMeterRegistry';

describe('NoopMeter', () => {
it('should not crash', () => {
const meter = new NoopMeter();
const meter = new NoopMeterRegistry().getMeter('test-noop');
const counter = meter.createCounter('some-name');
const labels = {} as Labels;
const labelSet = meter.labels(labels);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
initGlobalTracerRegistry,
} from '../../src/trace/globaltracer-utils';
import { NoopTracer, NoopSpan } from '../../src';
import { TraceFlags } from '@opentelemetry/types';
import { NoopTracerRegistry } from '../../src/trace/NoopTracerRegistry';

describe('globaltracer-utils', () => {
Expand All @@ -43,7 +42,7 @@ describe('globaltracer-utils', () => {
const spanContext = {
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
spanId: '6e0c63257de34c92',
traceFlags: TraceFlags.UNSAMPLED,
traceFlags: types.TraceFlags.UNSAMPLED,
};
const dummySpan = new NoopSpan(spanContext);

Expand Down
4 changes: 2 additions & 2 deletions packages/opentelemetry-exporter-prometheus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ Create & register the exporter on your application.

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

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

// Register the exporter
const meter = new Meter();
const meter = new MeterRegistry().getMeter('exporter-prometheus');
meter.addExporter(exporter);

// Now, start recording data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
* limitations under the License.
*/

import { CounterMetric, GaugeMetric, Meter } from '@opentelemetry/metrics';
import {
CounterMetric,
GaugeMetric,
Meter,
MeterRegistry,
} from '@opentelemetry/metrics';
import * as assert from 'assert';
import * as http from 'http';
import { PrometheusExporter } from '../src';
Expand Down Expand Up @@ -166,7 +171,7 @@ describe('PrometheusExporter', () => {

beforeEach(done => {
exporter = new PrometheusExporter();
meter = new Meter();
meter = new MeterRegistry().getMeter('test-prometheus');
exporter.startServer(done);
});

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

beforeEach(() => {
meter = new Meter();
meter = new MeterRegistry().getMeter('test-prometheus');
gauge = meter.createGauge('gauge') as GaugeMetric;
gauge.bind(meter.labels({ key1: 'labelValue1' })).set(10);
});
Expand Down
8 changes: 4 additions & 4 deletions packages/opentelemetry-metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ npm install --save @opentelemetry/metrics
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.

```js
const { Meter } = require('@opentelemetry/metrics');
const { MeterRegistry } = require('@opentelemetry/metrics');

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

const counter = meter.createCounter('metric_name', {
labelKeys: ["pid"],
Expand All @@ -40,10 +40,10 @@ boundCounter.add(10);
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.

```js
const { Meter } = require('@opentelemetry/metrics');
const { MeterRegistry } = require('@opentelemetry/metrics');

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

const gauge = meter.createGauge('metric_name', {
labelKeys: ["pid"],
Expand Down
46 changes: 46 additions & 0 deletions packages/opentelemetry-metrics/src/MeterRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*!
* Copyright 2019, OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ConsoleLogger } from '@opentelemetry/core';
import * as types from '@opentelemetry/types';
import { Meter } from '.';
import { DEFAULT_CONFIG, MeterConfig } from './types';

/**
* This class represents a meter registry which platform libraries can extend
*/
export class MeterRegistry implements types.MeterRegistry {
private readonly _meters: Map<string, Meter> = new Map();
readonly logger: types.Logger;

constructor(private _config: MeterConfig = DEFAULT_CONFIG) {
this.logger = _config.logger || new ConsoleLogger(_config.logLevel);
}

/**
* Returns a Meter, creating one if one with the given name and version is not already created
*
* @returns Meter A Meter with the given name and version
*/
getMeter(name: string, version = '*', config?: MeterConfig): Meter {
const key = `${name}@${version}`;
if (!this._meters.has(key)) {
this._meters.set(key, new Meter(config || this._config));
}

return this._meters.get(key)!;
}
}
1 change: 1 addition & 0 deletions packages/opentelemetry-metrics/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
export * from './BoundInstrument';
export * from './Meter';
export * from './Metric';
export * from './MeterRegistry';
export * from './export/ConsoleMetricExporter';
export * from './export/types';
5 changes: 3 additions & 2 deletions packages/opentelemetry-metrics/test/Meter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
hrTimeToMilliseconds,
} from '@opentelemetry/core';
import { NoopExporter } from './mocks/Exporter';
import { MeterRegistry } from '../src/MeterRegistry';

const performanceTimeOrigin = hrTime();

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

beforeEach(() => {
meter = new Meter({
meter = new MeterRegistry({
logger: new NoopLogger(),
});
}).getMeter('test-meter');
labelSet = meter.labels(labels);
});

Expand Down
Loading

0 comments on commit 63748ae

Please sign in to comment.