From 4e0fc68562197449c68f80b063197c357e5f078d Mon Sep 17 00:00:00 2001 From: Hector Hernandez <39923391+hectorhdzg@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:49:58 -0700 Subject: [PATCH 1/5] Delegating no-op provider --- api/src/api/metrics.ts | 17 +- api/src/index.ts | 2 + api/src/metrics/ProxyMeter.ts | 148 +++++++++++++ api/src/metrics/ProxyMeterProvider.ts | 63 ++++++ .../proxy-implementations/proxy-meter.test.ts | 198 ++++++++++++++++++ .../opentelemetry-sdk-node/test/sdk.test.ts | 55 ++++- 6 files changed, 470 insertions(+), 13 deletions(-) create mode 100644 api/src/metrics/ProxyMeter.ts create mode 100644 api/src/metrics/ProxyMeterProvider.ts create mode 100644 api/test/common/proxy-implementations/proxy-meter.test.ts diff --git a/api/src/api/metrics.ts b/api/src/api/metrics.ts index 186e7cce4b..1e2f350d2b 100644 --- a/api/src/api/metrics.ts +++ b/api/src/api/metrics.ts @@ -16,13 +16,13 @@ import { Meter, MeterOptions } from '../metrics/Meter'; import { MeterProvider } from '../metrics/MeterProvider'; -import { NOOP_METER_PROVIDER } from '../metrics/NoopMeterProvider'; import { getGlobal, registerGlobal, unregisterGlobal, } from '../internal/global-utils'; import { DiagAPI } from './diag'; +import { ProxyMeterProvider } from '../metrics/ProxyMeterProvider'; const API_NAME = 'metrics'; @@ -32,6 +32,8 @@ const API_NAME = 'metrics'; export class MetricsAPI { private static _instance?: MetricsAPI; + private _proxyMeterProvider = new ProxyMeterProvider(); + /** Empty private constructor prevents end users from constructing a new instance of the API */ private constructor() {} @@ -49,14 +51,22 @@ export class MetricsAPI { * Returns true if the meter provider was successfully registered, else false. */ public setGlobalMeterProvider(provider: MeterProvider): boolean { - return registerGlobal(API_NAME, provider, DiagAPI.instance()); + const success = registerGlobal( + API_NAME, + this._proxyMeterProvider, + DiagAPI.instance() + ); + if (success) { + this._proxyMeterProvider.setDelegate(provider); + } + return success; } /** * Returns the global meter provider. */ public getMeterProvider(): MeterProvider { - return getGlobal(API_NAME) || NOOP_METER_PROVIDER; + return getGlobal(API_NAME) || this._proxyMeterProvider; } /** @@ -73,5 +83,6 @@ export class MetricsAPI { /** Remove the global meter provider */ public disable(): void { unregisterGlobal(API_NAME, DiagAPI.instance()); + this._proxyMeterProvider = new ProxyMeterProvider(); } } diff --git a/api/src/index.ts b/api/src/index.ts index c5dbe1685b..bf60cebeee 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -37,6 +37,8 @@ export { export type { DiagAPI } from './api/diag'; // Metrics APIs +export { ProxyMeter, MeterDelegator } from './metrics/ProxyMeter'; +export { ProxyMeterProvider } from './metrics/ProxyMeterProvider'; export { createNoopMeter } from './metrics/NoopMeter'; export { MeterOptions, Meter } from './metrics/Meter'; export { MeterProvider } from './metrics/MeterProvider'; diff --git a/api/src/metrics/ProxyMeter.ts b/api/src/metrics/ProxyMeter.ts new file mode 100644 index 0000000000..d524080419 --- /dev/null +++ b/api/src/metrics/ProxyMeter.ts @@ -0,0 +1,148 @@ +/* + * Copyright The 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 { Meter, MeterOptions } from './Meter'; +import { NoopMeter } from './NoopMeter'; +import { + BatchObservableCallback, + Counter, + Histogram, + MetricOptions, + ObservableCounter, + ObservableGauge, + ObservableUpDownCounter, + UpDownCounter, + Observable, +} from './Metric'; + +const NOOP_METER = new NoopMeter(); + +/** + * Proxy meter provided by the proxy meter provider + */ +export class ProxyMeter implements Meter { + // When a real implementation is provided, this will be it + private _delegate?: Meter; + + constructor( + private _provider: MeterDelegator, + public readonly name: string, + public readonly version?: string, + public readonly options?: MeterOptions + ) {} + + /** + * @see {@link Meter.createUpDownCounter} + */ + createHistogram(_name: string, _options?: MetricOptions): Histogram { + return this._getMeter().createHistogram(_name, _options); + } + + /** + * @see {@link Meter.createUpDownCounter} + */ + createCounter(_name: string, _options?: MetricOptions): Counter { + return this._getMeter().createCounter(_name, _options); + } + + /** + * @see {@link Meter.createUpDownCounter} + */ + createUpDownCounter(_name: string, _options?: MetricOptions): UpDownCounter { + return this._getMeter().createUpDownCounter(_name, _options); + } + + /** + * @see {@link Meter.createObservableGauge} + */ + createObservableGauge( + _name: string, + _options?: MetricOptions + ): ObservableGauge { + return this._getMeter().createObservableGauge(_name, _options); + } + + /** + * @see {@link Meter.createObservableCounter} + */ + createObservableCounter( + _name: string, + _options?: MetricOptions + ): ObservableCounter { + return this._getMeter().createObservableCounter(_name, _options); + } + + /** + * @see {@link Meter.createObservableUpDownCounter} + */ + createObservableUpDownCounter( + _name: string, + _options?: MetricOptions + ): ObservableUpDownCounter { + return this._getMeter().createObservableUpDownCounter(_name, _options); + } + + /** + * @see {@link Meter.addBatchObservableCallback} + */ + addBatchObservableCallback( + _callback: BatchObservableCallback, + _observables: Observable[] + ): void { + this._getMeter().addBatchObservableCallback(_callback, _observables); + } + + /** + * @see {@link Meter.removeBatchObservableCallback} + */ + removeBatchObservableCallback( + _callback: BatchObservableCallback, + _observables: Observable[] + ): void { + this._getMeter().removeBatchObservableCallback(_callback, _observables); + } + + /** + * Try to get a meter from the proxy meter provider. + * If the proxy meter provider has no delegate, return a noop meter. + */ + private _getMeter() { + if (this._delegate) { + return this._delegate; + } + + const meter = this._provider.getDelegateMeter( + this.name, + this.version, + this.options + ); + + if (!meter) { + return NOOP_METER; + } + + this._delegate = meter; + return this._delegate; + } +} + +export interface MeterDelegator { + getDelegateMeter( + name: string, + version?: string, + options?: MeterOptions + ): Meter | undefined; +} diff --git a/api/src/metrics/ProxyMeterProvider.ts b/api/src/metrics/ProxyMeterProvider.ts new file mode 100644 index 0000000000..bbfbe1cdf0 --- /dev/null +++ b/api/src/metrics/ProxyMeterProvider.ts @@ -0,0 +1,63 @@ +/* + * Copyright The 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 { MeterProvider } from './MeterProvider'; +import { ProxyMeter } from './ProxyMeter'; +import { NoopMeterProvider } from './NoopMeterProvider'; +import { Meter, MeterOptions } from './Meter'; + +const NOOP_METER_PROVIDER = new NoopMeterProvider(); + +/** + * Meter provider which provides {@link ProxyMeter}s. + * + * Before a delegate is set, meters provided are NoOp. + * When a delegate is set, meters are provided from the delegate. + * When a delegate is set after meters have already been provided, + * all meters already provided will use the provided delegate implementation. + */ +export class ProxyMeterProvider implements MeterProvider { + private _delegate?: MeterProvider; + + /** + * Get a {@link ProxyMeter} + */ + getMeter(name: string, version?: string, options?: MeterOptions): Meter { + return ( + this.getDelegateMeter(name, version, options) ?? + new ProxyMeter(this, name, version, options) + ); + } + + getDelegate(): MeterProvider { + return this._delegate ?? NOOP_METER_PROVIDER; + } + + /** + * Set the delegate meter provider + */ + setDelegate(delegate: MeterProvider) { + this._delegate = delegate; + } + + getDelegateMeter( + name: string, + version?: string, + options?: MeterOptions + ): Meter | undefined { + return this._delegate?.getMeter(name, version, options); + } +} diff --git a/api/test/common/proxy-implementations/proxy-meter.test.ts b/api/test/common/proxy-implementations/proxy-meter.test.ts new file mode 100644 index 0000000000..f050592f4b --- /dev/null +++ b/api/test/common/proxy-implementations/proxy-meter.test.ts @@ -0,0 +1,198 @@ +/* + * Copyright The 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 assert from 'assert'; +import * as sinon from 'sinon'; +import { + ProxyMeter, + ProxyMeterProvider, + Meter, + MeterProvider, + Histogram, + UpDownCounter, + ObservableGauge, + ObservableCounter, + Counter, + ObservableUpDownCounter, +} from '../../../src'; +import { + NoopHistogramMetric, + NoopMeter, + NoopObservableCounterMetric, + NoopObservableGaugeMetric, + NoopObservableUpDownCounterMetric, + NoopUpDownCounterMetric, +} from '../../../src/metrics/NoopMeter'; + +describe('ProxyMeter', () => { + let provider: ProxyMeterProvider; + const sandbox = sinon.createSandbox(); + + beforeEach(() => { + provider = new ProxyMeterProvider(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + describe('when no delegate is set', () => { + it('should return proxy meters', () => { + const meter = provider.getMeter('test'); + + assert.ok(meter instanceof ProxyMeter); + }); + + it('create instruments should return Noop metric instruments', () => { + const meter = provider.getMeter('test'); + assert.ok( + meter.createHistogram('histogram-name') instanceof NoopHistogramMetric + ); + assert.ok( + meter.createObservableCounter('observablecounter-name') instanceof + NoopObservableCounterMetric + ); + assert.ok( + meter.createObservableGauge('observableGauge-name') instanceof + NoopObservableGaugeMetric + ); + assert.ok( + meter.createObservableUpDownCounter('observableCounter-name') instanceof + NoopObservableUpDownCounterMetric + ); + assert.ok( + meter.createUpDownCounter('upDownCounter-name') instanceof + NoopUpDownCounterMetric + ); + }); + }); + + describe('when delegate is set before getMeter', () => { + let delegate: MeterProvider; + let getMeterStub: sinon.SinonStub; + + beforeEach(() => { + getMeterStub = sandbox.stub().returns(new NoopMeter()); + delegate = { + getMeter: getMeterStub, + }; + provider.setDelegate(delegate); + }); + + it('should return meters directly from the delegate', () => { + const meter = provider.getMeter('test', 'v0'); + + sandbox.assert.calledOnce(getMeterStub); + assert.strictEqual(getMeterStub.firstCall.returnValue, meter); + assert.deepStrictEqual(getMeterStub.firstCall.args, [ + 'test', + 'v0', + undefined, + ]); + }); + + it('should return meters directly from the delegate with schema url', () => { + const meter = provider.getMeter('test', 'v0', { + schemaUrl: 'https://opentelemetry.io/schemas/1.7.0', + }); + + sandbox.assert.calledOnce(getMeterStub); + assert.strictEqual(getMeterStub.firstCall.returnValue, meter); + assert.deepStrictEqual(getMeterStub.firstCall.args, [ + 'test', + 'v0', + { schemaUrl: 'https://opentelemetry.io/schemas/1.7.0' }, + ]); + }); + }); + + describe('when delegate is set after getMeter', () => { + let meter: Meter; + let delegate: MeterProvider; + let delegateHistogram: Histogram; + let delegateCounter: Counter; + let delegateUpDownCounter: UpDownCounter; + let delegateObservableGauge: ObservableGauge; + let delegateObservableCounter: ObservableCounter; + let delegateObservableUpDownCounter: ObservableUpDownCounter; + let delegateMeter: Meter; + + beforeEach(() => { + delegateHistogram = new NoopHistogramMetric(); + delegateMeter = { + createHistogram() { + return delegateHistogram; + }, + createCounter() { + return delegateCounter; + }, + createObservableCounter() { + return delegateObservableCounter; + }, + createObservableGauge() { + return delegateObservableGauge; + }, + createObservableUpDownCounter() { + return delegateObservableUpDownCounter; + }, + createUpDownCounter() { + return delegateUpDownCounter; + }, + addBatchObservableCallback() {}, + removeBatchObservableCallback() {}, + }; + + meter = provider.getMeter('test'); + + delegate = { + getMeter() { + return delegateMeter; + }, + }; + provider.setDelegate(delegate); + }); + + it('should create histograms using the delegate meter', () => { + const instrument = meter.createHistogram('test'); + assert.strictEqual(instrument, delegateHistogram); + }); + + it('should create counters using the delegate meter', () => { + const instrument = meter.createCounter('test'); + assert.strictEqual(instrument, delegateCounter); + }); + + it('should create observable counters using the delegate meter', () => { + const instrument = meter.createObservableCounter('test'); + assert.strictEqual(instrument, delegateObservableCounter); + }); + + it('should create observable gauges using the delegate meter', () => { + const instrument = meter.createObservableGauge('test'); + assert.strictEqual(instrument, delegateObservableGauge); + }); + + it('should create observable up down counters using the delegate meter', () => { + const instrument = meter.createObservableUpDownCounter('test'); + assert.strictEqual(instrument, delegateObservableUpDownCounter); + }); + + it('should create observable up down counters using the delegate meter', () => { + const histogram = meter.createUpDownCounter('test'); + assert.strictEqual(histogram, delegateUpDownCounter); + }); + }); +}); diff --git a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts index 22e1794ccc..bb11f9fab1 100644 --- a/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts +++ b/experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts @@ -18,6 +18,7 @@ import { context, propagation, ProxyTracerProvider, + ProxyMeterProvider, trace, diag, DiagLogLevel, @@ -84,6 +85,7 @@ describe('Node SDK', () => { let ctxManager: any; let propagator: any; let delegate: any; + let metricsDelegate: any; beforeEach(() => { diag.disable(); @@ -95,6 +97,9 @@ describe('Node SDK', () => { ctxManager = context['_getContextManager'](); propagator = propagation['_getGlobalPropagator'](); delegate = (trace.getTracerProvider() as ProxyTracerProvider).getDelegate(); + metricsDelegate = ( + metrics.getMeterProvider() as ProxyMeterProvider + ).getDelegate(); }); afterEach(() => { @@ -127,7 +132,11 @@ describe('Node SDK', () => { delegate, 'tracer provider should not have changed' ); - assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); + assert.strictEqual( + (metrics.getMeterProvider() as ProxyMeterProvider).getDelegate(), + metricsDelegate, + 'meter provider should not have changed' + ); assert.ok(!(logs.getLoggerProvider() instanceof LoggerProvider)); delete env.OTEL_TRACES_EXPORTER; await sdk.shutdown(); @@ -175,7 +184,13 @@ describe('Node SDK', () => { sdk.start(); - assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); + assert.ok( + !( + ( + metrics.getMeterProvider() as ProxyMeterProvider + ).getDelegate() instanceof MeterProvider + ) + ); assert.ok( context['_getContextManager']().constructor.name === @@ -198,7 +213,13 @@ describe('Node SDK', () => { sdk.start(); - assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); + assert.ok( + !( + ( + metrics.getMeterProvider() as ProxyMeterProvider + ).getDelegate() instanceof MeterProvider + ) + ); assert.ok( context['_getContextManager']().constructor.name === @@ -228,7 +249,13 @@ describe('Node SDK', () => { sdk.start(); - assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); + assert.ok( + !( + ( + metrics.getMeterProvider() as ProxyMeterProvider + ).getDelegate() instanceof MeterProvider + ) + ); assert.ok( context['_getContextManager']().constructor.name === @@ -285,9 +312,11 @@ describe('Node SDK', () => { delegate, 'tracer provider should not have changed' ); - - assert.ok(metrics.getMeterProvider() instanceof MeterProvider); - + assert.ok( + ( + metrics.getMeterProvider() as ProxyMeterProvider + ).getDelegate() instanceof MeterProvider + ); await sdk.shutdown(); delete env.OTEL_TRACES_EXPORTER; }); @@ -386,8 +415,8 @@ describe('Node SDK', () => { 'tracer provider should not have changed' ); - const meterProvider = metrics.getMeterProvider() as MeterProvider; - assert.ok(meterProvider); + const meterProvider = metrics.getMeterProvider() as ProxyMeterProvider; + assert.ok(meterProvider.getDelegate() instanceof MeterProvider); const meter = meterProvider.getMeter('NodeSDKViews', '1.0.0'); const counter = meter.createCounter('test_counter', { @@ -768,7 +797,13 @@ describe('Node SDK', () => { }); sdk.start(); - assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider)); + assert.ok( + !( + ( + metrics.getMeterProvider() as ProxyMeterProvider + ).getDelegate() instanceof MeterProvider + ) + ); await sdk.shutdown(); }); From 2c8b47647c0b057896ea5d45af86ffb15ef9feca Mon Sep 17 00:00:00 2001 From: Hector Hernandez <39923391+hectorhdzg@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:01:25 -0700 Subject: [PATCH 2/5] add create gauge methods --- api/src/metrics/ProxyMeter.ts | 8 ++++++++ .../common/proxy-implementations/proxy-meter.test.ts | 10 ++++++++++ experimental/packages/otlp-grpc-exporter-base/protos | 1 + experimental/packages/otlp-proto-exporter-base/protos | 1 + 4 files changed, 20 insertions(+) create mode 160000 experimental/packages/otlp-grpc-exporter-base/protos create mode 160000 experimental/packages/otlp-proto-exporter-base/protos diff --git a/api/src/metrics/ProxyMeter.ts b/api/src/metrics/ProxyMeter.ts index d524080419..0e7f930b2b 100644 --- a/api/src/metrics/ProxyMeter.ts +++ b/api/src/metrics/ProxyMeter.ts @@ -26,6 +26,7 @@ import { ObservableUpDownCounter, UpDownCounter, Observable, + Gauge, } from './Metric'; const NOOP_METER = new NoopMeter(); @@ -44,6 +45,13 @@ export class ProxyMeter implements Meter { public readonly options?: MeterOptions ) {} + /** + * @see {@link Meter.createGauge} + */ + createGauge(_name: string, _options?: MetricOptions): Gauge { + return this._getMeter().createGauge(_name, _options); + } + /** * @see {@link Meter.createUpDownCounter} */ diff --git a/api/test/common/proxy-implementations/proxy-meter.test.ts b/api/test/common/proxy-implementations/proxy-meter.test.ts index f050592f4b..6007112976 100644 --- a/api/test/common/proxy-implementations/proxy-meter.test.ts +++ b/api/test/common/proxy-implementations/proxy-meter.test.ts @@ -27,6 +27,7 @@ import { ObservableCounter, Counter, ObservableUpDownCounter, + Gauge, } from '../../../src'; import { NoopHistogramMetric, @@ -122,6 +123,7 @@ describe('ProxyMeter', () => { describe('when delegate is set after getMeter', () => { let meter: Meter; let delegate: MeterProvider; + let delegateGauge: Gauge; let delegateHistogram: Histogram; let delegateCounter: Counter; let delegateUpDownCounter: UpDownCounter; @@ -133,6 +135,9 @@ describe('ProxyMeter', () => { beforeEach(() => { delegateHistogram = new NoopHistogramMetric(); delegateMeter = { + createGauge() { + return delegateGauge; + }, createHistogram() { return delegateHistogram; }, @@ -165,6 +170,11 @@ describe('ProxyMeter', () => { provider.setDelegate(delegate); }); + it('should create gauges using the delegate meter', () => { + const instrument = meter.createGauge('test'); + assert.strictEqual(instrument, delegateGauge); + }); + it('should create histograms using the delegate meter', () => { const instrument = meter.createHistogram('test'); assert.strictEqual(instrument, delegateHistogram); diff --git a/experimental/packages/otlp-grpc-exporter-base/protos b/experimental/packages/otlp-grpc-exporter-base/protos new file mode 160000 index 0000000000..1608f92cf0 --- /dev/null +++ b/experimental/packages/otlp-grpc-exporter-base/protos @@ -0,0 +1 @@ +Subproject commit 1608f92cf08119f9aec237c910b200d1317ec696 diff --git a/experimental/packages/otlp-proto-exporter-base/protos b/experimental/packages/otlp-proto-exporter-base/protos new file mode 160000 index 0000000000..1608f92cf0 --- /dev/null +++ b/experimental/packages/otlp-proto-exporter-base/protos @@ -0,0 +1 @@ +Subproject commit 1608f92cf08119f9aec237c910b200d1317ec696 From fa9d8dccbb9404fe39ba3cf2517ca27102b8b84c Mon Sep 17 00:00:00 2001 From: Hector Hernandez <39923391+hectorhdzg@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:04:13 -0700 Subject: [PATCH 3/5] Remove otlp protos --- experimental/packages/otlp-grpc-exporter-base/protos | 1 - experimental/packages/otlp-proto-exporter-base/protos | 1 - 2 files changed, 2 deletions(-) delete mode 160000 experimental/packages/otlp-grpc-exporter-base/protos delete mode 160000 experimental/packages/otlp-proto-exporter-base/protos diff --git a/experimental/packages/otlp-grpc-exporter-base/protos b/experimental/packages/otlp-grpc-exporter-base/protos deleted file mode 160000 index 1608f92cf0..0000000000 --- a/experimental/packages/otlp-grpc-exporter-base/protos +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1608f92cf08119f9aec237c910b200d1317ec696 diff --git a/experimental/packages/otlp-proto-exporter-base/protos b/experimental/packages/otlp-proto-exporter-base/protos deleted file mode 160000 index 1608f92cf0..0000000000 --- a/experimental/packages/otlp-proto-exporter-base/protos +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1608f92cf08119f9aec237c910b200d1317ec696 From 7fafc7a08ea29060130026553932abbfeaceb0d7 Mon Sep 17 00:00:00 2001 From: Hector Hernandez <39923391+hectorhdzg@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:40:26 -0700 Subject: [PATCH 4/5] Add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 644972b950..6e5d608d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :boom: Breaking Change +* feat(api) Add delegating no-op meter provider [#4858](https://github.com/open-telemetry/opentelemetry-js/pull/4858) @hectorhdzg + ### :rocket: (Enhancement) ### :bug: (Bug Fix) From 55fe56617e51f8914394d7ec8f0017134237abee Mon Sep 17 00:00:00 2001 From: Hector Hernandez <39923391+hectorhdzg@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:20:31 -0700 Subject: [PATCH 5/5] Update API changelog --- CHANGELOG.md | 2 -- api/CHANGELOG.md | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5d608d53..644972b950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,6 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :boom: Breaking Change -* feat(api) Add delegating no-op meter provider [#4858](https://github.com/open-telemetry/opentelemetry-js/pull/4858) @hectorhdzg - ### :rocket: (Enhancement) ### :bug: (Bug Fix) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 860f839c37..990a3e1c81 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -7,6 +7,8 @@ All notable changes to this project will be documented in this file. ### :boom: Breaking Change +* feat(api) Add delegating no-op meter provider [#4858](https://github.com/open-telemetry/opentelemetry-js/pull/4858) @hectorhdzg + ### :rocket: (Enhancement) ### :bug: (Bug Fix)