33using System . Collections . Generic ;
44using System . Diagnostics . Metrics ;
55using System . Linq ;
6- using System . Threading . Channels ;
6+ using System . Threading ;
77using System . Threading . Tasks ;
88using GuardNet ;
99using Microsoft . Extensions . Logging ;
@@ -17,11 +17,11 @@ namespace Promitor.Integrations.Sinks.OpenTelemetry
1717 public class OpenTelemetryCollectorMetricSink : MetricSink , IMetricSink
1818 {
1919 private readonly ILogger < OpenTelemetryCollectorMetricSink > _logger ;
20- private static readonly Meter azureMonitorMeter = new ( "Promitor.Scraper.Metrics.AzureMonitor" , "1.0" ) ;
20+ private static readonly Meter azureMonitorMeter = new Meter ( "Promitor.Scraper.Metrics.AzureMonitor" , "1.0" ) ;
2121
2222 public MetricSinkType Type => MetricSinkType . OpenTelemetryCollector ;
2323
24- public OpenTelemetryCollectorMetricSink ( IMetricsDeclarationProvider metricsDeclarationProvider , ILogger < OpenTelemetryCollectorMetricSink > logger )
24+ public OpenTelemetryCollectorMetricSink ( IMetricsDeclarationProvider metricsDeclarationProvider , ILogger < OpenTelemetryCollectorMetricSink > logger )
2525 : base ( metricsDeclarationProvider , logger )
2626 {
2727 Guard . NotNull ( logger , nameof ( logger ) ) ;
@@ -40,66 +40,53 @@ public async Task ReportMetricAsync(string metricName, string metricDescription,
4040 foreach ( var measuredMetric in scrapeResult . MetricValues )
4141 {
4242 var metricValue = measuredMetric . Value ?? 0 ;
43-
4443 var metricLabels = DetermineLabels ( metricName , scrapeResult , measuredMetric ) ;
4544
4645 var reportMetricTask = ReportMetricAsync ( metricName , metricDescription , metricValue , metricLabels ) ;
46+
4747 reportMetricTasks . Add ( reportMetricTask ) ;
4848 }
4949
5050 await Task . WhenAll ( reportMetricTasks ) ;
5151 }
5252
53- private readonly ConcurrentDictionary < string , ObservableGauge < double > > _gauges = new ( ) ;
54- private readonly ConcurrentDictionary < string , Channel < Measurement < double > > > _measurements = new ( ) ;
53+ private readonly ConcurrentDictionary < string , ObservableGauge < double > > _gauges = new ConcurrentDictionary < string , ObservableGauge < double > > ( ) ;
54+ private readonly ConcurrentDictionary < string , HashSet < Measurement < double > > > _measurements = new ConcurrentDictionary < string , HashSet < Measurement < double > > > ( ) ;
5555
56- public async Task ReportMetricAsync ( string metricName , string metricDescription , double metricValue , Dictionary < string , string > labels )
56+ public Task ReportMetricAsync ( string metricName , string metricDescription , double metricValue , Dictionary < string , string > labels )
5757 {
5858 Guard . NotNullOrEmpty ( metricName , nameof ( metricName ) ) ;
5959
60- // TODO: Move to factory instead?
60+ // TODO: Move to factory instead?
6161 if ( _gauges . ContainsKey ( metricName ) == false )
6262 {
6363 InitializeNewMetric ( metricName , metricDescription ) ;
6464 }
6565
6666 var composedTags = labels . Select ( kvp => new KeyValuePair < string , object ? > ( kvp . Key , kvp . Value ) ) . ToArray ( ) ;
6767 var newMeasurement = new Measurement < double > ( metricValue , composedTags ) ;
68- var channelWriter = _measurements [ metricName ] . Writer ;
69- await channelWriter . WriteAsync ( newMeasurement ) ;
70-
71- _logger . LogTrace ( "Metric {MetricName} with value {MetricValue} was pushed to OpenTelemetry Collector" , metricName , metricValue ) ;
68+ _measurements [ metricName ] . Add ( newMeasurement ) ;
69+
70+ _logger . LogTrace ( "Metric {MetricName} with value {MetricValue} and labels {Labels} was pushed to OpenTelemetry Collector" , metricName , metricValue , composedTags ) ;
71+
72+ return Task . CompletedTask ;
7273 }
7374
7475 private void InitializeNewMetric ( string metricName , string metricDescription )
7576 {
76- var gauge = azureMonitorMeter . CreateObservableGauge ( metricName , description : metricDescription , observeValues : ( ) => ReportMeasurementsForMetricAsync ( metricName ) . Result ) ;
77+ var gauge = azureMonitorMeter . CreateObservableGauge < double > ( metricName , description : metricDescription , observeValues : ( ) => ReportMeasurementsForMetric ( metricName ) ) ;
7778 _gauges . TryAdd ( metricName , gauge ) ;
7879
79- _measurements . TryAdd ( metricName , CreateNewMeasurementChannel ( ) ) ;
80+ _measurements . TryAdd ( metricName , [ ] ) ;
8081 }
8182
82- private async Task < IEnumerable < Measurement < double > > > ReportMeasurementsForMetricAsync ( string metricName )
83+ private IEnumerable < Measurement < double > > ReportMeasurementsForMetric ( string metricName )
8384 {
84- List < Measurement < double > > measurementsToReport = new List < Measurement < double > > ( ) ;
85- var channel = _measurements [ metricName ] ;
86-
87- var totalCount = channel . Reader . Count ;
88- var readItems = 0 ;
89- do
90- {
91- var item = await channel . Reader . ReadAsync ( ) ;
92- measurementsToReport . Add ( item ) ;
93- readItems ++ ;
94- }
95- while ( readItems < totalCount ) ;
85+ var recordedMeasurements = _measurements [ metricName ] ;
9686
97- return measurementsToReport ;
98- }
87+ var measurementsToReport = Interlocked . Exchange ( ref recordedMeasurements , [ ] ) ;
9988
100- static Channel < Measurement < double > > CreateNewMeasurementChannel ( )
101- {
102- return Channel . CreateUnbounded < Measurement < double > > ( ) ;
89+ return measurementsToReport ;
10390 }
10491 }
105- }
92+ }
0 commit comments