From 6cf1e79551ccd907aff4473b70902731e5f29ad5 Mon Sep 17 00:00:00 2001 From: Dima Voytenko Date: Thu, 25 Apr 2024 14:01:35 -0700 Subject: [PATCH] Manual protobuf encoding for OTLP (#81) * Manual protobuf encoding for OTLP * fix lints * changeset --- .changeset/brown-starfishes-drive.md | 5 + .github/workflows/unit-test.yml | 36 ++ package.json | 1 + packages/otel/build.ts | 25 ++ packages/otel/package.json | 6 +- .../exporter-trace-otlp-proto-fetch.ts | 8 +- packages/otel/src/exporters/proto.test.ts | 377 ++++++++++++++++++ packages/otel/src/exporters/proto.ts | 288 +++++++++++++ pnpm-lock.yaml | 11 +- 9 files changed, 745 insertions(+), 12 deletions(-) create mode 100644 .changeset/brown-starfishes-drive.md create mode 100644 .github/workflows/unit-test.yml create mode 100644 packages/otel/src/exporters/proto.test.ts create mode 100644 packages/otel/src/exporters/proto.ts diff --git a/.changeset/brown-starfishes-drive.md b/.changeset/brown-starfishes-drive.md new file mode 100644 index 0000000..7a82da5 --- /dev/null +++ b/.changeset/brown-starfishes-drive.md @@ -0,0 +1,5 @@ +--- +"@vercel/otel": patch +--- + +Manual protobuf encoding for OTLP to save about 180K binary size diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml new file mode 100644 index 0000000..57c3ab6 --- /dev/null +++ b/.github/workflows/unit-test.yml @@ -0,0 +1,36 @@ +name: Unit Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + name: "unit tests" + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: "pnpm" + + - name: Install dependencies + run: pnpm install + + - name: Build + run: pnpm build + + - name: Run unit tests + run: pnpm unit-test diff --git a/package.json b/package.json index 181fdc9..185a0ea 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "eslint-fix": "turbo eslint -- --fix", "release": "pnpm build && changeset publish", "type-check": "turbo --continue type-check", + "unit-test": "turbo unit-test", "version-packages": "changeset version && pnpm i --no-frozen-lockfile && git add ." }, "keywords": [], diff --git a/packages/otel/build.ts b/packages/otel/build.ts index de77285..1975a7d 100644 --- a/packages/otel/build.ts +++ b/packages/otel/build.ts @@ -1,9 +1,15 @@ +import { stat } from "node:fs/promises"; import type { Plugin } from "esbuild"; import { build } from "esbuild"; const MINIFY = true; const SOURCEMAP = false; +const MAX_SIZES = { + "dist/node/index.js": 210_000, + "dist/edge/index.js": 180_000, +}; + type ExternalPluginFactory = (external: string[]) => Plugin; const externalCjsToEsmPlugin: ExternalPluginFactory = (external) => ({ name: "external", @@ -93,6 +99,25 @@ async function buildAll(): Promise { ], }), ]); + + // Check max size. + const errors: string[] = []; + for (const [file, maxSize] of Object.entries(MAX_SIZES)) { + // eslint-disable-next-line no-await-in-loop + const s = await stat(file); + if (s.size > maxSize) { + errors.push( + `${file}: the size of ${s.size} is over the maximum allowed size of ${maxSize}` + ); + } + } + if (errors.length > 0) { + for (const error of errors) { + // eslint-disable-next-line no-console + console.error(error); + } + process.exit(1); + } } void buildAll(); diff --git a/packages/otel/package.json b/packages/otel/package.json index 82bd09e..982b41d 100644 --- a/packages/otel/package.json +++ b/packages/otel/package.json @@ -50,6 +50,7 @@ }, "scripts": { "build": "pnpm clean && pnpm tsx build.ts && pnpm build-types && pnpm build-site", + "build-only": "pnpm tsx build.ts", "build-types": "tsc --noEmit false --declaration --emitDeclarationOnly --stripInternal --declarationDir dist/types src/index.ts", "build-site": "pnpm build-typedoc && cp index.html LICENSE CHANGELOG.md dist-site", "build-typedoc": "pnpm typedoc src/index.ts", @@ -71,15 +72,16 @@ "@opentelemetry/instrumentation": "^0.46.0", "@opentelemetry/otlp-exporter-base": "^0.46.0", "@opentelemetry/otlp-proto-exporter-base": "^0.46.0", + "@opentelemetry/otlp-transformer": "^0.46.0", "@opentelemetry/resources": "^1.19.0", "@opentelemetry/sdk-logs": "^0.46.0", "@opentelemetry/sdk-metrics": "^1.19.0", - "@opentelemetry/semantic-conventions": "^1.19.0", - "@opentelemetry/otlp-transformer": "^0.46.0", "@opentelemetry/sdk-trace-base": "^1.19.0", + "@opentelemetry/semantic-conventions": "^1.19.0", "@types/node": "18.15.11", "esbuild": "^0.19.4", "eslint-config": "workspace:*", + "protobufjs": "^7.2.6", "rimraf": "3.0.2", "tsx": "^4.6.2", "typedoc": "^0.25.8", diff --git a/packages/otel/src/exporters/exporter-trace-otlp-proto-fetch.ts b/packages/otel/src/exporters/exporter-trace-otlp-proto-fetch.ts index 4f41ab7..c970eeb 100644 --- a/packages/otel/src/exporters/exporter-trace-otlp-proto-fetch.ts +++ b/packages/otel/src/exporters/exporter-trace-otlp-proto-fetch.ts @@ -1,12 +1,11 @@ import type { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base"; import type { IExportTraceServiceRequest } from "@opentelemetry/otlp-transformer"; import { createExportTraceServiceRequest } from "@opentelemetry/otlp-transformer/build/src/trace"; -import { ServiceClientType } from "@opentelemetry/otlp-proto-exporter-base/build/src/platform/index"; -import { getExportRequestProto } from "@opentelemetry/otlp-proto-exporter-base/build/src/platform/util"; import type { ExportResult } from "@opentelemetry/core"; import { OTLPExporterEdgeBase } from "./otlp-exporter-base"; import { getDefaultUrl } from "./trace-config"; import type { OTLPExporterConfig } from "./config"; +import { encodeTraceServiceRequest } from "./proto"; /** * OTLP exporter for the `http/protobuf` protocol. Compatible with the "edge" runtime. @@ -52,10 +51,7 @@ class Impl extends OTLPExporterEdgeBase< contentType: string; headers?: Record | undefined; } { - const serviceClientType = ServiceClientType.SPANS; - const exportRequestType = getExportRequestProto(serviceClientType); - const message = exportRequestType.create(serviceRequest); - const body = exportRequestType.encode(message).finish(); + const body = encodeTraceServiceRequest(serviceRequest); return { body, contentType: "application/x-protobuf", diff --git a/packages/otel/src/exporters/proto.test.ts b/packages/otel/src/exporters/proto.test.ts new file mode 100644 index 0000000..f8b17fe --- /dev/null +++ b/packages/otel/src/exporters/proto.test.ts @@ -0,0 +1,377 @@ +import { describe, expect, it } from "vitest"; +import type { TimedEvent, ReadableSpan } from "@opentelemetry/sdk-trace-base"; +import type { IExportTraceServiceRequest } from "@opentelemetry/otlp-transformer"; +import { createExportTraceServiceRequest } from "@opentelemetry/otlp-transformer/build/src/trace"; +import { ServiceClientType } from "@opentelemetry/otlp-proto-exporter-base/build/src/platform/index"; +import { getExportRequestProto } from "@opentelemetry/otlp-proto-exporter-base/build/src/platform/util"; +import { hrTime, TraceState } from "@opentelemetry/core"; +import type { InstrumentationLibrary } from "@opentelemetry/core"; +import type { Attributes, Link, HrTime, SpanStatus } from "@opentelemetry/api"; +import { TraceFlags, SpanKind, SpanStatusCode } from "@opentelemetry/api"; +import { Resource } from "@opentelemetry/resources"; +import { encodeTraceServiceRequest } from "./proto"; + +describe("OTLP Protobuf", () => { + const performanceOffset = new Date("2024-04-25T00:00:00.000Z").getTime(); + type LocalTime = number; + + function createSpan({ + name, + kind, + parentSpanId, + attributes, + startTime, + endTime, + links, + events, + instrumentationLibrary, + droppedAttributesCount, + droppedEventsCount, + droppedLinksCount, + status, + traceState, + }: { + name?: string; + kind?: SpanKind; + parentSpanId?: string; + attributes?: Attributes; + startTime?: LocalTime; + endTime?: LocalTime; + links?: Link[]; + events?: TimedEvent[]; + instrumentationLibrary?: InstrumentationLibrary; + droppedAttributesCount?: number; + droppedEventsCount?: number; + droppedLinksCount?: number; + status?: SpanStatus; + traceState?: TraceState; + }): ReadableSpan { + const resource = new Resource({ + env: "production", + }); + + const spanContext = { + traceId: "ee75cd9e534ff5e9ed78b4a0c706f0f2", + spanId: "0f6a325411bdc432", + traceFlags: TraceFlags.SAMPLED, + isRemote: false, + traceState, + }; + + const startTimeLocal = startTime ?? 1; + const endTimeLocal = endTime ?? startTimeLocal + 1; + return { + name: name ?? "span1", + kind: kind ?? SpanKind.SERVER, + spanContext: () => spanContext, + parentSpanId: + parentSpanId !== undefined + ? parentSpanId || undefined + : "7e2a325411bdc191", + startTime: time(startTimeLocal), + endTime: time(endTimeLocal), + status: status ?? { code: SpanStatusCode.UNSET }, + attributes: { ...attributes }, + links: links ?? [], + events: events ?? [], + duration: time(endTimeLocal - startTimeLocal), + ended: true, + resource, + instrumentationLibrary: instrumentationLibrary ?? { name: "default" }, + droppedAttributesCount: droppedAttributesCount ?? 0, + droppedEventsCount: droppedEventsCount ?? 0, + droppedLinksCount: droppedLinksCount ?? 0, + }; + } + + function createLink({ + attributes, + droppedAttributesCount, + }: { + attributes?: Attributes; + droppedAttributesCount?: number; + }): Link { + const spanContext = { + traceId: "ee75cd9e534ff5e9ed78b4a0c706f0f2", + spanId: "0f6a325411bdc432", + traceFlags: TraceFlags.SAMPLED, + }; + + return { + context: spanContext, + attributes: { ...attributes }, + droppedAttributesCount: droppedAttributesCount ?? 0, + }; + } + + function createEvent({ + name, + time: timeArg, + attributes, + droppedAttributesCount, + }: { + name?: string; + time?: number; + attributes?: Attributes; + droppedAttributesCount?: number; + }): TimedEvent { + const timeLocal = timeArg ?? 1; + return { + name: name ?? "event1", + time: time(timeLocal), + attributes: { ...attributes }, + droppedAttributesCount: droppedAttributesCount ?? 0, + }; + } + + function time(inp: number): HrTime { + return hrTime(performanceOffset + inp); + } + + function encodeViaOtlpLibrary( + request: IExportTraceServiceRequest + ): Uint8Array { + const serviceClientType = ServiceClientType.SPANS; + const exportRequestType = getExportRequestProto(serviceClientType); + const message = exportRequestType.create(request); + return new Uint8Array(exportRequestType.encode(message).finish()); + } + + it("should match a bare minimum span", () => { + const span = createSpan({}); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match multiple spans", () => { + const span1 = createSpan({ name: "span1" }); + const span2 = createSpan({ name: "span2" }); + const request = createExportTraceServiceRequest([span1, span2], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a kind", () => { + const span = createSpan({ kind: SpanKind.CONSUMER }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match an empty parentSpanId", () => { + const span = createSpan({ parentSpanId: "" }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a tracestate", () => { + const span = createSpan({ traceState: new TraceState("foo=bar") }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a status", () => { + const span = createSpan({ + status: { + code: SpanStatusCode.ERROR, + message: "some error", + }, + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + describe("instrumentationLibrary", () => { + it("should match instrumentationLibrary", () => { + const span = createSpan({ + instrumentationLibrary: { name: "lib1" }, + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match instrumentationLibrary with version", () => { + const span = createSpan({ + instrumentationLibrary: { name: "lib1", version: "1.0.1" }, + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match instrumentationLibrary with schema", () => { + const span = createSpan({ + instrumentationLibrary: { + name: "lib1", + version: "1.0.1", + schemaUrl: "https://vercel.com/schema1", + }, + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + }); + + describe("dropped counts", () => { + it("should match droppedAttributesCount", () => { + const span = createSpan({ droppedAttributesCount: 11 }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match droppedEventsCount", () => { + const span = createSpan({ droppedEventsCount: 11 }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match droppedLinksCount", () => { + const span = createSpan({ droppedLinksCount: 11 }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + }); + + describe("attributes", () => { + it("should match string attributes", () => { + const span = createSpan({ attributes: { foo: "bar", baz: "bat" } }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match numeric attributes", () => { + const span = createSpan({ attributes: { foo: 1, baz: 2 } }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match boolean attributes", () => { + const span = createSpan({ attributes: { foo: true, baz: false } }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match array attributes", () => { + const span = createSpan({ attributes: { foo: [1, 2, 3, null] } }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + }); + + describe("links", () => { + it("should match a single link", () => { + const span = createSpan({ links: [createLink({})] }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a single link with attributes", () => { + const span = createSpan({ + links: [createLink({ attributes: { foo: "bar", baz: true, bat: 11 } })], + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a single link with droppedAttributesCount", () => { + const span = createSpan({ + links: [createLink({ droppedAttributesCount: 11 })], + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match multiple links", () => { + const span = createSpan({ + links: [ + createLink({ attributes: { foo: 1 } }), + createLink({ attributes: { foo: 2 } }), + ], + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + }); + + describe("events", () => { + it("should match a single event", () => { + const span = createSpan({ events: [createEvent({})] }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a single event with attributes", () => { + const span = createSpan({ + events: [ + createEvent({ attributes: { foo: "bar", baz: true, bat: 11 } }), + ], + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match a single event with droppedAttributesCount", () => { + const span = createSpan({ + events: [createEvent({ droppedAttributesCount: 11 })], + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + + it("should match multiple events", () => { + const span = createSpan({ + events: [ + createEvent({ name: "event1", attributes: { foo: 1 } }), + createEvent({ name: "event2", attributes: { foo: 2 } }), + ], + }); + const request = createExportTraceServiceRequest([span], undefined); + const expected = encodeViaOtlpLibrary(request); + const actual = encodeTraceServiceRequest(request); + expect(actual.toString()).toEqual(expected.toString()); + }); + }); +}); diff --git a/packages/otel/src/exporters/proto.ts b/packages/otel/src/exporters/proto.ts new file mode 100644 index 0000000..13a62d0 --- /dev/null +++ b/packages/otel/src/exporters/proto.ts @@ -0,0 +1,288 @@ +/* eslint-disable eslint-comments/disable-enable-pair */ +/* eslint-disable camelcase */ +/* eslint-disable eqeqeq */ + +/* eslint-disable @typescript-eslint/prefer-optional-chain */ +/* eslint-disable @typescript-eslint/prefer-for-of */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ + +/** + * This file is constructed by: + * + * 1. Clone https://github.com/open-telemetry/opentelemetry-js.git + * 2. Run `protos:generate` in `experimental/packages/otlp-proto-exporter-base/` + * 3. Fork `experimental/packages/otlp-proto-exporter-base/src/generated/root.js` and inline all encode methods. Throw away the rest of the code. + * + * The OTLP protocol is very stable, so these steps would only need to be done rarely. + */ + +import type { + IAnyValue, + IArrayValue, + IEvent, + IExportTraceServiceRequest, + IInstrumentationScope, + IKeyValue, + IKeyValueList, + ILink, + IResource, + IResourceSpans, + IScopeSpans, + ISpan, + IStatus, +} from "@opentelemetry/otlp-transformer"; +import type { Long } from "protobufjs/minimal"; +import { Writer } from "protobufjs/minimal"; + +export function encodeTraceServiceRequest( + message: IExportTraceServiceRequest +): Uint8Array { + const writer = new Writer(); + ExportTraceServiceRequest_encode(message, writer); + return writer.finish(); +} + +export function ExportTraceServiceRequest_encode( + message: IExportTraceServiceRequest, + writer: Writer +): Writer { + if (message.resourceSpans != null && message.resourceSpans.length) + for (let i = 0; i < message.resourceSpans.length; ++i) + ResourceSpans_encode( + message.resourceSpans[i]!, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork() + ).ldelim(); + return writer; +} + +function ResourceSpans_encode(message: IResourceSpans, writer: Writer): Writer { + if (message.resource != null) + Resource_encode( + message.resource, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork() + ).ldelim(); + if (message.scopeSpans != null && message.scopeSpans.length) + for (let i = 0; i < message.scopeSpans.length; ++i) + ScopeSpans_encode( + message.scopeSpans[i]!, + writer.uint32(/* id 2, wireType 2 =*/ 18).fork() + ).ldelim(); + if (message.schemaUrl != null) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.schemaUrl); + return writer; +} + +function Resource_encode(message: IResource, writer: Writer): Writer { + if (message.attributes != null && message.attributes.length) + for (let i = 0; i < message.attributes.length; ++i) + KeyValue_encode( + message.attributes[i]!, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork() + ).ldelim(); + if (message.droppedAttributesCount != null) + writer + .uint32(/* id 2, wireType 0 =*/ 16) + .uint32(message.droppedAttributesCount); + return writer; +} + +function ScopeSpans_encode(message: IScopeSpans, writer: Writer): Writer { + if (message.scope != null) + InstrumentationScope_encode( + message.scope, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork() + ).ldelim(); + if (message.spans != null && message.spans.length) + for (let i = 0; i < message.spans.length; ++i) + Span_encode( + message.spans[i]!, + writer.uint32(/* id 2, wireType 2 =*/ 18).fork() + ).ldelim(); + if (message.schemaUrl != null) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.schemaUrl); + return writer; +} + +function KeyValue_encode(message: IKeyValue, writer: Writer): Writer { + if (message.key != null) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.key); + if (message.value != null) + AnyValue_encode( + message.value, + writer.uint32(/* id 2, wireType 2 =*/ 18).fork() + ).ldelim(); + return writer; +} + +function AnyValue_encode(message: IAnyValue, writer: Writer): Writer { + if (message.stringValue != null) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.stringValue); + if (message.boolValue != null) + writer.uint32(/* id 2, wireType 0 =*/ 16).bool(message.boolValue); + if (message.intValue != null) + writer.uint32(/* id 3, wireType 0 =*/ 24).int64(message.intValue); + if (message.doubleValue != null) + writer.uint32(/* id 4, wireType 1 =*/ 33).double(message.doubleValue); + if (message.arrayValue != null) + ArrayValue_encode( + message.arrayValue, + writer.uint32(/* id 5, wireType 2 =*/ 42).fork() + ).ldelim(); + if (message.kvlistValue != null) + KeyValueList_encode( + message.kvlistValue, + writer.uint32(/* id 6, wireType 2 =*/ 50).fork() + ).ldelim(); + if (message.bytesValue != null) + writer.uint32(/* id 7, wireType 2 =*/ 58).bytes(message.bytesValue); + return writer; +} + +function ArrayValue_encode(message: IArrayValue, writer: Writer): Writer { + if (message.values != null && message.values.length) + for (let i = 0; i < message.values.length; ++i) + AnyValue_encode( + message.values[i]!, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork() + ).ldelim(); + return writer; +} + +function KeyValueList_encode(message: IKeyValueList, writer: Writer): Writer { + if (message.values != null && message.values.length) + for (let i = 0; i < message.values.length; ++i) + KeyValue_encode( + message.values[i]!, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork() + ).ldelim(); + return writer; +} + +function InstrumentationScope_encode( + message: IInstrumentationScope, + writer: Writer +): Writer { + if (message.name != null) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.version != null) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.version); + if (message.attributes != null && message.attributes.length) + for (let i = 0; i < message.attributes.length; ++i) + KeyValue_encode( + message.attributes[i]!, + writer.uint32(/* id 3, wireType 2 =*/ 26).fork() + ).ldelim(); + if (message.droppedAttributesCount != null) + writer + .uint32(/* id 4, wireType 0 =*/ 32) + .uint32(message.droppedAttributesCount); + return writer; +} + +function Span_encode(message: ISpan, writer: Writer): Writer { + if (message.traceId != null) + writer.uint32(/* id 1, wireType 2 =*/ 10).bytes(message.traceId); + if (message.spanId != null) + writer.uint32(/* id 2, wireType 2 =*/ 18).bytes(message.spanId); + if (message.traceState != null) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.traceState); + if (message.parentSpanId != null) + writer.uint32(/* id 4, wireType 2 =*/ 34).bytes(message.parentSpanId); + if (message.name != null) + writer.uint32(/* id 5, wireType 2 =*/ 42).string(message.name); + if (message.kind != null) + writer.uint32(/* id 6, wireType 0 =*/ 48).int32(message.kind); + if (message.startTimeUnixNano != null) + writer + .uint32(/* id 7, wireType 1 =*/ 57) + .fixed64(message.startTimeUnixNano as Long); + if (message.endTimeUnixNano != null) + writer + .uint32(/* id 8, wireType 1 =*/ 65) + .fixed64(message.endTimeUnixNano as Long); + if (message.attributes != null && message.attributes.length) + for (let i = 0; i < message.attributes.length; ++i) + KeyValue_encode( + message.attributes[i]!, + writer.uint32(/* id 9, wireType 2 =*/ 74).fork() + ).ldelim(); + if (message.droppedAttributesCount != null) + writer + .uint32(/* id 10, wireType 0 =*/ 80) + .uint32(message.droppedAttributesCount); + if (message.events != null && message.events.length) + for (let i = 0; i < message.events.length; ++i) + Event_encode( + message.events[i]!, + writer.uint32(/* id 11, wireType 2 =*/ 90).fork() + ).ldelim(); + if (message.droppedEventsCount != null) + writer + .uint32(/* id 12, wireType 0 =*/ 96) + .uint32(message.droppedEventsCount); + if (message.links != null && message.links.length) + for (let i = 0; i < message.links.length; ++i) + Link_encode( + message.links[i]!, + writer.uint32(/* id 13, wireType 2 =*/ 106).fork() + ).ldelim(); + if (message.droppedLinksCount != null) + writer + .uint32(/* id 14, wireType 0 =*/ 112) + .uint32(message.droppedLinksCount); + if (message.status != null) + Status_encode( + message.status, + writer.uint32(/* id 15, wireType 2 =*/ 122).fork() + ).ldelim(); + return writer; +} + +function Status_encode(message: IStatus, writer: Writer): Writer { + if (message.message != null) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.message); + if (message.code != null) + writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.code); + return writer; +} + +function Event_encode(message: IEvent, writer: Writer): Writer { + if (message.timeUnixNano != null) + writer + .uint32(/* id 1, wireType 1 =*/ 9) + .fixed64(message.timeUnixNano as Long); + if (message.name != null) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.name); + if (message.attributes != null && message.attributes.length) + for (let i = 0; i < message.attributes.length; ++i) + KeyValue_encode( + message.attributes[i]!, + writer.uint32(/* id 3, wireType 2 =*/ 26).fork() + ).ldelim(); + if (message.droppedAttributesCount != null) + writer + .uint32(/* id 4, wireType 0 =*/ 32) + .uint32(message.droppedAttributesCount); + return writer; +} + +function Link_encode(message: ILink, writer: Writer): Writer { + if (message.traceId != null) + writer.uint32(/* id 1, wireType 2 =*/ 10).bytes(message.traceId); + if (message.spanId != null) + writer.uint32(/* id 2, wireType 2 =*/ 18).bytes(message.spanId); + if (message.traceState != null) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.traceState); + if (message.attributes != null && message.attributes.length) + for (let i = 0; i < message.attributes.length; ++i) + KeyValue_encode( + message.attributes[i]!, + writer.uint32(/* id 4, wireType 2 =*/ 34).fork() + ).ldelim(); + if (message.droppedAttributesCount != null) + writer + .uint32(/* id 5, wireType 0 =*/ 40) + .uint32(message.droppedAttributesCount); + return writer; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7dd4a1..f4acb03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -207,6 +207,9 @@ importers: eslint-config: specifier: workspace:* version: link:../eslint-config + protobufjs: + specifier: ^7.2.6 + version: 7.2.6 rimraf: specifier: 3.0.2 version: 3.0.2 @@ -1458,7 +1461,7 @@ packages: '@opentelemetry/api': 1.7.0 '@opentelemetry/core': 1.19.0(@opentelemetry/api@1.7.0) '@opentelemetry/otlp-exporter-base': 0.46.0(@opentelemetry/api@1.7.0) - protobufjs: 7.2.5 + protobufjs: 7.2.6 dev: true /@opentelemetry/otlp-transformer@0.46.0(@opentelemetry/api@1.7.0): @@ -5852,8 +5855,8 @@ packages: object-assign: 4.1.1 react-is: 16.13.1 - /protobufjs@7.2.5: - resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==} + /protobufjs@7.2.6: + resolution: {integrity: sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==} engines: {node: '>=12.0.0'} requiresBuild: true dependencies: @@ -5867,7 +5870,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.10.6 + '@types/node': 20.11.0 long: 5.2.3 dev: true