Cloudflare

TracesMetricsApp LogsCustom LogsProfiling

1. Prerequisites

Wrangler installed v2.2 or newer. Check your version:

1wrangler version

2. Install

1 Install the Worker APM package

1npm i @middleware.io/agent-apm-worker

2 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 env in 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

KeyWherePurposeExample
SERVICE_NAMEWrangler varsLogical service name for APMorders-worker
MW_API_KEYWrangler secretAuth token for Middleware(secret)
MW_TARGETWrangler varsIngest endpoint (serverless)https://{ACCOUNT-UID}.middleware.io
consoleLogEnabledinit optionPrint instrumented logs to consolefalse / true

(Names/usage align with the Middleware Worker agent options.) (docs.middleware.io, npm)

8. Troubleshooting

  • No traces/logs:
    • Confirm init(...) is called and track(request, ctx) wraps every request.
    • Check that accountKey/target are set (or bound via env).
  • Upstream service not showing as a child span:
    • Use sdk.fetch(...) instead of fetch(...) to propagate context.
  • Local dev secrets:
    • Use wrangler secret put for real secrets and .dev.vars for local-only values.
  • Multiple environments:
    • Define vars per environment in wrangler.toml ([env.staging], [env.production]).

Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.