public async Task CaptureAutoInstrumentedSpans(string targetFramework)
        {
            if (!TestEnvironment.IsWindows)
            {
                return;
            }

            var apmLogger = new InMemoryBlockingLogger(Elastic.Apm.Logging.LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            using (var profiledApplication = new ProfiledApplication("OracleManagedDataAccessSample"))
            {
                IDictionary <string, string> environmentVariables = new Dictionary <string, string>
                {
                    ["ELASTIC_APM_SERVER_URL"]      = $"http://localhost:{port}",
                    ["ORACLE_CONNECTION_STRING"]    = _fixture.ConnectionString,
                    ["ELASTIC_APM_DISABLE_METRICS"] = "*",
                    // to fix ORA-01882 Timezone region not found on CI.
                    ["TZ"] = "GMT",
                    ["ELASTIC_APM_EXIT_SPAN_MIN_DURATION"]   = "0",
                    ["ELASTIC_APM_SPAN_COMPRESSION_ENABLED"] = "false"
                };

                profiledApplication.Start(
                    targetFramework,
                    TimeSpan.FromMinutes(2),
                    environmentVariables,
                    null,
                    line => _output.WriteLine(line.Line),
                    exception => _output.WriteLine($"{exception}"));
            }

            apmServer.ReceivedData.Transactions.Should().HaveCount(2);
            apmServer.ReceivedData.Spans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedTotalSpans + AdoNetTestData.OracleProviderExpectedSpans);

            var testSpans = apmServer.ReceivedData.Spans
                            .Where(s => !s.Name.StartsWith(AdoNetTestData.OracleProviderSpanNameStart))
                            .ToList();

            var genericTransaction = apmServer.ReceivedData.Transactions.FirstOrDefault(t => t.Name == "RunAllAsync<TDbCommand>");

            genericTransaction.Should().NotBeNull();

            var genericSpans = testSpans.Where(s => s.TransactionId == genericTransaction.Id).ToList();

            genericSpans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedRunAllAsyncSpans);

            var baseTransaction = apmServer.ReceivedData.Transactions.FirstOrDefault(t => t.Name == "RunBaseTypesAsync");

            baseTransaction.Should().NotBeNull();

            var baseSpans = testSpans.Where(s => s.TransactionId == baseTransaction.Id).ToList();

            baseSpans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedRunBaseTypesAsyncSpans);

            await apmServer.StopAsync();
        }
Exemplo n.º 2
0
        public void ErrorContextSanitizerFilterDoesNotThrowWhenTransactionNotSampled()
        {
            var waitHandle = new ManualResetEventSlim();

            using var localServer = LocalServer.Create(context =>
            {
                context.Response.StatusCode = 200;
                waitHandle.Set();
            });

            var config        = new MockConfiguration(transactionSampleRate: "0", serverUrl: localServer.Uri, flushInterval: "0");
            var logger        = new InMemoryBlockingLogger(LogLevel.Warning);
            var payloadSender = new PayloadSenderV2(logger, config,
                                                    Service.GetDefaultService(config, logger), new Api.System(), MockApmServerInfo.Version710);

            using var agent = new ApmAgent(new AgentComponents(payloadSender: payloadSender, configurationReader: config));
            agent.Tracer.CaptureTransaction("Test", "Test", t =>
            {
                t.CaptureException(new Exception("boom!"));
            });

            waitHandle.Wait();

            logger.Lines.Should().NotContain(line => line.Contains("Exception during execution of the filter on transaction"));
        }
