Beispiel #1
0
        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);
            }
        }
Beispiel #4
0
        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));
 }
Beispiel #6
0
        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),
 })
 {
 }
Beispiel #8
0
        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);
                }
            }
        }
Beispiel #9
0
        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));
                }
            }
        }