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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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);
        }
Exemple #13
0
        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);
        }
Exemple #17
0
        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);
                        }
                    }
                }
            }
        }
Exemple #23
0
        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();
        }