Exemplo n.º 3
0
        public async Task CaptureAutoInstrumentedSpans(string targetFramework)
        {
            var apmLogger = new InMemoryBlockingLogger(Elastic.Apm.Logging.LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            using (var profiledApplication = new ProfiledApplication("MySqlDataSample"))
            {
                IDictionary <string, string> environmentVariables = new Dictionary <string, string>
                {
                    ["ELASTIC_APM_SERVER_URL"]               = $"http://localhost:{port}",
                    ["MYSQL_CONNECTION_STRING"]              = _fixture.ConnectionString,
                    ["ELASTIC_APM_DISABLE_METRICS"]          = "*",
                    ["ELASTIC_APM_EXIT_SPAN_MIN_DURATION"]   = "0",
                    ["ELASTIC_APM_SPAN_COMPRESSION_ENABLED"] = "false"
                };

                profiledApplication.Start(
                    targetFramework,
                    TimeSpan.FromMinutes(2),
                    environmentVariables,
                    null,
                    line => _output.WriteLine(line.Line),
                    exception => _output.WriteLine($"{exception}"));
            }

            // RunAllAsync<TDbCommand> transaction
            // RunBaseTypesAsync transaction
            apmServer.ReceivedData.Transactions.Should().HaveCount(2);

            // The first MySqlCommand on an opened MySqlConnection executes an additional
            // command that the profiler instrumentation will create a span for. Since there
            // are two connections opened, 1 for RunAllAsync<TDbCommand> and 1 for RunBaseTypesAsync,
            // expect 2 additional spans
            apmServer.ReceivedData.Spans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedTotalSpans + 2);

            var genericTransaction = apmServer.ReceivedData.Transactions.FirstOrDefault(t => t.Name == "RunAllAsync<TDbCommand>");

            genericTransaction.Should().NotBeNull();

            var genericSpans = apmServer.ReceivedData.Spans.Where(s => s.TransactionId == genericTransaction.Id).ToList();

            genericSpans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedRunAllAsyncSpans + 1);

            var baseTransaction = apmServer.ReceivedData.Transactions.FirstOrDefault(t => t.Name == "RunBaseTypesAsync");

            baseTransaction.Should().NotBeNull();

            var baseSpans = apmServer.ReceivedData.Spans.Where(s => s.TransactionId == baseTransaction.Id).ToList();

            baseSpans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedRunBaseTypesAsyncSpans + 1);

            await apmServer.StopAsync();
        }
Exemplo n.º 4
0
        public async Task Auto_Instrument_With_StartupHook_Should_Capture_Error(string targetFramework)
        {
            var apmLogger = new InMemoryBlockingLogger(LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(Auto_Instrument_With_StartupHook_Should_Capture_Error));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);
            var transactionWaitHandle = new ManualResetEvent(false);
            var errorWaitHandle       = new ManualResetEvent(false);

            apmServer.OnReceive += o =>
            {
                if (o is TransactionDto)
                {
                    transactionWaitHandle.Set();
                }
                if (o is ErrorDto)
                {
                    errorWaitHandle.Set();
                }
            };

            using (var sampleApp = new SampleApplication())
            {
                var environmentVariables = new Dictionary <string, string>
                {
                    [EnvVarNames.ServerUrl]     = $"http://localhost:{port}",
                    [EnvVarNames.CloudProvider] = "none"
                };

                var uri     = sampleApp.Start(targetFramework, environmentVariables);
                var builder = new UriBuilder(uri)
                {
                    Path = "Home/Exception"
                };
                var client   = new HttpClient();
                var response = await client.GetAsync(builder.Uri);

                response.IsSuccessStatusCode.Should().BeFalse();

                transactionWaitHandle.WaitOne(TimeSpan.FromMinutes(2));
                apmServer.ReceivedData.Transactions.Should().HaveCount(1);

                var transaction = apmServer.ReceivedData.Transactions.First();
                transaction.Name.Should().Be("GET Home/Exception");

                errorWaitHandle.WaitOne(TimeSpan.FromMinutes(2));
                apmServer.ReceivedData.Errors.Should().HaveCount(1);

                var error = apmServer.ReceivedData.Errors.First();
                error.Culprit.Should().Be("Elastic.Apm.StartupHook.Sample.Controllers.HomeController");
            }

            await apmServer.StopAsync();
        }
        public async Task CaptureAutoInstrumentedSpans(string targetFramework, string npgsqlVersion)
        {
            var apmLogger = new InMemoryBlockingLogger(Elastic.Apm.Logging.LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            using (var profiledApplication = new ProfiledApplication("NpgsqlSample"))
            {
                var environmentVariables = new Dictionary <string, string>
                {
                    ["ELASTIC_APM_SERVER_URL"]               = $"http://localhost:{port}",
                    ["POSTGRES_CONNECTION_STRING"]           = _fixture.ConnectionString,
                    ["ELASTIC_APM_DISABLE_METRICS"]          = "*",
                    ["ELASTIC_APM_EXIT_SPAN_MIN_DURATION"]   = "0",
                    ["ELASTIC_APM_SPAN_COMPRESSION_ENABLED"] = "false"
                };

                var msBuildProperties = npgsqlVersion is null
                                        ? null
                                        : new Dictionary <string, string> {
                    ["NpgsqlVersion"] = npgsqlVersion
                };

                profiledApplication.Start(
                    targetFramework,
                    TimeSpan.FromMinutes(2),
                    environmentVariables,
                    msBuildProperties,
                    line => _output.WriteLine(line.Line),
                    exception => _output.WriteLine($"{exception}"));
            }

            apmServer.ReceivedData.Transactions.Should().HaveCount(2);
            apmServer.ReceivedData.Spans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedTotalSpans);

            var genericTransaction = apmServer.ReceivedData.Transactions.FirstOrDefault(t => t.Name == "RunAllAsync<TDbCommand>");

            genericTransaction.Should().NotBeNull();

            var genericSpans = apmServer.ReceivedData.Spans.Where(s => s.TransactionId == genericTransaction.Id).ToList();

            genericSpans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedRunAllAsyncSpans);

            var baseTransaction = apmServer.ReceivedData.Transactions.FirstOrDefault(t => t.Name == "RunBaseTypesAsync");

            baseTransaction.Should().NotBeNull();

            var baseSpans = apmServer.ReceivedData.Spans.Where(s => s.TransactionId == baseTransaction.Id).ToList();

            baseSpans.Should().HaveCount(AdoNetTestData.DbRunnerExpectedRunBaseTypesAsyncSpans);

            await apmServer.StopAsync();
        }
