Пример #1
0
        public void SetInvalidLogLevelTest()
        {
            var logLevelValue = "InvalidLogLevel";
            var agent         = new ApmAgent(new TestAgentComponents(logLevelValue));
            var logger        = agent.Logger as TestLogger;

            logger.Should().NotBeNull();

            agent.ConfigurationReader.LogLevel.Should().Be(LogLevel.Error);
            logger?.Lines.Should().NotBeEmpty();
            logger?.Lines[0]
            .Should()
            .ContainAll(
                $"{{{nameof(TestAgentConfigurationReader)}}}",
                "Failed parsing log level from",
                TestAgentConfigurationReader.Origin,
                EnvVarNames.LogLevel,
                "Defaulting to "
                );
        }
Пример #2
0
        public void ServerUrlsMultipleUrlsTest()
        {
            var serverUrl1 = "http://myServer1.com:1234";
            var serverUrl2 = "http://myServer2.com:1234";
            var serverUrls = $"{serverUrl1},{serverUrl2}";

            var logger = new TestLogger();

            using var agent = new ApmAgent(new TestAgentComponents(logger,
                                                                   new MockConfigSnapshot(logger, serverUrls: serverUrls)));


            var parsedUrls = agent.ConfigurationReader.ServerUrls;

            parsedUrls[0].OriginalString.Should().Be(serverUrl1);
            parsedUrls[0].AbsoluteUri.Should().BeEquivalentTo($"{serverUrl1}/");

            parsedUrls[1].OriginalString.Should().Be(serverUrl2);
            parsedUrls[1].AbsoluteUri.Should().BeEquivalentTo($"{serverUrl2}/");
        }
Пример #3
0
        public void ServerUrls_Should_Log_Error_When_Invalid_Url()
        {
            var serverUrl = "InvalidUrl";
            var logger    = new TestLogger();

            using var agent = new ApmAgent(new TestAgentComponents(logger, new MockConfigSnapshot(logger, serverUrls: serverUrl)));
            agent.ConfigurationReader.ServerUrls[0].Should().Be(DefaultValues.ServerUri);
            agent.ConfigurationReader.ServerUrl.Should().Be(DefaultValues.ServerUri);

            logger.Lines.Should().NotBeEmpty();
            logger.Lines[0]
            .Should()
            .ContainAll(
                nameof(MockConfigSnapshot),
                "Failed parsing server URL from",
                MockConfigSnapshot.Origin,
                EnvVarNames.ServerUrls,
                serverUrl
                );
        }
Пример #4
0
        public void GetCulpritTest()
        {
            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
            {
                try
                {
                    // Throw the exception to generate a stacktrace
                    throw new Exception("TestMst");
                }
                catch (Exception e)
                {
                    agent.Tracer.CaptureTransaction("TestTransaction", "TestTransactionType",
                                                    t => { t.CaptureException(e); });
                }
            }

            payloadSender.FirstError.Culprit.Should().Be("Elastic.Apm.Tests.ApiTests.CulpritTests");
        }
Пример #5
0
        public void SimpleManualExitSpanWithContext()
        {
            var payloadSender = new MockPayloadSender();

            using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));
            agent.Tracer.CaptureTransaction("foo", "bar", t =>
            {
                var span = t.StartSpan("foo", "bar", isExitSpan: true);

                span.Context.Http = new Http {
                    Method = "GET", Url = "https://elastic.co", StatusCode = 200
                };
                span.End();
            });

            payloadSender.FirstSpan.Context.Destination.Should().NotBeNull();
            payloadSender.FirstSpan.Context.Destination.Address.Should().Be("elastic.co");
            payloadSender.FirstSpan.Context.Destination.Port.Should().Be(443);
            payloadSender.FirstSpan.Context.Destination.Service.Resource.Should().Be("elastic.co:443");
        }
Пример #6
0
        private static void AssertWithAgent(string stackTraceLimit, string spanFramesMinDuration, Action <MockPayloadSender> assertAction,
                                            int sleepLength = 0
                                            )
        {
            var payloadSender = new MockPayloadSender();

            using (var agent =
                       new ApmAgent(new TestAgentComponents(
                                        new TestAgentConfigurationReader(new NoopLogger(), stackTraceLimit: stackTraceLimit,
                                                                         spanFramesMinDurationInMilliseconds: spanFramesMinDuration), payloadSender)))
            {
                agent.Tracer.CaptureTransaction("TestTransaction", "Test", t
                                                =>
                {
                    t.CaptureSpan("span", "span", () => { Thread.Sleep(sleepLength); });
                });
            }

            assertAction(payloadSender);
        }
