public static void CreateManualTraces() { // Create a configuration source so we can enable runtime metrics without relying on environment variables, // which would require an additional permission to be added var configurationSource = new NameValueConfigurationSource(new NameValueCollection() { // TODO: Enable AppSec somehow. There is currently no way to enable it inside a sandboxed environment where environment variables and files cannot be accessed { "DD_RUNTIME_METRICS_ENABLED", "1" }, }); var tracerSettings = new TracerSettings(configurationSource); Tracer.Configure(tracerSettings); using (Tracer.Instance.StartActive("custom-span")) { // Simulate some work Thread.Sleep(500); using (Tracer.Instance.StartActive("inner-span")) { // Simulate some work Thread.Sleep(500); } } // Sleep so we add more time for Tracer threads to operate in the background Thread.Sleep(2000); }
public void GetTypedValues(NameValueCollection collection, string key, TestEnum[] expected) { var cs = new NameValueConfigurationSource(collection); var result = ConfigurationSourceExtensions.GetTypedValues <TestEnum>(cs, key); Assert.Equal(expected, result); }
public void IntegrationEnabled(string settingName, string settingValue, bool expected) { var source = new NameValueConfigurationSource(new NameValueCollection { { settingName, settingValue } }); var settings = new IntegrationSettings("FOO", source); Assert.Equal(expected, settings.Enabled); }
public void IntegrationAnalyticsSampleRate(string settingName, string settingValue, double expected) { var source = new NameValueConfigurationSource(new NameValueCollection { { settingName, settingValue } }); var settings = new IntegrationSettings("FOO", source); Assert.Equal(expected, settings.AnalyticsSampleRate); }
public void WhenNoUrlOrApiKeyIsProvided_UsesAgentBasedUrl() { var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, "1" } }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryUri.Should().Be(_defaultAgentUrl); }
public void WhenOnlyApiKeyIsProvided_UsesIntakeUrl() { var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, "1" }, { ConfigurationKeys.ApiKey, "some_key" }, }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryUri.Should().Be(_defaultIntakeUrl); }
public void SetsTelemetryEnabledBasedOnApiKeyAndEnabledSettings(string apiKey, string enabledSetting, bool enabled) { var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, enabledSetting }, { ConfigurationKeys.ApiKey, apiKey }, }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryEnabled.Should().Be(enabled); }
public void GetString_NoMatches() { var collection = new NameValueCollection { { "example1", "value1" }, { "example2", "value2" } }; var cs = new NameValueConfigurationSource(collection); var result = ConfigurationSourceExtensions.GetStrings(cs, "test"); Assert.Empty(result); }
public void GetString_MultipleValues() { var collection = new NameValueCollection { { "example1", "value1,value2,," } }; var cs = new NameValueConfigurationSource(collection); var result = ConfigurationSourceExtensions.GetStrings(cs, "example1"); Assert.Contains(result, (v) => v == "value1"); Assert.Contains(result, (v) => v == "value2"); Assert.True(result.Count() == 2); }
public void WhenInvalidUrlApiIsProvided_AndNoApiKey_UsesDefaultAgentUrl() { var url = "https://sometest::"; var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, "1" }, { ConfigurationKeys.Telemetry.Uri, url }, }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryUri.Should().Be(_defaultAgentUrl); }
public void WhenValidUrlIsProvided_AppendsSlashToPath(string url, string expected) { var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, "1" }, { ConfigurationKeys.Telemetry.Uri, url }, { ConfigurationKeys.ApiKey, "some_key" }, }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryUri.Should().Be(expected); }
public void WhenInvalidUrlIsProvided_AndHasApiKey_UsesDefaultIntakeUrl(string url) { var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, "1" }, { ConfigurationKeys.Telemetry.Uri, url }, { ConfigurationKeys.ApiKey, "some_key" }, }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryUri.Should().Be(_defaultIntakeUrl); }
public void WhenApiKeyAndDdSiteIsProvided_UsesDdSiteDomain() { var domain = "my-domain.net"; var source = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.Telemetry.Enabled, "1" }, { ConfigurationKeys.ApiKey, "some_key" }, { ConfigurationKeys.Site, domain }, }); var settings = new TelemetrySettings(source, _tracerSettings); settings.TelemetryUri.Should().Be($"https://instrumentation-telemetry-intake.{domain}/"); }
public void ConfiguredTracerSettings_DefaultTagsSetFromEnvironmentVariable(string environmentVariableKey, string tagKey, string value) { var collection = new NameValueCollection { { environmentVariableKey, value } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var settings = new TracerSettings(source); var tracer = new Tracer(settings, _writerMock.Object, _samplerMock.Object, scopeManager: null, statsd: null); var span = tracer.StartSpan("Operation"); Assert.Equal(span.GetTag(tagKey), value); }
public void GlobalNameValueConfigurationSource( string key, string value, Func <GlobalSettings, object> settingGetter, object expectedValue) { var collection = new NameValueCollection { { key, value } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var settings = new GlobalSettings(source); object actualValue = settingGetter(settings); Assert.Equal(expectedValue, actualValue); }
private ExporterSettings Setup(Func <string, bool> fileExistsMock, params string[] config) { var configNameValues = new NameValueCollection(); foreach (var item in config) { var parts = item.Split(':'); configNameValues.Add(parts[0], parts[1]); } var configSource = new NameValueConfigurationSource(configNameValues); var exporterSettings = new ExporterSettings(configSource, fileExistsMock); return(exporterSettings); }
public void CreateDbCommandScope_UsesReplacementServiceNameWhenProvided(IDbCommand command, string integrationName, string dbType) { // HACK: avoid analyzer warning about not using arguments _ = integrationName; // Set up tracer var collection = new NameValueCollection { { ConfigurationKeys.ServiceNameMappings, $"{dbType}:my-custom-type" } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var tracerSettings = new TracerSettings(source); var tracer = TracerHelper.Create(tracerSettings); // Create scope using var scope = CreateDbCommandScope(tracer, command); Assert.Equal("my-custom-type", scope.Span.ServiceName); }
public void CreateDbCommandScope_IgnoresReplacementServiceNameWhenNotProvided(IDbCommand command) { // Set up tracer var collection = new NameValueCollection { { ConfigurationKeys.ServiceNameMappings, $"something:my-custom-type" } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var tracerSettings = new TracerSettings(source); var tracer = new Tracer(tracerSettings); // Create scope using (var outerScope = ScopeFactory.CreateDbCommandScope(tracer, command)) { Assert.NotEqual("my-custom-type", outerScope.Span.ServiceName); } }
public void DDVarTakesPrecedenceOverDDTags(string envKey, string tagKey) { string envValue = $"ddenv-custom-{tagKey}"; string tagsLine = $"{tagKey}:ddtags-custom-{tagKey}"; var collection = new NameValueCollection { { envKey, envValue }, { ConfigurationKeys.GlobalTags, tagsLine } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var settings = new TracerSettings(source); Assert.True(settings.GlobalTags.Any()); var tracer = new Tracer(settings, _writerMock.Object, _samplerMock.Object, scopeManager: null, statsd: null); var span = tracer.StartSpan("Operation"); Assert.Equal(span.GetTag(tagKey), envValue); }
public void CreateDbCommandScope_UsesReplacementServiceNameWhenProvided(IDbCommand command) { // Set up tracer var t = command.GetType(); var dbType = ScopeFactory.GetDbType(t.Namespace, t.Name); var collection = new NameValueCollection { { ConfigurationKeys.ServiceNameMappings, $"{dbType}:my-custom-type" } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var tracerSettings = new TracerSettings(source); var tracer = new Tracer(tracerSettings); // Create scope using (var outerScope = ScopeFactory.CreateDbCommandScope(tracer, command)) { Assert.Equal("my-custom-type", outerScope.Span.ServiceName); } }
public void CreateDbCommandScope_ReturnsNullForExcludedAdoNetTypes(IDbCommand command) { // Set up tracer var collection = new NameValueCollection { { ConfigurationKeys.AdoNetExcludedTypes, command.GetType().FullName } }; IConfigurationSource source = new NameValueConfigurationSource(collection); var tracerSettings = new TracerSettings(source); var tracer = new Tracer(tracerSettings); // Create scope using (var outerScope = ScopeFactory.CreateDbCommandScope(tracer, new CustomDbCommand())) { using (var innerScope = ScopeFactory.CreateDbCommandScope(tracer, command)) { Assert.Null(innerScope); } Assert.NotNull(outerScope); } }
private static async Task AssertDiagnosticObserverSubmitsSpans <T>( string path, HttpStatusCode statusCode, bool isError, string resourceName, SerializableDictionary expectedParentSpanTags, bool featureFlag = false, int spanCount = 1, string childSpan1ResourceName = null, SerializableDictionary firstChildSpanTags = null, string childSpan2ResourceName = null, SerializableDictionary secondChildSpanTags = null) where T : class { var writer = new AgentWriterStub(); var configSource = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.FeatureFlags.RouteTemplateResourceNamesEnabled, featureFlag.ToString() }, }); var tracer = GetTracer(writer, configSource); var builder = new WebHostBuilder() .UseStartup <T>(); var testServer = new TestServer(builder); var client = testServer.CreateClient(); var observers = new List <DiagnosticObserver> { new AspNetCoreDiagnosticObserver(tracer) }; using (var diagnosticManager = new DiagnosticManager(observers)) { diagnosticManager.Start(); try { var response = await client.GetAsync(path); Assert.Equal(statusCode, response.StatusCode); } catch (Exception ex) { Assert.True(isError, $"Unexpected error calling endpoint: {ex}"); } // The diagnostic observer runs on a separate thread // This gives time for the Stop event to run and to be flushed to the writer const int timeoutInMilliseconds = 10000; var deadline = DateTime.Now.AddMilliseconds(timeoutInMilliseconds); while (DateTime.Now < deadline) { if (writer.Traces.Count > 0) { break; } Thread.Sleep(200); } } var trace = Assert.Single(writer.Traces); trace.Should().HaveCount(spanCount); var parentSpan = trace.Should() .ContainSingle(x => x.OperationName == "aspnet_core.request") .Subject; AssertTagHasValue(parentSpan, Tags.InstrumentationName, "aspnet_core"); parentSpan.Type.Should().Be(SpanTypes.Web); parentSpan.ResourceName.Should().Be(resourceName); AssertTagHasValue(parentSpan, Tags.SpanKind, SpanKinds.Server); AssertTagHasValue(parentSpan, Tags.Language, TracerConstants.Language); AssertTagHasValue(parentSpan, Tags.HttpStatusCode, ((int)statusCode).ToString()); parentSpan.Error.Should().Be(isError); if (expectedParentSpanTags is not null) { foreach (var expectedTag in expectedParentSpanTags.Values) { AssertTagHasValue(parentSpan, expectedTag.Key, expectedTag.Value); } } if (spanCount > 1) { trace.Should().Contain(x => x.OperationName == "aspnet_core_mvc.request"); var childSpan = trace.First(x => x.OperationName == "aspnet_core_mvc.request"); AssertTagHasValue(childSpan, Tags.InstrumentationName, "aspnet_core"); childSpan.Type.Should().Be(SpanTypes.Web); childSpan.ResourceName.Should().Be(childSpan1ResourceName ?? resourceName); AssertTagHasValue(childSpan, Tags.SpanKind, SpanKinds.Server); AssertTagHasValue(childSpan, Tags.Language, TracerConstants.Language); if (firstChildSpanTags is not null) { foreach (var expectedTag in firstChildSpanTags.Values) { AssertTagHasValue(childSpan, expectedTag.Key, expectedTag.Value); } } if (spanCount > 2) { var childSpan2 = trace.Last(x => x.OperationName == "aspnet_core_mvc.request"); childSpan2.Should().NotBe(childSpan); AssertTagHasValue(childSpan2, Tags.InstrumentationName, "aspnet_core"); childSpan2.Type.Should().Be(SpanTypes.Web); childSpan2.ResourceName.Should().Be(childSpan2ResourceName); AssertTagHasValue(childSpan2, Tags.SpanKind, SpanKinds.Server); AssertTagHasValue(childSpan2, Tags.Language, TracerConstants.Language); if (secondChildSpanTags is not null) { foreach (var expectedTag in secondChildSpanTags.Values) { AssertTagHasValue(childSpan2, expectedTag.Key, expectedTag.Value); } } } } }
public void PopulatesFromBuilderCorrectly() { var source = new NameValueConfigurationSource(new NameValueCollection { { "DD_TRACE_FOO_ENABLED", "true" }, { "DD_TRACE_FOO_ANALYTICS_ENABLED", "true" }, { "DD_TRACE_FOO_ANALYTICS_SAMPLE_RATE", "0.2" }, { "DD_TRACE_BAR_ENABLED", "false" }, { "DD_TRACE_BAR_ANALYTICS_ENABLED", "false" }, { "DD_BAZ_ENABLED", "false" }, { "DD_BAZ_ANALYTICS_ENABLED", "false" }, { "DD_BAZ_ANALYTICS_SAMPLE_RATE", "0.6" }, { "DD_TRACE_Kafka_ENABLED", "true" }, { "DD_TRACE_Kafka_ANALYTICS_ENABLED", "true" }, { "DD_TRACE_Kafka_ANALYTICS_SAMPLE_RATE", "0.2" }, { "DD_TRACE_GraphQL_ENABLED", "false" }, { "DD_TRACE_GraphQL_ANALYTICS_ENABLED", "false" }, { "DD_Wcf_ENABLED", "false" }, { "DD_Wcf_ANALYTICS_ENABLED", "false" }, { "DD_Wcf_ANALYTICS_SAMPLE_RATE", "0.2" }, { "DD_Msmq_ENABLED", "true" }, { "DD_TRACE_stackexchangeredis_ENABLED", "false" }, }); var disabledIntegrations = new HashSet <string> { "foobar", "MongoDb", "Msmq" }; var builderCollection = new IntegrationSettingsCollection(source); var final = new ImmutableIntegrationSettingsCollection(builderCollection, disabledIntegrations); var kafka = final[IntegrationId.Kafka]; kafka.Enabled.Should().BeTrue(); kafka.AnalyticsEnabled.Should().BeTrue(); kafka.AnalyticsSampleRate.Should().Be(0.2); var graphql = final[IntegrationId.GraphQL]; graphql.Enabled.Should().BeFalse(); graphql.AnalyticsEnabled.Should().BeFalse(); graphql.AnalyticsSampleRate.Should().Be(1.0); var wcf = final[IntegrationId.Wcf]; wcf.Enabled.Should().BeFalse(); wcf.AnalyticsEnabled.Should().BeFalse(); wcf.AnalyticsSampleRate.Should().Be(0.2); var mongodb = final[IntegrationId.MongoDb]; mongodb.Enabled.Should().BeFalse(); var msmq = final[IntegrationId.Msmq]; msmq.Enabled.Should().BeFalse(); var consmos = final[IntegrationId.CosmosDb]; consmos.Enabled.Should().BeNull(); var redis = final[IntegrationId.StackExchangeRedis]; redis.Enabled.Should().BeFalse(); }