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