| 1 | import { describe, it } from "@effect/vitest" |
| 2 | import { strictEqual } from "@effect/vitest/utils" |
| 3 | import { Option } from "effect" |
| 4 | import { Headers, HttpTraceContext } from "effect/http" |
| 5 | |
| 6 | const traceId = "80f198ee56343ba864fe8b2a57d3eff7" |
| 7 | const spanId = "e457b5a2e4d86bd1" |
| 8 | |
| 9 | const assertSampled = (headers: Record<string, string>, sampled: boolean) => { |
| 10 | const span = Option.getOrThrow(HttpTraceContext.fromHeaders(Headers.fromInput(headers))) |
| 11 | strictEqual(span.traceId, traceId) |
| 12 | strictEqual(span.spanId, spanId) |
| 13 | strictEqual(span.sampled, sampled) |
| 14 | } |
| 15 | |
| 16 | describe("HttpTraceContext", () => { |
| 17 | describe("fromHeaders", () => { |
| 18 | it("accepts single-header B3 debug sampling", () => { |
| 19 | assertSampled({ b3: `${traceId}-${spanId}-d` }, true) |
| 20 | }) |
| 21 | |
| 22 | it("accepts legacy X-B3-Sampled: true", () => { |
| 23 | assertSampled({ "X-B3-TraceId": traceId, "X-B3-SpanId": spanId, "X-B3-Sampled": "true" }, true) |
| 24 | }) |
| 25 | |
| 26 | it("lets X-B3-Flags debug override X-B3-Sampled: 0", () => { |
| 27 | assertSampled({ |
| 28 | "X-B3-TraceId": traceId, |
| 29 | "X-B3-SpanId": spanId, |
| 30 | "X-B3-Sampled": "0", |
| 31 | "X-B3-Flags": "1" |
| 32 | }, true) |
| 33 | }) |
| 34 | |
| 35 | it("rejects an all-zero W3C trace-id", () => { |
| 36 | strictEqual( |
| 37 | Option.isNone(HttpTraceContext.fromHeaders(Headers.fromInput({ |
| 38 | traceparent: `00-${"0".repeat(32)}-${spanId}-01` |
| 39 | }))), |
| 40 | true |
| 41 | ) |
| 42 | }) |
| 43 | |
| 44 | it("rejects an all-zero W3C parent-id", () => { |
| 45 | strictEqual( |
| 46 | Option.isNone(HttpTraceContext.fromHeaders(Headers.fromInput({ |
| 47 | traceparent: `00-${traceId}-${"0".repeat(16)}-01` |
| 48 | }))), |
| 49 | true |
| 50 | ) |
| 51 | }) |
| 52 | }) |
| 53 | }) |