public async Task TestGetEnvVar(TargetFrameworkMoniker tfm) { const string VariableDoesNotExist = "SomeEnvVarThatIsNotSet"; await TestHostHelper.CreateCollectionRulesHost( outputHelper : _outputHelper, setup : (Tools.Monitor.RootOptions rootOptions) => { rootOptions.CreateCollectionRule(DefaultRuleName) .SetStartupTrigger() .AddGetEnvironmentVariableAction(TestAppScenarios.EnvironmentVariables.IncrementVariableName) .AddGetEnvironmentVariableAction(VariableDoesNotExist); }, hostCallback : async(Extensions.Hosting.IHost host) => { GetEnvironmentVariableOptions getOpts = ActionTestsHelper.GetActionOptions <GetEnvironmentVariableOptions>(host, DefaultRuleName, 0); GetEnvironmentVariableOptions getFailOpts = ActionTestsHelper.GetActionOptions <GetEnvironmentVariableOptions>(host, DefaultRuleName, 1); ICollectionRuleActionOperations actionOperationsService = host.Services.GetService <ICollectionRuleActionOperations>(); Assert.True(actionOperationsService.TryCreateFactory(KnownCollectionRuleActions.GetEnvironmentVariable, out ICollectionRuleActionFactoryProxy getFactory)); EndpointInfoSourceCallback endpointInfoCallback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(endpointInfoCallback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); runner.ScenarioName = TestAppScenarios.EnvironmentVariables.Name; Task <IEndpointInfo> newEndpointInfoTask = endpointInfoCallback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction getAction = getFactory.Create(endpointInfo, getOpts); await runner.SendCommandAsync(TestAppScenarios.EnvironmentVariables.Commands.IncVar); Assert.Equal("1", await runner.GetEnvironmentVariable(TestAppScenarios.EnvironmentVariables.IncrementVariableName, CommonTestTimeouts.EnvVarsTimeout)); await runner.SendCommandAsync(TestAppScenarios.EnvironmentVariables.Commands.IncVar); Assert.Equal("2", await runner.GetEnvironmentVariable(TestAppScenarios.EnvironmentVariables.IncrementVariableName, CommonTestTimeouts.EnvVarsTimeout)); CollectionRuleActionResult result = await ActionTestsHelper.ExecuteAndDisposeAsync(getAction, CommonTestTimeouts.EnvVarsTimeout); Assert.Equal("2", result.OutputValues[CollectionRuleActionConstants.EnvironmentVariableValueName]); await runner.SendCommandAsync(TestAppScenarios.EnvironmentVariables.Commands.IncVar); Assert.Equal("3", await runner.GetEnvironmentVariable(TestAppScenarios.EnvironmentVariables.IncrementVariableName, CommonTestTimeouts.EnvVarsTimeout)); ICollectionRuleAction getActionFailure = getFactory.Create(endpointInfo, getFailOpts); CollectionRuleActionException thrownEx = await Assert.ThrowsAsync <CollectionRuleActionException>(async() => { await ActionTestsHelper.ExecuteAndDisposeAsync(getActionFailure, CommonTestTimeouts.EnvVarsTimeout); }); Assert.Contains(VariableDoesNotExist, thrownEx.Message); await runner.SendCommandAsync(TestAppScenarios.EnvironmentVariables.Commands.ShutdownScenario); }); }); }
private async Task PerformTrace(IHost host, TargetFrameworkMoniker tfm) { CollectTraceOptions options = ActionTestsHelper.GetActionOptions <CollectTraceOptions>(host, DefaultRuleName); ICollectionRuleActionFactoryProxy factory; Assert.True(host.Services.GetService <ICollectionRuleActionOperations>().TryCreateFactory(KnownCollectionRuleActions.CollectTrace, out factory)); EndpointInfoSourceCallback callback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(callback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); Task <IEndpointInfo> newEndpointInfoTask = callback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction action = factory.Create(endpointInfo, options); CollectionRuleActionResult result = await ActionTestsHelper.ExecuteAndDisposeAsync(action, CommonTestTimeouts.TraceTimeout); string egressPath = ActionTestsHelper.ValidateEgressPath(result); using FileStream traceStream = new(egressPath, FileMode.Open, FileAccess.Read); Assert.NotNull(traceStream); await ValidateTrace(traceStream); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }); }
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); }
public async Task ServerSourceNoPruneDuringDumpTest(TargetFrameworkMoniker appTfm) { EndpointInfoSourceCallback callback = new(_outputHelper); var operationTrackerService = new OperationTrackerService(); MockDumpService dumpService = new(operationTrackerService); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(callback, dumpService, operationTrackerService); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, appTfm); Task <IEndpointInfo> addedEndpointTask = callback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); Task <IEndpointInfo> removedEndpointTask = callback.WaitRemovedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); Task <Stream> dumpTask = null; IEndpointInfo endpointInfo = null; await runner.ExecuteAsync(async() => { _outputHelper.WriteLine("Waiting for added endpoint notification."); endpointInfo = await addedEndpointTask; _outputHelper.WriteLine("Received added endpoint notifications."); // Start a dump operation; the process should not be pruned until the operation is completed. dumpTask = dumpService.DumpAsync(endpointInfo, DumpType.Triage, CancellationToken.None); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }); // At this point, the process should no longer exist; but since the mock dump operation is // in progress, the ServiceEndpointInfoSource should not prune the process until the operation // is complete. int processId = await runner.ProcessIdTask; // Test that the process still exists. Assert.False(removedEndpointTask.IsCompleted); IEnumerable <IEndpointInfo> endpointInfos = await _endpointUtilities.GetEndpointInfoAsync(sourceHolder.Source); endpointInfo = Assert.Single(endpointInfos); Assert.Equal(processId, endpointInfo.ProcessId); // Signal and wait for mock dump operation to complete. dumpService.CompleteOperation(); await dumpTask; // Process should no longer exist endpointInfos = await _endpointUtilities.GetEndpointInfoAsync(sourceHolder.Source); Assert.Empty(endpointInfos); // Test that process removal sent notification endpointInfo = await removedEndpointTask; Assert.Equal(processId, endpointInfo.ProcessId); }
public async Task CollectDumpAction_Success(TargetFrameworkMoniker tfm, DumpType?dumpType) { // MacOS dumps inconsistently segfault the runtime on .NET 5: https://github.com/dotnet/dotnet-monitor/issues/174 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && tfm == TargetFrameworkMoniker.Net50) { return; } using TemporaryDirectory tempDirectory = new(_outputHelper); await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => { rootOptions.AddFileSystemEgress(ActionTestsConstants.ExpectedEgressProvider, tempDirectory.FullName); rootOptions.CreateCollectionRule(DefaultRuleName) .AddCollectDumpAction(ActionTestsConstants.ExpectedEgressProvider, dumpType) .SetStartupTrigger(); }, async host => { CollectDumpOptions options = ActionTestsHelper.GetActionOptions <CollectDumpOptions>(host, DefaultRuleName); ICollectionRuleActionFactoryProxy factory; Assert.True(host.Services.GetService <ICollectionRuleActionOperations>().TryCreateFactory(KnownCollectionRuleActions.CollectDump, out factory)); EndpointInfoSourceCallback callback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(callback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); Task <IEndpointInfo> newEndpointInfoTask = callback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction action = factory.Create(endpointInfo, options); CollectionRuleActionResult result = await ActionTestsHelper.ExecuteAndDisposeAsync(action, CommonTestTimeouts.DumpTimeout); string egressPath = ActionTestsHelper.ValidateEgressPath(result); using FileStream dumpStream = new(egressPath, FileMode.Open, FileAccess.Read); Assert.NotNull(dumpStream); await DumpTestUtilities.ValidateDump(runner.Environment.ContainsKey(DumpTestUtilities.EnableElfDumpOnMacOS), dumpStream); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }); }); }
public async Task TestEnvVarRoundTrip(TargetFrameworkMoniker tfm) { await TestHostHelper.CreateCollectionRulesHost( outputHelper : _outputHelper, setup : (Tools.Monitor.RootOptions rootOptions) => { rootOptions.CreateCollectionRule(DefaultRuleName) .SetStartupTrigger() .AddSetEnvironmentVariableAction(DefaultVarName, DefaultVarValue) .AddGetEnvironmentVariableAction(DefaultVarName); }, hostCallback : async(Extensions.Hosting.IHost host) => { SetEnvironmentVariableOptions setOpts = ActionTestsHelper.GetActionOptions <SetEnvironmentVariableOptions>(host, DefaultRuleName, 0); GetEnvironmentVariableOptions getOpts = ActionTestsHelper.GetActionOptions <GetEnvironmentVariableOptions>(host, DefaultRuleName, 1); ICollectionRuleActionOperations actionOperationsService = host.Services.GetService <ICollectionRuleActionOperations>(); Assert.True(actionOperationsService.TryCreateFactory(KnownCollectionRuleActions.SetEnvironmentVariable, out ICollectionRuleActionFactoryProxy setFactory)); Assert.True(actionOperationsService.TryCreateFactory(KnownCollectionRuleActions.GetEnvironmentVariable, out ICollectionRuleActionFactoryProxy getFactory)); EndpointInfoSourceCallback endpointInfoCallback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(endpointInfoCallback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); runner.ScenarioName = TestAppScenarios.EnvironmentVariables.Name; Task <IEndpointInfo> newEndpointInfoTask = endpointInfoCallback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction setAction = setFactory.Create(endpointInfo, setOpts); ICollectionRuleAction getAction = getFactory.Create(endpointInfo, getOpts); await ActionTestsHelper.ExecuteAndDisposeAsync(setAction, CommonTestTimeouts.EnvVarsTimeout); CollectionRuleActionResult getResult = await ActionTestsHelper.ExecuteAndDisposeAsync(getAction, CommonTestTimeouts.EnvVarsTimeout); await runner.SendCommandAsync(TestAppScenarios.EnvironmentVariables.Commands.ShutdownScenario); Assert.True(getResult.OutputValues.TryGetValue(CollectionRuleActionConstants.EnvironmentVariableValueName, out string value)); Assert.Equal(DefaultVarValue, value); }); }); }
public async Task CollectGCDumpAction_Success(TargetFrameworkMoniker tfm) { using TemporaryDirectory tempDirectory = new(_outputHelper); await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => { rootOptions.AddFileSystemEgress(ActionTestsConstants.ExpectedEgressProvider, tempDirectory.FullName); rootOptions.CreateCollectionRule(DefaultRuleName) .AddCollectGCDumpAction(ActionTestsConstants.ExpectedEgressProvider) .SetStartupTrigger(); }, async host => { CollectGCDumpOptions options = ActionTestsHelper.GetActionOptions <CollectGCDumpOptions>(host, DefaultRuleName); ICollectionRuleActionFactoryProxy factory; Assert.True(host.Services.GetService <ICollectionRuleActionOperations>().TryCreateFactory(KnownCollectionRuleActions.CollectGCDump, out factory)); EndpointInfoSourceCallback callback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(callback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); Task <IEndpointInfo> newEndpointInfoTask = callback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction action = factory.Create(endpointInfo, options); CollectionRuleActionResult result = await ActionTestsHelper.ExecuteAndDisposeAsync(action, CommonTestTimeouts.GCDumpTimeout); string egressPath = ActionTestsHelper.ValidateEgressPath(result); using FileStream gcdumpStream = new(egressPath, FileMode.Open, FileAccess.Read); Assert.NotNull(gcdumpStream); await ValidateGCDump(gcdumpStream); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }); }); }
public async Task ServerSourceAddRemoveSingleConnectionTest(TargetFrameworkMoniker appTfm) { EndpointInfoSourceCallback callback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(callback); var endpointInfos = await _endpointUtilities.GetEndpointInfoAsync(sourceHolder.Source); Assert.Empty(endpointInfos); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, appTfm); Task addedEndpointTask = callback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); Task removedEndpointTask = callback.WaitRemovedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { _outputHelper.WriteLine("Waiting for added endpoint notification."); await addedEndpointTask; _outputHelper.WriteLine("Received added endpoint notifications."); endpointInfos = await _endpointUtilities.GetEndpointInfoAsync(sourceHolder.Source); var endpointInfo = Assert.Single(endpointInfos); ValidateEndpointInfo(endpointInfo); await EndpointUtilities.VerifyConnectionAsync(runner, endpointInfo); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }); _outputHelper.WriteLine("Waiting for removed endpoint notification."); await removedEndpointTask; _outputHelper.WriteLine("Received removed endpoint notifications."); endpointInfos = await _endpointUtilities.GetEndpointInfoAsync(sourceHolder.Source); Assert.Empty(endpointInfos); }
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); }); }); }