25
25
logger ,
26
26
get_before_send_log ,
27
27
has_logs_enabled ,
28
+ has_trace_metrics_enabled ,
28
29
)
29
30
from sentry_sdk .serializer import serialize
30
31
from sentry_sdk .tracing import trace
@@ -184,6 +185,7 @@ def __init__(self, options=None):
184
185
self .monitor = None # type: Optional[Monitor]
185
186
self .metrics_aggregator = None # type: Optional[MetricsAggregator]
186
187
self .log_batcher = None # type: Optional[LogBatcher]
188
+ self .trace_metrics_batcher = None # type: Optional[TraceMetricsBatcher]
187
189
188
190
def __getstate__ (self , * args , ** kwargs ):
189
191
# type: (*Any, **Any) -> Any
@@ -219,6 +221,10 @@ def _capture_experimental_log(self, log):
219
221
# type: (Log) -> None
220
222
pass
221
223
224
+ def _capture_trace_metric (self , metric ):
225
+ # type: (TraceMetric) -> None
226
+ pass
227
+
222
228
def capture_session (self , * args , ** kwargs ):
223
229
# type: (*Any, **Any) -> None
224
230
return None
@@ -388,6 +394,13 @@ def _capture_envelope(envelope):
388
394
389
395
self .log_batcher = LogBatcher (capture_func = _capture_envelope )
390
396
397
+ self .trace_metrics_batcher = None
398
+
399
+ if has_trace_metrics_enabled (self .options ):
400
+ from sentry_sdk ._trace_metrics_batcher import TraceMetricsBatcher
401
+
402
+ self .trace_metrics_batcher = TraceMetricsBatcher (capture_func = _capture_envelope )
403
+
391
404
max_request_body_size = ("always" , "never" , "small" , "medium" )
392
405
if self .options ["max_request_body_size" ] not in max_request_body_size :
393
406
raise ValueError (
@@ -967,6 +980,56 @@ def _capture_experimental_log(self, log):
967
980
if self .log_batcher :
968
981
self .log_batcher .add (log )
969
982
983
+ def _capture_trace_metric (self , metric ):
984
+ # type: (Optional[TraceMetric]) -> None
985
+ if not has_trace_metrics_enabled (self .options ) or metric is None :
986
+ return
987
+
988
+ current_scope = sentry_sdk .get_current_scope ()
989
+ isolation_scope = sentry_sdk .get_isolation_scope ()
990
+
991
+ metric ["attributes" ]["sentry.sdk.name" ] = SDK_INFO ["name" ]
992
+ metric ["attributes" ]["sentry.sdk.version" ] = SDK_INFO ["version" ]
993
+
994
+ environment = self .options .get ("environment" )
995
+ if environment is not None and "sentry.environment" not in metric ["attributes" ]:
996
+ metric ["attributes" ]["sentry.environment" ] = environment
997
+
998
+ release = self .options .get ("release" )
999
+ if release is not None and "sentry.release" not in metric ["attributes" ]:
1000
+ metric ["attributes" ]["sentry.release" ] = release
1001
+
1002
+ if isolation_scope ._user is not None :
1003
+ for metric_attribute , user_attribute in (
1004
+ ("user.id" , "id" ),
1005
+ ("user.name" , "username" ),
1006
+ ("user.email" , "email" ),
1007
+ ):
1008
+ if (
1009
+ user_attribute in isolation_scope ._user
1010
+ and metric_attribute not in metric ["attributes" ]
1011
+ ):
1012
+ metric ["attributes" ][metric_attribute ] = isolation_scope ._user [
1013
+ user_attribute
1014
+ ]
1015
+
1016
+ debug = self .options .get ("debug" , False )
1017
+ if debug :
1018
+ logger .debug (
1019
+ f"[Sentry Trace Metrics] [{ metric .get ('type' )} ] { metric .get ('name' )} : { metric .get ('value' )} "
1020
+ )
1021
+
1022
+ from sentry_sdk .utils import get_before_send_trace_metric
1023
+ before_send_trace_metric = get_before_send_trace_metric (self .options )
1024
+ if before_send_trace_metric is not None :
1025
+ metric = before_send_trace_metric (metric , {})
1026
+
1027
+ if metric is None :
1028
+ return
1029
+
1030
+ if self .trace_metrics_batcher :
1031
+ self .trace_metrics_batcher .add (metric )
1032
+
970
1033
def capture_session (
971
1034
self ,
972
1035
session , # type: Session
@@ -1023,6 +1086,8 @@ def close(
1023
1086
self .metrics_aggregator .kill ()
1024
1087
if self .log_batcher is not None :
1025
1088
self .log_batcher .kill ()
1089
+ if self .trace_metrics_batcher is not None :
1090
+ self .trace_metrics_batcher .kill ()
1026
1091
if self .monitor :
1027
1092
self .monitor .kill ()
1028
1093
self .transport .kill ()
@@ -1049,6 +1114,8 @@ def flush(
1049
1114
self .metrics_aggregator .flush ()
1050
1115
if self .log_batcher is not None :
1051
1116
self .log_batcher .flush ()
1117
+ if self .trace_metrics_batcher is not None :
1118
+ self .trace_metrics_batcher .flush ()
1052
1119
self .transport .flush (timeout = timeout , callback = callback )
1053
1120
1054
1121
def __enter__ (self ):
0 commit comments