Пример #7
0
        public void SpansShouldNotBeSent_WhenTransactionMaxSpansIsEqualToZero()
        {
            // Arrange
            var mockPayloadSender = new MockPayloadSender();
            var mockConfig        = new MockConfigSnapshot(transactionMaxSpans: "0");

            // Act
            using (var agent = new ApmAgent(new TestAgentComponents(config: mockConfig, payloadSender: mockPayloadSender)))
            {
                agent.Tracer.CaptureTransaction("test transaction name", "test transaction type",
                                                transaction =>
                                                transaction.CaptureSpan("test span name", "test span type", span => { })
                                                );
            }

            // Assert
            mockPayloadSender.Transactions.Count.Should().Be(1);
            mockPayloadSender.Spans.Count.Should().Be(0);
            mockPayloadSender.FirstTransaction.SpanCount.Dropped.Should().Be(1);
        }
Пример #8
0
        public void Dispose_stops_the_thread()
        {
            CentralConfigFetcher lastCentralConfigFetcher;
            var configSnapshotFromReader = new ConfigSnapshotFromReader(new EnvironmentConfigurationReader(), "local");
            var configStore = new ConfigStore(configSnapshotFromReader, LoggerBase);
            var service     = Service.GetDefaultService(new EnvironmentConfigurationReader(), LoggerBase);

            using (var agent = new ApmAgent(new TestAgentComponents(LoggerBase,
                                                                    centralConfigFetcher: new CentralConfigFetcher(LoggerBase, configStore, service),
                                                                    payloadSender: new PayloadSenderV2(LoggerBase, configSnapshotFromReader, service,
                                                                                                       new SystemInfoHelper(LoggerBase).ParseSystemInfo(null)))))
            {
                lastCentralConfigFetcher = (CentralConfigFetcher)agent.CentralConfigFetcher;
                lastCentralConfigFetcher.IsRunning.Should().BeTrue();

                // Sleep a few seconds to let backend component to get to the stage where they contact APM Server
                Thread.Sleep(5.Seconds());
            }
            lastCentralConfigFetcher.IsRunning.Should().BeFalse();
        }
        public AspNetCoreMiddlewareTests(WebApplicationFactory <Startup> factory, ITestOutputHelper xUnitOutputHelper) : base(xUnitOutputHelper)
        {
            _logger  = LoggerBase.Scoped(ThisClassName);
            _factory = factory;

            _agent = new ApmAgent(new TestAgentComponents(
                                      _logger,
                                      new MockConfigSnapshot(_logger, captureBody: ConfigConsts.SupportedValues.CaptureBodyAll),
                                      // _agent needs to share CurrentExecutionSegmentsContainer with Agent.Instance
                                      // because the sample application used by the tests (SampleAspNetCoreApp) uses Agent.Instance.Tracer.CurrentTransaction/CurrentSpan
                                      currentExecutionSegmentsContainer: Agent.Instance.TracerInternal.CurrentExecutionSegmentsContainer)
                                  );
            HostBuilderExtensions.UpdateServiceInformation(_agent.Service);

            _capturedPayload = _agent.PayloadSender as MockPayloadSender;
            _client          = Helper.GetClient(_agent, _factory);
#if NETCOREAPP3_0 || NETCOREAPP3_1
            _client.DefaultRequestVersion = new Version(2, 0);
#endif
        }
Пример #10
0
        public void SingleLabelOnTransactionTests(object labelValue)
        {
            var mockPayloadSender = new MockPayloadSender();

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

            var          labelName   = "myLabel";
            ITransaction transaction = null;

            agent.Tracer.CaptureTransaction("test", "test", t =>
            {
                SetLabel(t, labelValue, labelName);
                t.Context.InternalLabels.Value.InnerDictionary[labelName].Value.Should().Be(labelValue);
                transaction = t;
            });

            var jsonString = _payloadItemSerializer.Serialize(transaction);

            jsonString.Should().Contain(GetAssertString(labelValue, labelName));
        }
        public void CustomAndLabelDontThrowNullRef()
        {
            var mockPayloadSender  = new MockPayloadSender();
            var mockConfigSnapshot = new MockConfigSnapshot(enabled: "false");

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

            var transaction = agent.Tracer.StartTransaction("foo", "bar");

            transaction.Should().BeOfType <NoopTransaction>();
            transaction.Custom["foo"] = "bar";
#pragma warning disable 618
            transaction.Labels["foo"] = "bar";
            var span = transaction.StartSpan("foo", "bar");
            span.Should().BeOfType <NoopSpan>();
            span.Labels["foo"] = "bar";
            span.End();
            transaction.End();
#pragma warning restore 618
        }
