Skip to content

Billing: emit compute usage MeterRecord per execution - #23858

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

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

Conversation

@DylanTinianov

@DylanTinianov DylanTinianov commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What

When [Metering].MeterRecordsEnabled is on, the syncer passes the metering identity to every v2 engine, and each engine owns its ResourceManager. After each execution 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

Testing

Verified on Staging compute + gas records are emitted and accepted by ChIP.

@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

✅ No conflicts with other open PRs targeting develop

@trunk-io

trunk-io Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

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 thread core/services/workflows/v2/base_engine.go Outdated
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>
…ink-common to ae91aba3 (#2457, confidential execution duration)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@DylanTinianov DylanTinianov changed the title workflows/v2: emit cre:workflow:compute usage MeterRecord per execution (CRE-6779) Billing: emit compute usage MeterRecord per execution Oct 9, 2026
DylanTinianov and others added 3 commits October 9, 2026 14:55
…nsume confidential mark unconditionally, paralleltest/gci

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Comment thread core/services/workflows/v2/base_engine.go
When [Metering].MeterRecordsEnabled is on, the syncer hands every v2
engine a ResourceManager and the engine emits one cre:workflow:compute
METER_ACTION_USAGE record per execution, for successful and failed runs,
outside the legacy isMetering block and fail-open.

The metered duration is what the module that ran the workflow reports on
ExecutionResult.compute_duration_ms (chainlink-protos #472/#473,
chainlink-common #2464): the WASM host's guest run, or for
ConfidentialModule the enclave-measured execution_duration_ms. The engine
falls back to its own wall-clock only when nothing was reported, so it no
longer tracks which executions were delegated to the enclave, and the
DON-time suspension tracker is gone; waits inside the run count as
compute the same way capability waits already did.

Every emission logs "Emitted capability usage meter record" with
executionID, eventID, resourceType, value, orgID; that line is the
contract for the billing reconciler.

Bump chainlink-common to eff4aa59 and chainlink-protos/cre/go to
94b3b3de across all modules; add changeset.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@DylanTinianov
DylanTinianov force-pushed the CRE-6779-compute-usage-records branch from 3b0e667 to b58f8d2 Compare October 14, 2026 13:04
DylanTinianov and others added 2 commits October 14, 2026 10:39
The WASM host inside the enclave sets it on the ExecutionResult, so the
response's execution_duration_ms is no longer copied. Bump chainlink-common.

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

Routes a TEE trigger through RequirementSelectingModule and ConfidentialModule
to a mocked confidential-workflows capability and asserts the record carries
the enclave-set compute_duration_ms, not the round trip; and that a module
reporting no duration is metered from the engine's wall-clock.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Comment thread core/services/workflows/syncer/v2/handler.go Outdated
DylanTinianov and others added 3 commits October 14, 2026 11:12
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The engine builds its ResourceManager from EngineConfig.MeterRecordsEnabled
and UsageIdentity (UsageEmitter overrides beholder for tests); the syncer
handler only forwards the identity via WithUsageMetering.

Pin chainlink-protos/cre/go to the main merge of #473 and chainlink-common
to d3ec3d0d.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@DylanTinianov DylanTinianov self-assigned this Oct 14, 2026
@DylanTinianov DylanTinianov added build-test-image Will build the e2e test image in integration-tests workflow for PRs build-publish Build and Publish image to SDLC run-e2e-tests Use on your PR to run E2E tests before the merge queue labels Oct 14, 2026
DylanTinianov and others added 2 commits October 14, 2026 13:06
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@DylanTinianov
DylanTinianov marked this pull request as ready for review October 14, 2026 18:19
@DylanTinianov
DylanTinianov requested review from a team as code owners October 14, 2026 18:19
Picks up the cre:workflow:gas usage MeterRecords (capabilities #804, #813).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
DylanTinianov and others added 4 commits October 15, 2026 09:57
Pins chainlink-common#2472 so the resource_manager_utilization gauge no longer
gains a series per execution. On staging zone-a that growth pushed the OTLP
export past the 16 MiB collector limit and dropped every engine metric.

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

Resolves go.mod/go.sum conflicts by taking develop and re-pinning common to
the chainlink-common#2472 branch head (utilization gauge cardinality fix).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Matches the gas meter in LOOP plugins, which uses the server's DurableEmitter.
If none is configured the engine logs once and emits nothing.

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

Copy link
Copy Markdown

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

build-publish Build and Publish image to SDLC build-test-image Will build the e2e test image in integration-tests workflow for PRs run-e2e-tests Use on your PR to run E2E tests before the merge queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants