diff --git a/CHANGELOG.md b/CHANGELOG.md index a7e1917b11..f8a0051fab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :bug: (Bug Fix) * fix(sdk-metrics): allow instrument names to contain '/' [#4155](https://github.com/open-telemetry/opentelemetry-js/pull/4155) +* fix(sdk-metrics): do not report empty scopes and metrics [#4135](https://github.com/open-telemetry/opentelemetry-js/pull/4135) @pichlermarc + * Instruments that were created, but did not have measurements will not be exported anymore + * Meters (Scopes) that were created, but did not have any instruments with measurements under them will not be exported anymore. +* fix(exporter-zipkin): round duration to the nearest int in annotations to be compliant with zipkin protocol [#4167](https://github.com/open-telemetry/opentelemetry-js/pull/4167) @FelipeEmerim ### :books: (Refine Doc) diff --git a/api/package.json b/api/package.json index 2b677d2451..8ce9138b9c 100644 --- a/api/package.json +++ b/api/package.json @@ -61,10 +61,10 @@ "access": "public" }, "devDependencies": { - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", - "@types/webpack": "4.41.33", + "@types/sinon": "10.0.17", + "@types/webpack": "4.41.34", "@types/webpack-env": "1.16.3", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index bc0fb011da..72f0289574 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -56,6 +56,7 @@ All notable changes to experimental packages in this project will be documented ### :bug: (Bug Fix) +* fix(otlp-transformer): Avoid precision loss when converting from HrTime to unix nanoseconds. [#4062](https://github.com/open-telemetry/opentelemetry-js/pull/4062) * fix(exporter-logs-otlp-http): add @opentelemetry/api-logs as dependency ## 0.41.2 diff --git a/experimental/packages/api-events/package.json b/experimental/packages/api-events/package.json index c93878d909..f430f3d31b 100644 --- a/experimental/packages/api-events/package.json +++ b/experimental/packages/api-events/package.json @@ -64,7 +64,7 @@ "@opentelemetry/api": "^1.0.0" }, "devDependencies": { - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", "@types/webpack-env": "1.16.3", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/api-logs/package.json b/experimental/packages/api-logs/package.json index 18806178ce..4dc86c99f2 100644 --- a/experimental/packages/api-logs/package.json +++ b/experimental/packages/api-logs/package.json @@ -64,7 +64,7 @@ "@opentelemetry/api": "^1.0.0" }, "devDependencies": { - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", "@types/webpack-env": "1.16.3", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/exporter-logs-otlp-grpc/package.json b/experimental/packages/exporter-logs-otlp-grpc/package.json index 82146ce439..eb79af2875 100644 --- a/experimental/packages/exporter-logs-otlp-grpc/package.json +++ b/experimental/packages/exporter-logs-otlp-grpc/package.json @@ -54,9 +54,9 @@ "@opentelemetry/api-logs": "0.43.0", "@opentelemetry/otlp-exporter-base": "0.43.0", "@opentelemetry/resources": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cpx": "1.5.0", "cross-var": "1.1.0", diff --git a/experimental/packages/exporter-logs-otlp-grpc/test/logsHelper.ts b/experimental/packages/exporter-logs-otlp-grpc/test/logsHelper.ts index 1dfd82675a..633d1a7833 100644 --- a/experimental/packages/exporter-logs-otlp-grpc/test/logsHelper.ts +++ b/experimental/packages/exporter-logs-otlp-grpc/test/logsHelper.ts @@ -88,7 +88,7 @@ export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) { ensureExportedAttributesAreCorrect(logRecord.attributes); assert.strictEqual( logRecord.timeUnixNano, - '1680253513123241728', + '1680253513123241635', 'timeUnixNano is wrong' ); assert.strictEqual( diff --git a/experimental/packages/exporter-logs-otlp-http/package.json b/experimental/packages/exporter-logs-otlp-http/package.json index 05b217da2d..e662e7c4b2 100644 --- a/experimental/packages/exporter-logs-otlp-http/package.json +++ b/experimental/packages/exporter-logs-otlp-http/package.json @@ -74,9 +74,9 @@ "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", "@opentelemetry/resources": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/exporter-logs-otlp-http/test/logHelper.ts b/experimental/packages/exporter-logs-otlp-http/test/logHelper.ts index 1d9461f873..b5832f7cd4 100644 --- a/experimental/packages/exporter-logs-otlp-http/test/logHelper.ts +++ b/experimental/packages/exporter-logs-otlp-http/test/logHelper.ts @@ -20,6 +20,7 @@ import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; import { VERSION } from '@opentelemetry/core'; import { + hrTimeToFixed64Nanos, IAnyValue, IExportLogsServiceRequest, IKeyValue, @@ -76,17 +77,22 @@ export function ensureExportedBodyIsCorrect(body?: IAnyValue) { ); } +function hrTimeToFixed64(hrTime: HrTime) { + const { low, high } = hrTimeToFixed64Nanos(hrTime); + return { low, high }; +} + export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) { ensureExportedBodyIsCorrect(logRecord.body); ensureExportedAttributesAreCorrect(logRecord.attributes); - assert.strictEqual( + assert.deepStrictEqual( logRecord.timeUnixNano, - 1680253513123241700, + hrTimeToFixed64(mockedReadableLogRecord.hrTime), 'timeUnixNano is wrong' ); - assert.strictEqual( + assert.deepStrictEqual( logRecord.observedTimeUnixNano, - 1680253513123241700, + hrTimeToFixed64(mockedReadableLogRecord.hrTimeObserved), 'observedTimeUnixNano is wrong' ); assert.strictEqual( diff --git a/experimental/packages/exporter-logs-otlp-proto/package.json b/experimental/packages/exporter-logs-otlp-proto/package.json index 4aa74b7eb2..5c673851f0 100644 --- a/experimental/packages/exporter-logs-otlp-proto/package.json +++ b/experimental/packages/exporter-logs-otlp-proto/package.json @@ -65,9 +65,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", "cpx": "1.5.0", diff --git a/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts b/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts index 54a752af1e..ae72deae33 100644 --- a/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts +++ b/experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts @@ -82,12 +82,12 @@ export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) { ensureExportedAttributesAreCorrect(logRecord.attributes); assert.strictEqual( logRecord.timeUnixNano, - '1680253513123241728', + '1680253513123241635', 'timeUnixNano is wrong' ); assert.strictEqual( logRecord.observedTimeUnixNano, - '1680253513123241728', + '1680253513123241635', 'observedTimeUnixNano is wrong' ); assert.strictEqual( diff --git a/experimental/packages/exporter-trace-otlp-grpc/package.json b/experimental/packages/exporter-trace-otlp-grpc/package.json index 80c2ea3a0c..4fb4e0ae15 100644 --- a/experimental/packages/exporter-trace-otlp-grpc/package.json +++ b/experimental/packages/exporter-trace-otlp-grpc/package.json @@ -51,9 +51,9 @@ "@grpc/proto-loader": "^0.7.3", "@opentelemetry/api": "1.6.0", "@opentelemetry/otlp-exporter-base": "0.43.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cpx": "1.5.0", "cross-var": "1.1.0", diff --git a/experimental/packages/exporter-trace-otlp-grpc/test/traceHelper.ts b/experimental/packages/exporter-trace-otlp-grpc/test/traceHelper.ts index 6ce80bf2c2..62157741a8 100644 --- a/experimental/packages/exporter-trace-otlp-grpc/test/traceHelper.ts +++ b/experimental/packages/exporter-trace-otlp-grpc/test/traceHelper.ts @@ -114,49 +114,49 @@ export function ensureExportedEventsAreCorrect(events: IEvent[]) { [ { attributes: [], - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'fetchStart', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'domainLookupStart', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'domainLookupEnd', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'connectStart', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'connectEnd', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165435513088', + timeUnixNano: '1574120165435513070', name: 'requestStart', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165436923136', + timeUnixNano: '1574120165436923070', name: 'responseStart', droppedAttributesCount: 0, }, { attributes: [], - timeUnixNano: '1574120165438688000', + timeUnixNano: '1574120165438688070', name: 'responseEnd', droppedAttributesCount: 0, }, @@ -235,12 +235,12 @@ export function ensureExportedSpanIsCorrect(span: ISpan) { assert.strictEqual(span.kind, 'SPAN_KIND_INTERNAL', 'kind is wrong'); assert.strictEqual( span.startTimeUnixNano, - '1574120165429803008', + '1574120165429803070', 'startTimeUnixNano is wrong' ); assert.strictEqual( span.endTimeUnixNano, - '1574120165438688000', + '1574120165438688070', 'endTimeUnixNano is wrong' ); assert.strictEqual( diff --git a/experimental/packages/exporter-trace-otlp-http/package.json b/experimental/packages/exporter-trace-otlp-http/package.json index cfc2522a53..2a88326e10 100644 --- a/experimental/packages/exporter-trace-otlp-http/package.json +++ b/experimental/packages/exporter-trace-otlp-http/package.json @@ -65,9 +65,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts index 9238260d30..3de60027dc 100644 --- a/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts +++ b/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts @@ -316,7 +316,6 @@ describe('OTLPTraceExporter - node with json over http', () => { fakeRequest.on('end', () => { const responseBody = buff.toString(); - const json = JSON.parse(responseBody) as IExportTraceServiceRequest; const span1 = json.resourceSpans?.[0].scopeSpans?.[0].spans?.[0]; assert.ok(typeof span1 !== 'undefined', "span doesn't exist"); diff --git a/experimental/packages/exporter-trace-otlp-http/test/traceHelper.ts b/experimental/packages/exporter-trace-otlp-http/test/traceHelper.ts index 06e256d253..6726b49017 100644 --- a/experimental/packages/exporter-trace-otlp-http/test/traceHelper.ts +++ b/experimental/packages/exporter-trace-otlp-http/test/traceHelper.ts @@ -31,6 +31,7 @@ import { ILink, IResource, ISpan, + UnsignedLong, } from '@opentelemetry/otlp-transformer'; if (typeof Buffer === 'undefined') { @@ -243,54 +244,59 @@ export const multiInstrumentationLibraryTrace: ReadableSpan[] = [ }, ]; +function fixed64FromString(str: string) { + const { low, high } = UnsignedLong.fromString(str); + return { low, high }; +} + export function ensureEventsAreCorrect(events: IEvent[]) { assert.deepStrictEqual( events, [ { - timeUnixNano: 1574120165429803000, + timeUnixNano: fixed64FromString('1574120165429803070'), name: 'fetchStart', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165429803000, + timeUnixNano: fixed64FromString('1574120165429803070'), name: 'domainLookupStart', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165429803000, + timeUnixNano: fixed64FromString('1574120165429803070'), name: 'domainLookupEnd', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165429803000, + timeUnixNano: fixed64FromString('1574120165429803070'), name: 'connectStart', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165429803000, + timeUnixNano: fixed64FromString('1574120165429803070'), name: 'connectEnd', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165435513000, + timeUnixNano: fixed64FromString('1574120165435513070'), name: 'requestStart', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165436923100, + timeUnixNano: fixed64FromString('1574120165436923070'), name: 'responseStart', attributes: [], droppedAttributesCount: 0, }, { - timeUnixNano: 1574120165438688000, + timeUnixNano: fixed64FromString('1574120165438688070'), name: 'responseEnd', attributes: [], droppedAttributesCount: 0, @@ -364,14 +370,14 @@ export function ensureSpanIsCorrect(span: ISpan, useHex = true) { ); assert.strictEqual(span.name, 'documentFetch', 'name is wrong'); assert.strictEqual(span.kind, ESpanKind.SPAN_KIND_INTERNAL, 'kind is wrong'); - assert.strictEqual( + assert.deepStrictEqual( span.startTimeUnixNano, - 1574120165429803008, + fixed64FromString('1574120165429803070'), 'startTimeUnixNano is wrong' ); - assert.strictEqual( + assert.deepStrictEqual( span.endTimeUnixNano, - 1574120165438688000, + fixed64FromString('1574120165438688070'), 'endTimeUnixNano is wrong' ); assert.strictEqual( diff --git a/experimental/packages/exporter-trace-otlp-proto/package.json b/experimental/packages/exporter-trace-otlp-proto/package.json index 935b79963f..2dc9e6d6b6 100644 --- a/experimental/packages/exporter-trace-otlp-proto/package.json +++ b/experimental/packages/exporter-trace-otlp-proto/package.json @@ -64,9 +64,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", "cpx": "1.5.0", diff --git a/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts b/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts index ff6a9c7b85..3a21d9b79d 100644 --- a/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts +++ b/experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts @@ -109,42 +109,42 @@ export function ensureProtoEventsAreCorrect(events: IEvent[]) { events, [ { - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'fetchStart', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'domainLookupStart', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'domainLookupEnd', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'connectStart', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165429803008', + timeUnixNano: '1574120165429803070', name: 'connectEnd', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165435513088', + timeUnixNano: '1574120165435513070', name: 'requestStart', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165436923136', + timeUnixNano: '1574120165436923070', name: 'responseStart', droppedAttributesCount: 0, }, { - timeUnixNano: '1574120165438688000', + timeUnixNano: '1574120165438688070', name: 'responseEnd', droppedAttributesCount: 0, }, @@ -219,12 +219,12 @@ export function ensureProtoSpanIsCorrect(span: ISpan) { assert.strictEqual(span.kind, 'SPAN_KIND_INTERNAL', 'kind is wrong'); assert.strictEqual( span.startTimeUnixNano, - '1574120165429803008', + '1574120165429803070', 'startTimeUnixNano is wrong' ); assert.strictEqual( span.endTimeUnixNano, - '1574120165438688000', + '1574120165438688070', 'endTimeUnixNano is wrong' ); assert.strictEqual( diff --git a/experimental/packages/opentelemetry-browser-detector/package.json b/experimental/packages/opentelemetry-browser-detector/package.json index d983979a06..32f4d8be83 100644 --- a/experimental/packages/opentelemetry-browser-detector/package.json +++ b/experimental/packages/opentelemetry-browser-detector/package.json @@ -55,9 +55,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json index 3c316d301f..1a6550dc6a 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/package.json @@ -50,9 +50,9 @@ "@babel/core": "7.22.20", "@grpc/proto-loader": "^0.7.3", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cpx": "1.5.0", "cross-var": "1.1.0", diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts index a85d2f342e..1df8e0cc12 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts @@ -253,18 +253,23 @@ const testOTLPMetricExporter = (params: TestParams) => { exportedData[0].scopeMetrics[0].metrics[histogramIndex]; ensureExportedCounterIsCorrect( counter, - counter.sum?.dataPoints[0].timeUnixNano, - counter.sum?.dataPoints[0].startTimeUnixNano + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] + .startTime ); ensureExportedObservableGaugeIsCorrect( observableGauge, - observableGauge.gauge?.dataPoints[0].timeUnixNano, - observableGauge.gauge?.dataPoints[0].startTimeUnixNano + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .startTime ); ensureExportedHistogramIsCorrect( histogram, - histogram.histogram?.dataPoints[0].timeUnixNano, - histogram.histogram?.dataPoints[0].startTimeUnixNano, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .startTime, [0, 100], ['0', '2', '0'] ); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts index 4713e7aa3f..e6332ff36f 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/metricsHelper.ts @@ -17,6 +17,7 @@ import { Counter, Histogram, + HrTime, ObservableGauge, ObservableResult, ValueType, @@ -31,7 +32,13 @@ import { MetricReader, View, } from '@opentelemetry/sdk-metrics'; -import { IKeyValue, IMetric, IResource } from '@opentelemetry/otlp-transformer'; +import { + hrTimeToFixed64Nanos, + IKeyValue, + IMetric, + IResource, + UnsignedLong, +} from '@opentelemetry/otlp-transformer'; class TestMetricReader extends MetricReader { protected onForceFlush(): Promise { @@ -125,92 +132,99 @@ export function ensureExportedAttributesAreCorrect(attributes: IKeyValue[]) { export function ensureExportedCounterIsCorrect( metric: IMetric, - time?: number, - startTime?: number + time: HrTime, + startTime: HrTime ) { - assert.deepStrictEqual(metric, { - name: 'int-counter', - description: 'sample counter description', - unit: '', - data: 'sum', - sum: { - dataPoints: [ - { - attributes: [], - exemplars: [], - value: 'asInt', - asInt: '1', - flags: 0, - startTimeUnixNano: String(startTime), - timeUnixNano: String(time), - }, - ], - isMonotonic: true, - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); + assert.strictEqual(metric.name, 'int-counter'); + assert.strictEqual(metric.description, 'sample counter description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.sum?.dataPoints.length, 1); + assert.strictEqual( + metric.sum?.aggregationTemporality, + 'AGGREGATION_TEMPORALITY_CUMULATIVE' + ); + assert.strictEqual(metric.sum?.isMonotonic, true); + + const [dp] = metric.sum.dataPoints; + + assert.deepStrictEqual(dp.attributes, []); + assert.deepStrictEqual(dp.exemplars, []); + assert.strictEqual(dp.asInt, '1'); + assert.strictEqual(dp.flags, 0); + + assert.deepStrictEqual( + UnsignedLong.fromString(dp.startTimeUnixNano as string), + hrTimeToFixed64Nanos(startTime) + ); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.timeUnixNano as string), + hrTimeToFixed64Nanos(time) + ); } export function ensureExportedObservableGaugeIsCorrect( metric: IMetric, - time?: number, - startTime?: number + time: HrTime, + startTime: HrTime ) { - assert.deepStrictEqual(metric, { - name: 'double-observable-gauge', - description: 'sample observable gauge description', - unit: '', - data: 'gauge', - gauge: { - dataPoints: [ - { - attributes: [], - exemplars: [], - value: 'asDouble', - asDouble: 6, - flags: 0, - startTimeUnixNano: String(startTime), - timeUnixNano: String(time), - }, - ], - }, - }); + assert.strictEqual(metric.name, 'double-observable-gauge'); + assert.strictEqual(metric.description, 'sample observable gauge description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.gauge?.dataPoints.length, 1); + + const [dp] = metric.gauge.dataPoints; + + assert.deepStrictEqual(dp.attributes, []); + assert.deepStrictEqual(dp.exemplars, []); + assert.strictEqual(dp.asDouble, 6); + assert.strictEqual(dp.flags, 0); + + assert.deepStrictEqual( + UnsignedLong.fromString(dp.startTimeUnixNano as string), + hrTimeToFixed64Nanos(startTime) + ); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.timeUnixNano as string), + hrTimeToFixed64Nanos(time) + ); } export function ensureExportedHistogramIsCorrect( metric: IMetric, - time?: number, - startTime?: number, + time: HrTime, + startTime: HrTime, explicitBounds: number[] = [Infinity], bucketCounts: string[] = ['2', '0'] ) { - assert.deepStrictEqual(metric, { - name: 'int-histogram', - description: 'sample histogram description', - unit: '', - data: 'histogram', - histogram: { - dataPoints: [ - { - attributes: [], - exemplars: [], - flags: 0, - _sum: 'sum', - _min: 'min', - _max: 'max', - sum: 21, - count: '2', - min: 7, - max: 14, - startTimeUnixNano: String(startTime), - timeUnixNano: String(time), - bucketCounts, - explicitBounds, - }, - ], - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); + assert.strictEqual(metric.name, 'int-histogram'); + assert.strictEqual(metric.description, 'sample histogram description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.histogram?.dataPoints.length, 1); + assert.strictEqual( + metric.histogram?.aggregationTemporality, + 'AGGREGATION_TEMPORALITY_CUMULATIVE' + ); + + const [dp] = metric.histogram.dataPoints; + + assert.deepStrictEqual(dp.attributes, []); + assert.deepStrictEqual(dp.exemplars, []); + assert.strictEqual(dp.flags, 0); + assert.strictEqual(dp.sum, 21); + assert.strictEqual(dp.count, '2'); + assert.strictEqual(dp.min, 7); + assert.strictEqual(dp.max, 14); + + assert.deepStrictEqual( + UnsignedLong.fromString(dp.startTimeUnixNano as string), + hrTimeToFixed64Nanos(startTime) + ); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.timeUnixNano as string), + hrTimeToFixed64Nanos(time) + ); + assert.deepStrictEqual(dp.bucketCounts, bucketCounts); + assert.deepStrictEqual(dp.explicitBounds, explicitBounds); } export function ensureResourceIsCorrect(resource: IResource) { diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json index 8db6655f59..77673dca59 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/package.json @@ -65,9 +65,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts index 053376b032..cc112a9b55 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts @@ -21,7 +21,7 @@ import { Counter, Histogram, } from '@opentelemetry/api'; -import { ExportResultCode, hrTimeToNanoseconds } from '@opentelemetry/core'; +import { ExportResultCode } from '@opentelemetry/core'; import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import * as assert from 'assert'; import * as sinon from 'sinon'; @@ -138,14 +138,9 @@ describe('OTLPMetricExporter - web', () => { ensureCounterIsCorrect( metric1, - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] - .endTime - ), - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] - .startTime - ) + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] + .startTime ); assert.ok( @@ -154,14 +149,10 @@ describe('OTLPMetricExporter - web', () => { ); ensureObservableGaugeIsCorrect( metric2, - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] - .endTime - ), - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] - .startTime - ), + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .startTime, 6, 'double-observable-gauge2' ); @@ -172,14 +163,10 @@ describe('OTLPMetricExporter - web', () => { ); ensureHistogramIsCorrect( metric3, - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] - .endTime - ), - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] - .startTime - ), + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .startTime, [0, 100], [0, 2, 0] ); @@ -273,14 +260,9 @@ describe('OTLPMetricExporter - web', () => { assert.ok(typeof metric1 !== 'undefined', "metric doesn't exist"); ensureCounterIsCorrect( metric1, - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] - .endTime - ), - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] - .startTime - ) + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] + .startTime ); assert.ok( @@ -289,14 +271,10 @@ describe('OTLPMetricExporter - web', () => { ); ensureObservableGaugeIsCorrect( metric2, - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] - .endTime - ), - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] - .startTime - ), + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .startTime, 6, 'double-observable-gauge2' ); @@ -307,14 +285,10 @@ describe('OTLPMetricExporter - web', () => { ); ensureHistogramIsCorrect( metric3, - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] - .endTime - ), - hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] - .startTime - ), + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .startTime, [0, 100], [0, 2, 0] ); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts index 6796c155f0..9bbeee652f 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/metricsHelper.ts @@ -22,6 +22,7 @@ import { ObservableCounter, ObservableGauge, ObservableUpDownCounter, + HrTime, } from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; @@ -33,6 +34,7 @@ import { View, } from '@opentelemetry/sdk-metrics'; import { + hrTimeToFixed64Nanos, IExportMetricsServiceRequest, IKeyValue, IMetric, @@ -205,28 +207,29 @@ export function ensureWebResourceIsCorrect(resource: IResource) { assert.strictEqual(resource.droppedAttributesCount, 0); } +function hrTimeToFixed64(hrTime: HrTime) { + const { low, high } = hrTimeToFixed64Nanos(hrTime); + return { low, high }; +} + export function ensureCounterIsCorrect( metric: IMetric, - time?: number, - startTime?: number + time: HrTime, + startTime: HrTime ) { - assert.deepStrictEqual(metric, { - name: 'int-counter', - description: 'sample counter description', - unit: '', - sum: { - dataPoints: [ - { - attributes: [], - asInt: 1, - startTimeUnixNano: startTime, - timeUnixNano: time, - }, - ], - isMonotonic: true, - aggregationTemporality: 2, - }, - }); + assert.strictEqual(metric.name, 'int-counter'); + assert.strictEqual(metric.description, 'sample counter description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.sum?.dataPoints.length, 1); + assert.strictEqual(metric.sum?.isMonotonic, true); + assert.strictEqual(metric.sum?.aggregationTemporality, 2); + + const [dp] = metric.sum.dataPoints; + + assert.deepStrictEqual(dp.attributes, []); + assert.strictEqual(dp.asInt, 1); + assert.deepStrictEqual(dp.startTimeUnixNano, hrTimeToFixed64(startTime)); + assert.deepStrictEqual(dp.timeUnixNano, hrTimeToFixed64(time)); } export function ensureDoubleCounterIsCorrect( @@ -255,108 +258,50 @@ export function ensureDoubleCounterIsCorrect( export function ensureObservableGaugeIsCorrect( metric: IMetric, - time: number, - startTime: number, + time: HrTime, + startTime: HrTime, value: number, name = 'double-observable-gauge' ) { - assert.deepStrictEqual(metric, { - name, - description: 'sample observable gauge description', - unit: '', - gauge: { - dataPoints: [ - { - attributes: [], - asDouble: value, - startTimeUnixNano: startTime, - timeUnixNano: time, - }, - ], - }, - }); -} + assert.strictEqual(metric.name, name); + assert.strictEqual(metric.description, 'sample observable gauge description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.gauge?.dataPoints.length, 1); -export function ensureObservableCounterIsCorrect( - metric: IMetric, - time: number, - startTime: number, - value: number, - name = 'double-observable-counter' -) { - assert.deepStrictEqual(metric, { - name, - description: 'sample observable counter description', - unit: '', - doubleSum: { - isMonotonic: true, - dataPoints: [ - { - attributes: [], - value, - startTimeUnixNano: startTime, - timeUnixNano: time, - }, - ], - aggregationTemporality: 2, - }, - }); -} + const [dp] = metric.gauge.dataPoints; -export function ensureObservableUpDownCounterIsCorrect( - metric: IMetric, - time: number, - startTime: number, - value: number, - name = 'double-up-down-observable-counter' -) { - assert.deepStrictEqual(metric, { - name, - description: 'sample observable up down counter description', - unit: '', - doubleSum: { - isMonotonic: false, - dataPoints: [ - { - labels: [], - value, - startTimeUnixNano: startTime, - timeUnixNano: time, - }, - ], - aggregationTemporality: 2, - }, - }); + assert.deepStrictEqual(dp.attributes, []); + assert.strictEqual(dp.asDouble, value); + + assert.deepStrictEqual(dp.startTimeUnixNano, hrTimeToFixed64(startTime)); + assert.deepStrictEqual(dp.timeUnixNano, hrTimeToFixed64(time)); } export function ensureHistogramIsCorrect( metric: IMetric, - time: number, - startTime: number, + time: HrTime, + startTime: HrTime, explicitBounds: (number | null)[] = [Infinity], bucketCounts: number[] = [2, 0] ) { - assert.deepStrictEqual(metric, { - name: 'int-histogram', - description: 'sample histogram description', - unit: '', - histogram: { - dataPoints: [ - { - attributes: [], - sum: 21, - count: 2, - min: 7, - max: 14, - startTimeUnixNano: startTime, - timeUnixNano: time, - bucketCounts, - explicitBounds, - }, - ], - aggregationTemporality: 2, - }, - }); + assert.strictEqual(metric.name, 'int-histogram'); + assert.strictEqual(metric.description, 'sample histogram description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.histogram?.dataPoints.length, 1); + assert.strictEqual(metric.histogram?.aggregationTemporality, 2); + + const [dp] = metric.histogram.dataPoints; + + assert.deepStrictEqual(dp.attributes, []); + assert.strictEqual(dp.sum, 21); + assert.strictEqual(dp.count, 2); + assert.strictEqual(dp.min, 7); + assert.strictEqual(dp.max, 14); + assert.deepStrictEqual(dp.bucketCounts, bucketCounts); + assert.deepStrictEqual(dp.explicitBounds, explicitBounds); + + assert.deepStrictEqual(dp.startTimeUnixNano, hrTimeToFixed64(startTime)); + assert.deepStrictEqual(dp.timeUnixNano, hrTimeToFixed64(time)); } export function ensureExportMetricsServiceRequestIsSet( diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts index 0844e5a9f2..2f809e6251 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts @@ -491,13 +491,8 @@ describe('OTLPMetricExporter - node with json over http', () => { assert.ok(typeof metric1 !== 'undefined', "counter doesn't exist"); ensureCounterIsCorrect( metric1, - core.hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime - ), - core.hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0] - .startTime - ) + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime ); assert.ok( typeof metric2 !== 'undefined', @@ -505,28 +500,19 @@ describe('OTLPMetricExporter - node with json over http', () => { ); ensureObservableGaugeIsCorrect( metric2, - core.hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] - .endTime - ), - core.hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] - .startTime - ), + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .endTime, + 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[histogramIndex].dataPoints[0] - .endTime - ), - core.hrTimeToNanoseconds( - metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] - .startTime - ), + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .startTime, [0, 100], [0, 2, 0] ); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json index 52ce8df0a2..12defa7e8c 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/package.json @@ -57,9 +57,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cpx": "1.5.0", "cross-var": "1.1.0", diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts index 4d4856481d..80902daeaa 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts @@ -45,7 +45,6 @@ import { } from '@opentelemetry/exporter-metrics-otlp-http'; import { Stream, PassThrough } from 'stream'; import { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'; -import { IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer'; import { VERSION } from '../src/version'; let fakeRequest: PassThrough; @@ -260,7 +259,7 @@ describe('OTLPMetricExporter - node with proto over http', () => { ServiceClientType.METRICS ); const data = ExportTraceServiceRequestProto.decode(buff); - const json = data?.toJSON() as IExportMetricsServiceRequest; + const json = data?.toJSON() as any; // The order of the metrics is not guaranteed. const counterIndex = metrics.scopeMetrics[0].metrics.findIndex( @@ -283,8 +282,8 @@ describe('OTLPMetricExporter - node with proto over http', () => { assert.ok(typeof metric1 !== 'undefined', "counter doesn't exist"); ensureExportedCounterIsCorrect( metric1, - metric1.sum?.dataPoints[0].timeUnixNano, - metric1.sum?.dataPoints[0].startTimeUnixNano + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].startTime ); assert.ok( typeof metric2 !== 'undefined', @@ -292,8 +291,10 @@ describe('OTLPMetricExporter - node with proto over http', () => { ); ensureExportedObservableGaugeIsCorrect( metric2, - metric2.gauge?.dataPoints[0].timeUnixNano, - metric2.gauge?.dataPoints[0].startTimeUnixNano + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .endTime, + metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0] + .startTime ); assert.ok( typeof metric3 !== 'undefined', @@ -301,8 +302,9 @@ describe('OTLPMetricExporter - node with proto over http', () => { ); ensureExportedHistogramIsCorrect( metric3, - metric3.histogram?.dataPoints[0].timeUnixNano, - metric3.histogram?.dataPoints[0].startTimeUnixNano, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0].endTime, + metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0] + .startTime, [0, 100], ['0', '2', '0'] ); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts index 27b816fe10..6a47a9a8f6 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/metricsHelper.ts @@ -20,6 +20,7 @@ import { Histogram, ValueType, ObservableGauge, + HrTime, } from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; @@ -30,9 +31,11 @@ import { View, } from '@opentelemetry/sdk-metrics'; import { + hrTimeToFixed64Nanos, IExportMetricsServiceRequest, IKeyValue, IMetric, + UnsignedLong, } from '@opentelemetry/otlp-transformer'; import { Stream } from 'stream'; @@ -129,75 +132,86 @@ export function ensureProtoAttributesAreCorrect(attributes: IKeyValue[]) { export function ensureExportedCounterIsCorrect( metric: IMetric, - time?: number, - startTime?: number + time: HrTime, + startTime: HrTime ) { - assert.deepStrictEqual(metric, { - name: 'int-counter', - description: 'sample counter description', - unit: '', - sum: { - dataPoints: [ - { - asInt: '1', - startTimeUnixNano: String(startTime), - timeUnixNano: String(time), - }, - ], - isMonotonic: true, - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); + assert.strictEqual(metric.name, 'int-counter'); + assert.strictEqual(metric.description, 'sample counter description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.sum?.dataPoints.length, 1); + assert.strictEqual(metric.sum?.isMonotonic, true); + assert.strictEqual( + metric.sum?.aggregationTemporality, + 'AGGREGATION_TEMPORALITY_CUMULATIVE' + ); + + const [dp] = metric.sum.dataPoints; + assert.strictEqual(dp.asInt, '1'); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.startTimeUnixNano as string), + hrTimeToFixed64Nanos(startTime) + ); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.timeUnixNano as string), + hrTimeToFixed64Nanos(time) + ); } export function ensureExportedObservableGaugeIsCorrect( metric: IMetric, - time?: number, - startTime?: number + time: HrTime, + startTime: HrTime ) { - assert.deepStrictEqual(metric, { - name: 'double-observable-gauge', - description: 'sample observable gauge description', - unit: '', - gauge: { - dataPoints: [ - { - asDouble: 6, - startTimeUnixNano: String(startTime), - timeUnixNano: String(time), - }, - ], - }, - }); + assert.strictEqual(metric.name, 'double-observable-gauge'); + assert.strictEqual(metric.description, 'sample observable gauge description'); + assert.strictEqual(metric.unit, ''); + assert.strictEqual(metric.gauge?.dataPoints.length, 1); + + const [dp] = metric.gauge.dataPoints; + assert.strictEqual(dp.asDouble, 6); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.startTimeUnixNano as string), + hrTimeToFixed64Nanos(startTime) + ); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.timeUnixNano as string), + hrTimeToFixed64Nanos(time) + ); } export function ensureExportedHistogramIsCorrect( metric: IMetric, - time?: number, - startTime?: number, + time: HrTime, + startTime: HrTime, explicitBounds: number[] = [Infinity], bucketCounts: string[] = ['2', '0'] ) { - assert.deepStrictEqual(metric, { - name: 'int-histogram', - description: 'sample histogram description', - unit: '', - histogram: { - dataPoints: [ - { - sum: 21, - count: '2', - min: 7, - max: 14, - startTimeUnixNano: String(startTime), - timeUnixNano: String(time), - bucketCounts, - explicitBounds, - }, - ], - aggregationTemporality: 'AGGREGATION_TEMPORALITY_CUMULATIVE', - }, - }); + assert.strictEqual(metric.name, 'int-histogram'); + assert.strictEqual(metric.description, 'sample histogram description'); + assert.strictEqual(metric.unit, ''); + + assert.strictEqual(metric.histogram?.dataPoints.length, 1); + assert.strictEqual( + metric.histogram.aggregationTemporality, + 'AGGREGATION_TEMPORALITY_CUMULATIVE' + ); + + const [dp] = metric.histogram.dataPoints; + + assert.strictEqual(dp.sum, 21); + assert.strictEqual(dp.count, '2'); + assert.strictEqual(dp.min, 7); + assert.strictEqual(dp.max, 14); + assert.deepStrictEqual(dp.explicitBounds, explicitBounds); + assert.deepStrictEqual(dp.bucketCounts, bucketCounts); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.startTimeUnixNano as string), + hrTimeToFixed64Nanos(startTime) + ); + assert.deepStrictEqual( + UnsignedLong.fromString(dp.timeUnixNano as string), + hrTimeToFixed64Nanos(time) + ); } export function ensureExportMetricsServiceRequestIsSet( diff --git a/experimental/packages/opentelemetry-exporter-prometheus/package.json b/experimental/packages/opentelemetry-exporter-prometheus/package.json index 5b55ececd8..f445d8bd12 100644 --- a/experimental/packages/opentelemetry-exporter-prometheus/package.json +++ b/experimental/packages/opentelemetry-exporter-prometheus/package.json @@ -45,9 +45,9 @@ "devDependencies": { "@opentelemetry/api": "1.6.0", "@opentelemetry/semantic-conventions": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/experimental/packages/opentelemetry-instrumentation-fetch/package.json b/experimental/packages/opentelemetry-instrumentation-fetch/package.json index 948b357d5a..767b9bbe70 100644 --- a/experimental/packages/opentelemetry-instrumentation-fetch/package.json +++ b/experimental/packages/opentelemetry-instrumentation-fetch/package.json @@ -59,9 +59,9 @@ "@opentelemetry/context-zone": "1.17.0", "@opentelemetry/propagator-b3": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/package.json b/experimental/packages/opentelemetry-instrumentation-grpc/package.json index fbf07ae716..1b3e5c47de 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/package.json +++ b/experimental/packages/opentelemetry-instrumentation-grpc/package.json @@ -57,10 +57,10 @@ "@protobuf-ts/grpc-transport": "2.9.1", "@protobuf-ts/runtime": "2.9.1", "@protobuf-ts/runtime-rpc": "2.9.1", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/semver": "7.5.2", - "@types/sinon": "10.0.16", + "@types/semver": "7.5.3", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/experimental/packages/opentelemetry-instrumentation-http/package.json b/experimental/packages/opentelemetry-instrumentation-http/package.json index aebe37781d..c18ac517d3 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/package.json +++ b/experimental/packages/opentelemetry-instrumentation-http/package.json @@ -50,13 +50,13 @@ "@opentelemetry/sdk-metrics": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", "@opentelemetry/sdk-trace-node": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/request-promise-native": "1.0.18", - "@types/semver": "7.5.2", - "@types/sinon": "10.0.16", - "@types/superagent": "4.1.18", - "axios": "1.5.0", + "@types/request-promise-native": "1.0.19", + "@types/semver": "7.5.3", + "@types/sinon": "10.0.17", + "@types/superagent": "4.1.19", + "axios": "1.5.1", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json index 511f4fe3e0..93bf3c9655 100644 --- a/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json +++ b/experimental/packages/opentelemetry-instrumentation-xml-http-request/package.json @@ -59,9 +59,9 @@ "@opentelemetry/context-zone": "1.17.0", "@opentelemetry/propagator-b3": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/opentelemetry-instrumentation/package.json b/experimental/packages/opentelemetry-instrumentation/package.json index ca9e9df4e8..9f6c031bef 100644 --- a/experimental/packages/opentelemetry-instrumentation/package.json +++ b/experimental/packages/opentelemetry-instrumentation/package.json @@ -84,10 +84,10 @@ "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", "@opentelemetry/sdk-metrics": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/semver": "7.5.2", - "@types/sinon": "10.0.16", + "@types/semver": "7.5.3", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/experimental/packages/opentelemetry-sdk-node/package.json b/experimental/packages/opentelemetry-sdk-node/package.json index 8517a07617..0f94bc4380 100644 --- a/experimental/packages/opentelemetry-sdk-node/package.json +++ b/experimental/packages/opentelemetry-sdk-node/package.json @@ -67,10 +67,10 @@ "@opentelemetry/api": "1.6.0", "@opentelemetry/context-async-hooks": "1.17.0", "@opentelemetry/exporter-jaeger": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/semver": "7.5.2", - "@types/sinon": "10.0.16", + "@types/semver": "7.5.3", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/experimental/packages/otlp-exporter-base/package.json b/experimental/packages/otlp-exporter-base/package.json index 7981365842..9701b1bfc4 100644 --- a/experimental/packages/otlp-exporter-base/package.json +++ b/experimental/packages/otlp-exporter-base/package.json @@ -66,9 +66,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/experimental/packages/otlp-grpc-exporter-base/package.json b/experimental/packages/otlp-grpc-exporter-base/package.json index cfa48c56e8..dbf84414ce 100644 --- a/experimental/packages/otlp-grpc-exporter-base/package.json +++ b/experimental/packages/otlp-grpc-exporter-base/package.json @@ -53,9 +53,9 @@ "@opentelemetry/otlp-transformer": "0.43.0", "@opentelemetry/resources": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cpx": "1.5.0", "cross-var": "1.1.0", diff --git a/experimental/packages/otlp-proto-exporter-base/package.json b/experimental/packages/otlp-proto-exporter-base/package.json index d350c263f6..5dde83bfa2 100644 --- a/experimental/packages/otlp-proto-exporter-base/package.json +++ b/experimental/packages/otlp-proto-exporter-base/package.json @@ -61,9 +61,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/experimental/packages/otlp-transformer/package.json b/experimental/packages/otlp-transformer/package.json index 9e138a5cd2..4efa0b84d0 100644 --- a/experimental/packages/otlp-transformer/package.json +++ b/experimental/packages/otlp-transformer/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "@opentelemetry/api": "1.6.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/webpack-env": "1.16.3", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", diff --git a/experimental/packages/otlp-transformer/src/common/index.ts b/experimental/packages/otlp-transformer/src/common/index.ts new file mode 100644 index 0000000000..19587be3ae --- /dev/null +++ b/experimental/packages/otlp-transformer/src/common/index.ts @@ -0,0 +1,29 @@ +/* + * 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 type { IFixed64 } from './types'; +import { HrTime } from '@opentelemetry/api'; +import { UnsignedLong } from './unsigned_long'; + +export * from './unsigned_long'; + +const NANOSECONDS = UnsignedLong.fromU32(1_000_000_000); + +export function hrTimeToFixed64Nanos(hrTime: HrTime): IFixed64 { + return UnsignedLong.fromU32(hrTime[0]) + .multiply(NANOSECONDS) + .add(UnsignedLong.fromU32(hrTime[1])); +} diff --git a/experimental/packages/otlp-transformer/src/common/types.ts b/experimental/packages/otlp-transformer/src/common/types.ts index 159a595ba9..6236da4ce6 100644 --- a/experimental/packages/otlp-transformer/src/common/types.ts +++ b/experimental/packages/otlp-transformer/src/common/types.ts @@ -73,3 +73,8 @@ export interface IKeyValueList { /** KeyValueList values */ values: IKeyValue[]; } + +export interface IFixed64 { + low: number; + high: number; +} diff --git a/experimental/packages/otlp-transformer/src/common/unsigned_long.ts b/experimental/packages/otlp-transformer/src/common/unsigned_long.ts new file mode 100644 index 0000000000..d2802e3ba8 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/common/unsigned_long.ts @@ -0,0 +1,122 @@ +/* + * Copyright 2009 The Closure Library Authors + * Copyright 2020 Daniel Wirtz / The long.js Authors. + * 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. + */ + +// Original version by long.js: https://github.com/dcodeIO/long.js/ + +const TWO_PWR_32 = (1 << 16) * (1 << 16); + +export class UnsignedLong { + low: number; + high: number; + + constructor(low: number, high: number) { + this.low = low; + this.high = high; + } + + static fromU32(value: number): UnsignedLong { + return new UnsignedLong(value % TWO_PWR_32 | 0, 0); + } + + multiply(value: UnsignedLong): UnsignedLong { + const a48 = this.high >>> 16; + const a32 = this.high & 0xffff; + const a16 = this.low >>> 16; + const a00 = this.low & 0xffff; + + const b48 = value.high >>> 16; + const b32 = value.high & 0xffff; + const b16 = value.low >>> 16; + const b00 = value.low & 0xffff; + + let c48 = 0; + let c32 = 0; + let c16 = 0; + let c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xffff; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xffff; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xffff; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xffff; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xffff; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xffff; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xffff; + + return new UnsignedLong((c16 << 16) | c00, (c48 << 16) | c32); + } + + add(value: UnsignedLong): UnsignedLong { + const a48 = this.high >>> 16; + const a32 = this.high & 0xffff; + const a16 = this.low >>> 16; + const a00 = this.low & 0xffff; + + const b48 = value.high >>> 16; + const b32 = value.high & 0xffff; + const b16 = value.low >>> 16; + const b00 = value.low & 0xffff; + + let c48 = 0; + let c32 = 0; + let c16 = 0; + let c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xffff; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xffff; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xffff; + c48 += a48 + b48; + c48 &= 0xffff; + + return new UnsignedLong((c16 << 16) | c00, (c48 << 16) | c32); + } + + static fromString(str: string): UnsignedLong { + let result = UnsignedLong.fromU32(0); + + for (let i = 0; i < str.length; i += 8) { + const size = Math.min(8, str.length - i); + const value = parseInt(str.substring(i, i + size)); + if (size < 8) { + const power = UnsignedLong.fromU32(Math.pow(10, size)); + result = result.multiply(power).add(UnsignedLong.fromU32(value)); + } else { + result = result.multiply(UnsignedLong.fromU32(100_000_000)); + result = result.add(UnsignedLong.fromU32(value)); + } + } + + return result; + } +} diff --git a/experimental/packages/otlp-transformer/src/index.ts b/experimental/packages/otlp-transformer/src/index.ts index a8e388e33a..9c325644dc 100644 --- a/experimental/packages/otlp-transformer/src/index.ts +++ b/experimental/packages/otlp-transformer/src/index.ts @@ -15,6 +15,7 @@ */ export * from './common/types'; +export * from './common'; export * from './metrics/types'; export * from './resource/types'; export * from './trace/types'; diff --git a/experimental/packages/otlp-transformer/src/logs/index.ts b/experimental/packages/otlp-transformer/src/logs/index.ts index c499476498..bffb7966dd 100644 --- a/experimental/packages/otlp-transformer/src/logs/index.ts +++ b/experimental/packages/otlp-transformer/src/logs/index.ts @@ -22,8 +22,9 @@ import { IResourceLogs, } from './types'; import { IResource } from '@opentelemetry/resources'; +import { hrTimeToFixed64Nanos } from '../common'; import { toAnyValue, toAttributes, toKeyValue } from '../common/internal'; -import { hexToBase64, hrTimeToNanoseconds } from '@opentelemetry/core'; +import { hexToBase64 } from '@opentelemetry/core'; import { SeverityNumber } from '@opentelemetry/api-logs'; import { IKeyValue } from '../common/types'; import { LogAttributes } from '@opentelemetry/api-logs'; @@ -94,8 +95,8 @@ function logRecordsToResourceLogs( function toLogRecord(log: ReadableLogRecord, useHex?: boolean): ILogRecord { return { - timeUnixNano: hrTimeToNanoseconds(log.hrTime), - observedTimeUnixNano: hrTimeToNanoseconds(log.hrTimeObserved), + timeUnixNano: hrTimeToFixed64Nanos(log.hrTime), + observedTimeUnixNano: hrTimeToFixed64Nanos(log.hrTimeObserved), severityNumber: toSeverityNumber(log.severityNumber), severityText: log.severityText, body: toAnyValue(log.body), diff --git a/experimental/packages/otlp-transformer/src/logs/types.ts b/experimental/packages/otlp-transformer/src/logs/types.ts index 05709af6f5..7704c37083 100644 --- a/experimental/packages/otlp-transformer/src/logs/types.ts +++ b/experimental/packages/otlp-transformer/src/logs/types.ts @@ -16,6 +16,7 @@ import type { IAnyValue, + IFixed64, IInstrumentationScope, IKeyValue, } from '../common/types'; @@ -67,10 +68,10 @@ export interface IScopeLogs { /** Properties of a LogRecord. */ export interface ILogRecord { /** LogRecord timeUnixNano */ - timeUnixNano: number; + timeUnixNano: IFixed64; /** LogRecord observedTimeUnixNano */ - observedTimeUnixNano: number; + observedTimeUnixNano: IFixed64; /** LogRecord severityNumber */ severityNumber?: ESeverityNumber; diff --git a/experimental/packages/otlp-transformer/src/metrics/internal.ts b/experimental/packages/otlp-transformer/src/metrics/internal.ts index b73696b0ab..670741eb30 100644 --- a/experimental/packages/otlp-transformer/src/metrics/internal.ts +++ b/experimental/packages/otlp-transformer/src/metrics/internal.ts @@ -14,7 +14,6 @@ * limitations under the License. */ import { ValueType } from '@opentelemetry/api'; -import { hrTimeToNanoseconds } from '@opentelemetry/core'; import { AggregationTemporality, DataPoint, @@ -25,6 +24,7 @@ import { ResourceMetrics, ScopeMetrics, } from '@opentelemetry/sdk-metrics'; +import { hrTimeToFixed64Nanos } from '../common'; import { toAttributes } from '../common/internal'; import { EAggregationTemporality, @@ -112,8 +112,8 @@ function toSingularDataPoint( ) { const out: INumberDataPoint = { attributes: toAttributes(dataPoint.attributes), - startTimeUnixNano: hrTimeToNanoseconds(dataPoint.startTime), - timeUnixNano: hrTimeToNanoseconds(dataPoint.endTime), + startTimeUnixNano: hrTimeToFixed64Nanos(dataPoint.startTime), + timeUnixNano: hrTimeToFixed64Nanos(dataPoint.endTime), }; switch (valueType) { @@ -145,8 +145,8 @@ function toHistogramDataPoints(metricData: MetricData): IHistogramDataPoint[] { sum: histogram.sum, min: histogram.min, max: histogram.max, - startTimeUnixNano: hrTimeToNanoseconds(dataPoint.startTime), - timeUnixNano: hrTimeToNanoseconds(dataPoint.endTime), + startTimeUnixNano: hrTimeToFixed64Nanos(dataPoint.startTime), + timeUnixNano: hrTimeToFixed64Nanos(dataPoint.endTime), }; }); } @@ -172,8 +172,8 @@ function toExponentialHistogramDataPoints( }, scale: histogram.scale, zeroCount: histogram.zeroCount, - startTimeUnixNano: hrTimeToNanoseconds(dataPoint.startTime), - timeUnixNano: hrTimeToNanoseconds(dataPoint.endTime), + startTimeUnixNano: hrTimeToFixed64Nanos(dataPoint.startTime), + timeUnixNano: hrTimeToFixed64Nanos(dataPoint.endTime), }; }); } diff --git a/experimental/packages/otlp-transformer/src/metrics/types.ts b/experimental/packages/otlp-transformer/src/metrics/types.ts index 2728ab1aba..65a2348516 100644 --- a/experimental/packages/otlp-transformer/src/metrics/types.ts +++ b/experimental/packages/otlp-transformer/src/metrics/types.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { IInstrumentationScope, IKeyValue } from '../common/types'; +import { IFixed64, IInstrumentationScope, IKeyValue } from '../common/types'; import { IResource } from '../resource/types'; /** Properties of an ExportMetricsServiceRequest. */ @@ -134,10 +134,10 @@ export interface INumberDataPoint { attributes: IKeyValue[]; /** NumberDataPoint startTimeUnixNano */ - startTimeUnixNano?: number; + startTimeUnixNano?: IFixed64 | string; /** NumberDataPoint timeUnixNano */ - timeUnixNano?: number; + timeUnixNano?: IFixed64 | string; /** NumberDataPoint asDouble */ asDouble?: number | null; @@ -158,10 +158,10 @@ export interface IHistogramDataPoint { attributes?: IKeyValue[]; /** HistogramDataPoint startTimeUnixNano */ - startTimeUnixNano?: number; + startTimeUnixNano?: IFixed64 | string; /** HistogramDataPoint timeUnixNano */ - timeUnixNano?: number; + timeUnixNano?: IFixed64 | string; /** HistogramDataPoint count */ count?: number; @@ -194,10 +194,10 @@ export interface IExponentialHistogramDataPoint { attributes?: IKeyValue[]; /** ExponentialHistogramDataPoint startTimeUnixNano */ - startTimeUnixNano?: number; + startTimeUnixNano?: IFixed64 | string; /** ExponentialHistogramDataPoint timeUnixNano */ - timeUnixNano?: number; + timeUnixNano?: IFixed64 | string; /** ExponentialHistogramDataPoint count */ count?: number; diff --git a/experimental/packages/otlp-transformer/src/trace/internal.ts b/experimental/packages/otlp-transformer/src/trace/internal.ts index 6811a8182f..d9c17855ce 100644 --- a/experimental/packages/otlp-transformer/src/trace/internal.ts +++ b/experimental/packages/otlp-transformer/src/trace/internal.ts @@ -14,8 +14,8 @@ * limitations under the License. */ import type { Link } from '@opentelemetry/api'; -import { hrTimeToNanoseconds } from '@opentelemetry/core'; import type { ReadableSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'; +import { hrTimeToFixed64Nanos } from '../common'; import { toAttributes } from '../common/internal'; import { EStatusCode, IEvent, ILink, ISpan } from './types'; import * as core from '@opentelemetry/core'; @@ -36,8 +36,8 @@ export function sdkSpanToOtlpSpan(span: ReadableSpan, useHex?: boolean): ISpan { name: span.name, // Span kind is offset by 1 because the API does not define a value for unset kind: span.kind == null ? 0 : span.kind + 1, - startTimeUnixNano: hrTimeToNanoseconds(span.startTime), - endTimeUnixNano: hrTimeToNanoseconds(span.endTime), + startTimeUnixNano: hrTimeToFixed64Nanos(span.startTime), + endTimeUnixNano: hrTimeToFixed64Nanos(span.endTime), attributes: toAttributes(span.attributes), droppedAttributesCount: span.droppedAttributesCount, events: span.events.map(toOtlpSpanEvent), @@ -72,7 +72,7 @@ export function toOtlpSpanEvent(timedEvent: TimedEvent): IEvent { ? toAttributes(timedEvent.attributes) : [], name: timedEvent.name, - timeUnixNano: hrTimeToNanoseconds(timedEvent.time), + timeUnixNano: hrTimeToFixed64Nanos(timedEvent.time), droppedAttributesCount: timedEvent.droppedAttributesCount || 0, }; } diff --git a/experimental/packages/otlp-transformer/src/trace/types.ts b/experimental/packages/otlp-transformer/src/trace/types.ts index a6cfb82ad7..294f45652f 100644 --- a/experimental/packages/otlp-transformer/src/trace/types.ts +++ b/experimental/packages/otlp-transformer/src/trace/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { IInstrumentationScope, IKeyValue } from '../common/types'; +import { IFixed64, IInstrumentationScope, IKeyValue } from '../common/types'; import { IResource } from '../resource/types'; /** Properties of an ExportTraceServiceRequest. */ @@ -81,10 +81,10 @@ export interface ISpan { kind: ESpanKind; /** Span startTimeUnixNano */ - startTimeUnixNano: number; + startTimeUnixNano: IFixed64; /** Span endTimeUnixNano */ - endTimeUnixNano: number; + endTimeUnixNano: IFixed64; /** Span attributes */ attributes: IKeyValue[]; @@ -166,7 +166,7 @@ export const enum EStatusCode { /** Properties of an Event. */ export interface IEvent { /** Event timeUnixNano */ - timeUnixNano: number; + timeUnixNano: IFixed64; /** Event name */ name: string; diff --git a/experimental/packages/otlp-transformer/test/logs.test.ts b/experimental/packages/otlp-transformer/test/logs.test.ts index ef0a4cf9d7..0937c7d152 100644 --- a/experimental/packages/otlp-transformer/test/logs.test.ts +++ b/experimental/packages/otlp-transformer/test/logs.test.ts @@ -21,6 +21,7 @@ import { createExportLogsServiceRequest, ESeverityNumber, IExportLogsServiceRequest, + UnsignedLong, } from '../src'; import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; import { SeverityNumber } from '@opentelemetry/api-logs'; @@ -49,10 +50,8 @@ function createExpectedLogJson(useHex: boolean): IExportLogsServiceRequest { scope: { name: 'scope_name_1', version: '0.1.0' }, logRecords: [ { - // eslint-disable-next-line @typescript-eslint/no-loss-of-precision - timeUnixNano: 1680253513123241635, - // eslint-disable-next-line @typescript-eslint/no-loss-of-precision - observedTimeUnixNano: 1683526948965142784, + timeUnixNano: new UnsignedLong(-162521437, 391214506), + observedTimeUnixNano: new UnsignedLong(584929536, 391976663), severityNumber: ESeverityNumber.SEVERITY_NUMBER_ERROR, severityText: 'error', body: { stringValue: 'some_log_body' }, diff --git a/experimental/packages/otlp-transformer/test/metrics.test.ts b/experimental/packages/otlp-transformer/test/metrics.test.ts index 748ef75889..15fd7d0531 100644 --- a/experimental/packages/otlp-transformer/test/metrics.test.ts +++ b/experimental/packages/otlp-transformer/test/metrics.test.ts @@ -25,7 +25,8 @@ import { import * as assert from 'assert'; import { createExportMetricsServiceRequest } from '../src/metrics'; import { EAggregationTemporality } from '../src/metrics/types'; -import { hrTime, hrTimeToNanoseconds } from '@opentelemetry/core'; +import { hrTime } from '@opentelemetry/core'; +import { hrTimeToFixed64Nanos } from '../src/common'; const START_TIME = hrTime(); const END_TIME = hrTime(); @@ -350,8 +351,8 @@ describe('Metrics', () => { dataPoints: [ { attributes: expectedAttributes, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), asInt: 10, }, ], @@ -393,8 +394,8 @@ describe('Metrics', () => { dataPoints: [ { attributes: expectedAttributes, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), asInt: 10, }, ], @@ -437,8 +438,8 @@ describe('Metrics', () => { dataPoints: [ { attributes: expectedAttributes, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), asInt: 10, }, ], @@ -481,8 +482,8 @@ describe('Metrics', () => { dataPoints: [ { attributes: expectedAttributes, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), asInt: 10, }, ], @@ -523,8 +524,8 @@ describe('Metrics', () => { dataPoints: [ { attributes: expectedAttributes, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), asDouble: 10.5, }, ], @@ -581,8 +582,8 @@ describe('Metrics', () => { sum: 9, min: 1, max: 8, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), }, ], }, @@ -635,8 +636,8 @@ describe('Metrics', () => { sum: 9, min: undefined, max: undefined, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), }, ], }, @@ -701,8 +702,8 @@ describe('Metrics', () => { bucketCounts: [1, 0, 0, 0, 1, 0, 1, 0], }, negative: { offset: 0, bucketCounts: [0] }, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), }, ], }, @@ -763,8 +764,8 @@ describe('Metrics', () => { bucketCounts: [1, 0, 0, 0, 1, 0, 1, 0], }, negative: { offset: 0, bucketCounts: [0] }, - startTimeUnixNano: hrTimeToNanoseconds(START_TIME), - timeUnixNano: hrTimeToNanoseconds(END_TIME), + startTimeUnixNano: hrTimeToFixed64Nanos(START_TIME), + timeUnixNano: hrTimeToFixed64Nanos(END_TIME), }, ], }, diff --git a/experimental/packages/otlp-transformer/test/trace.test.ts b/experimental/packages/otlp-transformer/test/trace.test.ts index 9fb0e3cbfb..380c9065c2 100644 --- a/experimental/packages/otlp-transformer/test/trace.test.ts +++ b/experimental/packages/otlp-transformer/test/trace.test.ts @@ -22,6 +22,7 @@ import { createExportTraceServiceRequest, ESpanKind, EStatusCode, + UnsignedLong, } from '../src'; function createExpectedSpanJson(useHex: boolean) { @@ -79,10 +80,8 @@ function createExpectedSpanJson(useHex: boolean) { ], }, ], - // eslint-disable-next-line @typescript-eslint/no-loss-of-precision - startTimeUnixNano: 1640715557342725388, - // eslint-disable-next-line @typescript-eslint/no-loss-of-precision - endTimeUnixNano: 1640715558642725388, + startTimeUnixNano: new UnsignedLong(1155450124, 382008859), + endTimeUnixNano: new UnsignedLong(-1839517172, 382008859), events: [ { droppedAttributesCount: 0, @@ -95,7 +94,7 @@ function createExpectedSpanJson(useHex: boolean) { }, ], name: 'some event', - timeUnixNano: 1640715558542725400, + timeUnixNano: new UnsignedLong(-1939517172, 382008859), }, ], attributes: [ diff --git a/experimental/packages/sdk-logs/package.json b/experimental/packages/sdk-logs/package.json index f35a643c07..1a353f9ebd 100644 --- a/experimental/packages/sdk-logs/package.json +++ b/experimental/packages/sdk-logs/package.json @@ -75,9 +75,9 @@ "@babel/core": "7.22.20", "@opentelemetry/api": ">=1.4.0 <1.7.0", "@opentelemetry/api-logs": "0.43.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/experimental/packages/shim-opencensus/package.json b/experimental/packages/shim-opencensus/package.json index 2e24690be8..3ec28d7aea 100644 --- a/experimental/packages/shim-opencensus/package.json +++ b/experimental/packages/shim-opencensus/package.json @@ -52,9 +52,9 @@ "@opentelemetry/api": "1.6.0", "@opentelemetry/context-async-hooks": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/integration-tests/propagation-validation-server/package.json b/integration-tests/propagation-validation-server/package.json index e54a18825c..2b5fcd3404 100644 --- a/integration-tests/propagation-validation-server/package.json +++ b/integration-tests/propagation-validation-server/package.json @@ -15,7 +15,7 @@ "@opentelemetry/context-async-hooks": "1.17.0", "@opentelemetry/core": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", - "axios": "1.5.0", + "axios": "1.5.1", "body-parser": "1.19.0", "express": "4.17.3" }, diff --git a/packages/opentelemetry-context-async-hooks/package.json b/packages/opentelemetry-context-async-hooks/package.json index 181fc92dce..ea0da0acbe 100644 --- a/packages/opentelemetry-context-async-hooks/package.json +++ b/packages/opentelemetry-context-async-hooks/package.json @@ -45,7 +45,7 @@ }, "devDependencies": { "@opentelemetry/api": ">=1.0.0 <1.7.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/packages/opentelemetry-context-zone-peer-dep/package.json b/packages/opentelemetry-context-zone-peer-dep/package.json index 0a673ab480..a428e499b9 100644 --- a/packages/opentelemetry-context-zone-peer-dep/package.json +++ b/packages/opentelemetry-context-zone-peer-dep/package.json @@ -55,9 +55,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": ">=1.0.0 <1.7.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "@types/zone.js": "0.5.12", "babel-loader": "8.3.0", diff --git a/packages/opentelemetry-context-zone/package.json b/packages/opentelemetry-context-zone/package.json index 76adff9578..74d3e4f23d 100644 --- a/packages/opentelemetry-context-zone/package.json +++ b/packages/opentelemetry-context-zone/package.json @@ -51,9 +51,9 @@ }, "devDependencies": { "@babel/core": "7.22.20", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "codecov": "3.8.3", diff --git a/packages/opentelemetry-core/package.json b/packages/opentelemetry-core/package.json index bb1e010b22..6806540667 100644 --- a/packages/opentelemetry-core/package.json +++ b/packages/opentelemetry-core/package.json @@ -65,9 +65,9 @@ }, "devDependencies": { "@opentelemetry/api": ">=1.0.0 <1.7.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", diff --git a/packages/opentelemetry-exporter-jaeger/package.json b/packages/opentelemetry-exporter-jaeger/package.json index 9e94b5f268..3fba91d4f3 100644 --- a/packages/opentelemetry-exporter-jaeger/package.json +++ b/packages/opentelemetry-exporter-jaeger/package.json @@ -46,9 +46,9 @@ "devDependencies": { "@opentelemetry/api": "^1.0.0", "@opentelemetry/resources": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/packages/opentelemetry-exporter-zipkin/package.json b/packages/opentelemetry-exporter-zipkin/package.json index 681d997e34..7f978b5543 100644 --- a/packages/opentelemetry-exporter-zipkin/package.json +++ b/packages/opentelemetry-exporter-zipkin/package.json @@ -62,9 +62,9 @@ "devDependencies": { "@babel/core": "7.22.20", "@opentelemetry/api": "^1.0.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/packages/opentelemetry-exporter-zipkin/src/transform.ts b/packages/opentelemetry-exporter-zipkin/src/transform.ts index 54392321f8..06fbe5973a 100644 --- a/packages/opentelemetry-exporter-zipkin/src/transform.ts +++ b/packages/opentelemetry-exporter-zipkin/src/transform.ts @@ -111,7 +111,7 @@ export function _toZipkinAnnotations( events: TimedEvent[] ): zipkinTypes.Annotation[] { return events.map(event => ({ - timestamp: hrTimeToMicroseconds(event.time), + timestamp: Math.round(hrTimeToMicroseconds(event.time)), value: event.name, })); } diff --git a/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts b/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts index 810b9e32f9..4df7f73f6c 100644 --- a/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts +++ b/packages/opentelemetry-exporter-zipkin/test/common/transform.test.ts @@ -82,7 +82,7 @@ describe('transform', () => { annotations: [ { value: 'my-event', - timestamp: hrTimeToMicroseconds(span.events[0].time), + timestamp: Math.round(hrTimeToMicroseconds(span.events[0].time)), }, ], duration: Math.round( @@ -329,11 +329,11 @@ describe('transform', () => { assert.deepStrictEqual(annotations, [ { value: 'my-event1', - timestamp: hrTimeToMicroseconds(span.events[0].time), + timestamp: Math.round(hrTimeToMicroseconds(span.events[0].time)), }, { value: 'my-event2', - timestamp: hrTimeToMicroseconds(span.events[1].time), + timestamp: Math.round(hrTimeToMicroseconds(span.events[1].time)), }, ]); }); diff --git a/packages/opentelemetry-propagator-b3/package.json b/packages/opentelemetry-propagator-b3/package.json index 353c87b20f..34f044c541 100644 --- a/packages/opentelemetry-propagator-b3/package.json +++ b/packages/opentelemetry-propagator-b3/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "@opentelemetry/api": ">=1.0.0 <1.7.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/packages/opentelemetry-propagator-jaeger/package.json b/packages/opentelemetry-propagator-jaeger/package.json index 8d7a70c84b..7735971bf7 100644 --- a/packages/opentelemetry-propagator-jaeger/package.json +++ b/packages/opentelemetry-propagator-jaeger/package.json @@ -55,9 +55,9 @@ }, "devDependencies": { "@opentelemetry/api": ">=1.0.0 <1.7.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", diff --git a/packages/opentelemetry-resources/package.json b/packages/opentelemetry-resources/package.json index 311ea9d90b..9951d8ee4a 100644 --- a/packages/opentelemetry-resources/package.json +++ b/packages/opentelemetry-resources/package.json @@ -63,9 +63,9 @@ "devDependencies": { "@opentelemetry/api": ">=1.0.0 <1.7.0", "@opentelemetry/resources_1.9.0": "npm:@opentelemetry/resources@1.9.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/packages/opentelemetry-sdk-trace-base/package.json b/packages/opentelemetry-sdk-trace-base/package.json index 600caa4294..97d034bfef 100644 --- a/packages/opentelemetry-sdk-trace-base/package.json +++ b/packages/opentelemetry-sdk-trace-base/package.json @@ -67,9 +67,9 @@ "devDependencies": { "@opentelemetry/api": ">=1.0.0 <1.7.0", "@opentelemetry/resources_1.9.0": "npm:@opentelemetry/resources@1.9.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", diff --git a/packages/opentelemetry-sdk-trace-node/package.json b/packages/opentelemetry-sdk-trace-node/package.json index 0bdcc4a090..d18133ec75 100644 --- a/packages/opentelemetry-sdk-trace-node/package.json +++ b/packages/opentelemetry-sdk-trace-node/package.json @@ -48,10 +48,10 @@ "@opentelemetry/api": ">=1.0.0 <1.7.0", "@opentelemetry/resources": "1.17.0", "@opentelemetry/semantic-conventions": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/semver": "7.5.2", - "@types/sinon": "10.0.16", + "@types/semver": "7.5.3", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/packages/opentelemetry-sdk-trace-web/package.json b/packages/opentelemetry-sdk-trace-web/package.json index ebbf2a4025..47a459e0d7 100644 --- a/packages/opentelemetry-sdk-trace-web/package.json +++ b/packages/opentelemetry-sdk-trace-web/package.json @@ -60,10 +60,10 @@ "@opentelemetry/context-zone": "1.17.0", "@opentelemetry/propagator-b3": "1.17.0", "@opentelemetry/resources": "1.17.0", - "@types/jquery": "3.5.19", - "@types/mocha": "10.0.1", + "@types/jquery": "3.5.20", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "@types/webpack-env": "1.16.3", "babel-loader": "8.3.0", "babel-plugin-istanbul": "6.1.1", diff --git a/packages/opentelemetry-semantic-conventions/package.json b/packages/opentelemetry-semantic-conventions/package.json index 0cc05eb2dd..0d0860cd22 100644 --- a/packages/opentelemetry-semantic-conventions/package.json +++ b/packages/opentelemetry-semantic-conventions/package.json @@ -49,9 +49,9 @@ "access": "public" }, "devDependencies": { - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "codecov": "3.8.3", "cross-var": "1.1.0", "lerna": "7.1.5", diff --git a/packages/opentelemetry-shim-opentracing/package.json b/packages/opentelemetry-shim-opentracing/package.json index f328e7fce4..78381872e2 100644 --- a/packages/opentelemetry-shim-opentracing/package.json +++ b/packages/opentelemetry-shim-opentracing/package.json @@ -46,7 +46,7 @@ "@opentelemetry/propagator-b3": "1.17.0", "@opentelemetry/propagator-jaeger": "1.17.0", "@opentelemetry/sdk-trace-base": "1.17.0", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/packages/sdk-metrics/package.json b/packages/sdk-metrics/package.json index 3d4f5b299e..b16f4531a9 100644 --- a/packages/sdk-metrics/package.json +++ b/packages/sdk-metrics/package.json @@ -57,9 +57,9 @@ "@babel/core": "7.22.20", "@opentelemetry/api": ">=1.3.0 <1.7.0", "@types/lodash.merge": "4.6.7", - "@types/mocha": "10.0.1", + "@types/mocha": "10.0.2", "@types/node": "18.6.5", - "@types/sinon": "10.0.16", + "@types/sinon": "10.0.17", "babel-plugin-istanbul": "6.1.1", "codecov": "3.8.3", "cross-var": "1.1.0", diff --git a/packages/sdk-metrics/src/state/MeterSharedState.ts b/packages/sdk-metrics/src/state/MeterSharedState.ts index 099a21c0d7..4189d6bb6c 100644 --- a/packages/sdk-metrics/src/state/MeterSharedState.ts +++ b/packages/sdk-metrics/src/state/MeterSharedState.ts @@ -78,7 +78,7 @@ export class MeterSharedState { collector: MetricCollectorHandle, collectionTime: HrTime, options?: MetricCollectOptions - ): Promise { + ): Promise { /** * 1. Call all observable callbacks first. * 2. Collect metric result for the collector. @@ -87,9 +87,14 @@ export class MeterSharedState { collectionTime, options?.timeoutMillis ); - const metricDataList = Array.from( - this.metricStorageRegistry.getStorages(collector) - ) + const storages = this.metricStorageRegistry.getStorages(collector); + + // prevent more allocations if there are no storages. + if (storages.length === 0) { + return null; + } + + const metricDataList = storages .map(metricStorage => { return metricStorage.collect( collector, @@ -99,10 +104,15 @@ export class MeterSharedState { }) .filter(isNotNullish); + // skip this scope if no data was collected (storage created, but no data observed) + if (metricDataList.length === 0) { + return { errors }; + } + return { scopeMetrics: { scope: this._instrumentationScope, - metrics: metricDataList.filter(isNotNullish), + metrics: metricDataList, }, errors, }; @@ -173,7 +183,7 @@ export class MeterSharedState { } interface ScopeMetricsResult { - scopeMetrics: ScopeMetrics; + scopeMetrics?: ScopeMetrics; errors: unknown[]; } diff --git a/packages/sdk-metrics/src/state/MetricCollector.ts b/packages/sdk-metrics/src/state/MetricCollector.ts index 3f17a0d5b9..f1f1dacdb1 100644 --- a/packages/sdk-metrics/src/state/MetricCollector.ts +++ b/packages/sdk-metrics/src/state/MetricCollector.ts @@ -16,12 +16,11 @@ import { millisToHrTime } from '@opentelemetry/core'; import { AggregationTemporalitySelector } from '../export/AggregationSelector'; -import { CollectionResult } from '../export/MetricData'; +import { CollectionResult, ScopeMetrics } from '../export/MetricData'; import { MetricProducer, MetricCollectOptions } from '../export/MetricProducer'; import { MetricReader } from '../export/MetricReader'; import { InstrumentType } from '../InstrumentDescriptor'; import { ForceFlushOptions, ShutdownOptions } from '../types'; -import { FlatMap } from '../utils'; import { MeterProviderSharedState } from './MeterProviderSharedState'; /** @@ -37,19 +36,36 @@ export class MetricCollector implements MetricProducer { async collect(options?: MetricCollectOptions): Promise { const collectionTime = millisToHrTime(Date.now()); + const scopeMetrics: ScopeMetrics[] = []; + const errors: unknown[] = []; + const meterCollectionPromises = Array.from( this._sharedState.meterSharedStates.values() - ).map(meterSharedState => - meterSharedState.collect(this, collectionTime, options) - ); - const result = await Promise.all(meterCollectionPromises); + ).map(async meterSharedState => { + const current = await meterSharedState.collect( + this, + collectionTime, + options + ); + + // only add scope metrics if available + if (current?.scopeMetrics != null) { + scopeMetrics.push(current.scopeMetrics); + } + + // only add errors if available + if (current?.errors != null) { + errors.push(...current.errors); + } + }); + await Promise.all(meterCollectionPromises); return { resourceMetrics: { resource: this._sharedState.resource, - scopeMetrics: result.map(it => it.scopeMetrics), + scopeMetrics: scopeMetrics, }, - errors: FlatMap(result, it => it.errors), + errors: errors, }; } diff --git a/packages/sdk-metrics/src/state/TemporalMetricProcessor.ts b/packages/sdk-metrics/src/state/TemporalMetricProcessor.ts index 2b9c5dbbaa..bb5559e70e 100644 --- a/packages/sdk-metrics/src/state/TemporalMetricProcessor.ts +++ b/packages/sdk-metrics/src/state/TemporalMetricProcessor.ts @@ -133,10 +133,17 @@ export class TemporalMetricProcessor> { aggregationTemporality, }); + const accumulationRecords = AttributesMapToAccumulationRecords(result); + + // do not convert to metric data if there is nothing to convert. + if (accumulationRecords.length === 0) { + return undefined; + } + return this._aggregator.toMetricData( instrumentDescriptor, aggregationTemporality, - AttributesMapToAccumulationRecords(result), + accumulationRecords, /* endTime */ collectionTime ); } diff --git a/packages/sdk-metrics/test/Instruments.test.ts b/packages/sdk-metrics/test/Instruments.test.ts index 80f834f30c..cfb6255039 100644 --- a/packages/sdk-metrics/test/Instruments.test.ts +++ b/packages/sdk-metrics/test/Instruments.test.ts @@ -434,10 +434,10 @@ describe('Instruments', () => { }); histogram.record(-1, { foo: 'bar' }); - await validateExport(deltaReader, { - dataPointType: DataPointType.HISTOGRAM, - dataPoints: [], - }); + const result = await deltaReader.collect(); + + // nothing observed + assert.equal(result.resourceMetrics.scopeMetrics.length, 0); }); it('should record DOUBLE values', async () => { @@ -499,10 +499,10 @@ describe('Instruments', () => { }); histogram.record(-0.5, { foo: 'bar' }); - await validateExport(deltaReader, { - dataPointType: DataPointType.HISTOGRAM, - dataPoints: [], - }); + const result = await deltaReader.collect(); + + // nothing observed + assert.equal(result.resourceMetrics.scopeMetrics.length, 0); }); }); diff --git a/packages/sdk-metrics/test/MeterProvider.test.ts b/packages/sdk-metrics/test/MeterProvider.test.ts index a9f8361b81..be075f0fa6 100644 --- a/packages/sdk-metrics/test/MeterProvider.test.ts +++ b/packages/sdk-metrics/test/MeterProvider.test.ts @@ -77,23 +77,29 @@ describe('MeterProvider', () => { const reader = new TestMetricReader(); meterProvider.addMetricReader(reader); - // Create meter and instrument. + // Create meter and instrument, needs observation on instrument, otherwise the scope will not be reported. // name+version pair 1 - meterProvider.getMeter('meter1', 'v1.0.0'); - meterProvider.getMeter('meter1', 'v1.0.0'); + meterProvider.getMeter('meter1', 'v1.0.0').createCounter('test').add(1); + meterProvider.getMeter('meter1', 'v1.0.0').createCounter('test').add(1); // name+version pair 2 - meterProvider.getMeter('meter2', 'v1.0.0'); - meterProvider.getMeter('meter2', 'v1.0.0'); + meterProvider.getMeter('meter2', 'v1.0.0').createCounter('test').add(1); + meterProvider.getMeter('meter2', 'v1.0.0').createCounter('test').add(1); // name+version pair 3 - meterProvider.getMeter('meter1', 'v1.0.1'); - meterProvider.getMeter('meter1', 'v1.0.1'); + meterProvider.getMeter('meter1', 'v1.0.1').createCounter('test').add(1); + meterProvider.getMeter('meter1', 'v1.0.1').createCounter('test').add(1); // name+version+schemaUrl pair 4 - meterProvider.getMeter('meter1', 'v1.0.1', { - schemaUrl: 'https://opentelemetry.io/schemas/1.4.0', - }); - meterProvider.getMeter('meter1', 'v1.0.1', { - schemaUrl: 'https://opentelemetry.io/schemas/1.4.0', - }); + meterProvider + .getMeter('meter1', 'v1.0.1', { + schemaUrl: 'https://opentelemetry.io/schemas/1.4.0', + }) + .createCounter('test') + .add(1); + meterProvider + .getMeter('meter1', 'v1.0.1', { + schemaUrl: 'https://opentelemetry.io/schemas/1.4.0', + }) + .createCounter('test') + .add(1); // Perform collection. const { resourceMetrics, errors } = await reader.collect(); diff --git a/packages/sdk-metrics/test/state/AsyncMetricStorage.test.ts b/packages/sdk-metrics/test/state/AsyncMetricStorage.test.ts index 9fe742ca02..03eca24236 100644 --- a/packages/sdk-metrics/test/state/AsyncMetricStorage.test.ts +++ b/packages/sdk-metrics/test/state/AsyncMetricStorage.test.ts @@ -110,8 +110,7 @@ describe('AsyncMetricStorage', () => { collectionTime ); - assertMetricData(metric, DataPointType.SUM); - assert.strictEqual(metric.dataPoints.length, 0); + assert.equal(metric, undefined); } delegate.setDelegate(observableResult => { diff --git a/packages/sdk-metrics/test/state/MetricCollector.test.ts b/packages/sdk-metrics/test/state/MetricCollector.test.ts index 3c70b35759..8466a5a95c 100644 --- a/packages/sdk-metrics/test/state/MetricCollector.test.ts +++ b/packages/sdk-metrics/test/state/MetricCollector.test.ts @@ -141,7 +141,8 @@ describe('MetricCollector', () => { assert.strictEqual(errors.length, 0); const { scopeMetrics } = resourceMetrics; const { metrics } = scopeMetrics[0]; - assert.strictEqual(metrics.length, 3); + // Should not export observableCounter3, as it was never observed + assert.strictEqual(metrics.length, 2); /** checking batch[0] */ const metricData1 = metrics[0]; @@ -160,13 +161,6 @@ describe('MetricCollector', () => { assert.strictEqual(metricData2.dataPoints.length, 2); assertDataPoint(metricData2.dataPoints[0], {}, 3); assertDataPoint(metricData2.dataPoints[1], { foo: 'bar' }, 4); - - /** checking batch[2] */ - const metricData3 = metrics[2]; - assertMetricData(metricData3, DataPointType.SUM, { - name: 'observable3', - }); - assert.strictEqual(metricData3.dataPoints.length, 0); }); it('should collect observer metrics with timeout', async () => { @@ -205,19 +199,15 @@ describe('MetricCollector', () => { assert(errors[0] instanceof TimeoutError); const { scopeMetrics } = resourceMetrics; const { metrics } = scopeMetrics[0]; - assert.strictEqual(metrics.length, 2); - /** observer1 */ - assertMetricData(metrics[0], DataPointType.SUM, { - name: 'observer1', - }); - assert.strictEqual(metrics[0].dataPoints.length, 0); + // Only observer2 is exported, observer1 never reported a measurement + assert.strictEqual(metrics.length, 1); /** observer2 */ - assertMetricData(metrics[1], DataPointType.SUM, { + assertMetricData(metrics[0], DataPointType.SUM, { name: 'observer2', }); - assert.strictEqual(metrics[1].dataPoints.length, 1); + assert.strictEqual(metrics[0].dataPoints.length, 1); } /** now the observer1 is back to normal */ @@ -272,19 +262,13 @@ describe('MetricCollector', () => { assert.strictEqual(`${errors[0]}`, 'Error: foobar'); const { scopeMetrics } = resourceMetrics; const { metrics } = scopeMetrics[0]; - assert.strictEqual(metrics.length, 2); - /** counter1 data points are collected */ + /** only counter1 data points are collected */ + assert.strictEqual(metrics.length, 1); assertMetricData(metrics[0], DataPointType.SUM, { name: 'counter1', }); assert.strictEqual(metrics[0].dataPoints.length, 1); - - /** observer1 data points are not collected */ - assertMetricData(metrics[1], DataPointType.SUM, { - name: 'observer1', - }); - assert.strictEqual(metrics[1].dataPoints.length, 0); }); it('should collect batch observer metrics with timeout', async () => { @@ -327,19 +311,13 @@ describe('MetricCollector', () => { assert(errors[0] instanceof TimeoutError); const { scopeMetrics } = resourceMetrics; const { metrics } = scopeMetrics[0]; - assert.strictEqual(metrics.length, 2); - /** observer1 */ + /** only observer2 is present; observer1's promise never settled*/ + assert.strictEqual(metrics.length, 1); assertMetricData(metrics[0], DataPointType.SUM, { - name: 'observer1', - }); - assert.strictEqual(metrics[0].dataPoints.length, 0); - - /** observer2 */ - assertMetricData(metrics[1], DataPointType.SUM, { name: 'observer2', }); - assert.strictEqual(metrics[1].dataPoints.length, 1); + assert.strictEqual(metrics[0].dataPoints.length, 1); } /** now the observer1 is back to normal */ @@ -398,19 +376,13 @@ describe('MetricCollector', () => { assert.strictEqual(`${errors[0]}`, 'Error: foobar'); const { scopeMetrics } = resourceMetrics; const { metrics } = scopeMetrics[0]; - assert.strictEqual(metrics.length, 2); - /** counter1 data points are collected */ + /** counter1 data points are collected; observer1's callback did throw, so data points are not collected */ + assert.strictEqual(metrics.length, 1); assertMetricData(metrics[0], DataPointType.SUM, { name: 'counter1', }); assert.strictEqual(metrics[0].dataPoints.length, 1); - - /** observer1 data points are not collected */ - assertMetricData(metrics[1], DataPointType.SUM, { - name: 'observer1', - }); - assert.strictEqual(metrics[1].dataPoints.length, 0); }); }); }); diff --git a/packages/sdk-metrics/test/state/SyncMetricStorage.test.ts b/packages/sdk-metrics/test/state/SyncMetricStorage.test.ts index 8e568be19e..072cc9d16d 100644 --- a/packages/sdk-metrics/test/state/SyncMetricStorage.test.ts +++ b/packages/sdk-metrics/test/state/SyncMetricStorage.test.ts @@ -88,8 +88,7 @@ describe('SyncMetricStorage', () => { [4, 4] ); - assertMetricData(metric, DataPointType.SUM); - assert.strictEqual(metric.dataPoints.length, 0); + assert.strictEqual(metric, undefined); } metricStorage.record(1, {}, api.context.active(), [5, 5]); diff --git a/packages/sdk-metrics/test/state/TemporalMetricProcessor.test.ts b/packages/sdk-metrics/test/state/TemporalMetricProcessor.test.ts index 8d0f165cd0..26a10aea57 100644 --- a/packages/sdk-metrics/test/state/TemporalMetricProcessor.test.ts +++ b/packages/sdk-metrics/test/state/TemporalMetricProcessor.test.ts @@ -107,13 +107,8 @@ describe('TemporalMetricProcessor', () => { [5, 5] ); - assertMetricData( - metric, - DataPointType.SUM, - defaultInstrumentDescriptor, - AggregationTemporality.DELTA - ); - assert.strictEqual(metric.dataPoints.length, 0); + // nothing recorded -> nothing collected + assert.equal(metric, undefined); } // selectAggregationTemporality should be called only once.