From 6ce27defe05d7fa7f54f033e1840d6de181231cf Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Thu, 26 Sep 2019 14:37:58 +0200 Subject: [PATCH 1/4] Implementing the "Named Tracers" proposal for .NET --- samples/Exporters/TestApplicationInsights.cs | 4 +- samples/Exporters/TestHttpClient.cs | 6 +- samples/Exporters/TestJaeger.cs | 6 +- samples/Exporters/TestLightstep.cs | 7 +- samples/Exporters/TestRedis.cs | 6 +- samples/Exporters/TestStackdriver.cs | 4 +- samples/Exporters/TestZipkin.cs | 6 +- .../LoggingTracerExtensions.cs | 2 +- .../LoggingTracer.Demo.ConsoleApp/Program.cs | 9 ++- .../LoggingTracer/LoggingTracer.cs | 5 ++ .../LoggingTracer/LoggingTracerFactory.cs | 19 +++++ .../Trace/ITracerFactory.cs | 35 +++++++++ .../Implementation/HttpInListener.cs | 6 +- .../RequestsCollector.cs | 12 +-- .../AzureSdkDiagnosticListener.cs | 19 ++--- .../DependenciesCollector.cs | 18 +++-- .../HttpHandlerDiagnosticListener.cs | 10 +-- .../Collector/DiagnosticSourceSubscriber.cs | 18 ++--- .../Collector/ListenerHandler.cs | 4 +- src/OpenTelemetry/Trace/Tracer.cs | 15 ++-- src/OpenTelemetry/Trace/TracerFactory.cs | 67 +++++++++++++++++ src/OpenTelemetry/Trace/Tracing.cs | 19 ++--- .../BasicTests.cs | 6 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 4 +- .../BasicTests.cs | 9 ++- .../HttpClientTests.cs | 6 +- .../RedisProfilerEntryToSpanConverterTests.cs | 4 +- .../StackExchangeRedisCallsCollectorTests.cs | 4 +- .../ApplicationInsightsTraceExporterTests.cs | 2 +- .../Implementation/JaegerSpanConverterTest.cs | 2 +- .../JaegerThriftIntegrationTest.cs | 2 +- .../LightStepSpanConverterTest.cs | 2 +- .../Impl/Trace/SpanBuilderTest.cs | 4 +- .../Impl/Trace/TracerFactoryTest.cs | 75 +++++++++++++++++++ .../Impl/Trace/TracerTest.cs | 19 +++-- .../Impl/Trace/TracingTest.cs | 4 +- 36 files changed, 337 insertions(+), 103 deletions(-) create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs create mode 100644 src/OpenTelemetry.Abstractions/Trace/ITracerFactory.cs create mode 100644 src/OpenTelemetry/Trace/TracerFactory.cs create mode 100644 test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs diff --git a/samples/Exporters/TestApplicationInsights.cs b/samples/Exporters/TestApplicationInsights.cs index 6824d3d504d..5da8b59fd1b 100644 --- a/samples/Exporters/TestApplicationInsights.cs +++ b/samples/Exporters/TestApplicationInsights.cs @@ -21,6 +21,7 @@ namespace Samples using System.Threading; using Microsoft.ApplicationInsights.Extensibility; using OpenTelemetry.Exporter.ApplicationInsights; + using OpenTelemetry.Resources; using OpenTelemetry.Stats; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; @@ -59,7 +60,8 @@ internal static object Run() var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); - var tracer = new Tracer(new BatchingSpanProcessor(exporter), TraceConfig.Default); + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(exporter)); + var tracer = tracerFactory.GetTracer(string.Empty); var spanBuilder = tracer .SpanBuilder("incoming request") .SetRecordEvents(true) diff --git a/samples/Exporters/TestHttpClient.cs b/samples/Exporters/TestHttpClient.cs index ed954cb2097..dd2de0a255e 100644 --- a/samples/Exporters/TestHttpClient.cs +++ b/samples/Exporters/TestHttpClient.cs @@ -21,6 +21,7 @@ namespace Samples using System.Threading; using OpenTelemetry.Collector.Dependencies; using OpenTelemetry.Exporter.Zipkin; + using OpenTelemetry.Resources; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; @@ -39,8 +40,9 @@ internal static object Run() ServiceName = typeof(Program).Assembly.GetName().Name, }); - var tracer = new Tracer(new BatchingSpanProcessor(exporter), TraceConfig.Default); - using (new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(exporter)); + var tracer = tracerFactory.GetTracer(string.Empty); + using (new DependenciesCollector(new DependenciesCollectorOptions(), tracerFactory, Samplers.AlwaysSample)) { using (tracer.WithSpan(tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartSpan())) { diff --git a/samples/Exporters/TestJaeger.cs b/samples/Exporters/TestJaeger.cs index 508d097e233..5a2dbf03ad3 100644 --- a/samples/Exporters/TestJaeger.cs +++ b/samples/Exporters/TestJaeger.cs @@ -20,6 +20,7 @@ namespace Samples using System.Collections.Generic; using System.Threading; using OpenTelemetry.Exporter.Jaeger; + using OpenTelemetry.Resources; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; @@ -38,7 +39,8 @@ internal static object Run(string host, int port) }); // Create a tracer. You may also need to register it as a global instance to make auto-collectors work.. - var tracer = new Tracer(new BatchingSpanProcessor(exporter), TraceConfig.Default); + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(exporter)); + var tracer = tracerFactory.GetTracer(string.Empty); // Create a scoped span. It will end automatically when using statement ends using (tracer.WithSpan(tracer.SpanBuilder("Main").StartSpan())) @@ -56,7 +58,7 @@ internal static object Run(string host, int port) return null; } - private static void DoWork(int i, Tracer tracer) + private static void DoWork(int i, ITracer tracer) { // Start another span. If another span was already started, it'll use that span as the parent span. // In this example, the main method already started a span, so that'll be the parent span, and this will be diff --git a/samples/Exporters/TestLightstep.cs b/samples/Exporters/TestLightstep.cs index a956f64739b..599bef4c065 100644 --- a/samples/Exporters/TestLightstep.cs +++ b/samples/Exporters/TestLightstep.cs @@ -1,5 +1,7 @@ // +using OpenTelemetry.Resources; + namespace Samples { using System; @@ -21,7 +23,8 @@ internal static object Run(string accessToken) ServiceName = "tracing-to-lightstep-service", }); - var tracer = new Tracer(new BatchingSpanProcessor(exporter), TraceConfig.Default); + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(exporter)); + var tracer = tracerFactory.GetTracer(string.Empty); using (tracer.WithSpan(tracer.SpanBuilder("Main").StartSpan())) { @@ -38,7 +41,7 @@ internal static object Run(string accessToken) return null; } - private static void DoWork(int i, Tracer tracer) + private static void DoWork(int i, ITracer tracer) { using (tracer.WithSpan(tracer.SpanBuilder("DoWork").StartSpan())) { diff --git a/samples/Exporters/TestRedis.cs b/samples/Exporters/TestRedis.cs index c6b7e85f2c9..a4098846885 100644 --- a/samples/Exporters/TestRedis.cs +++ b/samples/Exporters/TestRedis.cs @@ -21,6 +21,7 @@ namespace Samples using System.Threading; using OpenTelemetry.Collector.StackExchangeRedis; using OpenTelemetry.Exporter.Zipkin; + using OpenTelemetry.Resources; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; @@ -39,7 +40,8 @@ internal static object Run(string zipkinUri) }); // Create a tracer. You may also need to register it as a global instance to make auto-collectors work.. - var tracer = new Tracer(new BatchingSpanProcessor(exporter), TraceConfig.Default); + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(exporter)); + var tracer = tracerFactory.GetTracer(string.Empty); var collector = new StackExchangeRedisCallsCollector(tracer); @@ -65,7 +67,7 @@ internal static object Run(string zipkinUri) return null; } - private static void DoWork(IDatabase db, Tracer tracer) + private static void DoWork(IDatabase db, ITracer tracer) { // Start another span. If another span was already started, it'll use that span as the parent span. // In this example, the main method already started a span, so that'll be the parent span, and this will be diff --git a/samples/Exporters/TestStackdriver.cs b/samples/Exporters/TestStackdriver.cs index 2cca00b1208..72d500e9530 100644 --- a/samples/Exporters/TestStackdriver.cs +++ b/samples/Exporters/TestStackdriver.cs @@ -20,6 +20,7 @@ namespace Samples using System.Collections.Generic; using System.Threading; using OpenTelemetry.Exporter.Stackdriver; + using OpenTelemetry.Resources; using OpenTelemetry.Stats; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; @@ -57,7 +58,8 @@ internal static object Run(string projectId) Stats.ViewManager); metricExporter.Start(); - var tracer = new Tracer(new BatchingSpanProcessor(spanExporter), TraceConfig.Default); + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(spanExporter)); + var tracer = tracerFactory.GetTracer(string.Empty); var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); diff --git a/samples/Exporters/TestZipkin.cs b/samples/Exporters/TestZipkin.cs index 325eabc0045..08ef6346617 100644 --- a/samples/Exporters/TestZipkin.cs +++ b/samples/Exporters/TestZipkin.cs @@ -20,6 +20,7 @@ namespace Samples using System.Collections.Generic; using System.Threading; using OpenTelemetry.Exporter.Zipkin; + using OpenTelemetry.Resources; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; @@ -37,7 +38,8 @@ internal static object Run(string zipkinUri) }); // Create a tracer. You may also need to register it as a global instance to make auto-collectors work.. - var tracer = new Tracer(new BatchingSpanProcessor(exporter), TraceConfig.Default); + var tracerFactory = new TracerFactory(new BatchingSpanProcessor(exporter)); + var tracer = tracerFactory.GetTracer(string.Empty); // Create a scoped span. It will end automatically when using statement ends using (tracer.WithSpan(tracer.SpanBuilder("Main").StartSpan())) @@ -54,7 +56,7 @@ internal static object Run(string zipkinUri) return null; } - private static void DoWork(int i, Tracer tracer) + private static void DoWork(int i, ITracer tracer) { // Start another span. If another span was already started, it'll use that span as the parent span. // In this example, the main method already started a span, so that'll be the parent span, and this will be diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs index 96a290f79f5..eefe20fa262 100644 --- a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs @@ -15,7 +15,7 @@ internal static class LoggingTracerExtensions { internal static void AddLoggingTracer(this IServiceCollection services) { - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(Samplers.AlwaysSample); services.AddSingleton(); diff --git a/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs index 3d6d2b42a23..20ea8aef3f9 100644 --- a/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs +++ b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs @@ -9,19 +9,20 @@ namespace LoggingTracer.Demo.ConsoleApp public class Program { - private static ITracer tracer = new LoggingTracer(); - public static async Task Main(string[] args) { + var tracerFactory = new LoggingTracerFactory(); + var tracer = tracerFactory.GetTracer("ConsoleApp", "semver:1.0.0"); + var builder = tracer.SpanBuilder("Main (span1)"); using (tracer.WithSpan(builder.StartSpan())) { await Task.Delay(100); - await Foo(); + await Foo(tracer); } } - private static async Task Foo() + private static async Task Foo(ITracer tracer) { var builder = tracer.SpanBuilder("Foo (span2)"); using (tracer.WithSpan(builder.StartSpan())) diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs b/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs index 237118ee1a7..8c25a51aa76 100644 --- a/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs @@ -10,6 +10,11 @@ namespace LoggingTracer public class LoggingTracer : ITracer { + internal LoggingTracer() + { + Logger.Log($"Tracer.ctor()"); + } + public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan; public IBinaryFormat BinaryFormat => new LoggingBinaryFormat(); diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs b/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs new file mode 100644 index 00000000000..1a5cd7d82f8 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace LoggingTracer +{ + using OpenTelemetry.Context; + using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Trace; + + public class LoggingTracerFactory : ITracerFactory + { + public ITracer GetTracer(string name, string version = null) + { + Logger.Log($"TracerFactory.GetTracer('{name}', '{version}')"); + return new LoggingTracer(); + } + } +} diff --git a/src/OpenTelemetry.Abstractions/Trace/ITracerFactory.cs b/src/OpenTelemetry.Abstractions/Trace/ITracerFactory.cs new file mode 100644 index 00000000000..ead062784d4 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Trace/ITracerFactory.cs @@ -0,0 +1,35 @@ +// +// Copyright 2018, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace OpenTelemetry.Trace +{ + using OpenTelemetry.Context; + using OpenTelemetry.Context.Propagation; + + /// + /// Creates Tracers for an instrumentation library. + /// + public interface ITracerFactory + { + /// + /// Returns an ITracer for a given name and version. + /// + /// Name of the instrumentation library. + /// Version of the instrumentation library (optional). + /// Tracer for the given name and version information. + ITracer GetTracer(string name, string version = null); + } +} diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs index 8a5890ff884..af9657af2cf 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs @@ -34,8 +34,8 @@ internal class HttpInListener : ListenerHandler private readonly PropertyFetcher beforeActionTemplateFetcher = new PropertyFetcher("Template"); private readonly bool hostingSupportsW3C = false; - public HttpInListener(ITracer tracer, Func samplerFactory) - : base("Microsoft.AspNetCore", tracer, samplerFactory) + public HttpInListener(string name, Version version, ITracerFactory tracerFactory, Func samplerFactory) + : base(name, version, tracerFactory, samplerFactory) { this.hostingSupportsW3C = typeof(HttpRequest).Assembly.GetName().Version.Major >= 3; } @@ -46,7 +46,7 @@ public override void OnStartActivity(Activity activity, object payload) var context = this.startContextFetcher.Fetch(payload) as HttpContext; if (context == null) - { + { CollectorEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix); return; } diff --git a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs index 0395ea5a14f..72c2edbe0fc 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Collector.AspNetCore { using System; using System.Collections.Generic; + using System.Reflection; using Microsoft.AspNetCore.Http; using OpenTelemetry.Collector.AspNetCore.Implementation; using OpenTelemetry.Trace; @@ -33,16 +34,17 @@ public class RequestsCollector : IDisposable /// Initializes a new instance of the class. /// /// Configuration options for dependencies collector. - /// Tracer to record traced with. + /// TracerFactory which creates the Tracer to record traced with. /// Sampler to use to sample dependency calls. - public RequestsCollector(RequestsCollectorOptions options, ITracer tracer, ISampler sampler) + public RequestsCollector(RequestsCollectorOptions options, ITracerFactory tracerFactory, ISampler sampler) { + const string name = "Microsoft.AspNetCore"; this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber( - new Dictionary, ListenerHandler>>() + new Dictionary, ListenerHandler>>() { - { "Microsoft.AspNetCore", (t, s) => new HttpInListener(t, s) }, + { name, (t, s) => new HttpInListener(name, Assembly.GetExecutingAssembly().GetName().Version, t, s) }, }, - tracer, + tracerFactory, x => { ISampler s = null; diff --git a/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs index f7d31e8e8df..3d2bc733541 100644 --- a/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs @@ -20,20 +20,17 @@ namespace OpenTelemetry.Collector.Dependencies using System.Collections.Generic; using System.Diagnostics; using System.Net.Http; - using OpenTelemetry.Collector.Dependencies.Implementation; + using OpenTelemetry.Collector.Dependencies.Implementation; using OpenTelemetry.Trace; internal class AzureSdkDiagnosticListener : ListenerHandler { private static readonly PropertyFetcher LinksPropertyFetcher = new PropertyFetcher("Links"); - private readonly ITracer tracer; - private readonly ISampler sampler; - public AzureSdkDiagnosticListener(string sourceName, ITracer tracer, ISampler sampler) - : base(sourceName, tracer, null) + public AzureSdkDiagnosticListener(string sourceName, Version version, ITracerFactory tracerFactory, ISampler sampler) + : base(sourceName, version, tracerFactory, null) { - this.tracer = tracer; this.sampler = sampler; } @@ -67,7 +64,7 @@ public override void OnStartActivity(Activity current, object valueValue) } } - var spanBuilder = this.tracer.SpanBuilder(operationName) + var spanBuilder = this.Tracer.SpanBuilder(operationName) .SetCreateChild(false) .SetSampler(this.sampler); @@ -84,23 +81,23 @@ public override void OnStartActivity(Activity current, object valueValue) span.Status = Status.Ok; - this.tracer.WithSpan(span); + this.Tracer.WithSpan(span); } public override void OnStopActivity(Activity current, object valueValue) { - var span = this.tracer.CurrentSpan; + var span = this.Tracer.CurrentSpan; foreach (var keyValuePair in current.Tags) { span.SetAttribute(keyValuePair.Key, keyValuePair.Value); } - this.tracer.CurrentSpan.End(); + this.Tracer.CurrentSpan.End(); } public override void OnException(Activity current, object valueValue) { - var span = this.tracer.CurrentSpan; + var span = this.Tracer.CurrentSpan; span.Status = Status.Unknown.WithDescription(valueValue?.ToString()); } diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs index d7e6e3d51dc..ae000516469 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs @@ -19,6 +19,7 @@ namespace OpenTelemetry.Collector.Dependencies using System; using System.Collections.Generic; using System.Net.Http; + using System.Reflection; using OpenTelemetry.Collector.Dependencies.Implementation; using OpenTelemetry.Trace; @@ -33,18 +34,19 @@ public class DependenciesCollector : IDisposable /// Initializes a new instance of the class. /// /// Configuration options for dependencies collector. - /// Tracer to record traced with. - /// Sampler to use to sample dependnecy calls. - public DependenciesCollector(DependenciesCollectorOptions options, ITracer tracer, ISampler sampler) + /// TracerFactory to create a Tracer to record traced with. + /// Sampler to use to sample dependency calls. + public DependenciesCollector(DependenciesCollectorOptions options, ITracerFactory tracerFactory, ISampler sampler) { + var version = Assembly.GetExecutingAssembly().GetName().Version; this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber( - new Dictionary, ListenerHandler>>() + new Dictionary, ListenerHandler>>() { - { "HttpHandlerDiagnosticListener", (t, s) => new HttpHandlerDiagnosticListener(t, s) }, - { "Azure.Clients", (t, s) => new AzureSdkDiagnosticListener("Azure.Clients", t, sampler) }, - { "Azure.Pipeline", (t, s) => new AzureSdkDiagnosticListener("Azure.Pipeline", t, sampler) }, + { "HttpHandlerDiagnosticListener", (tf, s) => new HttpHandlerDiagnosticListener(tf, s) }, + { "Azure.Clients", (tf, s) => new AzureSdkDiagnosticListener("Azure.Clients", version, tf, sampler) }, + { "Azure.Pipeline", (tf, s) => new AzureSdkDiagnosticListener("Azure.Pipeline", version, tf, sampler) }, }, - tracer, + tracerFactory, x => { ISampler s = null; diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs index 238073d3e19..97358935e22 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Collector.Dependencies.Implementation using System.Linq; using System.Net; using System.Net.Http; - using System.Reflection; + using System.Reflection; using System.Runtime.Versioning; using System.Threading.Tasks; using OpenTelemetry.Trace; @@ -34,8 +34,8 @@ internal class HttpHandlerDiagnosticListener : ListenerHandler samplerFactory) - : base("HttpHandlerDiagnosticListener", tracer, samplerFactory) + public HttpHandlerDiagnosticListener(ITracerFactory tracerFactory, Func samplerFactory) + : base("HttpHandlerDiagnosticListener", Assembly.GetExecutingAssembly().GetName().Version, tracerFactory, samplerFactory) { var framework = Assembly .GetEntryAssembly()? @@ -55,7 +55,7 @@ public override void OnStartActivity(Activity activity, object payload) { const string EventNameSuffix = ".OnStartActivity"; if (!(this.startRequestFetcher.Fetch(payload) is HttpRequestMessage request)) - { + { CollectorEventSource.Log.NullPayload(nameof(HttpHandlerDiagnosticListener) + EventNameSuffix); return; } @@ -91,7 +91,7 @@ public override void OnStartActivity(Activity activity, object payload) } public override void OnStopActivity(Activity activity, object payload) - { + { const string EventNameSuffix = ".OnStopActivity"; var span = this.Tracer.CurrentSpan; diff --git a/src/OpenTelemetry/Collector/DiagnosticSourceSubscriber.cs b/src/OpenTelemetry/Collector/DiagnosticSourceSubscriber.cs index 03c99a00337..ad72c1b0609 100644 --- a/src/OpenTelemetry/Collector/DiagnosticSourceSubscriber.cs +++ b/src/OpenTelemetry/Collector/DiagnosticSourceSubscriber.cs @@ -25,18 +25,18 @@ namespace OpenTelemetry.Collector public class DiagnosticSourceSubscriber : IDisposable, IObserver { - private readonly Dictionary, ListenerHandler>> handlers; - private readonly ITracer tracer; + private readonly Dictionary, ListenerHandler>> handlers; + private readonly ITracerFactory tracerFactory; private readonly Func sampler; private ConcurrentDictionary> subscriptions; private long disposed; private IDisposable subscription; - public DiagnosticSourceSubscriber(Dictionary, ListenerHandler>> handlers, ITracer tracer, Func sampler) + public DiagnosticSourceSubscriber(Dictionary, ListenerHandler>> handlers, ITracerFactory tracerFactory, Func sampler) { - this.subscriptions = new ConcurrentDictionary>(); - this.handlers = handlers ?? throw new ArgumentNullException(nameof(handlers)); - this.tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); + this.subscriptions = new ConcurrentDictionary>(); + this.handlers = handlers ?? throw new ArgumentNullException(nameof(handlers)); + this.tracerFactory = tracerFactory ?? throw new ArgumentNullException(nameof(tracerFactory)); this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler)); } @@ -56,7 +56,7 @@ public void OnNext(DiagnosticListener value) { this.subscriptions.GetOrAdd(value.Name, name => { - var dl = new DiagnosticSourceListener(this.handlers[value.Name](this.tracer, this.sampler)); + var dl = new DiagnosticSourceListener(this.handlers[value.Name](this.tracerFactory, this.sampler)); dl.Subscription = value.Subscribe(dl); return dl; }); @@ -75,8 +75,8 @@ public void OnError(Exception error) public void Dispose() { if (Interlocked.CompareExchange(ref this.disposed, 1, 0) == 1) - { - return; + { + return; } var subsCopy = this.subscriptions; diff --git a/src/OpenTelemetry/Collector/ListenerHandler.cs b/src/OpenTelemetry/Collector/ListenerHandler.cs index 7986967c24a..6b1a5d84e7f 100644 --- a/src/OpenTelemetry/Collector/ListenerHandler.cs +++ b/src/OpenTelemetry/Collector/ListenerHandler.cs @@ -26,10 +26,10 @@ public abstract class ListenerHandler protected readonly Func SamplerFactory; - public ListenerHandler(string sourceName, ITracer tracer, Func samplerFactory) + public ListenerHandler(string sourceName, Version version, ITracerFactory tracerFactory, Func samplerFactory) { this.SourceName = sourceName; - this.Tracer = tracer; + this.Tracer = tracerFactory.GetTracer(this.SourceName, $"semver:{version.Major}.{version.Minor}.{version.Revision}"); this.SamplerFactory = samplerFactory; } diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 34fe9077e49..5d5b471bca4 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -20,6 +20,7 @@ namespace OpenTelemetry.Trace using System.Diagnostics; using OpenTelemetry.Context; using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Resources; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; @@ -40,12 +41,10 @@ static Tracer() /// /// Span processor. /// Trace configuration. - public Tracer(SpanProcessor spanProcessor, TraceConfig traceConfig) + /// Resource describing the instrumentation library. + public Tracer(SpanProcessor spanProcessor, TraceConfig traceConfig, Resource libraryResource) + : this(spanProcessor, traceConfig, new BinaryFormat(), new TraceContextFormat(), libraryResource) { - this.spanProcessor = spanProcessor ?? throw new ArgumentNullException(nameof(spanProcessor)); - this.ActiveTraceConfig = traceConfig ?? throw new ArgumentNullException(nameof(traceConfig)); - this.BinaryFormat = new BinaryFormat(); - this.TextFormat = new TraceContextFormat(); } /// @@ -55,14 +54,18 @@ public Tracer(SpanProcessor spanProcessor, TraceConfig traceConfig) /// Trace configuration. /// Binary format context propagator. /// Text format context propagator. - public Tracer(SpanProcessor spanProcessor, TraceConfig traceConfig, IBinaryFormat binaryFormat, ITextFormat textFormat) + /// Resource describing the instrumentation library. + internal Tracer(SpanProcessor spanProcessor, TraceConfig traceConfig, IBinaryFormat binaryFormat, ITextFormat textFormat, Resource libraryResource) { this.spanProcessor = spanProcessor ?? throw new ArgumentNullException(nameof(spanProcessor)); this.ActiveTraceConfig = traceConfig ?? throw new ArgumentNullException(nameof(traceConfig)); this.BinaryFormat = binaryFormat ?? throw new ArgumentNullException(nameof(binaryFormat)); this.TextFormat = textFormat ?? throw new ArgumentNullException(nameof(textFormat)); + this.LibraryResource = libraryResource ?? throw new ArgumentNullException(nameof(libraryResource)); } + public Resource LibraryResource { get; } + /// public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan; diff --git a/src/OpenTelemetry/Trace/TracerFactory.cs b/src/OpenTelemetry/Trace/TracerFactory.cs new file mode 100644 index 00000000000..20ed36dfa00 --- /dev/null +++ b/src/OpenTelemetry/Trace/TracerFactory.cs @@ -0,0 +1,67 @@ +// +// Copyright 2018, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace OpenTelemetry.Trace +{ + using System.Collections.Generic; + using OpenTelemetry.Resources; + using OpenTelemetry.Trace.Config; + using OpenTelemetry.Trace.Export; + + /// + public sealed class TracerFactory : ITracerFactory + { + private readonly object lck = new object(); + private readonly SpanProcessor spanProcessor; + private readonly TraceConfig traceConfig; + private readonly Dictionary tracerRegistry = new Dictionary(); + + public TracerFactory(SpanProcessor spanProcessor = null, TraceConfig traceConfig = null) + { + this.spanProcessor = spanProcessor ?? Tracing.SpanProcessor; + this.traceConfig = traceConfig ?? Tracing.TraceConfig; + } + + /// + public ITracer GetTracer(string name, string version = null) + { + var labels = new Dictionary(); + if (!string.IsNullOrEmpty(name)) + { + labels.Add("name", name); + } + + if (!string.IsNullOrEmpty(version)) + { + labels.Add("version", version); + } + + ITracer tracer; + var key = $"{name}-{version}"; + lock (this.lck) + { + if (!this.tracerRegistry.ContainsKey(key)) + { + this.tracerRegistry[key] = new Tracer(this.spanProcessor, this.traceConfig, Resource.Create(labels)); + } + + tracer = this.tracerRegistry[key]; + } + + return tracer; + } + } +} diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index a57d44d9da1..09a1ec3ce09 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -22,33 +22,30 @@ namespace OpenTelemetry.Trace /// /// Class that manages a global instance of the . /// - public sealed class Tracing + public static class Tracing { - private static Tracing tracingValue = new Tracing(); - private static Tracer tracer; + private static TracerFactory tracerFactory; - internal Tracing() + static Tracing() { TraceConfig = TraceConfig.Default; - SpanProcessor = new BatchingSpanProcessor(new NoopSpanExporter()); - - tracer = new Tracer(SpanProcessor, TraceConfig); + tracerFactory = new TracerFactory(SpanProcessor, TraceConfig); } /// /// Gets the tracer to record spans. /// - public static ITracer Tracer => (ITracer)tracer; - + public static ITracerFactory TracerFactory => tracerFactory; + /// /// Gets the exporter to use to upload spans. /// - public static SpanProcessor SpanProcessor { get; private set; } + public static SpanProcessor SpanProcessor { get; } /// /// Gets the trace config. /// - public static TraceConfig TraceConfig { get; private set; } + public static TraceConfig TraceConfig { get; } } } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index 20e77c56a63..ba857db71d5 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Collector.AspNetCore.Tests { using Xunit; @@ -47,7 +49,7 @@ public BasicTests(WebApplicationFactory factory) public async Task SuccessfulTemplateControllerCallGeneratesASpan() { var panProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(panProcessor.Object, TraceConfig.Default); + var tracer = new Tracer(panProcessor.Object, TraceConfig.Default, Resource.Empty); void ConfigureTestServices(IServiceCollection services) => services.AddSingleton(tracer); @@ -103,7 +105,7 @@ public async Task SuccessfulTemplateControllerCallUsesParentContext() Tracestate.Empty )); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default, new BinaryFormat(), tf.Object); + var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default, new BinaryFormat(), tf.Object, Resource.Empty); // Arrange using (var client = this.factory diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index 0e48b0ea541..3ce007fa147 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Collector.AspNetCore.Tests { using Xunit; @@ -55,7 +57,7 @@ public override async Task ProcessAsync(HttpContext context) public async Task SuccessfulTemplateControllerCallGeneratesASpan() { var spanProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default); + var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default, Resource.Empty); // Arrange using (var client = this.factory diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs index b8e67e13710..04fc3dc2dae 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -15,6 +15,7 @@ // using System.Linq; +using OpenTelemetry.Resources; namespace OpenTelemetry.Collector.Dependencies.Tests { @@ -51,7 +52,7 @@ public HttpClientTests() public async Task HttpDependenciesCollectorInjectsHeadersAsync() { var spanProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default); + var tracerFactory = new TracerFactory(spanProcessor.Object); var request = new HttpRequestMessage { @@ -64,7 +65,7 @@ public async Task HttpDependenciesCollectorInjectsHeadersAsync() .Start(); parent.TraceStateString = "k1=v1,k2=v2"; - using (new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) + using (new DependenciesCollector(new DependenciesCollectorOptions(), tracerFactory, Samplers.AlwaysSample)) using (var c = new HttpClient()) { await c.SendAsync(request); @@ -91,7 +92,7 @@ public async Task HttpDependenciesCollectorInjectsHeadersAsync() public async Task HttpDependenciesCollectorBacksOffIfAlreadyInstrumented() { var spanProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default); + var tracerFactory = new TracerFactory(spanProcessor.Object); var request = new HttpRequestMessage { @@ -101,7 +102,7 @@ public async Task HttpDependenciesCollectorBacksOffIfAlreadyInstrumented() request.Headers.Add("traceparent", "00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"); - using (new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) + using (new DependenciesCollector(new DependenciesCollectorOptions(), tracerFactory, Samplers.AlwaysSample)) using (var c = new HttpClient()) { await c.SendAsync(request); diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index 424e57243e7..4a6538a0961 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Collector.Dependencies.Tests { using Moq; @@ -93,12 +95,12 @@ public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpOutTestCase tc) out var port); var spanProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default); + var tracerFactory = new TracerFactory(spanProcessor.Object); tc.url = NormalizeValues(tc.url, host, port); using (serverLifeTime) { - using (var dc = new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) + using (var dc = new DependenciesCollector(new DependenciesCollectorOptions(), tracerFactory, Samplers.AlwaysSample)) { try diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index 66b905a92a8..824f341b163 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -15,6 +15,8 @@ // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation { using System; @@ -32,7 +34,7 @@ public class RedisProfilerEntryToSpanConverterTests public RedisProfilerEntryToSpanConverterTests() { - tracer = new Tracer(new SimpleSpanProcessor(new NoopSpanExporter()), TraceConfig.Default); + tracer = new Tracer(new SimpleSpanProcessor(new NoopSpanExporter()), TraceConfig.Default, Resource.Empty); } [Fact] diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs index 330d3a6f6cf..efca37e49d3 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Collector.StackExchangeRedis { using Moq; @@ -30,7 +32,7 @@ public class StackExchangeRedisCallsCollectorTests public async void ProfilerSessionUsesTheSameDefault() { var spanProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default); + var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default, Resource.Empty); using (var collector = new StackExchangeRedisCallsCollector(tracer)) { diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsTraceExporterTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsTraceExporterTests.cs index 83461dc790c..2bd77f826b3 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsTraceExporterTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsTraceExporterTests.cs @@ -1648,7 +1648,7 @@ internal static Span CreateTestSpan(string name, SpanKind kind, Status status) { - var spanBuilder = Tracing.Tracer + var spanBuilder = Tracing.TracerFactory.GetTracer("") .SpanBuilder(name); if (parentSpanId != default) diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs index 5628c6e8b66..a6d60f4b7c8 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs @@ -356,7 +356,7 @@ internal static Span CreateTestSpan(bool setAttributes = true, ActivityTraceFlags.Recorded, Tracestate.Empty)); - var span = (Span)Tracing.Tracer + var span = (Span)Tracing.TracerFactory.GetTracer("") .SpanBuilder("Name") .SetParent(SpanContext.Create(traceId, parentSpanId, ActivityTraceFlags.Recorded, Tracestate.Empty)) .SetSpanKind(SpanKind.Client) diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs index da594764d6f..26a872fbc79 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs @@ -100,7 +100,7 @@ private Span CreateTestSpan() ActivityTraceFlags.Recorded, Tracestate.Empty)); - var span = (Span)Tracing.Tracer + var span = (Span)Tracing.TracerFactory.GetTracer("") .SpanBuilder("Name") .SetParent(SpanContext.Create(traceId, parentSpanId, ActivityTraceFlags.Recorded, Tracestate.Empty)) .SetSpanKind(SpanKind.Client) diff --git a/test/OpenTelemetry.Exporter.LightStep.Tests/LightStepSpanConverterTest.cs b/test/OpenTelemetry.Exporter.LightStep.Tests/LightStepSpanConverterTest.cs index f66f0ab6b8b..90e818f6823 100644 --- a/test/OpenTelemetry.Exporter.LightStep.Tests/LightStepSpanConverterTest.cs +++ b/test/OpenTelemetry.Exporter.LightStep.Tests/LightStepSpanConverterTest.cs @@ -66,7 +66,7 @@ public void AllPropertiesShouldTranslate() var link = Link.FromSpanContext(SpanContext.Create( traceId, linkedSpanId, ActivityTraceFlags.Recorded, Tracestate.Empty)); - var span = (Span)Tracing.Tracer + var span = (Span)Tracing.TracerFactory.GetTracer("") .SpanBuilder("Test") .SetParent(SpanContext.Create(traceId, parentId, ActivityTraceFlags.Recorded, Tracestate.Empty)) .SetSpanKind(SpanKind.Client) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 08e6dd9c81d..8440376f13d 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Trace.Test { using System; @@ -38,7 +40,7 @@ public class SpanBuilderTest : IDisposable private readonly ITracer tracer; public SpanBuilderTest() { - tracer = new Tracer(spanProcessor, alwaysSampleTraceConfig); + tracer = new Tracer(spanProcessor, alwaysSampleTraceConfig, Resource.Empty); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs new file mode 100644 index 00000000000..e037257b72e --- /dev/null +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs @@ -0,0 +1,75 @@ +// +// Copyright 2018, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using OpenTelemetry.Resources; + +namespace OpenTelemetry.Trace.Test +{ + using System; + using OpenTelemetry.Trace.Config; + using OpenTelemetry.Trace.Export; + using OpenTelemetry.Trace.Sampler; + + using Xunit; + + public class TracerFactoryTest + { + private TracerFactory tracerFactory = new TracerFactory(); + + [Fact] + public void GetTracerWithEmptyNameAndVersion() + { + var tracer = (Tracer)tracerFactory.GetTracer(""); + Assert.False(tracer.LibraryResource.Labels.ContainsKey("name")); + Assert.False(tracer.LibraryResource.Labels.ContainsKey("version")); + } + + [Fact] + public void GetTracerWithEmptyVersion() + { + var tracer = (Tracer)tracerFactory.GetTracer("foo"); + Assert.Equal("foo", tracer.LibraryResource.Labels["name"]); + Assert.False(tracer.LibraryResource.Labels.ContainsKey("version")); + } + + [Fact] + public void GetTracerWithNameAndVersion() + { + var tracer = (Tracer)tracerFactory.GetTracer("foo", "semver:1.2.3"); + Assert.Equal("foo", tracer.LibraryResource.Labels["name"]); + Assert.Equal("semver:1.2.3", tracer.LibraryResource.Labels["version"]); + } + + [Fact] + public void FactoryReturnsSameTracerForGivenNameAndVersion() + { + var tracer1 = tracerFactory.GetTracer("foo", "semver:1.2.3"); + var tracer2 = tracerFactory.GetTracer("foo"); + var tracer3 = tracerFactory.GetTracer("foo", "semver:2.3.4"); + var tracer4 = tracerFactory.GetTracer("bar", "semver:1.2.3"); + var tracer5 = tracerFactory.GetTracer("foo", "semver:1.2.3"); + var tracer6 = tracerFactory.GetTracer(""); + var tracer7 = tracerFactory.GetTracer(null); + + Assert.NotEqual(tracer1, tracer2); + Assert.NotEqual(tracer1, tracer3); + Assert.NotEqual(tracer1, tracer4); + Assert.Equal(tracer1, tracer5); + Assert.NotEqual(tracer5, tracer6); + Assert.Equal(tracer6, tracer7); + } + } +} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index 9289a99a608..d0447e937e6 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -15,6 +15,7 @@ // using OpenTelemetry.Context.Propagation; +using OpenTelemetry.Resources; namespace OpenTelemetry.Trace.Test { @@ -37,7 +38,7 @@ public TracerTest() { spanProcessor = new SimpleSpanProcessor(new NoopSpanExporter()); traceConfig = TraceConfig.Default; - tracer = new Tracer(spanProcessor, traceConfig); + tracer = new Tracer(spanProcessor, traceConfig, Resource.Empty); } [Fact] @@ -51,15 +52,17 @@ public void CreateSpanBuilder() public void BadConstructorArgumentsThrow() { var noopProc = new SimpleSpanProcessor(new NoopSpanExporter()); - Assert.Throws(() => new Tracer(null, TraceConfig.Default)); - Assert.Throws(() => new Tracer(null, TraceConfig.Default, new BinaryFormat(), new TraceContextFormat())); + Assert.Throws(() => new Tracer(null, TraceConfig.Default, Resource.Empty)); + Assert.Throws(() => new Tracer(null, TraceConfig.Default, new BinaryFormat(), new TraceContextFormat(), Resource.Empty)); - Assert.Throws(() => new Tracer(noopProc, null)); - Assert.Throws(() => new Tracer(noopProc, null, new BinaryFormat(), new TraceContextFormat())); + Assert.Throws(() => new Tracer(noopProc, null, Resource.Empty)); + Assert.Throws(() => new Tracer(noopProc, null, new BinaryFormat(), new TraceContextFormat(), Resource.Empty)); - Assert.Throws(() => new Tracer(noopProc, TraceConfig.Default, null, new TraceContextFormat())); - Assert.Throws(() => new Tracer(noopProc, TraceConfig.Default, new BinaryFormat(), null)); + Assert.Throws(() => new Tracer(noopProc, TraceConfig.Default, null, new TraceContextFormat(), Resource.Empty)); + Assert.Throws(() => new Tracer(noopProc, TraceConfig.Default, new BinaryFormat(), null, Resource.Empty)); + Assert.Throws(() => new Tracer(noopProc, TraceConfig.Default, null)); + Assert.Throws(() => new Tracer(noopProc, TraceConfig.Default, new BinaryFormat(), new TraceContextFormat(), null)); } [Fact] @@ -107,7 +110,7 @@ public void GetBinaryFormat() public void GetActiveConfig() { var config = new TraceConfig(Samplers.NeverSample); - var tracer = new Tracer(spanProcessor, config); + var tracer = new Tracer(spanProcessor, config, Resource.Empty); Assert.Equal(config, tracer.ActiveTraceConfig); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs index 34cddc5e143..df59269f6ad 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs @@ -23,9 +23,9 @@ namespace OpenTelemetry.Trace.Test public class TracingTest { [Fact] - public void DefaultTracer() + public void DefaultTracerFactory() { - Assert.Equal(typeof(Tracer), Tracing.Tracer.GetType()); + Assert.Equal(typeof(TracerFactory), Tracing.TracerFactory.GetType()); } [Fact] From c53d101ebb65f6177b947362cc1241c209ff978f Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Fri, 27 Sep 2019 13:00:39 +0200 Subject: [PATCH 2/4] Improve Named Tracers implementation. LoggingTracer now prints "LibraryResource" information (name + version) Make "LibraryResource" available on Spans. --- .../LoggingTracer/LoggingTracer.cs | 14 ++- .../LoggingTracer/LoggingTracerFactory.cs | 18 ++- src/OpenTelemetry/Trace/Span.cs | 16 ++- src/OpenTelemetry/Trace/SpanBuilder.cs | 8 +- src/OpenTelemetry/Trace/Tracer.cs | 2 +- src/OpenTelemetry/Trace/TracerFactory.cs | 20 ++-- .../BasicTests.cs | 10 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 4 +- .../Impl/Trace/CurrentSpanUtilsTest.cs | 29 +++-- .../Export/BatchingSpanProcessorTests.cs | 11 +- .../Trace/Export/SimpleSpanProcessorTests.cs | 14 ++- .../Impl/Trace/SpanBuilderTest.cs | 112 +++++++++--------- .../Impl/Trace/SpanTest.cs | 59 ++++++--- .../Impl/Trace/TracerFactoryTest.cs | 16 ++- 14 files changed, 214 insertions(+), 119 deletions(-) diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs b/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs index 8c25a51aa76..924a96147ac 100644 --- a/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs @@ -2,6 +2,9 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +using System.Linq; +using OpenTelemetry.Resources; + namespace LoggingTracer { using OpenTelemetry.Context; @@ -10,9 +13,12 @@ namespace LoggingTracer public class LoggingTracer : ITracer { - internal LoggingTracer() + private string prefix; + + internal LoggingTracer(Resource libraryResource) { - Logger.Log($"Tracer.ctor()"); + this.prefix = "Tracer(" + string.Join(", ", libraryResource.Labels.Select(l => l.Value).ToArray()) + ")"; + Logger.Log($"{prefix}.ctor()"); } public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan; @@ -23,13 +29,13 @@ internal LoggingTracer() public ISpanBuilder SpanBuilder(string spanName) { - Logger.Log($"Tracer.SpanBuilder({spanName})"); + Logger.Log($"{prefix}.SpanBuilder({spanName})"); return new LoggingSpanBuilder(spanName, SpanKind.Internal); } public IScope WithSpan(ISpan span) { - Logger.Log("Tracer.WithSpan"); + Logger.Log($"{prefix}.WithSpan"); return new CurrentSpanUtils.LoggingScope(span); } } diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs b/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs index 1a5cd7d82f8..9f5bc92a6bc 100644 --- a/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracerFactory.cs @@ -2,6 +2,9 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +using System.Collections.Generic; +using OpenTelemetry.Resources; + namespace LoggingTracer { using OpenTelemetry.Context; @@ -13,7 +16,20 @@ public class LoggingTracerFactory : ITracerFactory public ITracer GetTracer(string name, string version = null) { Logger.Log($"TracerFactory.GetTracer('{name}', '{version}')"); - return new LoggingTracer(); + + // Create a Resource from "name" and "version" information. + var labels = new Dictionary(); + if (!string.IsNullOrEmpty(name)) + { + labels.Add("name", name); + if (!string.IsNullOrEmpty(version)) + { + labels.Add("version", version); + } + } + var libraryResource = Resource.Create(labels); + + return new LoggingTracer(libraryResource); } } } diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index 585a2115a78..e88554dce78 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -20,6 +20,7 @@ namespace OpenTelemetry.Trace using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using OpenTelemetry.Resources; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; @@ -48,7 +49,8 @@ internal Span( TraceConfig traceConfig, SpanProcessor spanProcessor, DateTimeOffset startTimestamp, - bool ownsActivity) + bool ownsActivity, + Resource libraryResource) { this.Activity = activity; this.spanContext = new Lazy(() => SpanContext.Create( @@ -63,6 +65,7 @@ internal Span( this.OwnsActivity = ownsActivity; this.IsRecordingEvents = this.Activity.Recorded; this.startTimestamp = startTimestamp; + this.LibraryResource = libraryResource; if (this.IsRecordingEvents) { @@ -140,12 +143,17 @@ public Status Status public DateTimeOffset EndTimestamp => this.endTimestamp; /// - /// Gets or sets span kind. + /// Gets the span kind. /// - public SpanKind? Kind { get; set; } + public SpanKind? Kind { get; } + /// + /// Gets the "Library Resource" (name + version) associated with the Tracer that produced this span. + /// + public Resource LibraryResource { get; } + internal bool OwnsActivity { get; } - + private Status StatusWithDefault => this.status.IsValid ? this.status : Status.Ok; /// diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index a3518bda289..9d6068a0365 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -20,6 +20,7 @@ namespace OpenTelemetry.Trace using System.Collections.Generic; using System.Diagnostics; using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Resources; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; @@ -41,12 +42,14 @@ public class SpanBuilder : ISpanBuilder private List links; private bool recordEvents; private DateTimeOffset startTimestamp; + private Resource libraryResource; - internal SpanBuilder(string name, SpanProcessor spanProcessor, TraceConfig traceConfig) + internal SpanBuilder(string name, SpanProcessor spanProcessor, TraceConfig traceConfig, Resource libraryResource) { this.name = name ?? throw new ArgumentNullException(nameof(name)); this.spanProcessor = spanProcessor ?? throw new ArgumentNullException(nameof(spanProcessor)); this.traceConfig = traceConfig ?? throw new ArgumentNullException(nameof(traceConfig)); + this.libraryResource = libraryResource ?? throw new ArgumentNullException(nameof(libraryResource)); } private enum ContextSource @@ -251,7 +254,8 @@ public ISpan StartSpan() this.traceConfig, this.spanProcessor, this.startTimestamp, - ownsActivity: this.contextSource != ContextSource.Activity); + ownsActivity: this.contextSource != ContextSource.Activity, + this.libraryResource); if (activityForSpan.OperationName != this.name) { diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 5d5b471bca4..0d3593beb23 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -80,7 +80,7 @@ internal Tracer(SpanProcessor spanProcessor, TraceConfig traceConfig, IBinaryFor /// public ISpanBuilder SpanBuilder(string spanName) { - return new SpanBuilder(spanName, this.spanProcessor, this.ActiveTraceConfig); + return new SpanBuilder(spanName, this.spanProcessor, this.ActiveTraceConfig, this.LibraryResource); } public IScope WithSpan(ISpan span) diff --git a/src/OpenTelemetry/Trace/TracerFactory.cs b/src/OpenTelemetry/Trace/TracerFactory.cs index 20ed36dfa00..9c45cbf12dc 100644 --- a/src/OpenTelemetry/Trace/TracerFactory.cs +++ b/src/OpenTelemetry/Trace/TracerFactory.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace { using System.Collections.Generic; + using OpenTelemetry.Context.Propagation; using OpenTelemetry.Resources; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; @@ -34,28 +35,31 @@ public TracerFactory(SpanProcessor spanProcessor = null, TraceConfig traceConfig this.spanProcessor = spanProcessor ?? Tracing.SpanProcessor; this.traceConfig = traceConfig ?? Tracing.TraceConfig; } - + + internal ITextFormat TextFormat { get; set; } + /// public ITracer GetTracer(string name, string version = null) { var labels = new Dictionary(); + var key = string.Empty; if (!string.IsNullOrEmpty(name)) { labels.Add("name", name); - } - - if (!string.IsNullOrEmpty(version)) - { - labels.Add("version", version); + if (!string.IsNullOrEmpty(version)) + { + labels.Add("version", version); + } + + key = $"{name}-{version}"; } ITracer tracer; - var key = $"{name}-{version}"; lock (this.lck) { if (!this.tracerRegistry.ContainsKey(key)) { - this.tracerRegistry[key] = new Tracer(this.spanProcessor, this.traceConfig, Resource.Create(labels)); + this.tracerRegistry[key] = new Tracer(this.spanProcessor, Tracing.TraceConfig, null, this.TextFormat, Resource.Create(labels)); } tracer = this.tracerRegistry[key]; diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index ba857db71d5..8f26f4579a4 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -49,10 +49,10 @@ public BasicTests(WebApplicationFactory factory) public async Task SuccessfulTemplateControllerCallGeneratesASpan() { var panProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(panProcessor.Object, TraceConfig.Default, Resource.Empty); + var tracerFactory = new TracerFactory(panProcessor.Object); void ConfigureTestServices(IServiceCollection services) => - services.AddSingleton(tracer); + services.AddSingleton(tracerFactory); // Arrange using (var client = this.factory @@ -105,16 +105,14 @@ public async Task SuccessfulTemplateControllerCallUsesParentContext() Tracestate.Empty )); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default, new BinaryFormat(), tf.Object, Resource.Empty); + var tracerFactory = new TracerFactory(spanProcessor.Object) { TextFormat = tf.Object }; // Arrange using (var client = this.factory .WithWebHostBuilder(builder => builder.ConfigureTestServices((services) => { - services.AddSingleton(tracer); - services.AddSingleton(tf.Object); - services.AddSingleton(new BinaryFormat()); + services.AddSingleton(tracerFactory); })) .CreateClient()) { diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index 3ce007fa147..f4fb233d227 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -57,7 +57,7 @@ public override async Task ProcessAsync(HttpContext context) public async Task SuccessfulTemplateControllerCallGeneratesASpan() { var spanProcessor = new Mock(new NoopSpanExporter()); - var tracer = new Tracer(spanProcessor.Object, TraceConfig.Default, Resource.Empty); + var tracerFactory = new TracerFactory(spanProcessor.Object); // Arrange using (var client = this.factory @@ -65,7 +65,7 @@ public async Task SuccessfulTemplateControllerCallGeneratesASpan() builder.ConfigureTestServices((IServiceCollection services) => { services.AddSingleton(new TestCallbackMiddlewareImpl()); - services.AddSingleton(tracer); + services.AddSingleton(tracerFactory); })) .CreateClient()) { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index 17d377f6f44..eb1344e4155 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -15,6 +15,7 @@ // using OpenTelemetry.Trace.Internal; +using OpenTelemetry.Resources; namespace OpenTelemetry.Trace.Test { @@ -68,7 +69,8 @@ public void WithSpan_CloseDetaches(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); using (CurrentSpanUtils.WithSpan(span, stopSpan)) @@ -102,7 +104,8 @@ public void WithSpan_NotOwningActivity(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - false); + false, + Resource.Empty); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); using (CurrentSpanUtils.WithSpan(span, stopSpan)) @@ -135,7 +138,9 @@ public void WithSpan_NoopOnBrokenScope(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); + var parentScope = CurrentSpanUtils.WithSpan(parentSpan, stopSpan); var childActivity = new Activity("child").Start(); @@ -146,7 +151,8 @@ public void WithSpan_NoopOnBrokenScope(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); @@ -180,7 +186,8 @@ public void WithSpan_RestoresParentScope(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); var parentScope = CurrentSpanUtils.WithSpan(parentSpan, stopSpan); @@ -192,7 +199,8 @@ public void WithSpan_RestoresParentScope(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); @@ -218,7 +226,8 @@ public void WithSpan_SameActivityCreateScopeTwice() TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); using(CurrentSpanUtils.WithSpan(span, true)) using(CurrentSpanUtils.WithSpan(span, true)) @@ -242,7 +251,8 @@ public void WithSpan_NullActivity() TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); activity.Stop(); @@ -276,7 +286,8 @@ public void WithSpan_WrongActivity(bool stopSpan, bool recordEvents) TraceConfig.Default, spanProcessor, default, - true); + true, + Resource.Empty); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); using (CurrentSpanUtils.WithSpan(span, stopSpan)) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/BatchingSpanProcessorTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/BatchingSpanProcessorTests.cs index 043b6bdf8be..30e602cc465 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/BatchingSpanProcessorTests.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/BatchingSpanProcessorTests.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Trace.Export.Test { using System; @@ -56,7 +58,8 @@ private Span CreateSampledEndedSpan(string spanName) TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - default); + default, + Resource.Empty); span.End(); return span; } @@ -74,7 +77,8 @@ private Span CreateNotSampledEndedSpan(string spanName) TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); span.End(); return span; } @@ -242,7 +246,8 @@ public void ProcessorDoesNotBlockOnExporter() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - default); + default, + Resource.Empty); // does not block var sw = Stopwatch.StartNew(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SimpleSpanProcessorTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SimpleSpanProcessorTests.cs index 13bd927daf9..b509337e782 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SimpleSpanProcessorTests.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SimpleSpanProcessorTests.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Trace.Export.Test { using System; @@ -53,7 +55,8 @@ private Span CreateSampledEndedSpan(string spanName) TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - default); + default, + Resource.Empty); span.End(); return span; } @@ -71,7 +74,8 @@ private Span CreateNotSampledEndedSpan(string spanName) TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); span.End(); return span; } @@ -100,7 +104,8 @@ public void ThrowsInExporter() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - default); + default, + Resource.Empty); // does not throw span.End(); @@ -125,7 +130,8 @@ public void ProcessorDoesNotBlockOnExporter() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - default); + default, + Resource.Empty); // does not block var sw = Stopwatch.StartNew(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 8440376f13d..ea5da389223 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -46,7 +46,7 @@ public SpanBuilderTest() [Fact] public void StartSpanNullParent() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetNoParent() .StartSpan(); @@ -73,7 +73,7 @@ public void StartSpanLastParentWins1() ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var span = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetNoParent() .SetParent(spanContext) .StartSpan(); @@ -92,7 +92,7 @@ public void StartSpanLastParentWins2() ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var span = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetParent(spanContext) .SetNoParent() .StartSpan(); @@ -110,10 +110,10 @@ public void StartSpanLastParentWins3() ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var rootSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .StartSpan(); - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetParent(spanContext) .SetParent(rootSpan) .StartSpan(); @@ -131,10 +131,10 @@ public void StartSpanLastParentWins4() ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var rootSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .StartSpan(); - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetParent(rootSpan) .SetParent(spanContext) .StartSpan(); @@ -156,7 +156,7 @@ public void StartSpanLastParentWins5() .SetIdFormat(ActivityIdFormat.W3C) .Start(); - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetParent(spanContext) .SetParent(activity) .StartSpan(); @@ -178,7 +178,7 @@ public void StartSpanLastParentWins6() .SetIdFormat(ActivityIdFormat.W3C) .Start(); - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetParent(spanContext) .SetCreateChild(false) .StartSpan(); @@ -200,7 +200,7 @@ public void StartSpanLastParentWins7() .SetIdFormat(ActivityIdFormat.W3C) .Start(); - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetCreateChild(false) .SetParent(spanContext) .StartSpan(); @@ -213,7 +213,7 @@ public void StartSpanLastParentWins7() [Fact] public void StartSpanNullParentWithRecordEvents() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetRecordEvents(true) @@ -229,7 +229,7 @@ public void StartSpanNullParentWithRecordEvents() public void StartSpanWithStartTimestamp() { var timestamp = DateTime.UtcNow.AddSeconds(-100); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.AlwaysSample) .SetStartTimestamp(timestamp) @@ -242,7 +242,7 @@ public void StartSpanWithStartTimestamp() public void StartSpanWithImplicitTimestamp() { var timestamp = PreciseTimestamp.GetUtcNow(); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.AlwaysSample) .StartSpan(); @@ -253,7 +253,7 @@ public void StartSpanWithImplicitTimestamp() [Fact] public void StartSpanNullParentNoRecordOptions() { - var span = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetNoParent() @@ -266,7 +266,7 @@ public void StartSpanNullParentNoRecordOptions() [Fact] public void StartChildSpan() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetNoParent() .StartSpan(); @@ -275,7 +275,7 @@ public void StartChildSpan() Assert.True(rootSpan.IsRecordingEvents); Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); - var childSpan = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(rootSpan) .StartSpan(); @@ -293,7 +293,7 @@ public void StartSpanInScopeOfCurrentActivity() .Start(); parentActivity.TraceStateString = "k1=v1,k2=v2"; - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .StartSpan(); @@ -316,7 +316,7 @@ public void StartSpanInScopeOfCurrentActivityRecorded() .Start(); parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .StartSpan(); @@ -333,7 +333,7 @@ public void StartSpanInScopeOfCurrentActivityNoParent() var parentActivity = new Activity(SpanName).Start(); parentActivity.TraceStateString = "k1=v1,k2=v2"; - var childSpan = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetNoParent() .StartSpan(); @@ -359,7 +359,7 @@ public void StartSpanFromExplicitActivity() parentActivity.TraceStateString = "k1=v1,k2=v2"; parentActivity.Stop(); - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(parentActivity) .StartSpan(); @@ -386,7 +386,7 @@ public void StartSpanFromExplicitRecordedActivity() parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; parentActivity.Stop(); - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(parentActivity) .StartSpan(); @@ -405,7 +405,7 @@ public void StartSpanFromCurrentActivity() .Start(); activity.TraceStateString = "k1=v1,k2=v2"; - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetCreateChild(false) .StartSpan(); @@ -430,7 +430,7 @@ public void StartSpanFromCurrentRecordedActivity() .Start(); activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; - var span = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetCreateChild(false) .StartSpan(); @@ -446,7 +446,7 @@ public void StartSpanFromCurrentRecordedActivity() [Fact] public void StartSpan_ExplicitNoParent() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetNoParent() .StartSpan(); @@ -467,7 +467,7 @@ public void StartSpan_ExplicitNoParent() [Fact] public void StartSpan_NoParent() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .StartSpan(); @@ -480,7 +480,7 @@ public void StartSpan_NoParent() [Fact] public void StartSpan_BlankSpanParent() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(BlankSpan.Instance) .StartSpan(); @@ -494,7 +494,7 @@ public void StartSpan_BlankSpanParent() [Fact] public void StartSpan_BlankSpanContextParent() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Blank) .StartSpan(); @@ -510,7 +510,7 @@ public void StartSpan_BlankSpanContextParent() [Fact] public void StartSpan_CurrentSpanParent() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetParent( SpanContext.Create( ActivityTraceId.CreateRandom(), @@ -520,7 +520,7 @@ public void StartSpan_CurrentSpanParent() .StartSpan(); using (tracer.WithSpan(rootSpan)) { - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .StartSpan(); Assert.True(childSpan.Context.IsValid); @@ -533,11 +533,11 @@ public void StartSpan_CurrentSpanParent() [Fact] public void StartSpan_NoParentInScopeOfCurrentSpan() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .StartSpan(); using (tracer.WithSpan(rootSpan)) { - var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = (Span)new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetNoParent() .StartSpan(); @@ -550,7 +550,7 @@ public void StartSpan_NoParentInScopeOfCurrentSpan() [Fact] public void StartSpanInvalidParent() { - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Blank) .StartSpan(); @@ -571,7 +571,7 @@ public void StartRemoteSpan() ActivityTraceFlags.None, Tracestate.Builder.Set("k1", "v1").Build()); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(spanContext) .SetRecordEvents(true) @@ -594,7 +594,7 @@ public void StartSpan_WithLink() ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty)); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .AddLink(link) .StartSpan(); @@ -616,7 +616,7 @@ public void StartSpan_WithLinkFromActivity() var contextLink = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .AddLink(contextLink) .StartSpan(); @@ -643,7 +643,7 @@ public void StartSpan_WithLinkFromSpanContextAndAttributes() ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .AddLink(linkContext, new Dictionary { ["k"] = "v", }) .StartSpan(); @@ -670,7 +670,7 @@ public void StartSpan_WithLinkFromSpanContext() ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .AddLink(linkContext) .StartSpan(); @@ -689,7 +689,7 @@ public void StartSpan_WithLinkFromSpanContext() public void StartRootSpan_WithSpecifiedSampler() { // Apply given sampler before default sampler for root spans. - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetNoParent() .SetSampler(Samplers.NeverSample) @@ -703,7 +703,7 @@ public void StartRootSpan_WithSpecifiedSampler() public void StartRootSpan_WithoutSpecifiedSampler() { // Apply default sampler (always true in the tests) for root spans. - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetNoParent() .StartSpan(); @@ -715,7 +715,7 @@ public void StartRootSpan_WithoutSpecifiedSampler() [Fact] public void StartRemoteChildSpan_WithSpecifiedSampler() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.AlwaysSample) .SetNoParent() @@ -724,7 +724,7 @@ public void StartRemoteChildSpan_WithSpecifiedSampler() Assert.True(rootSpan.Context.IsValid); Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); // Apply given sampler before default sampler for spans with remote parent. - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetParent(rootSpan.Context) @@ -738,7 +738,7 @@ public void StartRemoteChildSpan_WithSpecifiedSampler() [Fact] public void StartRemoteChildSpan_WithoutSpecifiedSampler() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetNoParent() @@ -747,7 +747,7 @@ public void StartRemoteChildSpan_WithoutSpecifiedSampler() Assert.True(rootSpan.Context.IsValid); Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); // Apply default sampler (always true in the tests) for spans with remote parent. - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(rootSpan.Context) .StartSpan(); @@ -760,7 +760,7 @@ public void StartRemoteChildSpan_WithoutSpecifiedSampler() [Fact] public void StartChildSpan_WithSpecifiedSampler() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.AlwaysSample) .SetNoParent() @@ -770,7 +770,7 @@ public void StartChildSpan_WithSpecifiedSampler() Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); // Apply the given sampler for child spans. - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetParent(rootSpan) @@ -784,7 +784,7 @@ public void StartChildSpan_WithSpecifiedSampler() [Fact] public void StartChildSpan_WithoutSpecifiedSampler() { - var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetNoParent() @@ -794,7 +794,7 @@ public void StartChildSpan_WithoutSpecifiedSampler() Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); // Don't apply the default sampler (always true) for child spans. - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(rootSpan) .StartSpan(); @@ -807,7 +807,7 @@ public void StartChildSpan_WithoutSpecifiedSampler() [Fact] public void StartChildSpan_SampledLinkedParent() { - var rootSpanUnsampled = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var rootSpanUnsampled = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.NeverSample) .SetNoParent() @@ -815,7 +815,7 @@ public void StartChildSpan_SampledLinkedParent() Assert.True((rootSpanUnsampled.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); var rootSpanSampled = - new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.AlwaysSample) .SetNoParent() @@ -823,7 +823,7 @@ public void StartChildSpan_SampledLinkedParent() Assert.True((rootSpanSampled.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); // Sampled because the linked parent is sampled. - var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + var childSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .AddLink(Link.FromSpanContext(rootSpanSampled.Context)) .SetParent(rootSpanUnsampled) @@ -845,7 +845,7 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() // If parent is sampled then the remote child must be sampled. var childSpan = - new SpanBuilder(SpanName, spanProcessor, new TraceConfig(ProbabilitySampler.Create(0.1))) + new SpanBuilder(SpanName, spanProcessor, new TraceConfig(ProbabilitySampler.Create(0.1)), Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Create( traceId, @@ -861,7 +861,7 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() // If parent is not sampled then the remote child must be not sampled. childSpan = - new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) + new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Create( traceId, @@ -879,11 +879,11 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() [Fact] public void SpanBuilder_BadArguments() { - Assert.Throws(() => new SpanBuilder(null, spanProcessor, alwaysSampleTraceConfig)); - Assert.Throws(() => new SpanBuilder(SpanName, null, alwaysSampleTraceConfig)); - Assert.Throws(() => new SpanBuilder(SpanName, spanProcessor, null)); + Assert.Throws(() => new SpanBuilder(null, spanProcessor, alwaysSampleTraceConfig, Resource.Empty)); + Assert.Throws(() => new SpanBuilder(SpanName, null, alwaysSampleTraceConfig, Resource.Empty)); + Assert.Throws(() => new SpanBuilder(SpanName, spanProcessor, null, Resource.Empty)); - var spanBuilder = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig); + var spanBuilder = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig, Resource.Empty); Assert.Throws(() => spanBuilder.SetParent((ISpan)null)); Assert.Throws(() => spanBuilder.SetParent((SpanContext)null)); Assert.Throws(() => spanBuilder.SetParent((Activity)null)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 42dd651e295..1e16517f4e9 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Resources; + namespace OpenTelemetry.Trace.Test { using System; @@ -52,6 +54,15 @@ public SpanTest() }; } + [Fact] + public void SpanHoldsSameLibraryResourceAsCreatingTracer() + { + var tracerFactory = new TracerFactory(); + var tracer = (Tracer)tracerFactory.GetTracer("foo", "semver:1.0.0"); + var span = (Span)tracer.SpanBuilder("some span").StartSpan(); + Assert.Equal(tracer.LibraryResource, span.LibraryResource); + } + [Fact] public void GetSpanContextFromActivity() { @@ -67,7 +78,8 @@ public void GetSpanContextFromActivity() TraceConfig.Default, spanProcessor, default, - false); + false, + Resource.Empty); Assert.NotNull(span.Context); Assert.Equal(activity.TraceId, span.Context.TraceId); Assert.Equal(activity.SpanId, span.Context.SpanId); @@ -91,7 +103,8 @@ public void GetSpanContextFromActivityRecordedWithParent() TraceConfig.Default, spanProcessor, default, - false); + false, + Resource.Empty); Assert.NotNull(span.Context); Assert.Equal(activity.TraceId, span.Context.TraceId); Assert.Equal(activity.SpanId, span.Context.SpanId); @@ -117,7 +130,8 @@ public void NoEventsRecordedAfterEnd() TraceConfig.Default, spanProcessor, spanStartTime, - false); + false, + Resource.Empty); var spanEndTime = PreciseTimestamp.GetUtcNow(); span.End(spanEndTime); // Check that adding trace events after Span#End() does not throw any exception and are not @@ -157,7 +171,8 @@ public void ImplicitTimestamps() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); var spanEndTime = PreciseTimestamp.GetUtcNow(); span.End(); @@ -188,7 +203,8 @@ public async Task ActiveSpan_Properties() TraceConfig.Default, spanProcessor, spanStartTime, - false); + false, + Resource.Empty); span.SetAttribute( "MySingleStringAttributeKey", @@ -261,7 +277,8 @@ public async Task EndedSpan_Properties() TraceConfig.Default, spanProcessor, spanStartTime, - false); + false, + Resource.Empty); span.SetAttribute( "MySingleStringAttributeKey", @@ -325,7 +342,8 @@ public void Status_ViaSetStatus() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); Assert.Equal(Status.Ok, span.Status); ((Span)span).Status = Status.Cancelled; @@ -351,7 +369,8 @@ public void status_ViaEndSpanOptions() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); Assert.Equal(Status.Ok, span.Status); ((Span)span).Status = Status.Cancelled; @@ -379,7 +398,8 @@ public void DroppingAttributes() traceConfig, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { IDictionary attributes = new Dictionary(); @@ -429,7 +449,8 @@ public void DroppingAndAddingAttributes() traceConfig, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { IDictionary attributes = new Dictionary(); @@ -496,7 +517,8 @@ public async Task DroppingEvents() traceConfig, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); var eventTimestamps = new DateTimeOffset[2 * maxNumberOfEvents]; @@ -539,7 +561,8 @@ public void DroppingLinks() traceConfig, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); var link = Link.FromSpanContext(contextLink); for (var i = 0; i < 2 * maxNumberOfLinks; i++) { @@ -575,7 +598,8 @@ public void BadArguments() TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - false); + false, + Resource.Empty); Assert.Throws(() => span.Status = new Status()); Assert.Throws(() => span.UpdateName(null)); @@ -611,7 +635,8 @@ public void EndSpanStopsActivity(bool recordEvents) TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - ownsActivity: true); + ownsActivity: true, + Resource.Empty); span.End(); Assert.Same(parentActivity, Activity.Current); @@ -636,7 +661,8 @@ public void EndSpanDoesNotStopActivityWhenDoesNotOwnIt(bool recordEvents) TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - ownsActivity: false); + ownsActivity: false, + Resource.Empty); span.End(); Assert.Equal(recordEvents, span.HasEnded); @@ -664,7 +690,8 @@ public void EndSpanStopActivity_NotCurrentActivity(bool recordEvents, bool ownsA TraceConfig.Default, spanProcessor, PreciseTimestamp.GetUtcNow(), - ownsActivity: ownsActivity); + ownsActivity: ownsActivity, + Resource.Empty); var anotherActivity = new Activity(SpanName).Start(); span.End(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs index e037257b72e..577bf7c7fd2 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerFactoryTest.cs @@ -30,7 +30,7 @@ public class TracerFactoryTest private TracerFactory tracerFactory = new TracerFactory(); [Fact] - public void GetTracerWithEmptyNameAndVersion() + public void GetTracer_NoName_NoVersion() { var tracer = (Tracer)tracerFactory.GetTracer(""); Assert.False(tracer.LibraryResource.Labels.ContainsKey("name")); @@ -38,7 +38,15 @@ public void GetTracerWithEmptyNameAndVersion() } [Fact] - public void GetTracerWithEmptyVersion() + public void GetTracer_NoName_Version() + { + var tracer = (Tracer)tracerFactory.GetTracer(null, "semver:1.0.0"); + Assert.False(tracer.LibraryResource.Labels.ContainsKey("name")); + Assert.False(tracer.LibraryResource.Labels.ContainsKey("version")); + } + + [Fact] + public void GetTracer_Name_NoVersion() { var tracer = (Tracer)tracerFactory.GetTracer("foo"); Assert.Equal("foo", tracer.LibraryResource.Labels["name"]); @@ -46,7 +54,7 @@ public void GetTracerWithEmptyVersion() } [Fact] - public void GetTracerWithNameAndVersion() + public void GetTracer_Name_Version() { var tracer = (Tracer)tracerFactory.GetTracer("foo", "semver:1.2.3"); Assert.Equal("foo", tracer.LibraryResource.Labels["name"]); @@ -63,6 +71,7 @@ public void FactoryReturnsSameTracerForGivenNameAndVersion() var tracer5 = tracerFactory.GetTracer("foo", "semver:1.2.3"); var tracer6 = tracerFactory.GetTracer(""); var tracer7 = tracerFactory.GetTracer(null); + var tracer8 = tracerFactory.GetTracer(null, "semver:1.2.3"); Assert.NotEqual(tracer1, tracer2); Assert.NotEqual(tracer1, tracer3); @@ -70,6 +79,7 @@ public void FactoryReturnsSameTracerForGivenNameAndVersion() Assert.Equal(tracer1, tracer5); Assert.NotEqual(tracer5, tracer6); Assert.Equal(tracer6, tracer7); + Assert.Equal(tracer7, tracer8); } } } From b5b10472b2e62df649821c12da800810ecebdea9 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Fri, 27 Sep 2019 13:54:36 +0200 Subject: [PATCH 3/4] Improved and refactored Tracer creation --- src/OpenTelemetry/Trace/TracerFactory.cs | 32 +++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/OpenTelemetry/Trace/TracerFactory.cs b/src/OpenTelemetry/Trace/TracerFactory.cs index 9c45cbf12dc..628def9e1ee 100644 --- a/src/OpenTelemetry/Trace/TracerFactory.cs +++ b/src/OpenTelemetry/Trace/TracerFactory.cs @@ -41,31 +41,33 @@ public TracerFactory(SpanProcessor spanProcessor = null, TraceConfig traceConfig /// public ITracer GetTracer(string name, string version = null) { - var labels = new Dictionary(); - var key = string.Empty; - if (!string.IsNullOrEmpty(name)) + lock (this.lck) { - labels.Add("name", name); - if (!string.IsNullOrEmpty(version)) + var key = string.IsNullOrEmpty(name) ? string.Empty : $"{name}-{version}"; + if (!this.tracerRegistry.TryGetValue(key, out var tracer)) { - labels.Add("version", version); + var labels = CreateLibraryResourceLabels(name, version); + tracer = new Tracer(this.spanProcessor, this.traceConfig, null, this.TextFormat, Resource.Create(labels)); + this.tracerRegistry.Add(key, tracer); } - key = $"{name}-{version}"; + return tracer; } + } - ITracer tracer; - lock (this.lck) + private static Dictionary CreateLibraryResourceLabels(string name, string version) + { + var labels = new Dictionary(); + if (!string.IsNullOrEmpty(name)) { - if (!this.tracerRegistry.ContainsKey(key)) + labels.Add("name", name); + if (!string.IsNullOrEmpty(version)) { - this.tracerRegistry[key] = new Tracer(this.spanProcessor, Tracing.TraceConfig, null, this.TextFormat, Resource.Create(labels)); + labels.Add("version", version); } - - tracer = this.tracerRegistry[key]; } - - return tracer; + + return labels; } } } From e71bf65a96eeaecc39a69f10da96368337c6abd3 Mon Sep 17 00:00:00 2001 From: Wolfgang Ziegler Date: Mon, 30 Sep 2019 15:57:13 +0200 Subject: [PATCH 4/4] Fixed issues and tests after merge --- src/OpenTelemetry/Trace/TracerFactory.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry/Trace/TracerFactory.cs b/src/OpenTelemetry/Trace/TracerFactory.cs index 628def9e1ee..e4bae9502ca 100644 --- a/src/OpenTelemetry/Trace/TracerFactory.cs +++ b/src/OpenTelemetry/Trace/TracerFactory.cs @@ -34,9 +34,13 @@ public TracerFactory(SpanProcessor spanProcessor = null, TraceConfig traceConfig { this.spanProcessor = spanProcessor ?? Tracing.SpanProcessor; this.traceConfig = traceConfig ?? Tracing.TraceConfig; + this.TextFormat = new TraceContextFormat(); + this.BinaryFormat = new BinaryFormat(); } internal ITextFormat TextFormat { get; set; } + + internal IBinaryFormat BinaryFormat { get; set; } /// public ITracer GetTracer(string name, string version = null) @@ -47,7 +51,7 @@ public ITracer GetTracer(string name, string version = null) if (!this.tracerRegistry.TryGetValue(key, out var tracer)) { var labels = CreateLibraryResourceLabels(name, version); - tracer = new Tracer(this.spanProcessor, this.traceConfig, null, this.TextFormat, Resource.Create(labels)); + tracer = new Tracer(this.spanProcessor, this.traceConfig, this.BinaryFormat, this.TextFormat, Resource.Create(labels)); this.tracerRegistry.Add(key, tracer); }