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 24, 2022
1 parent c73d782 commit fabdaf4
Show file tree
Hide file tree
Showing 31 changed files with 663 additions and 251 deletions.
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,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: support latest `@opentelemetry/api` [#3177](https://github.com/open-telemetry/opentelemetry-js/pull/3177) @dyladan
* 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 @@ -214,13 +214,18 @@ const testOTLPMetricExporter = (params: TestParams) =>

assert.ok(exportedData, 'exportedData does not exist');

// The order of the metrics is not guaranteed.
const counterIndex = exportedData[0].scopeMetrics[0].metrics.findIndex(it => it.name === 'int-counter');
const observableIndex = exportedData[0].scopeMetrics[0].metrics.findIndex(it => it.name === 'double-observable-gauge');
const histogramIndex = exportedData[0].scopeMetrics[0].metrics.findIndex(it => it.name === 'int-histogram');

const resource = exportedData[0].resource;
const counter =
exportedData[0].scopeMetrics[0].metrics[0];
exportedData[0].scopeMetrics[0].metrics[counterIndex];
const observableGauge =
exportedData[0].scopeMetrics[0].metrics[1];
exportedData[0].scopeMetrics[0].metrics[observableIndex];
const histogram =
exportedData[0].scopeMetrics[0].metrics[2];
exportedData[0].scopeMetrics[0].metrics[histogramIndex];
ensureExportedCounterIsCorrect(
counter,
counter.sum?.dataPoints[0].timeUnixNano,
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
Expand Up @@ -99,6 +99,7 @@ describe('OTLPMetricExporter - web', () => {
temporalityPreference: AggregationTemporality.CUMULATIVE
});
});

it('should successfully send metrics using sendBeacon', done => {
collectorExporter.export(metrics, () => {
});
Expand All @@ -109,16 +110,22 @@ describe('OTLPMetricExporter - web', () => {
const blob: Blob = args[1];
const body = await blob.text();
const json = JSON.parse(body) as IExportMetricsServiceRequest;
const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2];

// The order of the metrics is not guaranteed.
const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-counter');
const observableIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'double-observable-gauge2');
const histogramIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-histogram');

const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[counterIndex];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[observableIndex];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[histogramIndex];

assert.ok(typeof metric1 !== 'undefined', "metric doesn't exist");

ensureCounterIsCorrect(
metric1,
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].startTime)
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime)
);


Expand All @@ -128,8 +135,8 @@ describe('OTLPMetricExporter - web', () => {
);
ensureObservableGaugeIsCorrect(
metric2,
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].startTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].startTime),
6,
'double-observable-gauge2'
);
Expand All @@ -140,8 +147,8 @@ describe('OTLPMetricExporter - web', () => {
);
ensureHistogramIsCorrect(
metric3,
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].startTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].startTime),
[0, 100],
[0, 2, 0]
);
Expand Down Expand Up @@ -216,15 +223,20 @@ describe('OTLPMetricExporter - web', () => {

const body = request.requestBody;
const json = JSON.parse(body) as IExportMetricsServiceRequest;
const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2];
// The order of the metrics is not guaranteed.
const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-counter');
const observableIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'double-observable-gauge2');
const histogramIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-histogram');

const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[counterIndex];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[observableIndex];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[histogramIndex];

assert.ok(typeof metric1 !== 'undefined', "metric doesn't exist");
ensureCounterIsCorrect(
metric1,
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].startTime)
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime)
);

assert.ok(
Expand All @@ -233,8 +245,8 @@ describe('OTLPMetricExporter - web', () => {
);
ensureObservableGaugeIsCorrect(
metric2,
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].startTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].startTime),
6,
'double-observable-gauge2'
);
Expand All @@ -245,8 +257,8 @@ describe('OTLPMetricExporter - web', () => {
);
ensureHistogramIsCorrect(
metric3,
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].startTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime),
hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].startTime),
[0, 100],
[0, 2, 0]
);
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
Original file line number Diff line number Diff line change
Expand Up @@ -288,29 +288,34 @@ describe('OTLPMetricExporter - node with json over http', () => {
const responseBody = buff.toString();

const json = JSON.parse(responseBody) as IExportMetricsServiceRequest;
const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2];
// The order of the metrics is not guaranteed.
const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-counter');
const observableIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'double-observable-gauge2');
const histogramIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-histogram');

const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[counterIndex];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[observableIndex];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[histogramIndex];

