private static ITraceWriter CreateTraceWriter(TracerSettings settings, IDogStatsd statsd)
        {
            IMetrics metrics = statsd != null
                ? new DogStatsdMetrics(statsd)
                : new NullMetrics();

            switch (settings.Exporter)
            {
            case ExporterType.Zipkin:
                return(new ExporterWriter(new ZipkinExporter(settings.AgentUri), metrics));

            case ExporterType.Jaeger:
                return(new ExporterWriter(new JaegerExporter(JaegerOptions.FromTracerSettings(settings)), metrics));

            default:
                return(new AgentWriter(new Api(settings.AgentUri, TransportStrategy.Get(settings), statsd), metrics, maxBufferSize: settings.TraceBufferSize));
            }
        }
예제 #2
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));
                }
            }
        }