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);
        }
Exemple #2
0
        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);
                }
            }
        }