## Common Errors ### "Logs not appearing" **Cause:** Observability disabled, Worker not redeployed, no traffic, low sampling rate, or log size exceeds 256 KB **Solution:** ```bash # Verify config cat wrangler.jsonc | jq '.observability' # Check deployment wrangler deployments list # Test with curl curl https://your-worker.workers.dev ``` Ensure `observability.enabled = true`, redeploy Worker, check `head_sampling_rate`, verify traffic ### "Traces not being captured" **Cause:** Traces not enabled, incorrect sampling rate, Worker not redeployed, or destination unavailable **Solution:** ```jsonc // Temporarily set to 100% sampling for debugging { "observability": { "enabled": true, "head_sampling_rate": 1.0, "traces": { "enabled": true } } } ``` Ensure `observability.traces.enabled = true`, set `head_sampling_rate` to 1.0 for testing, redeploy, check destination status ## Limits | Resource/Limit | Value | Notes | |----------------|-------|-------| | Max log size | 256 KB | Logs exceeding this are truncated | | Default sampling rate | 1.0 (100%) | Reduce for high-traffic Workers | | Max destinations | Varies by plan | Check dashboard | | Trace context propagation | 100 spans max | Deep call chains may lose spans | | Analytics Engine write rate | 25 writes/request | Excess writes dropped silently | ## Performance Gotchas ### Spectre Mitigation Timing **Problem:** `Date.now()` and `performance.now()` have reduced precision (coarsened to 100μs) **Cause:** Spectre vulnerability mitigation in V8 **Solution:** Accept reduced precision or use Workers Traces for accurate timing ```typescript // Date.now() is coarsened - trace spans are accurate export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { // For user-facing timing, Date.now() is fine const start = Date.now(); const response = await processRequest(request); const duration = Date.now() - start; // For detailed performance analysis, use Workers Traces instead return response; } } ``` ### Analytics Engine _sample_interval Aggregation **Problem:** Queries return incorrect totals when not multiplying by `_sample_interval` **Cause:** Analytics Engine stores sampled data points, each representing multiple events **Solution:** Always multiply counts/sums by `_sample_interval` in aggregations ```sql -- WRONG: Undercounts actual events SELECT blob1 AS customer_id, COUNT(*) AS total_calls FROM api_usage GROUP BY customer_id; -- CORRECT: Accounts for sampling SELECT blob1 AS customer_id, SUM(_sample_interval) AS total_calls FROM api_usage GROUP BY customer_id; ``` ### Trace Context Propagation Limits **Problem:** Deep call chains lose trace context after 100 spans **Cause:** Cloudflare limits trace depth to prevent performance impact **Solution:** Design for flatter architectures or use custom correlation IDs for deep chains ```typescript // For deep call chains, add custom correlation ID const correlationId = crypto.randomUUID(); console.log({ correlationId, event: 'request_start' }); // Pass correlationId through headers to downstream services await fetch('https://api.example.com', { headers: { 'X-Correlation-ID': correlationId } }); ``` ## Pricing (2026) ### Workers Traces - **GA Pricing (starts March 1, 2026):** - $0.10 per 1M trace spans captured - Retention: 14 days included - **Free tier:** 10M trace spans/month - **Note:** Beta usage (before March 1, 2026) is free ### Workers Logs - **Included:** Free for all Workers - **Logpush:** Requires Business/Enterprise plan ### Analytics Engine - **Included:** 10M writes/month on Paid Workers plan - **Additional:** $0.25 per 1M writes beyond included quota