Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Export MinMaxLastSumCountAggregator metrics to the collector as Summary #1320

Merged
merged 14 commits into from
Aug 4, 2020
67 changes: 51 additions & 16 deletions packages/opentelemetry-exporter-collector/src/transformMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import * as core from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
import { toCollectorResource } from './transform';
import { CollectorExporterBase } from './CollectorExporterBase';
import { HrTime } from '@opentelemetry/api';

/**
* Converts labels
Expand Down Expand Up @@ -60,14 +61,16 @@ export function toCollectorType(
if (metric.aggregator instanceof HistogramAggregator) {
return opentelemetryProto.metrics.v1.MetricDescriptorType.HISTOGRAM;
}
if (metric.aggregator instanceof MinMaxLastSumCountAggregator) {
return opentelemetryProto.metrics.v1.MetricDescriptorType.SUMMARY;
}
if (metric.descriptor.valueType == api.ValueType.INT) {
return opentelemetryProto.metrics.v1.MetricDescriptorType.INT64;
}
if (metric.descriptor.valueType === api.ValueType.DOUBLE) {
return opentelemetryProto.metrics.v1.MetricDescriptorType.DOUBLE;
}

// @TODO #1294: Add Summary once implemented
return opentelemetryProto.metrics.v1.MetricDescriptorType.INVALID_TYPE;
}

Expand Down Expand Up @@ -132,14 +135,9 @@ export function toSingularPoint(
timeUnixNano: number;
value: number;
} {
const pointValue =
metric.aggregator instanceof MinMaxLastSumCountAggregator
? (metric.aggregator.toPoint().value as Distribution).last
: (metric.aggregator.toPoint().value as number);

return {
labels: toCollectorLabels(metric.labels),
value: pointValue,
value: metric.aggregator.toPoint().value as number,
startTimeUnixNano: startTime,
timeUnixNano: core.hrTimeToNanoseconds(
metric.aggregator.toPoint().timestamp
Expand All @@ -156,19 +154,47 @@ export function toHistogramPoint(
metric: MetricRecord,
startTime: number
): opentelemetryProto.metrics.v1.HistogramDataPoint {
const histValue = metric.aggregator.toPoint().value as Histogram;
const { value, timestamp } = metric.aggregator.toPoint() as {
value: Histogram;
timestamp: HrTime;
};
return {
labels: toCollectorLabels(metric.labels),
sum: histValue.sum,
count: histValue.count,
sum: value.sum,
count: value.count,
startTimeUnixNano: startTime,
timeUnixNano: core.hrTimeToNanoseconds(
metric.aggregator.toPoint().timestamp
),
buckets: histValue.buckets.counts.map(count => {
timeUnixNano: core.hrTimeToNanoseconds(timestamp),
buckets: value.buckets.counts.map(count => {
return { count };
}),
explicitBounds: histValue.buckets.boundaries,
explicitBounds: value.buckets.boundaries,
};
}

/**
* Returns a SummaryPoint to the collector
* @param metric
* @param startTime
*/
export function toSummaryPoint(
metric: MetricRecord,
startTime: number
): opentelemetryProto.metrics.v1.SummaryDataPoint {
const { value, timestamp } = metric.aggregator.toPoint() as {
value: Distribution;
timestamp: HrTime;
};

return {
labels: toCollectorLabels(metric.labels),
sum: value.sum,
count: value.count,
startTimeUnixNano: startTime,
timeUnixNano: core.hrTimeToNanoseconds(timestamp),
percentileValues: [
{ percentile: 0, value: value.min },
{ percentile: 100, value: value.max },
],
};
}

Expand All @@ -190,6 +216,15 @@ export function toCollectorMetric(
histogramDataPoints: [toHistogramPoint(metric, startTime)],
};
}
if (
toCollectorType(metric) ===
opentelemetryProto.metrics.v1.MetricDescriptorType.SUMMARY
) {
return {
metricDescriptor: toCollectorMetricDescriptor(metric),
summaryDataPoints: [toSummaryPoint(metric, startTime)],
};
}
if (metric.descriptor.valueType == api.ValueType.INT) {
return {
metricDescriptor: toCollectorMetricDescriptor(metric),
Expand All @@ -201,7 +236,7 @@ export function toCollectorMetric(
metricDescriptor: toCollectorMetricDescriptor(metric),
doubleDataPoints: [toSingularPoint(metric, startTime)],
};
} // TODO: Add support for summary points once implemented
}

