From 5c17bb42874469b95b23ed0fe325226111178363 Mon Sep 17 00:00:00 2001 From: snek Date: Wed, 4 Dec 2024 14:14:37 +0100 Subject: [PATCH] fix(unstable): otel context with multiple keys (#27230) `SafeMap` treats its argument as an object with a "length" and index properties, rather than a generic iterator, so every time we cloned it, it was dropping all the data. --- ext/telemetry/telemetry.ts | 14 ++++++------ tests/specs/cli/otel_basic/__test__.jsonc | 4 ++++ tests/specs/cli/otel_basic/context.ts | 26 +++++++++++++++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 tests/specs/cli/otel_basic/context.ts diff --git a/ext/telemetry/telemetry.ts b/ext/telemetry/telemetry.ts index e8065e8a3b..e9e38d1592 100644 --- a/ext/telemetry/telemetry.ts +++ b/ext/telemetry/telemetry.ts @@ -39,7 +39,6 @@ const { SafeWeakMap, Array, ObjectEntries, - SafeMap, ReflectApply, SymbolFor, Error, @@ -617,26 +616,25 @@ class SpanExporter { const CURRENT = new AsyncVariable(); class Context { - #data = new SafeMap(); + #data: Record = { __proto__: null }; - // deno-lint-ignore no-explicit-any - constructor(data?: Iterable | null | undefined) { - this.#data = data ? new SafeMap(data) : new SafeMap(); + constructor(data?: Record | null | undefined) { + this.#data = { __proto__: null, ...data }; } getValue(key: symbol): unknown { - return this.#data.get(key); + return this.#data[key]; } setValue(key: symbol, value: unknown): Context { const c = new Context(this.#data); - c.#data.set(key, value); + c.#data[key] = value; return c; } deleteValue(key: symbol): Context { const c = new Context(this.#data); - c.#data.delete(key); + delete c.#data[key]; return c; } } diff --git a/tests/specs/cli/otel_basic/__test__.jsonc b/tests/specs/cli/otel_basic/__test__.jsonc index 05e23d32e9..e7f8d17c7a 100644 --- a/tests/specs/cli/otel_basic/__test__.jsonc +++ b/tests/specs/cli/otel_basic/__test__.jsonc @@ -19,6 +19,10 @@ { "args": "run -A main.ts metric.ts", "output": "metric.out" + }, + { + "args": "run -A --unstable-otel context.ts", + "output": "" } ] } diff --git a/tests/specs/cli/otel_basic/context.ts b/tests/specs/cli/otel_basic/context.ts new file mode 100644 index 0000000000..cef0dbd81a --- /dev/null +++ b/tests/specs/cli/otel_basic/context.ts @@ -0,0 +1,26 @@ +import { assertEquals } from "@std/assert"; + +const { ContextManager } = Deno.telemetry; + +const cm = new ContextManager(); + +const a = cm.active(); +const b = a.setValue("b", 1); +const c = b.setValue("c", 2); + +const subB = c.deleteValue("b"); +const subC = subB.deleteValue("c"); + +assertEquals(a.getValue("b"), undefined); +assertEquals(b.getValue("b"), 1); +assertEquals(c.getValue("b"), 1); + +assertEquals(a.getValue("c"), undefined); +assertEquals(b.getValue("c"), undefined); +assertEquals(c.getValue("c"), 2); + +assertEquals(subB.getValue("b"), undefined); +assertEquals(subB.getValue("c"), 2); + +assertEquals(subC.getValue("b"), undefined); +assertEquals(subC.getValue("c"), undefined);