Exemple #1
0
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager)
        {
            // fall back to default implementations of each dependency if not provided
            Settings      = settings ?? TracerSettings.FromDefaultSources();
            _agentWriter  = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri));
            _scopeManager = scopeManager ?? new AsyncLocalScopeManager();
            Sampler       = sampler ?? new RateByServiceSampler();

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

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

            // If configured, add/remove the correlation identifiers into the
            // LibLog logging context when a scope is activated/closed
            if (Settings.LogsInjectionEnabled)
            {
                InitializeLibLogScopeEventSubscriber(_scopeManager);
            }
        }
Exemple #2
0
        static AgentWriterBenchmark()
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.StartupDiagnosticLogEnabled = false;
            settings.TraceEnabled = false;

            var api = new Api(settings.Exporter.AgentUri, new FakeApiRequestFactory(), statsd: null, updateSampleRates: null, isPartialFlushEnabled: false);

            AgentWriter = new AgentWriter(api, statsd: null, automaticFlush: false);

            var enrichedSpans = new Span[SpanCount];
            var now           = DateTimeOffset.UtcNow;

            for (int i = 0; i < SpanCount; i++)
            {
                enrichedSpans[i] = new Span(new SpanContext((ulong)i, (ulong)i, SamplingPriorityValues.UserReject, "Benchmark", null), now);
                enrichedSpans[i].SetTag(Tags.Env, "Benchmark");
                enrichedSpans[i].SetMetric(Metrics.SamplingRuleDecision, 1.0);
            }

            EnrichedSpans = new ArraySegment <Span>(enrichedSpans);

            // Run benchmarks once to reduce noise
            new AgentWriterBenchmark().WriteAndFlushEnrichedTraces().GetAwaiter().GetResult();
        }
Exemple #3
0
        static AgentWriterBenchmark()
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.StartupDiagnosticLogEnabled = false;
            settings.TraceEnabled = false;

            var api = new Api(settings.AgentUri, new FakeApiRequestFactory(), statsd: null);

            AgentWriter = new AgentWriter(api, new NullMetrics(), automaticFlush: false);

            Spans         = new Span[SpanCount];
            EnrichedSpans = new Span[SpanCount];
            var now = DateTimeOffset.UtcNow;

            for (int i = 0; i < SpanCount; i++)
            {
                Spans[i]         = new Span(new SpanContext(TraceId.CreateFromInt(i), (ulong)i, SamplingPriority.UserReject, "Benchmark", null), now);
                EnrichedSpans[i] = new Span(new SpanContext(TraceId.CreateFromInt(i), (ulong)i, SamplingPriority.UserReject, "Benchmark", null), now);
                EnrichedSpans[i].SetTag(Tags.Env, "Benchmark");
                EnrichedSpans[i].SetMetric(Metrics.SamplingRuleDecision, 1.0);
            }

            // Run benchmarks once to reduce noise
            new AgentWriterBenchmark().WriteAndFlushTraces().GetAwaiter().GetResult();
            new AgentWriterBenchmark().WriteAndFlushEnrichedTraces().GetAwaiter().GetResult();
        }
 public static void Main(string[] args)
 {
     CreateHostBuilder(args).Build().Run();
     var settings = TracerSettings.FromDefaultSources();
     var tracer   = new Tracer(settings);
     //Tracer.Instance = tracer;
 }
        private static void SetupTracer()
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.ServiceName = "squidex";

            Tracer.Instance = new Tracer(settings);
        }
        public static int RunLoggingProcedure(Action <string> logAction)
        {
#if NETFRAMEWORK
            // Set up the secondary AppDomain first
            // The plugin application we'll call was built and copied to the ApplicationFiles subdirectory
            // Create an AppDomain with that directory as the appBasePath
            var entryDirectory            = Directory.GetParent(Assembly.GetEntryAssembly().Location);
            var applicationFilesDirectory = Path.Combine(entryDirectory.FullName, "ApplicationFiles");
            var applicationAppDomain      = AppDomain.CreateDomain("ApplicationAppDomain", null, applicationFilesDirectory, applicationFilesDirectory, false);
#endif

            // Set up Tracer and start a trace
            // Do not explicitly set LogsInjectionEnabled = true, use DD_LOGS_INJECTION environment variable to enable
            var settings = TracerSettings.FromDefaultSources();
            settings.Environment ??= "dev";      // Ensure that we have an env value. In CI, this will automatically be assigned. Later we can test that everything is fine when Environment=null
            settings.ServiceVersion ??= "1.0.0"; // Ensure that we have an env value. In CI, this will automatically be assigned. Later we can test that everything is fine when when ServiceVersion=null
            Tracer.Configure(settings);

            try
            {
                logAction($"{ExcludeMessagePrefix}Entering Datadog scope.");
                using (var scope = Tracer.Instance.StartActive("transaction"))
                {
                    // In the middle of the trace, make a call across AppDomains
                    // Unless handled properly, this can cause the following error due
                    // to the way log4net stores "AsyncLocal" state in the
                    // System.Runtime.Remoting.Messaging.CallContext:
                    // System.Runtime.Serialization.SerializationException: Type is not resolved for member 'log4net.Util.PropertiesDictionary,log4net, Version=2.0.12.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a'.
#if NETFRAMEWORK
                    logAction("Calling the PluginApplication.Program in a separate AppDomain");
                    AppDomainProxy.Call(applicationAppDomain, "PluginApplication", "PluginApplication.Program", "Invoke", null);
#else
                    logAction("Skipping the cross-AppDomain call on .NET Core");
#endif
                }

                logAction($"{ExcludeMessagePrefix}Exited Datadog scope.");
#if NETFRAMEWORK
                AppDomain.Unload(applicationAppDomain);
#endif
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
                return((int)ExitCode.UnknownError);
            }

#if NETCOREAPP2_1
            // Add a delay to avoid a race condition on shutdown: https://github.com/dotnet/coreclr/pull/22712
            // This would cause a segmentation fault on .net core 2.x
            System.Threading.Thread.Sleep(5000);
#endif

            return((int)ExitCode.Success);
        }
