71
71
def get_code_location (stacklevel ):
72
72
# type: (int) -> Optional[Dict[str, Any]]
73
73
try :
74
- frm = sys ._getframe (stacklevel + 4 )
74
+ frm = sys ._getframe (stacklevel )
75
75
except Exception :
76
76
return None
77
77
@@ -508,7 +508,7 @@ def add(
508
508
tags , # type: Optional[MetricTags]
509
509
timestamp = None , # type: Optional[Union[float, datetime]]
510
510
local_aggregator = None , # type: Optional[LocalAggregator]
511
- stacklevel = 0 , # type: int
511
+ stacklevel = 0 , # type: Optional[ int]
512
512
):
513
513
# type: (...) -> None
514
514
if not self ._ensure_thread () or self ._flusher is None :
@@ -541,25 +541,9 @@ def add(
541
541
previous_weight = 0
542
542
543
543
added = metric .weight - previous_weight
544
- self ._buckets_total_weight += added
545
544
546
- # Store code location once per metric and per day (of bucket timestamp)
547
- if self ._enable_code_locations :
548
- meta_key = (ty , key , unit )
549
- start_of_day = utc_from_timestamp (timestamp ).replace (
550
- hour = 0 , minute = 0 , second = 0 , microsecond = 0 , tzinfo = None
551
- )
552
- start_of_day = int (to_timestamp (start_of_day ))
553
-
554
- if (start_of_day , meta_key ) not in self ._seen_locations :
555
- self ._seen_locations .add ((start_of_day , meta_key ))
556
- loc = get_code_location (stacklevel )
557
- if loc is not None :
558
- # Group metadata by day to make flushing more efficient.
559
- # There needs to be one envelope item per timestamp.
560
- self ._pending_locations .setdefault (start_of_day , []).append (
561
- (meta_key , loc )
562
- )
545
+ if stacklevel is not None :
546
+ self .record_code_location (ty , key , unit , stacklevel + 2 , timestamp )
563
547
564
548
# Given the new weight we consider whether we want to force flush.
565
549
self ._consider_force_flush ()
@@ -568,6 +552,53 @@ def add(
568
552
local_value = float (added if ty == "s" else value )
569
553
local_aggregator .add (ty , key , local_value , unit , serialized_tags )
570
554
555
+ def record_code_location (
556
+ self ,
557
+ ty , # type: MetricType
558
+ key , # type: str
559
+ unit , # type: MeasurementUnit
560
+ stacklevel , # type: int
561
+ timestamp = None , # type: Optional[float]
562
+ ):
563
+ # type: (...) -> None
564
+ if not self ._enable_code_locations :
565
+ return
566
+ if timestamp is None :
567
+ timestamp = time .time ()
568
+ meta_key = (ty , key , unit )
569
+ start_of_day = utc_from_timestamp (timestamp ).replace (
570
+ hour = 0 , minute = 0 , second = 0 , microsecond = 0 , tzinfo = None
571
+ )
572
+ start_of_day = int (to_timestamp (start_of_day ))
573
+
574
+ if (start_of_day , meta_key ) not in self ._seen_locations :
575
+ self ._seen_locations .add ((start_of_day , meta_key ))
576
+ loc = get_code_location (stacklevel + 3 )
577
+ if loc is not None :
578
+ # Group metadata by day to make flushing more efficient.
579
+ # There needs to be one envelope item per timestamp.
580
+ self ._pending_locations .setdefault (start_of_day , []).append (
581
+ (meta_key , loc )
582
+ )
583
+
584
+ @metrics_noop
585
+ def need_code_loation (
586
+ self ,
587
+ ty , # type: MetricType
588
+ key , # type: str
589
+ unit , # type: MeasurementUnit
590
+ timestamp , # type: float
591
+ ):
592
+ # type: (...) -> bool
593
+ if self ._enable_code_locations :
594
+ return False
595
+ meta_key = (ty , key , unit )
596
+ start_of_day = utc_from_timestamp (timestamp ).replace (
597
+ hour = 0 , minute = 0 , second = 0 , microsecond = 0 , tzinfo = None
598
+ )
599
+ start_of_day = int (to_timestamp (start_of_day ))
600
+ return (start_of_day , meta_key ) not in self ._seen_locations
601
+
571
602
def kill (self ):
572
603
# type: (...) -> None
573
604
if self ._flusher is None :
@@ -651,9 +682,19 @@ def _tags_to_dict(tags):
651
682
return rv
652
683
653
684
685
+ def _get_aggregator ():
686
+ # type: () -> Optional[MetricsAggregator]
687
+ hub = sentry_sdk .Hub .current
688
+ client = hub .client
689
+ return (
690
+ client .metrics_aggregator
691
+ if client is not None and client .metrics_aggregator is not None
692
+ else None
693
+ )
694
+
695
+
654
696
def _get_aggregator_and_update_tags (key , tags ):
655
697
# type: (str, Optional[MetricTags]) -> Tuple[Optional[MetricsAggregator], Optional[LocalAggregator], Optional[MetricTags]]
656
- """Returns the current metrics aggregator if there is one."""
657
698
hub = sentry_sdk .Hub .current
658
699
client = hub .client
659
700
if client is None or client .metrics_aggregator is None :
@@ -751,6 +792,12 @@ def __enter__(self):
751
792
value = "," .join (sorted (map (str , value )))
752
793
self ._span .set_tag (key , value )
753
794
self ._span .__enter__ ()
795
+
796
+ # report code locations here for better accuracy
797
+ aggregator = _get_aggregator ()
798
+ if aggregator is not None :
799
+ aggregator .record_code_location ("d" , self .key , self .unit , self .stacklevel )
800
+
754
801
return self
755
802
756
803
def __exit__ (self , exc_type , exc_value , tb ):
@@ -769,7 +816,7 @@ def __exit__(self, exc_type, exc_value, tb):
769
816
tags ,
770
817
self .timestamp ,
771
818
local_aggregator ,
772
- self . stacklevel ,
819
+ None , # code locations are reported in __enter__
773
820
)
774
821
775
822
self ._span .__exit__ (exc_type , exc_value , tb )
0 commit comments