diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index f094b61bd65..591e4b2a231 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -20,6 +20,7 @@ feat(configuration): parse config for rc 3 [#6304](https://github.com/open-telem ### :bug: Bug Fixes * fix(exporter-prometheus): add missing `@opentelemetry/semantic-conventions` dependency [#6330](https://github.com/open-telemetry/opentelemetry-js/pull/6330) @omizha +* fix(otlp-transformer): correctly handle Uint8Array attribute values when serializing to JSON [#6348](https://github.com/open-telemetry/opentelemetry-js/pull/6348) @pichlermarc ### :books: Documentation diff --git a/experimental/packages/otlp-transformer/src/common/internal-types.ts b/experimental/packages/otlp-transformer/src/common/internal-types.ts index 315fa46f984..3f707142b99 100644 --- a/experimental/packages/otlp-transformer/src/common/internal-types.ts +++ b/experimental/packages/otlp-transformer/src/common/internal-types.ts @@ -71,7 +71,7 @@ export interface IAnyValue { kvlistValue?: IKeyValueList; /** AnyValue bytesValue */ - bytesValue?: Uint8Array; + bytesValue?: Uint8Array | string; } /** Properties of an ArrayValue. */ diff --git a/experimental/packages/otlp-transformer/src/common/internal.ts b/experimental/packages/otlp-transformer/src/common/internal.ts index ba6d394cff0..e7ea8c6a91c 100644 --- a/experimental/packages/otlp-transformer/src/common/internal.ts +++ b/experimental/packages/otlp-transformer/src/common/internal.ts @@ -22,10 +22,14 @@ import type { import { Attributes } from '@opentelemetry/api'; import { InstrumentationScope } from '@opentelemetry/core'; import { Resource as ISdkResource } from '@opentelemetry/resources'; +import type { Encoder } from './utils'; -export function createResource(resource: ISdkResource): Resource { +export function createResource( + resource: ISdkResource, + encoder: Encoder +): Resource { const result: Resource = { - attributes: toAttributes(resource.attributes), + attributes: toAttributes(resource.attributes, encoder), droppedAttributesCount: 0, }; @@ -44,18 +48,27 @@ export function createInstrumentationScope( }; } -export function toAttributes(attributes: Attributes): IKeyValue[] { - return Object.keys(attributes).map(key => toKeyValue(key, attributes[key])); +export function toAttributes( + attributes: Attributes, + encoder: Encoder +): IKeyValue[] { + return Object.keys(attributes).map(key => + toKeyValue(key, attributes[key], encoder) + ); } -export function toKeyValue(key: string, value: unknown): IKeyValue { +export function toKeyValue( + key: string, + value: unknown, + encoder: Encoder +): IKeyValue { return { key: key, - value: toAnyValue(value), + value: toAnyValue(value, encoder), }; } -export function toAnyValue(value: unknown): IAnyValue { +export function toAnyValue(value: unknown, encoder: Encoder): IAnyValue { const t = typeof value; if (t === 'string') return { stringValue: value as string }; if (t === 'number') { @@ -63,11 +76,12 @@ export function toAnyValue(value: unknown): IAnyValue { return { intValue: value as number }; } if (t === 'boolean') return { boolValue: value as boolean }; - if (value instanceof Uint8Array) return { bytesValue: value }; + if (value instanceof Uint8Array) + return { bytesValue: encoder.encodeUint8Array(value) }; if (Array.isArray(value)) { const values: IAnyValue[] = new Array(value.length); for (let i = 0; i < value.length; i++) { - values[i] = toAnyValue(value[i]); + values[i] = toAnyValue(value[i], encoder); } return { arrayValue: { values } }; } @@ -77,7 +91,7 @@ export function toAnyValue(value: unknown): IAnyValue { for (let i = 0; i < keys.length; i++) { values[i] = { key: keys[i], - value: toAnyValue((value as Record)[keys[i]]), + value: toAnyValue((value as Record)[keys[i]], encoder), }; } return { kvlistValue: { values } }; diff --git a/experimental/packages/otlp-transformer/src/common/utils.ts b/experimental/packages/otlp-transformer/src/common/utils.ts index f4f8cb65e41..3fdf17d2956 100644 --- a/experimental/packages/otlp-transformer/src/common/utils.ts +++ b/experimental/packages/otlp-transformer/src/common/utils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { OtlpEncodingOptions, Fixed64, LongBits } from './internal-types'; +import type { Fixed64, LongBits } from './internal-types'; import { HrTime } from '@opentelemetry/api'; import { hrTimeToNanoseconds } from '@opentelemetry/core'; import { hexToBinary } from './hex-to-binary'; @@ -52,11 +52,15 @@ export type SpanContextEncodeFunction = ( export type OptionalSpanContextEncodeFunction = ( spanContext: string | undefined ) => string | Uint8Array | undefined; +export type Uint8ArrayEncodeFunction = ( + value: Uint8Array +) => string | Uint8Array; export interface Encoder { encodeHrTime: HrTimeEncodeFunction; encodeSpanContext: SpanContextEncodeFunction; encodeOptionalSpanContext: OptionalSpanContextEncodeFunction; + encodeUint8Array: Uint8ArrayEncodeFunction; } function identity(value: T): T { @@ -68,22 +72,36 @@ function optionalHexToBinary(str: string | undefined): Uint8Array | undefined { return hexToBinary(str); } -const DEFAULT_ENCODER: Encoder = { +/** + * Encoder for protobuf format. + * Uses { high, low } timestamps and binary for span/trace IDs, leaves Uint8Array attributes as-is. + */ +export const PROTOBUF_ENCODER: Encoder = { encodeHrTime: encodeAsLongBits, encodeSpanContext: hexToBinary, encodeOptionalSpanContext: optionalHexToBinary, + encodeUint8Array: identity, }; -export function getOtlpEncoder(options?: OtlpEncodingOptions): Encoder { - if (options === undefined) { - return DEFAULT_ENCODER; - } +/** + * Encoder for JSON format. + * Uses string timestamps, hex for span/trace IDs, and base64 for Uint8Array. + */ +export const JSON_ENCODER: Encoder = { + encodeHrTime: encodeTimestamp, + encodeSpanContext: identity, + encodeOptionalSpanContext: identity, + encodeUint8Array: (bytes: Uint8Array): string => { + if (typeof Buffer !== 'undefined') { + return Buffer.from(bytes).toString('base64'); + } - const useLongBits = options.useLongBits ?? true; - const useHex = options.useHex ?? false; - return { - encodeHrTime: useLongBits ? encodeAsLongBits : encodeTimestamp, - encodeSpanContext: useHex ? identity : hexToBinary, - encodeOptionalSpanContext: useHex ? identity : optionalHexToBinary, - }; -} + // implementation note: not using spread operator and passing to + // btoa to avoid stack overflow on large Uint8Arrays + const chars = new Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + chars[i] = String.fromCharCode(bytes[i]); + } + return btoa(chars.join('')); + }, +}; diff --git a/experimental/packages/otlp-transformer/src/logs/internal.ts b/experimental/packages/otlp-transformer/src/logs/internal.ts index 510206d37c9..b6623d05295 100644 --- a/experimental/packages/otlp-transformer/src/logs/internal.ts +++ b/experimental/packages/otlp-transformer/src/logs/internal.ts @@ -22,7 +22,7 @@ import { IResourceLogs, } from './internal-types'; import { Resource } from '@opentelemetry/resources'; -import { Encoder, getOtlpEncoder } from '../common/utils'; +import { Encoder } from '../common/utils'; import { createInstrumentationScope, createResource, @@ -30,14 +30,13 @@ import { toKeyValue, } from '../common/internal'; import { SeverityNumber } from '@opentelemetry/api-logs'; -import { OtlpEncodingOptions, IKeyValue } from '../common/internal-types'; +import { IKeyValue } from '../common/internal-types'; import { LogAttributes } from '@opentelemetry/api-logs'; export function createExportLogsServiceRequest( logRecords: ReadableLogRecord[], - options?: OtlpEncodingOptions + encoder: Encoder ): IExportLogsServiceRequest { - const encoder = getOtlpEncoder(options); return { resourceLogs: logRecordsToResourceLogs(logRecords, encoder), }; @@ -80,7 +79,7 @@ function logRecordsToResourceLogs( ): IResourceLogs[] { const resourceMap = createResourceMap(logRecords); return Array.from(resourceMap, ([resource, ismMap]) => { - const processedResource = createResource(resource); + const processedResource = createResource(resource, encoder); return { resource: processedResource, scopeLogs: Array.from(ismMap, ([, scopeLogs]) => { @@ -101,9 +100,9 @@ function toLogRecord(log: ReadableLogRecord, encoder: Encoder): ILogRecord { observedTimeUnixNano: encoder.encodeHrTime(log.hrTimeObserved), severityNumber: toSeverityNumber(log.severityNumber), severityText: log.severityText, - body: toAnyValue(log.body), + body: toAnyValue(log.body, encoder), eventName: log.eventName, - attributes: toLogAttributes(log.attributes), + attributes: toLogAttributes(log.attributes, encoder), droppedAttributesCount: log.droppedAttributesCount, flags: log.spanContext?.traceFlags, traceId: encoder.encodeOptionalSpanContext(log.spanContext?.traceId), @@ -117,6 +116,11 @@ function toSeverityNumber( return severityNumber as number | undefined as ESeverityNumber | undefined; } -export function toLogAttributes(attributes: LogAttributes): IKeyValue[] { - return Object.keys(attributes).map(key => toKeyValue(key, attributes[key])); +export function toLogAttributes( + attributes: LogAttributes, + encoder: Encoder +): IKeyValue[] { + return Object.keys(attributes).map(key => + toKeyValue(key, attributes[key], encoder) + ); } diff --git a/experimental/packages/otlp-transformer/src/logs/json/logs.ts b/experimental/packages/otlp-transformer/src/logs/json/logs.ts index 11c1e4910ae..53a1e1c05ce 100644 --- a/experimental/packages/otlp-transformer/src/logs/json/logs.ts +++ b/experimental/packages/otlp-transformer/src/logs/json/logs.ts @@ -17,6 +17,7 @@ import { ISerializer } from '../../i-serializer'; import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; import { createExportLogsServiceRequest } from '../internal'; import { IExportLogsServiceResponse } from '../export-response'; +import { JSON_ENCODER } from '../../common/utils'; /* * @experimental this serializer may receive breaking changes in minor versions, pin this package's version when using this constant @@ -26,10 +27,7 @@ export const JsonLogsSerializer: ISerializer< IExportLogsServiceResponse > = { serializeRequest: (arg: ReadableLogRecord[]) => { - const request = createExportLogsServiceRequest(arg, { - useHex: true, - useLongBits: false, - }); + const request = createExportLogsServiceRequest(arg, JSON_ENCODER); const encoder = new TextEncoder(); return encoder.encode(JSON.stringify(request)); }, diff --git a/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts b/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts index a5b32453b68..5c6f7631d5e 100644 --- a/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts +++ b/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts @@ -22,6 +22,7 @@ import { createExportLogsServiceRequest } from '../internal'; import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; import { ExportType } from '../../common/protobuf/protobuf-export-type'; import { ISerializer } from '../../i-serializer'; +import { PROTOBUF_ENCODER } from '../../common/utils'; const logsResponseType = root.opentelemetry.proto.collector.logs.v1 .ExportLogsServiceResponse as ExportType; @@ -37,7 +38,7 @@ export const ProtobufLogsSerializer: ISerializer< IExportLogsServiceResponse > = { serializeRequest: (arg: ReadableLogRecord[]) => { - const request = createExportLogsServiceRequest(arg); + const request = createExportLogsServiceRequest(arg, PROTOBUF_ENCODER); return logsRequestType.encode(request).finish(); }, deserializeResponse: (arg: Uint8Array) => { diff --git a/experimental/packages/otlp-transformer/src/metrics/internal.ts b/experimental/packages/otlp-transformer/src/metrics/internal.ts index 50feb9c60fa..c3c9fa9eb00 100644 --- a/experimental/packages/otlp-transformer/src/metrics/internal.ts +++ b/experimental/packages/otlp-transformer/src/metrics/internal.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { OtlpEncodingOptions } from '../common/internal-types'; import { ValueType } from '@opentelemetry/api'; import { AggregationTemporality, @@ -35,7 +34,7 @@ import { IResourceMetrics, IScopeMetrics, } from './internal-types'; -import { Encoder, getOtlpEncoder } from '../common/utils'; +import { Encoder } from '../common/utils'; import { createInstrumentationScope, createResource, @@ -44,10 +43,9 @@ import { export function toResourceMetrics( resourceMetrics: ResourceMetrics, - options?: OtlpEncodingOptions + encoder: Encoder ): IResourceMetrics { - const encoder = getOtlpEncoder(options); - const processedResource = createResource(resourceMetrics.resource); + const processedResource = createResource(resourceMetrics.resource, encoder); return { resource: processedResource, schemaUrl: processedResource.schemaUrl, @@ -118,7 +116,7 @@ function toSingularDataPoint( encoder: Encoder ) { const out: INumberDataPoint = { - attributes: toAttributes(dataPoint.attributes), + attributes: toAttributes(dataPoint.attributes, encoder), startTimeUnixNano: encoder.encodeHrTime(dataPoint.startTime), timeUnixNano: encoder.encodeHrTime(dataPoint.endTime), }; @@ -155,7 +153,7 @@ function toHistogramDataPoints( return metricData.dataPoints.map(dataPoint => { const histogram = dataPoint.value as Histogram; return { - attributes: toAttributes(dataPoint.attributes), + attributes: toAttributes(dataPoint.attributes, encoder), bucketCounts: histogram.buckets.counts, explicitBounds: histogram.buckets.boundaries, count: histogram.count, @@ -175,7 +173,7 @@ function toExponentialHistogramDataPoints( return metricData.dataPoints.map(dataPoint => { const histogram = dataPoint.value as ExponentialHistogram; return { - attributes: toAttributes(dataPoint.attributes), + attributes: toAttributes(dataPoint.attributes, encoder), count: histogram.count, min: histogram.min, max: histogram.max, @@ -209,11 +207,11 @@ function toAggregationTemporality( export function createExportMetricsServiceRequest( resourceMetrics: ResourceMetrics[], - options?: OtlpEncodingOptions + encoder: Encoder ): IExportMetricsServiceRequest { return { resourceMetrics: resourceMetrics.map(metrics => - toResourceMetrics(metrics, options) + toResourceMetrics(metrics, encoder) ), }; } diff --git a/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts b/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts index 85243ab1b1a..983aedfa4c6 100644 --- a/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts +++ b/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts @@ -17,15 +17,14 @@ import { ISerializer } from '../../i-serializer'; import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { createExportMetricsServiceRequest } from '../internal'; import { IExportMetricsServiceResponse } from '../export-response'; +import { JSON_ENCODER } from '../../common/utils'; export const JsonMetricsSerializer: ISerializer< ResourceMetrics, IExportMetricsServiceResponse > = { serializeRequest: (arg: ResourceMetrics) => { - const request = createExportMetricsServiceRequest([arg], { - useLongBits: false, - }); + const request = createExportMetricsServiceRequest([arg], JSON_ENCODER); const encoder = new TextEncoder(); return encoder.encode(JSON.stringify(request)); }, diff --git a/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts b/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts index ee21ca93eb2..bdce862a6d3 100644 --- a/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts +++ b/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts @@ -21,6 +21,7 @@ import { ExportType } from '../../common/protobuf/protobuf-export-type'; import { createExportMetricsServiceRequest } from '../internal'; import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; import { IExportMetricsServiceResponse } from '../export-response'; +import { PROTOBUF_ENCODER } from '../../common/utils'; const metricsResponseType = root.opentelemetry.proto.collector.metrics.v1 .ExportMetricsServiceResponse as ExportType; @@ -33,7 +34,7 @@ export const ProtobufMetricsSerializer: ISerializer< IExportMetricsServiceResponse > = { serializeRequest: (arg: ResourceMetrics) => { - const request = createExportMetricsServiceRequest([arg]); + const request = createExportMetricsServiceRequest([arg], PROTOBUF_ENCODER); return metricsRequestType.encode(request).finish(); }, deserializeResponse: (arg: Uint8Array) => { diff --git a/experimental/packages/otlp-transformer/src/trace/internal.ts b/experimental/packages/otlp-transformer/src/trace/internal.ts index cccd56eb9db..f0c04ba3df9 100644 --- a/experimental/packages/otlp-transformer/src/trace/internal.ts +++ b/experimental/packages/otlp-transformer/src/trace/internal.ts @@ -31,8 +31,6 @@ import { IScopeSpans, ISpan, } from './internal-types'; -import { OtlpEncodingOptions } from '../common/internal-types'; -import { getOtlpEncoder } from '../common/utils'; // Span flags constants matching the OTLP specification const SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK = 0x100; @@ -67,7 +65,7 @@ export function sdkSpanToOtlpSpan(span: ReadableSpan, encoder: Encoder): ISpan { kind: span.kind == null ? 0 : span.kind + 1, startTimeUnixNano: encoder.encodeHrTime(span.startTime), endTimeUnixNano: encoder.encodeHrTime(span.endTime), - attributes: toAttributes(span.attributes), + attributes: toAttributes(span.attributes, encoder), droppedAttributesCount: span.droppedAttributesCount, events: span.events.map(event => toOtlpSpanEvent(event, encoder)), droppedEventsCount: span.droppedEventsCount, @@ -84,7 +82,7 @@ export function sdkSpanToOtlpSpan(span: ReadableSpan, encoder: Encoder): ISpan { export function toOtlpLink(link: Link, encoder: Encoder): ILink { return { - attributes: link.attributes ? toAttributes(link.attributes) : [], + attributes: link.attributes ? toAttributes(link.attributes, encoder) : [], spanId: encoder.encodeSpanContext(link.context.spanId), traceId: encoder.encodeSpanContext(link.context.traceId), traceState: link.context.traceState?.serialize(), @@ -99,7 +97,7 @@ export function toOtlpSpanEvent( ): IEvent { return { attributes: timedEvent.attributes - ? toAttributes(timedEvent.attributes) + ? toAttributes(timedEvent.attributes, encoder) : [], name: timedEvent.name, timeUnixNano: encoder.encodeHrTime(timedEvent.time), @@ -109,9 +107,8 @@ export function toOtlpSpanEvent( export function createExportTraceServiceRequest( spans: ReadableSpan[], - options?: OtlpEncodingOptions + encoder: Encoder ): IExportTraceServiceRequest { - const encoder = getOtlpEncoder(options); return { resourceSpans: spanRecordsToResourceSpans(spans, encoder), }; @@ -173,7 +170,7 @@ function spanRecordsToResourceSpans( } ilmEntry = ilmIterator.next(); } - const processedResource = createResource(resource); + const processedResource = createResource(resource, encoder); const transformedSpans: IResourceSpans = { resource: processedResource, scopeSpans: scopeResourceSpans, diff --git a/experimental/packages/otlp-transformer/src/trace/json/trace.ts b/experimental/packages/otlp-transformer/src/trace/json/trace.ts index fa15a39f30b..2be15249fee 100644 --- a/experimental/packages/otlp-transformer/src/trace/json/trace.ts +++ b/experimental/packages/otlp-transformer/src/trace/json/trace.ts @@ -17,16 +17,14 @@ import { ISerializer } from '../../i-serializer'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import { IExportTraceServiceResponse } from '../export-response'; import { createExportTraceServiceRequest } from '../internal'; +import { JSON_ENCODER } from '../../common/utils'; export const JsonTraceSerializer: ISerializer< ReadableSpan[], IExportTraceServiceResponse > = { serializeRequest: (arg: ReadableSpan[]) => { - const request = createExportTraceServiceRequest(arg, { - useHex: true, - useLongBits: false, - }); + const request = createExportTraceServiceRequest(arg, JSON_ENCODER); const encoder = new TextEncoder(); return encoder.encode(JSON.stringify(request)); }, diff --git a/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts b/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts index 87d5f481fe0..dc65b35d573 100644 --- a/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts +++ b/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts @@ -21,6 +21,7 @@ import { IExportTraceServiceRequest } from '../internal-types'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import { createExportTraceServiceRequest } from '../internal'; import { IExportTraceServiceResponse } from '../export-response'; +import { PROTOBUF_ENCODER } from '../../common/utils'; const traceResponseType = root.opentelemetry.proto.collector.trace.v1 .ExportTraceServiceResponse as ExportType; @@ -33,7 +34,7 @@ export const ProtobufTraceSerializer: ISerializer< IExportTraceServiceResponse > = { serializeRequest: (arg: ReadableSpan[]) => { - const request = createExportTraceServiceRequest(arg); + const request = createExportTraceServiceRequest(arg, PROTOBUF_ENCODER); return traceRequestType.encode(request).finish(); }, deserializeResponse: (arg: Uint8Array) => { diff --git a/experimental/packages/otlp-transformer/test/common.test.ts b/experimental/packages/otlp-transformer/test/common.test.ts index 38444c48914..ed9bc0878b7 100644 --- a/experimental/packages/otlp-transformer/test/common.test.ts +++ b/experimental/packages/otlp-transformer/test/common.test.ts @@ -16,23 +16,22 @@ import { toAnyValue } from '../src/common/internal'; import * as assert from 'assert'; -import { getOtlpEncoder } from '../src/common/utils'; -import { hexToBinary } from '../src/common/hex-to-binary'; - -const traceId = 'abcdef01234567890000000000000000'; -const spanId = '12341234abcdabcd'; +import { PROTOBUF_ENCODER } from '../src/common/utils'; describe('common', () => { describe('toAnyValue', () => { it('serializes an array', () => { - const anyValue = toAnyValue([ - 1, - 'two', - false, - 2.5, - new Uint8Array([0, 1, 2]), - { somekey: 'somevalue' }, - ]); + const anyValue = toAnyValue( + [ + 1, + 'two', + false, + 2.5, + new Uint8Array([0, 1, 2]), + { somekey: 'somevalue' }, + ], + PROTOBUF_ENCODER + ); assert.deepStrictEqual(anyValue, { arrayValue: { values: [ @@ -68,64 +67,4 @@ describe('common', () => { }); }); }); - - describe('otlp encoder', () => { - it('defaults to long timestamps and binary encoding given no options', () => { - const encoder = getOtlpEncoder(); - assert.deepStrictEqual(encoder.encodeHrTime([1697978649, 99870675]), { - low: 3352011219, - high: 395341461, - }); - assert.deepStrictEqual( - encoder.encodeSpanContext(traceId), - hexToBinary(traceId) - ); - assert.deepStrictEqual( - encoder.encodeOptionalSpanContext(spanId), - hexToBinary(spanId) - ); - assert.deepStrictEqual( - encoder.encodeOptionalSpanContext(undefined), - undefined - ); - }); - - it('defaults to long timestamps and base64 encoding given empty options', () => { - const encoder = getOtlpEncoder({}); - assert.deepStrictEqual(encoder.encodeHrTime([1697978649, 99870675]), { - low: 3352011219, - high: 395341461, - }); - assert.deepStrictEqual( - encoder.encodeSpanContext(traceId), - hexToBinary(traceId) - ); - assert.deepStrictEqual( - encoder.encodeOptionalSpanContext(spanId), - hexToBinary(spanId) - ); - assert.deepStrictEqual( - encoder.encodeOptionalSpanContext(undefined), - undefined - ); - }); - - it('can encode HrTime as string', () => { - const encoder = getOtlpEncoder({ useLongBits: false }); - assert.deepStrictEqual( - encoder.encodeHrTime([1697978649, 99870675]), - '1697978649099870675' - ); - }); - - it('can encode span context as hex', () => { - const encoder = getOtlpEncoder({ useHex: true }); - assert.deepStrictEqual(encoder.encodeSpanContext(traceId), traceId); - assert.deepStrictEqual(encoder.encodeOptionalSpanContext(spanId), spanId); - assert.deepStrictEqual( - encoder.encodeOptionalSpanContext(undefined), - undefined - ); - }); - }); }); diff --git a/experimental/packages/otlp-transformer/test/logs.test.ts b/experimental/packages/otlp-transformer/test/logs.test.ts index 4ddd4ff3b45..db7ea3aa190 100644 --- a/experimental/packages/otlp-transformer/test/logs.test.ts +++ b/experimental/packages/otlp-transformer/test/logs.test.ts @@ -19,9 +19,9 @@ import { Resource, resourceFromAttributes } from '@opentelemetry/resources'; import * as assert from 'assert'; import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; import { SeverityNumber } from '@opentelemetry/api-logs'; +import { JSON_ENCODER, PROTOBUF_ENCODER, Encoder } from '../src/common/utils'; import { toBase64 } from './utils'; import * as root from '../src/generated/root'; -import { OtlpEncodingOptions } from '../src/common/internal-types'; import { ESeverityNumber, IExportLogsServiceRequest, @@ -29,25 +29,17 @@ import { import { createExportLogsServiceRequest } from '../src/logs/internal'; import { ProtobufLogsSerializer } from '../src/logs/protobuf'; import { JsonLogsSerializer } from '../src/logs/json'; -import { hexToBinary } from '../src/common/hex-to-binary'; - -function createExpectedLogJson( - options: OtlpEncodingOptions -): IExportLogsServiceRequest { - const useHex = options.useHex ?? false; - const useLongBits = options.useLongBits ?? true; - - const timeUnixNano = useLongBits - ? { low: 4132445859, high: 391214506 } - : '1680253513123241635'; - const observedTimeUnixNano = useLongBits - ? { low: 584929536, high: 391976663 } - : '1683526948965142784'; - - const traceId = useHex - ? '00000000000000000000000000000001' - : hexToBinary('00000000000000000000000000000001'); - const spanId = useHex ? '0000000000000002' : hexToBinary('0000000000000002'); + +function createExpectedLogJson(encoder: Encoder): IExportLogsServiceRequest { + const timeUnixNano = encoder.encodeHrTime([1680253513, 123241635]); + const observedTimeUnixNano = encoder.encodeHrTime([1683526948, 965142784]); + + const traceId = encoder.encodeSpanContext('00000000000000000000000000000001'); + const spanId = encoder.encodeSpanContext('0000000000000002'); + + // Encode Uint8Array test bytes + const testBytes = new Uint8Array([1, 2, 3, 4, 5]); + const bytesValue = encoder.encodeUint8Array(testBytes); return { resourceLogs: [ @@ -82,6 +74,10 @@ function createExpectedLogJson( key: 'some-attribute', value: { stringValue: 'some attribute value' }, }, + { + key: 'bytes-attribute', + value: { bytesValue: bytesValue }, + }, ], droppedAttributesCount: 0, flags: 1, @@ -101,6 +97,12 @@ function createExpectedLogProtobuf(): IExportLogsServiceRequest { const traceId = toBase64('00000000000000000000000000000001'); const spanId = toBase64('0000000000000002'); + // Base64 encoding of Uint8Array([1, 2, 3, 4, 5]) + // Note: protobuf serializer encodes as binary. However, when decoding, with protobuf.js + // we use `bytes: String`, as otherwise the type will be different for Node.js (Buffer) and Browser (Uint8Array) + // which makes assertions overly complex. + const bytesValue = 'AQIDBAU='; + return { resourceLogs: [ { @@ -129,6 +131,10 @@ function createExpectedLogProtobuf(): IExportLogsServiceRequest { key: 'some-attribute', value: { stringValue: 'some attribute value' }, }, + { + key: 'bytes-attribute', + value: { bytesValue: bytesValue }, + }, ], droppedAttributesCount: 0, flags: 1, @@ -152,6 +158,7 @@ const DEFAULT_LOG_FRAGMENT: Omit< hrTimeObserved: [1683526948, 965142784] as HrTime, attributes: { 'some-attribute': 'some attribute value', + 'bytes-attribute': new Uint8Array([1, 2, 3, 4, 5]), }, droppedAttributesCount: 0, severityNumber: SeverityNumber.ERROR, @@ -233,40 +240,39 @@ describe('Logs', () => { describe('createExportLogsServiceRequest', () => { it('returns null on an empty list', () => { - assert.deepStrictEqual( - createExportLogsServiceRequest([], { useHex: true }), - { - resourceLogs: [], - } - ); + assert.deepStrictEqual(createExportLogsServiceRequest([], JSON_ENCODER), { + resourceLogs: [], + }); }); it('serializes a log record with useHex = true', () => { - const exportRequest = createExportLogsServiceRequest([log_1_1_1], { - useHex: true, - }); + const exportRequest = createExportLogsServiceRequest( + [log_1_1_1], + JSON_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual( exportRequest, - createExpectedLogJson({ useHex: true }) + createExpectedLogJson(JSON_ENCODER) ); }); it('serializes a log record with useHex = false', () => { - const exportRequest = createExportLogsServiceRequest([log_1_1_1], { - useHex: false, - }); + const exportRequest = createExportLogsServiceRequest( + [log_1_1_1], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual( exportRequest, - createExpectedLogJson({ useHex: false }) + createExpectedLogJson(PROTOBUF_ENCODER) ); }); it('aggregates multiple logs with same resource and same scope', () => { const exportRequest = createExportLogsServiceRequest( [log_1_1_1, log_1_1_2], - { useHex: false } + PROTOBUF_ENCODER ); assert.ok(exportRequest); assert.strictEqual(exportRequest.resourceLogs?.length, 1); @@ -280,7 +286,7 @@ describe('Logs', () => { it('aggregates multiple logs with same resource and different scopes', () => { const exportRequest = createExportLogsServiceRequest( [log_1_1_1, log_1_2_1], - { useHex: false } + PROTOBUF_ENCODER ); assert.ok(exportRequest); assert.strictEqual(exportRequest.resourceLogs?.length, 1); @@ -290,7 +296,7 @@ describe('Logs', () => { it('aggregates multiple logs with different resources', () => { const exportRequest = createExportLogsServiceRequest( [log_1_1_1, log_2_1_1], - { useHex: false } + PROTOBUF_ENCODER ); assert.ok(exportRequest); assert.strictEqual(exportRequest.resourceLogs?.length, 2); @@ -308,9 +314,10 @@ describe('Logs', () => { DEFAULT_LOG_FRAGMENT ); - const exportRequest = createExportLogsServiceRequest([logWithSchema], { - useHex: true, - }); + const exportRequest = createExportLogsServiceRequest( + [logWithSchema], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual(exportRequest.resourceLogs?.length, 1); @@ -319,6 +326,22 @@ describe('Logs', () => { 'https://opentelemetry.test/schemas/1.2.3' ); }); + + it('encodes Uint8Array to base64 when used with JSON_ENCODER', () => { + const exportRequest = createExportLogsServiceRequest( + [log_1_1_1], + JSON_ENCODER + ); + assert.ok(exportRequest); + const bytesAttr = + exportRequest.resourceLogs?.[0].scopeLogs[0].logRecords?.[0].attributes?.find( + attr => attr.key === 'bytes-attribute' + ); + assert.ok(bytesAttr, 'bytes-attribute not found'); + // JSON_ENCODER should encode Uint8Array as base64 string in bytesValue + assert.strictEqual(bytesAttr.value.bytesValue, 'AQIDBAU='); + assert.strictEqual(bytesAttr.value.stringValue, undefined); + }); }); describe('ProtobufLogsSerializer', function () { @@ -385,14 +408,14 @@ describe('Logs', () => { it('serializes an export request', () => { // stringify, then parse to remove undefined keys in the expected JSON const expected = JSON.parse( - JSON.stringify( - createExpectedLogJson({ useHex: true, useLongBits: false }) - ) + JSON.stringify(createExpectedLogJson(JSON_ENCODER)) ); const serialized = JsonLogsSerializer.serializeRequest([log_1_1_1]); const decoder = new TextDecoder(); - assert.deepStrictEqual(JSON.parse(decoder.decode(serialized)), expected); + const actual = JSON.parse(decoder.decode(serialized)); + + assert.deepStrictEqual(actual, expected); }); it('deserializes a response', () => { diff --git a/experimental/packages/otlp-transformer/test/metrics.test.ts b/experimental/packages/otlp-transformer/test/metrics.test.ts index ffd100febb3..80a9317f9e1 100644 --- a/experimental/packages/otlp-transformer/test/metrics.test.ts +++ b/experimental/packages/otlp-transformer/test/metrics.test.ts @@ -24,9 +24,13 @@ import { import * as assert from 'assert'; import { createExportMetricsServiceRequest } from '../src/metrics/internal'; import { EAggregationTemporality } from '../src/metrics/internal-types'; +import { + PROTOBUF_ENCODER, + encodeAsLongBits, + encodeAsString, +} from '../src/common/utils'; import { hrTime, hrTimeToNanoseconds } from '@opentelemetry/core'; import * as root from '../src/generated/root'; -import { encodeAsLongBits, encodeAsString } from '../src/common/utils'; import { ProtobufMetricsSerializer } from '../src/metrics/protobuf'; import { JsonMetricsSerializer } from '../src/metrics/json'; @@ -331,7 +335,10 @@ describe('Metrics', () => { const metrics = createResourceMetrics([ createCounterData(10, AggregationTemporality.DELTA), ]); - const exportRequest = createExportMetricsServiceRequest([metrics]); + const exportRequest = createExportMetricsServiceRequest( + [metrics], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -374,7 +381,10 @@ describe('Metrics', () => { const metrics = createResourceMetrics([ createUpDownCounterData(10, AggregationTemporality.DELTA), ]); - const exportRequest = createExportMetricsServiceRequest([metrics]); + const exportRequest = createExportMetricsServiceRequest( + [metrics], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -414,11 +424,14 @@ describe('Metrics', () => { }); it('serializes an observable monotonic sum metric record', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([ - createObservableCounterData(10, AggregationTemporality.DELTA), - ]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [ + createResourceMetrics([ + createObservableCounterData(10, AggregationTemporality.DELTA), + ]), + ], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -458,11 +471,14 @@ describe('Metrics', () => { }); it('serializes an observable non-monotonic sum metric record', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([ - createObservableUpDownCounterData(10, AggregationTemporality.DELTA), - ]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [ + createResourceMetrics([ + createObservableUpDownCounterData(10, AggregationTemporality.DELTA), + ]), + ], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -502,9 +518,10 @@ describe('Metrics', () => { }); it('serializes a gauge metric record', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([createObservableGaugeData(10.5)]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [createResourceMetrics([createObservableGaugeData(10.5)])], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -542,19 +559,22 @@ describe('Metrics', () => { describe('serializes a histogram metric record', () => { it('with min/max', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([ - createHistogramMetrics( - 2, - 9, - [5], - [1, 1], - AggregationTemporality.CUMULATIVE, - 1, - 8 - ), - ]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [ + createResourceMetrics([ + createHistogramMetrics( + 2, + 9, + [5], + [1, 1], + AggregationTemporality.CUMULATIVE, + 1, + 8 + ), + ]), + ], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -598,17 +618,20 @@ describe('Metrics', () => { }); it('without min/max', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([ - createHistogramMetrics( - 2, - 9, - [5], - [1, 1], - AggregationTemporality.CUMULATIVE - ), - ]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [ + createResourceMetrics([ + createHistogramMetrics( + 2, + 9, + [5], + [1, 1], + AggregationTemporality.CUMULATIVE + ), + ]), + ], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual(exportRequest, { @@ -654,21 +677,24 @@ describe('Metrics', () => { describe('serializes an exponential histogram metric record', () => { it('with min/max', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([ - createExponentialHistogramMetrics( - 3, - 10, - 1, - 0, - { offset: 0, bucketCounts: [1, 0, 0, 0, 1, 0, 1, 0] }, - { offset: 0, bucketCounts: [0] }, - AggregationTemporality.CUMULATIVE, - 1, - 8 - ), - ]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [ + createResourceMetrics([ + createExponentialHistogramMetrics( + 3, + 10, + 1, + 0, + { offset: 0, bucketCounts: [1, 0, 0, 0, 1, 0, 1, 0] }, + { offset: 0, bucketCounts: [0] }, + AggregationTemporality.CUMULATIVE, + 1, + 8 + ), + ]), + ], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); @@ -718,19 +744,22 @@ describe('Metrics', () => { }); it('without min/max', () => { - const exportRequest = createExportMetricsServiceRequest([ - createResourceMetrics([ - createExponentialHistogramMetrics( - 3, - 10, - 1, - 0, - { offset: 0, bucketCounts: [1, 0, 0, 0, 1, 0, 1, 0] }, - { offset: 0, bucketCounts: [0] }, - AggregationTemporality.CUMULATIVE - ), - ]), - ]); + const exportRequest = createExportMetricsServiceRequest( + [ + createResourceMetrics([ + createExponentialHistogramMetrics( + 3, + 10, + 1, + 0, + { offset: 0, bucketCounts: [1, 0, 0, 0, 1, 0, 1, 0] }, + { offset: 0, bucketCounts: [0] }, + AggregationTemporality.CUMULATIVE + ), + ]), + ], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); @@ -791,9 +820,10 @@ describe('Metrics', () => { resourceWithSchema ); - const exportRequest = createExportMetricsServiceRequest([ - resourceMetrics, - ]); + const exportRequest = createExportMetricsServiceRequest( + [resourceMetrics], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.strictEqual(exportRequest.resourceMetrics?.length, 1); diff --git a/experimental/packages/otlp-transformer/test/performance/benchmark/toAnyValue.js b/experimental/packages/otlp-transformer/test/performance/benchmark/toAnyValue.js index 4d16b1dc6a1..263ff813d67 100644 --- a/experimental/packages/otlp-transformer/test/performance/benchmark/toAnyValue.js +++ b/experimental/packages/otlp-transformer/test/performance/benchmark/toAnyValue.js @@ -16,6 +16,7 @@ const Benchmark = require('benchmark'); const { toAnyValue } = require('../../../build/src/common/internal'); +const { JSON_ENCODER } = require('../../../build/src/common/utils'); const suite = new Benchmark.Suite(); @@ -23,6 +24,10 @@ suite.on('cycle', event => { console.log(String(event.target)); }); +suite.add('toAnyValue Uint8Array (JSON)', function () { + toAnyValue(new Uint8Array([1, 2, 3, 4, 5]), JSON_ENCODER); +}); + suite.add('toAnyValue string', function () { toAnyValue('test-string-value'); }); diff --git a/experimental/packages/otlp-transformer/test/trace.test.ts b/experimental/packages/otlp-transformer/test/trace.test.ts index 5a1aaf13a23..0895873cec9 100644 --- a/experimental/packages/otlp-transformer/test/trace.test.ts +++ b/experimental/packages/otlp-transformer/test/trace.test.ts @@ -27,6 +27,7 @@ import { ProtobufTraceSerializer } from '../src/trace/protobuf'; import { JsonTraceSerializer } from '../src/trace/json'; import { hexToBinary } from '../src/common/hex-to-binary'; import { ISpan } from '../src/trace/internal-types'; +import { JSON_ENCODER, PROTOBUF_ENCODER } from '../src/common/utils'; function createExpectedSpanJson(options: OtlpEncodingOptions) { const useHex = options.useHex ?? false; @@ -305,28 +306,30 @@ describe('Trace', () => { describe('createExportTraceServiceRequest', () => { it('returns null on an empty list', () => { assert.deepStrictEqual( - createExportTraceServiceRequest([], { useHex: true }), + createExportTraceServiceRequest([], JSON_ENCODER), { resourceSpans: [], } ); }); - it('serializes a span with useHex = true', () => { - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + it('serializes a span with json encoder', () => { + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual( exportRequest, - createExpectedSpanJson({ useHex: true }) + createExpectedSpanJson({ useHex: true, useLongBits: false }) ); }); - it('serializes a span with useHex = false', () => { - const exportRequest = createExportTraceServiceRequest([span], { - useHex: false, - }); + it('serializes a span with protobuf encoder', () => { + const exportRequest = createExportTraceServiceRequest( + [span], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.deepStrictEqual( exportRequest, @@ -335,17 +338,23 @@ describe('Trace', () => { }); it('serializes a span with string timestamps', () => { - const options: OtlpEncodingOptions = { useLongBits: false }; - const exportRequest = createExportTraceServiceRequest([span], options); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); - assert.deepStrictEqual(exportRequest, createExpectedSpanJson(options)); + assert.deepStrictEqual( + exportRequest, + createExpectedSpanJson({ useLongBits: false, useHex: true }) + ); }); it('serializes a span without a parent with useHex = true', () => { (span as any).parentSpanContext.spanId = undefined; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( (exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0] as ISpan) @@ -356,9 +365,10 @@ describe('Trace', () => { it('serializes a span without a parent with useHex = false', () => { (span as any).parentSpanContext.spanId = undefined; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: false, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + PROTOBUF_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( (exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0] as ISpan) @@ -371,9 +381,10 @@ describe('Trace', () => { it('error', () => { span.status.code = SpanStatusCode.ERROR; span.status.message = 'error message'; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); const spanStatus = exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].status; @@ -383,9 +394,10 @@ describe('Trace', () => { it('unset', () => { span.status.code = SpanStatusCode.UNSET; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].status.code, @@ -397,9 +409,10 @@ describe('Trace', () => { describe('span kind', () => { it('consumer', () => { (span as any).kind = SpanKind.CONSUMER; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind, @@ -408,9 +421,10 @@ describe('Trace', () => { }); it('internal', () => { (span as any).kind = SpanKind.INTERNAL; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind, @@ -419,9 +433,10 @@ describe('Trace', () => { }); it('producer', () => { (span as any).kind = SpanKind.PRODUCER; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind, @@ -430,9 +445,10 @@ describe('Trace', () => { }); it('server', () => { (span as any).kind = SpanKind.SERVER; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind, @@ -441,9 +457,10 @@ describe('Trace', () => { }); it('unspecified', () => { (span as any).kind = undefined; - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual( exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].kind, @@ -460,9 +477,10 @@ describe('Trace', () => { const spanFromSDK = createSpanWithResource(resourceWithSchema); - const exportRequest = createExportTraceServiceRequest([spanFromSDK], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [spanFromSDK], + JSON_ENCODER + ); assert.ok(exportRequest); assert.strictEqual(exportRequest.resourceSpans?.length, 1); @@ -587,9 +605,10 @@ describe('Trace', () => { describe('span flags', () => { it('sets flags to 0x101 for local parent span context', () => { - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); const spanFlags = exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].flags; @@ -612,9 +631,7 @@ describe('Trace', () => { const exportRequest = createExportTraceServiceRequest( [spanWithRemoteParent], - { - useHex: true, - } + JSON_ENCODER ); assert.ok(exportRequest); const spanFlags = @@ -623,9 +640,10 @@ describe('Trace', () => { }); it('sets flags to 0x101 for links with local context', () => { - const exportRequest = createExportTraceServiceRequest([span], { - useHex: true, - }); + const exportRequest = createExportTraceServiceRequest( + [span], + JSON_ENCODER + ); assert.ok(exportRequest); const linkFlags = exportRequest.resourceSpans?.[0].scopeSpans[0].spans?.[0].links?.[0] @@ -655,9 +673,7 @@ describe('Trace', () => { const exportRequest = createExportTraceServiceRequest( [spanWithRemoteLink], - { - useHex: true, - } + JSON_ENCODER ); assert.ok(exportRequest); const linkFlags = @@ -693,9 +709,10 @@ describe('Trace', () => { isRemote: false, }, } as unknown as ReadableSpan; - const reqLocal = createExportTraceServiceRequest([spanLocal], { - useHex: true, - }); + const reqLocal = createExportTraceServiceRequest( + [spanLocal], + JSON_ENCODER + ); const spanFlagsLocal = reqLocal.resourceSpans?.[0].scopeSpans[0].spans?.[0].flags; assert.strictEqual(spanFlagsLocal, c.local); @@ -708,9 +725,10 @@ describe('Trace', () => { isRemote: true, }, } as unknown as ReadableSpan; - const reqRemote = createExportTraceServiceRequest([spanRemote], { - useHex: true, - }); + const reqRemote = createExportTraceServiceRequest( + [spanRemote], + JSON_ENCODER + ); const spanFlagsRemote = reqRemote.resourceSpans?.[0].scopeSpans[0].spans?.[0].flags; assert.strictEqual(spanFlagsRemote, c.remote); @@ -734,9 +752,10 @@ describe('Trace', () => { ...span, links: [linkLocal], } as unknown as ReadableSpan; - const reqLocal = createExportTraceServiceRequest([spanWithLocalLink], { - useHex: true, - }); + const reqLocal = createExportTraceServiceRequest( + [spanWithLocalLink], + JSON_ENCODER + ); const linkFlagsLocal = reqLocal.resourceSpans?.[0].scopeSpans[0].spans?.[0].links?.[0].flags; assert.strictEqual(linkFlagsLocal, c.local); @@ -751,7 +770,7 @@ describe('Trace', () => { } as unknown as ReadableSpan; const reqRemote = createExportTraceServiceRequest( [spanWithRemoteLink], - { useHex: true } + JSON_ENCODER ); const linkFlagsRemote = reqRemote.resourceSpans?.[0].scopeSpans[0].spans?.[0].links?.[0] @@ -774,9 +793,7 @@ describe('Trace', () => { }), parentSpanContext: undefined, } as unknown as ReadableSpan; - const req = createExportTraceServiceRequest([rootSpan], { - useHex: true, - }); + const req = createExportTraceServiceRequest([rootSpan], JSON_ENCODER); const flags = req.resourceSpans?.[0].scopeSpans[0].spans?.[0].flags; assert.strictEqual(flags, c.local); } diff --git a/karma.base.js b/karma.base.js index 2af28693688..c8d3a7f83d5 100644 --- a/karma.base.js +++ b/karma.base.js @@ -22,7 +22,7 @@ module.exports = { coverageReporter: { type : 'json', subdir: '.', - dir : '.nyc_output/' + dir : 'coverage/' }, reporters: ['spec', 'coverage'], files: ['test/index-webpack.ts'],