コード例 #1
0
        public void Dispose()
        {
            try {
                _session?.Stop();
            } catch (ServerNotAvailableException) {
            }

            _session?.Dispose();
        }
コード例 #2
0
        public bool Stop()
        {
            if (!IsStarted)
            {
                return(false);
            }

            if (_source != null)
            {
                _source.Dispose(); _source = null;
            }
            if (_session != null)
            {
                _session.Dispose(); _session = null;
            }

            IsStarted = false;
            return(true);
        }
        private async Task StartTracing(Action <string> log)
        {
            var providers = new List <EventPipeProvider>()
            {
                // Runtime Metrics
                new EventPipeProvider(
                    "System.Runtime",
                    EventLevel.Informational,
                    0,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),

                // new EventPipeProvider("Microsoft-DotNETCore-SampleProfiler", EventLevel.Informational),
                new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, 65536 | 32768),//ClrTraceEventParser.Keywords.Default)

                // Activity correlation
                new EventPipeProvider("System.Threading.Tasks.TplEventSource",
                                      keywords: 511,
                                      eventLevel: EventLevel.LogAlways),
            };

            log($"Starting event pipe session for pid {Process.GetCurrentProcess().Id}");

            EventPipeSession session = null;
            var client = new DiagnosticsClient(Process.GetCurrentProcess().Id);

            try
            {
                session = client.StartEventPipeSession(providers);
            }
            catch (EndOfStreamException)
            {
            }
            // If the process has already exited, a ServerNotAvailableException will be thrown.
            catch (ServerNotAvailableException)
            {
            }
            catch (Exception)
            {
                // We can't even start the session, wait until the process boots up again to start another metrics thread
            }

            void StopSession()
            {
                try
                {
                    session.Stop();
                }
                catch (EndOfStreamException)
                {
                    // If the app we're monitoring exits abruptly, this may throw in which case we just swallow the exception and exit gracefully.
                }
                // We may time out if the process ended before we sent StopTracing command. We can just exit in that case.
                catch (TimeoutException)
                {
                }
                // On Unix platforms, we may actually get a PNSE since the pipe is gone with the process, and Runtime Client Library
                // does not know how to distinguish a situation where there is no pipe to begin with, or where the process has exited
                // before dotnet-counters and got rid of a pipe that once existed.
                // Since we are catching this in StopMonitor() we know that the pipe once existed (otherwise the exception would've
                // been thrown in StartMonitor directly)
                catch (PlatformNotSupportedException)
                {
                }
                // If the process has already exited, a ServerNotAvailableException will be thrown.
                // This can always race with tye shutting down and a process being restarted on exiting.
                catch (ServerNotAvailableException)
                {
                }
            }

            var _ = _cts.Token.Register(() => StopSession());

            try
            {
                using var traceOutput = File.Create("trace.nettrace");

                await session.EventStream.CopyToAsync(traceOutput);
            }
            catch (DiagnosticsClientException)
            {
            }
            catch (Exception)
            {
                // This fails if stop is called or if the process dies
            }
            finally
            {
                session?.Dispose();
            }
        }
コード例 #4
0
 public void Dispose()
 {
     _cts.Cancel();
     _eventSource?.Dispose();
     _listeningSession?.Dispose();
 }