Пример #12
0
        public void PublicStringDictionaryPropertyRemoveItem()
        {
            var mockPayloadSender = new MockPayloadSender();

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

            var transaction = agent.Tracer.StartTransaction("test", "test");

            transaction.Labels["foo"] = "bar";
            transaction.SetLabel("intItem", 42);
            transaction.Labels.Remove("foo");

            transaction.End();

            var spanJsonString = _payloadItemSerializer.Serialize(transaction);

            spanJsonString.Should().Contain(GetAssertString(42, "intItem"));
            spanJsonString.Should().NotContain("foo");
            spanJsonString.Should().NotContain("bar");
        }
Пример #13
0
        public void StartEndTransaction()
        {
            var transactionName = "TestTransaction";
            var transactionType = "UnitTest";
            var payloadSender   = new MockPayloadSender();
            var agent           = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));

            var transaction = agent.Tracer.StartTransaction(transactionName, transactionType);

            Thread.Sleep(5);             //Make sure we have duration > 0

            transaction.End();
            Assert.Single(payloadSender.Payloads);
            Assert.Equal(transactionName, payloadSender.Payloads[0].Transactions[0].Name);
            Assert.Equal(transactionType, payloadSender.Payloads[0].Transactions[0].Type);
            Assert.True(payloadSender.Payloads[0].Transactions[0].Duration >= 5);
            Assert.True(payloadSender.Payloads[0].Transactions[0].Id != Guid.Empty);

            Assert.NotNull(payloadSender.Payloads[0].Service);
        }
Пример #14
0
        public void TransactionWithSpanWithoutEnd()
        {
            var transactionName = "TestTransaction";
            var transactionType = "UnitTest";
            var spanName        = "TestSpan";
            var payloadSender   = new MockPayloadSender();
            var agent           = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));

            var transaction = agent.Tracer.StartTransaction(transactionName, transactionType);

            var unused = transaction.StartSpan(spanName, ApiConstants.TypeExternal);

            Thread.Sleep(5);             //Make sure we have duration > 0

            transaction.End();           //Ends transaction, but doesn't end span.
            Assert.NotEmpty(payloadSender.Payloads);
            Assert.Empty(payloadSender.Payloads[0].Transactions[0].Spans);

            Assert.NotNull(payloadSender.Payloads[0].Service);
        }
Пример #15
0
        public void DefaultStackTraceLimitAndSpanFramesMinDuration_LongSpan()
        {
            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
            {
                agent.Tracer.CaptureTransaction("TestTransaction", "Test", t
                                                =>
                {
                    t.CaptureSpan("span", "span", () =>
                    {
                        WaitHelpers.SleepMinimum();
                        Thread.Sleep((int)ConfigConsts.DefaultValues.SpanFramesMinDurationInMilliseconds);
                    });
                });
            }

            payloadSender.FirstSpan.Should().NotBeNull();
            payloadSender.FirstSpan.StackTrace.Should().NotBeNullOrEmpty();
        }
Пример #16
0
        public void End_ShouldRestoreParentSpan_WhenTransactionIsNotSampled()
        {
            // Arrange
            var payloadSender = new MockPayloadSender();

            using (var agent =
                       new ApmAgent(new TestAgentComponents(config: new MockConfigSnapshot(transactionSampleRate: "0"), payloadSender: payloadSender)))
            {
                var transaction = agent.Tracer.StartTransaction("transaction", "type");

                var parentSpan = transaction.StartSpan("parent", "type");

                // Act
                parentSpan.CaptureSpan("span", "type", span => { });

                // Assert
                payloadSender.Spans.Count.Should().Be(0);
                agent.Tracer.CurrentSpan.Should().Be(parentSpan);
            }
        }
