Skip to content

Commit abf451a

Browse files
adinauergetsentry-botlcian
authored
feat(metrics): Trace Metrics (#5026)
* Metrics Options * MetricsApi stub * Add transport types for metrics * Enable metrics by default * Format code * Add batch processor for Metrics * Wire up Metrics parts * Metrics counter basic API * Metrics Count API * Metrics Distribution API * Metrics Gauge API * Metrics Envelope item deserialization * Record client report for discarded metrics envelope item * Metrics external options * Metrics Manifest options for Android * Android Metrics batch processor and factory * Only send user attributes if sendDefaultPii is true * Remove Experimental Annotation from Metrics Options * Add unit tests for Metrics * Create SentryMetricsParameters for Metrics * Use uv for managing python version * fix * Add device and OS attributes to metrics * Add AI rules files for Metrics (and update feature flags rule) * Close and flush MetricsBatchProcessor from SentryClient * fix * Add E2E tests for Metrics * Final keyword in Metrics methods * Add Hint to Metrics * SentryMetricsParameters create shortcut for attributes map * Automatically use SentryOptions.Metrics.BeforeSendMetricCallback Spring beans * Rename sample API param, remove sleep * Create MetricsUnit constants * Format code * Metrics Options (#4980) * feat(metrics): [Trace Metrics 2] MetricsApi stub (#4981) * Metrics Options * MetricsApi stub * More PR review changes (#5028) * Some more PR review changes * Format code --------- Co-authored-by: Sentry Github Bot <[email protected]> * changelog * non nullable trace id * error log now says metric instead of log --------- Co-authored-by: Sentry Github Bot <[email protected]> Co-authored-by: lcian <[email protected]>
1 parent f064536 commit abf451a

File tree

109 files changed

+5048
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+5048
-44
lines changed

.cursor/rules/feature_flags.mdc

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,35 @@ There is a scope based and a span based API for tracking feature flag evaluation
1010

1111
The `addFeatureFlag` method can be used to track feature flag evaluations. It exists on `Sentry` static API as well as `IScopes` and `IScope`.
1212

13+
When using static API, `IScopes` or COMBINED scope type, Sentry will also invoke `addFeatureFlag` on the current span. This does not happen, when directly invoking `addFeatureFlag` on `IScope` (except for COMBINED scope type).
14+
1315
The `maxFeatureFlags` option controls how many flags are tracked per scope and also how many are sent to Sentry as part of events.
1416
Scope based feature flags can also be disabled by setting the value to 0. Defaults to 100 feature flag evaluations.
1517

1618
Order of feature flag evaluations is important as we only keep track of the last {maxFeatureFlag} items.
1719

18-
When a feature flag evluation with the same name is added, the previous one is removed and the new one is stored so that it'll be dropped last.
20+
When a feature flag evaluation with the same name is added, the previous one is removed and the new one is stored so that it'll be dropped last.
21+
Refer to `FeatureFlagBuffer` fore more details. `FeatureFlagBuffer` has been optimized for storing scope based feature flag evaluations, especially clone performance.
1922

20-
When sending out an error event, feature flag buffers from all three scope types (global, isolation and current scope) are merged, chosing the newest {maxFeatureFlag} entries across all scope types. Feature flags are sent as part of the `flags` context.
23+
When sending out an error event, feature flag buffers from all three scope types (global, isolation and current scope) are merged, choosing the newest {maxFeatureFlag} entries across all scope types. Feature flags are sent as part of the `flags` context.
2124

2225
## Span Based API
2326

24-
tbd
27+
It's also possible to use the `addFeatureFlag` method on `ISpan` (and by extension `ITransaction`). Feature flag evaluations tracked this way
28+
will not be added to the scope and thus won't be added to error events.
29+
30+
Each span has its own `SpanFeatureFlagBuffer`. When starting a child span, feature flag evaluations are NOT copied from the parent. Each span starts out with an empty buffer and has its own limit.
31+
`SpanFeatureFlagBuffer` has been optimized for storing feature flag evaluations on spans.
32+
33+
Spans have a hard coded limit of 10 feature flag evaluations. When full, new entries are rejected. Updates to existing entries are still allowed even if full.
34+
35+
## Integrations
36+
37+
We offer integrations that automatically track feature flag evaluations.
38+
39+
Android:
40+
- LaunchDarkly (`SentryLaunchDarklyAndroidHook`)
41+
42+
JVM (non Android):
43+
- LaunchDarkly (`SentryLaunchDarklyServerHook`)
44+
- OpenFeature (`SentryOpenFeatureHook`)

.cursor/rules/metrics.mdc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
alwaysApply: false
3+
description: Metrics API
4+
---
5+
# Java SDK Metrics API
6+
7+
Metrics are enabled by default.
8+
9+
API has been namespaced under `Sentry.metrics()` and `IScopes.metrics()` using the `IMetricsApi` interface and `MetricsApi` implementation.
10+
11+
Options are namespaced under `SentryOptions.getMetrics()`.
12+
13+
Three different APIs exist:
14+
- `count`: Counters are one of the more basic types of metrics and can be used to count certain event occurrences.
15+
- `distribution`: Distributions help you get the most insights from your data by allowing you to obtain aggregations such as p90, min, max, and avg.
16+
- `gauge`: Gauges let you obtain aggregates like min, max, avg, sum, and count. They can be represented in a more space-efficient way than distributions, but they can't be used to get percentiles. If percentiles aren't important to you, we recommend using gauges.
17+
18+
Refer to `SentryMetricsEvent` for details about available fields.
19+
20+
`MetricsBatchProcessor` handles batching (`MAX_BATCH_SIZE`), automatic sending of metrics after a timeout (`FLUSH_AFTER_MS`) and rejecting if `MAX_QUEUE_SIZE` has been hit.
21+
22+
The flow is `IMetricsApi` -> `IMetricsBatchProcessor` -> `SentryClient.captureBatchedMetricsEvents` -> `ITransport`.
23+
24+
Each `SentryMetricsEvent` goes through `SentryOptions.metrics.beforeSend` (if configured) and can be modified or dropped.
25+
26+
For sending, a batch of `SentryMetricsEvent` objects is sent inside a `SentryMetricsEvents` object.

.cursor/rules/overview_dev.mdc

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,21 @@ Use the `fetch_rules` tool to include these rules when working on specific areas
3737
- **`feature_flags`**: Use when working with:
3838
- Feature flag tracking and evaluation
3939
- `addFeatureFlag()`, `getFeatureFlags()` methods
40-
- `FeatureFlagBuffer`, `FeatureFlag` protocol
40+
- `FeatureFlagBuffer`, `SpanFeatureFlagBuffer`, `FeatureFlag` protocol
4141
- `maxFeatureFlags` option and buffer management
4242
- Feature flag merging across scope types
4343
- Scope-based vs span-based feature flag APIs
44+
- Scope-based API: `Sentry`, `IScopes`, `IScope` APIs
45+
- Span-based API: `ISpan`, `ITransaction` APIs
46+
- Integrations: LaunchDarkly (Android/JVM), OpenFeature (JVM)
47+
48+
- **`metrics`**: Use when working with:
49+
- Metrics API (`Sentry.metrics()`, `IScopes.metrics()`)
50+
- `IMetricsApi`, `MetricsApi` implementation
51+
- Metrics types: `count`, `distribution`, `gauge`
52+
- `MetricsBatchProcessor`, batching and queue management
53+
- `SentryMetricsEvent`, `SentryMetricsEvents`
54+
- `SentryOptions.getMetrics()`, `beforeSend` callback
4455

4556
### Integration & Infrastructure
4657
- **`opentelemetry`**: Use when working with:
@@ -72,3 +83,4 @@ Use the `fetch_rules` tool to include these rules when working on specific areas
7283
- Cache/offline/network → `offline`
7384
- System test/e2e/sample → `e2e_tests`
7485
- Feature flag/addFeatureFlag/flag evaluation → `feature_flags`
86+
- Metrics/count/distribution/gauge → `metrics`

.cursor/rules/scopes.mdc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ Data is also passed on to newly forked child scopes but not to parents.
4949

5050
Current scope can be retrieved from `Scopes` via `getScope`.
5151

52+
### Combined Scope
53+
54+
This is a special scope type that combines global, isolation and current scope.
55+
56+
Refer to `CombinedScopeView` for each field of interest to see whether values from the three individual scopes are merged,
57+
whether a specific one is used or whether we're simply using the first one that has a value.
58+
59+
Also see the section about `defaultScopeType` further down.
60+
5261
## Storage of `Scopes`
5362

5463
`Scopes` are stored in a `ThreadLocal` by default (NOTE: this is different for OpenTelemetry, see opentelemetry.mdc).

.envrc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
export VIRTUAL_ENV=".venv"
2-
layout python3
1+
export VIRTUAL_ENV="${PWD}/.venv"
2+
devenv sync
3+
PATH_add "${PWD}/.venv/bin"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ spring-server.txt
2727
spy.log
2828
.kotlin
2929
**/tomcat.8080/webapps/
30+
**/__pycache__

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13.3

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
- Add a Tombstone integration that detects native crashes without relying on the NDK integration, but instead using `ApplicationExitInfo.REASON_CRASH_NATIVE` on Android 12+. ([#4933](https://github.com/getsentry/sentry-java/pull/4933))
2121
- Currently exposed via options as an _internal_ API only.
2222
- If enabled alongside the NDK integration, crashes will be reported as two separate events. Users should enable only one; deduplication between both integrations will be added in a future release.
23+
- Add Sentry Metrics to Java SDK ([#5026](https://github.com/getsentry/sentry-java/pull/5026))
24+
- Metrics are enabled by default
25+
- APIs are namespaced under `Sentry.metrics()`
26+
- We offer the following APIs:
27+
- `count`: A metric that increments counts
28+
- `gauge`: A metric that tracks a value that can go up or down
29+
- `distribution`: A metric that tracks the statistical distribution of values
2330

2431
## 8.29.0
2532

devenv/config.ini

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[devenv]
2+
minimum_version = 1.22.1
3+
4+
[uv]
5+
darwin_arm64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-aarch64-apple-darwin.tar.gz
6+
darwin_arm64_sha256 = 954d24634d5f37fa26c7af75eb79893d11623fc81b4de4b82d60d1ade4bfca22
7+
darwin_x86_64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-x86_64-apple-darwin.tar.gz
8+
darwin_x86_64_sha256 = ae755df53c8c2c1f3dfbee6e3d2e00be0dfbc9c9b4bdffdb040b96f43678b7ce
9+
linux_arm64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-aarch64-unknown-linux-gnu.tar.gz
10+
linux_arm64_sha256 = 27da35ef54e9131c2e305de67dd59a07c19257882c6b1f3cf4d8d5fbb8eaf4ca
11+
linux_x86_64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-x86_64-unknown-linux-gnu.tar.gz
12+
linux_x86_64_sha256 = 6dcb28a541868a455aefb2e8d4a1283dd6bf888605a2db710f0530cec888b0ad
13+
# used for autoupdate
14+
# NOTE: if using uv-build as a build backend, you'll have to make sure the versions match
15+
version = 0.8.2
16+

devenv/sync.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from devenv import constants
2+
from devenv.lib import config, proc, uv
3+
import os
4+
5+
def main(context: dict[str, str]) -> int:
6+
reporoot = context["reporoot"]
7+
cfg = config.get_repo(reporoot)
8+
9+
uv.install(
10+
cfg["uv"]["version"],
11+
cfg["uv"][constants.SYSTEM_MACHINE],
12+
cfg["uv"][f"{constants.SYSTEM_MACHINE}_sha256"],
13+
reporoot,
14+
)
15+
16+
# reporoot/.venv is the default venv location
17+
print(f"syncing .venv ...")
18+
if not os.path.exists(".venv"):
19+
proc.run(("uv", "venv", "--seed"))
20+
proc.run(("uv", "sync", "--frozen", "--quiet"))
21+
22+
return 0
23+

0 commit comments

Comments
 (0)