7
7
using System . Globalization ;
8
8
using System . Runtime . Versioning ;
9
9
using System . Text ;
10
+ using System . Threading ;
10
11
11
12
namespace System . Diagnostics . Metrics
12
13
{
@@ -60,13 +61,22 @@ public static class Keywords
60
61
public const EventKeywords InstrumentPublishing = ( EventKeywords ) 0x4 ;
61
62
}
62
63
63
- private CommandHandler _handler ;
64
+ private CommandHandler ? _handler ;
64
65
65
- private MetricsEventSource ( )
66
+ private CommandHandler Handler
66
67
{
67
- _handler = new CommandHandler ( ) ;
68
+ get
69
+ {
70
+ if ( _handler == null )
71
+ {
72
+ Interlocked . CompareExchange ( ref _handler , new CommandHandler ( this ) , null ) ;
73
+ }
74
+ return _handler ;
75
+ }
68
76
}
69
77
78
+ private MetricsEventSource ( ) { }
79
+
70
80
/// <summary>
71
81
/// Used to send ad-hoc diagnostics to humans.
72
82
/// </summary>
@@ -189,7 +199,7 @@ protected override void OnEventCommand(EventCommandEventArgs command)
189
199
{
190
200
lock ( this )
191
201
{
192
- _handler . OnEventCommand ( command ) ;
202
+ Handler . OnEventCommand ( command ) ;
193
203
}
194
204
}
195
205
@@ -202,6 +212,13 @@ private sealed class CommandHandler
202
212
private AggregationManager ? _aggregationManager ;
203
213
private string _sessionId = "" ;
204
214
215
+ public CommandHandler ( MetricsEventSource parent )
216
+ {
217
+ Parent = parent ;
218
+ }
219
+
220
+ public MetricsEventSource Parent { get ; private set ; }
221
+
205
222
public void OnEventCommand ( EventCommandEventArgs command )
206
223
{
207
224
try
@@ -215,7 +232,7 @@ public void OnEventCommand(EventCommandEventArgs command)
215
232
// This limitation shouldn't really matter because browser also doesn't support out-of-proc EventSource communication
216
233
// which is the intended scenario for this EventSource. If it matters in the future AggregationManager can be
217
234
// modified to have some other fallback path that works for browser.
218
- Log . Error ( "" , "System.Diagnostics.Metrics EventSource not supported on browser" ) ;
235
+ Parent . Error ( "" , "System.Diagnostics.Metrics EventSource not supported on browser" ) ;
219
236
return ;
220
237
}
221
238
#endif
@@ -233,13 +250,13 @@ public void OnEventCommand(EventCommandEventArgs command)
233
250
// one other listener is active. In the future we might be able to figure out how
234
251
// to infer the changes from the info we do have or add a better API but for now
235
252
// I am taking the simple route and not supporting it.
236
- Log . MultipleSessionsNotSupportedError ( _sessionId ) ;
253
+ Parent . MultipleSessionsNotSupportedError ( _sessionId ) ;
237
254
return ;
238
255
}
239
256
240
257
_aggregationManager . Dispose ( ) ;
241
258
_aggregationManager = null ;
242
- Log . Message ( $ "Previous session with id { _sessionId } is stopped") ;
259
+ Parent . Message ( $ "Previous session with id { _sessionId } is stopped") ;
243
260
}
244
261
_sessionId = "" ;
245
262
}
@@ -249,12 +266,12 @@ public void OnEventCommand(EventCommandEventArgs command)
249
266
if ( command . Arguments ! . TryGetValue ( "SessionId" , out string ? id ) )
250
267
{
251
268
_sessionId = id ! ;
252
- Log . Message ( $ "SessionId argument received: { _sessionId } ") ;
269
+ Parent . Message ( $ "SessionId argument received: { _sessionId } ") ;
253
270
}
254
271
else
255
272
{
256
273
_sessionId = System . Guid . NewGuid ( ) . ToString ( ) ;
257
- Log . Message ( $ "New session started. SessionId auto-generated: { _sessionId } ") ;
274
+ Parent . Message ( $ "New session started. SessionId auto-generated: { _sessionId } ") ;
258
275
}
259
276
260
277
@@ -263,55 +280,55 @@ public void OnEventCommand(EventCommandEventArgs command)
263
280
double refreshIntervalSecs ;
264
281
if ( command . Arguments ! . TryGetValue ( "RefreshInterval" , out string ? refreshInterval ) )
265
282
{
266
- Log . Message ( $ "RefreshInterval argument received: { refreshInterval } ") ;
283
+ Parent . Message ( $ "RefreshInterval argument received: { refreshInterval } ") ;
267
284
if ( ! double . TryParse ( refreshInterval , out refreshIntervalSecs ) )
268
285
{
269
- Log . Message ( $ "Failed to parse RefreshInterval. Using default { defaultIntervalSecs } s.") ;
286
+ Parent . Message ( $ "Failed to parse RefreshInterval. Using default { defaultIntervalSecs } s.") ;
270
287
refreshIntervalSecs = defaultIntervalSecs ;
271
288
}
272
289
else if ( refreshIntervalSecs < AggregationManager . MinCollectionTimeSecs )
273
290
{
274
- Log . Message ( $ "RefreshInterval too small. Using minimum interval { AggregationManager . MinCollectionTimeSecs } seconds.") ;
291
+ Parent . Message ( $ "RefreshInterval too small. Using minimum interval { AggregationManager . MinCollectionTimeSecs } seconds.") ;
275
292
refreshIntervalSecs = AggregationManager . MinCollectionTimeSecs ;
276
293
}
277
294
}
278
295
else
279
296
{
280
- Log . Message ( $ "No RefreshInterval argument received. Using default { defaultIntervalSecs } s.") ;
297
+ Parent . Message ( $ "No RefreshInterval argument received. Using default { defaultIntervalSecs } s.") ;
281
298
refreshIntervalSecs = defaultIntervalSecs ;
282
299
}
283
300
284
301
int defaultMaxTimeSeries = 1000 ;
285
302
int maxTimeSeries ;
286
303
if ( command . Arguments ! . TryGetValue ( "MaxTimeSeries" , out string ? maxTimeSeriesString ) )
287
304
{
288
- Log . Message ( $ "MaxTimeSeries argument received: { maxTimeSeriesString } ") ;
305
+ Parent . Message ( $ "MaxTimeSeries argument received: { maxTimeSeriesString } ") ;
289
306
if ( ! int . TryParse ( maxTimeSeriesString , out maxTimeSeries ) )
290
307
{
291
- Log . Message ( $ "Failed to parse MaxTimeSeries. Using default { defaultMaxTimeSeries } ") ;
308
+ Parent . Message ( $ "Failed to parse MaxTimeSeries. Using default { defaultMaxTimeSeries } ") ;
292
309
maxTimeSeries = defaultMaxTimeSeries ;
293
310
}
294
311
}
295
312
else
296
313
{
297
- Log . Message ( $ "No MaxTimeSeries argument received. Using default { defaultMaxTimeSeries } ") ;
314
+ Parent . Message ( $ "No MaxTimeSeries argument received. Using default { defaultMaxTimeSeries } ") ;
298
315
maxTimeSeries = defaultMaxTimeSeries ;
299
316
}
300
317
301
318
int defaultMaxHistograms = 20 ;
302
319
int maxHistograms ;
303
320
if ( command . Arguments ! . TryGetValue ( "MaxHistograms" , out string ? maxHistogramsString ) )
304
321
{
305
- Log . Message ( $ "MaxHistograms argument received: { maxHistogramsString } ") ;
322
+ Parent . Message ( $ "MaxHistograms argument received: { maxHistogramsString } ") ;
306
323
if ( ! int . TryParse ( maxHistogramsString , out maxHistograms ) )
307
324
{
308
- Log . Message ( $ "Failed to parse MaxHistograms. Using default { defaultMaxHistograms } ") ;
325
+ Parent . Message ( $ "Failed to parse MaxHistograms. Using default { defaultMaxHistograms } ") ;
309
326
maxHistograms = defaultMaxHistograms ;
310
327
}
311
328
}
312
329
else
313
330
{
314
- Log . Message ( $ "No MaxHistogram argument received. Using default { defaultMaxHistograms } ") ;
331
+ Parent . Message ( $ "No MaxHistogram argument received. Using default { defaultMaxHistograms } ") ;
315
332
maxHistograms = defaultMaxHistograms ;
316
333
}
317
334
@@ -320,27 +337,27 @@ public void OnEventCommand(EventCommandEventArgs command)
320
337
maxTimeSeries ,
321
338
maxHistograms ,
322
339
( i , s ) => TransmitMetricValue ( i , s , sessionId ) ,
323
- ( startIntervalTime , endIntervalTime ) => Log . CollectionStart ( sessionId , startIntervalTime , endIntervalTime ) ,
324
- ( startIntervalTime , endIntervalTime ) => Log . CollectionStop ( sessionId , startIntervalTime , endIntervalTime ) ,
325
- i => Log . BeginInstrumentReporting ( sessionId , i . Meter . Name , i . Meter . Version , i . Name , i . GetType ( ) . Name , i . Unit , i . Description ) ,
326
- i => Log . EndInstrumentReporting ( sessionId , i . Meter . Name , i . Meter . Version , i . Name , i . GetType ( ) . Name , i . Unit , i . Description ) ,
327
- i => Log . InstrumentPublished ( sessionId , i . Meter . Name , i . Meter . Version , i . Name , i . GetType ( ) . Name , i . Unit , i . Description ) ,
328
- ( ) => Log . InitialInstrumentEnumerationComplete ( sessionId ) ,
329
- e => Log . Error ( sessionId , e . ToString ( ) ) ,
330
- ( ) => Log . TimeSeriesLimitReached ( sessionId ) ,
331
- ( ) => Log . HistogramLimitReached ( sessionId ) ,
332
- e => Log . ObservableInstrumentCallbackError ( sessionId , e . ToString ( ) ) ) ;
340
+ ( startIntervalTime , endIntervalTime ) => Parent . CollectionStart ( sessionId , startIntervalTime , endIntervalTime ) ,
341
+ ( startIntervalTime , endIntervalTime ) => Parent . CollectionStop ( sessionId , startIntervalTime , endIntervalTime ) ,
342
+ i => Parent . BeginInstrumentReporting ( sessionId , i . Meter . Name , i . Meter . Version , i . Name , i . GetType ( ) . Name , i . Unit , i . Description ) ,
343
+ i => Parent . EndInstrumentReporting ( sessionId , i . Meter . Name , i . Meter . Version , i . Name , i . GetType ( ) . Name , i . Unit , i . Description ) ,
344
+ i => Parent . InstrumentPublished ( sessionId , i . Meter . Name , i . Meter . Version , i . Name , i . GetType ( ) . Name , i . Unit , i . Description ) ,
345
+ ( ) => Parent . InitialInstrumentEnumerationComplete ( sessionId ) ,
346
+ e => Parent . Error ( sessionId , e . ToString ( ) ) ,
347
+ ( ) => Parent . TimeSeriesLimitReached ( sessionId ) ,
348
+ ( ) => Parent . HistogramLimitReached ( sessionId ) ,
349
+ e => Parent . ObservableInstrumentCallbackError ( sessionId , e . ToString ( ) ) ) ;
333
350
334
351
_aggregationManager . SetCollectionPeriod ( TimeSpan . FromSeconds ( refreshIntervalSecs ) ) ;
335
352
336
353
if ( command . Arguments ! . TryGetValue ( "Metrics" , out string ? metricsSpecs ) )
337
354
{
338
- Log . Message ( $ "Metrics argument received: { metricsSpecs } ") ;
355
+ Parent . Message ( $ "Metrics argument received: { metricsSpecs } ") ;
339
356
ParseSpecs ( metricsSpecs ) ;
340
357
}
341
358
else
342
359
{
343
- Log . Message ( "No Metrics argument received" ) ;
360
+ Parent . Message ( "No Metrics argument received" ) ;
344
361
}
345
362
346
363
_aggregationManager . Start ( ) ;
@@ -354,7 +371,7 @@ public void OnEventCommand(EventCommandEventArgs command)
354
371
355
372
private bool LogError ( Exception e )
356
373
{
357
- Log . Error ( _sessionId , e . ToString ( ) ) ;
374
+ Parent . Error ( _sessionId , e . ToString ( ) ) ;
358
375
// this code runs as an exception filter
359
376
// returning false ensures the catch handler isn't run
360
377
return false ;
@@ -374,11 +391,11 @@ private void ParseSpecs(string? metricsSpecs)
374
391
{
375
392
if ( ! MetricSpec . TryParse ( specString , out MetricSpec spec ) )
376
393
{
377
- Log . Message ( $ "Failed to parse metric spec: { specString } ") ;
394
+ Parent . Message ( $ "Failed to parse metric spec: { specString } ") ;
378
395
}
379
396
else
380
397
{
381
- Log . Message ( $ "Parsed metric: { spec } ") ;
398
+ Parent . Message ( $ "Parsed metric: { spec } ") ;
382
399
if ( spec . InstrumentName != null )
383
400
{
384
401
_aggregationManager ! . Include ( spec . MeterName , spec . InstrumentName ) ;
0 commit comments