Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
e156d3c
Metrics Options
adinauer Dec 17, 2025
b0ec8eb
MetricsApi stub
adinauer Dec 17, 2025
a4b97cc
Add transport types for metrics
adinauer Dec 17, 2025
d3c7452
Enable metrics by default
adinauer Dec 17, 2025
14ea96a
Format code
getsentry-bot Dec 22, 2025
ff0fe29
Add batch processor for Metrics
adinauer Dec 18, 2025
4605172
Wire up Metrics parts
adinauer Dec 18, 2025
38a5226
Metrics counter basic API
adinauer Dec 18, 2025
557f6dd
Metrics Count API
adinauer Dec 18, 2025
661415a
Metrics Distribution API
adinauer Dec 18, 2025
ece88f1
Metrics Gauge API
adinauer Dec 19, 2025
5aed561
Metrics Envelope item deserialization
adinauer Dec 19, 2025
0107c8e
Record client report for discarded metrics envelope item
adinauer Dec 19, 2025
cceb10f
Metrics external options
adinauer Dec 19, 2025
870ba66
Metrics Manifest options for Android
adinauer Dec 19, 2025
56879b3
Android Metrics batch processor and factory
adinauer Dec 19, 2025
15ec6da
Only send user attributes if sendDefaultPii is true
adinauer Dec 22, 2025
52863e3
Remove Experimental Annotation from Metrics Options
adinauer Dec 22, 2025
a79f91b
Add unit tests for Metrics
adinauer Jan 5, 2026
d3cadef
Create SentryMetricsParameters for Metrics
adinauer Jan 5, 2026
75beb08
Use uv for managing python version
adinauer Jan 8, 2026
924a40c
fix
lcian Jan 8, 2026
301f9a2
Add device and OS attributes to metrics
adinauer Jan 7, 2026
af4f8c4
Add AI rules files for Metrics (and update feature flags rule)
adinauer Jan 7, 2026
8330a3e
Close and flush MetricsBatchProcessor from SentryClient
adinauer Jan 8, 2026
53ea75b
fix
lcian Jan 8, 2026
9988b7e
Add E2E tests for Metrics
adinauer Jan 8, 2026
f502ffe
Final keyword in Metrics methods
adinauer Jan 8, 2026
76e7b2c
Add Hint to Metrics
adinauer Jan 12, 2026
5bfb646
SentryMetricsParameters create shortcut for attributes map
adinauer Jan 12, 2026
4d16452
Automatically use SentryOptions.Metrics.BeforeSendMetricCallback Spri…
adinauer Jan 12, 2026
6913b95
Rename sample API param, remove sleep
adinauer Jan 13, 2026
81e4b6a
Create MetricsUnit constants
adinauer Jan 13, 2026
735f8f1
Format code
getsentry-bot Jan 13, 2026
e7b20a0
Metrics Options (#4980)
adinauer Jan 14, 2026
1c96999
feat(metrics): [Trace Metrics 2] MetricsApi stub (#4981)
adinauer Jan 14, 2026
29af336
Merge branch 'feat/trace-metrics' into 12-17-enable_metrics_by_default
adinauer Jan 14, 2026
20376f7
Merge pull request #4982 from getsentry/12-17-enable_metrics_by_default
adinauer Jan 14, 2026
b8f9218
Merge pull request #4983 from getsentry/12-17-add_transport_types_for…
adinauer Jan 14, 2026
b3e9f9d
Merge pull request #4984 from getsentry/12-18-add_batch_processor_for…
adinauer Jan 14, 2026
21e0687
Merge pull request #4985 from getsentry/12-18-wire_up_metrics_parts
adinauer Jan 14, 2026
d4f469f
Merge pull request #4986 from getsentry/12-18-metrics_counter_basic_api
adinauer Jan 14, 2026
2d8889f
Merge pull request #4987 from getsentry/12-18-metrics_count_api
adinauer Jan 14, 2026
236a3a8
Merge pull request #4988 from getsentry/12-18-metrics_distribution_api
adinauer Jan 14, 2026
9443344
Merge pull request #4989 from getsentry/12-19-metrics_gauge_api
adinauer Jan 14, 2026
78bfea0
Merge pull request #4990 from getsentry/12-19-metrics_envelope_item_d…
adinauer Jan 14, 2026
7a122ec
Merge pull request #4991 from getsentry/12-19-record_client_report_fo…
adinauer Jan 14, 2026
c02f059
Merge pull request #4992 from getsentry/12-19-metrics_external_options
adinauer Jan 14, 2026
5cd1a70
Merge pull request #4993 from getsentry/12-19-metrics_manifest_option…
adinauer Jan 14, 2026
dc0107f
Merge pull request #4994 from getsentry/12-19-android_metrics_batch_p…
adinauer Jan 14, 2026
e396044
Merge pull request #4995 from getsentry/12-22-only_send_user_attribut…
adinauer Jan 14, 2026
9e12f62
Merge pull request #4996 from getsentry/12-22-remove_experimental_ann…
adinauer Jan 14, 2026
6511ed5
Merge pull request #5005 from getsentry/01-05-add_unit_tests_for_metrics
adinauer Jan 14, 2026
a9786bd
Merge pull request #5006 from getsentry/01-05-create_sentrymetricspar…
adinauer Jan 14, 2026
d265938
Merge pull request #5007 from getsentry/01-07-add_device_and_os_attri…
adinauer Jan 14, 2026
82249fc
Merge pull request #5008 from getsentry/01-07-add_ai_rules_files_for_…
adinauer Jan 14, 2026
7f42e1f
Merge pull request #5010 from getsentry/01-08-close_and_flush_metrics…
adinauer Jan 14, 2026
bea07c7
Merge pull request #5009 from getsentry/01-08-use_uv_for_managing_pyt…
adinauer Jan 14, 2026
386b53d
Merge pull request #5011 from getsentry/01-08-add_e2e_tests_for_metrics
adinauer Jan 14, 2026
552940b
Final keyword in Metrics methods (#5013)
adinauer Jan 14, 2026
6f439ac
Merge pull request #5019 from getsentry/01-12-add_hint_to_metrics
adinauer Jan 14, 2026
9fddc10
Merge pull request #5020 from getsentry/01-12-sentrymetricsparameters…
adinauer Jan 14, 2026
a930276
Merge pull request #5021 from getsentry/01-12-automatically_use_sentr…
adinauer Jan 14, 2026
f2dca3b
Merge pull request #5024 from getsentry/01-13-rename_sample_api_param…
adinauer Jan 14, 2026
1737697
Merge pull request #5025 from getsentry/01-13-create_metricsunit_cons…
adinauer Jan 14, 2026
c791f64
Merge branch 'main' into feat/trace-metrics
adinauer Jan 14, 2026
0d16364
More PR review changes (#5028)
adinauer Jan 14, 2026
de58ea0
changelog
adinauer Jan 14, 2026
e8963d8
non nullable trace id
adinauer Jan 14, 2026
11a2ea8
error log now says metric instead of log
adinauer Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions .cursor/rules/feature_flags.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,35 @@ There is a scope based and a span based API for tracking feature flag evaluation

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

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).

The `maxFeatureFlags` option controls how many flags are tracked per scope and also how many are sent to Sentry as part of events.
Scope based feature flags can also be disabled by setting the value to 0. Defaults to 100 feature flag evaluations.

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

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.
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.
Refer to `FeatureFlagBuffer` fore more details. `FeatureFlagBuffer` has been optimized for storing scope based feature flag evaluations, especially clone performance.

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

## Span Based API

tbd
It's also possible to use the `addFeatureFlag` method on `ISpan` (and by extension `ITransaction`). Feature flag evaluations tracked this way
will not be added to the scope and thus won't be added to error events.

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.
`SpanFeatureFlagBuffer` has been optimized for storing feature flag evaluations on spans.

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.

## Integrations

We offer integrations that automatically track feature flag evaluations.

Android:
- LaunchDarkly (`SentryLaunchDarklyAndroidHook`)

JVM (non Android):
- LaunchDarkly (`SentryLaunchDarklyServerHook`)
- OpenFeature (`SentryOpenFeatureHook`)
26 changes: 26 additions & 0 deletions .cursor/rules/metrics.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
alwaysApply: false
description: Metrics API
---
# Java SDK Metrics API

Metrics are enabled by default.

API has been namespaced under `Sentry.metrics()` and `IScopes.metrics()` using the `IMetricsApi` interface and `MetricsApi` implementation.

Options are namespaced under `SentryOptions.getMetrics()`.

Three different APIs exist:
- `count`: Counters are one of the more basic types of metrics and can be used to count certain event occurrences.
- `distribution`: Distributions help you get the most insights from your data by allowing you to obtain aggregations such as p90, min, max, and avg.
- `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.

Refer to `SentryMetricsEvent` for details about available fields.

`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.

The flow is `IMetricsApi` -> `IMetricsBatchProcessor` -> `SentryClient.captureBatchedMetricsEvents` -> `ITransport`.

Each `SentryMetricsEvent` goes through `SentryOptions.metrics.beforeSend` (if configured) and can be modified or dropped.

For sending, a batch of `SentryMetricsEvent` objects is sent inside a `SentryMetricsEvents` object.
14 changes: 13 additions & 1 deletion .cursor/rules/overview_dev.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,21 @@ Use the `fetch_rules` tool to include these rules when working on specific areas
- **`feature_flags`**: Use when working with:
- Feature flag tracking and evaluation
- `addFeatureFlag()`, `getFeatureFlags()` methods
- `FeatureFlagBuffer`, `FeatureFlag` protocol
- `FeatureFlagBuffer`, `SpanFeatureFlagBuffer`, `FeatureFlag` protocol
- `maxFeatureFlags` option and buffer management
- Feature flag merging across scope types
- Scope-based vs span-based feature flag APIs
- Scope-based API: `Sentry`, `IScopes`, `IScope` APIs
- Span-based API: `ISpan`, `ITransaction` APIs
- Integrations: LaunchDarkly (Android/JVM), OpenFeature (JVM)

- **`metrics`**: Use when working with:
- Metrics API (`Sentry.metrics()`, `IScopes.metrics()`)
- `IMetricsApi`, `MetricsApi` implementation
- Metrics types: `count`, `distribution`, `gauge`
- `MetricsBatchProcessor`, batching and queue management
- `SentryMetricsEvent`, `SentryMetricsEvents`
- `SentryOptions.getMetrics()`, `beforeSend` callback

### Integration & Infrastructure
- **`opentelemetry`**: Use when working with:
Expand Down Expand Up @@ -72,3 +83,4 @@ Use the `fetch_rules` tool to include these rules when working on specific areas
- Cache/offline/network → `offline`
- System test/e2e/sample → `e2e_tests`
- Feature flag/addFeatureFlag/flag evaluation → `feature_flags`
- Metrics/count/distribution/gauge → `metrics`
9 changes: 9 additions & 0 deletions .cursor/rules/scopes.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ Data is also passed on to newly forked child scopes but not to parents.

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

### Combined Scope

This is a special scope type that combines global, isolation and current scope.

Refer to `CombinedScopeView` for each field of interest to see whether values from the three individual scopes are merged,
whether a specific one is used or whether we're simply using the first one that has a value.

Also see the section about `defaultScopeType` further down.

## Storage of `Scopes`

`Scopes` are stored in a `ThreadLocal` by default (NOTE: this is different for OpenTelemetry, see opentelemetry.mdc).
Expand Down
5 changes: 3 additions & 2 deletions .envrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export VIRTUAL_ENV=".venv"
layout python3
export VIRTUAL_ENV="${PWD}/.venv"
devenv sync
PATH_add "${PWD}/.venv/bin"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ spring-server.txt
spy.log
.kotlin
**/tomcat.8080/webapps/
**/__pycache__
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13.3
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
- 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))
- Currently exposed via options as an _internal_ API only.
- 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.
- Add Sentry Metrics to Java SDK ([#5026](https://github.com/getsentry/sentry-java/pull/5026))
- Metrics are enabled by default
- APIs are namespaced under `Sentry.metrics()`
- We offer the following APIs:
- `count`: A metric that increments counts
- `gauge`: A metric that tracks a value that can go up or down
- `distribution`: A metric that tracks the statistical distribution of values

## 8.29.0

Expand Down
16 changes: 16 additions & 0 deletions devenv/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[devenv]
minimum_version = 1.22.1

[uv]
darwin_arm64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-aarch64-apple-darwin.tar.gz
darwin_arm64_sha256 = 954d24634d5f37fa26c7af75eb79893d11623fc81b4de4b82d60d1ade4bfca22
darwin_x86_64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-x86_64-apple-darwin.tar.gz
darwin_x86_64_sha256 = ae755df53c8c2c1f3dfbee6e3d2e00be0dfbc9c9b4bdffdb040b96f43678b7ce
linux_arm64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-aarch64-unknown-linux-gnu.tar.gz
linux_arm64_sha256 = 27da35ef54e9131c2e305de67dd59a07c19257882c6b1f3cf4d8d5fbb8eaf4ca
linux_x86_64 = https://github.com/astral-sh/uv/releases/download/0.8.2/uv-x86_64-unknown-linux-gnu.tar.gz
linux_x86_64_sha256 = 6dcb28a541868a455aefb2e8d4a1283dd6bf888605a2db710f0530cec888b0ad
# used for autoupdate
# NOTE: if using uv-build as a build backend, you'll have to make sure the versions match
version = 0.8.2

23 changes: 23 additions & 0 deletions devenv/sync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from devenv import constants
from devenv.lib import config, proc, uv
import os

def main(context: dict[str, str]) -> int:
reporoot = context["reporoot"]
cfg = config.get_repo(reporoot)

uv.install(
cfg["uv"]["version"],
cfg["uv"][constants.SYSTEM_MACHINE],
cfg["uv"][f"{constants.SYSTEM_MACHINE}_sha256"],
reporoot,
)

# reporoot/.venv is the default venv location
print(f"syncing .venv ...")
if not os.path.exists(".venv"):
proc.run(("uv", "venv", "--seed"))
proc.run(("uv", "sync", "--frozen", "--quiet"))

return 0

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[project]
name = "javasdk"
version = "0.0.0"
12 changes: 12 additions & 0 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ public class io/sentry/android/core/AndroidMemoryCollector : io/sentry/IPerforma
public fun setup ()V
}

public final class io/sentry/android/core/AndroidMetricsBatchProcessor : io/sentry/metrics/MetricsBatchProcessor, io/sentry/android/core/AppState$AppStateListener {
public fun <init> (Lio/sentry/SentryOptions;Lio/sentry/ISentryClient;)V
public fun close (Z)V
public fun onBackground ()V
public fun onForeground ()V
}

public final class io/sentry/android/core/AndroidMetricsBatchProcessorFactory : io/sentry/metrics/IMetricsBatchProcessorFactory {
public fun <init> ()V
public fun create (Lio/sentry/SentryOptions;Lio/sentry/SentryClient;)Lio/sentry/metrics/IMetricsBatchProcessor;
}

public class io/sentry/android/core/AndroidProfiler {
protected final field lock Lio/sentry/util/AutoClosableReentrantLock;
public fun <init> (Ljava/lang/String;ILio/sentry/android/core/internal/util/SentryFrameMetricsCollector;Lio/sentry/ISentryExecutorService;Lio/sentry/ILogger;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.sentry.android.core;

import io.sentry.ISentryClient;
import io.sentry.SentryLevel;
import io.sentry.SentryOptions;
import io.sentry.metrics.MetricsBatchProcessor;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

@ApiStatus.Internal
public final class AndroidMetricsBatchProcessor extends MetricsBatchProcessor
implements AppState.AppStateListener {

public AndroidMetricsBatchProcessor(
final @NotNull SentryOptions options, final @NotNull ISentryClient client) {
super(options, client);
AppState.getInstance().addAppStateListener(this);
}

@Override
public void onForeground() {
// no-op
}

@Override
public void onBackground() {
try {
options
.getExecutorService()
.submit(
new Runnable() {
@Override
public void run() {
flush(MetricsBatchProcessor.FLUSH_AFTER_MS);
}
});
} catch (Throwable t) {
options
.getLogger()
.log(SentryLevel.ERROR, t, "Failed to submit metrics flush in onBackground()");
}
}

@Override
public void close(boolean isRestarting) {
AppState.getInstance().removeAppStateListener(this);
super.close(isRestarting);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.sentry.android.core;

import io.sentry.SentryClient;
import io.sentry.SentryOptions;
import io.sentry.metrics.IMetricsBatchProcessor;
import io.sentry.metrics.IMetricsBatchProcessorFactory;
import org.jetbrains.annotations.NotNull;

public final class AndroidMetricsBatchProcessorFactory implements IMetricsBatchProcessorFactory {
@Override
public @NotNull IMetricsBatchProcessor create(
final @NotNull SentryOptions options, final @NotNull SentryClient client) {
return new AndroidMetricsBatchProcessor(options, client);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ static void loadDefaultAndMetadataOptions(
options.setDateProvider(new SentryAndroidDateProvider());
options.setRuntimeManager(new AndroidRuntimeManager());
options.getLogs().setLoggerBatchProcessorFactory(new AndroidLoggerBatchProcessorFactory());
options.getMetrics().setMetricsBatchProcessorFactory(new AndroidMetricsBatchProcessorFactory());

// set a lower flush timeout on Android to avoid ANRs
options.setFlushTimeoutMillis(DEFAULT_FLUSH_TIMEOUT_MS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ public DefaultAndroidEventProcessor(
return event;
}

@Override
public @Nullable SentryMetricsEvent process(
final @NotNull SentryMetricsEvent event, final @NotNull Hint hint) {
setDevice(event);
setOs(event);
return event;
}

/**
* The last exception is usually used for picking the issue title, but the convention is to send
* inner exceptions first, e.g. [inner, outer] This doesn't work very well on Android, as some
Expand Down Expand Up @@ -248,6 +256,34 @@ private void setOs(final @NotNull SentryLogEvent event) {
}
}

private void setDevice(final @NotNull SentryMetricsEvent event) {
try {
event.setAttribute(
"device.brand",
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.BRAND));
event.setAttribute(
"device.model",
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.MODEL));
event.setAttribute(
"device.family",
new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily.getValue()));
} catch (Throwable e) {
options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve device info", e);
}
}

private void setOs(final @NotNull SentryMetricsEvent event) {
try {
event.setAttribute(
"os.name", new SentryLogEventAttributeValue(SentryAttributeType.STRING, "Android"));
event.setAttribute(
"os.version",
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.VERSION.RELEASE));
} catch (Throwable e) {
options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve os system", e);
}
}

// Data to be applied to events that was created in the running process
private void processNonCachedEvent(
final @NotNull SentryBaseEvent event, final @NotNull Hint hint) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ final class ManifestMetadataReader {

static final String ENABLE_LOGS = "io.sentry.logs.enabled";

static final String ENABLE_METRICS = "io.sentry.metrics.enabled";

static final String ENABLE_AUTO_TRACE_ID_GENERATION =
"io.sentry.traces.enable-auto-id-generation";

Expand Down Expand Up @@ -614,6 +616,11 @@ static void applyMetadata(
.getLogs()
.setEnabled(readBool(metadata, logger, ENABLE_LOGS, options.getLogs().isEnabled()));

options
.getMetrics()
.setEnabled(
readBool(metadata, logger, ENABLE_METRICS, options.getMetrics().isEnabled()));

final @NotNull SentryFeedbackOptions feedbackOptions = options.getFeedbackOptions();
feedbackOptions.setNameRequired(
readBool(metadata, logger, FEEDBACK_NAME_REQUIRED, feedbackOptions.isNameRequired()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.sentry.android.core

import androidx.test.ext.junit.runners.AndroidJUnit4
import io.sentry.SentryClient
import kotlin.test.Test
import kotlin.test.assertIs
import org.junit.runner.RunWith
import org.mockito.kotlin.mock

@RunWith(AndroidJUnit4::class)
class AndroidMetricsBatchProcessorFactoryTest {

@Test
fun `create returns AndroidMetricsBatchProcessor instance`() {
val factory = AndroidMetricsBatchProcessorFactory()
val options = SentryAndroidOptions()
val client: SentryClient = mock()

val processor = factory.create(options, client)

assertIs<AndroidMetricsBatchProcessor>(processor)
}
}
Loading
Loading