Skip to content

[wrangler] Add metrics export configuration - #15112

Open
cf-mandarin wants to merge 18 commits into
cloudflare:mainfrom
cf-mandarin:wrangler-metrics-export-config
Open

[wrangler] Add metrics export configuration#15112
cf-mandarin wants to merge 18 commits into
cloudflare:mainfrom
cf-mandarin:wrangler-metrics-export-config

Conversation

@cf-mandarin

@cf-mandarin cf-mandarin commented Aug 10, 2026

Copy link
Copy Markdown

Fixes https://jira.cfdata.org/browse/WO-1037.

Purpose

This PR makes metrics export a first-class Wrangler configuration under observability.metrics, alongside the existing observability.logs and observability.traces settings.

Users can declare whether metrics export is enabled and which destinations should receive metrics directly in their wrangler.jsonc file:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "metrics-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-10",

  "observability": {
    "logs": {
      "enabled": true
    },
    "traces": {
      "enabled": true
    },
    "metrics": {
      "enabled": true,
      "destinations": ["opentelemetry-metrics"]
    }
  },

  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "metrics-database",
      "database_id": "11111111-1111-1111-1111-111111111111"
    }
  ],

  "r2_buckets": [
    {
      "binding": "BUCKET",
      "bucket_name": "metrics-bucket"
    }
  ]
}

The same destinations are applied to the Worker and its supported bound resources.

Metrics export can be explicitly disabled without removing the configuration block:

{
  "observability": {
    "metrics": {
      "enabled": false
    }
  }
}

Supported resources

This initial implementation supports:

  • Workers
  • D1 databases bound to the Worker
  • R2 buckets bound to the Worker

Wrangler resolves canonical D1 and R2 identifiers from local configuration or deployed Worker settings. Other resource types are not included in the reconciliation request.

Lifecycle coverage

Wrangler path Metrics export behavior
wrangler deploy Supported. Reconciles metrics after the Worker, routes, and cron triggers have been deployed.
wrangler delete Supported. Deletes the Worker first, then attempts best-effort metrics cleanup. A failed Worker deletion leaves metrics export unchanged; cleanup failures after deletion warn.
wrangler versions deploy No-op. The metrics block is removed from script settings and is not reconciled.
wrangler versions upload No-op. Observability settings are non-versioned and metrics are not reconciled.
Preview and development flows No-op. The metrics block is removed from preview settings and is not sent to the metrics export API.
Dispatch namespace deploys No-op. The deployment continues normally without metrics reconciliation.

Native Logs and Traces settings continue through their existing upload and script-settings paths. Adding a metrics-only block does not enable, disable, or otherwise change Logs or Traces.

Validation

When observability.metrics is present:

  • enabled must be explicitly set to true or false.
  • destinations is required and must be non-empty when enabled.
  • Destination names are trimmed.
  • Blank and duplicate destinations are rejected.

Implementation

Metrics export uses a separate API from the native Worker observability settings. Wrangler therefore removes metrics from Worker upload, preview, and script-settings payloads before reconciling it independently.

The reconciliation request identifies the Worker as the requester and includes the supported Worker, D1, and R2 resources. Transient API failures are retried. Configuration errors, such as unresolved bindings, retain their actionable error messages.

If reconciliation fails during a regular deployment, Wrangler warns that the primary Worker deployment succeeded but metrics export configuration was not applied. The completed Worker deployment still returns successfully.

Configuration removal semantics

Removing the entire observability section or only observability.metrics intentionally leaves any existing metrics export active. Wrangler does not call the Portal /metricsexport API when the metrics block is absent. This prevents every normal deployment, including projects that never adopted metrics export, from calling an API that is currently restricted to allowlisted accounts.

To stop an existing export, users must explicitly deploy observability.metrics.enabled: false. This differs from native Workers Logs and Traces, which are disabled when their observability configuration is removed. We plan to revisit this behavior when Wrangler can distinguish existing metrics-export state without calling the Portal API for unrelated deployments.

Rollout

The metrics export API is currently behind a Flagship rollout flag and is available only to whitelisted accounts. The internal Flagship flag name is intentionally not exposed here.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: rollout is currently restricted to allowlisted accounts.

…r-metrics-export-config

# Conflicts:
#	packages/deploy-helpers/src/deploy/deploy.ts
#	packages/deploy-helpers/src/preview/preview.ts
#	packages/workers-utils/src/config/validation.ts
#	packages/wrangler/src/__tests__/preview.test.ts
@changeset-bot

changeset-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6261c79

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@cloudflare/config Minor
@cloudflare/workers-auth Minor
@cloudflare/workers-utils Minor
wrangler Minor
@cloudflare/build-output-utils Patch
@cloudflare/vite-plugin Patch
@cloudflare/remote-bindings Patch
@cloudflare/autoconfig Patch
@cloudflare/cli-shared-helpers Patch
@cloudflare/deploy-helpers Patch
@cloudflare/vitest-pool-workers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@workers-devprod
workers-devprod requested review from a team and jamesopstad and removed request for a team August 10, 2026 11:18
@workers-devprod

