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);
                });
            });
        }
Esempio n. 3
0
        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);
                });
            });
        }
Esempio n. 5
0
        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;
 }
Esempio n. 10
0
        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);
                });
            });
        }