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