public async Task CustomSanitizeFieldNameSettingWithHeaders(string sanitizeFieldNames, string[] headerNames, bool useOnlyDiagnosticSource) { CreateAgent(useOnlyDiagnosticSource, sanitizeFieldNames); foreach (var header in headerNames) { _client.DefaultRequestHeaders.Add(header, "123"); } await _client.GetAsync("/Home/SimplePage"); _capturedPayload.WaitForTransactions(); _capturedPayload.Transactions.Should().ContainSingle(); _capturedPayload.FirstTransaction.Context.Should().NotBeNull(); _capturedPayload.FirstTransaction.Context.Request.Should().NotBeNull(); _capturedPayload.FirstTransaction.Context.Request.Headers.Should().NotBeNull(); foreach (var header in headerNames) { _capturedPayload.FirstTransaction.Context.Request.Headers[header].Should().Be(Apm.Consts.Redacted); } }
public void LabelsOnTransactionAndSpan() { const string transactionName = TestTransaction; const string transactionType = UnitTest; const string spanName = "TestSpan"; const string exceptionMessage = "Foo!"; var payloadSender = new MockPayloadSender(); using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender))) { var transaction = agent.Tracer.StartTransaction(transactionName, transactionType); transaction.SetLabel("fooTransaction1", "barTransaction1"); transaction.SetLabel("fooTransaction2", "barTransaction2"); var span = transaction.StartSpan(spanName, ApiConstants.TypeExternal); span.SetLabel("fooSpan1", "barSpan1"); span.SetLabel("fooSpan2", "barSpan2"); Thread.Sleep(5); //Make sure we have duration > 0 try { throw new InvalidOperationException(exceptionMessage); } catch (Exception e) { span.CaptureException(e); } span.End(); transaction.End(); } payloadSender.WaitForTransactions(); payloadSender.Transactions.Should().ContainSingle(); payloadSender.WaitForErrors(); payloadSender.Errors.Should().ContainSingle(); payloadSender.FirstError.Exception.Message.Should().Be(exceptionMessage); payloadSender.FirstTransaction.Context.InternalLabels.Value.MergedDictionary["fooTransaction1"].Value.Should().Be("barTransaction1"); payloadSender.FirstTransaction.Context.InternalLabels.Value.MergedDictionary["fooTransaction2"].Value.Should().Be("barTransaction2"); payloadSender.WaitForSpans(); payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.MergedDictionary["fooSpan1"].Value.Should().Be("barSpan1"); payloadSender.SpansOnFirstTransaction[0].Context.InternalLabels.Value.MergedDictionary["fooSpan2"].Value.Should().Be("barSpan2"); }
public void CaptureCustom() { var payloadSender = new MockPayloadSender(); var customValue = "b".Repeat(10_000); var customKey = "a"; using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender))) { var transaction = agent.Tracer.StartTransaction(TestTransaction, CustomTransactionTypeForTests); transaction.Custom.Add(customKey, customValue); transaction.End(); } payloadSender.WaitForTransactions(); payloadSender.FirstTransaction.Should().NotBeNull(); payloadSender.FirstTransaction.Custom[customKey].Should().Be(customValue); }
private async Task <MockPayloadSender> AssertWith1TransactionAnd1SpanAsyncOnSubSpan(Func <ISpan, Task> func) { var payloadSender = new MockPayloadSender(); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)); await agent.Tracer.CaptureTransaction(TransactionName, TransactionType, async t => { await WaitHelpers.DelayMinimum(); await t.CaptureSpan("SubSpan", "SubSpanType", async s => { await WaitHelpers.DelayMinimum(); await func(s); }); }); payloadSender.WaitForTransactions(); payloadSender.Transactions.Should().NotBeEmpty(); payloadSender.FirstTransaction.Name.Should().Be(TransactionName); payloadSender.FirstTransaction.Type.Should().Be(TransactionType); var duration = payloadSender.FirstTransaction.Duration; duration.Should().BeGreaterOrEqualToMinimumSleepLength(3); payloadSender.WaitForSpans(); payloadSender.SpansOnFirstTransaction.Should().NotBeEmpty(); payloadSender.SpansOnFirstTransaction[0].Name.Should().Be(SpanName); payloadSender.SpansOnFirstTransaction[0].Type.Should().Be(SpanType); 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); return(payloadSender); }
public void CustomServiceSetTwice() { var payloadSender = new MockPayloadSender(); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)); var transaction1 = agent.Tracer.StartTransaction("Transaction1", "test"); transaction1.SetService("Service1", "1.0-beta1"); transaction1.SetService("Service2", "1.0-beta2"); transaction1.End(); payloadSender.WaitForTransactions(); payloadSender.FirstTransaction.Should().NotBeNull(); payloadSender.FirstTransaction?.Context.Service.Name.Should().Be("Service2"); payloadSender.FirstTransaction?.Context.Service.Version.Should().Be("1.0-beta2"); }
public void TransactionResultTest() { const string transactionName = TestTransaction; const string transactionType = UnitTest; var payloadSender = new MockPayloadSender(); using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender))) { var transaction = agent.Tracer.StartTransaction(transactionName, transactionType); const string result = "success"; transaction.Result = result; transaction.End(); payloadSender.WaitForTransactions(); payloadSender.Transactions[0].Result.Should().Be(result); } }
public void UnsampledTransactionWithSpansOnV8OrNewer() { var payloadSender = new MockPayloadSender(); using (var agent = new ApmAgent(new TestAgentComponents(apmServerInfo: MockApmServerInfo.Version80, payloadSender: payloadSender, configuration: new MockConfiguration(transactionSampleRate: "0")))) { agent.Tracer.CaptureTransaction("foo", "bar", (t) => { t.CaptureSpan("span1", "testSpan", (s1) => s1.CaptureSpan("span2", "testSpan", () => { })); t.CaptureSpan("span3", "testSpan", () => { }); }); } payloadSender.WaitForTransactions(TimeSpan.FromMilliseconds(100)); payloadSender.Transactions.Should().BeNullOrEmpty(); payloadSender.Spans.Should().BeNullOrEmpty(); }
private void AssertWith1TransactionAnd1SpanOnSubSpan(Action <ISpan> action) { var payloadSender = new MockPayloadSender(); using 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.WaitForTransactions(); payloadSender.Transactions.Should().NotBeEmpty(); payloadSender.FirstTransaction.Name.Should().Be(TransactionName); payloadSender.FirstTransaction.Type.Should().Be(TransactionType); payloadSender.WaitForSpans(); 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 AgentDisabledBasicTransaction() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfiguration(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, configuration: configReader)); agent.Tracer.CurrentTransaction.Should().BeNull(); var transaction = agent.Tracer.StartTransaction("TestTransaction", "Test"); transaction.Should().NotBeOfType <Transaction>(); transaction.Should().BeOfType <NoopTransaction>(); agent.Tracer.CurrentTransaction.Should().Be(transaction); transaction.End(); payloadSender.SignalEndTransactions(); agent.Tracer.CurrentTransaction.Should().BeNull(); payloadSender.WaitForTransactions(); payloadSender.Transactions.Should().BeNullOrEmpty(); }
public void CustomServiceTest() { var payloadSender = new MockPayloadSender(); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)); var transaction1 = agent.Tracer.StartTransaction("Transaction1", "test"); transaction1.SetService("Service1", "1.0-beta1"); transaction1.End(); var transaction2 = agent.Tracer.StartTransaction("Transaction2", "test"); transaction2.SetService("Service2", "1.0-beta2"); transaction2.End(); var transaction3 = agent.Tracer.StartTransaction("Transaction3", "test"); transaction3.End(); payloadSender.WaitForTransactions(); payloadSender.Transactions.Count.Should().Be(3); var recordedTransaction1 = payloadSender.Transactions.FirstOrDefault(t => t.Name == "Transaction1"); recordedTransaction1.Should().NotBeNull(); recordedTransaction1?.Context.Service.Name.Should().Be("Service1"); recordedTransaction1?.Context.Service.Version.Should().Be("1.0-beta1"); var recordedTransaction2 = payloadSender.Transactions.FirstOrDefault(t => t.Name == "Transaction2"); recordedTransaction2.Should().NotBeNull(); recordedTransaction2?.Context.Service.Name.Should().Be("Service2"); recordedTransaction2?.Context.Service.Version.Should().Be("1.0-beta2"); var recordedTransaction3 = payloadSender.Transactions.FirstOrDefault(t => t.Name == "Transaction3"); recordedTransaction3.Should().NotBeNull(); recordedTransaction3?.Context.Service.Should().BeNull(); }
/// <summary> /// Shared between ErrorOnTransaction and ErrorOnTransactionWithCulprit /// </summary> /// <param name="culprit">Culprit.</param> private static void ErrorOnTransactionCommon(string culprit = null) { const string transactionName = TestTransaction; const string transactionType = UnitTest; const string exceptionMessage = "Foo!"; var payloadSender = new MockPayloadSender(); using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender))) { var transaction = agent.Tracer.StartTransaction(transactionName, transactionType); Thread.Sleep(5); //Make sure we have duration > 0 try { throw new InvalidOperationException(exceptionMessage); } catch (Exception e) { if (string.IsNullOrEmpty(culprit)) { transaction.CaptureException(e); } else { transaction.CaptureException(e, culprit); } } transaction.End(); } payloadSender.WaitForTransactions(); payloadSender.Transactions.Should().ContainSingle(); payloadSender.WaitForErrors(); payloadSender.Errors.Should().ContainSingle(); payloadSender.FirstError.Exception.Message.Should().Be(exceptionMessage); payloadSender.FirstError.Exception.Message.Should().Be(exceptionMessage); payloadSender.FirstError.Culprit.Should().Be(!string.IsNullOrEmpty(culprit) ? culprit : "Elastic.Apm.Tests.ApiTests.ApiTests"); }
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.WaitForTransactions(); mockPayloadSender.Transactions.Count.Should().Be(1); mockPayloadSender.Spans.Count.Should().Be(0); mockPayloadSender.FirstTransaction.SpanCount.Dropped.Should().Be(1); mockPayloadSender.FirstTransaction.SampleRate.Should().Be(1); }
public void AgentDisabledTransactionWithLambda() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfiguration(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, configuration: configReader)); var codeExecuted = false; agent.Tracer.CaptureTransaction("TestTransaction", "Test", transaction => { codeExecuted = true; transaction.Should().NotBeOfType <Transaction>(); transaction.Should().BeOfType <NoopTransaction>(); // ReSharper disable AccessToDisposedClosure agent.Tracer.CurrentTransaction.Should().NotBeNull(); agent.Tracer.CurrentTransaction.Should().Be(transaction); }); codeExecuted.Should().BeTrue(); payloadSender.SignalEndTransactions(); payloadSender.WaitForTransactions(); payloadSender.Transactions.Should().BeNullOrEmpty(); }
/// <summary> /// Asserts on 1 transaction with 1 async span and 1 error /// </summary> private async Task <MockPayloadSender> AssertWith1TransactionAnd1ErrorAnd1SpanAsync(Func <ITransaction, Task> func) { var payloadSender = new MockPayloadSender(); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender)); await agent.Tracer.CaptureTransaction(TransactionName, TransactionType, async t => { await WaitHelpers.DelayMinimum(); await func(t); }); payloadSender.WaitForTransactions(); payloadSender.Transactions.Should().NotBeEmpty(); payloadSender.FirstTransaction.Name.Should().Be(TransactionName); payloadSender.FirstTransaction.Type.Should().Be(TransactionType); var duration = payloadSender.FirstTransaction.Duration; duration.Should().BeGreaterOrEqualToMinimumSleepLength(3); payloadSender.WaitForSpans(); payloadSender.SpansOnFirstTransaction.Should().NotBeEmpty(); payloadSender.SpansOnFirstTransaction[0].Name.Should().Be(SpanName); payloadSender.SpansOnFirstTransaction[0].Type.Should().Be(SpanType); payloadSender.WaitForErrors(); payloadSender.Errors.Should().NotBeEmpty(); payloadSender.FirstError.Exception.Type.Should().Be(typeof(InvalidOperationException).FullName); payloadSender.FirstError.Exception.Message.Should().Be(ExceptionMessage); return(payloadSender); }
public async Task Capture_Transaction_When_Receive_From_Queue() { await using var scope = await QueueScope.CreateWithQueue(_adminClient); var sender = _client.CreateSender(scope.QueueName); var receiver = _client.CreateReceiver(scope.QueueName); await sender.SendMessageAsync( new ServiceBusMessage("test message")).ConfigureAwait(false); await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(30)).ConfigureAwait(false); if (!_sender.WaitForTransactions(TimeSpan.FromMinutes(2))) { throw new Exception("No transaction received in timeout"); } _sender.Transactions.Should().HaveCount(1); var transaction = _sender.FirstTransaction; transaction.Name.Should().Be($"{ServiceBus.SegmentName} RECEIVE from {scope.QueueName}"); transaction.Type.Should().Be(ApiConstants.TypeMessaging); }
public void ChangeTransactionContextAfterError() { var mockPayloadSender = new MockPayloadSender(); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: mockPayloadSender)); agent.Tracer.CaptureTransaction("Test", "Test", t => { t.Context.Request = new Request("GET", new Url { Full = "http://localhost", Protocol = "http", Search = "abc" }) { Body = "abc", Headers = new Dictionary <string, string> { { "header1", "headerValue" } } }; t.Context.Response = new Response { StatusCode = 404, Finished = false }; t.SetLabel("foo", "bar"); // Let's capture an error t.CaptureError("Test Error", "Test", new StackTrace().GetFrames()); // Let's change CurrentTransaction.Context after the error is captured t.Context.Request.Method = "PUT"; t.Context.Request.Body = "cde"; t.Context.Request.Headers["header2"] = "headerValue"; t.Context.Request.Url.Full = "http://elastic.co"; t.Context.Request.Url.Protocol = "tcp"; t.Context.Request.Url.Search = "cde"; t.Context.Response.StatusCode = 500; t.Context.Response.Finished = true; t.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); // Asserts on the captured error mockPayloadSender.WaitForErrors(); mockPayloadSender.FirstError.Should().NotBeNull("first error should not be null"); mockPayloadSender.FirstError.Context.Should().NotBeNull("context should not be null"); mockPayloadSender.FirstError.Context.Request.Method.Should().Be("GET"); mockPayloadSender.FirstError.Context.Request.Body.Should().Be("abc"); mockPayloadSender.FirstError.Context.Request.Headers.Count.Should().Be(1); mockPayloadSender.FirstError.Context.Request.Headers["header1"].Should().Be("headerValue"); mockPayloadSender.FirstError.Context.Request.Url.Full.Should().Be("http://localhost"); mockPayloadSender.FirstError.Context.Request.Url.Protocol.Should().Be("http"); mockPayloadSender.FirstError.Context.Request.Url.Search.Should().Be("abc"); mockPayloadSender.FirstError.Context.Response.StatusCode.Should().Be(404); mockPayloadSender.FirstError.Context.Response.Finished.Should().BeFalse(); mockPayloadSender.FirstError.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); mockPayloadSender.FirstError.Context.Response.Headers.Should().BeNull(); }); // Asserts on the captured transaction mockPayloadSender.WaitForTransactions(); mockPayloadSender.FirstTransaction.Context.Request.Method.Should().Be("PUT"); mockPayloadSender.FirstTransaction.Context.Request.Body.Should().Be("cde"); mockPayloadSender.FirstTransaction.Context.Request.Headers.Count.Should().Be(2); mockPayloadSender.FirstTransaction.Context.Request.Headers["header1"].Should().Be("headerValue"); mockPayloadSender.FirstTransaction.Context.Request.Headers["header2"].Should().Be("headerValue"); mockPayloadSender.FirstTransaction.Context.Request.Url.Full.Should().Be("http://elastic.co"); mockPayloadSender.FirstTransaction.Context.Request.Url.Protocol.Should().Be("tcp"); mockPayloadSender.FirstTransaction.Context.Request.Url.Search.Should().Be("cde"); mockPayloadSender.FirstTransaction.Context.Response.StatusCode.Should().Be(500); mockPayloadSender.FirstTransaction.Context.Response.Finished.Should().BeTrue(); mockPayloadSender.FirstTransaction.Context.InternalLabels.Value.InnerDictionary["foo"].Value.Should().Be("bar"); mockPayloadSender.FirstTransaction.Context.Response.Headers.Should().BeNull(); }
public async Task HomeSimplePageTransactionTest(bool withDiagnosticSourceOnly) { _client = Helper.ConfigureHttpClient(true, withDiagnosticSourceOnly, _agent, _factory); var headerKey = "X-Additional-Header"; var headerValue = "For-Elastic-Apm-Agent"; _client.DefaultRequestHeaders.Add(headerKey, headerValue); var response = await _client.GetAsync("/Home/SimplePage"); //test service _capturedPayload.WaitForTransactions(); _capturedPayload.Transactions.Should().ContainSingle(); _agent.Service.Name.Should() .NotBeNullOrWhiteSpace() .And.NotBe(ConfigConsts.DefaultValues.UnknownServiceName); _agent.Service.Agent.Name.Should().Be(Apm.Consts.AgentName); var apmVersion = typeof(Agent).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>().InformationalVersion; _agent.Service.Agent.Version.Should().Be(apmVersion); _agent.Service.Framework.Name.Should().Be("ASP.NET Core"); var aspNetCoreVersion = Assembly.Load("Microsoft.AspNetCore").GetName().Version.ToString(); _agent.Service.Framework.Version.Should().Be(aspNetCoreVersion); _agent.Service.Runtime.Name.Should().Be(Runtime.DotNetCoreName); _agent.Service.Runtime.Version.Should().Be(Directory.GetParent(typeof(object).Assembly.Location).Name); var transaction = _capturedPayload.FirstTransaction; var transactionName = $"{response.RequestMessage.Method} Home/SimplePage"; transaction.Name.Should().Be(transactionName); transaction.Result.Should().Be("HTTP 2xx"); transaction.Duration.Should().BeGreaterThan(0); transaction.Outcome.Should().Be(Outcome.Success); transaction.Type.Should().Be("request"); transaction.Id.Should().NotBeEmpty(); //test transaction.context.response transaction.Context.Response.StatusCode.Should().Be(200); if (_agent.ConfigurationReader.CaptureHeaders) { transaction.Context.Response.Headers.Should().NotBeNull(); transaction.Context.Response.Headers.Should().NotBeEmpty(); transaction.Context.Response.Headers.Should().ContainKeys(headerKey); transaction.Context.Response.Headers[headerKey].Should().Be(headerValue); } //test transaction.context.request #if NETCOREAPP3_0 || NETCOREAPP3_1 transaction.Context.Request.HttpVersion.Should().Be("2"); #else transaction.Context.Request.HttpVersion.Should().Be("2.0"); #endif transaction.Context.Request.Method.Should().Be("GET"); //test transaction.context.request.url transaction.Context.Request.Url.Full.Should().Be(response.RequestMessage.RequestUri.AbsoluteUri); transaction.Context.Request.Url.HostName.Should().Be("localhost"); transaction.Context.Request.Url.Protocol.Should().Be("HTTP"); if (_agent.ConfigurationReader.CaptureHeaders) { transaction.Context.Request.Headers.Should().NotBeNull(); transaction.Context.Request.Headers.Should().NotBeEmpty(); transaction.Context.Request.Headers.Should().ContainKeys(headerKey); transaction.Context.Request.Headers[headerKey].Should().Be(headerValue); } //test transaction.context.request.encrypted transaction.Context.Request.Socket.Encrypted.Should().BeFalse(); }