return {
metricDescriptor: toCollectorMetricDescriptor(metric),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ describe('CollectorMetricExporter - common', () => {
};
collectorExporter = new CollectorMetricExporter(collectorExporterConfig);
metrics = [];
metrics.push(Object.assign({}, mockCounter));
metrics.push(Object.assign({}, mockObserver));
metrics.push(mockCounter());
metrics.push(mockObserver());
});

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,90 @@ import * as assert from 'assert';
import * as transform from '../../src/transformMetrics';
import {
mockCounter,
mockDoubleCounter,
mockObserver,
mockedResources,
mockedInstrumentationLibraries,
multiResourceMetrics,
multiInstrumentationLibraryMetrics,
ensureCounterIsCorrect,
ensureDoubleCounterIsCorrect,
ensureObserverIsCorrect,
mockHistogram,
ensureHistogramIsCorrect,
ensureValueRecorderIsCorrect,
mockValueRecorder,
} from '../helper';
import { MetricRecord, SumAggregator } from '@opentelemetry/metrics';
import { hrTimeToNanoseconds } from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
describe('transformMetrics', () => {
describe('toCollectorMetric', () => {
const counter: MetricRecord = mockCounter();
const doubleCounter: MetricRecord = mockDoubleCounter();
const observer: MetricRecord = mockObserver();
const histogram: MetricRecord = mockHistogram();
const recorder: MetricRecord = mockValueRecorder();
const invalidMetric: MetricRecord = {
descriptor: {
name: 'name',
description: 'description',
unit: 'unit',
metricKind: 8, // Not a valid metricKind
valueType: 2, // Not double or int
},
labels: {},
aggregator: new SumAggregator(),
resource: new Resource({}),
instrumentationLibrary: { name: 'x', version: 'y' },
};
beforeEach(() => {
// Counter
mockCounter.aggregator.update(1);
counter.aggregator.update(1);

// Double Counter
doubleCounter.aggregator.update(8);

// Observer
mockObserver.aggregator.update(10);
observer.aggregator.update(3);
observer.aggregator.update(6);

// Histogram
mockHistogram.aggregator.update(7);
mockHistogram.aggregator.update(14);
histogram.aggregator.update(7);
histogram.aggregator.update(14);

// ValueRecorder
mockValueRecorder.aggregator.update(5);
});

afterEach(() => {
mockCounter.aggregator.update(-1); // Reset counter
recorder.aggregator.update(5);
});
it('should convert metric', () => {
ensureCounterIsCorrect(
transform.toCollectorMetric(mockCounter, 1592602232694000000),
hrTimeToNanoseconds(mockCounter.aggregator.toPoint().timestamp)
transform.toCollectorMetric(counter, 1592602232694000000),
hrTimeToNanoseconds(counter.aggregator.toPoint().timestamp)
);
ensureObserverIsCorrect(
transform.toCollectorMetric(mockObserver, 1592602232694000000),
hrTimeToNanoseconds(mockObserver.aggregator.toPoint().timestamp)
transform.toCollectorMetric(observer, 1592602232694000000),
hrTimeToNanoseconds(observer.aggregator.toPoint().timestamp)
);
ensureHistogramIsCorrect(
transform.toCollectorMetric(mockHistogram, 1592602232694000000),
hrTimeToNanoseconds(mockHistogram.aggregator.toPoint().timestamp)
transform.toCollectorMetric(histogram, 1592602232694000000),
hrTimeToNanoseconds(histogram.aggregator.toPoint().timestamp)
);

ensureValueRecorderIsCorrect(
transform.toCollectorMetric(mockValueRecorder, 1592602232694000000),
hrTimeToNanoseconds(mockValueRecorder.aggregator.toPoint().timestamp)
transform.toCollectorMetric(recorder, 1592602232694000000),
hrTimeToNanoseconds(recorder.aggregator.toPoint().timestamp)
);

ensureDoubleCounterIsCorrect(
transform.toCollectorMetric(doubleCounter, 1592602232694000000),
hrTimeToNanoseconds(doubleCounter.aggregator.toPoint().timestamp)
);

const emptyMetric = transform.toCollectorMetric(
invalidMetric,
1592602232694000000
);
assert.deepStrictEqual(emptyMetric.int64DataPoints, []);
});
});
describe('toCollectorMetricDescriptor', () => {
Expand Down
Loading