From 5ad61ec9490bea86b4ef5f3d98c417790e20c389 Mon Sep 17 00:00:00 2001 From: Marc Pichler Date: Fri, 13 Dec 2024 14:12:46 +0100 Subject: [PATCH 1/3] refactor(otlp-transformer): re-struture package to prepare for separate entrypoints --- .../common/{types.ts => internal-types.ts} | 9 ++ .../otlp-transformer/src/common/internal.ts | 15 ++- .../protobuf/protobuf-export-type.ts | 0 .../src/common/{index.ts => utils.ts} | 2 +- .../src/{common => }/i-serializer.ts | 0 .../packages/otlp-transformer/src/index.ts | 27 ++-- .../otlp-transformer/src/json/serializers.ts | 81 ------------ .../src/logs/export-response.ts | 28 +++++ .../otlp-transformer/src/logs/index.ts | 107 +--------------- .../src/logs/{types.ts => internal-types.ts} | 17 +-- .../otlp-transformer/src/logs/internal.ts | 118 +++++++++++++++++ .../{resource/types.ts => logs/json/index.ts} | 12 +- .../otlp-transformer/src/logs/json/logs.ts | 40 ++++++ .../internal.ts => logs/protobuf/index.ts} | 10 +- .../src/logs/protobuf/logs.ts | 46 +++++++ .../src/metrics/export-response.ts | 28 +++++ .../otlp-transformer/src/metrics/index.ts | 19 +-- .../metrics/{types.ts => internal-types.ts} | 21 +--- .../otlp-transformer/src/metrics/internal.ts | 25 +++- .../src/metrics/json/index.ts | 18 +++ .../src/metrics/json/metrics.ts | 36 ++++++ .../src/metrics/protobuf/index.ts | 18 +++ .../src/metrics/protobuf/metrics.ts | 42 +++++++ .../src/protobuf/serializers.ts | 97 -------------- .../src/trace/export-response.ts | 28 +++++ .../otlp-transformer/src/trace/index.ts | 98 +-------------- .../src/trace/{types.ts => internal-types.ts} | 21 +--- .../otlp-transformer/src/trace/internal.ts | 119 +++++++++++++++++- .../otlp-transformer/src/trace/json/index.ts | 18 +++ .../otlp-transformer/src/trace/json/trace.ts | 37 ++++++ .../src/trace/protobuf/index.ts | 18 +++ .../src/trace/protobuf/trace.ts | 42 +++++++ .../otlp-transformer/test/common.test.ts | 2 +- .../otlp-transformer/test/logs.test.ts | 12 +- .../otlp-transformer/test/metrics.test.ts | 9 +- .../test/performance/benchmark/index.js | 10 +- .../otlp-transformer/test/trace.test.ts | 9 +- 37 files changed, 744 insertions(+), 495 deletions(-) rename experimental/packages/otlp-transformer/src/common/{types.ts => internal-types.ts} (91%) rename experimental/packages/otlp-transformer/src/{ => common}/protobuf/protobuf-export-type.ts (100%) rename experimental/packages/otlp-transformer/src/common/{index.ts => utils.ts} (97%) rename experimental/packages/otlp-transformer/src/{common => }/i-serializer.ts (100%) delete mode 100644 experimental/packages/otlp-transformer/src/json/serializers.ts create mode 100644 experimental/packages/otlp-transformer/src/logs/export-response.ts rename experimental/packages/otlp-transformer/src/logs/{types.ts => internal-types.ts} (87%) create mode 100644 experimental/packages/otlp-transformer/src/logs/internal.ts rename experimental/packages/otlp-transformer/src/{resource/types.ts => logs/json/index.ts} (71%) create mode 100644 experimental/packages/otlp-transformer/src/logs/json/logs.ts rename experimental/packages/otlp-transformer/src/{resource/internal.ts => logs/protobuf/index.ts} (65%) create mode 100644 experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts create mode 100644 experimental/packages/otlp-transformer/src/metrics/export-response.ts rename experimental/packages/otlp-transformer/src/metrics/{types.ts => internal-types.ts} (95%) create mode 100644 experimental/packages/otlp-transformer/src/metrics/json/index.ts create mode 100644 experimental/packages/otlp-transformer/src/metrics/json/metrics.ts create mode 100644 experimental/packages/otlp-transformer/src/metrics/protobuf/index.ts create mode 100644 experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts delete mode 100644 experimental/packages/otlp-transformer/src/protobuf/serializers.ts create mode 100644 experimental/packages/otlp-transformer/src/trace/export-response.ts rename experimental/packages/otlp-transformer/src/trace/{types.ts => internal-types.ts} (90%) create mode 100644 experimental/packages/otlp-transformer/src/trace/json/index.ts create mode 100644 experimental/packages/otlp-transformer/src/trace/json/trace.ts create mode 100644 experimental/packages/otlp-transformer/src/trace/protobuf/index.ts create mode 100644 experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts diff --git a/experimental/packages/otlp-transformer/src/common/types.ts b/experimental/packages/otlp-transformer/src/common/internal-types.ts similarity index 91% rename from experimental/packages/otlp-transformer/src/common/types.ts rename to experimental/packages/otlp-transformer/src/common/internal-types.ts index 732944f2e09..b3026f121a1 100644 --- a/experimental/packages/otlp-transformer/src/common/types.ts +++ b/experimental/packages/otlp-transformer/src/common/internal-types.ts @@ -14,6 +14,15 @@ * limitations under the License. */ +/** Properties of a Resource. */ +export interface IResource { + /** Resource attributes */ + attributes: IKeyValue[]; + + /** Resource droppedAttributesCount */ + droppedAttributesCount: number; +} + /** Properties of an InstrumentationScope. */ export interface IInstrumentationScope { /** InstrumentationScope name */ diff --git a/experimental/packages/otlp-transformer/src/common/internal.ts b/experimental/packages/otlp-transformer/src/common/internal.ts index 8755362bb34..0deeb1d51f2 100644 --- a/experimental/packages/otlp-transformer/src/common/internal.ts +++ b/experimental/packages/otlp-transformer/src/common/internal.ts @@ -13,9 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { IAnyValue, IInstrumentationScope, IKeyValue } from './types'; +import type { + IAnyValue, + IInstrumentationScope, + IKeyValue, + IResource, +} from './internal-types'; import { Attributes } from '@opentelemetry/api'; import { InstrumentationScope } from '@opentelemetry/core'; +import { IResource as ISdkResource } from '@opentelemetry/resources'; + +export function createResource(resource: ISdkResource): IResource { + return { + attributes: toAttributes(resource.attributes), + droppedAttributesCount: 0, + }; +} export function createInstrumentationScope( scope: InstrumentationScope diff --git a/experimental/packages/otlp-transformer/src/protobuf/protobuf-export-type.ts b/experimental/packages/otlp-transformer/src/common/protobuf/protobuf-export-type.ts similarity index 100% rename from experimental/packages/otlp-transformer/src/protobuf/protobuf-export-type.ts rename to experimental/packages/otlp-transformer/src/common/protobuf/protobuf-export-type.ts diff --git a/experimental/packages/otlp-transformer/src/common/index.ts b/experimental/packages/otlp-transformer/src/common/utils.ts similarity index 97% rename from experimental/packages/otlp-transformer/src/common/index.ts rename to experimental/packages/otlp-transformer/src/common/utils.ts index 96d281bad6f..1d3fd73c580 100644 --- a/experimental/packages/otlp-transformer/src/common/index.ts +++ b/experimental/packages/otlp-transformer/src/common/utils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { OtlpEncodingOptions, Fixed64, LongBits } from './types'; +import type { OtlpEncodingOptions, Fixed64, LongBits } from './internal-types'; import { HrTime } from '@opentelemetry/api'; import { hexToBinary, hrTimeToNanoseconds } from '@opentelemetry/core'; diff --git a/experimental/packages/otlp-transformer/src/common/i-serializer.ts b/experimental/packages/otlp-transformer/src/i-serializer.ts similarity index 100% rename from experimental/packages/otlp-transformer/src/common/i-serializer.ts rename to experimental/packages/otlp-transformer/src/i-serializer.ts diff --git a/experimental/packages/otlp-transformer/src/index.ts b/experimental/packages/otlp-transformer/src/index.ts index 18cc064bbcd..8b5832d66a6 100644 --- a/experimental/packages/otlp-transformer/src/index.ts +++ b/experimental/packages/otlp-transformer/src/index.ts @@ -17,26 +17,19 @@ export { IExportMetricsPartialSuccess, IExportMetricsServiceResponse, -} from './metrics/types'; +} from './metrics'; export { IExportTracePartialSuccess, IExportTraceServiceResponse, -} from './trace/types'; -export { - IExportLogsServiceResponse, - IExportLogsPartialSuccess, -} from './logs/types'; +} from './trace'; +export { IExportLogsServiceResponse, IExportLogsPartialSuccess } from './logs'; -export { - ProtobufLogsSerializer, - ProtobufMetricsSerializer, - ProtobufTraceSerializer, -} from './protobuf/serializers'; +export { ProtobufLogsSerializer } from './logs/protobuf'; +export { ProtobufMetricsSerializer } from './metrics/protobuf'; +export { ProtobufTraceSerializer } from './trace/protobuf'; -export { - JsonTraceSerializer, - JsonLogsSerializer, - JsonMetricsSerializer, -} from './json/serializers'; +export { JsonLogsSerializer } from './logs/json'; +export { JsonMetricsSerializer } from './metrics/json'; +export { JsonTraceSerializer } from './trace/json'; -export { ISerializer } from './common/i-serializer'; +export { ISerializer } from './i-serializer'; diff --git a/experimental/packages/otlp-transformer/src/json/serializers.ts b/experimental/packages/otlp-transformer/src/json/serializers.ts deleted file mode 100644 index c187d6309b9..00000000000 --- a/experimental/packages/otlp-transformer/src/json/serializers.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 { ISerializer } from '../common/i-serializer'; -import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { IExportTraceServiceResponse } from '../trace/types'; -import { createExportTraceServiceRequest } from '../trace'; -import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; -import { createExportMetricsServiceRequest } from '../metrics'; -import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; -import { IExportMetricsServiceResponse } from '../metrics/types'; -import { IExportLogsServiceResponse } from '../logs/types'; -import { createExportLogsServiceRequest } from '../logs'; - -export const JsonTraceSerializer: ISerializer< - ReadableSpan[], - IExportTraceServiceResponse -> = { - serializeRequest: (arg: ReadableSpan[]) => { - const request = createExportTraceServiceRequest(arg, { - useHex: true, - useLongBits: false, - }); - const encoder = new TextEncoder(); - return encoder.encode(JSON.stringify(request)); - }, - deserializeResponse: (arg: Uint8Array) => { - const decoder = new TextDecoder(); - return JSON.parse(decoder.decode(arg)) as IExportTraceServiceResponse; - }, -}; - -export const JsonMetricsSerializer: ISerializer< - ResourceMetrics, - IExportMetricsServiceResponse -> = { - serializeRequest: (arg: ResourceMetrics) => { - const request = createExportMetricsServiceRequest([arg], { - useLongBits: false, - }); - const encoder = new TextEncoder(); - return encoder.encode(JSON.stringify(request)); - }, - deserializeResponse: (arg: Uint8Array) => { - const decoder = new TextDecoder(); - return JSON.parse(decoder.decode(arg)) as IExportMetricsServiceResponse; - }, -}; - -/* - * @experimental this serializer may receive breaking changes in minor versions, pin this package's version when using this constant - */ -export const JsonLogsSerializer: ISerializer< - ReadableLogRecord[], - IExportLogsServiceResponse -> = { - serializeRequest: (arg: ReadableLogRecord[]) => { - const request = createExportLogsServiceRequest(arg, { - useHex: true, - useLongBits: false, - }); - const encoder = new TextEncoder(); - return encoder.encode(JSON.stringify(request)); - }, - deserializeResponse: (arg: Uint8Array) => { - const decoder = new TextDecoder(); - return JSON.parse(decoder.decode(arg)) as IExportLogsServiceResponse; - }, -}; diff --git a/experimental/packages/otlp-transformer/src/logs/export-response.ts b/experimental/packages/otlp-transformer/src/logs/export-response.ts new file mode 100644 index 00000000000..55a62da77d5 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/logs/export-response.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export interface IExportLogsServiceResponse { + /** ExportLogsServiceResponse partialSuccess */ + partialSuccess?: IExportLogsPartialSuccess; +} + +export interface IExportLogsPartialSuccess { + /** ExportLogsPartialSuccess rejectedLogRecords */ + rejectedLogRecords?: number; + + /** ExportLogsPartialSuccess errorMessage */ + errorMessage?: string; +} diff --git a/experimental/packages/otlp-transformer/src/logs/index.ts b/experimental/packages/otlp-transformer/src/logs/index.ts index 73013c0e260..2578d9b43a1 100644 --- a/experimental/packages/otlp-transformer/src/logs/index.ts +++ b/experimental/packages/otlp-transformer/src/logs/index.ts @@ -14,105 +14,8 @@ * limitations under the License. */ -import type { ReadableLogRecord } from '@opentelemetry/sdk-logs'; -import { - ESeverityNumber, - IExportLogsServiceRequest, - ILogRecord, - IResourceLogs, -} from './types'; -import { IResource } from '@opentelemetry/resources'; -import { Encoder, getOtlpEncoder } from '../common'; -import { - createInstrumentationScope, - toAnyValue, - toKeyValue, -} from '../common/internal'; -import { SeverityNumber } from '@opentelemetry/api-logs'; -import { OtlpEncodingOptions, IKeyValue } from '../common/types'; -import { LogAttributes } from '@opentelemetry/api-logs'; -import { createResource } from '../resource/internal'; - -export function createExportLogsServiceRequest( - logRecords: ReadableLogRecord[], - options?: OtlpEncodingOptions -): IExportLogsServiceRequest { - const encoder = getOtlpEncoder(options); - return { - resourceLogs: logRecordsToResourceLogs(logRecords, encoder), - }; -} - -function createResourceMap( - logRecords: ReadableLogRecord[] -): Map> { - const resourceMap: Map< - IResource, - Map - > = new Map(); - - for (const record of logRecords) { - const { - resource, - instrumentationScope: { name, version = '', schemaUrl = '' }, - } = record; - - let ismMap = resourceMap.get(resource); - if (!ismMap) { - ismMap = new Map(); - resourceMap.set(resource, ismMap); - } - - const ismKey = `${name}@${version}:${schemaUrl}`; - let records = ismMap.get(ismKey); - if (!records) { - records = []; - ismMap.set(ismKey, records); - } - records.push(record); - } - return resourceMap; -} - -function logRecordsToResourceLogs( - logRecords: ReadableLogRecord[], - encoder: Encoder -): IResourceLogs[] { - const resourceMap = createResourceMap(logRecords); - return Array.from(resourceMap, ([resource, ismMap]) => ({ - resource: createResource(resource), - scopeLogs: Array.from(ismMap, ([, scopeLogs]) => { - return { - scope: createInstrumentationScope(scopeLogs[0].instrumentationScope), - logRecords: scopeLogs.map(log => toLogRecord(log, encoder)), - schemaUrl: scopeLogs[0].instrumentationScope.schemaUrl, - }; - }), - schemaUrl: undefined, - })); -} - -function toLogRecord(log: ReadableLogRecord, encoder: Encoder): ILogRecord { - return { - timeUnixNano: encoder.encodeHrTime(log.hrTime), - observedTimeUnixNano: encoder.encodeHrTime(log.hrTimeObserved), - severityNumber: toSeverityNumber(log.severityNumber), - severityText: log.severityText, - body: toAnyValue(log.body), - attributes: toLogAttributes(log.attributes), - droppedAttributesCount: log.droppedAttributesCount, - flags: log.spanContext?.traceFlags, - traceId: encoder.encodeOptionalSpanContext(log.spanContext?.traceId), - spanId: encoder.encodeOptionalSpanContext(log.spanContext?.spanId), - }; -} - -function toSeverityNumber( - severityNumber: SeverityNumber | undefined -): ESeverityNumber | undefined { - return severityNumber as number | undefined as ESeverityNumber | undefined; -} - -export function toLogAttributes(attributes: LogAttributes): IKeyValue[] { - return Object.keys(attributes).map(key => toKeyValue(key, attributes[key])); -} +// IMPORTANT: exports added here are public +export { + IExportLogsServiceResponse, + IExportLogsPartialSuccess, +} from './export-response'; diff --git a/experimental/packages/otlp-transformer/src/logs/types.ts b/experimental/packages/otlp-transformer/src/logs/internal-types.ts similarity index 87% rename from experimental/packages/otlp-transformer/src/logs/types.ts rename to experimental/packages/otlp-transformer/src/logs/internal-types.ts index 57c5422cbb4..28917fbd74f 100644 --- a/experimental/packages/otlp-transformer/src/logs/types.ts +++ b/experimental/packages/otlp-transformer/src/logs/internal-types.ts @@ -19,8 +19,8 @@ import type { IAnyValue, IInstrumentationScope, IKeyValue, -} from '../common/types'; -import type { IResource } from '../resource/types'; + IResource, +} from '../common/internal-types'; /** Properties of an ExportLogsServiceRequest. */ export interface IExportLogsServiceRequest { @@ -28,19 +28,6 @@ export interface IExportLogsServiceRequest { resourceLogs?: IResourceLogs[]; } -export interface IExportLogsServiceResponse { - /** ExportLogsServiceResponse partialSuccess */ - partialSuccess?: IExportLogsPartialSuccess; -} - -export interface IExportLogsPartialSuccess { - /** ExportLogsPartialSuccess rejectedLogRecords */ - rejectedLogRecords?: number; - - /** ExportLogsPartialSuccess errorMessage */ - errorMessage?: string; -} - /** Properties of a ResourceLogs. */ export interface IResourceLogs { /** ResourceLogs resource */ diff --git a/experimental/packages/otlp-transformer/src/logs/internal.ts b/experimental/packages/otlp-transformer/src/logs/internal.ts new file mode 100644 index 00000000000..53fe9ea6688 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/logs/internal.ts @@ -0,0 +1,118 @@ +/* + * 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 { ReadableLogRecord } from '@opentelemetry/sdk-logs'; +import { + ESeverityNumber, + IExportLogsServiceRequest, + ILogRecord, + IResourceLogs, +} from './internal-types'; +import { IResource } from '@opentelemetry/resources'; +import { Encoder, getOtlpEncoder } from '../common/utils'; +import { + createInstrumentationScope, + createResource, + toAnyValue, + toKeyValue, +} from '../common/internal'; +import { SeverityNumber } from '@opentelemetry/api-logs'; +import { OtlpEncodingOptions, IKeyValue } from '../common/internal-types'; +import { LogAttributes } from '@opentelemetry/api-logs'; + +export function createExportLogsServiceRequest( + logRecords: ReadableLogRecord[], + options?: OtlpEncodingOptions +): IExportLogsServiceRequest { + const encoder = getOtlpEncoder(options); + return { + resourceLogs: logRecordsToResourceLogs(logRecords, encoder), + }; +} + +function createResourceMap( + logRecords: ReadableLogRecord[] +): Map> { + const resourceMap: Map< + IResource, + Map + > = new Map(); + + for (const record of logRecords) { + const { + resource, + instrumentationScope: { name, version = '', schemaUrl = '' }, + } = record; + + let ismMap = resourceMap.get(resource); + if (!ismMap) { + ismMap = new Map(); + resourceMap.set(resource, ismMap); + } + + const ismKey = `${name}@${version}:${schemaUrl}`; + let records = ismMap.get(ismKey); + if (!records) { + records = []; + ismMap.set(ismKey, records); + } + records.push(record); + } + return resourceMap; +} + +function logRecordsToResourceLogs( + logRecords: ReadableLogRecord[], + encoder: Encoder +): IResourceLogs[] { + const resourceMap = createResourceMap(logRecords); + return Array.from(resourceMap, ([resource, ismMap]) => ({ + resource: createResource(resource), + scopeLogs: Array.from(ismMap, ([, scopeLogs]) => { + return { + scope: createInstrumentationScope(scopeLogs[0].instrumentationScope), + logRecords: scopeLogs.map(log => toLogRecord(log, encoder)), + schemaUrl: scopeLogs[0].instrumentationScope.schemaUrl, + }; + }), + schemaUrl: undefined, + })); +} + +function toLogRecord(log: ReadableLogRecord, encoder: Encoder): ILogRecord { + return { + timeUnixNano: encoder.encodeHrTime(log.hrTime), + observedTimeUnixNano: encoder.encodeHrTime(log.hrTimeObserved), + severityNumber: toSeverityNumber(log.severityNumber), + severityText: log.severityText, + body: toAnyValue(log.body), + attributes: toLogAttributes(log.attributes), + droppedAttributesCount: log.droppedAttributesCount, + flags: log.spanContext?.traceFlags, + traceId: encoder.encodeOptionalSpanContext(log.spanContext?.traceId), + spanId: encoder.encodeOptionalSpanContext(log.spanContext?.spanId), + }; +} + +function toSeverityNumber( + severityNumber: SeverityNumber | undefined +): ESeverityNumber | undefined { + return severityNumber as number | undefined as ESeverityNumber | undefined; +} + +export function toLogAttributes(attributes: LogAttributes): IKeyValue[] { + return Object.keys(attributes).map(key => toKeyValue(key, attributes[key])); +} diff --git a/experimental/packages/otlp-transformer/src/resource/types.ts b/experimental/packages/otlp-transformer/src/logs/json/index.ts similarity index 71% rename from experimental/packages/otlp-transformer/src/resource/types.ts rename to experimental/packages/otlp-transformer/src/logs/json/index.ts index 7755b756e91..039ac0af2ff 100644 --- a/experimental/packages/otlp-transformer/src/resource/types.ts +++ b/experimental/packages/otlp-transformer/src/logs/json/index.ts @@ -14,13 +14,5 @@ * limitations under the License. */ -import { IKeyValue } from '../common/types'; - -/** Properties of a Resource. */ -export interface IResource { - /** Resource attributes */ - attributes: IKeyValue[]; - - /** Resource droppedAttributesCount */ - droppedAttributesCount: number; -} +// IMPORTANT: exports added here are public +export { JsonLogsSerializer } from './logs'; diff --git a/experimental/packages/otlp-transformer/src/logs/json/logs.ts b/experimental/packages/otlp-transformer/src/logs/json/logs.ts new file mode 100644 index 00000000000..b9e6f6b15c9 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/logs/json/logs.ts @@ -0,0 +1,40 @@ +/* + * 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 { ISerializer } from '../../i-serializer'; +import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; +import { createExportLogsServiceRequest } from '../internal'; +import { IExportLogsServiceResponse } from '../export-response'; + +/* + * @experimental this serializer may receive breaking changes in minor versions, pin this package's version when using this constant + */ +export const JsonLogsSerializer: ISerializer< + ReadableLogRecord[], + IExportLogsServiceResponse +> = { + serializeRequest: (arg: ReadableLogRecord[]) => { + const request = createExportLogsServiceRequest(arg, { + useHex: true, + useLongBits: false, + }); + const encoder = new TextEncoder(); + return encoder.encode(JSON.stringify(request)); + }, + deserializeResponse: (arg: Uint8Array) => { + const decoder = new TextDecoder(); + return JSON.parse(decoder.decode(arg)) as IExportLogsServiceResponse; + }, +}; diff --git a/experimental/packages/otlp-transformer/src/resource/internal.ts b/experimental/packages/otlp-transformer/src/logs/protobuf/index.ts similarity index 65% rename from experimental/packages/otlp-transformer/src/resource/internal.ts rename to experimental/packages/otlp-transformer/src/logs/protobuf/index.ts index 93b69645080..af594b5bc2c 100644 --- a/experimental/packages/otlp-transformer/src/resource/internal.ts +++ b/experimental/packages/otlp-transformer/src/logs/protobuf/index.ts @@ -13,13 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { IResource as ISdkResource } from '@opentelemetry/resources'; -import { toAttributes } from '../common/internal'; -import { IResource } from './types'; -export function createResource(resource: ISdkResource): IResource { - return { - attributes: toAttributes(resource.attributes), - droppedAttributesCount: 0, - }; -} +export { ProtobufLogsSerializer } from './logs'; diff --git a/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts b/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts new file mode 100644 index 00000000000..a5b32453b68 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/logs/protobuf/logs.ts @@ -0,0 +1,46 @@ +/* + * 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 * as root from '../../generated/root'; + +import { IExportLogsServiceRequest } from '../internal-types'; +import { IExportLogsServiceResponse } from '../export-response'; + +import { createExportLogsServiceRequest } from '../internal'; +import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; +import { ExportType } from '../../common/protobuf/protobuf-export-type'; +import { ISerializer } from '../../i-serializer'; + +const logsResponseType = root.opentelemetry.proto.collector.logs.v1 + .ExportLogsServiceResponse as ExportType; + +const logsRequestType = root.opentelemetry.proto.collector.logs.v1 + .ExportLogsServiceRequest as ExportType; + +/* + * @experimental this serializer may receive breaking changes in minor versions, pin this package's version when using this constant + */ +export const ProtobufLogsSerializer: ISerializer< + ReadableLogRecord[], + IExportLogsServiceResponse +> = { + serializeRequest: (arg: ReadableLogRecord[]) => { + const request = createExportLogsServiceRequest(arg); + return logsRequestType.encode(request).finish(); + }, + deserializeResponse: (arg: Uint8Array) => { + return logsResponseType.decode(arg); + }, +}; diff --git a/experimental/packages/otlp-transformer/src/metrics/export-response.ts b/experimental/packages/otlp-transformer/src/metrics/export-response.ts new file mode 100644 index 00000000000..79e09d0fd80 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/metrics/export-response.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export interface IExportMetricsServiceResponse { + /** ExportMetricsServiceResponse partialSuccess */ + partialSuccess?: IExportMetricsPartialSuccess; +} + +export interface IExportMetricsPartialSuccess { + /** ExportMetricsPartialSuccess rejectedDataPoints */ + rejectedDataPoints?: number; + + /** ExportMetricsPartialSuccess errorMessage */ + errorMessage?: string; +} diff --git a/experimental/packages/otlp-transformer/src/metrics/index.ts b/experimental/packages/otlp-transformer/src/metrics/index.ts index 9ef3c57d3d2..288a0dbbc8c 100644 --- a/experimental/packages/otlp-transformer/src/metrics/index.ts +++ b/experimental/packages/otlp-transformer/src/metrics/index.ts @@ -13,18 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { ResourceMetrics } from '@opentelemetry/sdk-metrics'; -import type { IExportMetricsServiceRequest } from './types'; -import type { OtlpEncodingOptions } from '../common/types'; -import { toResourceMetrics } from './internal'; -export function createExportMetricsServiceRequest( - resourceMetrics: ResourceMetrics[], - options?: OtlpEncodingOptions -): IExportMetricsServiceRequest { - return { - resourceMetrics: resourceMetrics.map(metrics => - toResourceMetrics(metrics, options) - ), - }; -} +// IMPORTANT: exports added here are public +export { + IExportMetricsPartialSuccess, + IExportMetricsServiceResponse, +} from './export-response'; diff --git a/experimental/packages/otlp-transformer/src/metrics/types.ts b/experimental/packages/otlp-transformer/src/metrics/internal-types.ts similarity index 95% rename from experimental/packages/otlp-transformer/src/metrics/types.ts rename to experimental/packages/otlp-transformer/src/metrics/internal-types.ts index 208c6aa6782..f210a88fe93 100644 --- a/experimental/packages/otlp-transformer/src/metrics/types.ts +++ b/experimental/packages/otlp-transformer/src/metrics/internal-types.ts @@ -13,8 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Fixed64, IInstrumentationScope, IKeyValue } from '../common/types'; -import { IResource } from '../resource/types'; +import { + Fixed64, + IInstrumentationScope, + IKeyValue, + IResource, +} from '../common/internal-types'; /** Properties of an ExportMetricsServiceRequest. */ export interface IExportMetricsServiceRequest { @@ -22,19 +26,6 @@ export interface IExportMetricsServiceRequest { resourceMetrics: IResourceMetrics[]; } -export interface IExportMetricsServiceResponse { - /** ExportMetricsServiceResponse partialSuccess */ - partialSuccess?: IExportMetricsPartialSuccess; -} - -export interface IExportMetricsPartialSuccess { - /** ExportMetricsPartialSuccess rejectedDataPoints */ - rejectedDataPoints?: number; - - /** ExportMetricsPartialSuccess errorMessage */ - errorMessage?: string; -} - /** Properties of a ResourceMetrics. */ export interface IResourceMetrics { /** ResourceMetrics resource */ diff --git a/experimental/packages/otlp-transformer/src/metrics/internal.ts b/experimental/packages/otlp-transformer/src/metrics/internal.ts index fc13a807997..edcc0cddce8 100644 --- a/experimental/packages/otlp-transformer/src/metrics/internal.ts +++ b/experimental/packages/otlp-transformer/src/metrics/internal.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { OtlpEncodingOptions } from '../common/types'; +import type { OtlpEncodingOptions } from '../common/internal-types'; import { ValueType } from '@opentelemetry/api'; import { AggregationTemporality, @@ -28,15 +28,19 @@ import { import { EAggregationTemporality, IExponentialHistogramDataPoint, + IExportMetricsServiceRequest, IHistogramDataPoint, IMetric, INumberDataPoint, IResourceMetrics, IScopeMetrics, -} from './types'; -import { Encoder, getOtlpEncoder } from '../common'; -import { createInstrumentationScope, toAttributes } from '../common/internal'; -import { createResource } from '../resource/internal'; +} from './internal-types'; +import { Encoder, getOtlpEncoder } from '../common/utils'; +import { + createInstrumentationScope, + createResource, + toAttributes, +} from '../common/internal'; export function toResourceMetrics( resourceMetrics: ResourceMetrics, @@ -201,3 +205,14 @@ function toAggregationTemporality( return EAggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE; } } + +export function createExportMetricsServiceRequest( + resourceMetrics: ResourceMetrics[], + options?: OtlpEncodingOptions +): IExportMetricsServiceRequest { + return { + resourceMetrics: resourceMetrics.map(metrics => + toResourceMetrics(metrics, options) + ), + }; +} diff --git a/experimental/packages/otlp-transformer/src/metrics/json/index.ts b/experimental/packages/otlp-transformer/src/metrics/json/index.ts new file mode 100644 index 00000000000..acd1af11c0d --- /dev/null +++ b/experimental/packages/otlp-transformer/src/metrics/json/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +// IMPORTANT: exports added here are public +export { JsonMetricsSerializer } from './metrics'; diff --git a/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts b/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts new file mode 100644 index 00000000000..9f7273cbc4f --- /dev/null +++ b/experimental/packages/otlp-transformer/src/metrics/json/metrics.ts @@ -0,0 +1,36 @@ +/* + * 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 { ISerializer } from '../../i-serializer'; +import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; +import { createExportMetricsServiceRequest } from '../internal'; +import { IExportMetricsServiceResponse } from '../export-response'; + +export const JsonMetricsSerializer: ISerializer< + ResourceMetrics, + IExportMetricsServiceResponse +> = { + serializeRequest: (arg: ResourceMetrics) => { + const request = createExportMetricsServiceRequest([arg], { + useLongBits: false, + }); + const encoder = new TextEncoder(); + return encoder.encode(JSON.stringify(request)); + }, + deserializeResponse: (arg: Uint8Array) => { + const decoder = new TextDecoder(); + return JSON.parse(decoder.decode(arg)) as IExportMetricsServiceResponse; + }, +}; diff --git a/experimental/packages/otlp-transformer/src/metrics/protobuf/index.ts b/experimental/packages/otlp-transformer/src/metrics/protobuf/index.ts new file mode 100644 index 00000000000..72fc2f627a0 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/metrics/protobuf/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +// IMPORTANT: exports added here are public +export { ProtobufMetricsSerializer } from './metrics'; diff --git a/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts b/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts new file mode 100644 index 00000000000..ee21ca93eb2 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/metrics/protobuf/metrics.ts @@ -0,0 +1,42 @@ +/* + * 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 * as root from '../../generated/root'; +import { ISerializer } from '../../i-serializer'; +import { IExportMetricsServiceRequest } from '../internal-types'; +import { ExportType } from '../../common/protobuf/protobuf-export-type'; +import { createExportMetricsServiceRequest } from '../internal'; +import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; +import { IExportMetricsServiceResponse } from '../export-response'; + +const metricsResponseType = root.opentelemetry.proto.collector.metrics.v1 + .ExportMetricsServiceResponse as ExportType; + +const metricsRequestType = root.opentelemetry.proto.collector.metrics.v1 + .ExportMetricsServiceRequest as ExportType; + +export const ProtobufMetricsSerializer: ISerializer< + ResourceMetrics, + IExportMetricsServiceResponse +> = { + serializeRequest: (arg: ResourceMetrics) => { + const request = createExportMetricsServiceRequest([arg]); + return metricsRequestType.encode(request).finish(); + }, + deserializeResponse: (arg: Uint8Array) => { + return metricsResponseType.decode(arg); + }, +}; diff --git a/experimental/packages/otlp-transformer/src/protobuf/serializers.ts b/experimental/packages/otlp-transformer/src/protobuf/serializers.ts deleted file mode 100644 index 95b475695d9..00000000000 --- a/experimental/packages/otlp-transformer/src/protobuf/serializers.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 * as root from '../generated/root'; -import { ISerializer } from '../common/i-serializer'; -import { - IExportMetricsServiceRequest, - IExportMetricsServiceResponse, -} from '../metrics/types'; -import { ExportType } from './protobuf-export-type'; -import { - IExportTraceServiceRequest, - IExportTraceServiceResponse, -} from '../trace/types'; -import { - IExportLogsServiceRequest, - IExportLogsServiceResponse, -} from '../logs/types'; -import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { createExportTraceServiceRequest } from '../trace'; -import { createExportMetricsServiceRequest } from '../metrics'; -import { ResourceMetrics } from '@opentelemetry/sdk-metrics'; -import { createExportLogsServiceRequest } from '../logs'; -import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; - -const logsResponseType = root.opentelemetry.proto.collector.logs.v1 - .ExportLogsServiceResponse as ExportType; - -const logsRequestType = root.opentelemetry.proto.collector.logs.v1 - .ExportLogsServiceRequest as ExportType; - -const metricsResponseType = root.opentelemetry.proto.collector.metrics.v1 - .ExportMetricsServiceResponse as ExportType; - -const metricsRequestType = root.opentelemetry.proto.collector.metrics.v1 - .ExportMetricsServiceRequest as ExportType; - -const traceResponseType = root.opentelemetry.proto.collector.trace.v1 - .ExportTraceServiceResponse as ExportType; - -const traceRequestType = root.opentelemetry.proto.collector.trace.v1 - .ExportTraceServiceRequest as ExportType; - -/* - * @experimental this serializer may receive breaking changes in minor versions, pin this package's version when using this constant - */ -export const ProtobufLogsSerializer: ISerializer< - ReadableLogRecord[], - IExportLogsServiceResponse -> = { - serializeRequest: (arg: ReadableLogRecord[]) => { - const request = createExportLogsServiceRequest(arg); - return logsRequestType.encode(request).finish(); - }, - deserializeResponse: (arg: Uint8Array) => { - return logsResponseType.decode(arg); - }, -}; - -export const ProtobufMetricsSerializer: ISerializer< - ResourceMetrics, - IExportMetricsServiceResponse -> = { - serializeRequest: (arg: ResourceMetrics) => { - const request = createExportMetricsServiceRequest([arg]); - return metricsRequestType.encode(request).finish(); - }, - deserializeResponse: (arg: Uint8Array) => { - return metricsResponseType.decode(arg); - }, -}; - -export const ProtobufTraceSerializer: ISerializer< - ReadableSpan[], - IExportTraceServiceResponse -> = { - serializeRequest: (arg: ReadableSpan[]) => { - const request = createExportTraceServiceRequest(arg); - return traceRequestType.encode(request).finish(); - }, - deserializeResponse: (arg: Uint8Array) => { - return traceResponseType.decode(arg); - }, -}; diff --git a/experimental/packages/otlp-transformer/src/trace/export-response.ts b/experimental/packages/otlp-transformer/src/trace/export-response.ts new file mode 100644 index 00000000000..df8279f5764 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/trace/export-response.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export interface IExportTraceServiceResponse { + /** ExportTraceServiceResponse partialSuccess */ + partialSuccess?: IExportTracePartialSuccess; +} + +export interface IExportTracePartialSuccess { + /** ExportLogsServiceResponse rejectedLogRecords */ + rejectedSpans?: number; + + /** ExportLogsServiceResponse errorMessage */ + errorMessage?: string; +} diff --git a/experimental/packages/otlp-transformer/src/trace/index.ts b/experimental/packages/otlp-transformer/src/trace/index.ts index 9fef398c544..04ead47a2b9 100644 --- a/experimental/packages/otlp-transformer/src/trace/index.ts +++ b/experimental/packages/otlp-transformer/src/trace/index.ts @@ -13,97 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { IResource } from '@opentelemetry/resources'; -import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import type { OtlpEncodingOptions } from '../common/types'; -import { sdkSpanToOtlpSpan } from './internal'; -import { - IExportTraceServiceRequest, - IResourceSpans, - IScopeSpans, -} from './types'; -import { Encoder, getOtlpEncoder } from '../common'; -import { createInstrumentationScope } from '../common/internal'; -import { createResource } from '../resource/internal'; -export function createExportTraceServiceRequest( - spans: ReadableSpan[], - options?: OtlpEncodingOptions -): IExportTraceServiceRequest { - const encoder = getOtlpEncoder(options); - return { - resourceSpans: spanRecordsToResourceSpans(spans, encoder), - }; -} - -function createResourceMap(readableSpans: ReadableSpan[]) { - const resourceMap: Map> = new Map(); - for (const record of readableSpans) { - let ilmMap = resourceMap.get(record.resource); - - if (!ilmMap) { - ilmMap = new Map(); - resourceMap.set(record.resource, ilmMap); - } - - // TODO this is duplicated in basic tracer. Consolidate on a common helper in core - const instrumentationLibraryKey = `${record.instrumentationLibrary.name}@${ - record.instrumentationLibrary.version || '' - }:${record.instrumentationLibrary.schemaUrl || ''}`; - let records = ilmMap.get(instrumentationLibraryKey); - - if (!records) { - records = []; - ilmMap.set(instrumentationLibraryKey, records); - } - - records.push(record); - } - - return resourceMap; -} - -function spanRecordsToResourceSpans( - readableSpans: ReadableSpan[], - encoder: Encoder -): IResourceSpans[] { - const resourceMap = createResourceMap(readableSpans); - const out: IResourceSpans[] = []; - - const entryIterator = resourceMap.entries(); - let entry = entryIterator.next(); - while (!entry.done) { - const [resource, ilmMap] = entry.value; - const scopeResourceSpans: IScopeSpans[] = []; - const ilmIterator = ilmMap.values(); - let ilmEntry = ilmIterator.next(); - while (!ilmEntry.done) { - const scopeSpans = ilmEntry.value; - if (scopeSpans.length > 0) { - const spans = scopeSpans.map(readableSpan => - sdkSpanToOtlpSpan(readableSpan, encoder) - ); - - scopeResourceSpans.push({ - scope: createInstrumentationScope( - scopeSpans[0].instrumentationLibrary - ), - spans: spans, - schemaUrl: scopeSpans[0].instrumentationLibrary.schemaUrl, - }); - } - ilmEntry = ilmIterator.next(); - } - // TODO SDK types don't provide resource schema URL at this time - const transformedSpans: IResourceSpans = { - resource: createResource(resource), - scopeSpans: scopeResourceSpans, - schemaUrl: undefined, - }; - - out.push(transformedSpans); - entry = entryIterator.next(); - } - - return out; -} +// IMPORTANT: exports added here are public +export { + IExportTracePartialSuccess, + IExportTraceServiceResponse, +} from './export-response'; diff --git a/experimental/packages/otlp-transformer/src/trace/types.ts b/experimental/packages/otlp-transformer/src/trace/internal-types.ts similarity index 90% rename from experimental/packages/otlp-transformer/src/trace/types.ts rename to experimental/packages/otlp-transformer/src/trace/internal-types.ts index d32c85eb5a5..94e78072b27 100644 --- a/experimental/packages/otlp-transformer/src/trace/types.ts +++ b/experimental/packages/otlp-transformer/src/trace/internal-types.ts @@ -14,8 +14,12 @@ * limitations under the License. */ -import { Fixed64, IInstrumentationScope, IKeyValue } from '../common/types'; -import { IResource } from '../resource/types'; +import { + Fixed64, + IInstrumentationScope, + IKeyValue, + IResource, +} from '../common/internal-types'; /** Properties of an ExportTraceServiceRequest. */ export interface IExportTraceServiceRequest { @@ -23,19 +27,6 @@ export interface IExportTraceServiceRequest { resourceSpans?: IResourceSpans[]; } -export interface IExportTraceServiceResponse { - /** ExportTraceServiceResponse partialSuccess */ - partialSuccess?: IExportTracePartialSuccess; -} - -export interface IExportTracePartialSuccess { - /** ExportLogsServiceResponse rejectedLogRecords */ - rejectedSpans?: number; - - /** ExportLogsServiceResponse errorMessage */ - errorMessage?: string; -} - /** Properties of a ResourceSpans. */ export interface IResourceSpans { /** ResourceSpans resource */ diff --git a/experimental/packages/otlp-transformer/src/trace/internal.ts b/experimental/packages/otlp-transformer/src/trace/internal.ts index a4236e5dca4..06aab08bcc3 100644 --- a/experimental/packages/otlp-transformer/src/trace/internal.ts +++ b/experimental/packages/otlp-transformer/src/trace/internal.ts @@ -14,10 +14,25 @@ * limitations under the License. */ import type { Link } from '@opentelemetry/api'; +import { IResource } from '@opentelemetry/resources'; import type { ReadableSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'; -import type { Encoder } from '../common'; -import { toAttributes } from '../common/internal'; -import { EStatusCode, IEvent, ILink, ISpan } from './types'; +import type { Encoder } from '../common/utils'; +import { + createInstrumentationScope, + createResource, + toAttributes, +} from '../common/internal'; +import { + EStatusCode, + IEvent, + IExportTraceServiceRequest, + ILink, + IResourceSpans, + IScopeSpans, + ISpan, +} from './internal-types'; +import { OtlpEncodingOptions } from '../common/internal-types'; +import { getOtlpEncoder } from '../common/utils'; export function sdkSpanToOtlpSpan(span: ReadableSpan, encoder: Encoder): ISpan { const ctx = span.spanContext(); @@ -69,3 +84,101 @@ export function toOtlpSpanEvent( droppedAttributesCount: timedEvent.droppedAttributesCount || 0, }; } + +/* + * 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. + */ + +export function createExportTraceServiceRequest( + spans: ReadableSpan[], + options?: OtlpEncodingOptions +): IExportTraceServiceRequest { + const encoder = getOtlpEncoder(options); + return { + resourceSpans: spanRecordsToResourceSpans(spans, encoder), + }; +} + +function createResourceMap(readableSpans: ReadableSpan[]) { + const resourceMap: Map> = new Map(); + for (const record of readableSpans) { + let ilmMap = resourceMap.get(record.resource); + + if (!ilmMap) { + ilmMap = new Map(); + resourceMap.set(record.resource, ilmMap); + } + + // TODO this is duplicated in basic tracer. Consolidate on a common helper in core + const instrumentationLibraryKey = `${record.instrumentationLibrary.name}@${ + record.instrumentationLibrary.version || '' + }:${record.instrumentationLibrary.schemaUrl || ''}`; + let records = ilmMap.get(instrumentationLibraryKey); + + if (!records) { + records = []; + ilmMap.set(instrumentationLibraryKey, records); + } + + records.push(record); + } + + return resourceMap; +} + +function spanRecordsToResourceSpans( + readableSpans: ReadableSpan[], + encoder: Encoder +): IResourceSpans[] { + const resourceMap = createResourceMap(readableSpans); + const out: IResourceSpans[] = []; + + const entryIterator = resourceMap.entries(); + let entry = entryIterator.next(); + while (!entry.done) { + const [resource, ilmMap] = entry.value; + const scopeResourceSpans: IScopeSpans[] = []; + const ilmIterator = ilmMap.values(); + let ilmEntry = ilmIterator.next(); + while (!ilmEntry.done) { + const scopeSpans = ilmEntry.value; + if (scopeSpans.length > 0) { + const spans = scopeSpans.map(readableSpan => + sdkSpanToOtlpSpan(readableSpan, encoder) + ); + + scopeResourceSpans.push({ + scope: createInstrumentationScope( + scopeSpans[0].instrumentationLibrary + ), + spans: spans, + schemaUrl: scopeSpans[0].instrumentationLibrary.schemaUrl, + }); + } + ilmEntry = ilmIterator.next(); + } + // TODO SDK types don't provide resource schema URL at this time + const transformedSpans: IResourceSpans = { + resource: createResource(resource), + scopeSpans: scopeResourceSpans, + schemaUrl: undefined, + }; + + out.push(transformedSpans); + entry = entryIterator.next(); + } + + return out; +} diff --git a/experimental/packages/otlp-transformer/src/trace/json/index.ts b/experimental/packages/otlp-transformer/src/trace/json/index.ts new file mode 100644 index 00000000000..1a00b83b443 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/trace/json/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +// IMPORTANT: exports added here are public +export { JsonTraceSerializer } from './trace'; diff --git a/experimental/packages/otlp-transformer/src/trace/json/trace.ts b/experimental/packages/otlp-transformer/src/trace/json/trace.ts new file mode 100644 index 00000000000..da188b090a5 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/trace/json/trace.ts @@ -0,0 +1,37 @@ +/* + * 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 { ISerializer } from '../../i-serializer'; +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { IExportTraceServiceResponse } from '../export-response'; +import { createExportTraceServiceRequest } from '../internal'; + +export const JsonTraceSerializer: ISerializer< + ReadableSpan[], + IExportTraceServiceResponse +> = { + serializeRequest: (arg: ReadableSpan[]) => { + const request = createExportTraceServiceRequest(arg, { + useHex: true, + useLongBits: false, + }); + const encoder = new TextEncoder(); + return encoder.encode(JSON.stringify(request)); + }, + deserializeResponse: (arg: Uint8Array) => { + const decoder = new TextDecoder(); + return JSON.parse(decoder.decode(arg)) as IExportTraceServiceResponse; + }, +}; diff --git a/experimental/packages/otlp-transformer/src/trace/protobuf/index.ts b/experimental/packages/otlp-transformer/src/trace/protobuf/index.ts new file mode 100644 index 00000000000..c3e4b868c32 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/trace/protobuf/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +// IMPORTANT: exports added here are public +export { ProtobufTraceSerializer } from './trace'; diff --git a/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts b/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts new file mode 100644 index 00000000000..87d5f481fe0 --- /dev/null +++ b/experimental/packages/otlp-transformer/src/trace/protobuf/trace.ts @@ -0,0 +1,42 @@ +/* + * 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 * as root from '../../generated/root'; +import { ISerializer } from '../../i-serializer'; +import { ExportType } from '../../common/protobuf/protobuf-export-type'; +import { IExportTraceServiceRequest } from '../internal-types'; +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { createExportTraceServiceRequest } from '../internal'; +import { IExportTraceServiceResponse } from '../export-response'; + +const traceResponseType = root.opentelemetry.proto.collector.trace.v1 + .ExportTraceServiceResponse as ExportType; + +const traceRequestType = root.opentelemetry.proto.collector.trace.v1 + .ExportTraceServiceRequest as ExportType; + +export const ProtobufTraceSerializer: ISerializer< + ReadableSpan[], + IExportTraceServiceResponse +> = { + serializeRequest: (arg: ReadableSpan[]) => { + const request = createExportTraceServiceRequest(arg); + return traceRequestType.encode(request).finish(); + }, + deserializeResponse: (arg: Uint8Array) => { + return traceResponseType.decode(arg); + }, +}; diff --git a/experimental/packages/otlp-transformer/test/common.test.ts b/experimental/packages/otlp-transformer/test/common.test.ts index 9ab639c6029..a3d05aaa6a3 100644 --- a/experimental/packages/otlp-transformer/test/common.test.ts +++ b/experimental/packages/otlp-transformer/test/common.test.ts @@ -17,7 +17,7 @@ import { hexToBinary } from '@opentelemetry/core'; import { toAnyValue } from '../src/common/internal'; import * as assert from 'assert'; -import { getOtlpEncoder } from '../src/common'; +import { getOtlpEncoder } from '../src/common/utils'; const traceId = 'abcdef01234567890000000000000000'; const spanId = '12341234abcdabcd'; diff --git a/experimental/packages/otlp-transformer/test/logs.test.ts b/experimental/packages/otlp-transformer/test/logs.test.ts index b3c606d1b78..4cf3c93090a 100644 --- a/experimental/packages/otlp-transformer/test/logs.test.ts +++ b/experimental/packages/otlp-transformer/test/logs.test.ts @@ -17,14 +17,18 @@ import { HrTime, TraceFlags } from '@opentelemetry/api'; import { InstrumentationScope, hexToBinary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; -import { ProtobufLogsSerializer, JsonLogsSerializer } from '../src'; import { ReadableLogRecord } from '@opentelemetry/sdk-logs'; import { SeverityNumber } from '@opentelemetry/api-logs'; import { toBase64 } from './utils'; import * as root from '../src/generated/root'; -import { OtlpEncodingOptions } from '../src/common/types'; -import { ESeverityNumber, IExportLogsServiceRequest } from '../src/logs/types'; -import { createExportLogsServiceRequest } from '../src/logs'; +import { OtlpEncodingOptions } from '../src/common/internal-types'; +import { + ESeverityNumber, + IExportLogsServiceRequest, +} from '../src/logs/internal-types'; +import { createExportLogsServiceRequest } from '../src/logs/internal'; +import { ProtobufLogsSerializer } from '../src/logs/protobuf'; +import { JsonLogsSerializer } from '../src/logs/json'; function createExpectedLogJson( options: OtlpEncodingOptions diff --git a/experimental/packages/otlp-transformer/test/metrics.test.ts b/experimental/packages/otlp-transformer/test/metrics.test.ts index 6c8d332321e..5ad8615548b 100644 --- a/experimental/packages/otlp-transformer/test/metrics.test.ts +++ b/experimental/packages/otlp-transformer/test/metrics.test.ts @@ -23,12 +23,13 @@ import { ResourceMetrics, } from '@opentelemetry/sdk-metrics'; import * as assert from 'assert'; -import { createExportMetricsServiceRequest } from '../src/metrics'; -import { EAggregationTemporality } from '../src/metrics/types'; +import { createExportMetricsServiceRequest } from '../src/metrics/internal'; +import { EAggregationTemporality } from '../src/metrics/internal-types'; import { hrTime, hrTimeToNanoseconds } from '@opentelemetry/core'; -import { ProtobufMetricsSerializer, JsonMetricsSerializer } from '../src'; import * as root from '../src/generated/root'; -import { encodeAsLongBits, encodeAsString } from '../src/common'; +import { encodeAsLongBits, encodeAsString } from '../src/common/utils'; +import { ProtobufMetricsSerializer } from '../src/metrics/protobuf'; +import { JsonMetricsSerializer } from '../src/metrics/json'; const START_TIME = hrTime(); const END_TIME = hrTime(); diff --git a/experimental/packages/otlp-transformer/test/performance/benchmark/index.js b/experimental/packages/otlp-transformer/test/performance/benchmark/index.js index e110bbe7845..f79703ffe73 100644 --- a/experimental/packages/otlp-transformer/test/performance/benchmark/index.js +++ b/experimental/packages/otlp-transformer/test/performance/benchmark/index.js @@ -15,11 +15,13 @@ */ const Benchmark = require('benchmark'); -const { createExportTraceServiceRequest } = require('../../../build/src'); +const { + createExportTraceServiceRequest, +} = require('../../../build/src/trace/internal'); const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base'); const tracerProvider = new BasicTracerProvider(); -const tracer = tracerProvider.getTracer('test') +const tracer = tracerProvider.getTracer('test'); const suite = new Benchmark.Suite(); @@ -33,11 +35,11 @@ suite.on('cycle', event => { console.log(String(event.target)); }); -suite.add('transform 1 span', function() { +suite.add('transform 1 span', function () { createExportTraceServiceRequest([span]); }); -suite.add('transform 100 spans', function() { +suite.add('transform 100 spans', function () { createExportTraceServiceRequest(spans); }); diff --git a/experimental/packages/otlp-transformer/test/trace.test.ts b/experimental/packages/otlp-transformer/test/trace.test.ts index dd6354ea4d6..81ad9eb2cc3 100644 --- a/experimental/packages/otlp-transformer/test/trace.test.ts +++ b/experimental/packages/otlp-transformer/test/trace.test.ts @@ -19,11 +19,12 @@ import { TraceState, hexToBinary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; -import { ProtobufTraceSerializer, JsonTraceSerializer } from '../src'; import { toBase64 } from './utils'; -import { OtlpEncodingOptions } from '../src/common/types'; -import { ESpanKind, EStatusCode } from '../src/trace/types'; -import { createExportTraceServiceRequest } from '../src/trace'; +import { OtlpEncodingOptions } from '../src/common/internal-types'; +import { ESpanKind, EStatusCode } from '../src/trace/internal-types'; +import { createExportTraceServiceRequest } from '../src/trace/internal'; +import { ProtobufTraceSerializer } from '../src/trace/protobuf'; +import { JsonTraceSerializer } from '../src/trace/json'; function createExpectedSpanJson(options: OtlpEncodingOptions) { const useHex = options.useHex ?? false; From 676d6f4a3069b074e13fe6cfa8dc79839848ee34 Mon Sep 17 00:00:00 2001 From: Marc Pichler Date: Fri, 13 Dec 2024 14:36:01 +0100 Subject: [PATCH 2/3] chore: add changelog entry --- experimental/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index f8c6110c344..dc5fb39d6d5 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -17,6 +17,8 @@ All notable changes to experimental packages in this project will be documented ### :house: (Internal) +* refactor(otlp-transformer): re-structure package to prepare for separate entrypoints [#5264](https://github.com/open-telemetry/opentelemetry-js/pull/5264) @pichlermarc + ## 0.56.0 ### :boom: Breaking Change From 2bcd3b3c09a02256772ae3aed1cfa392df46abb7 Mon Sep 17 00:00:00 2001 From: Marc Pichler Date: Fri, 13 Dec 2024 14:46:23 +0100 Subject: [PATCH 3/3] fixup! chore: add changelog entry --- experimental/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index dc5fb39d6d5..881b34576a8 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -17,7 +17,7 @@ All notable changes to experimental packages in this project will be documented ### :house: (Internal) -* refactor(otlp-transformer): re-structure package to prepare for separate entrypoints [#5264](https://github.com/open-telemetry/opentelemetry-js/pull/5264) @pichlermarc +* refactor(otlp-transformer): re-structure package to prepare for separate entrypoints [#5264](https://github.com/open-telemetry/opentelemetry-js/pull/5264) @pichlermarc ## 0.56.0