1import * as Axiom from "@/Axiom";
2import * as Cloudflare from "@/Cloudflare/index.ts";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6
7/**
8 * End-to-end fixture for Axiom telemetry: datasets and an ingest token
9 * declared next to the Worker, wired through the `Axiom.Telemetry` binding
10 * layer. Deterministic dataset names so re-runs reconcile the same
11 * datasets.
12 */
13export const TRACES_DATASET = "alchemy-test-otel-traces";
14export const LOGS_DATASET = "alchemy-test-otel-logs";
15
16export const Traces = Axiom.Dataset("Traces", {
17 name: TRACES_DATASET,
18 kind: "otel:traces:v1",
19});
20
21export const Logs = Axiom.Dataset("Logs", {
22 name: LOGS_DATASET,
23 kind: "otel:logs:v1",
24});
25
26export const Ingest = Axiom.ApiToken("Ingest", {
27 name: "alchemy-test-otel-ingest",
28 datasetCapabilities: {
29 [TRACES_DATASET]: { ingest: ["create"] },
30 [LOGS_DATASET]: { ingest: ["create"] },
31 },
32});
33
34export default class AxiomTracedWorker extends Cloudflare.Worker<AxiomTracedWorker>()(
35 "AxiomTracedWorker",
36 {
37 main: import.meta.url,
38 },
39 Effect.gen(function* () {
40 return {
41 fetch: Effect.gen(function* () {
42 const request = yield* HttpServerRequest;
43 const url = new URL(request.url, "http://x");
44 if (url.pathname === "/work") {
45 yield* Effect.log("axiom-work-log").pipe(
46 Effect.withSpan("axiom.child-span"),
47 );
48 return yield* HttpServerResponse.json({ marker: "axiom-did-work" });
49 }
50 return HttpServerResponse.text("axiom-ok");
51 }),
52 };
53 }).pipe(
54 // The whole observability integration: dataset endpoints + the ingest
55 // token bind onto the Worker; the built-in exporter ships each signal
56 // to its dataset, flushed per request.
57 Effect.provide(
58 Axiom.Telemetry({
59 token: Ingest,
60 traces: Traces,
61 logs: Logs,
62 serviceName: "otel-axiom-e2e",
63 }),
64 ),
65 ),
66) {}