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); }); }
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); }); }); }
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); }); }); }
private async Task WaitForCompletion(CollectionRuleContext context, Action startCallback, IDictionary <string, CollectionRuleActionResult> allResults, ICollectionRuleAction action, CollectionRuleActionOptions actionOption, CancellationToken cancellationToken) { //Before we wait for any other action to complete, we signal that execution has started. //This allows process resume to occur. startCallback?.Invoke(); CollectionRuleActionResult results = await action.WaitForCompletionAsync(cancellationToken); if (!string.IsNullOrEmpty(actionOption.Name)) { allResults.Add(actionOption.Name, results); } _logger.CollectionRuleActionCompleted(context.Name, actionOption.Type); }
private static async Task ValidateAction(Action <ExecuteOptions> optionsCallback, Func <ICollectionRuleAction, CancellationToken, Task> actionCallback) { ExecuteActionFactory factory = new(); ExecuteOptions options = new(); optionsCallback(options); using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(DefaultTimeout); ICollectionRuleAction action = factory.Create(null, options); try { await actionCallback(action, cancellationTokenSource.Token); } finally { await DisposableHelper.DisposeAsync(action); } }
//CONSIDER Only named rules currently return results since only named results can be referenced public async Task <IDictionary <string, CollectionRuleActionResult> > ExecuteActions( CollectionRuleContext context, Action startCallback, CancellationToken cancellationToken) { if (context == null) { throw new ArgumentNullException(nameof(context)); } bool started = false; Action wrappedStartCallback = () => { if (!started) { started = true; startCallback?.Invoke(); } }; int actionIndex = 0; List <ActionCompletionEntry> deferredCompletions = new(context.Options.Actions.Count); var actionResults = new Dictionary <string, CollectionRuleActionResult>(StringComparer.Ordinal); var dependencyAnalyzer = ActionOptionsDependencyAnalyzer.Create(context); try { // Start and optionally wait for each action to complete foreach (CollectionRuleActionOptions actionOption in context.Options.Actions) { KeyValueLogScope actionScope = new(); actionScope.AddCollectionRuleAction(actionOption.Type, actionIndex); using IDisposable actionScopeRegistration = _logger.BeginScope(actionScope); _logger.CollectionRuleActionStarted(context.Name, actionOption.Type); try { IList <CollectionRuleActionOptions> actionDependencies = dependencyAnalyzer.GetActionDependencies(actionIndex); foreach (CollectionRuleActionOptions actionDependency in actionDependencies) { for (int i = 0; i < deferredCompletions.Count; i++) { ActionCompletionEntry deferredCompletion = deferredCompletions[i]; if (string.Equals(deferredCompletion.Options.Name, actionDependency.Name, StringComparison.Ordinal)) { deferredCompletions.RemoveAt(i); i--; await WaitForCompletion(context, wrappedStartCallback, actionResults, deferredCompletion, cancellationToken); break; } } } ICollectionRuleActionFactoryProxy factory; if (!_actionOperations.TryCreateFactory(actionOption.Type, out factory)) { throw new InvalidOperationException(Strings.ErrorMessage_CouldNotMapToAction); } object newSettings = dependencyAnalyzer.SubstituteOptionValues(actionResults, actionIndex, actionOption.Settings); ICollectionRuleAction action = factory.Create(context.EndpointInfo, newSettings); try { await action.StartAsync(cancellationToken); // Check if the action completion should be awaited synchronously (in respect to // starting the next action). If not, add a deferred entry so that it can be completed // after starting each action in the list. if (actionOption.WaitForCompletion.GetValueOrDefault(CollectionRuleActionOptionsDefaults.WaitForCompletion)) { await WaitForCompletion(context, wrappedStartCallback, actionResults, action, actionOption, cancellationToken); } else { deferredCompletions.Add(new(action, actionOption, actionIndex)); // Set to null to skip disposal action = null; } } finally { await DisposableHelper.DisposeAsync(action); } } catch (Exception ex) when(ShouldHandleException(ex, context.Name, actionOption.Type)) { throw new CollectionRuleActionExecutionException(ex, actionOption.Type, actionIndex); } ++actionIndex; } // Notify that all actions have started wrappedStartCallback?.Invoke(); // Wait for any actions whose completion has been deferred. while (deferredCompletions.Count > 0) { ActionCompletionEntry deferredCompletion = deferredCompletions[0]; deferredCompletions.RemoveAt(0); await WaitForCompletion(context, wrappedStartCallback, actionResults, deferredCompletion, cancellationToken); } return(actionResults); } finally { // Always dispose any deferred action completions so that those actions // are stopped before leaving the action list executor. foreach (ActionCompletionEntry deferredCompletion in deferredCompletions) { await DisposableHelper.DisposeAsync(deferredCompletion.Action); } } }
public ActionCompletionEntry(ICollectionRuleAction action, CollectionRuleActionOptions options, int index) { Action = action ?? throw new ArgumentNullException(nameof(action)); Options = options ?? throw new ArgumentNullException(nameof(options)); Index = index; }
internal async static Task <CollectionRuleActionResult> ExecuteAndDisposeAsync(ICollectionRuleAction action, TimeSpan timeout) { using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(timeout); CollectionRuleActionResult result; try { await action.StartAsync(cancellationTokenSource.Token); result = await action.WaitForCompletionAsync(cancellationTokenSource.Token); } finally { await DisposableHelper.DisposeAsync(action); } return(result); }
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); }); }); }