public Task <ActionResult> CaptureLogs( ProcessKey?processKey, [FromQuery][Range(-1, int.MaxValue)] int durationSeconds = 30, [FromQuery] LogLevel?level = null, [FromQuery] string egressProvider = null) { return(InvokeForProcess(processInfo => { TimeSpan duration = ConvertSecondsToTimeSpan(durationSeconds); LogFormat format = ComputeLogFormat(Request.GetTypedHeaders().Accept); if (format == LogFormat.None) { return this.NotAcceptable(); } string fileName = FormattableString.Invariant($"{GetFileNameTimeStampUtcNow()}_{processInfo.EndpointInfo.ProcessId}.txt"); string contentType = format == LogFormat.EventStream ? ContentTypes.TextEventStream : ContentTypes.ApplicationNdJson; Func <Stream, CancellationToken, Task> action = async(outputStream, token) => { using var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream, format, level)); var settings = new EventLogsPipelineSettings() { Duration = duration }; //If the user does not explicitly specify a log level, we will use the apps defaults for .net 5. //Otherwise, we use the log level specified by the query. if ((!level.HasValue) && (processInfo.EndpointInfo.RuntimeInstanceCookie != Guid.Empty)) { settings.UseAppFilters = true; } else { settings.LogLevel = level.GetValueOrDefault(LogLevel.Warning); } var client = new DiagnosticsClient(processInfo.EndpointInfo.Endpoint); await using EventLogsPipeline pipeline = new EventLogsPipeline(client, settings, loggerFactory); await pipeline.RunAsync(token); }; return Result( ArtifactType_Logs, egressProvider, action, fileName, contentType, processInfo.EndpointInfo, format != LogFormat.EventStream); }, processKey, ArtifactType_Logs)); }
public Task <ActionResult> CaptureLogsCustom( [FromBody] Models.LogsConfiguration configuration, [FromQuery] int?pid = null, [FromQuery] Guid?uid = null, [FromQuery] string name = null, [FromQuery][Range(-1, int.MaxValue)] int durationSeconds = 30, [FromQuery] string egressProvider = null) { ProcessKey?processKey = GetProcessKey(pid, uid, name); return(InvokeForProcess(processInfo => { TimeSpan duration = Utilities.ConvertSecondsToTimeSpan(durationSeconds); var settings = new EventLogsPipelineSettings() { Duration = duration, FilterSpecs = configuration.FilterSpecs, LogLevel = configuration.LogLevel, UseAppFilters = configuration.UseAppFilters }; return StartLogs(processInfo, settings, egressProvider); }, processKey, Utilities.ArtifactType_Logs)); }
private async Task <Stream> GetLogsAsync(Action <EventLogsPipelineSettings> settingsCallback = null) { var outputStream = new MemoryStream(); await using (var testExecution = StartTraceeProcess(LoggerRemoteTestName)) { //TestRunner should account for start delay to make sure that the diagnostic pipe is available. using var loggerFactory = new LoggerFactory(new[] { new TestStreamingLoggerProvider(outputStream) }); var client = new DiagnosticsClient(testExecution.TestRunner.Pid); var logSettings = new EventLogsPipelineSettings { Duration = Timeout.InfiniteTimeSpan }; if (null != settingsCallback) { settingsCallback(logSettings); } await using var pipeline = new EventLogsPipeline(client, logSettings, loggerFactory); await PipelineTestUtilities.ExecutePipelineWithDebugee(_output, pipeline, testExecution); } outputStream.Position = 0L; return(outputStream); }
public async Task TestLogs() { var outputStream = new MemoryStream(); await using (var testExecution = StartTraceeProcess("LoggerRemoteTest")) { //TestRunner should account for start delay to make sure that the diagnostic pipe is available. using var loggerFactory = new LoggerFactory(new[] { new TestStreamingLoggerProvider(outputStream) }); var client = new DiagnosticsClient(testExecution.TestRunner.Pid); var logSettings = new EventLogsPipelineSettings { Duration = Timeout.InfiniteTimeSpan }; await using var pipeline = new EventLogsPipeline(client, logSettings, loggerFactory); await PipelineTestUtilities.ExecutePipelineWithDebugee(pipeline, testExecution); } outputStream.Position = 0L; Assert.True(outputStream.Length > 0, "No data written by logging process."); using var reader = new StreamReader(outputStream); string firstMessage = reader.ReadLine(); Assert.NotNull(firstMessage); LoggerTestResult result = JsonSerializer.Deserialize <LoggerTestResult>(firstMessage); Assert.Equal("Some warning message with 6", result.Message); Assert.Equal("LoggerRemoteTest", result.Category); Assert.Equal("Warning", result.LogLevel); Assert.Equal("0", result.EventId); Validate(result.Scopes, ("BoolValue", "true"), ("StringValue", "test"), ("IntValue", "5")); Validate(result.Arguments, ("arg", "6")); string secondMessage = reader.ReadLine(); Assert.NotNull(secondMessage); result = JsonSerializer.Deserialize <LoggerTestResult>(secondMessage); Assert.Equal("Another message", result.Message); Assert.Equal("LoggerRemoteTest", result.Category); Assert.Equal("Warning", result.LogLevel); Assert.Equal("0", result.EventId); Assert.Equal(0, result.Scopes.Count); //We are expecting only the original format Assert.Equal(1, result.Arguments.Count); }
public Task <ActionResult> Logs( ProcessFilter?processFilter, [FromQuery][Range(-1, int.MaxValue)] int durationSeconds = 30, [FromQuery] LogLevel level = LogLevel.Debug, [FromQuery] string egressProvider = null) { TimeSpan duration = ConvertSecondsToTimeSpan(durationSeconds); return(this.InvokeService(async() => { IProcessInfo processInfo = await _diagnosticServices.GetProcessAsync(processFilter, HttpContext.RequestAborted); LogFormat format = ComputeLogFormat(Request.GetTypedHeaders().Accept); if (format == LogFormat.None) { return this.NotAcceptable(); } string fileName = FormattableString.Invariant($"{GetFileNameTimeStampUtcNow()}_{processInfo.EndpointInfo.ProcessId}.txt"); string contentType = format == LogFormat.EventStream ? ContentTypes.TextEventStream : ContentTypes.ApplicationNdJson; Func <Stream, CancellationToken, Task> action = async(outputStream, token) => { using var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream, format, level)); var settings = new EventLogsPipelineSettings { Duration = duration, LogLevel = level, }; var client = new DiagnosticsClient(processInfo.EndpointInfo.Endpoint); await using EventLogsPipeline pipeline = new EventLogsPipeline(client, settings, loggerFactory); await pipeline.RunAsync(token); }; return Result( egressProvider, action, fileName, contentType, processInfo.EndpointInfo, format != LogFormat.EventStream); })); }
protected override async Task <CollectionRuleActionResult> ExecuteCoreAsync( TaskCompletionSource <object> startCompletionSource, CancellationToken token) { TimeSpan duration = Options.Duration.GetValueOrDefault(TimeSpan.Parse(CollectLogsOptionsDefaults.Duration)); bool useAppFilters = Options.UseAppFilters.GetValueOrDefault(CollectLogsOptionsDefaults.UseAppFilters); LogLevel defaultLevel = Options.DefaultLevel.GetValueOrDefault(CollectLogsOptionsDefaults.DefaultLevel); Dictionary <string, LogLevel?> filterSpecs = Options.FilterSpecs; string egressProvider = Options.Egress; LogFormat logFormat = Options.Format.GetValueOrDefault(CollectLogsOptionsDefaults.Format); var settings = new EventLogsPipelineSettings() { Duration = duration, LogLevel = defaultLevel, UseAppFilters = useAppFilters, FilterSpecs = filterSpecs }; string fileName = LogsUtilities.GenerateLogsFileName(EndpointInfo); string contentType = LogsUtilities.GetLogsContentType(logFormat); KeyValueLogScope scope = Utils.CreateArtifactScope(Utils.ArtifactType_Logs, EndpointInfo); EgressOperation egressOperation = new EgressOperation( (outputStream, token) => LogsUtilities.CaptureLogsAsync(startCompletionSource, logFormat, EndpointInfo, settings, outputStream, token), egressProvider, fileName, EndpointInfo, contentType, scope); ExecutionResult <EgressResult> result = await egressOperation.ExecuteAsync(_serviceProvider, token); string logsFilePath = result.Result.Value; return(new CollectionRuleActionResult() { OutputValues = new Dictionary <string, string>(StringComparer.Ordinal) { { CollectionRuleActionConstants.EgressPathOutputValueName, logsFilePath } } }); }
public Task <ActionResult> CaptureLogs( [FromQuery] int?pid = null, [FromQuery] Guid?uid = null, [FromQuery] string name = null, [FromQuery][Range(-1, int.MaxValue)] int durationSeconds = 30, [FromQuery] LogLevel?level = null, [FromQuery] string egressProvider = null) { ProcessKey?processKey = GetProcessKey(pid, uid, name); return(InvokeForProcess(processInfo => { TimeSpan duration = Utilities.ConvertSecondsToTimeSpan(durationSeconds); var settings = new EventLogsPipelineSettings() { Duration = duration }; // Use log level query parameter if specified, otherwise use application-defined filters. if (level.HasValue) { settings.LogLevel = level.Value; settings.UseAppFilters = false; } else { settings.UseAppFilters = true; } return StartLogs(processInfo, settings, egressProvider); }, processKey, Utilities.ArtifactType_Logs)); }
private Task <ActionResult> StartLogs( IProcessInfo processInfo, EventLogsPipelineSettings settings, string egressProvider) { LogFormat?format = ComputeLogFormat(Request.GetTypedHeaders().Accept); if (null == format) { return(Task.FromResult <ActionResult>(this.NotAcceptable())); } string fileName = LogsUtilities.GenerateLogsFileName(processInfo.EndpointInfo); string contentType = LogsUtilities.GetLogsContentType(format.Value); return(Result( Utilities.ArtifactType_Logs, egressProvider, (outputStream, token) => LogsUtilities.CaptureLogsAsync(null, format.Value, processInfo.EndpointInfo, settings, outputStream, token), fileName, contentType, processInfo.EndpointInfo, format != LogFormat.PlainText)); }
public Task <ActionResult> Logs( ProcessFilter?processFilter, [FromQuery][Range(-1, int.MaxValue)] int durationSeconds = 30, [FromQuery] LogLevel level = LogLevel.Debug) { TimeSpan duration = ConvertSecondsToTimeSpan(durationSeconds); return(this.InvokeService(async() => { IProcessInfo processInfo = await _diagnosticServices.GetProcessAsync(processFilter, HttpContext.RequestAborted); LogFormat format = ComputeLogFormat(Request.GetTypedHeaders().Accept); if (format == LogFormat.None) { return this.NotAcceptable(); } string contentType = (format == LogFormat.EventStream) ? ContentTypeEventStream : ContentTypeNdJson; string downloadName = (format == LogFormat.EventStream) ? null : FormattableString.Invariant($"{GetFileNameTimeStampUtcNow()}_{processInfo.ProcessId}.txt"); return new OutputStreamResult(async(outputStream, token) => { using var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream, format, level)); var settings = new EventLogsPipelineSettings { Duration = duration, LogLevel = level, }; await using EventLogsPipeline pipeline = new EventLogsPipeline(processInfo.Client, settings, loggerFactory); await pipeline.RunAsync(token); }, contentType, downloadName); })); }
public static async Task CaptureLogsAsync(TaskCompletionSource <object> startCompletionSource, LogFormat format, IEndpointInfo endpointInfo, EventLogsPipelineSettings settings, Stream outputStream, CancellationToken token) { using var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(new StreamingLoggerProvider(outputStream, format, logLevel: null)); var client = new DiagnosticsClient(endpointInfo.Endpoint); await using EventLogsPipeline pipeline = new EventLogsPipeline(client, settings, loggerFactory); Task runTask = await pipeline.StartAsync(token); if (null != startCompletionSource) { startCompletionSource.TrySetResult(null); } await runTask; }