Пример #17
0
        public void ErrorWithDefaultStackTraceLimit()
        {
            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
            {
                Assert.Throws <Exception>(() =>
                {
                    agent.Tracer.CaptureTransaction("TestTransaction", "Test", t
                                                    =>
                    {
                        t.CaptureSpan("span", "span", () => { RecursiveCall100XAndThrow(0); });
                    });
                });
            }

            payloadSender.FirstError.Should().NotBeNull();
            payloadSender.FirstError.Exception.StackTrace.Should().NotBeNullOrEmpty();
            payloadSender.FirstError.Exception.StackTrace.Should().HaveCount(ConfigConsts.DefaultValues.StackTraceLimit);
        }
Пример #18
0
        public void TransactionWithSpanWithoutEnd()
        {
            const string transactionName = "TestTransaction";
            const string transactionType = "UnitTest";
            const string spanName        = "TestSpan";
            var          payloadSender   = new MockPayloadSender();
            var          agent           = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));

            var transaction = agent.Tracer.StartTransaction(transactionName, transactionType);

            var unused = transaction.StartSpan(spanName, ApiConstants.TypeExternal);

            Thread.Sleep(5);             //Make sure we have duration > 0

            transaction.End();           //Ends transaction, but doesn't end span.
            payloadSender.Transactions.Should().NotBeEmpty();
            payloadSender.SpansOnFirstTransaction.Should().BeEmpty();

            agent.Service.Should().NotBeNull();
        }
        public void ElasticTransactionReusesTraceIdFromCurrentActivity()
        {
            Activity.DefaultIdFormat = ActivityIdFormat.W3C;

            var activity = new Activity("UnitTestActivity");

            activity.Start();

            Activity.Current.TraceId.Should().Be(activity.TraceId);

            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
                agent.Tracer.CaptureTransaction("TestTransaction", "Test", () => Thread.Sleep(10));

            payloadSender.FirstTransaction.TraceId.Should().Be(activity.TraceId.ToString());
            payloadSender.FirstTransaction.ParentId.Should().BeNullOrEmpty();

            activity.Stop();
        }
Пример #20
0
        public void ServerUrlInvalidUrlLogTest()
        {
            var serverUrl = "InvalidUrl";
            var logger    = new TestLogger();
            var agent     = new ApmAgent(new TestAgentComponents(logger,
                                                                 new TestAgentConfigurationReader(logger, serverUrls: serverUrl)));

            agent.ConfigurationReader.ServerUrls[0].Should().Be(DefaultValues.ServerUri);

            logger.Lines.Should().NotBeEmpty();
            logger.Lines[0]
            .Should()
            .ContainAll(
                $"{{{nameof(TestAgentConfigurationReader)}}}",
                "Failed parsing server URL from",
                TestAgentConfigurationReader.Origin,
                EnvVarNames.ServerUrls,
                serverUrl
                );
        }
Пример #21
0
        internal static HttpClient GetClient <T>(ApmAgent agent, WebApplicationFactory <T> factory) where T : class
        => factory
        .WithWebHostBuilder(n =>
        {
            n.Configure(app =>
            {
                app.UseElasticApm(agent, agent.Logger, new HttpDiagnosticsSubscriber(), new EfCoreDiagnosticsSubscriber());

                app.UseDeveloperExceptionPage();

                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseCookiePolicy();

                RegisterRoutingAndMvc(app);
            });

            n.ConfigureServices(ConfigureServices);
        })
        .CreateClient();
