Cloudflare
| Traces | Metrics | App Logs | Custom Logs | Profiling |
|---|---|---|---|---|
| ✅ | ✖ | ✖ | ✅ | ✖ |
1. Prerequisites#
Wrangler installed v2.2 or newer. Check your version:
1wrangler version2. Install#
1 Install the Worker APM package#
1npm i @middleware.io/agent-apm-worker2 Import the tracker#
1import { init, track } from '@middleware.io/agent-apm-worker';3 Initialize the tracker (once per isolate)#
Add this near the top of your Worker module (or inside fetch as shown on the docs page):
1init({
2 serviceName: "{APM-SERVICE-NAME}",
3 accountKey: "<MW_API_KEY>",
4 target: "https://{ACCOUNT-UID}.middleware.io",
5 consoleLogEnabled: false, // set true to see instrumented logs locally
6});3. Capture application data#
- Trace the incoming request Use track(request, ctx) and return via sdk.sendResponse(response):
1export default { 2 async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { 3 const sdk = track(request, ctx); 4 5 // your app logic 6 const response = new Response("ok", { status: 200 }); 7 8 return sdk.sendResponse(response); 9 }, 10}; - Trace upstream calls (HTTP client propagation) If your Worker calls an external API, use
sdk.fetch(...)to propagate context automatically:1const sdk = track(request, ctx); 2const url = new URL(request.url); 3const upstream = await sdk.fetch(`https://httpbin.org${url.pathname}`); 4return sdk.sendResponse(upstream);
4. Custom logs (optional)#
Emit structured logs correlated with the current trace:
1// sdk.logger.SEVERITY(message, attributes?)
2sdk.logger.error("error test");
3sdk.logger.error("error with attributes", { "log.file.name": "error.log" });
4sdk.logger.info("info test");
5sdk.logger.debug("debug test");
6sdk.logger.warn("warn test");5. Configure secrets & env (Wrangler)#
Use Wrangler vars/secrets to avoid hardcoding keys:
- wrangler.toml
1name = "my-worker" 2 main = "src/index.ts" 3 compatibility_date = "2024-12-01" 4 5 [vars] 6 SERVICE_NAME = "orders-worker" 7 MW_TARGET = "https://<ACCOUNT-UID>.middleware.io" 8 9 # Per-environment overrides 10 [env.staging.vars] 11 SERVICE_NAME = "orders-worker-staging" 12 13 [env.production.vars] 14 SERVICE_NAME = "orders-worker" - Set your API key as a secret:
1wrangler secret put MW_API_KEY 2 # optionally per-env: 3 wrangler secret put MW_API_KEY --env production - Then read from
envin your Worker:1init({ 2 serviceName: env.SERVICE_NAME, 3 accountKey: env.MW_API_KEY, // bound secret 4 target: env.MW_TARGET, 5 consoleLogEnabled: false, 6});
6. View your data#
After deployment, give it 3–5 minutes, then open Middleware to see:
- Traces (incoming Worker requests, plus any upstream calls done via
sdk.fetch) - Logs (from
sdk.logger.*) - Profiling is not yet available for Cloudflare Workers in Middleware.
7. Environment variables#
| Key | Where | Purpose | Example |
|---|---|---|---|
SERVICE_NAME | Wrangler vars | Logical service name for APM | orders-worker |
MW_API_KEY | Wrangler secret | Auth token for Middleware | (secret) |
MW_TARGET | Wrangler vars | Ingest endpoint (serverless) | https://{ACCOUNT-UID}.middleware.io |
consoleLogEnabled | init option | Print instrumented logs to console | false / true |
(Names/usage align with the Middleware Worker agent options.) (docs.middleware.io, npm)
8. Troubleshooting#
- No traces/logs:
- Confirm
init(...)is called andtrack(request, ctx)wraps every request. - Check that
accountKey/targetare set (or bound via env).
- Confirm
- Upstream service not showing as a child span:
- Use
sdk.fetch(...)instead offetch(...)to propagate context.
- Use
- Local dev secrets:
- Use
wrangler secret putfor real secrets and.dev.varsfor local-only values.
- Use
- Multiple environments:
- Define
varsper environment inwrangler.toml([env.staging],[env.production]).
- Define
Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us or join our Slack channel.
What did you think of this content?