Observability
OpenTelemetry, instrumentedFetch, server timings, health endpoints.
v2 traz observability na caixa: traces OpenTelemetry, headers Server-Timing, métricas de health e tail logs do Worker. Esta página cobre o que vem grátis e como exportar para o coletor que você quiser.
OpenTelemetry
@decocms/start/observability configura OTel automaticamente. Os pontos de auto-instrumentação:
- Cada request HTTP → span de root para o response.
- Cada chamada de loader → span filho com nome do loader, tempo, status.
- Cada chamada de matcher → span filho com veredito.
- Cada
instrumentedFetch(incluindovtexFetch,shopifyFetch) → span filho com URL, método, status, tempo. - Cada renderização de section → span filho com nome.
Atributos comuns:
service.name = "minha-loja"
service.version = "<git-sha>"
http.method = "GET"
http.url = "https://minha-loja.com/p/produto"
deco.section = "site/sections/Hero/Hero.tsx"
deco.profile = "pdp"
deco.cache.status = "HIT"
Exportando
Default: spans são logados ao stdout (visível em wrangler tail ). Para enviar a um coletor, configure exportador:
// src/setup.ts
import { configureObservability } from "@decocms/start/observability";
configureObservability({
exporter: "otlp",
endpoint: env.OTEL_ENDPOINT,
headers: { Authorization: `Bearer ${env.OTEL_TOKEN}` },
});
Onde rotear:
| Coletor | Notas |
|---|---|
| Honeycomb | OTLP nativo; exporter funciona out-of-box |
| Grafana Tempo | Aceita OTLP; pareie com Loki para logs |
| Datadog | Use vendor de OTel; alguns atributos são renomeados |
| New Relic | OTLP nativo |
Veja HyperDX skill para o setup canônico em produção da deco.cx.
Server-Timing headers
Cada response carrega timings:
Server-Timing: total;dur=125, vtex.pdp;dur=80, render;dur=15, cache;dur=2
Inspect em devtools tab Network → coluna Timing. Útil para spot-check de gargalos sem abrir o coletor de tracing.
@decocms/start emite por default. Para customizar, use addServerTiming :
import { addServerTiming } from "@decocms/start/observability";
const fetchData = async () => {
const start = performance.now();
const data = await fetchUpstream();
addServerTiming("upstream", performance.now() - start);
return data;
};
Health endpoint
/_health retorna 200 com check básico. Use para liveness/readiness probes:
curl https://minha-loja.com/_health
# → { "status": "ok", "version": "abc123" }
Adicione checks custom:
import { addHealthCheck } from "@decocms/start/observability";
addHealthCheck("vtex", async () => {
const res = await fetch("https://loja.vtexcommercestable.com.br/api/...");
return res.ok ? "ok" : "degraded";
});
/_health agrega; status all-ok responde 200, qualquer “degraded” responde 503.
Métricas custom
import { recordMetric } from "@decocms/start/observability";
recordMetric("cart.items_added", 1, { product_id: "123" });
recordMetric("checkout.duration_ms", 1250);
Exportadas via mesmo OTLP endpoint dos traces. Configure por separado se precisar:
configureObservability({
exporter: "otlp",
endpoint: env.OTEL_ENDPOINT,
metrics: {
endpoint: env.OTEL_METRICS_ENDPOINT,
interval: 60_000,
},
});
instrumentedFetch
Coberto em Loaders. Lembrete:
import { createInstrumentedFetch } from "@decocms/start/sdk/instrumentedFetch";
const vtexFetch = createInstrumentedFetch("vtex");
Toda chamada feita por essa instância pega seu próprio span com a label “vtex”. @decocms/apps faz automaticamente quando você roda setVtexFetch(createInstrumentedFetch("vtex")) em setup.
Tail logs
npx wrangler tail --format pretty
Stream de requests em tempo real, com console.log e errors. Filtros úteis:
# só errors
npx wrangler tail --status error
# por path
npx wrangler tail --search "/p/"
# por região
npx wrangler tail --colo gru01
Tail logs são complementares para tracing — bom para reativo (algo está quebrado agora) vs traces (analise tendência ao longo do tempo).
Sentry
Para tracking de erro de usuário-visível, integre Sentry:
import * as Sentry from "@sentry/cloudflare";
Sentry.init({
dsn: env.SENTRY_DSN,
tracesSampleRate: 0.01,
});
@sentry/cloudflare é compatível com Workers. Exception capture acontece automaticamente quando handlers do Worker lançam.
Sentry não vem ligado por padrão — instale @sentry/cloudflare e chame o init dele a partir do setup.ts se quiser.
Real User Monitoring (RUM)
Para Core Web Vitals (LCP, INP, CLS), client-side:
import { onCLS, onLCP, onINP } from "web-vitals";
onLCP((metric) => {
fetch("/api/rum", { method: "POST", body: JSON.stringify(metric) });
});
Expose /api/rum como server function que encaminha pro coletor. Default é encaminhar pro mesmo OTel endpoint dos server traces, mas pode ser separado.
Dashboards
Padrões de dashboard típicos:
| Painel | Query |
|---|---|
| Request rate | count(spans) where service.name="minha-loja" |
| p50/p95/p99 latency | percentile(duration_ms) where http.method="GET" |
| Cache hit rate | count(spans) where deco.cache.status="HIT" / total |
| Errors | count(spans) where status="error" |
| Slow loaders | top(spans) where deco.loader.* and duration_ms>500 |
Em Grafana: queries Tempo + Loki. Em Honeycomb: bookmarks vão diretas. Em Datadog: dashboards APM.
Custos
Tracing pesado vira ruído quando volume cresce. Defaults:
- Sample 10% de requests bem-sucedidos.
- Sample 100% de errors (sempre logue).
- Sample 100% de requests > 1s (sempre logue lentos).
Override:
configureObservability({
sampleRate: 0.05, // 5% baseline
errorSampleRate: 1.0, // 100% de errors
slowThreshold: 2000, // log requests > 2s
});
Veja também
Found an error or want to improve this page?
Edit this page