Beispiel #1
0
        public void RateLimiter_Never_Applied_For_DefaultRule()
        {
            var sampler = new RuleBasedSampler(new DenyAll());

            RunSamplerTest(
                sampler,
                500,
                1,
                0);
        }
        public void Keep_Half_Rule()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.RegisterRule(new CustomSamplingRule(0.5f, "Allow_nothing", ".*", ".*"));
            RunSamplerTest(
                sampler,
                10_000, // Higher number for lower variance
                0.5f,
                0.05f);
        }
        public void Keep_Nothing_Rule()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.RegisterRule(new CustomSamplingRule(0, "Allow_nothing", ".*", ".*"));
            RunSamplerTest(
                sampler,
                500,
                0,
                0);
        }
        public void Keep_Everything_Rule()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.RegisterRule(new CustomSamplingRule(1, "Allow_all", ".*", ".*"));
            RunSamplerTest(
                sampler,
                500,
                1,
                0);
        }
        public void RateLimiter_Denies_All_Traces()
        {
            var sampler = new RuleBasedSampler(new DenyAll());

            sampler.RegisterRule(new CustomSamplingRule(1, "Allow_all", ".*", ".*"));
            RunSamplerTest(
                sampler,
                500,
                0,
                0);
        }
Beispiel #6
0
        public void RateLimiter_Never_Applied_For_DefaultRule()
        {
            var sampler = new RuleBasedSampler(new DenyAll());

            RunSamplerTest(
                sampler,
                iterations: 500,
                expectedAutoKeepRate: 1,
                expectedUserKeepRate: 0,
                acceptableVariancePercent: 0);
        }
        public void No_Registered_Rules_Uses_Legacy_Rates()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.SetDefaultSampleRates(MockAgentRates);

            RunSamplerTest(
                sampler,
                10_000, // Higher number for lower variance
                FallbackRate,
                0.05f);
        }
Beispiel #8
0
        public void Keep_Half_Rule()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.RegisterRule(new CustomSamplingRule(0.5f, "Allow_half", ".*", ".*"));
            RunSamplerTest(
                sampler,
                iterations: 50_000, // Higher number for lower variance
                expectedAutoKeepRate: 0,
                expectedUserKeepRate: 0.5f,
                acceptableVariancePercent: 0.05f);
        }
Beispiel #9
0
        public void Keep_Nothing_Rule()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.RegisterRule(new CustomSamplingRule(0, "Allow_nothing", ".*", ".*"));
            RunSamplerTest(
                sampler,
                iterations: 500,
                expectedAutoKeepRate: 0,
                expectedUserKeepRate: 0,
                acceptableVariancePercent: 0);
        }
Beispiel #10
0
        public void RateLimiter_Denies_All_Traces()
        {
            var sampler = new RuleBasedSampler(new DenyAll());

            sampler.RegisterRule(new CustomSamplingRule(1, "Allow_all", ".*", ".*"));
            RunSamplerTest(
                sampler,
                iterations: 500,
                expectedAutoKeepRate: 0,
                expectedUserKeepRate: 0,
                acceptableVariancePercent: 0);
        }
Beispiel #11
0
        public void No_Registered_Rules_Uses_Legacy_Rates()
        {
            var sampler = new RuleBasedSampler(new NoLimits());

            sampler.SetDefaultSampleRates(MockAgentRates);

            RunSamplerTest(
                sampler,
                iterations: 50_000, // Higher number for lower variance
                expectedAutoKeepRate: FallbackRate,
                expectedUserKeepRate: 0,
                acceptableVariancePercent: 0.05f);
        }
