Skip to content

workflows/v2: emit cre:workflow:compute usage MeterRecord per execution (CRE-6779) - #23858

Draft
DylanTinianov wants to merge 3 commits into
developfrom
CRE-6779-compute-usage-records
Draft

DylanTinianov wants to merge 3 commits into
developfrom
CRE-6779-compute-usage-records

Conversation

@DylanTinianov

@DylanTinianov DylanTinianov commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

CRE-6779. Depends on chainlink-common #2428; pinned to that branch merged with develop's common pin until #2428 and #23910 land, then re-bump to main.

What

When [Metering].MeterRecordsEnabled is on (the same gate as durable resource metering; no separate flag), the syncer builds a ResourceManager (beholder emitter) and hands it to every v2 engine (syncerV2.WithUsageMeter, EngineConfig.UsageMeter/UsageIdentity). After computeDuration is known, baseEngine.emitComputeUsage emits one METER_ACTION_USAGE record:

Field Value
resource type cre:workflow:compute, value in ms
ResourceId <workflow_id>:<execution_id>
EventId execution id (one compute record per execution, identical on every node; billing builds cre:workflow:<wf>:<exec>:<exec>)
Identity.Service / Don.DonId workflow-engine / local node's workflow DON
Identity.ResourcePool / ResourcePoolId cre:workflow:compute / cre:workflow:compute
OrgId engine's resolved org id

Behaviour:

  • emitted for successful and failed executions (the compute happened)
  • outside the legacy isMetering block, so a legacy metering failure cannot suppress it
  • skipped when the execution was delegated to the confidential module: ConfidentialModule now marks executions it handled and the engine consumes the mark (EngineConfig.ConfidentialExecutions). Confidential compute is metered from the enclave-reported duration in a follow-up (CRE-6780).
  • fail-open: never affects the execution

Every emission logs Emitted capability usage meter record with executionID, eventID, resourceType, value, orgID. That line is a contract for the billing reconciler (it compares ran vs emitted vs billed) and is asserted in the test.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ No conflicts with other open PRs targeting CRE-6778-capability-usage-flag

@github-actions

Copy link
Copy Markdown
Contributor

I see you updated files related to core. Please run make gocs in the root directory to add a changeset as well as in the text include at least one of the following tags:

  • #added For any new functionality added.
  • #breaking_change For any functionality that requires manual action for the node to boot.
  • #bugfix For bug fixes.
  • #changed For any change to the existing functionality.
  • #db_update For any feature that introduces updates to database schema.
  • #deprecation_notice For any upcoming deprecation functionality.
  • #internal For changesets that need to be excluded from the final changelog.
  • #nops For any feature that is NOP facing and needs to be in the official Release Notes for the release.
  • #removed For any functionality/config that is removed.
  • #updated For any functionality that is updated.
  • #wip For any change that is not ready yet and external communication about it should be held off till it is feature complete.

@trunk-io

trunk-io Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
TestScripts/node/validate The test 'TestScripts/node/validate' failed without providing specific error details. Logs ↗︎
TestConfigDocs The test failed because the actual documentation content did not match the expected documentation string. Logs ↗︎
TestScripts/node/validate/fallback-override The test failed during a configuration validation step, but the specific reason for failure is not provided in the log. Logs ↗︎
TestScripts/node/validate/default The test failed during the execution of a node validation command, but the specific cause of failure is not detailed in the log. Logs ↗︎

... and 10 more

View Full Report ↗︎ ⋅ Docs

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Failed emissions are logged as successful, and disabled metering leaks confidential execution marks.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Risk Rating: MEDIUM

Adds per-execution compute usage metering for workflow v2 engines, including confidential-execution exclusion and billing reconciliation logs.

Changes:

  • Wires capability usage metering into workflow engines.
  • Emits compute usage for successful and failed executions.
  • Tracks confidential executions to avoid duplicate billing.

Scrupulous human review: ResourceManager failure reporting and confidential tracking lifecycle.

File Description
core/​services/​workflows/​v2/​config.go Adds usage metering configuration.
core/​services/​workflows/​v2/​confidential_module.go Tracks confidential executions.
core/​services/​workflows/​v2/​compute_usage_test.go Tests compute usage emission.
core/​services/​workflows/​v2/​base_engine.go Emits compute usage records.
core/​services/​workflows/​syncer/​v2/​handler.go Wires and manages the usage meter.
core/​services/​cre/​cre.go Creates the feature-gated ResourceManager.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +1063 to +1068
if e.cfg.UsageMeter == nil {
return
}
if e.cfg.ConfidentialExecutions != nil && e.cfg.ConfidentialExecutions.TookExecution(executionID) {
return
}
DylanTinianov and others added 3 commits October 6, 2026 13:27
…on (CRE-6779)

When [Metering].CapabilityUsageEnabled is set, the syncer builds a
ResourceManager and every v2 engine emits one METER_ACTION_USAGE record per
execution after computeDuration is known:

- resource type cre:workflow:compute, value in milliseconds
- Utilization.ResourceId "<workflow_id>:<execution_id>", EventId = execution id
  (identical on every node; billing derives
  cre:workflow:<wf>:<exec>:<exec>)
- Identity.Service workflow-engine, DON id from the local node, org from the
  engine's resolved org id

Emitted for successful and failed executions, outside the legacy metering
block so a legacy metering failure cannot suppress it, and skipped when the
execution was delegated to the confidential module (ConfidentialModule now
tracks the executions it handled; the enclave path meters those).

Each emission logs "Emitted capability usage meter record" with executionID,
eventID, resourceType, value and orgID. That line is a contract for the
billing reconciler and is covered by a unit test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ntract

Identity.ResourcePool and ResourcePoolID are now "cre:workflow:compute",
derived via resourcemanager.WithWorkflowUsagePool, matching the
Billing <-> Decentralized stack contract. Bumps chainlink-common.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… CapabilityUsageEnabled

chainlink-common #2428 dropped the separate CapabilityUsageEnabled flag per
review: capability usage records share the existing [Metering].MeterRecordsEnabled
gate with durable resource metering. The syncer now builds the compute usage
ResourceManager when MeterRecordsEnabled is set, next to the spec meter.

Bumps chainlink-common to 16997122620e in all modules: CRE-6781-emit-usage-value
merged with develop's current pin 8fdc7816. Re-bump to main once #2428 and the
develop bump #23910 land.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cl-sonarqube-production

Copy link
Copy Markdown

Quality Gate failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE SonarQube for IDE

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants