refactor(core-shared): delete SentryTracer (replaced by OtelTracer)

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 <noreply@anthropic.com>
This commit is contained in:
2026-05-11 11:43:26 +02:00
parent 149f91255c
commit 4b390e028d
2 changed files with 0 additions and 104 deletions

View File

@@ -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<typeof vi.fn>).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<typeof vi.fn>).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<typeof vi.fn>).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();
});
});

View File

@@ -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<T>(opts: SpanOpts, fn: (span: ISpan) => Promise<T>): Promise<T> {
// 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<string, string | number | boolean>
: 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);
},
);
}
}