|
9 | 9 | // "kv_namespaces": [ |
10 | 10 | // { "binding": "SITES_KV", "id": "YOUR_KV_NAMESPACE_ID" } |
11 | 11 | // ], |
| 12 | + // Strategy B tail worker — 100% capture of producer errors that the |
| 13 | + // framework's direct-POST channel can't see (uncaught throws, exceededCpu, |
| 14 | + // exceededMemory, raw console.error). Invoked by CF on every request to |
| 15 | + // this worker; filters and forwards to deco-otel-ingest via in-account |
| 16 | + // service binding. See the observability block below for the full |
| 17 | + // three-channel model. |
| 18 | + "tail_consumers": [ |
| 19 | + { "service": "deco-otel-tail" } |
| 20 | + ], |
| 21 | + // Worker version (build SHA / deployment id) — surfaced as |
| 22 | + // `service.version` on every span / log line by `instrumentWorker`. |
| 23 | + "version_metadata": { |
| 24 | + "binding": "CF_VERSION_METADATA" |
| 25 | + }, |
| 26 | + // Cloudflare Analytics Engine dataset for high-cardinality counters |
| 27 | + // (per-route request counts, cache hit/miss, request duration). |
| 28 | + // Queryable via SQL from the CF dashboard. Replace YOUR_SITE_NAME with |
| 29 | + // the actual site slug (must match DECO_SITE_NAME below). |
| 30 | + // "analytics_engine_datasets": [ |
| 31 | + // { |
| 32 | + // "binding": "DECO_METRICS", |
| 33 | + // "dataset": "deco_metrics_YOUR_SITE_NAME" |
| 34 | + // } |
| 35 | + // ], |
| 36 | + // Observability — three-channel model (Strategy B, see decocms/deco-start D-8). |
| 37 | + // |
| 38 | + // Identity: |
| 39 | + // `DECO_SITE_NAME` drives `service.name` on every span and log line. |
| 40 | + // `DECO_ENV_NAME` drives `deployment.environment`. |
| 41 | + // |
| 42 | + // Three channels, each owning a different slice of the observability cube: |
| 43 | + // |
| 44 | + // 1. CF Destinations (`observability.{logs,traces}.destinations` below) |
| 45 | + // Sampled 1% logs + 1% traces. Bulk volume. |
| 46 | + // 2. Direct-POST in-worker (`DECO_OTEL_*_ENDPOINT`, resolved at |
| 47 | + // `instrumentWorker` boot) |
| 48 | + // - METRICS_ENDPOINT → direct POST `/v1/metrics` (CF Destinations |
| 49 | + // doesn't support OTLP metrics). Buffered per-isolate, flushed |
| 50 | + // via `ctx.waitUntil` after every request. |
| 51 | + // - LOGS_ENDPOINT → direct POST `/v1/logs` for framework |
| 52 | + // `logger.error(...)` only (100% capture, rate-limited). |
| 53 | + // 3. Tail Worker (`tail_consumers` above → deco-otel-tail) |
| 54 | + // Catches uncaught throws, exceededCpu/Memory, raw console.error — |
| 55 | + // what direct-POST can't see and CF Destinations would sample away. |
| 56 | + // |
| 57 | + // Coverage matrix: |
| 58 | + // framework logger.error → direct-POST (100%, rate-limited) |
| 59 | + // framework span errors → CF Destinations + tail (1% sampled + 100%) |
| 60 | + // uncaught throws → tail worker (100%) |
| 61 | + // exceededCpu / exceededMemory → tail worker (100%) |
| 62 | + // raw console.error → tail worker (100%) |
| 63 | + // console.log / console.warn → CF Destinations (1% sampled) |
| 64 | + // OTel spans → CF Destinations (1% sampled) |
| 65 | + // OTel metrics → direct-POST (100%, buffered) |
| 66 | + "vars": { |
| 67 | + "DECO_SITE_NAME": "storefront", |
| 68 | + "DECO_ENV_NAME": "production", |
| 69 | + "DECO_OTEL_METRICS_ENDPOINT": "https://deco-otel-ingest.deco-cx.workers.dev/v1/metrics", |
| 70 | + "DECO_OTEL_LOGS_ENDPOINT": "https://deco-otel-ingest.deco-cx.workers.dev/v1/logs" |
| 71 | + }, |
| 72 | + // CF-native observability: structured console.* output and auto- |
| 73 | + // instrumented traces (fetch/KV/R2/DO subrequests + @opentelemetry/api |
| 74 | + // global-tracer spans the framework's withTracing() emits) are |
| 75 | + // captured by the Cloudflare runtime, retained in the CF dashboard |
| 76 | + // via persist:true, AND forwarded to deco-otel-ingest → |
| 77 | + // stats-lake ClickHouse via the named destinations below. |
| 78 | + // |
| 79 | + // The named destinations are registered out-of-band in the CF |
| 80 | + // dashboard (Workers & Pages → Observability → Destinations) against |
| 81 | + // the deco-cx account. Wrangler resolves these names to the URLs + |
| 82 | + // any auth headers configured there. |
12 | 83 | "observability": { |
| 84 | + // Master switch — without enabled:true at the top level CF |
| 85 | + // captures nothing, regardless of the sub-block flags. |
| 86 | + "enabled": true, |
13 | 87 | "logs": { |
14 | 88 | "enabled": true, |
15 | | - "invocation_logs": true |
| 89 | + "invocation_logs": true, |
| 90 | + // 1% of info/warn logs forward to deco-otel-ingest. Errors are |
| 91 | + // NOT subject to this rate — they're covered by both the |
| 92 | + // direct-POST channel (framework logger.error) and the tail |
| 93 | + // worker (uncaught throws, exceededCpu, raw console.error). |
| 94 | + "head_sampling_rate": 0.01, |
| 95 | + "persist": true, |
| 96 | + "destinations": ["deco-otel-ingest-logs"] |
| 97 | + }, |
| 98 | + "traces": { |
| 99 | + "enabled": true, |
| 100 | + // Fleet-scale cost discipline — see `@decocms/start` |
| 101 | + // docs/observability.md "Sampling" section. 1% gives 2.5x |
| 102 | + // headroom against the 5B-events/day CF cap at projected |
| 103 | + // fleet traffic. |
| 104 | + "head_sampling_rate": 0.01, |
| 105 | + "persist": true, |
| 106 | + "destinations": ["deco-otel-ingest-traces"] |
16 | 107 | } |
17 | 108 | } |
18 | 109 | } |
0 commit comments