From a1d4420d09f16994754be2057b39469cf6ccbfad Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Thu, 5 Mar 2020 09:23:47 -0800 Subject: [PATCH] feat: metric observer (#828) * feat: metric observer * chore: update after review * chore: reviews Co-authored-by: Mayur Kale --- api/package.json | 3 ++- api/src/index.ts | 1 + api/src/metrics/BoundInstrument.ts | 12 ++++++++++++ api/src/metrics/Meter.ts | 11 +++++++++-- api/src/metrics/Metric.ts | 8 ++++++++ api/src/metrics/NoopMeter.ts | 24 +++++++++++++++++++++++- api/src/metrics/ObserverResult.ts | 25 +++++++++++++++++++++++++ 7 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 api/src/metrics/ObserverResult.ts diff --git a/api/package.json b/api/package.json index 93eb52e62a..d9a44de09a 100644 --- a/api/package.json +++ b/api/package.json @@ -18,7 +18,8 @@ "compile": "npm run version:update && tsc -p .", "docs-test": "linkinator docs/out --silent --skip david-dm.org", "docs": "typedoc --tsconfig tsconfig.json --exclude test/**/*.ts", - "prepare": "npm run compile" + "prepare": "npm run compile", + "watch": "tsc -w" }, "keywords": [ "opentelemetry", diff --git a/api/src/index.ts b/api/src/index.ts index 04b0876e0a..2653d5af56 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -26,6 +26,7 @@ export * from './metrics/MeterProvider'; export * from './metrics/Metric'; export * from './metrics/NoopMeter'; export * from './metrics/NoopMeterProvider'; +export * from './metrics/ObserverResult'; export * from './trace/attributes'; export * from './trace/Event'; export * from './trace/instrumentation/Plugin'; diff --git a/api/src/metrics/BoundInstrument.ts b/api/src/metrics/BoundInstrument.ts index 07302bd22f..11204029d6 100644 --- a/api/src/metrics/BoundInstrument.ts +++ b/api/src/metrics/BoundInstrument.ts @@ -16,6 +16,7 @@ import { CorrelationContext } from '../correlation_context/CorrelationContext'; import { SpanContext } from '../trace/span_context'; +import { ObserverResult } from './ObserverResult'; /** An Instrument for Counter Metric. */ export interface BoundCounter { @@ -44,3 +45,14 @@ export interface BoundMeasure { spanContext: SpanContext ): void; } + +/** Base interface for the Observer metrics. */ +export interface BoundObserver { + /** + * Sets callback for the observer. The callback is called once and then it + * sets observers for values. The observers are called periodically to + * retrieve the value. + * @param callback + */ + setCallback(callback: (observerResult: ObserverResult) => {}): void; +} diff --git a/api/src/metrics/Meter.ts b/api/src/metrics/Meter.ts index 54f09118d2..4348370fd0 100644 --- a/api/src/metrics/Meter.ts +++ b/api/src/metrics/Meter.ts @@ -15,7 +15,7 @@ */ import { Metric, MetricOptions, Labels, LabelSet } from './Metric'; -import { BoundCounter, BoundMeasure } from './BoundInstrument'; +import { BoundCounter, BoundMeasure, BoundObserver } from './BoundInstrument'; /** * An interface to allow the recording metrics. @@ -33,7 +33,7 @@ export interface Meter { createMeasure(name: string, options?: MetricOptions): Metric; /** - * Creates a new `counter` metric. Generally, this kind of metric when the + * Creates a new `Counter` metric. Generally, 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. * @param name the name of the metric. @@ -41,6 +41,13 @@ export interface Meter { */ createCounter(name: string, options?: MetricOptions): Metric; + /** + * Creates a new `Observer` metric. + * @param name the name of the metric. + * @param [options] the metric options. + */ + createObserver(name: string, options?: MetricOptions): Metric; + /** * Provide a pre-computed re-useable LabelSet by * converting the unordered labels into a canonicalized diff --git a/api/src/metrics/Metric.ts b/api/src/metrics/Metric.ts index e6e711353f..23f19f6af2 100644 --- a/api/src/metrics/Metric.ts +++ b/api/src/metrics/Metric.ts @@ -16,6 +16,7 @@ import { CorrelationContext } from '../correlation_context/CorrelationContext'; import { SpanContext } from '../trace/span_context'; +import { ObserverResult } from './ObserverResult'; /** * Options needed for metric creation @@ -105,6 +106,13 @@ export interface MetricUtils { */ add(value: number, labelSet: LabelSet): void; + /** + * Sets a callback where user can observe value for certain labels + * @param callback a function that will be called once to set observers + * for values + */ + setCallback(callback: (observerResult: ObserverResult) => void): void; + /** * Sets the given value. Values can be negative. */ diff --git a/api/src/metrics/NoopMeter.ts b/api/src/metrics/NoopMeter.ts index b3ab749831..2a48c68c96 100644 --- a/api/src/metrics/NoopMeter.ts +++ b/api/src/metrics/NoopMeter.ts @@ -16,9 +16,10 @@ import { Meter } from './Meter'; import { MetricOptions, Metric, Labels, LabelSet, MetricUtils } from './Metric'; -import { BoundMeasure, BoundCounter } from './BoundInstrument'; +import { BoundMeasure, BoundCounter, BoundObserver } from './BoundInstrument'; import { CorrelationContext } from '../correlation_context/CorrelationContext'; import { SpanContext } from '../trace/span_context'; +import { ObserverResult } from './ObserverResult'; /** * NoopMeter is a noop implementation of the {@link Meter} interface. It reuses @@ -45,6 +46,15 @@ export class NoopMeter implements Meter { return NOOP_COUNTER_METRIC; } + /** + * Returns constant noop observer. + * @param name the name of the metric. + * @param [options] the metric options. + */ + createObserver(name: string, options?: MetricOptions): Metric { + return NOOP_OBSERVER_METRIC; + } + labels(labels: Labels): LabelSet { return NOOP_LABEL_SET; } @@ -120,6 +130,11 @@ export class NoopMeasureMetric extends NoopMetric } } +export class NoopObserverMetric extends NoopMetric + implements Pick { + setCallback(callback: (observerResult: ObserverResult) => void): void {} +} + export class NoopBoundCounter implements BoundCounter { add(value: number): void { return; @@ -136,6 +151,10 @@ export class NoopBoundMeasure implements BoundMeasure { } } +export class NoopBoundObserver implements BoundObserver { + setCallback(callback: (observerResult: ObserverResult) => {}): void {} +} + export const NOOP_METER = new NoopMeter(); export const NOOP_BOUND_COUNTER = new NoopBoundCounter(); export const NOOP_COUNTER_METRIC = new NoopCounterMetric(NOOP_BOUND_COUNTER); @@ -143,4 +162,7 @@ export const NOOP_COUNTER_METRIC = new NoopCounterMetric(NOOP_BOUND_COUNTER); export const NOOP_BOUND_MEASURE = new NoopBoundMeasure(); export const NOOP_MEASURE_METRIC = new NoopMeasureMetric(NOOP_BOUND_MEASURE); +export const NOOP_BOUND_OBSERVER = new NoopBoundObserver(); +export const NOOP_OBSERVER_METRIC = new NoopObserverMetric(NOOP_BOUND_OBSERVER); + export const NOOP_LABEL_SET = {} as LabelSet; diff --git a/api/src/metrics/ObserverResult.ts b/api/src/metrics/ObserverResult.ts new file mode 100644 index 0000000000..f3eb082fd4 --- /dev/null +++ b/api/src/metrics/ObserverResult.ts @@ -0,0 +1,25 @@ +/*! + * Copyright 2020, 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 { LabelSet } from './Metric'; + +/** + * Interface that is being used in function setCallback for Observer Metric + */ +export interface ObserverResult { + observers: Map; + observe(callback: Function, labelSet: LabelSet): void; +}