Exemplo n.º 6
0
        public void SubscribeDuplicateDiagnosticListenerTypesShouldOnlySubscribeSingle()
        {
            using (var listener = new DiagnosticListener("Test"))
            {
                var logger = new InMemoryBlockingLogger(LogLevel.Debug);
                using var agent = new ApmAgent(new TestAgentComponents(logger: logger));

                agent.Subscribe(new TestSubscriber());
                agent.Subscribe(new TestSubscriber());

                logger.Lines.Should().Contain(line => line.Contains($"Subscribed {typeof(TestListener).FullName} to `Test' events source"));
                logger.Lines.Should().Contain(line => line.Contains($"already subscribed to `Test' events source"));
                agent.SubscribedListeners.Should().HaveCount(1).And.Contain(typeof(TestListener));
            }
        }
Exemplo n.º 7
0
        public void DisposeSubscriptionShouldRemoveFromSubscribedListeners()
        {
            using (var listener = new DiagnosticListener("Test"))
            {
                var logger = new InMemoryBlockingLogger(LogLevel.Debug);
                using var agent = new ApmAgent(new TestAgentComponents(logger: logger));

                using (agent.Subscribe(new TestSubscriber()))
                {
                    logger.Lines.Should().Contain(line => line.Contains($"Subscribed {typeof(TestListener).FullName} to `Test' events source"));
                    agent.SubscribedListeners.Should().HaveCount(1).And.Contain(typeof(TestListener));
                }

                agent.SubscribedListeners.Should().BeEmpty();
            }
        }
