Skip to content

feat(server): meter bytes transferred on forward deliveries#6240

Merged
ErickRDev merged 6 commits into
masterfrom
erickr/NAN-5426/meter-webhook-forward
May 28, 2026
Merged

feat(server): meter bytes transferred on forward deliveries#6240
ErickRDev merged 6 commits into
masterfrom
erickr/NAN-5426/meter-webhook-forward

Conversation

@ErickRDev

Copy link
Copy Markdown
Contributor

Track HTTP request/response bytes per webhook delivery hop via a
metering transport. Accumulate across all URLs (primary + secondary)
and connection fan-out, then emit WEBHOOK_REQUEST_SIZE_IN_BYTES and
WEBHOOK_RESPONSE_SIZE_IN_BYTES metrics from the server.

@ErickRDev ErickRDev self-assigned this May 25, 2026
@linear

linear Bot commented May 25, 2026

Copy link
Copy Markdown

NAN-5426

@cubic-dev-ai cubic-dev-ai 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.

3 issues found across 10 files

Confidence score: 3/5

  • There is concrete regression risk in packages/webhooks/lib/utils.ts: unhandled onBytes errors can convert an otherwise successful webhook delivery into a retry/failure path, which may resend the same event.
  • packages/webhooks/lib/utils.unit.test.ts introduces a real flake risk because fixed port 4103 conflicts with sync.unit.test.ts when Vitest runs in parallel.
  • packages/webhooks/lib/forward.ts appears to drop accumulated bytes on the result.isErr() path, so failed single-hop forwards miss the new size metrics; this is moderate observability impact rather than a hard blocker.
  • Pay close attention to packages/webhooks/lib/utils.ts, packages/webhooks/lib/utils.unit.test.ts, and packages/webhooks/lib/forward.ts - delivery retry behavior, parallel test port contention, and error-path metric emission need validation.

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread packages/webhooks/lib/utils.unit.test.ts Outdated
Comment thread packages/webhooks/lib/utils.ts Outdated
Comment thread packages/webhooks/lib/forward.ts Outdated
@ErickRDev ErickRDev marked this pull request as ready for review May 26, 2026 00:25
@superagent-security superagent-security Bot added contributor:verified Contributor passed trust analysis. pr:verified PR passed security analysis. labels May 26, 2026
@ErickRDev ErickRDev force-pushed the erickr/NAN-5426/meter-webhook-forward branch from f5d1b5d to c2bbc0c Compare May 26, 2026 00:43
@ErickRDev ErickRDev requested review from a team, TBonnin and agusayerza May 26, 2026 01:18
Comment thread packages/webhooks/lib/forward.ts Outdated
logContextGetter,
onBytes: (bytes) => {
metrics.increment(metrics.Types.WEBHOOK_REQUEST_SIZE_IN_BYTES, bytes.sent, { callsite: 'forward' });
metrics.increment(metrics.Types.WEBHOOK_RESPONSE_SIZE_IN_BYTES, bytes.received, { callsite: 'forward' });

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.

Why does bytes.sent = request size and bytes.received = response size?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For context: we're only metering data transfer from within our subnets to the internet (as those are charged as DTO and NAT). So with that in mind, bytes.sent is the request size because it captures the payload size forwarded to the webhook server (as a request originating from us) and bytes.received is the response size because it captures the response we got back from the webhook server.

return Ok({ forwarded });
} finally {
try {
onBytes?.(totalBytes);

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.

We already increase metrics from within functions here. forwardWebhook is only called from 1 place. What's the value of adding a callback function to it instead of just increasing the metrics inline in the finally block?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For context: sending metrics to DD is phase 1; phase 2 is to send it over pubsub and from there fork to DD (observability) and ClickHouse (billing).

I exposed a callback in order to contain the dependency only in the caller packages. It also comes with the minor perk of making it a bit simpler to test, as I don't have to monkeypatch the metrics module to verify it aggregates bytes correctly.

But, to be frank, I don't see a problem in bringing pubsub as a dependency on webhooks - both it's callers, jobs and server, already depend on it - and ditching away the callback approach, if you feel strongly about this.

@TBonnin TBonnin May 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

jobs and server are app packages. They are therefore not imported. On the other end, webhooks is an internal package. Adding pubsub as a dependency means it becomes a transient dependency of everything that import webhooks itself. For now it happens that pubsub is also a dep of all the parents of webhooks but if webhooks is ever needed somewhere else, the new parent would have to bring pubsub even if it doesn't need the functionalities that depend on it.
I think we should be careful when adding dependencies between packages, especially when they are not core capabilities of the package itself

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.

Ok it makes sense to keep it as is to avoid dependency issues.

@ErickRDev ErickRDev force-pushed the erickr/NAN-5426/meter-webhook-forward branch from f4379a4 to e3b6948 Compare May 28, 2026 15:29
@superagent-security superagent-security Bot removed contributor:verified Contributor passed trust analysis. pr:verified PR passed security analysis. labels May 28, 2026
@ErickRDev ErickRDev force-pushed the erickr/NAN-5426/meter-webhook-forward branch from 024ef74 to f5a130e Compare May 28, 2026 16:39
@ErickRDev ErickRDev added this pull request to the merge queue May 28, 2026
Merged via the queue into master with commit a447dd8 May 28, 2026
31 checks passed
@ErickRDev ErickRDev deleted the erickr/NAN-5426/meter-webhook-forward branch May 28, 2026 17:17
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.

3 participants