11import type {
2- ClientOptions ,
2+ Client ,
33 MeasurementUnit ,
44 MetricsAggregator as MetricsAggregatorInterface ,
55 Primitive ,
66} from '@sentry/types' ;
77import { logger } from '@sentry/utils' ;
8- import type { BaseClient } from '../baseclient' ;
98import { getCurrentScope } from '../currentScopes' ;
109import { getClient } from '../currentScopes' ;
1110import { DEBUG_BUILD } from '../debug-build' ;
@@ -17,18 +16,43 @@ export interface MetricData {
1716 unit ?: MeasurementUnit ;
1817 tags ?: Record < string , Primitive > ;
1918 timestamp ?: number ;
19+ client ?: Client ;
2020}
2121
2222type MetricsAggregatorConstructor = {
23- new ( client : BaseClient < ClientOptions > ) : MetricsAggregatorInterface ;
23+ new ( client : Client ) : MetricsAggregatorInterface ;
2424} ;
2525
2626/**
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.
3028 */
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+ }
3256
3357function addToMetricsAggregator (
3458 Aggregator : MetricsAggregatorConstructor ,
@@ -37,38 +61,32 @@ function addToMetricsAggregator(
3761 value : number | string ,
3862 data : MetricData | undefined = { } ,
3963) : void {
40- const client = getClient < BaseClient < ClientOptions > > ( ) ;
64+ const client = data . client || getClient < Client > ( ) ;
65+
4166 if ( ! client ) {
4267 return ;
4368 }
4469
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 ;
5078 }
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 || '' ;
7184 }
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 ) ;
7290}
7391
7492/**
@@ -112,4 +130,8 @@ export const metrics = {
112130 distribution,
113131 set,
114132 gauge,
133+ /**
134+ * @ignore This is for internal use only.
135+ */
136+ getMetricsAggregatorForClient,
115137} ;
0 commit comments