Exemplo n.º 8
0
    public void RequestTimeoutTest()
    {
        var waitHandle = new ManualResetEvent(false);

        using var localServer = LocalServer.Create(context =>
        {
            Thread.Sleep(500000);
            context.Response.StatusCode = 200;
        });

        var iterCount = 0;
        var handler   = new MockHttpMessageHandler((r, c) =>
        {
            // 1. request times out
            if (iterCount == 0)
            {
                throw new OperationCanceledException();
            }

            // 2. request returns OK
            iterCount++;
            waitHandle.Set();
            return(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)));
        });


        var config        = new MockConfiguration(serverUrl: localServer.Uri, flushInterval: "1ms");
        var logger        = new InMemoryBlockingLogger(LogLevel.Trace);
        var payloadSender = new PayloadSenderV2(logger, config,
                                                Service.GetDefaultService(config, logger), new Api.System(), MockApmServerInfo.Version710, handler);

        using var agent = new ApmAgent(new AgentComponents(payloadSender: payloadSender, configurationReader: config));

        // This won't be sent due to timeout
        agent.Tracer.CaptureTransaction("Test", "Test", t => { });

        Thread.Sleep(500);

        // This will be sent
        agent.Tracer.CaptureTransaction("Test2", "Test", t => { });

        Thread.Sleep(500);

        waitHandle.WaitOne(TimeSpan.FromMilliseconds(1000));

        logger.Lines.Should().NotContain(l => l.Contains("WorkLoop is about to exit because it was cancelled"));
    }
        public async Task Auto_Instrument_With_StartupHook_Should_Capture_Metadata(
            string targetFramework,
            string expectedRuntimeName,
            string expectedFrameworkVersion)
        {
            var apmLogger = new InMemoryBlockingLogger(LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(Auto_Instrument_With_StartupHook_Should_Capture_Metadata));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            var waitHandle = new ManualResetEvent(false);

            apmServer.OnReceive += o =>
            {
                if (o is MetadataDto)
                {
                    waitHandle.Set();
                }
            };

            using (var sampleApp = new SampleApplication())
            {
                var environmentVariables = new Dictionary <string, string>
                {
                    [EnvVarNames.ServerUrl]     = $"http://localhost:{port}",
                    [EnvVarNames.CloudProvider] = "none"
                };

                var uri      = sampleApp.Start(targetFramework, environmentVariables);
                var client   = new HttpClient();
                var response = await client.GetAsync(uri);

                response.IsSuccessStatusCode.Should().BeTrue();

                waitHandle.WaitOne(TimeSpan.FromMinutes(2));
                apmServer.ReceivedData.Metadata.Should().HaveCountGreaterOrEqualTo(1);

                var metadata = apmServer.ReceivedData.Metadata.First();
                metadata.Service.Runtime.Name.Should().Be(expectedRuntimeName);
                metadata.Service.Framework.Name.Should().Be("ASP.NET Core");
                metadata.Service.Framework.Version.Should().Be(expectedFrameworkVersion);
            }

            await apmServer.StopAsync();
        }
        public void OsTest()
        {
            var logger = new InMemoryBlockingLogger(LogLevel.Trace);
            var cgroupMetricsProvider = new CgroupMetricsProvider(logger, new List <WildcardMatcher>());

            var samples = cgroupMetricsProvider.GetSamples();

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                samples.Should().NotBeNullOrEmpty();
                logger.Lines.Where(line => line.Contains("detected a non Linux OS, therefore Cgroup metrics will not be reported")).Should().BeNullOrEmpty();
            }
            else
            {
                samples.Should().BeNullOrEmpty();
                logger.Lines.Where(line => line.Contains("detected a non Linux OS, therefore Cgroup metrics will not be reported")).Should().NotBeNullOrEmpty();
            }
        }
Exemplo n.º 11
0
        public void CentralConfigNoUserNamePwPrinted()
        {
            var userName = "******";
            var pw       = "def";

            var inMemoryLogger = new InMemoryBlockingLogger(LogLevel.Error);
            var configReader   = new MockConfiguration(serverUrls: $"http://{userName}:{pw}@localhost:8123", maxBatchEventCount: "0",
                                                       flushInterval: "0");

            var configStore = new ConfigurationStore(configReader, inMemoryLogger);

            using var centralConfigFetcher =
                      new CentralConfigurationFetcher(inMemoryLogger, configStore, Service.GetDefaultService(configReader, inMemoryLogger));

            inMemoryLogger.Lines.Should().HaveCount(1);
            inMemoryLogger.Lines.Should().NotContain(n => n.Contains($"{userName}:{pw}"));
            inMemoryLogger.Lines.Should().Contain(n => n.Contains("http://[REDACTED]:[REDACTED]@localhost:8123"));
        }