Exemple #7
0
        public static void AddDistributedTracing(this IServiceCollection services)
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.Integrations["AdoNet"].Enabled = false;

            var tracer = new Tracer(settings);

            // set the global tracer
            Tracer.Instance = tracer;
        }
Exemple #8
0
        static Common()
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.TraceBufferSize = 1024 * 1024 * 45; // slightly lower than the 50mb payload agent limit.

            TestTracer  = new Tracer(settings);
            ServiceName = TestTracer.DefaultServiceName;

            // Preload environment variables.
            CIEnvironmentValues.DecorateSpan(null);
        }
Exemple #9
0
        private static void RunStuff(string serviceName, string operationName)
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.ServiceName = serviceName;
            Tracer.Configure(settings);

            Counts[Key(serviceName, operationName)]++;

            IScope root;

            using (root = Tracer.Instance.StartActive(operationName: operationName))
            {
                Thread.Sleep(3);

                using (var sub = Tracer.Instance.StartActive(operationName: SubOperation))
                {
                    Thread.Sleep(2);

                    using (var open = Tracer.Instance.StartActive(operationName: OpenOperation))
                    {
                        Thread.Sleep(2);
                    }

                    using (var close = Tracer.Instance.StartActive(operationName: CloseOperation))
                    {
                        Thread.Sleep(1);
                    }
                }

                Thread.Sleep(3);
            }

            var metrics     = GetMetrics(root);
            var rulePsrKey  = "_dd.rule_psr";
            var limitPsrKey = "_dd.limit_psr";
            var priorityKey = "_sampling_priority_v1";

            if (!metrics.ContainsKey(rulePsrKey))
            {
                throw new Exception($"{rulePsrKey} must be set in a user defined rule.");
            }

            var priority = metrics[priorityKey];

            if (priority > 0f && !metrics.ContainsKey(limitPsrKey))
            {
                throw new Exception($"{limitPsrKey} must be set if a user defined rule is configured and the trace is sampled.");
            }

            Counts[Key(serviceName, operationName, priority)]++;
        }
