Skip to content

feat(effect): Add metrics to Sentry.effectLayer#19709

Merged
JPeer264 merged 4 commits intojp/add-effect-sdkfrom
jp/add-effect-sdk-stack/5
Mar 11, 2026
Merged

feat(effect): Add metrics to Sentry.effectLayer#19709
JPeer264 merged 4 commits intojp/add-effect-sdkfrom
jp/add-effect-sdk-stack/5

Conversation

@JPeer264
Copy link
Member

@JPeer264 JPeer264 commented Mar 9, 2026

This adds metrics to the Sentry.effectLayer. It is enabled when enableMetrics: true is added as option

@JPeer264 JPeer264 requested review from andreiborza and s1gr1d March 9, 2026 11:36
@JPeer264 JPeer264 marked this pull request as ready for review March 9, 2026 11:36
attributes: { ...attributes, word },
});
}
}
Copy link

Choose a reason for hiding this comment

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

Frequency metrics double-counted on every flush cycle

High Severity

Frequency metrics use sentryMetrics.count() (which is additive) with cumulative occurrence counts from Effect's state, but lack delta tracking. Every 10-second flush re-sends the full cumulative counts, causing Sentry to multiply the actual values by the number of flushes. Counters correctly use sendDeltaMetricToSentry for this, but frequency metrics go through sendMetricToSentry without any delta logic.

Additional Locations (1)

Fix in Cursor Fix in Web

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.63 kB added added
@sentry/browser - with treeshaking flags 24.13 kB added added
@sentry/browser (incl. Tracing) 42.43 kB added added
@sentry/browser (incl. Tracing, Profiling) 47.09 kB added added
@sentry/browser (incl. Tracing, Replay) 81.25 kB added added
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 70.87 kB added added
@sentry/browser (incl. Tracing, Replay with Canvas) 85.95 kB added added
@sentry/browser (incl. Tracing, Replay, Feedback) 98.21 kB added added
@sentry/browser (incl. Feedback) 42.44 kB added added
@sentry/browser (incl. sendFeedback) 30.3 kB added added
@sentry/browser (incl. FeedbackAsync) 35.35 kB added added
@sentry/browser (incl. Metrics) 26.8 kB added added
@sentry/browser (incl. Logs) 26.94 kB added added
@sentry/browser (incl. Metrics & Logs) 27.61 kB added added
@sentry/react 27.38 kB added added
@sentry/react (incl. Tracing) 44.77 kB added added
@sentry/vue 30.08 kB added added
@sentry/vue (incl. Tracing) 44.3 kB added added
@sentry/svelte 25.66 kB added added
CDN Bundle 28.17 kB added added
CDN Bundle (incl. Tracing) 43.26 kB added added
CDN Bundle (incl. Logs, Metrics) 29.01 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) 44.1 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) 68.09 kB added added
CDN Bundle (incl. Tracing, Replay) 80.14 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 81 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) 85.65 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 86.53 kB added added
CDN Bundle - uncompressed 82.35 kB added added
CDN Bundle (incl. Tracing) - uncompressed 128.07 kB added added
CDN Bundle (incl. Logs, Metrics) - uncompressed 85.19 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 130.9 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 208.85 kB added added
CDN Bundle (incl. Tracing, Replay) - uncompressed 244.95 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 247.77 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 257.86 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 260.67 kB added added
@sentry/nextjs (client) 47.18 kB added added
@sentry/sveltekit (client) 42.89 kB added added
@sentry/node-core 52.24 kB added added
@sentry/node 174.69 kB added added
@sentry/node - without tracing 97.39 kB added added
@sentry/aws-serverless 113.19 kB added added

}

const { enableLogs = false } = options;
const { enableLogs = false, enableMetrics = false } = options;
Copy link
Member

Choose a reason for hiding this comment

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