Exemplo n.º 12
0
        public void PayloadSenderNoUserNamePwPrintedForServerUrl()
        {
            var userName       = "******";
            var pw             = "def";
            var inMemoryLogger = new InMemoryBlockingLogger(LogLevel.Warning);
            var configReader   = new MockConfiguration(serverUrls: $"http://{userName}:{pw}@localhost:8234", maxBatchEventCount: "0",
                                                       flushInterval: "0");

            using var payloadSender = new PayloadSenderV2(inMemoryLogger, configReader,
                                                          Service.GetDefaultService(configReader, inMemoryLogger), new Api.System(), MockApmServerInfo.Version710);

            using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));

            agent.Tracer.CaptureTransaction("Test", "TestTransaction", () => { });

            inMemoryLogger.Lines.Should().HaveCount(1);
            inMemoryLogger.Lines.Should().NotContain(n => n.Contains($"{userName}:{pw}"));
            inMemoryLogger.Lines.Should().Contain(n => n.Contains("http://[REDACTED]:[REDACTED]@localhost:8234"));
        }
Exemplo n.º 13
0
        public void PayloadSenderNoUserNamePwPrintedForServerUrlWithServerReturn()
        {
            var userName       = "******";
            var pw             = "def";
            var inMemoryLogger = new InMemoryBlockingLogger(LogLevel.Error);
            var port           = new Random(DateTime.UtcNow.Millisecond).Next(8100, 65535);
            var configReader   = new MockConfigSnapshot(serverUrls: $"http://{userName}:{pw}@localhost:{port}", maxBatchEventCount: "0",
                                                        flushInterval: "0");

            using var payloadSender = new PayloadSenderV2(inMemoryLogger, configReader,
                                                          Service.GetDefaultService(configReader, inMemoryLogger), new Api.System());

            using var localServer = new LocalServer(httpListenerContext => { httpListenerContext.Response.StatusCode = 500; },
                                                    $"http://*****:*****@localhost:{port}"));
        }
Exemplo n.º 14
0
        public void PayloadSenderNoUserNamePwPrintedForServerUrlWithServerReturn()
        {
            var userName       = "******";
            var pw             = "def";
            var inMemoryLogger = new InMemoryBlockingLogger(LogLevel.Error);

            using var localServer = LocalServer.Create(httpListenerContext => { httpListenerContext.Response.StatusCode = 500; });

            var uri = new Uri(localServer.Uri);

            var configReader = new MockConfiguration(serverUrls: $"http://{userName}:{pw}@{uri.Authority}", maxBatchEventCount: "0",
                                                     flushInterval: "0");

            using var payloadSender = new PayloadSenderV2(inMemoryLogger, configReader,
                                                          Service.GetDefaultService(configReader, inMemoryLogger), new Api.System(), MockApmServerInfo.Version710);

            using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));

            agent.Tracer.CaptureTransaction("Test", "TestTransaction", () => { });

            inMemoryLogger.Lines.Should().HaveCount(1);
            inMemoryLogger.Lines.Should().NotContain(n => n.Contains($"{userName}:{pw}"));
            inMemoryLogger.Lines.Should().Contain(n => n.Contains($"http://[REDACTED]:[REDACTED]@{uri.Authority}"));
        }
