Skip to content

Commit 513d067

Browse files
seemkpichlermarc
andauthored
fix(otlp-transformer): avoid precision loss when converting HrTime to unix nanoseconds (#4062)
Co-authored-by: Marc Pichler <[email protected]>
1 parent 6bf1b78 commit 513d067

File tree

28 files changed

+530
-420
lines changed

28 files changed

+530
-420
lines changed

experimental/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ All notable changes to experimental packages in this project will be documented
5656

5757
### :bug: (Bug Fix)
5858

59+
* fix(otlp-transformer): Avoid precision loss when converting from HrTime to unix nanoseconds. [#4062](https://github.com/open-telemetry/opentelemetry-js/pull/4062)
5960
* fix(exporter-logs-otlp-http): add @opentelemetry/api-logs as dependency
6061

6162
## 0.41.2

experimental/packages/exporter-logs-otlp-grpc/test/logsHelper.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) {
8888
ensureExportedAttributesAreCorrect(logRecord.attributes);
8989
assert.strictEqual(
9090
logRecord.timeUnixNano,
91-
'1680253513123241728',
91+
'1680253513123241635',
9292
'timeUnixNano is wrong'
9393
);
9494
assert.strictEqual(

experimental/packages/exporter-logs-otlp-http/test/logHelper.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Resource } from '@opentelemetry/resources';
2020
import * as assert from 'assert';
2121
import { VERSION } from '@opentelemetry/core';
2222
import {
23+
hrTimeToFixed64Nanos,
2324
IAnyValue,
2425
IExportLogsServiceRequest,
2526
IKeyValue,
@@ -76,17 +77,22 @@ export function ensureExportedBodyIsCorrect(body?: IAnyValue) {
7677
);
7778
}
7879

80+
function hrTimeToFixed64(hrTime: HrTime) {
81+
const { low, high } = hrTimeToFixed64Nanos(hrTime);
82+
return { low, high };
83+
}
84+
7985
export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) {
8086
ensureExportedBodyIsCorrect(logRecord.body);
8187
ensureExportedAttributesAreCorrect(logRecord.attributes);
82-
assert.strictEqual(
88+
assert.deepStrictEqual(
8389
logRecord.timeUnixNano,
84-
1680253513123241700,
90+
hrTimeToFixed64(mockedReadableLogRecord.hrTime),
8591
'timeUnixNano is wrong'
8692
);
87-
assert.strictEqual(
93+
assert.deepStrictEqual(
8894
logRecord.observedTimeUnixNano,
89-
1680253513123241700,
95+
hrTimeToFixed64(mockedReadableLogRecord.hrTimeObserved),
9096
'observedTimeUnixNano is wrong'
9197
);
9298
assert.strictEqual(

experimental/packages/exporter-logs-otlp-proto/test/logHelper.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@ export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) {
8282
ensureExportedAttributesAreCorrect(logRecord.attributes);
8383
assert.strictEqual(
8484
logRecord.timeUnixNano,
85-
'1680253513123241728',
85+
'1680253513123241635',
8686
'timeUnixNano is wrong'
8787
);
8888
assert.strictEqual(
8989
logRecord.observedTimeUnixNano,
90-
'1680253513123241728',
90+
'1680253513123241635',
9191
'observedTimeUnixNano is wrong'
9292
);
9393
assert.strictEqual(

experimental/packages/exporter-trace-otlp-grpc/test/traceHelper.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -114,49 +114,49 @@ export function ensureExportedEventsAreCorrect(events: IEvent[]) {
114114
[
115115
{
116116
attributes: [],
117-
timeUnixNano: '1574120165429803008',
117+
timeUnixNano: '1574120165429803070',
118118
name: 'fetchStart',
119119
droppedAttributesCount: 0,
120120
},
121121
{
122122
attributes: [],
123-
timeUnixNano: '1574120165429803008',
123+
timeUnixNano: '1574120165429803070',
124124
name: 'domainLookupStart',
125125
droppedAttributesCount: 0,
126126
},
127127
{
128128
attributes: [],
129-
timeUnixNano: '1574120165429803008',
129+
timeUnixNano: '1574120165429803070',
130130
name: 'domainLookupEnd',
131131
droppedAttributesCount: 0,
132132
},
133133
{
134134
attributes: [],
135-
timeUnixNano: '1574120165429803008',
135+
timeUnixNano: '1574120165429803070',
136136
name: 'connectStart',
137137
droppedAttributesCount: 0,
138138
},
139139
{
140140
attributes: [],
141-
timeUnixNano: '1574120165429803008',
141+
timeUnixNano: '1574120165429803070',
142142
name: 'connectEnd',
143143
droppedAttributesCount: 0,
144144
},
145145
{
146146
attributes: [],
147-
timeUnixNano: '1574120165435513088',
147+
timeUnixNano: '1574120165435513070',
148148
name: 'requestStart',
149149
droppedAttributesCount: 0,
150150
},
151151
{
152152
attributes: [],
153-
timeUnixNano: '1574120165436923136',
153+
timeUnixNano: '1574120165436923070',
154154
name: 'responseStart',
155155
droppedAttributesCount: 0,
156156
},
157157
{
158158
attributes: [],
159-
timeUnixNano: '1574120165438688000',
159+
timeUnixNano: '1574120165438688070',
160160
name: 'responseEnd',
161161
droppedAttributesCount: 0,
162162
},
@@ -235,12 +235,12 @@ export function ensureExportedSpanIsCorrect(span: ISpan) {
235235
assert.strictEqual(span.kind, 'SPAN_KIND_INTERNAL', 'kind is wrong');
236236
assert.strictEqual(
237237
span.startTimeUnixNano,
238-
'1574120165429803008',
238+
'1574120165429803070',
239239
'startTimeUnixNano is wrong'
240240
);
241241
assert.strictEqual(
242242
span.endTimeUnixNano,
243-
'1574120165438688000',
243+
'1574120165438688070',
244244
'endTimeUnixNano is wrong'
245245
);
246246
assert.strictEqual(

experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,6 @@ describe('OTLPTraceExporter - node with json over http', () => {
316316

317317
fakeRequest.on('end', () => {
318318
const responseBody = buff.toString();
319-
320319
const json = JSON.parse(responseBody) as IExportTraceServiceRequest;
321320
const span1 = json.resourceSpans?.[0].scopeSpans?.[0].spans?.[0];
322321
assert.ok(typeof span1 !== 'undefined', "span doesn't exist");

experimental/packages/exporter-trace-otlp-http/test/traceHelper.ts

+18-12
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
ILink,
3232
IResource,
3333
ISpan,
34+
UnsignedLong,
3435
} from '@opentelemetry/otlp-transformer';
3536

3637
if (typeof Buffer === 'undefined') {
@@ -243,54 +244,59 @@ export const multiInstrumentationLibraryTrace: ReadableSpan[] = [
243244
},
244245
];
245246

247+
function fixed64FromString(str: string) {
248+
const { low, high } = UnsignedLong.fromString(str);
249+
return { low, high };
250+
}
251+
246252
export function ensureEventsAreCorrect(events: IEvent[]) {
247253
assert.deepStrictEqual(
248254
events,
249255
[
250256
{
251-
timeUnixNano: 1574120165429803000,
257+
timeUnixNano: fixed64FromString('1574120165429803070'),
252258
name: 'fetchStart',
253259
attributes: [],
254260
droppedAttributesCount: 0,
255261
},
256262
{
257-
timeUnixNano: 1574120165429803000,
263+
timeUnixNano: fixed64FromString('1574120165429803070'),
258264
name: 'domainLookupStart',
259265
attributes: [],
260266
droppedAttributesCount: 0,
261267
},
262268
{
263-
timeUnixNano: 1574120165429803000,
269+
timeUnixNano: fixed64FromString('1574120165429803070'),
264270
name: 'domainLookupEnd',
265271
attributes: [],
266272
droppedAttributesCount: 0,
267273
},
268274
{
269-
timeUnixNano: 1574120165429803000,
275+
timeUnixNano: fixed64FromString('1574120165429803070'),
270276
name: 'connectStart',
271277
attributes: [],
272278
droppedAttributesCount: 0,
273279
},
274280
{
275-
timeUnixNano: 1574120165429803000,
281+
timeUnixNano: fixed64FromString('1574120165429803070'),
276282
name: 'connectEnd',
277283
attributes: [],
278284
droppedAttributesCount: 0,
279285
},
280286
{
281-
timeUnixNano: 1574120165435513000,
287+
timeUnixNano: fixed64FromString('1574120165435513070'),
282288
name: 'requestStart',
283289
attributes: [],
284290
droppedAttributesCount: 0,
285291
},
286292
{
287-
timeUnixNano: 1574120165436923100,
293+
timeUnixNano: fixed64FromString('1574120165436923070'),
288294
name: 'responseStart',
289295
attributes: [],
290296
droppedAttributesCount: 0,
291297
},
292298
{
293-
timeUnixNano: 1574120165438688000,
299+
timeUnixNano: fixed64FromString('1574120165438688070'),
294300
name: 'responseEnd',
295301
attributes: [],
296302
droppedAttributesCount: 0,
@@ -364,14 +370,14 @@ export function ensureSpanIsCorrect(span: ISpan, useHex = true) {
364370
);
365371
assert.strictEqual(span.name, 'documentFetch', 'name is wrong');
366372
assert.strictEqual(span.kind, ESpanKind.SPAN_KIND_INTERNAL, 'kind is wrong');
367-
assert.strictEqual(
373+
assert.deepStrictEqual(
368374
span.startTimeUnixNano,
369-
1574120165429803008,
375+
fixed64FromString('1574120165429803070'),
370376
'startTimeUnixNano is wrong'
371377
);
372-
assert.strictEqual(
378+
assert.deepStrictEqual(
373379
span.endTimeUnixNano,
374-
1574120165438688000,
380+
fixed64FromString('1574120165438688070'),
375381
'endTimeUnixNano is wrong'
376382
);
377383
assert.strictEqual(

experimental/packages/exporter-trace-otlp-proto/test/traceHelper.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -109,42 +109,42 @@ export function ensureProtoEventsAreCorrect(events: IEvent[]) {
109109
events,
110110
[
111111
{
112-
timeUnixNano: '1574120165429803008',
112+
timeUnixNano: '1574120165429803070',
113113
name: 'fetchStart',
114114
droppedAttributesCount: 0,
115115
},
116116
{
117-
timeUnixNano: '1574120165429803008',
117+
timeUnixNano: '1574120165429803070',
118118
name: 'domainLookupStart',
119119
droppedAttributesCount: 0,
120120
},
121121
{
122-
timeUnixNano: '1574120165429803008',
122+
timeUnixNano: '1574120165429803070',
123123
name: 'domainLookupEnd',
124124
droppedAttributesCount: 0,
125125
},
126126
{
127-
timeUnixNano: '1574120165429803008',
127+
timeUnixNano: '1574120165429803070',
128128
name: 'connectStart',
129129
droppedAttributesCount: 0,
130130
},
131131
{
132-
timeUnixNano: '1574120165429803008',
132+
timeUnixNano: '1574120165429803070',
133133
name: 'connectEnd',
134134
droppedAttributesCount: 0,
135135
},
136136
{
137-
timeUnixNano: '1574120165435513088',
137+
timeUnixNano: '1574120165435513070',
138138
name: 'requestStart',
139139
droppedAttributesCount: 0,
140140
},
141141
{
142-
timeUnixNano: '1574120165436923136',
142+
timeUnixNano: '1574120165436923070',
143143
name: 'responseStart',
144144
droppedAttributesCount: 0,
145145
},
146146
{
147-
timeUnixNano: '1574120165438688000',
147+
timeUnixNano: '1574120165438688070',
148148
name: 'responseEnd',
149149
droppedAttributesCount: 0,
150150
},
@@ -219,12 +219,12 @@ export function ensureProtoSpanIsCorrect(span: ISpan) {
219219
assert.strictEqual(span.kind, 'SPAN_KIND_INTERNAL', 'kind is wrong');
220220
assert.strictEqual(
221221
span.startTimeUnixNano,
222-
'1574120165429803008',
222+
'1574120165429803070',
223223
'startTimeUnixNano is wrong'
224224
);
225225
assert.strictEqual(
226226
span.endTimeUnixNano,
227-
'1574120165438688000',
227+
'1574120165438688070',
228228
'endTimeUnixNano is wrong'
229229
);
230230
assert.strictEqual(

experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,23 @@ const testOTLPMetricExporter = (params: TestParams) => {
253253
exportedData[0].scopeMetrics[0].metrics[histogramIndex];
254254
ensureExportedCounterIsCorrect(
255255
counter,
256-
counter.sum?.dataPoints[0].timeUnixNano,
257-
counter.sum?.dataPoints[0].startTimeUnixNano
256+
metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0].endTime,
257+
metrics.scopeMetrics[0].metrics[counterIndex].dataPoints[0]
258+
.startTime
258259
);
259260
ensureExportedObservableGaugeIsCorrect(
260261
observableGauge,
261-
observableGauge.gauge?.dataPoints[0].timeUnixNano,
262-
observableGauge.gauge?.dataPoints[0].startTimeUnixNano
262+
metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0]
263+
.endTime,
264+
metrics.scopeMetrics[0].metrics[observableIndex].dataPoints[0]
265+
.startTime
263266
);
264267
ensureExportedHistogramIsCorrect(
265268
histogram,
266-
histogram.histogram?.dataPoints[0].timeUnixNano,
267-
histogram.histogram?.dataPoints[0].startTimeUnixNano,
269+
metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0]
270+
.endTime,
271+
metrics.scopeMetrics[0].metrics[histogramIndex].dataPoints[0]
272+
.startTime,
268273
[0, 100],
269274
['0', '2', '0']
270275
);

0 commit comments

Comments
 (0)