1
1
import type {
2
- ClientOptions ,
2
+ Client ,
3
3
MeasurementUnit ,
4
4
MetricsAggregator as MetricsAggregatorInterface ,
5
5
Primitive ,
6
6
} from '@sentry/types' ;
7
7
import { logger } from '@sentry/utils' ;
8
- import type { BaseClient } from '../baseclient' ;
9
8
import { getCurrentScope } from '../currentScopes' ;
10
9
import { getClient } from '../currentScopes' ;
11
10
import { DEBUG_BUILD } from '../debug-build' ;
@@ -17,18 +16,43 @@ export interface MetricData {
17
16
unit ?: MeasurementUnit ;
18
17
tags ?: Record < string , Primitive > ;
19
18
timestamp ?: number ;
19
+ client ?: Client ;
20
20
}
21
21
22
22
type MetricsAggregatorConstructor = {
23
- new ( client : BaseClient < ClientOptions > ) : MetricsAggregatorInterface ;
23
+ new ( client : Client ) : MetricsAggregatorInterface ;
24
24
} ;
25
25
26
26
/**
27
- * Global metrics aggregator instance.
28
- *
29
- * This is initialized on the first call to any `Sentry.metric.*` method.
27
+ * A metrics aggregator instance per Client.
30
28
*/
31
- let globalMetricsAggregator : MetricsAggregatorInterface | undefined ;
29
+ let globalMetricsAggregators : WeakMap < Client , MetricsAggregatorInterface > | undefined ;
30
+
31
+ /**
32
+ * Gets the metrics aggregator for a given client.
33
+ * @param client The client for which to get the metrics aggregator.
34
+ * @param Aggregator Optional metrics aggregator class to use to create an aggregator if one does not exist.
35
+ */
36
+ function getMetricsAggregatorForClient (
37
+ client : Client ,
38
+ Aggregator : MetricsAggregatorConstructor ,
39
+ ) : MetricsAggregatorInterface {
40
+ if ( ! globalMetricsAggregators ) {
41
+ globalMetricsAggregators = new WeakMap ( ) ;
42
+ }
43
+
44
+ const aggregator = globalMetricsAggregators . get ( client ) ;
45
+ if ( aggregator ) {
46
+ return aggregator ;
47
+ }
48
+
49
+ const newAggregator = new Aggregator ( client ) ;
50
+ client . on ( 'flush' , ( ) => newAggregator . flush ( ) ) ;
51
+ client . on ( 'close' , ( ) => newAggregator . close ( ) ) ;
52
+ globalMetricsAggregators . set ( client , newAggregator ) ;
53
+
54
+ return newAggregator ;
55
+ }
32
56
33
57
function addToMetricsAggregator (
34
58
Aggregator : MetricsAggregatorConstructor ,
@@ -37,38 +61,32 @@ function addToMetricsAggregator(
37
61
value : number | string ,
38
62
data : MetricData | undefined = { } ,
39
63
) : void {
40
- const client = getClient < BaseClient < ClientOptions > > ( ) ;
64
+ const client = data . client || getClient < Client > ( ) ;
65
+
41
66
if ( ! client ) {
42
67
return ;
43
68
}
44
69
45
- if ( ! globalMetricsAggregator ) {
46
- const aggregator = ( globalMetricsAggregator = new Aggregator ( client ) ) ;
47
-
48
- client . on ( 'flush' , ( ) => aggregator . flush ( ) ) ;
49
- client . on ( 'close' , ( ) => aggregator . close ( ) ) ;
70
+ const scope = getCurrentScope ( ) ;
71
+ const { unit, tags, timestamp } = data ;
72
+ const { release, environment } = client . getOptions ( ) ;
73
+ // eslint-disable-next-line deprecation/deprecation
74
+ const transaction = scope . getTransaction ( ) ;
75
+ const metricTags : Record < string , string > = { } ;
76
+ if ( release ) {
77
+ metricTags . release = release ;
50
78
}
51
-
52
- if ( client ) {
53
- const scope = getCurrentScope ( ) ;
54
- const { unit, tags, timestamp } = data ;
55
- const { release, environment } = client . getOptions ( ) ;
56
- // eslint-disable-next-line deprecation/deprecation
57
- const transaction = scope . getTransaction ( ) ;
58
- const metricTags : Record < string , string > = { } ;
59
- if ( release ) {
60
- metricTags . release = release ;
61
- }
62
- if ( environment ) {
63
- metricTags . environment = environment ;
64
- }
65
- if ( transaction ) {
66
- metricTags . transaction = spanToJSON ( transaction ) . description || '' ;
67
- }
68
-
69
- DEBUG_BUILD && logger . log ( `Adding value of ${ value } to ${ metricType } metric ${ name } ` ) ;
70
- globalMetricsAggregator . add ( metricType , name , value , unit , { ...metricTags , ...tags } , timestamp ) ;
79
+ if ( environment ) {
80
+ metricTags . environment = environment ;
81
+ }
82
+ if ( transaction ) {
83
+ metricTags . transaction = spanToJSON ( transaction ) . description || '' ;
71
84
}
85
+
86
+ DEBUG_BUILD && logger . log ( `Adding value of ${ value } to ${ metricType } metric ${ name } ` ) ;
87
+
88
+ const aggregator = getMetricsAggregatorForClient ( client , Aggregator ) ;
89
+ aggregator . add ( metricType , name , value , unit , { ...metricTags , ...tags } , timestamp ) ;
72
90
}
73
91
74
92
/**
@@ -112,4 +130,8 @@ export const metrics = {
112
130
distribution,
113
131
set,
114
132
gauge,
133
+ /**
134
+ * @ignore This is for internal use only.
135
+ */
136
+ getMetricsAggregatorForClient,
115
137
} ;
0 commit comments