q: Our Metrics need to default to true (https://develop.sentry.dev/sdk/telemetry/metrics/#initialization-options). Why do we override this here?

Copy link
Member Author

Choose a reason for hiding this comment

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

TIL. Thanks for giving the hint here - I assumed it is the same default as enableLogs, I'll tripple check if it would be possible to not even touch that at all and rely on the options entirely.

Copy link
Member Author

Choose a reason for hiding this comment

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

Alright. I'll redo the buildEffectLayer in a follow up PR, so the options are coming from the client directly - so we don't have to think about updating these here once the defaults are changing. For now I switched the default to true to make it correct.

Copy link
Member Author

@JPeer264 JPeer264 Mar 10, 2026

Choose a reason for hiding this comment

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

Alright, we discussed offline that we need a opt-in for metrics and logs in a form of a different naming. I'd like to keep the settings as is in this PR and focus on the metrics implementation itself. On a follow-up PR I'd like to propose the new settings (this PR is anyways onto jp/add-effect-sdk, so there is nothing lost now)

see: #19755

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: No final metrics flush before layer teardown
    • Added a final flush call in the release effect before clearing previousCounterValues to ensure all accumulated metrics are sent to Sentry before the layer is torn down.

Create PR

Or push these changes by commenting:

@cursor push 80a4dab25a
Preview (80a4dab25a)
diff --git a/packages/effect/src/metrics.ts b/packages/effect/src/metrics.ts
--- a/packages/effect/src/metrics.ts
+++ b/packages/effect/src/metrics.ts
@@ -126,6 +126,7 @@
 
     yield* Effect.acquireRelease(Effect.void, () =>
       Effect.sync(() => {
+        flushMetricsToSentry(previousCounterValues);
         previousCounterValues.clear();
       }),
     );
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.


yield* Effect.forkScoped(createMetricsReporterEffect(previousCounterValues));
}),
);
Copy link

Choose a reason for hiding this comment

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

No final metrics flush before layer teardown

Medium Severity

The SentryEffectMetricsLayer release effect clears previousCounterValues but never performs a final flush. When the layer is torn down, the scoped fiber running the periodic reporter is interrupted, and any metrics accumulated since the last 10-second flush are silently lost.

Fix in Cursor Fix in Web

@JPeer264 JPeer264 requested a review from chargome March 11, 2026 09:07
const attributes = labelsToAttributes(metricKey.tags);

if (MetricState.isCounterState(metricState)) {
const value = typeof metricState.count === 'bigint' ? Number(metricState.count) : metricState.count;
Copy link
Member

Choose a reason for hiding this comment

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

ultra-l: I'd just always call Number(metricState.count), no need to do an extra check

const metricId = getMetricId(pair);

if (MetricState.isCounterState(metricState)) {
const currentValue = typeof metricState.count === 'bigint' ? Number(metricState.count) : metricState.count;
Copy link
Member

Choose a reason for hiding this comment

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

ultra-l: same here, just Number(metricState.count)?

@JPeer264 JPeer264 force-pushed the jp/add-effect-sdk-stack/5 branch from 6cc903f to 6fa5fa8 Compare March 11, 2026 10:20
@JPeer264 JPeer264 requested a review from andreiborza March 11, 2026 10:20
Copy link
Member

@andreiborza andreiborza left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

const layerWithoutMetrics = buildEffectLayer({ enableMetrics: false }, mockClient);

expect(layerWithMetrics).not.toBe(layerWithoutMetrics);
});
Copy link

Choose a reason for hiding this comment

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

Removed test for disabled logs, no metrics equivalent

Low Severity

The existing test verifying that disabled logs don't route to the Sentry logger was removed and replaced with a weaker structural comparison test. There's also no integration or E2E test verifying that the metrics layer actually sends metrics to Sentry through the full effectLayer pipeline. For a feat PR, at least one integration or E2E test is recommended per the review guidelines.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

@JPeer264 JPeer264 merged commit ed68b6b into jp/add-effect-sdk Mar 11, 2026
33 checks passed
@JPeer264 JPeer264 deleted the jp/add-effect-sdk-stack/5 branch March 11, 2026 10:47
JPeer264 added a commit that referenced this pull request Mar 11, 2026
This adds metrics to the `Sentry.effectLayer`. It is enabled when
`enableMetrics: true` is added as option
JPeer264 added a commit that referenced this pull request Mar 11, 2026
This adds metrics to the `Sentry.effectLayer`. It is enabled when
`enableMetrics: true` is added as option
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