From 42aaae0270aec344d22e8a0b7b3c595700fcae97 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 19 Dec 2023 20:59:34 +0100 Subject: [PATCH 1/2] chore(deps): update dependency chromedriver to v120 (#4374) --- package-lock.json | 23 ++++++++++++++++------- selenium-tests/package.json | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index f926ba0d835..2be1e4a30cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14187,10 +14187,11 @@ } }, "node_modules/chromedriver": { - "version": "119.0.1", + "version": "120.0.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-120.0.0.tgz", + "integrity": "sha512-LGy2LhWRBiqDarFIU8gQ43EEyj+07Tc3JuUhthkESAwZ99lrifSnKZwKU0aVwansU84+k6bt71z7K3dkk65gZg==", "dev": true, "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "@testim/chrome-version": "^1.1.4", "axios": "^1.6.0", @@ -14209,8 +14210,9 @@ }, "node_modules/chromedriver/node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, - "license": "MIT", "dependencies": { "debug": "4" }, @@ -14220,8 +14222,9 @@ }, "node_modules/chromedriver/node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, - "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -35481,7 +35484,7 @@ "babel-loader": "8.3.0", "babel-polyfill": "6.26.0", "browserstack-local": "1.4.8", - "chromedriver": "119.0.1", + "chromedriver": "120.0.0", "dotenv": "16.0.0", "fast-safe-stringify": "2.1.1", "geckodriver": "3.0.1", @@ -42823,7 +42826,7 @@ "babel-loader": "8.3.0", "babel-polyfill": "6.26.0", "browserstack-local": "1.4.8", - "chromedriver": "119.0.1", + "chromedriver": "120.0.0", "dotenv": "16.0.0", "fast-safe-stringify": "2.1.1", "geckodriver": "3.0.1", @@ -46508,7 +46511,9 @@ "dev": true }, "chromedriver": { - "version": "119.0.1", + "version": "120.0.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-120.0.0.tgz", + "integrity": "sha512-LGy2LhWRBiqDarFIU8gQ43EEyj+07Tc3JuUhthkESAwZ99lrifSnKZwKU0aVwansU84+k6bt71z7K3dkk65gZg==", "dev": true, "requires": { "@testim/chrome-version": "^1.1.4", @@ -46522,6 +46527,8 @@ "dependencies": { "agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "requires": { "debug": "4" @@ -46529,6 +46536,8 @@ }, "https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "requires": { "agent-base": "6", diff --git a/selenium-tests/package.json b/selenium-tests/package.json index c5468ef006a..104b4d06f55 100644 --- a/selenium-tests/package.json +++ b/selenium-tests/package.json @@ -40,7 +40,7 @@ "babel-loader": "8.3.0", "babel-polyfill": "6.26.0", "browserstack-local": "1.4.8", - "chromedriver": "119.0.1", + "chromedriver": "120.0.0", "dotenv": "16.0.0", "fast-safe-stringify": "2.1.1", "geckodriver": "3.0.1", From a512494ba2a7248823fc79e2aa85e9163f0fbdb8 Mon Sep 17 00:00:00 2001 From: Siim Kallas Date: Tue, 19 Dec 2023 23:05:32 +0200 Subject: [PATCH 2/2] perf: remove unnecessary base64 encode+decode from OTLP export (#4343) * fix: remove unnecessary base64 encoding for span contexts * chore: add changelog --------- Co-authored-by: Daniel Dyla --- CHANGELOG.md | 1 + .../otlp-transformer/src/common/index.ts | 20 +++++---- .../otlp-transformer/src/logs/types.ts | 4 +- .../otlp-transformer/src/metrics/types.ts | 4 +- .../otlp-transformer/src/trace/types.ts | 10 ++--- .../otlp-transformer/test/common.test.ts | 12 +++--- .../otlp-transformer/test/logs.test.ts | 6 +-- .../otlp-transformer/test/trace.test.ts | 12 +++--- .../src/common/hex-to-binary.ts | 43 +++++++++++++++++++ packages/opentelemetry-core/src/index.ts | 1 + .../src/platform/browser/hex-to-base64.ts | 12 ++---- .../src/platform/node/hex-to-base64.ts | 36 +--------------- 12 files changed, 86 insertions(+), 75 deletions(-) create mode 100644 packages/opentelemetry-core/src/common/hex-to-binary.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 28759606768..0aa44839eed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ For experimental package changes, see the [experimental CHANGELOG](experimental/ ### :rocket: (Enhancement) +* perf(otlp-transformer): skip unnecessary base64 encode of span contexts [#4343](https://github.com/open-telemetry/opentelemetry-js/pull/4343) @seemk * feat(sdk-trace-base): improve log messages when dropping span events [#4223](https://github.com/open-telemetry/opentelemetry-js/pull/4223) @mkubliniak ### :bug: (Bug Fix) diff --git a/experimental/packages/otlp-transformer/src/common/index.ts b/experimental/packages/otlp-transformer/src/common/index.ts index c759fafc4b0..00dcccfb059 100644 --- a/experimental/packages/otlp-transformer/src/common/index.ts +++ b/experimental/packages/otlp-transformer/src/common/index.ts @@ -16,7 +16,7 @@ import type { OtlpEncodingOptions, Fixed64, LongBits } from './types'; import { HrTime } from '@opentelemetry/api'; -import { hexToBase64, hrTimeToNanoseconds } from '@opentelemetry/core'; +import { hexToBinary, hrTimeToNanoseconds } from '@opentelemetry/core'; const NANOSECONDS = BigInt(1_000_000_000); @@ -44,10 +44,12 @@ const encodeTimestamp = typeof BigInt !== 'undefined' ? encodeAsString : hrTimeToNanoseconds; export type HrTimeEncodeFunction = (hrTime: HrTime) => Fixed64; -export type SpanContextEncodeFunction = (spanContext: string) => string; +export type SpanContextEncodeFunction = ( + spanContext: string +) => string | Uint8Array; export type OptionalSpanContextEncodeFunction = ( spanContext: string | undefined -) => string | undefined; +) => string | Uint8Array | undefined; export interface Encoder { encodeHrTime: HrTimeEncodeFunction; @@ -59,15 +61,15 @@ function identity(value: T): T { return value; } -function optionalHexToBase64(str: string | undefined): string | undefined { +function optionalHexToBinary(str: string | undefined): Uint8Array | undefined { if (str === undefined) return undefined; - return hexToBase64(str); + return hexToBinary(str); } const DEFAULT_ENCODER: Encoder = { encodeHrTime: encodeAsLongBits, - encodeSpanContext: hexToBase64, - encodeOptionalSpanContext: optionalHexToBase64, + encodeSpanContext: hexToBinary, + encodeOptionalSpanContext: optionalHexToBinary, }; export function getOtlpEncoder(options?: OtlpEncodingOptions): Encoder { @@ -79,7 +81,7 @@ export function getOtlpEncoder(options?: OtlpEncodingOptions): Encoder { const useHex = options.useHex ?? false; return { encodeHrTime: useLongBits ? encodeAsLongBits : encodeTimestamp, - encodeSpanContext: useHex ? identity : hexToBase64, - encodeOptionalSpanContext: useHex ? identity : optionalHexToBase64, + encodeSpanContext: useHex ? identity : hexToBinary, + encodeOptionalSpanContext: useHex ? identity : optionalHexToBinary, }; } diff --git a/experimental/packages/otlp-transformer/src/logs/types.ts b/experimental/packages/otlp-transformer/src/logs/types.ts index 2af77ad7c8f..57c5422cbb4 100644 --- a/experimental/packages/otlp-transformer/src/logs/types.ts +++ b/experimental/packages/otlp-transformer/src/logs/types.ts @@ -92,10 +92,10 @@ export interface ILogRecord { flags?: number; /** LogRecord traceId */ - traceId?: string; + traceId?: string | Uint8Array; /** LogRecord spanId */ - spanId?: string; + spanId?: string | Uint8Array; } /** diff --git a/experimental/packages/otlp-transformer/src/metrics/types.ts b/experimental/packages/otlp-transformer/src/metrics/types.ts index 96a3dda798f..208c6aa6782 100644 --- a/experimental/packages/otlp-transformer/src/metrics/types.ts +++ b/experimental/packages/otlp-transformer/src/metrics/types.ts @@ -287,10 +287,10 @@ export interface IExemplar { asInt?: number; /** Exemplar spanId */ - spanId?: string; + spanId?: string | Uint8Array; /** Exemplar traceId */ - traceId?: string; + traceId?: string | Uint8Array; } /** diff --git a/experimental/packages/otlp-transformer/src/trace/types.ts b/experimental/packages/otlp-transformer/src/trace/types.ts index b9618dd75ff..d32c85eb5a5 100644 --- a/experimental/packages/otlp-transformer/src/trace/types.ts +++ b/experimental/packages/otlp-transformer/src/trace/types.ts @@ -63,16 +63,16 @@ export interface IScopeSpans { /** Properties of a Span. */ export interface ISpan { /** Span traceId */ - traceId: string; + traceId: string | Uint8Array; /** Span spanId */ - spanId: string; + spanId: string | Uint8Array; /** Span traceState */ traceState?: string | null; /** Span parentSpanId */ - parentSpanId?: string; + parentSpanId?: string | Uint8Array; /** Span name */ name: string; @@ -181,10 +181,10 @@ export interface IEvent { /** Properties of a Link. */ export interface ILink { /** Link traceId */ - traceId: string; + traceId: string | Uint8Array; /** Link spanId */ - spanId: string; + spanId: string | Uint8Array; /** Link traceState */ traceState?: string; diff --git a/experimental/packages/otlp-transformer/test/common.test.ts b/experimental/packages/otlp-transformer/test/common.test.ts index d31267406c3..1925ee1283f 100644 --- a/experimental/packages/otlp-transformer/test/common.test.ts +++ b/experimental/packages/otlp-transformer/test/common.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { hexToBase64 } from '@opentelemetry/core'; +import { hexToBinary } from '@opentelemetry/core'; import { getOtlpEncoder } from '../src'; import { toAnyValue } from '../src/common/internal'; import * as assert from 'assert'; @@ -70,7 +70,7 @@ describe('common', () => { }); describe('otlp encoder', () => { - it('defaults to long timestamps and base64 encoding given no options', () => { + it('defaults to long timestamps and binary encoding given no options', () => { const encoder = getOtlpEncoder(); assert.deepStrictEqual(encoder.encodeHrTime([1697978649, 99870675]), { low: 3352011219, @@ -78,11 +78,11 @@ describe('common', () => { }); assert.deepStrictEqual( encoder.encodeSpanContext(traceId), - hexToBase64(traceId) + hexToBinary(traceId) ); assert.deepStrictEqual( encoder.encodeOptionalSpanContext(spanId), - hexToBase64(spanId) + hexToBinary(spanId) ); assert.deepStrictEqual( encoder.encodeOptionalSpanContext(undefined), @@ -98,11 +98,11 @@ describe('common', () => { }); assert.deepStrictEqual( encoder.encodeSpanContext(traceId), - hexToBase64(traceId) + hexToBinary(traceId) ); assert.deepStrictEqual( encoder.encodeOptionalSpanContext(spanId), - hexToBase64(spanId) + hexToBinary(spanId) ); assert.deepStrictEqual( encoder.encodeOptionalSpanContext(undefined), diff --git a/experimental/packages/otlp-transformer/test/logs.test.ts b/experimental/packages/otlp-transformer/test/logs.test.ts index 18dfbdabe4e..ea8dd7e82bb 100644 --- a/experimental/packages/otlp-transformer/test/logs.test.ts +++ b/experimental/packages/otlp-transformer/test/logs.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { HrTime, TraceFlags } from '@opentelemetry/api'; -import { InstrumentationScope, hexToBase64 } from '@opentelemetry/core'; +import { InstrumentationScope, hexToBinary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import * as assert from 'assert'; import { @@ -28,8 +28,8 @@ import { SeverityNumber } from '@opentelemetry/api-logs'; function createExpectedLogJson(useHex: boolean): IExportLogsServiceRequest { const traceId = useHex ? '00000000000000000000000000000001' - : hexToBase64('00000000000000000000000000000001'); - const spanId = useHex ? '0000000000000002' : hexToBase64('0000000000000002'); + : hexToBinary('00000000000000000000000000000001'); + const spanId = useHex ? '0000000000000002' : hexToBinary('0000000000000002'); return { resourceLogs: [ diff --git a/experimental/packages/otlp-transformer/test/trace.test.ts b/experimental/packages/otlp-transformer/test/trace.test.ts index 1eb786b30f5..65b23ddc2dd 100644 --- a/experimental/packages/otlp-transformer/test/trace.test.ts +++ b/experimental/packages/otlp-transformer/test/trace.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { SpanKind, SpanStatusCode, TraceFlags } from '@opentelemetry/api'; -import { TraceState, hexToBase64 } from '@opentelemetry/core'; +import { TraceState, hexToBinary } from '@opentelemetry/core'; import { Resource } from '@opentelemetry/resources'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import * as assert from 'assert'; @@ -41,17 +41,17 @@ function createExpectedSpanJson(options: OtlpEncodingOptions) { const traceId = useHex ? '00000000000000000000000000000001' - : hexToBase64('00000000000000000000000000000001'); - const spanId = useHex ? '0000000000000002' : hexToBase64('0000000000000002'); + : hexToBinary('00000000000000000000000000000001'); + const spanId = useHex ? '0000000000000002' : hexToBinary('0000000000000002'); const parentSpanId = useHex ? '0000000000000001' - : hexToBase64('0000000000000001'); + : hexToBinary('0000000000000001'); const linkSpanId = useHex ? '0000000000000003' - : hexToBase64('0000000000000003'); + : hexToBinary('0000000000000003'); const linkTraceId = useHex ? '00000000000000000000000000000002' - : hexToBase64('00000000000000000000000000000002'); + : hexToBinary('00000000000000000000000000000002'); return { resourceSpans: [ diff --git a/packages/opentelemetry-core/src/common/hex-to-binary.ts b/packages/opentelemetry-core/src/common/hex-to-binary.ts new file mode 100644 index 00000000000..d2a367d3bcc --- /dev/null +++ b/packages/opentelemetry-core/src/common/hex-to-binary.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +function intValue(charCode: number): number { + // 0-9 + if (charCode >= 48 && charCode <= 57) { + return charCode - 48; + } + + // a-f + if (charCode >= 97 && charCode <= 102) { + return charCode - 87; + } + + // A-F + return charCode - 55; +} + +export function hexToBinary(hexStr: string): Uint8Array { + const buf = new Uint8Array(hexStr.length / 2); + let offset = 0; + + for (let i = 0; i < hexStr.length; i += 2) { + const hi = intValue(hexStr.charCodeAt(i)); + const lo = intValue(hexStr.charCodeAt(i + 1)); + buf[offset++] = (hi << 4) | lo; + } + + return buf; +} diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index a3ab418117d..4ec08b1db1f 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -21,6 +21,7 @@ export * from './common/global-error-handler'; export * from './common/logging-error-handler'; export * from './common/time'; export * from './common/types'; +export * from './common/hex-to-binary'; export * from './ExportResult'; export * as baggageUtils from './baggage/utils'; export * from './platform'; diff --git a/packages/opentelemetry-core/src/platform/browser/hex-to-base64.ts b/packages/opentelemetry-core/src/platform/browser/hex-to-base64.ts index baf01bdc369..dee61ec727d 100644 --- a/packages/opentelemetry-core/src/platform/browser/hex-to-base64.ts +++ b/packages/opentelemetry-core/src/platform/browser/hex-to-base64.ts @@ -13,13 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { hexToBinary } from '../../common/hex-to-binary'; + export function hexToBase64(hexStr: string): string { - const hexStrLen = hexStr.length; - let hexAsciiCharsStr = ''; - for (let i = 0; i < hexStrLen; i += 2) { - const hexPair = hexStr.substring(i, i + 2); - const hexVal = parseInt(hexPair, 16); - hexAsciiCharsStr += String.fromCharCode(hexVal); - } - return btoa(hexAsciiCharsStr); + return btoa(String.fromCharCode(...hexToBinary(hexStr))); } diff --git a/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts b/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts index 66d4ad0fe9c..7be359e6512 100644 --- a/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts +++ b/packages/opentelemetry-core/src/platform/node/hex-to-base64.ts @@ -13,40 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -function intValue(charCode: number): number { - // 0-9 - if (charCode >= 48 && charCode <= 57) { - return charCode - 48; - } - - // a-f - if (charCode >= 97 && charCode <= 102) { - return charCode - 87; - } - - // A-F - return charCode - 55; -} - -const buf8 = Buffer.alloc(8); -const buf16 = Buffer.alloc(16); +import { hexToBinary } from '../../common/hex-to-binary'; export function hexToBase64(hexStr: string): string { - let buf; - if (hexStr.length === 16) { - buf = buf8; - } else if (hexStr.length === 32) { - buf = buf16; - } else { - buf = Buffer.alloc(hexStr.length / 2); - } - let offset = 0; - - for (let i = 0; i < hexStr.length; i += 2) { - const hi = intValue(hexStr.charCodeAt(i)); - const lo = intValue(hexStr.charCodeAt(i + 1)); - buf.writeUInt8((hi << 4) | lo, offset++); - } - - return buf.toString('base64'); + return Buffer.from(hexToBinary(hexStr)).toString('base64'); }