Exemple #10
0
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            log4net.Config.XmlConfigurator.Configure();

            var settings = TracerSettings.FromDefaultSources();

            settings.Integrations["AdoNet"].Enabled             = false;
            settings.Integrations["AspNet"].Enabled             = true;
            settings.Integrations["AspNetMvc"].Enabled          = true;
            settings.Integrations["AspNetWebApi2"].Enabled      = true;
            settings.Integrations["Wcf"].Enabled                = true;
            settings.Integrations["HttpMessageHandler"].Enabled = true;
            settings.Integrations["WebRequest"].Enabled         = true;

            Process currentProcessInfo = System.Diagnostics.Process.GetCurrentProcess();
            var     startTime          = currentProcessInfo.StartTime;

            TimeSpan startTimeSpan         = (startTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc));
            var      startTimeMilliseconds = Convert.ToUInt64(Math.Truncate(startTimeSpan.TotalMilliseconds));

            ILog log = log4net.LogManager.GetLogger(typeof(Tracer));

            log.Info($"Starting... {currentProcessInfo.Id.ToString()}");

            var enrichMode = ConfigurationManager.AppSettings["STS_ENRICH_MODE"];

            if (string.IsNullOrEmpty(enrichMode) || enrichMode != "OFF")
            {
                log.Info("Enriching with pid starttime hostname");
                settings.GlobalTags.Add("span.pid", currentProcessInfo.Id.ToString());
                settings.GlobalTags.Add("span.starttime", startTimeMilliseconds.ToString());
                if (!settings.GlobalTags.ContainsKey("span.hostname"))
                {
                    settings.GlobalTags.Add("span.hostname", Environment.MachineName);
                }
            }
            else
            {
                log.Info("SKIPPED enrichment on init.");
            }

            // create a new Tracer using these settings
            var tracer = new Tracer(settings);

            // set the global tracer
            Tracer.Instance = tracer;
        }
Exemple #11
0
        private void SetupDatadogTracing()
        {
            // read default configuration sources (env vars, web.config, datadog.json)
            TracerSettings settings = TracerSettings.FromDefaultSources();

            settings.LogsInjectionEnabled = true;

            // create a new Tracer using these settings
            Tracer tracer = new Tracer(settings);

            // set the global tracer
            Tracer.Instance = tracer;
        }
Exemple #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);
            }
        }
Exemple #13
0
        public static void ProvideTracer(AppSettings appSettings)
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.Environment    = "prod";
            settings.ServiceName    = "CsgoHoldem.api";
            settings.ServiceVersion = "alpha";
            GlobalSettings.SetDebugEnabled(appSettings.DataDogTracerDebugMode);
            settings.AgentUri     = new Uri("http://localhost:8126/");
            settings.TraceEnabled = appSettings.EnableDataDogTracing;
            var tracer = new Tracer(settings);

            Tracer.Instance = tracer;
        }
        private static void Main()
        {
            var numberOfSeconds          = 5;
            var maxMilliseconds          = numberOfSeconds * 1000;
            var configuredLimitPerSecond = int.Parse(Environment.GetEnvironmentVariables()["DD_MAX_TRACES_PER_SECOND"].ToString());

            Console.WriteLine($"Ready to run for {numberOfSeconds} seconds.");
            Console.WriteLine($"Configured rate limit of {configuredLimitPerSecond}");

            var settings = TracerSettings.FromDefaultSources();

            settings.ServiceName = ServiceDogWalker;
            Tracer.Configure(settings);

            PrepKeys(ServiceDogWalker, RootWalkOperation, configuredLimitPerSecond * numberOfSeconds);

            var timer = new Stopwatch();

            timer.Start();

            while (true)
            {
                if (timer.ElapsedMilliseconds >= maxMilliseconds)
                {
                    timer.Stop();
                    break;
                }

                RunStuff(ServiceDogWalker, RootWalkOperation);
            }

            Console.WriteLine();

            foreach (var key in Counts.Keys)
            {
                var isExpect = key.Contains("Expecting");

                if (isExpect)
                {
                    Console.WriteLine();
                    Console.WriteLine($"{key}");
                }
                else
                {
                    Console.WriteLine($"{key}: {Counts[key]}");
                }
            }
        }
        public static async Task <Tracer> CreateTracer()
        {
            var tracerSettings = TracerSettings.FromDefaultSources();

            OutputDebugInfo(tracerSettings);

            if (tracerSettings.Environment != "Development")
            {
                await LoadTracerSettingsFromAws(tracerSettings);
            }
            var tracer = new Tracer(tracerSettings);

            tracer.StartActive("Setup", serviceName: "YOLO");

            return(tracer);
        }