assert.ok(typeof metric1 !== 'undefined', "counter doesn't exist");
ensureCounterIsCorrect(
metric1,
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].endTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[0].dataPoints[0].startTime)
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime)
);
assert.ok(typeof metric2 !== 'undefined', "observable gauge doesn't exist");
ensureObservableGaugeIsCorrect(
metric2,
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].endTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[1].dataPoints[0].startTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].endTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0].startTime),
6,
'double-observable-gauge2'
);
assert.ok(typeof metric3 !== 'undefined', "histogram doesn't exist");
ensureHistogramIsCorrect(
metric3,
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].endTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[2].dataPoints[0].startTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime),
core.hrTimeToNanoseconds(metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].startTime),
[0, 100],
[0, 2, 0]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,14 @@ describe('OTLPMetricExporter - node with proto over http', () => {
const data = ExportTraceServiceRequestProto.decode(buff);
const json = data?.toJSON() as IExportMetricsServiceRequest;

const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[0];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[1];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[2];
// The order of the metrics is not guaranteed.
const counterIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-counter');
const observableIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'double-observable-gauge');
const histogramIndex = metrics.scopeMetrics[0].metrics.findIndex(it => it.descriptor.name === 'int-histogram');

const metric1 = json.resourceMetrics[0].scopeMetrics[0].metrics[counterIndex];
const metric2 = json.resourceMetrics[0].scopeMetrics[0].metrics[observableIndex];
const metric3 = json.resourceMetrics[0].scopeMetrics[0].metrics[histogramIndex];

assert.ok(typeof metric1 !== 'undefined', "counter doesn't exist");
ensureExportedCounterIsCorrect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
import { Resource } from '@opentelemetry/resources';
import * as assert from 'assert';
import {
Aggregation,
AggregationTemporality,
ExplicitBucketHistogramAggregation,
MeterProvider,
Expand All @@ -34,6 +35,10 @@ import { IExportMetricsServiceRequest, IKeyValue, IMetric } from '@opentelemetry
import { Stream } from 'stream';

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

selectAggregationTemporality() {
return AggregationTemporality.CUMULATIVE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { diag } from '@opentelemetry/api';
import {
globalErrorHandler,
} from '@opentelemetry/core';
import { AggregationTemporality, MetricReader } from '@opentelemetry/sdk-metrics';
import { Aggregation, AggregationTemporality, MetricReader } from '@opentelemetry/sdk-metrics';
import { createServer, IncomingMessage, Server, ServerResponse } from 'http';
import { ExporterConfig } from './export/types';
import { PrometheusSerializer } from './PrometheusSerializer';
Expand Down Expand Up @@ -90,6 +90,10 @@ export class PrometheusExporter extends MetricReader {
}
}

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

selectAggregationTemporality(): AggregationTemporality {
return AggregationTemporality.CUMULATIVE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
*/

import { Meter, ObservableResult } from '@opentelemetry/api-metrics';
import {
MeterProvider,
} from '@opentelemetry/sdk-metrics';
import { MeterProvider } from '@opentelemetry/sdk-metrics';
import * as assert from 'assert';
import * as sinon from 'sinon';
import * as http from 'http';
Expand Down Expand Up @@ -480,22 +478,19 @@ describe('PrometheusExporter', () => {
let meter: Meter;
let meterProvider: MeterProvider;
let counter: Counter;
let exporter: PrometheusExporter | undefined;
let exporter: PrometheusExporter;

beforeEach(() => {
function setup(reader: PrometheusExporter) {
meterProvider = new MeterProvider();
meterProvider.addMetricReader(reader);

meter = meterProvider.getMeter('test-prometheus');
counter = meter.createCounter('counter');
counter.add(10, { key1: 'attributeValue1' });
});
}

afterEach(done => {
if (exporter) {
exporter.shutdown().then(done);
exporter = undefined;
} else {
done();
}
afterEach(async () => {
await exporter.shutdown();
});

it('should use a configured name prefix', done => {
Expand All @@ -504,7 +499,7 @@ describe('PrometheusExporter', () => {
prefix: 'test_prefix',
},
async () => {
meterProvider.addMetricReader(exporter!);
setup(exporter);
http
.get('http://localhost:9464/metrics', res => {
res.on('data', chunk => {
Expand Down Expand Up @@ -532,7 +527,7 @@ describe('PrometheusExporter', () => {
port: 8080,
},
async () => {
meterProvider.addMetricReader(exporter!);
setup(exporter);
http
.get('http://localhost:8080/metrics', res => {
res.on('data', chunk => {
Expand Down Expand Up @@ -560,7 +555,7 @@ describe('PrometheusExporter', () => {
endpoint: '/test',
},
async () => {
meterProvider.addMetricReader(exporter!);
setup(exporter);
http
.get('http://localhost:9464/test', res => {
res.on('data', chunk => {
Expand Down Expand Up @@ -588,7 +583,7 @@ describe('PrometheusExporter', () => {
appendTimestamp: false,
},
async () => {
meterProvider.addMetricReader(exporter!);
setup(exporter);
http
.get('http://localhost:9464/metrics', res => {
res.on('data', chunk => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import * as assert from 'assert';
import { MetricAttributes, UpDownCounter } from '@opentelemetry/api-metrics';
import {
Aggregation,
AggregationTemporality,
DataPoint,
DataPointType,
Expand Down Expand Up @@ -46,6 +47,10 @@ class TestMetricReader extends MetricReader {
return AggregationTemporality.CUMULATIVE;
}

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

async onForceFlush() {}

async onShutdown() {}
Expand Down
Loading

0 comments on commit fabdaf4

Please sign in to comment.