Skip to content

Commit

Permalink
feat(sdk-metrics-base): per metric-reader aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
legendecas committed Aug 9, 2022
1 parent d995b80 commit a9a058d
Show file tree
Hide file tree
Showing 43 changed files with 691 additions and 342 deletions.
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to experimental packages in this project will be documented

* feature(add-console-metrics-exporter): add ConsoleMetricExporter [#3120](https://github.com/open-telemetry/opentelemetry-js/pull/3120) @weyert
* feature(prometheus-serialiser): export the unit block when unit is set in metric descriptor [#3066](https://github.com/open-telemetry/opentelemetry-js/pull/3041) @weyert
* feat(sdk-metrics-base): add per metric-reader aggregation support [#3153](https://github.com/open-telemetry/opentelemetry-js/pull/3153) @legendecas

### :bug: (Bug Fix)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
*/

import {
defaultOptions,
OTLPMetricExporterBase,
OTLPMetricExporterOptions
} from '@opentelemetry/exporter-metrics-otlp-http';
import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base';
import {
Expand All @@ -33,7 +31,7 @@ import { createExportMetricsServiceRequest, IExportMetricsServiceRequest } from

class OTLPMetricExporterProxy extends OTLPGRPCExporterNodeBase<ResourceMetrics, IExportMetricsServiceRequest> {

constructor(config: OTLPGRPCExporterConfigNode & OTLPMetricExporterOptions= defaultOptions) {
constructor(config: OTLPGRPCExporterConfigNode = {}) {
super(config);
const headers = baggageUtils.parseKeyPairsIntoRecord(getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS);
this.metadata ||= new Metadata();
Expand Down Expand Up @@ -73,7 +71,7 @@ class OTLPMetricExporterProxy extends OTLPGRPCExporterNodeBase<ResourceMetrics,
* OTLP-gRPC metric exporter
*/
export class OTLPMetricExporter extends OTLPMetricExporterBase<OTLPMetricExporterProxy>{
constructor(config: OTLPGRPCExporterConfigNode & OTLPMetricExporterOptions = defaultOptions) {
super(new OTLPMetricExporterProxy(config), config);
constructor(config: OTLPGRPCExporterConfigNode = {}) {
super(new OTLPMetricExporterProxy(config));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
mockHistogram,
mockObservableGauge, setUp, shutdown,
} from './metricsHelper';
import { AggregationTemporality, ResourceMetrics } from '@opentelemetry/sdk-metrics-base';
import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base';
import { IExportMetricsServiceRequest, IResourceMetrics } from '@opentelemetry/otlp-transformer';

const metricsServiceProtoPath =
Expand Down Expand Up @@ -128,7 +128,6 @@ const testOTLPMetricExporter = (params: TestParams) =>
url: 'https://' + address,
credentials,
metadata: params.metadata,
temporalityPreference: AggregationTemporality.CUMULATIVE
});

setUp();
Expand Down Expand Up @@ -184,15 +183,13 @@ const testOTLPMetricExporter = (params: TestParams) =>
headers: {
foo: 'bar',
},
temporalityPreference: AggregationTemporality.CUMULATIVE
});
const args = warnStub.args[0];
assert.strictEqual(args[0], 'Headers cannot be set when using grpc');
});
it('should warn about path in url', () => {
collectorExporter = new OTLPMetricExporter({
url: `http://${address}/v1/metrics`,
temporalityPreference: AggregationTemporality.CUMULATIVE
});
const args = warnStub.args[0];
assert.strictEqual(
Expand Down Expand Up @@ -264,7 +261,6 @@ describe('OTLPMetricExporter - node (getDefaultUrl)', () => {
const url = 'http://foo.bar.com';
const collectorExporter = new OTLPMetricExporter({
url,
temporalityPreference: AggregationTemporality.CUMULATIVE
});
setTimeout(() => {
assert.strictEqual(collectorExporter._otlpExporter.url, 'foo.bar.com');
Expand Down Expand Up @@ -309,7 +305,6 @@ describe('when configuring via environment', () => {
envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo';
const collectorExporter = new OTLPMetricExporter({
metadata,
temporalityPreference: AggregationTemporality.CUMULATIVE
});
assert.deepStrictEqual(collectorExporter._otlpExporter.metadata?.get('foo'), ['boo']);
assert.deepStrictEqual(collectorExporter._otlpExporter.metadata?.get('bar'), ['foo']);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as assert from 'assert';
import * as grpc from '@grpc/grpc-js';
import { VERSION } from '@opentelemetry/core';
import {
Aggregation,
AggregationTemporality,
ExplicitBucketHistogramAggregation,
MeterProvider,
Expand All @@ -29,6 +30,10 @@ import {
import { IKeyValue, IMetric, IResource } from '@opentelemetry/otlp-transformer';

class TestMetricReader extends MetricReader {
selectAggregation() {
return Aggregation.Default();
}

selectAggregationTemporality() {
return AggregationTemporality.CUMULATIVE;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 { getEnv } from '@opentelemetry/core';
import { Aggregation, AggregationSelector, AggregationTemporality, AggregationTemporalitySelector, InstrumentType } from '@opentelemetry/sdk-metrics-base';

/**
* Default {@link AggregationTemporalitySelector} when the OTLP Metrics Exporter is configured with environ `OTEL_METRICS_EXPORTER`.
*/
const CumulativeTemporalitySelector: AggregationTemporalitySelector = () => AggregationTemporality.CUMULATIVE;

/**
* Default {@link AggregationSelector} when the OTLP Metrics Exporter is configured with environ `OTEL_METRICS_EXPORTER`.
*/
const DeltaTemporalitySelector: AggregationTemporalitySelector = (instrumentType: InstrumentType) => {
switch (instrumentType) {
case InstrumentType.COUNTER:
case InstrumentType.OBSERVABLE_COUNTER:
case InstrumentType.HISTOGRAM:
case InstrumentType.OBSERVABLE_GAUGE:
return AggregationTemporality.DELTA;
case InstrumentType.UP_DOWN_COUNTER:
case InstrumentType.OBSERVABLE_UP_DOWN_COUNTER:
return AggregationTemporality.CUMULATIVE;
}
};

function chooseTemporalitySelector(temporalityPreference?: AggregationTemporality): AggregationTemporalitySelector {
if (temporalityPreference === AggregationTemporality.DELTA) {
return DeltaTemporalitySelector;
}

return CumulativeTemporalitySelector;
}

/**
* Get the default {@link AggregationTemporalitySelector} based on the environ `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE`.
*/
export function getDefaultAggregationTemporalitySelector(): AggregationTemporalitySelector {
const env = getEnv();
const temporalityPreference = env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE !== 'cumulative' ? AggregationTemporality.DELTA : AggregationTemporality.CUMULATIVE;
return chooseTemporalitySelector(temporalityPreference);
}

/**
* Get the default {@link AggregationSelector} based on the environ `OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION`.
*/
export function getDefaultAggregationSelector(): AggregationSelector {
// TODO(legendecas): exponential bucket histogram support.
return Aggregation.Default;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,20 @@

import { ExportResult } from '@opentelemetry/core';
import {
AggregationTemporality,
AggregationTemporalitySelector,
InstrumentType,
PushMetricExporter,
ResourceMetrics
} from '@opentelemetry/sdk-metrics-base';
import { defaultOptions, OTLPMetricExporterOptions } from './OTLPMetricExporterOptions';
import { OTLPExporterBase } from '@opentelemetry/otlp-exporter-base';
import { OTLPExporterBase, OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base';
import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer';

export const CumulativeTemporalitySelector: AggregationTemporalitySelector = () => AggregationTemporality.CUMULATIVE;

export const DeltaTemporalitySelector: AggregationTemporalitySelector = (instrumentType: InstrumentType) => {
switch (instrumentType) {
case InstrumentType.COUNTER:
case InstrumentType.OBSERVABLE_COUNTER:
case InstrumentType.HISTOGRAM:
case InstrumentType.OBSERVABLE_GAUGE:
return AggregationTemporality.DELTA;
case InstrumentType.UP_DOWN_COUNTER:
case InstrumentType.OBSERVABLE_UP_DOWN_COUNTER:
return AggregationTemporality.CUMULATIVE;
}
};

function chooseTemporalitySelector(temporalityPreference?: AggregationTemporality): AggregationTemporalitySelector {
if (temporalityPreference === AggregationTemporality.DELTA) {
return DeltaTemporalitySelector;
}

return CumulativeTemporalitySelector;
}

export class OTLPMetricExporterBase<T extends OTLPExporterBase<OTLPMetricExporterOptions,
export class OTLPMetricExporterBase<T extends OTLPExporterBase<OTLPExporterConfigBase,
ResourceMetrics,
IExportMetricsServiceRequest>>
implements PushMetricExporter {
public _otlpExporter: T;
protected _aggregationTemporalitySelector: AggregationTemporalitySelector;

constructor(exporter: T,
config: OTLPMetricExporterOptions = defaultOptions) {
constructor(exporter: T) {
this._otlpExporter = exporter;
this._aggregationTemporalitySelector = chooseTemporalitySelector(config.temporalityPreference);
}

export(metrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): void {
Expand All @@ -73,8 +43,4 @@ implements PushMetricExporter {
forceFlush(): Promise<void> {
return Promise.resolve();
}

selectAggregationTemporality(instrumentType: InstrumentType): AggregationTemporality {
return this._aggregationTemporalitySelector(instrumentType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@
*/

export * from './platform';
export * from './OTLPMetricExporterOptions';
export * from './OTLPMetricExporterBase';
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base';
import { baggageUtils, getEnv } from '@opentelemetry/core';
import { defaultOptions, OTLPMetricExporterOptions } from '../../OTLPMetricExporterOptions';
import { OTLPMetricExporterBase } from '../../OTLPMetricExporterBase';
import {
OTLPExporterBrowserBase,
Expand All @@ -31,7 +30,7 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC

class OTLPExporterBrowserProxy extends OTLPExporterBrowserBase<ResourceMetrics, IExportMetricsServiceRequest> {

constructor(config: OTLPMetricExporterOptions & OTLPExporterConfigBase = defaultOptions) {
constructor(config: OTLPExporterConfigBase) {
super(config);
this._headers = Object.assign(
this._headers,
Expand Down Expand Up @@ -60,7 +59,7 @@ class OTLPExporterBrowserProxy extends OTLPExporterBrowserBase<ResourceMetrics,
* Collector Metric Exporter for Web
*/
export class OTLPMetricExporter extends OTLPMetricExporterBase<OTLPExporterBrowserProxy> {
constructor(config: OTLPExporterConfigBase & OTLPMetricExporterOptions = defaultOptions) {
super(new OTLPExporterBrowserProxy(config), config);
constructor(config: OTLPExporterConfigBase = {}) {
super(new OTLPExporterBrowserProxy(config));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import { ResourceMetrics } from '@opentelemetry/sdk-metrics-base';
import { getEnv, baggageUtils} from '@opentelemetry/core';
import { defaultOptions, OTLPMetricExporterOptions } from '../../OTLPMetricExporterOptions';
import { OTLPMetricExporterBase } from '../../OTLPMetricExporterBase';
import {
OTLPExporterNodeBase,
Expand All @@ -31,7 +30,7 @@ const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURC

class OTLPExporterNodeProxy extends OTLPExporterNodeBase<ResourceMetrics, IExportMetricsServiceRequest> {

constructor(config: OTLPExporterNodeConfigBase & OTLPMetricExporterOptions = defaultOptions) {
constructor(config: OTLPExporterNodeConfigBase) {
super(config);
this.headers = Object.assign(
this.headers,
Expand Down Expand Up @@ -60,7 +59,7 @@ class OTLPExporterNodeProxy extends OTLPExporterNodeBase<ResourceMetrics, IExpor
* Collector Metric Exporter for Node
*/
export class OTLPMetricExporter extends OTLPMetricExporterBase<OTLPExporterNodeProxy> {
constructor(config: OTLPExporterNodeConfigBase & OTLPMetricExporterOptions = defaultOptions) {
super(new OTLPExporterNodeProxy(config), config);
constructor(config: OTLPExporterNodeConfigBase = {}) {
super(new OTLPExporterNodeProxy(config));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { diag, DiagLogger, DiagLogLevel } from '@opentelemetry/api';
import { Counter, Histogram, } from '@opentelemetry/api-metrics';
import { ExportResultCode, hrTimeToNanoseconds } from '@opentelemetry/core';
import { AggregationTemporality, ResourceMetrics, } from '@opentelemetry/sdk-metrics-base';
import { ResourceMetrics, } from '@opentelemetry/sdk-metrics-base';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { OTLPMetricExporter } from '../../src/platform/browser';
Expand All @@ -34,7 +34,6 @@ import {
setUp,
shutdown,
} from '../metricsHelper';
import { OTLPMetricExporterOptions } from '../../src';
import { OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base';
import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer';

Expand Down Expand Up @@ -96,9 +95,9 @@ describe('OTLPMetricExporter - web', () => {
beforeEach(() => {
collectorExporter = new OTLPMetricExporter({
url: 'http://foo.bar.com',
temporalityPreference: AggregationTemporality.CUMULATIVE
});
});

it('should successfully send metrics using sendBeacon', done => {
collectorExporter.export(metrics, () => {
});
Expand Down Expand Up @@ -193,7 +192,6 @@ describe('OTLPMetricExporter - web', () => {
(window.navigator as any).sendBeacon = false;
collectorExporter = new OTLPMetricExporter({
url: 'http://foo.bar.com',
temporalityPreference: AggregationTemporality.CUMULATIVE
});
// Overwrites the start time to make tests consistent
Object.defineProperty(collectorExporter, '_startTime', {
Expand Down Expand Up @@ -313,12 +311,11 @@ describe('OTLPMetricExporter - web', () => {
foo: 'bar',
bar: 'baz',
};
let collectorExporterConfig: (OTLPExporterConfigBase & OTLPMetricExporterOptions) | undefined;
let collectorExporterConfig: OTLPExporterConfigBase;

beforeEach(() => {
collectorExporterConfig = {
headers: customHeaders,
temporalityPreference: AggregationTemporality.CUMULATIVE
};
server = sinon.fakeServer.create();
});
Expand Down Expand Up @@ -454,8 +451,7 @@ describe('when configuring via environment', () => {
it('should use headers defined via env', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar';
const collectorExporter = new OTLPMetricExporter({
headers: {},
temporalityPreference: AggregationTemporality.CUMULATIVE
headers: {}
});
assert.strictEqual(collectorExporter['_otlpExporter']['_headers'].foo, 'bar');
envSource.OTEL_EXPORTER_OTLP_HEADERS = '';
Expand All @@ -464,8 +460,7 @@ describe('when configuring via environment', () => {
envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo';
envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo';
const collectorExporter = new OTLPMetricExporter({
headers: {},
temporalityPreference: AggregationTemporality.CUMULATIVE
headers: {}
});
assert.strictEqual(collectorExporter['_otlpExporter']['_headers'].foo, 'boo');
assert.strictEqual(collectorExporter['_otlpExporter']['_headers'].bar, 'foo');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Resource } from '@opentelemetry/resources';
import * as assert from 'assert';
import { InstrumentationScope, VERSION } from '@opentelemetry/core';
import {
Aggregation,
AggregationTemporality,
ExplicitBucketHistogramAggregation,
MeterProvider,
Expand Down Expand Up @@ -57,6 +58,10 @@ class TestMetricReader extends MetricReader {
return Promise.resolve(undefined);
}

selectAggregation() {
return Aggregation.Default();
}

selectAggregationTemporality() {
return AggregationTemporality.CUMULATIVE;
}
Expand Down
Loading

0 comments on commit a9a058d

Please sign in to comment.