コード例 #5
0
        public void ProcessEvents(
            string applicationName,
            string serviceName,
            int processId,
            string replicaName,
            IDictionary <string, string> metrics,
            CancellationToken cancellationToken)
        {
            var hasEventPipe = false;

            for (var i = 0; i < 10; ++i)
            {
                if (DiagnosticsClient.GetPublishedProcesses().Contains(processId))
                {
                    hasEventPipe = true;
                    break;
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                Thread.Sleep(500);
            }

            if (!hasEventPipe)
            {
                _logger.LogInformation("Process id {PID}, does not support event pipe", processId);
                return;
            }

            _logger.LogInformation("Listening for event pipe events for {ServiceName} on process id {PID}", replicaName, processId);

            // Create the logger factory for this replica
            using var loggerFactory = LoggerFactory.Create(builder => ConfigureLogging(serviceName, replicaName, builder));

            var processor = new SimpleSpanProcessor(CreateSpanExporter(serviceName, replicaName));

            var providers = new List <EventPipeProvider>()
            {
                // Runtime Metrics
                new EventPipeProvider(
                    SystemRuntimeEventSourceName,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),
                new EventPipeProvider(
                    MicrosoftAspNetCoreHostingEventSourceName,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),
                new EventPipeProvider(
                    GrpcAspNetCoreServer,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),

                // Application Metrics
                new EventPipeProvider(
                    applicationName,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),

                // Logging
                new EventPipeProvider(
                    MicrosoftExtensionsLoggingProviderName,
                    EventLevel.LogAlways,
                    (long)(LoggingEventSource.Keywords.JsonMessage | LoggingEventSource.Keywords.FormattedMessage)
                    ),

                // Distributed Tracing

                // Activity correlation
                new EventPipeProvider(TplEventSource,
                                      keywords: 0x80,
                                      eventLevel: EventLevel.LogAlways),

                // Diagnostic source events
                new EventPipeProvider(DiagnosticSourceEventSource,
                                      keywords: 0x1 | 0x2,
                                      eventLevel: EventLevel.Verbose,
                                      arguments: new Dictionary <string, string>
                {
                    { "FilterAndPayloadSpecs", DiagnosticFilterString }
                })
            };

            while (!cancellationToken.IsCancellationRequested)
            {
                EventPipeSession session = null;
                var client = new DiagnosticsClient(processId);

                try
                {
                    session = client.StartEventPipeSession(providers);
                }
                catch (EndOfStreamException)
                {
                    break;
                }
                // If the process has already exited, a ServerNotAvailableException will be thrown.
                catch (ServerNotAvailableException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        _logger.LogDebug(0, ex, "Failed to start the event pipe session");
                    }

                    // We can't even start the session, wait until the process boots up again to start another metrics thread
                    break;
                }

                void StopSession()
                {
                    try
                    {
                        session.Stop();
                    }
                    catch (EndOfStreamException)
                    {
                        // If the app we're monitoring exits abruptly, this may throw in which case we just swallow the exception and exit gracefully.
                    }
                    // We may time out if the process ended before we sent StopTracing command. We can just exit in that case.
                    catch (TimeoutException)
                    {
                    }
                    // On Unix platforms, we may actually get a PNSE since the pipe is gone with the process, and Runtime Client Library
                    // does not know how to distinguish a situation where there is no pipe to begin with, or where the process has exited
                    // before dotnet-counters and got rid of a pipe that once existed.
                    // Since we are catching this in StopMonitor() we know that the pipe once existed (otherwise the exception would've
                    // been thrown in StartMonitor directly)
                    catch (PlatformNotSupportedException)
                    {
                    }
                    // If the process has already exited, a ServerNotAvailableException will be thrown.
                    // This can always race with tye shutting down and a process being restarted on exiting.
                    catch (ServerNotAvailableException)
                    {
                    }
                }

                using var _ = cancellationToken.Register(() => StopSession());

                try
                {
                    var source = new EventPipeEventSource(session.EventStream);

                    // Distribued Tracing
                    HandleDistributedTracingEvents(source, processor);

                    // Metrics
                    HandleEventCounters(source, metrics);

                    // Logging
                    HandleLoggingEvents(source, loggerFactory, replicaName);

                    source.Process();
                }
                catch (DiagnosticsClientException ex)
                {
                    _logger.LogDebug(0, ex, "Failed to start the event pipe session");
                }
                catch (Exception)
                {
                    // This fails if stop is called or if the process dies
                }
                finally
                {
                    session?.Dispose();
                }
            }

            _logger.LogInformation("Event pipe collection completed for {ServiceName} on process id {PID}", replicaName, processId);
        }
コード例 #6
0
 public void Dispose()
 {
     _session?.Stop();
     _session?.Dispose();
 }
コード例 #7
0
        public async Task ProcessEvents(int processId, CancellationToken cancellationToken)
        {
            var hasEventPipe = false;

            for (int i = 0; i < 10; ++i)
            {
                if (DiagnosticsClient.GetPublishedProcesses().Contains(processId))
                {
                    hasEventPipe = true;
                    break;
                }

                cancellationToken.ThrowIfCancellationRequested();

                await Task.Delay(500);
            }

            if (!hasEventPipe)
            {
                _logger.LogInformation("Process id {PID}, does not support event pipe", processId);
                return;
            }

            _logger.LogInformation("Listening for event pipe events for {ServiceName} on process id {PID}", _dimValues[1], processId);

            while (!cancellationToken.IsCancellationRequested)
            {
                EventPipeSession session = null;
                var client = new DiagnosticsClient(processId);

                try
                {
                    session = client.StartEventPipeSession(_sourceConfig.GetProviders());
                }
                catch (EndOfStreamException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        _logger.LogDebug(0, ex, "Failed to start the event pipe session");
                    }

                    // We can't even start the session, wait until the process boots up again to start another metrics thread
                    break;
                }

                void StopSession()
                {
                    try
                    {
                        session.Stop();
                    }
                    catch (EndOfStreamException)
                    {
                        // If the app we're monitoring exits abruptly, this may throw in which case we just swallow the exception and exit gracefully.
                    }
                    // We may time out if the process ended before we sent StopTracing command. We can just exit in that case.
                    catch (TimeoutException)
                    {
                    }
                    // On Unix platforms, we may actually get a PNSE since the pipe is gone with the process, and Runtime Client Library
                    // does not know how to distinguish a situation where there is no pipe to begin with, or where the process has exited
                    // before dotnet-counters and got rid of a pipe that once existed.
                    // Since we are catching this in StopMonitor() we know that the pipe once existed (otherwise the exception would've
                    // been thrown in StartMonitor directly)
                    catch (PlatformNotSupportedException)
                    {
                    }
                }

                using var _ = cancellationToken.Register(() => StopSession());

                try
                {
                    var source = new EventPipeEventSource(session.EventStream);

                    // Metrics
                    HandleEventCounters(source);

                    // Logging
                    HandleLoggingEvents(source);

                    source.Process();
                }
                catch (DiagnosticsClientException ex)
                {
                    _logger.LogDebug(0, ex, "Failed to start the event pipe session");
                }
                catch (Exception)
                {
                    // This fails if stop is called or if the process dies
                }
                finally
                {
                    session?.Dispose();
                }
            }

            _logger.LogInformation("Event pipe collection completed for {ServiceName} on process id {PID}", _dimValues[1], processId);
        }