Skip to content

Commit

Permalink
chore: rename Metric Handle to Bound Instrument (open-telemetry#634)
Browse files Browse the repository at this point in the history
  • Loading branch information
cthulhu-bot committed Dec 23, 2019
1 parent 38ce1c3 commit 98e9891
Show file tree
Hide file tree
Showing 18 changed files with 308 additions and 281 deletions.
8 changes: 4 additions & 4 deletions examples/prometheus/index.js
Expand Up @@ -46,10 +46,10 @@ setInterval(() => {

currentMonotonicGaugeValue += Math.random();

monotonicCounter.getHandle(labels).add(1);
nonMonotonicCounter.getHandle(labels).add(Math.random() > 0.5 ? 1 : -1);
monotonicGauge.getHandle(labels).set(currentMonotonicGaugeValue);
monotonicCounter.bind(labels).add(1);
nonMonotonicCounter.bind(labels).add(Math.random() > 0.5 ? 1 : -1);
monotonicGauge.bind(labels).set(currentMonotonicGaugeValue);
nonMonotonicGauge
.getHandle(labels)
.bind(labels)
.set(Math.random() > 0.5 ? Math.random() * 10 : -Math.random() * 10);
}, 1000);
22 changes: 11 additions & 11 deletions getting-started/README.md
Expand Up @@ -227,17 +227,17 @@ const requestCount = meter.createCounter("requests", {
description: "Count all incoming requests"
});

const handles = new Map();
const boundInstruments = new Map();

module.exports.countAllRequests = () => {
return (req, res, next) => {
if (!handles.has(req.path)) {
if (!boundInstruments.has(req.path)) {
const labelSet = meter.labels({ route: req.path });
const handle = requestCount.getHandle(labelSet);
handles.set(req.path, handle);
const boundCounter = requestCount.bind(labelSet);
boundInstruments.set(req.path, boundCounter);
}

handles.get(req.path).add(1);
boundInstruments.get(req.path).add(1);
next();
};
};
Expand All @@ -253,7 +253,7 @@ app.use(countAllRequests());

Now, when we make requests to our service our meter will count all requests.

**Note**: Creating a new `labelSet` and `handle` on every request is not ideal as creating the `labelSet` can often be an expensive operation. This is why handles are created and stored in a `Map` according to the route key.
**Note**: Creating a new `labelSet` and `binding` on every request is not ideal as creating the `labelSet` can often be an expensive operation. This is why instruments are created and stored in a `Map` according to the route key.

#### Initialize and register a metrics exporter
Counting metrics is only useful if we can export them somewhere that we can see them. For this, we're going to use prometheus. Creating and registering a metrics exporter is much like the tracing exporter above. First we will need to install the prometheus exporter.
Expand Down Expand Up @@ -287,17 +287,17 @@ const requestCount = meter.createCounter("requests", {
description: "Count all incoming requests"
});

const handles = new Map();
const boundInstruments = new Map();

module.exports.countAllRequests = () => {
return (req, res, next) => {
if (!handles.has(req.path)) {
if (!boundInstruments.has(req.path)) {
const labelSet = meter.labels({ route: req.path });
const handle = requestCount.getHandle(labelSet);
handles.set(req.path, handle);
const boundCounter = requestCount.bind(labelSet);
boundInstruments.set(req.path, boundCounter);
}

handles.get(req.path).add(1);
boundInstruments.get(req.path).add(1);
next();
};
};
Expand Down
10 changes: 5 additions & 5 deletions getting-started/monitored-example/monitoring.js
Expand Up @@ -22,17 +22,17 @@ const requestCount = meter.createCounter("requests", {
description: "Count all incoming requests"
});

const handles = new Map();
const instruments = new Map();

module.exports.countAllRequests = () => {
return (req, res, next) => {
if (!handles.has(req.path)) {
if (!instruments.has(req.path)) {
const labelSet = meter.labels({ route: req.path });
const handle = requestCount.getHandle(labelSet);
handles.set(req.path, handle);
const boundCounter = requestCount.bind(labelSet);
instruments.set(req.path, boundCounter);
}

handles.get(req.path).add(1);
instruments.get(req.path).add(1);
next();
};
};
84 changes: 47 additions & 37 deletions packages/opentelemetry-core/src/metrics/NoopMeter.ts
Expand Up @@ -15,14 +15,14 @@
*/

import {
CounterHandle,
BoundCounter,
DistributedContext,
GaugeHandle,
BoundGauge,
Meter,
Metric,
MetricOptions,
MetricUtils,
MeasureHandle,
BoundMeasure,
SpanContext,
LabelSet,
Labels,
Expand All @@ -40,7 +40,10 @@ export class NoopMeter implements Meter {
* @param name the name of the metric.
* @param [options] the metric options.
*/
createMeasure(name: string, options?: MetricOptions): Metric<MeasureHandle> {
createMeasure(
name: string,
options?: MetricOptions
): Metric<BoundMeasure> {
return NOOP_MEASURE_METRIC;
}

Expand All @@ -49,7 +52,10 @@ export class NoopMeter implements Meter {
* @param name the name of the metric.
* @param [options] the metric options.
*/
createCounter(name: string, options?: MetricOptions): Metric<CounterHandle> {
createCounter(
name: string,
options?: MetricOptions
): Metric<BoundCounter> {
return NOOP_COUNTER_METRIC;
}

Expand All @@ -58,7 +64,7 @@ export class NoopMeter implements Meter {
* @param name the name of the metric.
* @param [options] the metric options.
*/
createGauge(name: string, options?: MetricOptions): Metric<GaugeHandle> {
createGauge(name: string, options?: MetricOptions): Metric<BoundGauge> {
return NOOP_GAUGE_METRIC;
}

Expand All @@ -68,33 +74,33 @@ export class NoopMeter implements Meter {
}

export class NoopMetric<T> implements Metric<T> {
private readonly _handle: T;
private readonly _instrument: T;

constructor(handle: T) {
this._handle = handle;
constructor(instrument: T) {
this._instrument = instrument;
}
/**
* Returns a Handle associated with specified LabelSet.
* It is recommended to keep a reference to the Handle instead of always
* Returns an Instrument associated with specified LabelSet.
* It is recommended to keep a reference to the Instrument instead of always
* calling this method for every operations.
* @param labels the canonicalized LabelSet used to associate with this metric handle.
* @param labels the canonicalized LabelSet used to associate with this metric instrument.
*/
getHandle(labels: LabelSet): T {
return this._handle;
bind(labels: LabelSet): T {
return this._instrument;
}

/**
* Returns a Handle for a metric with all labels not set.
* Returns an Instrument for a metric with all labels not set.
*/
getDefaultHandle(): T {
return this._handle;
getDefaultBound(): T {
return this._instrument;
}

/**
* Removes the Handle from the metric, if it is present.
* @param labels the canonicalized LabelSet used to associate with this metric handle.
* Removes the Binding from the metric, if it is present.
* @param labels the canonicalized LabelSet used to associate with this metric instrument.
*/
removeHandle(labels: LabelSet): void {
unbind(labels: LabelSet): void {
// @todo: implement this method
return;
}
Expand All @@ -111,21 +117,21 @@ export class NoopMetric<T> implements Metric<T> {
}
}

export class NoopCounterMetric extends NoopMetric<CounterHandle>
export class NoopCounterMetric extends NoopMetric<BoundCounter>
implements Pick<MetricUtils, 'add'> {
add(value: number, labelSet: LabelSet) {
this.getHandle(labelSet).add(value);
this.bind(labelSet).add(value);
}
}

export class NoopGaugeMetric extends NoopMetric<GaugeHandle>
export class NoopGaugeMetric extends NoopMetric<BoundGauge>
implements Pick<MetricUtils, 'set'> {
set(value: number, labelSet: LabelSet) {
this.getHandle(labelSet).set(value);
this.bind(labelSet).set(value);
}
}

export class NoopMeasureMetric extends NoopMetric<MeasureHandle>
export class NoopMeasureMetric extends NoopMetric<BoundMeasure>
implements Pick<MetricUtils, 'record'> {
record(
value: number,
Expand All @@ -134,28 +140,28 @@ export class NoopMeasureMetric extends NoopMetric<MeasureHandle>
spanContext?: SpanContext
) {
if (typeof distContext === 'undefined') {
this.getHandle(labelSet).record(value);
this.bind(labelSet).record(value);
} else if (typeof spanContext === 'undefined') {
this.getHandle(labelSet).record(value, distContext);
this.bind(labelSet).record(value, distContext);
} else {
this.getHandle(labelSet).record(value, distContext, spanContext);
this.bind(labelSet).record(value, distContext, spanContext);
}
}
}

export class NoopCounterHandle implements CounterHandle {
export class NoopBoundCounter implements BoundCounter {
add(value: number): void {
return;
}
}

export class NoopGaugeHandle implements GaugeHandle {
export class NoopBoundGauge implements BoundGauge {
set(value: number): void {
return;
}
}

export class NoopMeasureHandle implements MeasureHandle {
export class NoopBoundMeasure implements BoundMeasure {
record(
value: number,
distContext?: DistributedContext,
Expand All @@ -165,13 +171,17 @@ export class NoopMeasureHandle implements MeasureHandle {
}
}

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

export const NOOP_COUNTER_HANDLE = new NoopCounterHandle();
export const NOOP_COUNTER_METRIC = new NoopCounterMetric(NOOP_COUNTER_HANDLE);
export const NOOP_BOUND_COUNTER = new NoopBoundCounter();
export const NOOP_COUNTER_METRIC = new NoopCounterMetric(
NOOP_BOUND_COUNTER
);

export const NOOP_MEASURE_HANDLE = new NoopMeasureHandle();
export const NOOP_MEASURE_METRIC = new NoopMeasureMetric(NOOP_MEASURE_HANDLE);
export const NOOP_BOUND_MEASURE = new NoopBoundMeasure();
export const NOOP_MEASURE_METRIC = new NoopMeasureMetric(
NOOP_BOUND_MEASURE
);

export const NOOP_LABEL_SET = {} as LabelSet;
32 changes: 16 additions & 16 deletions packages/opentelemetry-core/test/metrics/NoopMeter.test.ts
Expand Up @@ -17,11 +17,11 @@
import * as assert from 'assert';
import {
NoopMeter,
NOOP_GAUGE_HANDLE,
NOOP_BOUND_GAUGE,
NOOP_GAUGE_METRIC,
NOOP_COUNTER_HANDLE,
NOOP_BOUND_COUNTER,
NOOP_COUNTER_METRIC,
NOOP_MEASURE_HANDLE,
NOOP_BOUND_MEASURE,
NOOP_MEASURE_METRIC,
} from '../../src/metrics/NoopMeter';
import { Labels } from '@opentelemetry/types';
Expand All @@ -37,20 +37,20 @@ describe('NoopMeter', () => {
counter.setCallback(() => {
assert.fail('callback occurred');
});
counter.getHandle(labelSet).add(1);
counter.getDefaultHandle().add(1);
counter.removeHandle(labelSet);
counter.bind(labelSet).add(1);
counter.getDefaultBound().add(1);
counter.unbind(labelSet);

// ensure the correct noop const is returned
assert.strictEqual(counter, NOOP_COUNTER_METRIC);
assert.strictEqual(counter.getHandle(labelSet), NOOP_COUNTER_HANDLE);
assert.strictEqual(counter.getDefaultHandle(), NOOP_COUNTER_HANDLE);
assert.strictEqual(counter.bind(labelSet), NOOP_BOUND_COUNTER);
assert.strictEqual(counter.getDefaultBound(), NOOP_BOUND_COUNTER);
counter.clear();

const measure = meter.createMeasure('some-name');
measure.getDefaultHandle().record(1);
measure.getDefaultHandle().record(1, { key: { value: 'value' } });
measure.getDefaultHandle().record(
measure.getDefaultBound().record(1);
measure.getDefaultBound().record(1, { key: { value: 'value' } });
measure.getDefaultBound().record(
1,
{ key: { value: 'value' } },
{
Expand All @@ -61,16 +61,16 @@ describe('NoopMeter', () => {

// ensure the correct noop const is returned
assert.strictEqual(measure, NOOP_MEASURE_METRIC);
assert.strictEqual(measure.getDefaultHandle(), NOOP_MEASURE_HANDLE);
assert.strictEqual(measure.getHandle(labelSet), NOOP_MEASURE_HANDLE);
assert.strictEqual(measure.getDefaultBound(), NOOP_BOUND_MEASURE);
assert.strictEqual(measure.bind(labelSet), NOOP_BOUND_MEASURE);

const gauge = meter.createGauge('some-name');
gauge.getDefaultHandle().set(1);
gauge.getDefaultBound().set(1);

// ensure the correct noop const is returned
assert.strictEqual(gauge, NOOP_GAUGE_METRIC);
assert.strictEqual(gauge.getDefaultHandle(), NOOP_GAUGE_HANDLE);
assert.strictEqual(gauge.getHandle(labelSet), NOOP_GAUGE_HANDLE);
assert.strictEqual(gauge.getDefaultBound(), NOOP_BOUND_GAUGE);
assert.strictEqual(gauge.bind(labelSet), NOOP_BOUND_GAUGE);

const options = {
component: 'tests',
Expand Down
8 changes: 4 additions & 4 deletions packages/opentelemetry-exporter-prometheus/README.md
Expand Up @@ -36,10 +36,10 @@ meter.addExporter(exporter);
const counter = meter.createCounter('metric_name');
counter.add(10, meter.labels({ [key]: 'value' }));

// Record data using Handle: It is recommended to keep a reference to the Handle instead of
// always calling `getHandle()` method for every operations.
const handle = counter.getHandle(meter.labels({ [key]: 'value' }));
handle.add(10);
// Record data using Instrument: It is recommended to keep a reference to the Instrument instead of
// always calling `bind()` method for every operations.
const boundCounter = counter.bind(meter.labels({ [key]: 'value' }));
boundCounter.add(10);

// .. some other work

Expand Down

0 comments on commit 98e9891

Please sign in to comment.