Beispiel #12
0
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IStatsd statsd)
        {
            // update the count of Tracer instances
            Interlocked.Increment(ref _liveTracerCount);

            Settings = settings ?? TracerSettings.FromDefaultSources();

            // if not configured, try to determine an appropriate service name
            DefaultServiceName = Settings.ServiceName ??
                                 GetApplicationName() ??
                                 UnknownServiceName;

            // only set DogStatsdClient if tracer metrics are enabled
            if (Settings.TracerMetricsEnabled)
            {
                Statsd = statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName);
            }

            // fall back to default implementations of each dependency if not provided
            IApi apiClient = new Api(Settings.AgentUri, delegatingHandler: null, Statsd);

            _agentWriter  = agentWriter ?? new AgentWriter(apiClient, Statsd);
            _scopeManager = scopeManager ?? new AsyncLocalScopeManager();
            Sampler       = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond));

            if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules))
            {
                // User has opted in, ensure rate limiter is used
                RuleBasedSampler.OptInTracingWithoutLimits();

                foreach (var rule in CustomSamplingRule.BuildFromConfigurationString(Settings.CustomSamplingRules))
                {
                    Sampler.RegisterRule(rule);
                }
            }

            // Register callbacks to make sure we flush the traces before exiting
            AppDomain.CurrentDomain.ProcessExit        += CurrentDomain_ProcessExit;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            Console.CancelKeyPress += Console_CancelKeyPress;

            // start the heartbeat loop
            _heartbeatTimer = new Timer(HeartbeatCallback, state: null, dueTime: TimeSpan.Zero, period: TimeSpan.FromMinutes(1));

            // If configured, add/remove the correlation identifiers into the
            // LibLog logging context when a scope is activated/closed
            if (Settings.LogsInjectionEnabled)
            {
                InitializeLibLogScopeEventSubscriber(_scopeManager);
            }
        }
