private async Task ValidateResponseStream(AppRunner runner, Task <ResponseStreamHolder> holderTask, Func <ChannelReader <LogEntry>, Task> callback, LogFormat logFormat) { Assert.NotNull(runner); Assert.NotNull(holderTask); Assert.NotNull(callback); // CONSIDER: Give dotnet-monitor some time to start the logs pipeline before having the target // application start logging. It would be best if dotnet-monitor could write a console event // (at Debug or Trace level) for when the pipeline has started. This would require dotnet-monitor // to know when the pipeline started and is waiting for logging data. await Task.Delay(TimeSpan.FromSeconds(3)); // Start logging in the target application await runner.SendCommandAsync(TestAppScenarios.Logger.Commands.StartLogging); // Await the holder after sending the message to start logging so that ASP.NET can send chunked responses. // If awaited before sending the message, ASP.NET will not send the complete set of headers because no data // is written into the response stream. Since HttpClient.SendAsync has to wait for the complete set of headers, // the /logs invocation would run and complete with no log events. To avoid this, the /logs invocation is started, // then the StartLogging message is sent, and finally the holder is awaited. using ResponseStreamHolder holder = await holderTask; Assert.NotNull(holder); await LogsTestUtilities.ValidateLogsEquality(holder.Stream, callback, logFormat, _outputHelper); }
private async Task ValidateLogsActionAsync( LogsConfiguration configuration, Func <ChannelReader <LogEntry>, Task> callback, LogFormat logFormat, TargetFrameworkMoniker tfm) { using TemporaryDirectory tempDirectory = new(_outputHelper); await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => { rootOptions.AddFileSystemEgress(ActionTestsConstants.ExpectedEgressProvider, tempDirectory.FullName); rootOptions.CreateCollectionRule(DefaultRuleName) .AddCollectLogsAction(ActionTestsConstants.ExpectedEgressProvider, options => { options.Duration = CommonTestTimeouts.LogsDuration; options.FilterSpecs = configuration.FilterSpecs; options.DefaultLevel = configuration.LogLevel; options.Format = logFormat; options.UseAppFilters = configuration.UseAppFilters; }) .SetStartupTrigger(); }, async host => { CollectLogsOptions options = ActionTestsHelper.GetActionOptions <CollectLogsOptions>(host, DefaultRuleName); // This is reassigned here due to a quirk in which a null value in the dictionary has its key removed, thus causing LogsDefaultLevelFallbackActionTest to fail. By reassigning here, any keys with null values are maintained. options.FilterSpecs = configuration.FilterSpecs; ICollectionRuleActionFactoryProxy factory; Assert.True(host.Services.GetService <ICollectionRuleActionOperations>().TryCreateFactory(KnownCollectionRuleActions.CollectLogs, out factory)); using CancellationTokenSource endpointTokenSource = new CancellationTokenSource(CommonTestTimeouts.LogsTimeout); EndpointInfoSourceCallback endpointInfoCallback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(endpointInfoCallback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); runner.ScenarioName = TestAppScenarios.Logger.Name; Task <IEndpointInfo> newEndpointInfoTask = endpointInfoCallback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction action = factory.Create(endpointInfo, options); using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(CommonTestTimeouts.LogsTimeout); CollectionRuleActionResult result; try { await action.StartAsync(cancellationTokenSource.Token); await runner.SendCommandAsync(TestAppScenarios.Logger.Commands.StartLogging); result = await action.WaitForCompletionAsync(cancellationTokenSource.Token); } finally { await Tools.Monitor.DisposableHelper.DisposeAsync(action); } string egressPath = ActionTestsHelper.ValidateEgressPath(result); using FileStream logsStream = new(egressPath, FileMode.Open, FileAccess.Read); Assert.NotNull(logsStream); await LogsTestUtilities.ValidateLogsEquality(logsStream, callback, logFormat, _outputHelper); }); }); }