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));
        }
Example #3
0
        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);
        }
Example #5
0
        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);
            }));
        }
Example #6
0
            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));
        }
Example #9
0
        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);
            }));
        }
Example #10
0
        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;
        }