Exemple #16
0
        public static void Setup()
        {
            // read default configuration sources (env vars, web.config, datadog.json)
            var settings = TracerSettings.FromDefaultSources();

            // change some settings
            settings.ServiceName = "datadog-test";
            settings.AgentUri    = new Uri("http://localhost:8126/");

            // disable the AdoNet integration
            settings.Integrations["AdoNet"].Enabled = false;

            // create a new Tracer using these settings
            var tracer = new Tracer(settings);

            // set the global tracer
            Tracer.Instance = tracer;
        }
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager)
        {
            // fall back to default implementations of each dependency if not provided
            Settings      = settings ?? TracerSettings.FromDefaultSources();
            _agentWriter  = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri));
            _scopeManager = scopeManager ?? new AsyncLocalScopeManager();
            Sampler       = sampler ?? new RateByServiceSampler();

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

            // 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;
        }
        static AgentWriterBenchmark()
        {
            var settings = TracerSettings.FromDefaultSources();

            settings.StartupDiagnosticLogEnabled = false;
            settings.TraceEnabled = false;

            var api = new Api(settings.AgentUri, new FakeApiRequestFactory(), statsd: null);

            _agentWriter = new AgentWriter(api, statsd: null, automaticFlush: false);

            _spans = new Span[SpanCount];
            var now = DateTimeOffset.UtcNow;

            for (int i = 0; i < SpanCount; i++)
            {
                _spans[i] = new Span(new SpanContext((ulong)i, (ulong)i, SamplingPriority.UserReject, "Benchmark", null), now);
            }
        }
Exemple #19
0
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IStatsd statsd)
        {
            // fall back to default implementations of each dependency if not provided
            Settings = settings ?? TracerSettings.FromDefaultSources();

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

            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))
            {
                foreach (var rule in RegexSamplingRule.BuildFromConfigurationString(Settings.CustomSamplingRules))
                {
                    Sampler.RegisterRule(rule);
                }
            }

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

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

            // If configured, add/remove the correlation identifiers into the
            // LibLog logging context when a scope is activated/closed
            if (Settings.LogsInjectionEnabled)
            {
                InitializeLibLogScopeEventSubscriber(_scopeManager);
            }
        }
Exemple #20
0
        /// <summary>
        /// Create a new Tracer with the given parameters
        /// </summary>
        /// <param name="agentEndpoint">The agent endpoint where the traces will be sent (default is http://localhost:8126).</param>
        /// <param name="defaultServiceName">Default name of the service (default is the name of the executing assembly).</param>
        /// <param name="isDebugEnabled">Turns on all debug logging (this may have an impact on application performance).</param>
        /// <returns>The newly created tracer</returns>
        public static Tracer Create(Uri agentEndpoint = null, string defaultServiceName = null, bool isDebugEnabled = false)
        {
            // Keep supporting this older public method by creating a TracerConfiguration
            // from default sources, overwriting the specified settings, and passing that to the constructor.
            var configuration = TracerSettings.FromDefaultSources();

            GlobalSettings.SetDebugEnabled(isDebugEnabled);

            if (agentEndpoint != null)
            {
                configuration.AgentUri = agentEndpoint;
            }

            if (defaultServiceName != null)
            {
                configuration.ServiceName = defaultServiceName;
            }

            return(new Tracer(configuration));
        }