Beispiel #13
0
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IStatsd statsd)
        {
            // update the count of Tracer instances
            Interlocked.Increment(ref _liveTracerCount);

            Settings = settings ?? TracerSettings.FromDefaultSources();

            // if not configured, try to determine an appropriate service name
            DefaultServiceName = Settings.ServiceName ??
                                 GetApplicationName() ??
                                 UnknownServiceName;

            // only set DogStatsdClient if tracer metrics are enabled
            if (Settings.TracerMetricsEnabled)
            {
                // Run this first in case the port override is ready
                TracingProcessManager.SubscribeToDogStatsDPortOverride(
                    port =>
                {
                    Log.Debug("Attempting to override dogstatsd port with {0}", port);
                    Statsd = CreateDogStatsdClient(Settings, DefaultServiceName, port);
                });

                Statsd = statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort);
            }

            // Run this first in case the port override is ready
            TracingProcessManager.SubscribeToTraceAgentPortOverride(
                port =>
            {
                Log.Debug("Attempting to override trace agent port with {0}", port);
                var builder = new UriBuilder(Settings.AgentUri)
                {
                    Port = port
                };
                var baseEndpoint         = builder.Uri;
                IApi overridingApiClient = new Api(baseEndpoint, delegatingHandler: null, Statsd);
                if (_agentWriter == null)
                {
                    _agentWriter = _agentWriter ?? new AgentWriter(overridingApiClient, Statsd);
                }
                else
                {
                    _agentWriter.OverrideApi(overridingApiClient);
                }
            });

            // fall back to default implementations of each dependency if not provided
            _agentWriter = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri, delegatingHandler: null, Statsd), Statsd);

            _scopeManager = scopeManager ?? new AsyncLocalScopeManager();
            Sampler       = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond));

            if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules))
            {
                // User has opted in, ensure rate limiter is used
                RuleBasedSampler.OptInTracingWithoutLimits();

                foreach (var rule in CustomSamplingRule.BuildFromConfigurationString(Settings.CustomSamplingRules))
                {
                    Sampler.RegisterRule(rule);
                }
            }

            if (Settings.GlobalSamplingRate != null)
            {
                var globalRate = (float)Settings.GlobalSamplingRate;

                if (globalRate < 0f || globalRate > 1f)
                {
                    Log.Warning("{0} configuration of {1} is out of range", ConfigurationKeys.GlobalSamplingRate, Settings.GlobalSamplingRate);
                }
                else
                {
                    Sampler.RegisterRule(new GlobalSamplingRule(globalRate));
                }
            }

            // Register callbacks to make sure we flush the traces before exiting
            AppDomain.CurrentDomain.ProcessExit        += CurrentDomain_ProcessExit;
            AppDomain.CurrentDomain.DomainUnload       += CurrentDomain_DomainUnload;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            Console.CancelKeyPress += Console_CancelKeyPress;

            // start the heartbeat loop
            _heartbeatTimer = new Timer(HeartbeatCallback, state: null, dueTime: TimeSpan.Zero, period: TimeSpan.FromMinutes(1));

            // If configured, add/remove the correlation identifiers into the
            // LibLog logging context when a scope is activated/closed
            if (Settings.LogsInjectionEnabled)
            {
                InitializeLibLogScopeEventSubscriber(_scopeManager, DefaultServiceName, Settings.ServiceVersion, Settings.Environment);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TracerSettings"/> class
        /// using the specified <see cref="IConfigurationSource"/> to initialize values.
        /// </summary>
        /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param>
        public TracerSettings(IConfigurationSource source)
        {
            Environment = source?.GetString(ConfigurationKeys.Environment);

            ServiceName = source?.GetString(ConfigurationKeys.ServiceName);

            TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ??
                           // default value
                           true;

            var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations)
                                           ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ??
                                           Enumerable.Empty <string>();

            DisabledIntegrationNames = new HashSet <string>(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase);

            var agentHost = source?.GetString(ConfigurationKeys.AgentHost) ??
                            // backwards compatibility for names used in the past
                            source?.GetString("DD_TRACE_AGENT_HOSTNAME") ??
                            source?.GetString("DATADOG_TRACE_AGENT_HOSTNAME") ??
                            // default value
                            DefaultAgentHost;

            var agentPort = source?.GetInt32(ConfigurationKeys.AgentPort) ??
                            // backwards compatibility for names used in the past
                            source?.GetInt32("DATADOG_TRACE_AGENT_PORT") ??
                            // default value
                            DefaultAgentPort;

            var agentUri = source?.GetString(ConfigurationKeys.AgentUri) ??
                           // default value
                           $"http://{agentHost}:{agentPort}";

            AgentUri = new Uri(agentUri);

            AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ??
                               // default value
                               false;

            LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ??
                                   // default value
                                   false;

            var maxTracesPerSecond = source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond);

            if (maxTracesPerSecond != null)
            {
                // Ensure our flag for the rate limiter is enabled
                RuleBasedSampler.OptInTracingWithoutLimits();
            }
            else
            {
                maxTracesPerSecond = 100; // default
            }

            MaxTracesSubmittedPerSecond = maxTracesPerSecond.Value;

            Integrations = new IntegrationSettingsCollection(source);

            GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ??
                         // default value (empty)
                         new ConcurrentDictionary <string, string>();

            DogStatsdPort = source?.GetInt32(ConfigurationKeys.DogStatsdPort) ??
                            // default value
                            8125;

            TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ??
                                   // default value
                                   false;

            CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules);

            GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate);

            DiagnosticSourceEnabled = source?.GetBool(ConfigurationKeys.DiagnosticSourceEnabled) ??
                                      // default value
                                      true;
        }