Пример #22
0
        public void MultipleLabelsTest()
        {
            var mockPayloadSender = new MockPayloadSender();

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

            ITransaction transaction = null;
            ISpan        span        = null;

            agent.Tracer.CaptureTransaction("test", "test", t =>
            {
                transaction = t;
                t.CaptureSpan("testSpan", "test", s =>
                {
                    span = s;
                    SetLabel(s, 1, "intLabel");
                    SetLabel(s, "abc", "stringLabel");
                    SetLabel(s, true, "boolLabel");

                    s.Context.InternalLabels.Value.InnerDictionary["intLabel"].Value.Should().Be(1);
                    s.Context.InternalLabels.Value.InnerDictionary["stringLabel"].Value.Should().Be("abc");
                    s.Context.InternalLabels.Value.InnerDictionary["boolLabel"].Value.Should().Be(true);
                });

                SetLabel(t, 1, "intLabel");
                SetLabel(t, "abc", "stringLabel");
                SetLabel(t, true, "boolLabel");

                t.Context.InternalLabels.Value.InnerDictionary["intLabel"].Value.Should().Be(1);
                t.Context.InternalLabels.Value.InnerDictionary["stringLabel"].Value.Should().Be("abc");
                t.Context.InternalLabels.Value.InnerDictionary["boolLabel"].Value.Should().Be(true);
            });

            var transactionJsonString = _payloadItemSerializer.Serialize(transaction);

            transactionJsonString.Should().Contain("\"intLabel\":1,\"stringLabel\":\"abc\",\"boolLabel\":true");

            var spanJsonString = _payloadItemSerializer.Serialize(span);

            spanJsonString.Should().Contain("\"intLabel\":1,\"stringLabel\":\"abc\",\"boolLabel\":true");
        }
Пример #23
0
        private void AssertWith1TransactionAnd1SpanOnSubSpan(Action <ISpan> action)
        {
            var payloadSender = new MockPayloadSender();
            var agent         = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender));

            WaitHelpers.SleepMinimum();
            agent.Tracer.CaptureTransaction(TransactionName, TransactionType, t =>
            {
                WaitHelpers.SleepMinimum();
                t.CaptureSpan("aa", "bb", s =>                 //TODO Name
                {
                    WaitHelpers.SleepMinimum();
                    action(s);
                });
            });

            payloadSender.Transactions.Should().NotBeEmpty();

            payloadSender.FirstTransaction.Name.Should().Be(TransactionName);
            payloadSender.FirstTransaction.Type.Should().Be(TransactionType);

            payloadSender.SpansOnFirstTransaction.Should().NotBeEmpty();

            payloadSender.SpansOnFirstTransaction[0].Name.Should().Be(SpanName);
            payloadSender.SpansOnFirstTransaction[0].Type.Should().Be(SpanType);

            var duration = payloadSender.FirstTransaction.Duration;

            duration.Should().BeGreaterOrEqualToMinimumSleepLength(3);

            var orderedSpans = payloadSender.Spans.OrderBy(n => n.Timestamp).ToList();

            var firstSpan = orderedSpans.First();
            var innerSpan = orderedSpans.Last();

            firstSpan.ParentId.Should().Be(payloadSender.FirstTransaction.Id);
            innerSpan.ParentId.Should().Be(firstSpan.Id);

            firstSpan.TransactionId.Should().Be(payloadSender.FirstTransaction.Id);
            innerSpan.TransactionId.Should().Be(payloadSender.FirstTransaction.Id);
        }
        public void CompressEligibleSpanAfterParenEnded()
        {
            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender,
                                                                    configuration: new MockConfiguration(spanCompressionEnabled: "true", spanCompressionExactMatchMaxDuration: "5s",
                                                                                                         exitSpanMinDuration: "0"))))
            {
                agent.Tracer.CaptureTransaction("Foo", "Bar", t =>
                {
                    var parentSpan = t.StartSpan("foo1", "bar");

                    parentSpan.End();
                    for (var i = 0; i < 10; i++)
                    {
                        var childSpan = parentSpan.StartSpan("Select * From Table1", ApiConstants.TypeDb, ApiConstants.SubtypeMssql,
                                                             isExitSpan: true);
                        childSpan.Context.Db = new Database()
                        {
                            Type = "mssql", Instance = "01"
                        };
                        childSpan.End();
                    }
                });
            }

            // The manifestation of not implementing issues/1686 is to only have the parent span and skipping the children
            // Which in the test case means only a single span.
            payloadSender.Spans.Count.Should().NotBe(1);

            payloadSender.Spans.Count.Should().Be(11);
            payloadSender.Spans.Where(s =>
            {
                if (s is Span realSpan)
                {
                    return(realSpan.Composite != null);
                }

                return(false);
            }).Should().BeNullOrEmpty();
        }
Пример #25
0
        public void StartActivityAfterTransaction()
        {
            Activity.Current = null;

            string activityTraceId = null;
            var    payloadSender   = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
            {
                agent.Tracer.CaptureTransaction("TestTransaction", "Test", () =>
                {
                    var activity = new Activity("UnitTestActivity");
                    activity.Start();
                    Thread.Sleep(10);
                    activityTraceId = activity.TraceId.ToString();
                    activity.Stop();
                });
            }

            activityTraceId.Should().Be(payloadSender.FirstTransaction.TraceId);
        }
