public void CleanupResources() { var statsd = new Mock <IDogStatsd>(); var runtimeListener = new Mock <IRuntimeMetricsListener>(); var writer = new RuntimeMetricsWriter(statsd.Object, TimeSpan.FromMilliseconds(Timeout.Infinite), (_, d) => runtimeListener.Object); writer.Dispose(); runtimeListener.Verify(l => l.Dispose(), Times.Once); // Make sure that the writer unsubscribed from the global exception handler try { throw new CustomException1(); } catch { // ignored } writer.ExceptionCounts.TryGetValue(nameof(CustomException1), out var count); Assert.Equal(0, count); }
public void ShouldSwallowFactoryExceptions() { Func<IDogStatsd, TimeSpan, IRuntimeMetricsListener> factory = (_, d) => throw new InvalidOperationException("This exception should be caught"); var writer = new RuntimeMetricsWriter(Mock.Of<IDogStatsd>(), TimeSpan.FromMilliseconds(10), factory); writer.Dispose(); }
public void ShouldCaptureFirstChanceExceptions() { var statsd = new Mock <IDogStatsd>(); var listener = new Mock <IRuntimeMetricsListener>(); using (var writer = new RuntimeMetricsWriter(statsd.Object, TimeSpan.FromMilliseconds(Timeout.Infinite), (statsd, timeSpan) => listener.Object)) { for (int i = 0; i < 10; i++) { try { throw new CustomException1(); } catch { // ignored } if (i % 2 == 0) { try { throw new CustomException2(); } catch { // ignored } } } statsd.Verify( s => s.Increment(MetricsNames.ExceptionsCount, It.IsAny <int>(), It.IsAny <double>(), It.IsAny <string[]>()), Times.Never); writer.PushEvents(); statsd.Verify( s => s.Increment(MetricsNames.ExceptionsCount, 10, It.IsAny <double>(), new[] { "exception_type:CustomException1" }), Times.Once); statsd.Verify( s => s.Increment(MetricsNames.ExceptionsCount, 5, It.IsAny <double>(), new[] { "exception_type:CustomException2" }), Times.Once); statsd.Invocations.Clear(); // Make sure stats are reset when pushed writer.PushEvents(); statsd.Verify( s => s.Increment(MetricsNames.ExceptionsCount, It.IsAny <int>(), It.IsAny <double>(), new[] { "exception_type:CustomException1" }), Times.Never); statsd.Verify( s => s.Increment(MetricsNames.ExceptionsCount, It.IsAny <int>(), It.IsAny <double>(), new[] { "exception_type:CustomException2" }), Times.Never); } }
public void ShouldSwallowFactoryExceptions() { Func <IDogStatsd, IRuntimeMetricsListener> factory = _ => throw new InvalidOperationException("This exception should be caught"); var writer = new RuntimeMetricsWriter(Mock.Of <IDogStatsd>(), 10, factory); writer.Dispose(); }
protected override TracerManager CreateTracerManagerFrom( ImmutableTracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IDogStatsd statsd, RuntimeMetricsWriter runtimeMetrics, DirectLogSubmissionManager logSubmissionManager, ITelemetryController telemetry, string defaultServiceName) { return(new CITracerManager(settings, agentWriter, sampler, scopeManager, statsd, runtimeMetrics, logSubmissionManager, telemetry, defaultServiceName)); }
public void CleanupResources() { var statsd = new Mock <IDogStatsd>(); var runtimeListener = new Mock <IRuntimeMetricsListener>(); var writer = new RuntimeMetricsWriter(statsd.Object, Timeout.Infinite, _ => runtimeListener.Object); writer.Dispose(); runtimeListener.Verify(l => l.Dispose(), Times.Once); // Make sure that the writer unsubscribed from the global exception handler try { throw new CustomException1(); } catch { // ignored } Assert.True(writer.ExceptionCounts.IsEmpty); }
public CITracerManager(ImmutableTracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IDogStatsd statsd, RuntimeMetricsWriter runtimeMetricsWriter, ITraceIdConvention traceIdConvention, DirectLogSubmissionManager logSubmissionManager, ITelemetryController telemetry, string defaultServiceName) : base(settings, agentWriter, sampler, scopeManager, statsd, runtimeMetricsWriter, traceIdConvention, logSubmissionManager, telemetry, defaultServiceName, new Trace.Processors.ITraceProcessor[] { new Trace.Processors.NormalizerTraceProcessor(), new Trace.Processors.TruncatorTraceProcessor(), new Processors.OriginTagTraceProcessor(settings.ExporterSettings.PartialFlushEnabled, agentWriter is CIAgentlessWriter), }) { }
internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IDogStatsd 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; if (_agentWriter == null) { IApi overridingApiClient = new Api(baseEndpoint, apiRequestFactory: null, Statsd); _agentWriter = _agentWriter ?? new AgentWriter(overridingApiClient, Statsd, queueSize: Settings.TraceQueueSize); } else { _agentWriter.SetApiBaseEndpoint(baseEndpoint); } }); // fall back to default implementations of each dependency if not provided _agentWriter = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri, apiRequestFactory: null, Statsd), Statsd, queueSize: Settings.TraceQueueSize); _scopeManager = scopeManager ?? new AsyncLocalScopeManager(); Sampler = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond)); if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules)) { 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; try { // Registering for the AppDomain.UnhandledException event cannot be called by a security transparent method // This will only happen if the Tracer is not run full-trust AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; } catch (Exception ex) { Log.Warning(ex, "Unable to register a callback to the AppDomain.UnhandledException event."); } try { // Registering for the cancel key press event requires the System.Security.Permissions.UIPermission Console.CancelKeyPress += Console_CancelKeyPress; } catch (Exception ex) { Log.Warning(ex, "Unable to register a callback to the Console.CancelKeyPress event."); } // 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); } if (Interlocked.Exchange(ref _firstInitialization, 0) == 1) { if (Settings.StartupDiagnosticLogEnabled) { _ = WriteDiagnosticLog(); } if (Settings.RuntimeMetricsEnabled) { _runtimeMetricsWriter = new RuntimeMetricsWriter(Statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort), 10000); } } }
internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IDogStatsd statsd) { // update the count of Tracer instances Interlocked.Increment(ref _liveTracerCount); Settings = settings ?? TracerSettings.FromDefaultSources(); Settings.Freeze(); // 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, Settings.DogStatsdPort); } // fall back to default implementations of each dependency if not provided if (agentWriter != null) { _agentWriter = agentWriter; } else { IApi api = null; switch (Settings.Exporter) { case ExporterType.Zipkin: api = new ZipkinApi(Settings); break; case ExporterType.DatadogAgent: default: api = new Api(Settings.AgentUri, TransportStrategy.Get(Settings), Statsd); break; } _agentWriter = new AgentWriter(api, Statsd, queueSize: Settings.TraceQueueSize); } _scopeManager = scopeManager ?? new AsyncLocalScopeManager(); Sampler = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond)); if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules)) { 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("{ConfigurationKey} configuration of {ConfigurationValue} 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; try { // Registering for the AppDomain.UnhandledException event cannot be called by a security transparent method // This will only happen if the Tracer is not run full-trust AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; } catch (Exception ex) { Log.Warning(ex, "Unable to register a callback to the AppDomain.UnhandledException event."); } try { // Registering for the cancel key press event requires the System.Security.Permissions.UIPermission Console.CancelKeyPress += Console_CancelKeyPress; } catch (Exception ex) { Log.Warning(ex, "Unable to register a callback to the Console.CancelKeyPress event."); } // 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); } if (Interlocked.Exchange(ref _firstInitialization, 0) == 1) { if (Settings.StartupDiagnosticLogEnabled) { _ = Task.Run(WriteDiagnosticLog); } if (Settings.RuntimeMetricsEnabled) { _runtimeMetricsWriter = new RuntimeMetricsWriter(Statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort), TimeSpan.FromSeconds(10)); } } }