Exemplo n.º 15
0
        public async Task Auto_Instrument_With_StartupHook(string template, string name, string targetFramework, string path)
        {
            var apmLogger = new InMemoryBlockingLogger(LogLevel.Trace);
            var apmServer = new MockApmServer(apmLogger, nameof(Auto_Instrument_With_StartupHook));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            var transactionWaitHandle = new ManualResetEvent(false);
            var metadataWaitHandle    = new ManualResetEvent(false);

            apmServer.OnReceive += o =>
            {
                if (o is TransactionDto)
                {
                    transactionWaitHandle.Set();
                }
                else if (o is MetadataDto)
                {
                    metadataWaitHandle.Set();
                }
            };


            using var project = DotnetProject.Create(name, template, targetFramework, "--no-https");
            var environmentVariables = new Dictionary <string, string>
            {
                [EnvVarNames.ServerUrl]     = $"http://*****:*****@"\s*Now listening on:\s*(?<endpoint>http\:[^\s]*)");

                process.SubscribeLines(
                    line =>
                {
                    capturedLines.Add(line.Line);
                    var match = endpointRegex.Match(line.Line);
                    if (match.Success)
                    {
                        try
                        {
                            var endpoint = match.Groups["endpoint"].Value.Trim();
                            uri          = new UriBuilder(endpoint)
                            {
                                Path = path
                            }.Uri;
                        }
                        catch (Exception exception)
                        {
                            e = ExceptionDispatchInfo.Capture(exception);
                        }

                        startHandle.Set();
                    }
                },
                    exception => e = ExceptionDispatchInfo.Capture(exception));

                var timeout   = TimeSpan.FromMinutes(2);
                var signalled = startHandle.WaitOne(timeout);
                if (!signalled)
                {
                    throw new Exception($"Could not start dotnet project within timeout {timeout}: "
                                        + string.Join(Environment.NewLine, capturedLines));
                }

                e?.Throw();

                var client   = new HttpClient();
                var response = await client.GetAsync(uri);

                response.IsSuccessStatusCode.Should().BeTrue();

                signalled = transactionWaitHandle.WaitOne(timeout);
                if (!signalled)
                {
                    throw new Exception($"Did not receive transaction within timeout {timeout}: "
                                        + string.Join(Environment.NewLine, capturedLines)
                                        + Environment.NewLine
                                        + string.Join(Environment.NewLine, apmLogger.Lines));
                }

                apmServer.ReceivedData.Transactions.Should().HaveCount(1);

                var transaction = apmServer.ReceivedData.Transactions.First();
                transaction.Name.Should().NotBeNullOrEmpty();

                signalled = metadataWaitHandle.WaitOne(timeout);
                if (!signalled)
                {
                    throw new Exception($"Did not receive metadata within timeout {timeout}: "
                                        + string.Join(Environment.NewLine, capturedLines)
                                        + Environment.NewLine
                                        + string.Join(Environment.NewLine, apmLogger.Lines));
                }

                apmServer.ReceivedData.Metadata.Should().HaveCountGreaterOrEqualTo(1);
                var metadata = apmServer.ReceivedData.Metadata.First();
                metadata.Service.Runtime.Name.Should().NotBeNullOrEmpty();
                metadata.Service.Framework.Name.Should().Be("ASP.NET Core");
                metadata.Service.Framework.Version.Should().NotBeNullOrEmpty();
            }

            await apmServer.StopAsync();
        }