Пример #26
0
        [NetCoreFact]         //see: https://github.com/elastic/apm-agent-dotnet/issues/516
        public void OnNextWithStart()
        {
            var logger = new TestLogger();
            var agent  = new ApmAgent(new TestAgentComponents(logger));

            StartTransaction(agent);
            var listener = HttpDiagnosticListener.New(agent);

            var request = new HttpRequestMessage(HttpMethod.Get, "https://elastic.co");

            //Simulate Start
            listener.OnNext(new KeyValuePair <string, object>("System.Net.Http.HttpRequestOut.Start", new { Request = request }));
            ProcessingRequestsCount(listener).Should().Be(1);
            var span = GetSpanForRequest(listener, request);

            span.Context.Http.Url.Should().Be(request.RequestUri.ToString());
            span.Context.Http.Method.Should().Be(HttpMethod.Get.ToString());
            span.End();
            span.Context.Destination.Address.Should().Be(request.RequestUri.Host);
            span.Context.Destination.Port.Should().Be(UrlUtilsTests.DefaultHttpsPort);
        }
Пример #27
0
        public async Task NoWarningWithNoTransaction()
        {
            var logger = new TestLogger(LogLevel.Trace);

            // ServiceVersion is set, otherwise in the xUnit context it'd log a warning, since it can be auto discovered
            using var agent = new ApmAgent(new TestAgentComponents(logger, new MockConfigSnapshot(serviceVersion: "1.0")))
                              .Subscribe(new HttpDiagnosticsSubscriber());

            // No active transaction, just an HTTP request with an active agent
            try
            {
                var httpClient = new HttpClient();
                await(await httpClient.GetAsync("https://elastic.co")).Content.ReadAsStringAsync();
            }
            catch
            {
                /*ignore - result of the request does not matter */
            }

            logger.Lines.Should().NotContain(line => line.ToLower().Contains("warn"));
        }
Пример #28
0
        public void OnErrorLog()
        {
            var logger   = new TestLogger();
            var agent    = new ApmAgent(new TestAgentComponents(logger));
            var listener = HttpDiagnosticListener.New(agent);

            const string exceptionMessage = "Oops, this went wrong";
            var          fakeException    = new Exception(exceptionMessage);

            listener.OnError(fakeException);

            logger.Lines.Should().NotBeEmpty();
            logger.Lines[0]
            .Should()
            .ContainAll(
                "HttpDiagnosticListener",
                "in OnError",
                ".cs:",
                exceptionMessage
                );
        }
        public void CallStackWithMoveNextWithoutAsync()
        {
            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
            {
                Assert.Throws <Exception>(() =>
                {
                    agent.Tracer.CaptureTransaction("TestTransaction", "Test", () =>
                    {
                        var classWithSyncMethods = new ClassWithSyncMethods();
                        classWithSyncMethods.MoveNext();
                    });
                });
            }

            payloadSender.Errors.Should().NotBeEmpty();
            (payloadSender.Errors.First() as Error).Should().NotBeNull();
            (payloadSender.Errors.First() as Error)?.Exception.Stacktrace.Should().Contain(m => m.Function == nameof(ClassWithSyncMethods.MoveNext));
            (payloadSender.Errors.First() as Error)?.Exception.Stacktrace.Should().Contain(m => m.Function == nameof(ClassWithSyncMethods.M2));
        }
        public async Task AsyncCallStackTest()
        {
            var payloadSender = new MockPayloadSender();

            using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)))
            {
                await Assert.ThrowsAsync <Exception>(async() =>
                {
                    await agent.Tracer.CaptureTransaction("TestTransaction", "Test", async() =>
                    {
                        var classWithAsync = new ClassWithAsync();
                        await classWithAsync.TestMethodAsync();
                    });
                });
            }

            payloadSender.Errors.Should().NotBeEmpty();
            (payloadSender.Errors.First() as Error).Should().NotBeNull();
            (payloadSender.Errors.First() as Error)?.Exception.Stacktrace.Should()
            .Contain(m => m.Function == nameof(ClassWithAsync.TestMethodAsync) && m.LineNo != 0);
        }