public async Task StartLogs(Stream outputStream, int pid, TimeSpan duration, CancellationToken token) { using var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream)); await using var processor = new DiagnosticsEventPipeProcessor(PipeMode.Logs, loggerFactory: loggerFactory); await processor.Process(pid, duration, token); }
public async Task StartLogs(Stream outputStream, IProcessInfo pi, TimeSpan duration, LogFormat format, LogLevel level, CancellationToken token) { using var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream, format, level)); await using var processor = new DiagnosticsEventPipeProcessor( PipeMode.Logs, loggerFactory: loggerFactory, logsLevel: level); await processor.Process(pi.Client, pi.ProcessId, duration, token); }
public async Task <Stream> GetGcDump(int pid, CancellationToken cancellationToken) { var graph = new MemoryGraph(50_000); await using var processor = new DiagnosticsEventPipeProcessor(PipeMode.GCDump, gcGraph: graph); await processor.Process(pid, Timeout.InfiniteTimeSpan, cancellationToken); var dumper = new GCHeapDump(graph); dumper.CreationTool = "dotnet-monitor"; var stream = new MemoryStream(); var serializer = new Serializer(stream, dumper, leaveOpen: true); serializer.Close(); stream.Position = 0; return(stream); }
public async Task StartLogs(Stream outputStream, int pid, TimeSpan duration, CancellationToken token) { var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream)); var processor = new DiagnosticsEventPipeProcessor(_contextConfiguration, PipeMode.Logs, loggerFactory, Enumerable.Empty <IMetricsLogger>()); try { await processor.Process(pid, duration, token); } finally { await processor.DisposeAsync(); loggerFactory.Dispose(); } }
// Creates a ProcessInfo object from the IEndpointInfo. Attempts to get the command line using event pipe // if the endpoint information doesn't provide it. The cancelation token can be used to timebox this fallback // mechansim. public static async Task <ProcessInfo> FromEndpointInfoAsync(IEndpointInfo endpointInfo, CancellationToken extendedInfoCancellationToken) { if (null == endpointInfo) { throw new ArgumentNullException(nameof(endpointInfo)); } var client = new DiagnosticsClient(endpointInfo.Endpoint); string commandLine = endpointInfo.CommandLine; if (string.IsNullOrEmpty(commandLine)) { await using var processor = new DiagnosticsEventPipeProcessor( PipeMode.ProcessInfo, processInfoCallback: cmdLine => { commandLine = cmdLine; return(Task.CompletedTask); }); try { await processor.Process( client, endpointInfo.ProcessId, Timeout.InfiniteTimeSpan, extendedInfoCancellationToken); } catch { } } string processName = null; if (!string.IsNullOrEmpty(commandLine)) { // Get the process name from the command line bool isWindowsProcess = false; if (string.IsNullOrEmpty(endpointInfo.OperatingSystem)) { // If operating system is null, the process is likely .NET Core 3.1 (which doesn't have the GetProcessInfo command). // Since the underlying diagnostic communication channel used by the .NET runtime requires that the diagnostic process // must be running on the same type of operating system as the target process (e.g. dotnet-monitor must be running on Windows // if the target process is running on Windows), then checking the local operating system should be a sufficient heuristic // to determine the operating system of the target process. isWindowsProcess = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); } else { isWindowsProcess = ProcessOperatingSystemWindowsValue.Equals(endpointInfo.OperatingSystem, StringComparison.OrdinalIgnoreCase); } string processPath = CommandLineHelper.ExtractExecutablePath(commandLine, isWindowsProcess); if (!string.IsNullOrEmpty(processPath)) { processName = Path.GetFileName(processPath); if (isWindowsProcess) { // Remove the extension on Windows to match the behavior of Process.ProcessName processName = Path.GetFileNameWithoutExtension(processName); } } } // The GetProcessInfo command will return "unknown" for values for which it does // not know the value, such as operating system and process architecture if the // process is running on one that is not predefined. Mimic the same behavior here // when the extra process information was not provided. return(new ProcessInfo( client, endpointInfo.RuntimeInstanceCookie, endpointInfo.ProcessId, processName ?? ProcessFieldUnknownValue, commandLine ?? ProcessFieldUnknownValue, endpointInfo.OperatingSystem ?? ProcessFieldUnknownValue, endpointInfo.ProcessArchitecture ?? ProcessFieldUnknownValue)); }