1010import io .sentry .hints .TransactionEnd ;
1111import io .sentry .logger .ILoggerBatchProcessor ;
1212import io .sentry .logger .NoOpLoggerBatchProcessor ;
13+ import io .sentry .metrics .IMetricsBatchProcessor ;
14+ import io .sentry .metrics .NoOpMetricsBatchProcessor ;
1315import io .sentry .protocol .Contexts ;
1416import io .sentry .protocol .DebugMeta ;
1517import io .sentry .protocol .FeatureFlags ;
@@ -42,6 +44,7 @@ public final class SentryClient implements ISentryClient {
4244 private final @ NotNull ITransport transport ;
4345 private final @ NotNull SortBreadcrumbsByDate sortBreadcrumbsByDate = new SortBreadcrumbsByDate ();
4446 private final @ NotNull ILoggerBatchProcessor loggerBatchProcessor ;
47+ private final @ NotNull IMetricsBatchProcessor metricsBatchProcessor ;
4548
4649 @ Override
4750 public boolean isEnabled () {
@@ -66,6 +69,12 @@ public SentryClient(final @NotNull SentryOptions options) {
6669 } else {
6770 loggerBatchProcessor = NoOpLoggerBatchProcessor .getInstance ();
6871 }
72+ if (options .getMetrics ().isEnabled ()) {
73+ metricsBatchProcessor =
74+ options .getMetrics ().getMetricsBatchProcessorFactory ().create (options , this );
75+ } else {
76+ metricsBatchProcessor = NoOpMetricsBatchProcessor .getInstance ();
77+ }
6978 }
7079
7180 private boolean shouldApplyScopeData (
@@ -506,6 +515,38 @@ private SentryLogEvent processLogEvent(
506515 return event ;
507516 }
508517
518+ @ Nullable
519+ private SentryMetricsEvent processMetricsEvent (
520+ @ NotNull SentryMetricsEvent event , final @ NotNull List <EventProcessor > eventProcessors ) {
521+ for (final EventProcessor processor : eventProcessors ) {
522+ try {
523+ event = processor .process (event );
524+ } catch (Throwable e ) {
525+ options
526+ .getLogger ()
527+ .log (
528+ SentryLevel .ERROR ,
529+ e ,
530+ "An exception occurred while processing metrics event by processor: %s" ,
531+ processor .getClass ().getName ());
532+ }
533+
534+ if (event == null ) {
535+ options
536+ .getLogger ()
537+ .log (
538+ SentryLevel .DEBUG ,
539+ "Metrics event was dropped by a processor: %s" ,
540+ processor .getClass ().getName ());
541+ options
542+ .getClientReportRecorder ()
543+ .recordLostEvent (DiscardReason .EVENT_PROCESSOR , DataCategory .TraceMetric );
544+ break ;
545+ }
546+ }
547+ return event ;
548+ }
549+
509550 private @ Nullable SentryTransaction processTransaction (
510551 @ NotNull SentryTransaction transaction ,
511552 final @ NotNull Hint hint ,
@@ -1235,6 +1276,40 @@ public void captureBatchedLogEvents(final @NotNull SentryLogEvents logEvents) {
12351276 }
12361277 }
12371278
1279+ @ ApiStatus .Experimental
1280+ @ Override
1281+ public void captureMetric (@ Nullable SentryMetricsEvent metricsEvent , @ Nullable IScope scope ) {
1282+ if (metricsEvent != null && scope != null ) {
1283+ metricsEvent = processMetricsEvent (metricsEvent , scope .getEventProcessors ());
1284+ if (metricsEvent == null ) {
1285+ return ;
1286+ }
1287+ }
1288+
1289+ if (metricsEvent != null ) {
1290+ metricsEvent = processMetricsEvent (metricsEvent , options .getEventProcessors ());
1291+ if (metricsEvent == null ) {
1292+ return ;
1293+ }
1294+ }
1295+
1296+ if (metricsEvent != null ) {
1297+ metricsEvent = executeBeforeSendMetric (metricsEvent );
1298+
1299+ if (metricsEvent == null ) {
1300+ options
1301+ .getLogger ()
1302+ .log (SentryLevel .DEBUG , "Metrics Event was dropped by beforeSendMetrics" );
1303+ options
1304+ .getClientReportRecorder ()
1305+ .recordLostEvent (DiscardReason .BEFORE_SEND , DataCategory .TraceMetric );
1306+ return ;
1307+ }
1308+
1309+ metricsBatchProcessor .add (metricsEvent );
1310+ }
1311+ }
1312+
12381313 @ ApiStatus .Internal
12391314 @ Override
12401315 public void captureBatchedMetricsEvents (final @ NotNull SentryMetricsEvents metricsEvents ) {
@@ -1550,6 +1625,27 @@ private void sortBreadcrumbsByDate(
15501625 return event ;
15511626 }
15521627
1628+ private @ Nullable SentryMetricsEvent executeBeforeSendMetric (@ NotNull SentryMetricsEvent event ) {
1629+ final SentryOptions .Metrics .BeforeSendMetricCallback beforeSendMetric =
1630+ options .getMetrics ().getBeforeSend ();
1631+ if (beforeSendMetric != null ) {
1632+ try {
1633+ event = beforeSendMetric .execute (event );
1634+ } catch (Throwable e ) {
1635+ options
1636+ .getLogger ()
1637+ .log (
1638+ SentryLevel .ERROR ,
1639+ "The BeforeSendMetric callback threw an exception. Dropping metrics event." ,
1640+ e );
1641+
1642+ // drop event in case of an error in beforeSendMetric due to PII concerns
1643+ event = null ;
1644+ }
1645+ }
1646+ return event ;
1647+ }
1648+
15531649 @ Override
15541650 public void close () {
15551651 close (false );
0 commit comments