Beispiel #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TracerSettings"/> class
        /// using the specified <see cref="IConfigurationSource"/> to initialize values.
        /// </summary>
        /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param>
        public TracerSettings(IConfigurationSource source)
        {
            Environment = source?.GetString(ConfigurationKeys.Environment);

            ServiceName = source?.GetString(ConfigurationKeys.ServiceName);

            ServiceNamePerSpanEnabled = source?.GetBool(ConfigurationKeys.ServiceNamePerSpan) ??
                                        false;

            SignalFxAccessToken = source?.GetString(ConfigurationKeys.SignalFxAccessToken);

            TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ??
                           true;

            SynchronousSend = source?.GetBool(ConfigurationKeys.SynchronousSend) ??
                              false;

            var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations)
                                           ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ??
                                           Enumerable.Empty <string>();

            DisabledIntegrationNames = new HashSet <string>(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase);

            var endpointUrl = source?.GetString(ConfigurationKeys.EndpointUrl) ?? DefaultEndpointUrl;

            EndpointUrl = new Uri(endpointUrl);

            var agentHost = source?.GetString(ConfigurationKeys.AgentHost) ??
                            // backwards compatibility for names used in the past
                            source?.GetString("SIGNALFX_TRACE_AGENT_HOSTNAME") ??
                            source?.GetString("DATADOG_TRACE_AGENT_HOSTNAME") ??
                            // default value
                            EndpointUrl.Host;

            var agentPort = source?.GetInt32(ConfigurationKeys.AgentPort) ??
                            // backwards compatibility for names used in the past
                            source?.GetInt32("DATADOG_TRACE_AGENT_PORT") ??
                            // default value
                            EndpointUrl.Port;

            var agentUri = source?.GetString(ConfigurationKeys.AgentUri) ??
                           // default value
                           $"{EndpointUrl.Scheme}://{agentHost}:{agentPort}";

            AgentUri = new Uri(agentUri);

            var endpointPath = EndpointUrl.PathAndQuery != "/"
                ? EndpointUrl.PathAndQuery
                : FallbackUriPath;

            var agentPath = source?.GetString(ConfigurationKeys.AgentPath) ?? endpointPath;

            // We still want tests and users to be able to configure Uri elements, so reform Endpoint Url
            EndpointUrl = new Uri(AgentUri, agentPath);

            ApiType = source?.GetString(ConfigurationKeys.ApiType) ?? DefaultApiType;

            AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ??
                               // default value
                               false;

            LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ??
                                   // default value
                                   false;

            var maxTracesPerSecond = source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond);

            if (maxTracesPerSecond != null)
            {
                // Ensure our flag for the rate limiter is enabled
                RuleBasedSampler.OptInTracingWithoutLimits();
            }
            else
            {
                maxTracesPerSecond = 100; // default
            }

            MaxTracesSubmittedPerSecond = maxTracesPerSecond.Value;

            Integrations = new IntegrationSettingsCollection(source);

            GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags);

            DogStatsdPort = source?.GetInt32(ConfigurationKeys.DogStatsdPort) ??
                            // default value
                            8125;

            TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ??
                                   // default value
                                   false;

            CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules);

            GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate);

            DiagnosticSourceEnabled = source?.GetBool(ConfigurationKeys.DiagnosticSourceEnabled) ??
                                      // default value
                                      true;

            TagMongoCommands = source?.GetBool(ConfigurationKeys.TagMongoCommands) ?? true;

            TagElasticsearchQueries = source?.GetBool(ConfigurationKeys.TagElasticsearchQueries) ?? true;

            TagRedisCommands = source?.GetBool(ConfigurationKeys.TagRedisCommands) ?? true;

            SanitizeSqlStatements = source?.GetBool(ConfigurationKeys.SanitizeSqlStatements) ?? true;

            AdditionalDiagnosticListeners = source?.GetString(ConfigurationKeys.AdditionalDiagnosticListeners)
                                            ?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                            .Select(s => s.Trim()).ToArray() ??
                                            new string[0];

            AppendUrlPathToName = source?.GetBool(ConfigurationKeys.AppendUrlPathToName) ?? false;

            UseWebServerResourceAsOperationName = source?.GetBool(ConfigurationKeys.UseWebServerResourceAsOperationName) ?? true;

            AddClientIpToServerSpans = source?.GetBool(ConfigurationKeys.AddClientIpToServerSpans) ?? false;

            RecordedValueMaxLength = source?.GetInt32(ConfigurationKeys.RecordedValueMaxLength) ?? DefaultRecordedValueMaxLength;
            if (RecordedValueMaxLength < 0)
            {
                RecordedValueMaxLength = DefaultRecordedValueMaxLength;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TracerSettings"/> class
        /// using the specified <see cref="IConfigurationSource"/> to initialize values.
        /// </summary>
        /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param>
        public TracerSettings(IConfigurationSource source)
        {
            Environment = source?.GetString(ConfigurationKeys.Environment);

            ServiceName = source?.GetString(ConfigurationKeys.ServiceName) ??
                          // backwards compatibility for names used in the past
                          source?.GetString("DD_SERVICE_NAME");

            ServiceVersion = source?.GetString(ConfigurationKeys.ServiceVersion);

            TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ??
                           // default value
                           true;

            var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations)
                                           ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ??
                                           Enumerable.Empty <string>();

            DisabledIntegrationNames = new HashSet <string>(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase);

            var agentHost = source?.GetString(ConfigurationKeys.AgentHost) ??
                            // backwards compatibility for names used in the past
                            source?.GetString("DD_TRACE_AGENT_HOSTNAME") ??
                            source?.GetString("DATADOG_TRACE_AGENT_HOSTNAME") ??
                            // default value
                            DefaultAgentHost;

            var agentPort = source?.GetInt32(ConfigurationKeys.AgentPort) ??
                            // backwards compatibility for names used in the past
                            source?.GetInt32("DATADOG_TRACE_AGENT_PORT") ??
                            // default value
                            DefaultAgentPort;

            var agentUri = source?.GetString(ConfigurationKeys.AgentUri) ??
                           // default value
                           $"http://{agentHost}:{agentPort}";

            AgentUri = new Uri(agentUri);

            if (string.Equals(AgentUri.Host, "localhost", StringComparison.OrdinalIgnoreCase))
            {
                // Replace localhost with 127.0.0.1 to avoid DNS resolution.
                // When ipv6 is enabled, localhost is first resolved to ::1, which fails
                // because the trace agent is only bound to ipv4.
                // This causes delays when sending traces.
                var builder = new UriBuilder(agentUri)
                {
                    Host = "127.0.0.1"
                };
                AgentUri = builder.Uri;
            }

            AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ??
                               // default value
                               false;

            LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ??
                                   // default value
                                   false;

            var maxTracesPerSecond = source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond);

            if (maxTracesPerSecond != null)
            {
                // Ensure our flag for the rate limiter is enabled
                RuleBasedSampler.OptInTracingWithoutLimits();
            }
            else
            {
                maxTracesPerSecond = 100; // default
            }

            MaxTracesSubmittedPerSecond = maxTracesPerSecond.Value;

            Integrations = new IntegrationSettingsCollection(source);

            GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ??
                         // backwards compatibility for names used in the past
                         source?.GetDictionary("DD_TRACE_GLOBAL_TAGS") ??
                         // default value (empty)
                         new ConcurrentDictionary <string, string>();

            // Filter out tags with empty keys or empty values, and trim whitespace
            GlobalTags = GlobalTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value))
                         .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim());

            HeaderTags = source?.GetDictionary(ConfigurationKeys.HeaderTags) ??
                         // default value (empty)
                         new ConcurrentDictionary <string, string>();

            // Filter out tags with empty keys or empty values, and trim whitespace
            HeaderTags = HeaderTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value))
                         .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim());

            DogStatsdPort = source?.GetInt32(ConfigurationKeys.DogStatsdPort) ??
                            // default value
                            8125;

            TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ??
                                   // default value
                                   false;

            CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules);

            GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate);

            StartupDiagnosticLogEnabled = source?.GetBool(ConfigurationKeys.StartupDiagnosticLogEnabled) ??
                                          // default value
                                          true;
        }