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 " ); }
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}/"); }
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 ); }
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"); }
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"); }
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); }
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); }
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 }
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 }
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"); }
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); }
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); }
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(); }
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); } }
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); }
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(); }
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 ); }
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();
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"); }
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(); }
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); }
[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); }
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")); }
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); }