public async Task MetricsWithRealAgent() { // Note: If XunitOutputLogger is used with MetricsCollector it might cause issues because // MetricsCollector's Dispose is currently broken - it doesn't guarantee that MetricsCollector's behaves correctly (i.e., ignores) // timer callbacks after Dispose completed. // This bug in turn causes MetricsCollector to possibly use XunitOutputLogger even after the current test has exited // and ITestOutputHelper on which XunitOutputLogger is based became invalid. // // After https://github.com/elastic/apm-agent-dotnet/issues/494 is fixed the line below can be uncommented. // // var logger = _logger; // var logger = new NoopLogger(); // var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(logger, metricsInterval: "1s", logLevel: "Debug"); using var agentComponents = new AgentComponents(payloadSender: payloadSender, logger: logger, configurationReader: configReader); using (var agent = new ApmAgent(agentComponents)) { await Task.Delay(10000); //make sure we wait enough to collect 1 set of metrics agent.ConfigurationReader.MetricsIntervalInMilliseconds.Should().Be(1000); } payloadSender.Metrics.Should().NotBeEmpty(); payloadSender.Metrics.First().Samples.Should().NotBeEmpty(); }
public void LimitedAmountOfSpansShouldBeSent_WhenSpansAreCapturedConcurrently() { // Arrange const int spansCount = 10; const int maxSpansCount = 2; var mockPayloadSender = new MockPayloadSender(); var mockConfig = new MockConfigSnapshot(transactionMaxSpans: maxSpansCount.ToString()); // Act using (var agent = new ApmAgent(new TestAgentComponents(config: mockConfig, payloadSender: mockPayloadSender))) { agent.Tracer.CaptureTransaction("test transaction name", "test transaction type", transaction => { MultiThreadsTestUtils.TestOnThreads(spansCount, threadIndex => { transaction.CaptureSpan($"test span name #{threadIndex}", "test span type", span => { }); return(1); }); }); } // Assert mockPayloadSender.WaitForTransactions(); mockPayloadSender.Transactions.Count.Should().Be(1); mockPayloadSender.WaitForSpans(); mockPayloadSender.Spans.Count.Should().Be(maxSpansCount); mockPayloadSender.FirstTransaction.SpanCount.Dropped.Should().Be(spansCount - maxSpansCount); }
public async Task SecretToken_test() { var isRequestFinished = new TaskCompletionSource <object>(); AuthenticationHeaderValue authHeader = null; var handler = new MockHttpMessageHandler((r, c) => { authHeader = r.Headers.Authorization; isRequestFinished.SetResult(null); return(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); }); const string secretToken = "SecretToken"; var noopLogger = new NoopLogger(); var mockConfig = new MockConfigSnapshot(_logger, secretToken: secretToken, maxBatchEventCount: "1"); var payloadSender = new PayloadSenderV2(_logger, mockConfig, Service.GetDefaultService(mockConfig, noopLogger), new Api.System(), handler, /* dbgName: */ TestDisplayName); using (var agent = new ApmAgent(new TestAgentComponents(LoggerBase, mockConfig, payloadSender))) { agent.PayloadSender.QueueTransaction(new Transaction(agent, "TestName", "TestType")); await isRequestFinished.Task; } authHeader.Should().NotBeNull(); authHeader.Scheme.Should().Be("Bearer"); authHeader.Parameter.Should().Be(secretToken); }
public async Task ToggleRecordingAndCaptureMetrics() { var logger = new NoopLogger(); var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(logger, metricsInterval: "1s", logLevel: "Debug", recording: "false"); using var agentComponents = new AgentComponents(payloadSender: payloadSender, logger: logger, configurationReader: configReader); using var agent = new ApmAgent(agentComponents); await Task.Delay(10000); //make sure we wait enough to collect 1 set of metrics agent.ConfigurationReader.MetricsIntervalInMilliseconds.Should().Be(1000); payloadSender.Metrics.Should().BeEmpty(); //start recording agent.ConfigStore.CurrentSnapshot = new MockConfigSnapshot(logger, metricsInterval: "1s", logLevel: "Debug", recording: "true"); await Task.Delay(10000); //make sure we wait enough to collect 1 set of metrics //stop recording agent.ConfigStore.CurrentSnapshot = new MockConfigSnapshot(logger, metricsInterval: "1s", logLevel: "Debug", recording: "false"); payloadSender.Metrics.Should().NotBeEmpty(); await Task.Delay(500); //make sure collection on the MetricCollector is finished var numberOfEvents = payloadSender.Metrics.Count; await Task.Delay(10000); //make sure we wait enough to collect 1 set of metrics payloadSender.Metrics.Count.Should().Be(numberOfEvents); }
public async Task CheckAuthorizationHeader(string authorizationHeader) { var isRequestFinished = new TaskCompletionSource <object>(); AuthenticationHeaderValue authHeader = null; var handler = new MockHttpMessageHandler((r, c) => { authHeader = r.Headers.Authorization; isRequestFinished.SetResult(null); return(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); }); var logger = new NoopLogger(); var mockConfig = new MockConfigSnapshot(logger, secretToken: _secretToken, apiKey: _apiKey, flushInterval: "1s"); var payloadSender = new PayloadSenderV2(logger, mockConfig, Api.Service.GetDefaultService(mockConfig, logger), new Api.System(), handler, /* dbgName: */ nameof(ApiKeyFeatureContext)); using (var agent = new ApmAgent(new TestAgentComponents(logger, mockConfig, payloadSender))) { agent.PayloadSender.QueueTransaction(new Transaction(agent, "TestName", "TestType")); await isRequestFinished.Task; } authHeader.Should().NotBeNull(); authHeader.ToString().Should().Be(authorizationHeader); }
public void LimitedAmountOfSpansShouldBeSent_WhenTransactionMaxSpansIsPositiveNumber() { // Arrange const int spansCount = 10; const int maxSpansCount = 5; var mockPayloadSender = new MockPayloadSender(); var mockConfig = new MockConfigSnapshot(transactionMaxSpans: maxSpansCount.ToString()); // Act using (var agent = new ApmAgent(new TestAgentComponents(config: mockConfig, payloadSender: mockPayloadSender))) { agent.Tracer.CaptureTransaction("test transaction name", "test transaction type", transaction => { foreach (var iteration in Enumerable.Range(1, spansCount)) { transaction.CaptureSpan($"test span name #{iteration}", "test span type", span => { }); } }); } // Assert mockPayloadSender.WaitForTransactions(); mockPayloadSender.Transactions.Count.Should().Be(1); mockPayloadSender.Spans.Count.Should().Be(maxSpansCount); mockPayloadSender.FirstTransaction.SpanCount.Dropped.Should().Be(spansCount - maxSpansCount); }
public void AllSpansShouldBeSent_WhenTransactionMaxSpansIsEqualToMinusOne() { // Arrange var mockPayloadSender = new MockPayloadSender(); var mockConfig = new MockConfigSnapshot(transactionMaxSpans: "-1"); var spansCount = 1000; // Act using (var agent = new ApmAgent(new TestAgentComponents(config: mockConfig, payloadSender: mockPayloadSender))) { agent.Tracer.CaptureTransaction("test transaction name", "test transaction type", transaction => { foreach (var iteration in Enumerable.Range(1, spansCount)) { transaction.CaptureSpan($"test span name #{iteration}", "test span type", span => { }); } }); } // Assert mockPayloadSender.WaitForTransactions(); mockPayloadSender.Transactions.Count.Should().Be(1); mockPayloadSender.WaitForSpans(); mockPayloadSender.Spans.Count.Should().Be(spansCount); mockPayloadSender.FirstTransaction.SpanCount.Dropped.Should().Be(0); }
public void AgentDisabledBasicTransactionWithSpans() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: configReader)); var transaction = agent.Tracer.StartTransaction("TestTransaction", "Test"); transaction.Should().NotBeOfType <Transaction>(); transaction.Should().BeOfType <NoopTransaction>(); var span1 = transaction.StartSpan("test", "test"); span1.Should().NotBeOfType <Span>(); span1.Should().BeOfType <NoopSpan>(); agent.Tracer.CurrentSpan.Should().Be(span1); span1.End(); agent.Tracer.CurrentSpan.Should().BeNull(); var span2 = span1.StartSpan("test2", "test"); span2.Should().NotBeOfType <Span>(); span2.Should().BeOfType <NoopSpan>(); span2.End(); transaction.End(); payloadSender.Transactions.Should().BeNullOrEmpty(); payloadSender.Spans.Should().BeNullOrEmpty(); }
public void ServerCert_Should_Allow_Https_To_Apm_Server() { using var tempFile = new TempFile(); var certPath = Path.Combine(SolutionPaths.Root, "test", "Elastic.Apm.Tests.MockApmServer", "cert.pfx"); var serverCert = new X509Certificate2(certPath, "password"); File.WriteAllBytes(tempFile.Path, serverCert.Export(X509ContentType.Cert)); var configuration = new MockConfigSnapshot( serverUrl: $"https://localhost:{_port}", serverCert: tempFile.Path, disableMetrics: "*", cloudProvider: "none"); using var agent = new ApmAgent(new AgentComponents(_logger, configuration)); agent.Tracer.CaptureTransaction("TestTransaction", "TestType", t => { t.SetLabel("self_signed_cert", true); }); var signalled = _waitHandle.WaitOne(TimeSpan.FromMinutes(2)); signalled.Should().BeTrue("timed out waiting to receive transaction"); _server.ReceivedData.Transactions.Should().HaveCount(1); var transaction = _server.ReceivedData.Transactions.First(); transaction.Context.Labels.MergedDictionary.Should().ContainKey("self_signed_cert"); }
public void SpansSentOnlyForSampledTransaction(bool isSampled) { var mockPayloadSender = new MockPayloadSender(); var mockConfig = new MockConfigSnapshot(transactionSampleRate: isSampled ? "1" : "0"); 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 => { }) ); } mockPayloadSender.WaitForTransactions(); mockPayloadSender.Transactions.Count.Should().Be(1); mockPayloadSender.FirstTransaction.SpanCount.Dropped.Should().Be(0); if (isSampled) { mockPayloadSender.FirstTransaction.SampleRate.Should().Be(1); mockPayloadSender.FirstTransaction.SpanCount.Started.Should().Be(1); mockPayloadSender.Spans.Count.Should().Be(1); } else { mockPayloadSender.FirstTransaction.SampleRate.Should().Be(0); mockPayloadSender.FirstTransaction.SpanCount.Started.Should().Be(0); mockPayloadSender.Spans.Should().BeEmpty(); } }
public void ErrorShouldContainTransactionData(bool isSampled, bool captureOnSpan, bool captureAsError) { var payloadSender = new MockPayloadSender(); var expectedErrorContext = new Context(); expectedErrorContext.Labels["one"] = "1"; expectedErrorContext.Labels["twenty two"] = "22"; ITransaction capturedTransaction = null; IExecutionSegment errorCapturingExecutionSegment = null; var mockConfig = new MockConfigSnapshot(transactionSampleRate: isSampled ? "1" : "0"); using (var agent = new ApmAgent(new TestAgentComponents(config: mockConfig, payloadSender: payloadSender))) { agent.Tracer.CaptureTransaction(TestTransaction, CustomTransactionTypeForTests, transaction => { capturedTransaction = transaction; foreach (var keyValue in expectedErrorContext.Labels) { transaction.Context.Labels[keyValue.Key] = keyValue.Value; } ISpan span = null; if (captureOnSpan) { span = transaction.StartSpan(TestSpan1, ApiConstants.TypeExternal); errorCapturingExecutionSegment = span; } else { errorCapturingExecutionSegment = transaction; } if (captureAsError) { errorCapturingExecutionSegment.CaptureError("Test error message", "Test error culprit", new StackTrace(true).GetFrames()); } else { errorCapturingExecutionSegment.CaptureException(new TestException("test exception")); } // Immutable snapshot of the context should be captured instead of reference to a mutable object // transaction.Context.Labels["three hundred thirty three"] = "333"; span?.End(); }); } payloadSender.Errors.Count.Should().Be(1); payloadSender.FirstError.Transaction.IsSampled.Should().Be(isSampled); payloadSender.FirstError.Transaction.Type.Should().Be(CustomTransactionTypeForTests); payloadSender.FirstError.TransactionId.Should().Be(capturedTransaction.Id); payloadSender.FirstError.TraceId.Should().Be(capturedTransaction.TraceId); payloadSender.FirstError.ParentId.Should().Be(errorCapturingExecutionSegment.Id); payloadSender.FirstError.Context.Should().BeEquivalentTo(expectedErrorContext); }
public void Subscribers_Not_Subscribed_When_Agent_Disabled() { var payloadSender = new NoopPayloadSender(); var configReader = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: configReader)); var subscriber = new Mock <IDiagnosticsSubscriber>(); agent.Subscribe(subscriber.Object); subscriber.Verify(s => s.Subscribe(It.IsAny <IApmAgent>()), Times.Never); }
public void CaptureTransactionAndSpansWithRecordingOnFalse() { var mockPayloadSender = new MockPayloadSender(); var mockConfigSnapshot = new MockConfigSnapshot(recording: "false"); using var agent = new ApmAgent(new AgentComponents(payloadSender: mockPayloadSender, configurationReader: mockConfigSnapshot)); CreateTransactionsAndSpans(agent); mockPayloadSender.Transactions.Should().BeEmpty(); mockPayloadSender.Spans.Should().BeEmpty(); mockPayloadSender.Errors.Should().BeEmpty(); }
public async Task ChangeTransactionIgnoreUrlsAfterStart(bool useDiagnosticSourceOnly) { // Start with default config var startConfigSnapshot = new MockConfigSnapshot(new NoopLogger()); _capturedPayload = new MockPayloadSender(); var agentComponents = new TestAgentComponents( _logger, startConfigSnapshot, _capturedPayload, new CurrentExecutionSegmentsContainer()); _agent = new ApmAgent(agentComponents); _client = Helper.GetClient(_agent, _factory, useDiagnosticSourceOnly); _client.DefaultRequestHeaders.Add("foo", "bar"); await _client.GetAsync("/Home/SimplePage"); _capturedPayload.WaitForTransactions(); _capturedPayload.Transactions.Should().ContainSingle(); _capturedPayload.FirstTransaction.Context.Request.Url.Full.ToLower().Should().Contain("simplepage"); //change config to ignore urls with SimplePage var updateConfigSnapshot = new MockConfigSnapshot( new NoopLogger() , transactionIgnoreUrls: "*SimplePage*" ); _agent.ConfigStore.CurrentSnapshot = updateConfigSnapshot; await _client.GetAsync("/Home/SimplePage"); _capturedPayload.WaitForTransactions(TimeSpan.FromSeconds(5)); //assert that no more transaction is captured - so still 1 captured transaction _capturedPayload.Transactions.Should().ContainSingle(); //update config again updateConfigSnapshot = new MockConfigSnapshot( new NoopLogger() , transactionIgnoreUrls: "FooBar" ); _agent.ConfigStore.CurrentSnapshot = updateConfigSnapshot; await _client.GetAsync("/Home/SimplePage"); _capturedPayload.WaitForTransactions(); //assert that the number of captured transaction increased _capturedPayload.Transactions.Count.Should().Be(2); }
private void CreateSutEnvAndTest(Action <ApmAgent, PayloadSenderV2> doAction) { var configReader = new MockConfigSnapshot(_logger); var mockHttpMessageHandler = new MockHttpMessageHandler((r, c) => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); var service = Service.GetDefaultService(configReader, _logger); var payloadSender = new PayloadSenderV2(_logger, configReader, service, new Api.System(), mockHttpMessageHandler , /* dbgName: */ TestDisplayName); payloadSender.IsRunning.Should().BeTrue(); using (var agent = new ApmAgent(new TestAgentComponents(LoggerBase, payloadSender: payloadSender))) doAction(agent, payloadSender); payloadSender.IsRunning.Should().BeFalse(); }
public void CaptureTransactionAndSpansWithEnabledOnFalse() { var mockPayloadSender = new MockPayloadSender(); var mockConfigSnapshot = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new AgentComponents(payloadSender: mockPayloadSender, configurationReader: mockConfigSnapshot)); CreateTransactionsAndSpans(agent); mockPayloadSender.WaitForAny(TimeSpan.FromSeconds(5)); mockPayloadSender.Transactions.Should().BeEmpty(); mockPayloadSender.Spans.Should().BeEmpty(); mockPayloadSender.Errors.Should().BeEmpty(); mockPayloadSender.Metrics.Should().BeEmpty(); }
public async Task ChangeSanitizeFieldNamesAfterStart(bool useDiagnosticSourceOnly) { var startConfigSnapshot = new MockConfigSnapshot(new NoopLogger()); _capturedPayload = new MockPayloadSender(); var agentComponents = new TestAgentComponents( _logger, startConfigSnapshot, _capturedPayload, new CurrentExecutionSegmentsContainer()); _agent = new ApmAgent(agentComponents); _client = Helper.GetClient(_agent, _factory, useDiagnosticSourceOnly); _client.DefaultRequestHeaders.Add("foo", "bar"); 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(); _capturedPayload.FirstTransaction.Context.Request.Headers["foo"].Should().Be("bar"); _capturedPayload.Clear(); //change config to sanitize headers with "foo" var updateConfigSnapshot = new MockConfigSnapshot( new NoopLogger() , sanitizeFieldNames: "foo" ); _agent.ConfigStore.CurrentSnapshot = updateConfigSnapshot; 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(); _capturedPayload.FirstTransaction.Context.Request.Headers["foo"].Should().Be("[REDACTED]"); }
public void Should_Update_Logger_That_Is_ILogLevelSwitchable() { var logLevel = LogLevel.Trace; var testLogger = new ConsoleLogger(logLevel); var configSnapshotFromReader = new MockConfigSnapshot(testLogger, logLevel: "Trace"); var configStore = new ConfigStore(configSnapshotFromReader, testLogger); var service = Service.GetDefaultService(configSnapshotFromReader, testLogger); var waitHandle = new ManualResetEvent(false); var handler = new MockHttpMessageHandler(); var configUrl = BackendCommUtils.ApmServerEndpoints .BuildGetConfigAbsoluteUrl(configSnapshotFromReader.ServerUrl, service); handler.When(configUrl.AbsoluteUri) .Respond(_ => { waitHandle.Set(); return(new HttpResponseMessage(HttpStatusCode.OK) { Headers = { ETag = new EntityTagHeaderValue("\"etag\"") }, Content = new StringContent("{ \"log_level\": \"error\" }", Encoding.UTF8) }); }); var centralConfigFetcher = new CentralConfigFetcher(testLogger, configStore, service, handler); using var agent = new ApmAgent(new TestAgentComponents(testLogger, centralConfigFetcher: centralConfigFetcher, payloadSender: new NoopPayloadSender())); centralConfigFetcher.IsRunning.Should().BeTrue(); waitHandle.WaitOne(); // wait up to 60 seconds for the log level to change. Change can often be slower in CI var count = 0; while (count < 60 && testLogger.LogLevelSwitch.Level == logLevel) { count++; Thread.Sleep(TimeSpan.FromSeconds(1)); } testLogger.LogLevelSwitch.Level.Should().Be(LogLevel.Error); }
public void CentralConfigNoUserNamePwPrinted() { var userName = "******"; var pw = "def"; var inMemoryLogger = new InMemoryBlockingLogger(LogLevel.Error); var configReader = new MockConfigSnapshot(serverUrls: $"http://{userName}:{pw}@localhost:8123", maxBatchEventCount: "0", flushInterval: "0"); var configStore = new ConfigStore(configReader, inMemoryLogger); using var centralConfigFetcher = new CentralConfigFetcher(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")); }
public void PayloadSenderNoUserNamePwPrintedForServerUrl() { var userName = "******"; var pw = "def"; var inMemoryLogger = new InMemoryBlockingLogger(LogLevel.Warning); var configReader = new MockConfigSnapshot(serverUrls: $"http://{userName}:{pw}@localhost:8234", maxBatchEventCount: "0", flushInterval: "0"); using var payloadSender = new PayloadSenderV2(inMemoryLogger, configReader, Service.GetDefaultService(configReader, inMemoryLogger), new Api.System()); using var agent = new ApmAgent(new AgentComponents(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")); }
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 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 ShouldReturnIncludedNamespaces() { var payloadSender = new MockPayloadSender(); var config = new MockConfigSnapshot(applicationNamespaces: "MyApp1, Elastic.Apm.Tests., MyApp2"); using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: config))) { 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 GetCulpritWithLibraryFrames() { var payloadSender = new MockPayloadSender(); var config = new MockConfigSnapshot(excludedNamespaces: "LibraryNamespace"); using (var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: config))) { try { // Throw the exception to generate a stacktrace new ApplicationClass().Method1(); } catch (Exception e) { agent.Tracer.CaptureTransaction("TestTransaction", "TestTransactionType", t => { t.CaptureException(e); }); } } payloadSender.FirstError.Culprit.Should().Be("Test.Application.ApplicationClass"); }
public void AgentDisabledBasicTransaction() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: 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 DistributionShouldBeUniform(double rate) { const int total = 1_000_000; var startCheckingAfter = Convert.ToInt32(total * 0.1); // i.e., after 10% const double allowedDiffInRate = 0.01; var sampledCount = 0; var noopLogger = new NoopLogger(); var currentExecutionSegmentsContainer = new NoopCurrentExecutionSegmentsContainer(); var noopPayloadSender = new NoopPayloadSender(); var configurationReader = new MockConfigSnapshot(noopLogger); var sampler = new Sampler(rate); total.Repeat(i => { // reset current activity, otherwise all transactions share the same traceid which influences the sampling decision Activity.Current = null; var transaction = new Transaction(noopLogger, "test transaction name", "test transaction type", sampler, /* distributedTracingData: */ null, noopPayloadSender, configurationReader, currentExecutionSegmentsContainer); if (transaction.IsSampled) { ++sampledCount; } // ReSharper disable once InvertIf if (i + 1 >= startCheckingAfter) { var actualRate = (double)sampledCount / (i + 1); var diffInRate = actualRate - rate; Assert.True(Math.Abs(diffInRate) <= allowedDiffInRate, "Abs(diffInRate) should be <= allowedDiffInRate. " + $"diffInRate: {diffInRate}, allowedDiffInRate: {allowedDiffInRate}, " + $"i: {i}, " + $"actual rate: {actualRate}, expected rate: {rate}, " + $"actual sampled count: {sampledCount}, expected sampled count: {Convert.ToInt32((i + 1) * rate)}" ); } }); }
public void AgentDisabledTransactionWithLambdaAndSpans() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: configReader)); var block1Ran = false; var block2Ran = false; var block3Ran = false; agent.Tracer.CaptureTransaction("TestTransaction", "Test", transaction => { block1Ran = true; transaction.Should().NotBeOfType <Transaction>(); transaction.Should().BeOfType <NoopTransaction>(); transaction.CaptureSpan("test", "test", span1 => { block2Ran = true; span1.Should().NotBeOfType <Span>(); span1.Should().BeOfType <NoopSpan>(); span1.CaptureSpan("test2", "test", span2 => { block3Ran = true; span2.Should().NotBeOfType <Span>(); span2.Should().BeOfType <NoopSpan>(); }); }); }); block1Ran.Should().BeTrue(); block2Ran.Should().BeTrue(); block3Ran.Should().BeTrue(); payloadSender.SignalEndTransactions(); payloadSender.WaitForAny(); payloadSender.Transactions.Should().BeNullOrEmpty(); payloadSender.Spans.Should().BeNullOrEmpty(); }
public void AgentDisabledTransactionWithLambda() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: 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.Transactions.Should().BeNullOrEmpty(); }
public void AgentDisabledCaptureErrors() { var payloadSender = new MockPayloadSender(); var configReader = new MockConfigSnapshot(enabled: "false"); using var agent = new ApmAgent(new TestAgentComponents(payloadSender: payloadSender, config: configReader)); agent.Tracer.CaptureTransaction("foo", "bar", transaction => { transaction.CaptureError("foo", "bar", new StackTrace().GetFrames()); transaction.CaptureException(new Exception()); transaction.CaptureSpan("foo", "bar", span => { span.CaptureError("foo", "bar", new StackTrace().GetFrames()); span.CaptureException(new Exception()); }); }); payloadSender.Transactions.Should().BeNullOrEmpty(); payloadSender.Spans.Should().BeNullOrEmpty(); }
public void VerifyServerCert_Should_Allow_Https_To_Apm_Server() { var configuration = new MockConfigSnapshot( serverUrl: $"https://localhost:{_port}", verifyServerCert: "false", disableMetrics: "*", cloudProvider: "none"); using var agent = new ApmAgent(new AgentComponents(_logger, configuration)); agent.Tracer.CaptureTransaction("TestTransaction", "TestType", t => { t.SetLabel("verify_server_cert", false); }); var signalled = _waitHandle.WaitOne(TimeSpan.FromMinutes(2)); signalled.Should().BeTrue("timed out waiting to receive transaction"); _server.ReceivedData.Transactions.Should().HaveCount(1); var transaction = _server.ReceivedData.Transactions.First(); transaction.Context.Labels.MergedDictionary.Should().ContainKey("verify_server_cert"); }