Exemple #21
0
        private static async Task Main(string[] args)
        {
            if (Environment.GetEnvironmentVariable("IS_CONTAINER") != "true")
            {
                DotEnv.Config();
            }

            var settings = TracerSettings.FromDefaultSources();

            settings.ServiceName = "Pisstaube";
            settings.AgentUri    = new Uri($"http://{Environment.GetEnvironmentVariable("DD_AGENT_HOST")}:{Environment.GetEnvironmentVariable("DD_DOGSTATSD_PORT")}/");

            settings.Integrations["AdoNet"].Enabled = false;

            var tracer = new Tracer(settings);

            Tracer.Instance = tracer;


            if (!Directory.Exists("./data"))
            {
                Directory.CreateDirectory("data");
            }

            var host = WebHost.CreateDefaultBuilder(args)
                       .UseKestrel(opt =>
            {
                opt.Limits.MaxRequestBodySize = null;
                opt.Listen(IPAddress.Any, 5000);
            })
                       .ConfigureServices(services => services.AddAutofac())
                       .UseContentRoot(Path.Join(Directory.GetCurrentDirectory(), "data"))
                       .UseStartup <Startup>()
                       .UseShutdownTimeout(TimeSpan.FromSeconds(5))
                       .UseSentry(Environment.GetEnvironmentVariable("SENTRY_DNS"))
                       .Build();

            await host.RunAsync(Cts.Token);
        }
        static int Main(string[] args)
        {
            try
            {
                InMemoryLog4NetLogger.Setup();
                var logger = LogManager.GetLogger(typeof(Program));

                var ddTraceSettings = TracerSettings.FromDefaultSources();
                ddTraceSettings.AnalyticsEnabled     = true;
                ddTraceSettings.LogsInjectionEnabled = true;
                ddTraceSettings.TraceEnabled         = true;
                var tracer = new Tracer(ddTraceSettings);

                var totalIterations      = 10_000;
                var threadRepresentation = Enumerable.Range(0, 10).ToArray();
                var threadCount          = threadRepresentation.Length;

                // Two logs per thread iteration + 1 extra log at the end of each thread
                var expectedLogCount = (totalIterations * threadCount * 2) + threadCount;
                var exceptionBag     = new ConcurrentBag <Exception>();

                Console.WriteLine($"Running {threadRepresentation.Length} threads with {totalIterations} iterations.");

                var threads =
                    threadRepresentation
                    .Select(
                        idx => new Thread(
                            thread =>
                {
                    try
                    {
                        Thread.Sleep(2000);
                        var i = 0;
                        while (i++ < totalIterations)
                        {
                            using (var outerScope = tracer.StartActive("thread-test"))
                            {
                                var outerTraceId = outerScope.Span.TraceId;
                                var outerSpanId  = outerScope.Span.SpanId;

                                logger.Info($"TraceId: {outerTraceId}, SpanId: {outerSpanId}");

                                using (var innerScope = tracer.StartActive("nest-thread-test"))
                                {
                                    var innerTraceId = innerScope.Span.TraceId;
                                    var innerSpanId  = innerScope.Span.SpanId;

                                    if (outerTraceId != innerTraceId)
                                    {
                                        throw new Exception($"TraceId mismatch - outer: {outerTraceId}, inner: {innerTraceId}");
                                    }

                                    if (outerSpanId == innerSpanId)
                                    {
                                        throw new Exception($"Unexpected SpanId match - outer: {outerSpanId}, inner: {innerSpanId}");
                                    }

                                    logger.Info($"TraceId: {innerTraceId}, SpanId: {innerSpanId}");
                                }
                            }
                        }

                        // Verify everything is cleaned up on this thread
                        logger.Info(NonTraceMessage);
                    }
                    catch (Exception ex)
                    {
                        exceptionBag.Add(ex);
                    }
                }))
                    .ToList();

                foreach (var thread in threads)
                {
                    thread.Start();
                }

                while (threads.Any(x => x.IsAlive))
                {
                    Thread.Sleep(1000);
                }

                if (exceptionBag.Any())
                {
                    // No exceptions are acceptable
                    throw new AggregateException(exceptionBag.ToArray());
                }

                var loggingEvents = RelevantLogs();

                foreach (var group in loggingEvents.Where(e => e.RenderedMessage != NonTraceMessage).GroupBy(e => e.RenderedMessage))
                {
                    var message = group.First().RenderedMessage;
                    if (group.Count() > 1)
                    {
                        Console.WriteLine($"Has duplicate log entries ({group.Count()}): {message}");
                    }
                }

                Console.WriteLine($"Expecting {expectedLogCount} total log events.");
                Console.WriteLine($"Received {loggingEvents.Length} total log events.");

                if (loggingEvents.Length != expectedLogCount)
                {
                    throw new Exception($"Expected {expectedLogCount}, actual log count {loggingEvents.Length}");
                }

                foreach (var loggingEvent in loggingEvents)
                {
                    var attachedTraceId  = loggingEvent.Properties[TraceIdKey];
                    var attachedSpanIdId = loggingEvent.Properties[SpanIdKey];
                    var expectedMessage  = $"TraceId: {attachedTraceId}, SpanId: {attachedSpanIdId}";
                    if (expectedMessage.Equals(loggingEvent.RenderedMessage))
                    {
                        // all is well
                        continue;
                    }

                    throw new Exception($"LOGGING EVENT DOES NOT MATCH ({attachedTraceId}, {attachedSpanIdId}): {loggingEvent.RenderedMessage}");
                }

                Console.WriteLine("Every trace wrapped logging event has the expected TraceId and SpanId.");

                // Test non-traced logging event
                logger.Info(NonTraceMessage);

                var lastLog         = RelevantLogs().Last();
                var lastLogTraceId  = lastLog.Properties[TraceIdKey];
                var lastLogSpanIdId = lastLog.Properties[SpanIdKey];
                var actual          = $"TraceId: {lastLogTraceId}, SpanId: {lastLogSpanIdId}";

                if (!actual.Equals(NonTraceMessage))
                {
                    throw new Exception($"Unexpected TraceId or SpanId: {actual}");
                }

                Console.WriteLine("Non-trace wrapped logging event has 0 for TraceId and SpanId.");
                Console.WriteLine("All is well!");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
                return((int)ExitCode.UnknownError);
            }

            return((int)ExitCode.Success);
        }
        static int Main(string[] args)
        {
            try
            {
                InMemoryLog4NetLogger.Setup();
                var logger = LogManager.GetLogger(typeof(Program));

                var ddTraceSettings = TracerSettings.FromDefaultSources();
                ddTraceSettings.AnalyticsEnabled     = true;
                ddTraceSettings.LogsInjectionEnabled = true;
                ddTraceSettings.TraceEnabled         = true;
                var tracer = new Tracer(ddTraceSettings);

                var totalIterations      = 400_000;
                var threadRepresentation = Enumerable.Range(0, 5).ToArray();
                var threadCount          = threadRepresentation.Length;

                // Two logs per thread iteration + 1 extra log at the end of each thread
                var expectedLogCount = threadCount;
                var exceptionBag     = new ConcurrentBag <Exception>();

                Console.WriteLine($"Running {threadRepresentation.Length} threads with {totalIterations} iterations.");

                var threads =
                    threadRepresentation
                    .Select(
                        idx => new Thread(
                            thread =>
                {
                    try
                    {
                        Span firstSpan;
                        using (var outerScope = tracer.StartActive("outer-span"))
                        {
                            // Save the span so we can later re-use its TraceContext
                            firstSpan = outerScope.Span;

                            // Initialize scopes/spans to aggressively open
                            var threadScopes = new Stack <IDisposable>();
                            var i            = 0;

                            while (i++ < totalIterations)
                            {
                                string spanString = $"inner-span-{i}";
                                threadScopes.Push(tracer.StartActive(spanString));
                            }

                            i = 0;
                            while (threadScopes.Count > 0)
                            {
                                threadScopes.Pop().Dispose();
                            }
                        }

                        Thread.Sleep(500);

                        // Now that the entire set of spans has been closed and queued
                        // to be written to the agent, re-open that same TraceContext
                        // Repeat the operation to trigger the exception
                        using (var outerScope = tracer.ActivateSpan(firstSpan))
                        {
                            // Initialize scopes/spans to aggressively open
                            var threadScopes = new Stack <IDisposable>();
                            var i            = 0;

                            while (i++ < totalIterations)
                            {
                                string spanString = $"second inner-span-{i}";
                                threadScopes.Push(tracer.StartActive(spanString));
                            }

                            i = 0;
                            while (threadScopes.Count > 0)
                            {
                                threadScopes.Pop().Dispose();
                            }
                        }

                        // Verify everything is cleaned up on this thread
                        logger.Info(ThreadFinishedMessage);
                    }
                    catch (Exception ex)
                    {
                        exceptionBag.Add(ex);
                    }
                }))
                    .ToList();

                foreach (var thread in threads)
                {
                    thread.Start();
                }

                while (threads.Any(x => x.IsAlive))
                {
                    Thread.Sleep(1000);
                }

                if (exceptionBag.Any())
                {
                    // No exceptions are acceptable
                    throw new AggregateException(exceptionBag.ToArray());
                }

                var loggingEvents = InMemoryLog4NetLogger.InMemoryAppender.GetEvents();
                var invalidOperationExceptionEvents = loggingEvents.Where(e => e.RenderedMessage.Contains("InvalidOperationException"));
                int invalidOperationExceptionCount  = invalidOperationExceptionEvents.Count();

                Console.WriteLine($"Received {invalidOperationExceptionCount} log events containing 'InvalidOperationException'.");

                if (loggingEvents.Length != expectedLogCount && invalidOperationExceptionEvents.Count() > 0)
                {
                    throw new Exception($"Expected log count: {expectedLogCount}, actual log count: {loggingEvents.Length}, logs containing 'InvalidOperationException': {invalidOperationExceptionCount}");
                }

                Console.WriteLine("All is well!");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
                return((int)ExitCode.UnknownError);
            }

            return((int)ExitCode.Success);
        }