workers-devprod commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/fuzzy-metrics-export.md: [@cloudflare/wrangler]
  • packages/config/src/tests/convert.test.ts: [@cloudflare/wrangler]
  • packages/config/src/tests/schema.test.ts: [@cloudflare/wrangler]
  • packages/config/src/convert.ts: [@cloudflare/wrangler]
  • packages/config/src/schema.ts: [@cloudflare/wrangler]
  • packages/config/src/types.ts: [@cloudflare/wrangler]
  • packages/deploy-helpers/src/deploy/deploy.ts: [@cloudflare/wrangler]
  • packages/deploy-helpers/src/deploy/helpers/metrics-export.ts: [@cloudflare/wrangler]
  • packages/deploy-helpers/src/index.ts: [@cloudflare/wrangler]
  • packages/deploy-helpers/src/preview/shared.ts: [@cloudflare/wrangler]
  • packages/workers-auth/src/core/scopes.ts: [@cloudflare/wrangler]
  • packages/workers-utils/src/config/environment.ts: [@cloudflare/wrangler]
  • packages/workers-utils/src/config/validation-helpers.ts: [@cloudflare/wrangler]
  • packages/workers-utils/src/config/validation.ts: [@cloudflare/wrangler]
  • packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/delete.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/deploy/core.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/deploy/metrics-export.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/preview.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/profiles.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/user.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/versions/versions.deploy.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/whoami.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/delete.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/versions/deploy.ts: [@cloudflare/wrangler]

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@pkg-pr-new

pkg-pr-new Bot commented Aug 11, 2026

Copy link
Copy Markdown
@cloudflare/autoconfig

npm i https://pkg.pr.new/@cloudflare/autoconfig@15112

@cloudflare/build-output-utils

npm i https://pkg.pr.new/@cloudflare/build-output-utils@15112

@cloudflare/config

npm i https://pkg.pr.new/@cloudflare/config@15112

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@15112

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@15112

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@15112

miniflare

npm i https://pkg.pr.new/miniflare@15112

@cloudflare/pages-functions

npm i https://pkg.pr.new/@cloudflare/pages-functions@15112

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@15112

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@15112

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@15112

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@15112

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@15112

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@15112

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@15112

wrangler

npm i https://pkg.pr.new/wrangler@15112

commit: c1484dc

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@@ -545,7 +546,7 @@ async function maybePatchSettings(
logpush: config.logpush,
tail_consumers: config.tail_consumers,
streaming_tail_consumers: config.streaming_tail_consumers,
observability: config.observability, // TODO reconcile with how regular deploy handles empty state
observability: withoutMetricsExportConfig(config.observability), // TODO reconcile with how regular deploy handles empty state

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this TODO something worth fixing now?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think we should address this in this PR. The TODO predates the metrics change and concerns broader differences in how regular and versions deploys clear non-versioned observability settings. This PR only preserves existing behavior while stripping the metrics-only configuration from versions deploys. I’d keep this as follow-up work, what do you think?

.optional(),
metrics: z
.strictObject({
enabled: z.boolean(),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the metrics object is optional but the enabled field is always required?

@cf-mandarin cf-mandarin Aug 11, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, this is intentional. Metrics export is optional, but once the block is present we require an explicit enabled: true or enabled: false. This prevents destinations-only configurations from being silently ignored and gives users an explicit way to clear existing export configuration. Do it make sense?

WorkerMetadataBinding,
} from "@cloudflare/workers-utils";

export function withoutMetricsExportConfig(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: Can we add some JSDoc comments to these functions with a brief description of what they do.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree 👍 , on it!

@@ -336,9 +351,21 @@ describe("wrangler preview", () => {
);
});

test("should create a new preview with defaults applied", async ({
test("should ignore metrics export and create a new preview", async ({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title implies we're ignoring the metrics export but all we do is write a Wrangler config but not actually check anything after to validate metrics exports were ignored?
Unless I am missing something here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch. There is a separate unit test covering assemblePreviewScriptSettings, but this integration test does not explicitly verify the preview request or absence of a metrics API call. I’ll add assertions that metrics are excluded from the preview payload and that no metrics reconciliation is attempted.

Comment on lines +29 to +31
writeWranglerConfig({
observability: { metrics: { enabled: false } },
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really needed if we already have a fallback to disable metrics?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metrics block is needed because cleanup is intentionally gated on its presence, avoiding calls to the allowlist-restricted endpoint for unrelated deletes. However, enabled: false is misleading in this test. I’ll use enabled: true and rename the test to make clear that it verifies post-delete cleanup of an actively configured export.

devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

Comment on lines +1 to +6
---
"@cloudflare/config": minor
"@cloudflare/workers-auth": minor
"@cloudflare/workers-utils": minor
"wrangler": minor
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Release notes leave out one of the packages that was changed

The release note file (.changeset/fuzzy-metrics-export.md:1-6) lists only four packages even though the deploy helper package was also modified, so that package will not get a version bump or changelog entry when the release is cut.
Impact: The published deploy-helpers package stays on its old version without the metrics-export code, and its changelog omits this change.

Why the missing entry matters for the release pipeline

packages/deploy-helpers is a published (non-private, version 0.6.6) workspace package and is not in the changesets ignore list (.changeset/config.json). This PR adds packages/deploy-helpers/src/deploy/helpers/metrics-export.ts and modifies packages/deploy-helpers/src/deploy/deploy.ts, src/preview/shared.ts, and src/index.ts, but the changeset front-matter only bumps @cloudflare/config, @cloudflare/workers-auth, @cloudflare/workers-utils, and wrangler. Repository rules (AGENTS.md / CONTRIBUTING.md) state that every change to package code requires a changeset, and @cloudflare/deploy-helpers is routinely included in changesets elsewhere in the repo history.

Suggested change
---
"@cloudflare/config": minor
"@cloudflare/workers-auth": minor
"@cloudflare/workers-utils": minor
"wrangler": minor
---
---
"@cloudflare/config": minor
"@cloudflare/deploy-helpers": minor
"@cloudflare/workers-auth": minor
"@cloudflare/workers-utils": minor
"wrangler": minor
---
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

3 participants