private static List <EventPipeCounterGroup> ConvertCounterGroups(IList <MetricProvider> providers) { List <EventPipeCounterGroup> counterGroups = new(); if (providers?.Count > 0) { foreach (MetricProvider customProvider in providers) { var customCounterGroup = new EventPipeCounterGroup { ProviderName = customProvider.ProviderName }; if (customProvider.CounterNames.Count > 0) { customCounterGroup.CounterNames = customProvider.CounterNames.ToArray(); } counterGroups.Add(customCounterGroup); } } return(counterGroups); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { stoppingToken.ThrowIfCancellationRequested(); try { //TODO In multi-process scenarios, how do we decide which process to choose? //One possibility is to enable metrics after a request to begin polling for metrics IProcessInfo pi = await _services.GetProcessAsync(filter : null, stoppingToken); var client = new DiagnosticsClient(pi.EndpointInfo.Endpoint); MetricsOptions options = _optionsMonitor.CurrentValue; using var optionsTokenSource = new CancellationTokenSource(); //If metric options change, we need to cancel the existing metrics pipeline and restart with the new settings. using IDisposable monitorListener = _optionsMonitor.OnChange((_, _) => optionsTokenSource.Cancel()); EventPipeCounterGroup[] counterGroups = Array.Empty <EventPipeCounterGroup>(); if (options.Providers.Count > 0) { //In the dotnet-monitor case, custom metrics are additive to the default counters. var eventPipeCounterGroups = new List <EventPipeCounterGroup>(); if (options.IncludeDefaultProviders) { eventPipeCounterGroups.Add(new EventPipeCounterGroup { ProviderName = MonitoringSourceConfiguration.SystemRuntimeEventSourceName }); eventPipeCounterGroups.Add(new EventPipeCounterGroup { ProviderName = MonitoringSourceConfiguration.MicrosoftAspNetCoreHostingEventSourceName }); eventPipeCounterGroups.Add(new EventPipeCounterGroup { ProviderName = MonitoringSourceConfiguration.GrpcAspNetCoreServer }); } foreach (MetricProvider customProvider in options.Providers) { var customCounterGroup = new EventPipeCounterGroup { ProviderName = customProvider.ProviderName }; if (customProvider.CounterNames.Count > 0) { customCounterGroup.CounterNames = customProvider.CounterNames.ToArray(); } eventPipeCounterGroups.Add(customCounterGroup); } counterGroups = eventPipeCounterGroups.ToArray(); } _counterPipeline = new EventCounterPipeline(client, new EventPipeCounterPipelineSettings { CounterGroups = counterGroups, Duration = Timeout.InfiniteTimeSpan, RefreshInterval = TimeSpan.FromSeconds(options.UpdateIntervalSeconds) }, metricsLogger: new[] { new MetricsLogger(_store.MetricsStore) }); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, optionsTokenSource.Token); await _counterPipeline.RunAsync(linkedTokenSource.Token); } catch (Exception e) when(e is not OperationCanceledException || !stoppingToken.IsCancellationRequested) { //Most likely we failed to resolve the pid or metric configuration change. Attempt to do this again. if (_counterPipeline != null) { await _counterPipeline.DisposeAsync(); } await Task.Delay(5000); } } }