From 4b390e028d7a4eeef554c3b84f944fd50157d7bb Mon Sep 17 00:00:00 2001 From: Danijel Martinek Date: Mon, 11 May 2026 11:43:26 +0200 Subject: [PATCH] refactor(core-shared): delete SentryTracer (replaced by OtelTracer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sentry/sentry-tracer.ts and its test removed. OtelTracer is now the active ITracer implementation. Spans flow to Sentry via @sentry/opentelemetry's SentrySpanProcessor wired in bindOtelInstrumentation → initOtelServerNode. Co-Authored-By: Claude Sonnet 4.6 --- .../sentry/sentry-tracer.test.ts | 69 ------------------- .../instrumentation/sentry/sentry-tracer.ts | 35 ---------- 2 files changed, 104 deletions(-) delete mode 100644 packages/core-shared/src/instrumentation/sentry/sentry-tracer.test.ts delete mode 100644 packages/core-shared/src/instrumentation/sentry/sentry-tracer.ts diff --git a/packages/core-shared/src/instrumentation/sentry/sentry-tracer.test.ts b/packages/core-shared/src/instrumentation/sentry/sentry-tracer.test.ts deleted file mode 100644 index fa89e6a..0000000 --- a/packages/core-shared/src/instrumentation/sentry/sentry-tracer.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// packages/core-shared/src/instrumentation/sentry/sentry-tracer.test.ts -import { describe, it, expect, vi, beforeEach } from "vitest"; - -vi.mock("@sentry/nextjs", () => ({ - startSpan: vi.fn((_opts: unknown, fn: (span: unknown) => unknown) => - fn({ setAttribute: vi.fn(), setStatus: vi.fn() }), - ), -})); - -import * as Sentry from "@sentry/nextjs"; -import { SentryTracer } from "@/instrumentation/sentry/sentry-tracer"; - -describe("SentryTracer", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it("delegates startSpan to @sentry/nextjs.startSpan", async () => { - const tracer = new SentryTracer(); - const result = await tracer.startSpan( - { name: "blog.getArticles", op: "use-case" }, - async () => "value", - ); - expect(result).toBe("value"); - expect(Sentry.startSpan).toHaveBeenCalledTimes(1); - expect((Sentry.startSpan as ReturnType).mock.calls[0]![0]).toMatchObject({ - name: "blog.getArticles", - op: "use-case", - }); - }); - - it("forwards attributes to Sentry", async () => { - const tracer = new SentryTracer(); - await tracer.startSpan( - { name: "articles.findAll", op: "repository", attributes: { collection: "articles", limit: 10 } }, - async () => undefined, - ); - expect( - (Sentry.startSpan as ReturnType).mock.calls[0]![0].attributes, - ).toEqual({ - collection: "articles", - limit: 10, - }); - }); - - it("propagates errors from the wrapped function", async () => { - const tracer = new SentryTracer(); - await expect( - tracer.startSpan({ name: "x" }, async () => { - throw new Error("boom"); - }), - ).rejects.toThrow("boom"); - }); - - it("ISpan adapter forwards setAttribute and setStatus to Sentry's span", async () => { - const sentrySpan = { setAttribute: vi.fn(), setStatus: vi.fn() }; - (Sentry.startSpan as ReturnType).mockImplementationOnce( - (_opts: unknown, fn: (span: unknown) => unknown) => fn(sentrySpan), - ); - const tracer = new SentryTracer(); - await tracer.startSpan({ name: "x" }, async (span) => { - span.setAttribute("k", "v"); - span.setStatus("error", "msg"); - return undefined; - }); - expect(sentrySpan.setAttribute).toHaveBeenCalledWith("k", "v"); - expect(sentrySpan.setStatus).toHaveBeenCalled(); - }); -}); diff --git a/packages/core-shared/src/instrumentation/sentry/sentry-tracer.ts b/packages/core-shared/src/instrumentation/sentry/sentry-tracer.ts deleted file mode 100644 index 2ff0a46..0000000 --- a/packages/core-shared/src/instrumentation/sentry/sentry-tracer.ts +++ /dev/null @@ -1,35 +0,0 @@ -// packages/core-shared/src/instrumentation/sentry/sentry-tracer.ts -import * as Sentry from "@sentry/nextjs"; -import type { ITracer, ISpan, SpanOpts } from "../tracer.interface"; - -export class SentryTracer implements ITracer { - async startSpan(opts: SpanOpts, fn: (span: ISpan) => Promise): Promise { - // Filter out null values — Sentry SpanAttributes doesn't allow null - const attributes = opts.attributes - ? Object.fromEntries( - Object.entries(opts.attributes).filter(([, v]) => v !== null), - ) as Record - : undefined; - - return Sentry.startSpan( - { - name: opts.name, - op: opts.op, - attributes, - }, - async (sentrySpan) => { - const adapter: ISpan = { - setAttribute(key, value) { - sentrySpan?.setAttribute?.(key, value as string | number | boolean); - }, - setStatus(status, message) { - // Sentry v8+ uses { code: number, message?: string }; we map our enum - const code = status === "ok" ? 1 : 2; - sentrySpan?.setStatus?.({ code, message }); - }, - }; - return fn(adapter); - }, - ); - } -}