Exemplo n.º 16
0
        public async Task CaptureAutoInstrumentedSpans(string targetFramework)
        {
            var apmLogger = new InMemoryBlockingLogger(Elastic.Apm.Logging.LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            var ignoreTopic = "ignore-topic";

            using (var profiledApplication = new ProfiledApplication("KafkaSample"))
            {
                IDictionary <string, string> environmentVariables = new Dictionary <string, string>
                {
                    ["KAFKA_HOST"]                        = _fixture.BootstrapServers,
                    ["ELASTIC_APM_SERVER_URL"]            = $"http://localhost:{port}",
                    ["ELASTIC_APM_DISABLE_METRICS"]       = "*",
                    ["ELASTIC_APM_IGNORE_MESSAGE_QUEUES"] = ignoreTopic
                };

                profiledApplication.Start(
                    targetFramework,
                    TimeSpan.FromMinutes(2),
                    environmentVariables,
                    line => _output.WriteLine(line.Line),
                    exception => _output.WriteLine($"{exception}"));
            }

            // 6 * 10 consume transactions, 14 produce transactions
            var transactions = apmServer.ReceivedData.Transactions;

            transactions.Should().HaveCount(74);

            var consumeTransactions = transactions.Where(t => t.Name.StartsWith("Kafka RECEIVE")).ToList();

            consumeTransactions.Should().HaveCount(60);

            foreach (var consumeTransaction in consumeTransactions)
            {
                var spans = apmServer.ReceivedData.Spans.Where(s => s.TransactionId == consumeTransaction.Id);
                spans.Should().HaveCount(1);
                consumeTransaction.Context.Message.Queue.Should().NotBeNull();
                consumeTransaction.Context.Message.Queue.Name.Should().NotBeNullOrEmpty();
                consumeTransaction.ParentId.Should().NotBeNull();
            }

            var produceTransactions = transactions.Where(t => !t.Name.StartsWith("Kafka RECEIVE")).ToList();

            produceTransactions.Should().HaveCount(14);

            foreach (var produceTransaction in produceTransactions)
            {
                var spans = apmServer.ReceivedData.Spans.Where(s => s.TransactionId == produceTransaction.Id).ToList();

                if (produceTransaction.Name.Contains("INVALID-TOPIC"))
                {
                    spans.Should().HaveCount(1);
                }
                // the produce transaction shouldn't have an auto instrumented publish span as topic is ignored
                else if (produceTransaction.Name.Contains(ignoreTopic))
                {
                    spans.Should().BeEmpty();
                }
                else
                {
                    spans.Should().HaveCount(10);
                }

                foreach (var span in spans)
                {
                    span.Context.Message.Should().NotBeNull();
                    span.Context.Message.Queue.Should().NotBeNull();
                    span.Context.Message.Queue.Name.Should().NotBeNullOrEmpty();
                }
            }

            await apmServer.StopAsync();
        }
Exemplo n.º 17
0
        public async Task CaptureAutoInstrumentedSpans(string targetFramework)
        {
            var apmLogger = new InMemoryBlockingLogger(Logging.LogLevel.Error);
            var apmServer = new MockApmServer(apmLogger, nameof(CaptureAutoInstrumentedSpans));
            var port      = apmServer.FindAvailablePortToListen();

            apmServer.RunInBackground(port);

            using (var profiledApplication = new ProfiledApplication("RabbitMqSample"))
            {
                IDictionary <string, string> environmentVariables = new Dictionary <string, string>
                {
                    ["RABBITMQ_HOST"]                     = _fixture.ConnectionString,
                    ["ELASTIC_APM_SERVER_URL"]            = $"http://localhost:{port}",
                    ["ELASTIC_APM_DISABLE_METRICS"]       = "*",
                    ["ELASTIC_APM_IGNORE_MESSAGE_QUEUES"] = "test-ignore-exchange-name,test-ignore-queue-name"
                };

                profiledApplication.Start(
                    targetFramework,
                    TimeSpan.FromMinutes(2),
                    environmentVariables,
                    null,
                    line => _output.WriteLine(line.Line),
                    exception => _output.WriteLine($"{exception}"));
            }

            var transactions = apmServer.ReceivedData.Transactions;
            var spans        = apmServer.ReceivedData.Spans;

            transactions.Should().HaveCount(9);

            var ignoreTransaction = transactions.Single(t => t.Name == "PublishAndGetIgnore");

            // don't capture any spans for ignored queues and messages
            spans.Where(s => s.TransactionId == ignoreTransaction.Id).Should().BeEmpty();

            var publishAndGetTransaction = transactions.Single(t => t.Name == "PublishAndGet");

            spans.Where(s => s.TransactionId == publishAndGetTransaction.Id).Should().HaveCount(3, "PublishAndGet");

            var publishAndGetDefaultTransaction = transactions.Single(t => t.Name == "PublishAndGetDefault");

            spans.Where(s => s.TransactionId == publishAndGetDefaultTransaction.Id).Should().HaveCount(3, "PublishAndGetDefault");

            var senderTransactions = transactions.Where(t => t.Name == "PublishToConsumer").ToList();

            senderTransactions.Should().HaveCount(3, "PublishToConsumer");

            var consumeTransactions = transactions.Where(t => t.Name.StartsWith("RabbitMQ RECEIVE from")).ToList();

            consumeTransactions.Should().HaveCount(3, "RabbitMQ RECEIVE from");

            foreach (var senderTransaction in senderTransactions)
            {
                var senderSpan = spans.FirstOrDefault(s => s.TransactionId == senderTransaction.Id);
                senderSpan.Should().NotBeNull();

                var tracingTransaction = consumeTransactions.FirstOrDefault(t => t.TraceId == senderTransaction.TraceId);
                tracingTransaction.Should().NotBeNull();
                tracingTransaction.ParentId.Should().Be(senderSpan.Id);
            }

            foreach (var consumeTransaction in consumeTransactions)
            {
                spans.Where(s => s.TransactionId == consumeTransaction.Id).Should().HaveCount(1);
            }

            await apmServer.StopAsync();
        }