Exemple #24
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));
                }
            }
        }
Exemple #25
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);
            }
        }
 public static IEnumerable <object[]> ExporterEnvVarAndLoadSettingsAction()
 {
     yield return(new object[] { ConfigurationKeys.Traces.Exporter, void() => TracerSettings.FromDefaultSources() });
        static int Main(string[] args)
        {
            try
            {
                InMemoryLog4NetLogger.Setup();
                var logger          = LogManager.GetLogger(typeof(Program));
                var ddTraceSettings = TracerSettings.FromDefaultSources();
                ddTraceSettings.LogsInjectionEnabled = true;
                ddTraceSettings.TraceEnabled         = true;
                ddTraceSettings.TracerMetricsEnabled = true;
                GlobalSettings.SetDebugEnabled(true);

                Tracer.Configure(ddTraceSettings);
                var tracer               = Tracer.Instance;
                var totalIterations      = 100;
                var threadRepresentation = Enumerable.Range(0, 25).ToArray();
                var threadCount          = threadRepresentation.Length;

                // Two logs per thread iteration + 1 extra log at the end of each thread
                var expectedLogCount = threadCount;
                var exceptionBag     = new ConcurrentBag <Exception>();

                Console.WriteLine($"Running {threadRepresentation.Length} threads with {totalIterations} iterations.");

                var threads =
                    threadRepresentation
                    .Select(
                        idx => new Thread(
                            thread =>
                {
                    try
                    {
                        var i = 0;

                        while (i++ < totalIterations)
                        {
                            using (var outerScope = tracer.StartActive("outer-span"))
                            {
                            }
                        }

                        Thread.Sleep(100);

                        // Verify everything is cleaned up on this thread
                        logger.Info(ThreadFinishedMessage);
                    }
                    catch (Exception ex)
                    {
                        exceptionBag.Add(ex);
                    }
                }))
                    .ToList();

                foreach (var thread in threads)
                {
                    thread.Start();
                }

                while (threads.Any(x => x.IsAlive))
                {
                    Thread.Sleep(500);
                }

                if (exceptionBag.Any())
                {
                    // No exceptions are acceptable
                    throw new AggregateException(exceptionBag.ToArray());
                }

                var loggingEvents                  = InMemoryLog4NetLogger.InMemoryAppender.GetEvents();
                var systemOutOfRangeException      = loggingEvents.Where(e => e.RenderedMessage.Contains("Index was outside the bounds of the array"));
                int systemOutOfRangeExceptionCount = systemOutOfRangeException.Count();

                Console.WriteLine($"Received {systemOutOfRangeExceptionCount} log events containing 'Index was outside the bounds of the array'.");

                if (systemOutOfRangeException.Count() > 0)
                {
                    throw new Exception("Got exception with 'System.IndexOutOfRangeException'");
                }

                Console.WriteLine("Press any key to exit");
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
                return((int)ExitCode.UnknownError);
            }

            return((int)ExitCode.Success);
        }
        public static int Process(string jsonFilePath)
        {
            Console.WriteLine("Importing Crank json result file...");
            try
            {
                string jsonContent = File.ReadAllText(jsonFilePath);
                var    result      = JsonConvert.DeserializeObject <Models.ExecutionResult>(jsonContent);

                if (result?.JobResults?.Jobs?.Count > 0)
                {
                    var fileName = Path.GetFileName(jsonFilePath);

                    var tracerSettings = TracerSettings.FromDefaultSources();
                    if (string.IsNullOrEmpty(tracerSettings.ServiceName))
                    {
                        tracerSettings.ServiceName = "crank";
                    }

                    Tracer tracer = new Tracer(tracerSettings);

                    foreach (var jobItem in result.JobResults.Jobs)
                    {
                        var jobResult = jobItem.Value;
                        if (jobResult is null)
                        {
                            continue;
                        }

                        DateTimeOffset minTimeStamp = DateTimeOffset.UtcNow;
                        DateTimeOffset maxTimeStamp = minTimeStamp;
                        var            measurements = jobResult.Measurements?.SelectMany(i => i).ToList() ?? new List <Models.Measurement>();
                        if (measurements.Count > 0)
                        {
                            maxTimeStamp = measurements.Max(i => i.Timestamp).ToUniversalTime();
                            minTimeStamp = measurements.Min(i => i.Timestamp).ToUniversalTime();
                        }

                        var duration = (maxTimeStamp - minTimeStamp);

                        Span span = tracer.StartSpan("crank.test", startTime: minTimeStamp);

                        span.SetTraceSamplingPriority(SamplingPriority.AutoKeep);
                        span.Type         = SpanTypes.Test;
                        span.ResourceName = $"{fileName}/{jobItem.Key}";
                        CIEnvironmentValues.DecorateSpan(span);

                        span.SetTag(TestTags.Name, jobItem.Key);
                        span.SetTag(TestTags.Type, TestTags.TypeBenchmark);
                        span.SetTag(TestTags.Suite, fileName);
                        span.SetTag(TestTags.Framework, $"Crank");
                        span.SetTag(TestTags.Status, result.ReturnCode == 0 ? TestTags.StatusPass : TestTags.StatusFail);

                        if (result.JobResults.Properties?.Count > 0)
                        {
                            string scenario = string.Empty;
                            string profile  = string.Empty;
                            string arch     = string.Empty;
                            string testName = jobItem.Key;
                            foreach (var propItem in result.JobResults.Properties)
                            {
                                span.SetTag("test.properties." + propItem.Key, propItem.Value);

                                if (propItem.Key == "name")
                                {
                                    testName = propItem.Value + "." + jobItem.Key;
                                }
                                else if (propItem.Key == "scenario")
                                {
                                    scenario = propItem.Value;
                                }
                                else if (propItem.Key == "profile")
                                {
                                    profile = propItem.Value;
                                }
                                else if (propItem.Key == "arch")
                                {
                                    arch = propItem.Value;
                                }
                            }

                            string suite = fileName;
                            if (!string.IsNullOrEmpty(scenario))
                            {
                                suite = scenario;

                                if (!string.IsNullOrEmpty(profile))
                                {
                                    suite += "." + profile;
                                }

                                if (!string.IsNullOrEmpty(arch))
                                {
                                    suite += "." + arch;
                                }
                            }

                            span.SetTag(TestTags.Suite, suite);
                            span.SetTag(TestTags.Name, testName);
                            span.ResourceName = $"{suite}/{testName}";
                        }

                        try
                        {
                            if (jobResult.Results?.Count > 0)
                            {
                                foreach (var resultItem in jobResult.Results)
                                {
                                    if (string.IsNullOrEmpty(resultItem.Key))
                                    {
                                        continue;
                                    }

                                    if (resultItem.Value is string valueString)
                                    {
                                        span.SetTag("test.results." + resultItem.Key.Replace("/", ".").Replace("-", "_"), valueString);
                                    }
                                    else
                                    {
                                        NumberResultConverter numberConverter = default;

                                        bool converted = false;
                                        foreach (var converter in Converters)
                                        {
                                            if (converter.CanConvert(resultItem.Key))
                                            {
                                                converter.SetToSpan(span, "test.results." + resultItem.Key.Replace("/", ".").Replace("-", "_"), resultItem.Value);
                                                converted = true;
                                                break;
                                            }
                                        }

                                        if (!converted)
                                        {
                                            numberConverter.SetToSpan(span, "test.results." + resultItem.Key.Replace("/", ".").Replace("-", "_"), resultItem.Value);
                                        }
                                    }
                                }
                            }

                            if (jobResult.Environment?.Count > 0)
                            {
                                foreach (var envItem in jobResult.Environment)
                                {
                                    span.SetTag("environment." + envItem.Key, envItem.Value?.ToString() ?? "(null)");
                                }
                            }
                        }
                        finally
                        {
                            if (duration == TimeSpan.Zero)
                            {
                                span.Finish();
                            }
                            else
                            {
                                span.Finish(span.StartTime.Add(duration));
                            }
                        }
                    }

                    // Ensure all the spans gets flushed before we report the success.
                    // In some cases the process finishes without sending the traces in the buffer.
                    SynchronizationContext context = SynchronizationContext.Current;
                    try
                    {
                        SynchronizationContext.SetSynchronizationContext(null);
                        tracer.FlushAsync().GetAwaiter().GetResult();
                    }
                    finally
                    {
                        SynchronizationContext.SetSynchronizationContext(context);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return(1);
            }

            Console.WriteLine("The result file was imported successfully.");
            return(0);
        }
Exemple #29
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);
                }
            }
        }