From 0869961473f84bcff2a6c2947d0591b9e3859533 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Wed, 19 Jun 2019 20:02:39 +0200 Subject: [PATCH 01/41] Mention an existent .NET Framework version (#112) .NET 4.7.2 was superseded by 4.8. There was no 4.7.3. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13727b16f22..b71bb710aab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Reporting bugs is an important contribution. Please make sure to include: - expected and actual behavior. - dotnet version that application is compiled on and running with (it may be different - for instance target framework was set to .NET 4.6 for - compilation, but application is running on .NET 4.7.3). + compilation, but application is running on .NET 4.7.2). - exception call stack and other artifacts. - if possible - repro application and steps to reproduce. From 27d9b9816b886b3e9a69ea046d1f222048b9cbc1 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Fri, 21 Jun 2019 17:18:16 +0200 Subject: [PATCH 02/41] Zipkin/refactor (#114) * Don't await task if unused * Supress exception at the API entry --- .../Implementation/TraceExporterHandler.cs | 49 ++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index 40d23324a78..8fffe4c7688 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -58,7 +58,14 @@ public async Task ExportAsync(IEnumerable spanDataList) zipkinSpans.Add(zipkinSpan); } - await this.SendSpansAsync(zipkinSpans); + try + { + await this.SendSpansAsync(zipkinSpans); + } + catch (Exception) + { + // Ignored + } } internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint) @@ -155,38 +162,24 @@ private ZipkinSpanKind ToSpanKind(SpanData spanData) return ZipkinSpanKind.CLIENT; } - private async Task SendSpansAsync(IEnumerable spans) + private Task SendSpansAsync(IEnumerable spans) { - try - { - var requestUri = this.options.Endpoint; - var request = this.GetHttpRequestMessage(HttpMethod.Post, requestUri); - request.Content = this.GetRequestContent(spans); - await this.DoPost(this.httpClient, request); - } - catch (Exception) - { - } + var requestUri = this.options.Endpoint; + var request = this.GetHttpRequestMessage(HttpMethod.Post, requestUri); + request.Content = this.GetRequestContent(spans); + return this.DoPost(this.httpClient, request); } private async Task DoPost(HttpClient client, HttpRequestMessage request) { - try + using (HttpResponseMessage response = await client.SendAsync(request)) { - using (HttpResponseMessage response = await client.SendAsync(request)) + if (response.StatusCode != HttpStatusCode.OK && + response.StatusCode != HttpStatusCode.Accepted) { - if (response.StatusCode != HttpStatusCode.OK && - response.StatusCode != HttpStatusCode.Accepted) - { - var statusCode = (int)response.StatusCode; - } - - return; + var statusCode = (int)response.StatusCode; } } - catch (Exception) - { - } } private HttpRequestMessage GetHttpRequestMessage(HttpMethod method, Uri requestUri) @@ -198,17 +191,17 @@ private HttpRequestMessage GetHttpRequestMessage(HttpMethod method, Uri requestU private HttpContent GetRequestContent(IEnumerable toSerialize) { + string content = string.Empty; try { - string json = JsonConvert.SerializeObject(toSerialize); - - return new StringContent(json, Encoding.UTF8, "application/json"); + content = JsonConvert.SerializeObject(toSerialize); } catch (Exception) { + // Ignored } - return new StringContent(string.Empty, Encoding.UTF8, "application/json"); + return new StringContent(content, Encoding.UTF8, "application/json"); } private ZipkinEndpoint GetLocalZipkinEndpoint() From f6e400e02cfb60d439b8ecc2203ca34db7b9e932 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Fri, 21 Jun 2019 18:02:22 +0200 Subject: [PATCH 03/41] dhere to coding style (#116) * .editorconfig defines to use var --- samples/Exporters/TestApplicationInsights.cs | 2 +- samples/Exporters/TestHttpClient.cs | 2 +- samples/Exporters/TestPrometheus.cs | 6 +- samples/Exporters/TestRedis.cs | 18 +-- samples/Exporters/TestStackdriver.cs | 2 +- samples/Exporters/TestZipkin.cs | 12 +- .../Common/Duration.cs | 4 +- .../Common/Timestamp.cs | 22 ++-- .../Context/Propagation/BinaryFormat.cs | 10 +- .../Context/Propagation/TraceContextFormat.cs | 8 +- .../Resources/Resource.cs | 4 +- src/OpenTelemetry.Abstractions/Tags/Tag.cs | 2 +- src/OpenTelemetry.Abstractions/Tags/TagKey.cs | 2 +- .../Tags/TagValue.cs | 2 +- .../Tags/TagValues.cs | 4 +- .../Trace/Config/TraceParams.cs | 2 +- .../Trace/Config/TraceParamsBuilder.cs | 2 +- src/OpenTelemetry.Abstractions/Trace/Event.cs | 2 +- .../Trace/Export/Attributes.cs | 2 +- .../Trace/Export/LinkList.cs | 2 +- .../Trace/Export/TimedEvent.cs | 2 +- .../Trace/Export/TimedEvents.cs | 2 +- .../Trace/Internal/AttributeValue{T}.cs | 10 +- src/OpenTelemetry.Abstractions/Trace/Link.cs | 2 +- .../Trace/SpanContext.cs | 4 +- .../Trace/SpanData.cs | 2 +- .../Trace/SpanExtensions.cs | 2 +- .../Trace/SpanId.cs | 18 +-- .../Trace/Status.cs | 4 +- .../Trace/TraceId.cs | 22 ++-- .../Trace/TraceOptions.cs | 8 +- .../Trace/TraceState.cs | 18 +-- .../Utils/Arrays.cs | 26 ++-- .../Utils/Collections.cs | 4 +- .../Utils/StringUtil.cs | 2 +- .../AspNetCoreCollectorEventSource.cs | 2 +- .../Implementation/HttpInListener.cs | 4 +- .../DependenciesCollectorEventSource.cs | 2 +- .../HttpHandlerDiagnosticListener.cs | 4 +- .../RedisProfilerEntryToSpanConverter.cs | 10 +- .../ApplicationInsightsExporter.cs | 2 +- .../Implementation/MetricsExporterThread.cs | 4 +- .../Implementation/TraceExporterHandler.cs | 4 +- .../ExporterOcagentEventSource.cs | 2 +- .../Implementation/TraceExporterHandler.cs | 6 +- .../Implementation/MetricsHttpServer.cs | 2 +- .../Implementation/PrometheusMetricBuilder.cs | 12 +- .../PrometheusExporter.cs | 2 +- .../ExporterStackdriverEventSource.cs | 2 +- .../GoogleCloudResourceUtils.cs | 2 +- .../Implementation/MetricsConversions.cs | 24 ++-- .../StackdriverStatsExporter.cs | 14 +-- .../StackdriverTraceExporter.cs | 10 +- .../StackdriverExporter.cs | 4 +- .../Utils/CommonUtils.cs | 2 +- .../Implementation/TraceExporterHandler.cs | 22 ++-- .../Context/Propagation/B3Format.cs | 6 +- .../OpenTelemetryEventSource.cs | 2 +- src/OpenTelemetry/Internal/VarInt.cs | 24 ++-- src/OpenTelemetry/Stats/Aggregations/Count.cs | 2 +- .../Stats/Aggregations/Distribution.cs | 2 +- .../Stats/Aggregations/LastValue.cs | 2 +- src/OpenTelemetry/Stats/Aggregations/Mean.cs | 2 +- src/OpenTelemetry/Stats/Aggregations/Sum.cs | 2 +- src/OpenTelemetry/Stats/BucketBoundaries.cs | 10 +- src/OpenTelemetry/Stats/MeasureMapBuilder.cs | 4 +- src/OpenTelemetry/Stats/MeasureToViewMap.cs | 26 ++-- .../Stats/Measures/MeasureDouble.cs | 2 +- .../Stats/Measures/MeasureLong.cs | 2 +- src/OpenTelemetry/Stats/MutableCount.cs | 2 +- .../Stats/MutableDistribution.cs | 12 +- src/OpenTelemetry/Stats/MutableLastValue.cs | 2 +- src/OpenTelemetry/Stats/MutableMean.cs | 2 +- src/OpenTelemetry/Stats/MutableViewData.cs | 10 +- src/OpenTelemetry/Stats/NoopViewManager.cs | 8 +- src/OpenTelemetry/Stats/StatsComponent.cs | 2 +- src/OpenTelemetry/Stats/StatsExtensions.cs | 10 +- src/OpenTelemetry/Stats/View.cs | 2 +- src/OpenTelemetry/Stats/ViewData.cs | 2 +- src/OpenTelemetry/Stats/ViewName.cs | 2 +- .../Tags/Propagation/SerializationUtils.cs | 26 ++-- src/OpenTelemetry/Tags/TagContextBase.cs | 4 +- src/OpenTelemetry/Tags/Tagger.cs | 4 +- src/OpenTelemetry/Trace/EndSpanOptions.cs | 2 +- .../Trace/EndSpanOptionsBuilder.cs | 2 +- .../Trace/Export/RunningPerSpanNameSummary.cs | 2 +- .../Trace/Export/SampledPerSpanNameSummary.cs | 2 +- .../Trace/Export/SpanExporter.cs | 2 +- .../Trace/Export/SpanExporterWorker.cs | 6 +- .../SpanStore/InProcessRunningSpanStore.cs | 14 +-- .../SpanStore/InProcessSampledSpanStore.cs | 64 +++++----- .../Export/SpanStore/NoopSampledSpanStore.cs | 2 +- .../SpanStore/RunningSpanStoreFilter.cs | 2 +- .../SpanStore/RunningSpanStoreSummary.cs | 2 +- .../SpanStore/SampledSpanStoreErrorFilter.cs | 2 +- .../SpanStore/SampledSpanStoreSummary.cs | 2 +- .../Trace/Sampler/ProbabilitySampler.cs | 2 +- src/OpenTelemetry/Trace/Span.cs | 8 +- src/OpenTelemetry/Trace/SpanBuilder.cs | 22 ++-- src/OpenTelemetry/Trace/TracerBase.cs | 2 +- .../Utils/AttributesWithCapacity.cs | 6 +- src/OpenTelemetry/Utils/Collections.cs | 4 +- .../Utils/ConcurrentIntrusiveList.cs | 4 +- src/OpenTelemetry/Utils/StringUtil.cs | 2 +- .../BasicTests.cs | 4 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 2 +- .../BasicTests.cs | 8 +- .../HttpClientTests.cs | 8 +- .../TestServer.cs | 2 +- .../TraceExporterHandlerTests.cs | 2 +- .../Impl/Common/TimestampTest.cs | 12 +- .../Impl/Resources/ResourceTest.cs | 2 +- .../Impl/Stats/AggregationDataTest.cs | 8 +- .../Impl/Stats/AggregationTest.cs | 10 +- .../Impl/Stats/BucketBoundariesTest.cs | 16 +-- .../Impl/Stats/CurrentStatsStateTest.cs | 6 +- .../Impl/Stats/MeasureMapBuilderTest.cs | 4 +- .../Impl/Stats/MeasureTest.cs | 12 +- .../Impl/Stats/MeasureToViewMapTest.cs | 4 +- .../Impl/Stats/MutableAggregationTest.cs | 58 ++++----- .../Impl/Stats/MutableViewDataTest.cs | 14 +-- .../Impl/Stats/NoopStatsTest.cs | 2 +- .../Impl/Stats/NoopViewManagerTest.cs | 42 +++---- .../Impl/Stats/QuickStartExampleTest.cs | 62 +++++----- .../Impl/Stats/StatsRecorderTest.cs | 24 ++-- .../Impl/Stats/StatsTestUtil.cs | 4 +- .../Impl/Stats/ViewDataTest.cs | 12 +- .../Impl/Stats/ViewManagerTest.cs | 114 +++++++++--------- .../Impl/Stats/ViewTest.cs | 14 +-- .../Impl/Tags/CurrentTagContextUtilsTest.cs | 6 +- .../Impl/Tags/CurrentTaggingStateTest.cs | 4 +- .../Impl/Tags/NoopTagsTest.cs | 16 +-- .../TagContextDeserializationExceptionTest.cs | 4 +- .../TagContextDeserializationTest.cs | 60 ++++----- .../Propagation/TagContextRoundtripTest.cs | 8 +- .../TagContextSerializationExceptionTest.cs | 4 +- .../TagContextSerializationTest.cs | 18 +-- .../Impl/Tags/ScopedTagContextsTest.cs | 20 +-- .../Impl/Tags/TagContextTest.cs | 30 ++--- .../Impl/Tags/TagKeyTest.cs | 12 +- test/OpenTelemetry.Tests/Impl/Tags/TagTest.cs | 8 +- .../Impl/Tags/TagValueTest.cs | 14 +-- .../Impl/Tags/TaggerTest.cs | 52 ++++---- .../Impl/Trace/AttributeValueTest.cs | 12 +- .../Impl/Trace/Config/TraceConfigBaseTest.cs | 2 +- .../Impl/Trace/Config/TraceConfigTest.cs | 2 +- .../Impl/Trace/Config/TraceParamsTest.cs | 2 +- .../Impl/Trace/CurrentSpanUtilsTest.cs | 2 +- .../Impl/Trace/EndSpanOptionsTest.cs | 8 +- .../Impl/Trace/EventTest.cs | 12 +- .../Export/InProcessRunningSpanStoreTest.cs | 16 +-- .../Export/InProcessSampledSpanStoreTest.cs | 44 +++---- .../Trace/Export/NoopRunningSpanStoreTest.cs | 2 +- .../Trace/Export/NoopSampledSpanStoreTest.cs | 12 +- .../Impl/Trace/Export/SpanDataTest.cs | 14 +-- .../Impl/Trace/Export/SpanExporterTest.cs | 36 +++--- .../Internal/ConcurrentIntrusiveListTest.cs | 12 +- .../Impl/Trace/LinkTest.cs | 10 +- .../Impl/Trace/Propagation/B3FormatTest.cs | 4 +- .../Trace/Propagation/BinaryFormatTest.cs | 2 +- .../SpanContextParseExceptionTest.cs | 4 +- .../Trace/Propagation/TraceContextTest.cs | 2 +- .../Impl/Trace/Sampler/SamplersTest.cs | 12 +- .../Impl/Trace/SpanBaseTest.cs | 6 +- .../Impl/Trace/SpanBuilderBaseTest.cs | 4 +- .../Impl/Trace/SpanBuilderTest.cs | 32 ++--- .../Impl/Trace/SpanTest.cs | 74 ++++++------ .../Impl/Trace/StatusTest.cs | 2 +- .../Impl/Trace/TracerBaseTest.cs | 6 +- .../Impl/Trace/TracerTest.cs | 4 +- .../Controllers/ForwardController.cs | 2 +- 171 files changed, 871 insertions(+), 871 deletions(-) diff --git a/samples/Exporters/TestApplicationInsights.cs b/samples/Exporters/TestApplicationInsights.cs index 289d27d3f1a..1b7cd86eeff 100644 --- a/samples/Exporters/TestApplicationInsights.cs +++ b/samples/Exporters/TestApplicationInsights.cs @@ -38,7 +38,7 @@ internal static object Run() var exporter = new ApplicationInsightsExporter(Tracing.ExportComponent, Stats.ViewManager, TelemetryConfiguration.Active); exporter.Start(); - ITagContextBuilder tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); + var tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); var spanBuilder = tracer .SpanBuilder("incoming request") diff --git a/samples/Exporters/TestHttpClient.cs b/samples/Exporters/TestHttpClient.cs index 521eb63cdf2..3103d114d3e 100644 --- a/samples/Exporters/TestHttpClient.cs +++ b/samples/Exporters/TestHttpClient.cs @@ -30,7 +30,7 @@ internal static object Run() var scope = tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartScopedSpan(); //Thread.Sleep(TimeSpan.FromSeconds(1)); - HttpClient client = new HttpClient(); + var client = new HttpClient(); var t = client.GetStringAsync("http://bing.com"); t.Wait(); diff --git a/samples/Exporters/TestPrometheus.cs b/samples/Exporters/TestPrometheus.cs index 458a8d1f44d..e89758a9e44 100644 --- a/samples/Exporters/TestPrometheus.cs +++ b/samples/Exporters/TestPrometheus.cs @@ -44,14 +44,14 @@ internal static object Run() try { - ITagContextBuilder tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); + var tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); Stats.ViewManager.RegisterView(VideoSizeView); var t = new Task(() => { - Random r = new Random(); - byte[] values = new byte[1]; + var r = new Random(); + var values = new byte[1]; while (true) { diff --git a/samples/Exporters/TestRedis.cs b/samples/Exporters/TestRedis.cs index e6fab107569..8cafe783148 100644 --- a/samples/Exporters/TestRedis.cs +++ b/samples/Exporters/TestRedis.cs @@ -25,8 +25,8 @@ internal static object Run(string zipkinUri) exporter.Start(); // 2. Configure 100% sample rate for the purposes of the demo - ITraceConfig traceConfig = Tracing.TraceConfig; - ITraceParams currentConfig = traceConfig.ActiveTraceParams; + var traceConfig = Tracing.TraceConfig; + var currentConfig = traceConfig.ActiveTraceParams; var newConfig = currentConfig.ToBuilder() .SetSampler(Samplers.AlwaysSample) .Build(); @@ -39,18 +39,18 @@ internal static object Run(string zipkinUri) var collector = new StackExchangeRedisCallsCollector(null, tracer, null, Tracing.ExportComponent); // connect to the server - ConnectionMultiplexer connection = ConnectionMultiplexer.Connect("localhost:6379"); + var connection = ConnectionMultiplexer.Connect("localhost:6379"); connection.RegisterProfiler(collector.GetProfilerSessionsFactory()); // select a database (by default, DB = 0) - IDatabase db = connection.GetDatabase(); + var db = connection.GetDatabase(); // 4. Create a scoped span. It will end automatically when using statement ends using (var scope = tracer.SpanBuilder("Main").StartScopedSpan()) { Console.WriteLine("About to do a busy work"); - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { DoWork(db, i); } @@ -65,15 +65,15 @@ internal static object Run(string zipkinUri) private static void DoWork(IDatabase db, int i) { // 6. Get the global singleton Tracer object - ITracer tracer = Tracing.Tracer; + var tracer = Tracing.Tracer; // 7. 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 // a child span. - using (OpenTelemetry.Context.IScope scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) + using (var scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) { // Simulate some work. - ISpan span = tracer.CurrentSpan; + var span = tracer.CurrentSpan; try { @@ -83,7 +83,7 @@ private static void DoWork(IDatabase db, int i) Thread.Sleep(1000); // run a command, in this case a GET - RedisValue myVal = db.StringGet("key"); + var myVal = db.StringGet("key"); Console.WriteLine(myVal); diff --git a/samples/Exporters/TestStackdriver.cs b/samples/Exporters/TestStackdriver.cs index 49530365df8..6f2b8faa186 100644 --- a/samples/Exporters/TestStackdriver.cs +++ b/samples/Exporters/TestStackdriver.cs @@ -39,7 +39,7 @@ internal static object Run(string projectId) Stats.ViewManager); exporter.Start(); - ITagContextBuilder tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); + var tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); var spanBuilder = tracer .SpanBuilder("incoming request") diff --git a/samples/Exporters/TestZipkin.cs b/samples/Exporters/TestZipkin.cs index 9b63e311d46..6b75082d6b3 100644 --- a/samples/Exporters/TestZipkin.cs +++ b/samples/Exporters/TestZipkin.cs @@ -23,8 +23,8 @@ internal static object Run(string zipkinUri) exporter.Start(); // 2. Configure 100% sample rate for the purposes of the demo - ITraceConfig traceConfig = Tracing.TraceConfig; - ITraceParams currentConfig = traceConfig.ActiveTraceParams; + var traceConfig = Tracing.TraceConfig; + var currentConfig = traceConfig.ActiveTraceParams; var newConfig = currentConfig.ToBuilder() .SetSampler(Samplers.AlwaysSample) .Build(); @@ -38,7 +38,7 @@ internal static object Run(string zipkinUri) using (var scope = tracer.SpanBuilder("Main").StartScopedSpan()) { Console.WriteLine("About to do a busy work"); - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { DoWork(i); } @@ -53,15 +53,15 @@ internal static object Run(string zipkinUri) private static void DoWork(int i) { // 6. Get the global singleton Tracer object - ITracer tracer = Tracing.Tracer; + var tracer = Tracing.Tracer; // 7. 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 // a child span. - using (OpenTelemetry.Context.IScope scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) + using (var scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) { // Simulate some work. - ISpan span = tracer.CurrentSpan; + var span = tracer.CurrentSpan; try { diff --git a/src/OpenTelemetry.Abstractions/Common/Duration.cs b/src/OpenTelemetry.Abstractions/Common/Duration.cs index 8d52029e376..b3019457f05 100644 --- a/src/OpenTelemetry.Abstractions/Common/Duration.cs +++ b/src/OpenTelemetry.Abstractions/Common/Duration.cs @@ -81,7 +81,7 @@ public static Duration Create(long seconds, int nanos) public static Duration Create(TimeSpan duration) { var seconds = duration.Ticks / TimeSpan.TicksPerSecond; - int nanoseconds = (int)(duration.Ticks % TimeSpan.TicksPerSecond) * 100; + var nanoseconds = (int)(duration.Ticks % TimeSpan.TicksPerSecond) * 100; return Create(seconds, nanoseconds); } @@ -92,7 +92,7 @@ public static Duration Create(TimeSpan duration) /// Zero if equal, -1 when lesser and +1 when greater than given value. public int CompareTo(Duration other) { - int cmp = (this.Seconds < other.Seconds) ? -1 : ((this.Seconds > other.Seconds) ? 1 : 0); + var cmp = (this.Seconds < other.Seconds) ? -1 : ((this.Seconds > other.Seconds) ? 1 : 0); if (cmp != 0) { return cmp; diff --git a/src/OpenTelemetry.Abstractions/Common/Timestamp.cs b/src/OpenTelemetry.Abstractions/Common/Timestamp.cs index de8a9f7465c..517eb175b22 100644 --- a/src/OpenTelemetry.Abstractions/Common/Timestamp.cs +++ b/src/OpenTelemetry.Abstractions/Common/Timestamp.cs @@ -83,7 +83,7 @@ public static Timestamp Create(long seconds, int nanos) /// New instance of . public static Timestamp FromMillis(long millis) { - long nanos = millis * NanosPerMilli; + var nanos = millis * NanosPerMilli; return Zero.Plus(0, nanos); } @@ -102,7 +102,7 @@ public static Timestamp FromDateTimeOffset(DateTimeOffset time) seconds = time.ToUnixTimeSeconds(); #endif - int nanos = (int)time.Subtract(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).Subtract(TimeSpan.FromSeconds(seconds)).Ticks * 100; + var nanos = (int)time.Subtract(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).Subtract(TimeSpan.FromSeconds(seconds)).Ticks * 100; return Timestamp.Create(seconds, nanos); } @@ -133,8 +133,8 @@ public Timestamp AddNanos(long nanosToAdd) /// Returns the timestamp with the substructed duration. public Duration SubtractTimestamp(Timestamp timestamp) { - long durationSeconds = this.Seconds - timestamp.Seconds; - int durationNanos = this.Nanos - timestamp.Nanos; + var durationSeconds = this.Seconds - timestamp.Seconds; + var durationNanos = this.Nanos - timestamp.Nanos; if (durationSeconds < 0 && durationNanos > 0) { durationSeconds += 1; @@ -152,7 +152,7 @@ public Duration SubtractTimestamp(Timestamp timestamp) /// public int CompareTo(Timestamp other) { - int cmp = (this.Seconds < other.Seconds) ? -1 : ((this.Seconds > other.Seconds) ? 1 : 0); + var cmp = (this.Seconds < other.Seconds) ? -1 : ((this.Seconds > other.Seconds) ? 1 : 0); if (cmp != 0) { return cmp; @@ -205,9 +205,9 @@ public override int GetHashCode() private static Timestamp OfSecond(long seconds, long nanoAdjustment) { - long floor = (long)Math.Floor((double)nanoAdjustment / NanosPerSecond); - long secs = seconds + floor; - long nos = nanoAdjustment - (floor * NanosPerSecond); + var floor = (long)Math.Floor((double)nanoAdjustment / NanosPerSecond); + var secs = seconds + floor; + var nos = nanoAdjustment - (floor * NanosPerSecond); return Create(secs, (int)nos); } @@ -218,10 +218,10 @@ private Timestamp Plus(long secondsToAdd, long nanosToAdd) return this; } - long sec = this.Seconds + secondsToAdd; - long nanoSeconds = Math.DivRem(nanosToAdd, NanosPerSecond, out long nanosSpill); + var sec = this.Seconds + secondsToAdd; + var nanoSeconds = Math.DivRem(nanosToAdd, NanosPerSecond, out var nanosSpill); sec += nanoSeconds; - long nanoAdjustment = this.Nanos + nanosSpill; + var nanoAdjustment = this.Nanos + nanosSpill; return OfSecond(sec, nanoAdjustment); } } diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs index ea9a776fd98..ebcda32141c 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs @@ -49,11 +49,11 @@ public SpanContext FromByteArray(byte[] bytes) throw new SpanContextParseException("Unsupported version."); } - TraceId traceId = TraceId.Invalid; - SpanId spanId = SpanId.Invalid; - TraceOptions traceOptions = TraceOptions.Default; + var traceId = TraceId.Invalid; + var spanId = SpanId.Invalid; + var traceOptions = TraceOptions.Default; - int pos = 1; + var pos = 1; try { if (bytes.Length > pos && bytes[pos] == TraceIdFieldId) @@ -88,7 +88,7 @@ public byte[] ToByteArray(SpanContext spanContext) throw new ArgumentNullException(nameof(spanContext)); } - byte[] bytes = new byte[FormatLength]; + var bytes = new byte[FormatLength]; bytes[VersionIdOffset] = VersionId; bytes[TraceIdFieldIdOffset] = TraceIdFieldId; spanContext.TraceId.CopyBytesTo(bytes, TraceIdOffset); diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs index 94282b0d6c1..350c567307e 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs @@ -54,7 +54,7 @@ public SpanContext Extract(T carrier, Func> ge } var traceparent = traceparentCollection?.FirstOrDefault(); - var traceparentParsed = this.TryExtractTraceparent(traceparent, out TraceId traceId, out SpanId spanId, out TraceOptions traceoptions); + var traceparentParsed = this.TryExtractTraceparent(traceparent, out var traceId, out var spanId, out var traceoptions); if (!traceparentParsed) { @@ -64,8 +64,8 @@ public SpanContext Extract(T carrier, Func> ge var tracestateResult = Tracestate.Empty; try { - List> entries = new List>(); - HashSet names = new HashSet(); + var entries = new List>(); + var names = new HashSet(); var discardTracestate = false; if (tracestateCollection != null) { @@ -170,7 +170,7 @@ public void Inject(SpanContext spanContext, T carrier, Action label in other.Labels) + foreach (var label in other.Labels) { if (this.labelCollection.ContainsKey(label.Key) == false) { @@ -88,7 +88,7 @@ private static IDictionary ValidateLabels(IDictionary label in labels) + foreach (var label in labels) { if (!IsValidAndNotEmpty(label.Key)) { diff --git a/src/OpenTelemetry.Abstractions/Tags/Tag.cs b/src/OpenTelemetry.Abstractions/Tags/Tag.cs index 0080ba85a9c..2a585de5e3f 100644 --- a/src/OpenTelemetry.Abstractions/Tags/Tag.cs +++ b/src/OpenTelemetry.Abstractions/Tags/Tag.cs @@ -84,7 +84,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Key.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Tags/TagKey.cs b/src/OpenTelemetry.Abstractions/Tags/TagKey.cs index 291338e661a..bf90e094410 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagKey.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagKey.cs @@ -81,7 +81,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Name.GetHashCode(); return h; diff --git a/src/OpenTelemetry.Abstractions/Tags/TagValue.cs b/src/OpenTelemetry.Abstractions/Tags/TagValue.cs index ef592526f53..a12d5162809 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagValue.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagValue.cs @@ -81,7 +81,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.AsString.GetHashCode(); return h; diff --git a/src/OpenTelemetry.Abstractions/Tags/TagValues.cs b/src/OpenTelemetry.Abstractions/Tags/TagValues.cs index 2a9c22cd8b6..46d66cd9ff3 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagValues.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagValues.cs @@ -67,7 +67,7 @@ public override bool Equals(object o) return false; } - for (int i = 0; i < this.Values.Count; i++) + for (var i = 0; i < this.Values.Count; i++) { if (this.Values[i] == null) { @@ -94,7 +94,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; foreach (var v in this.Values) { diff --git a/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs b/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs index 010714977fe..46b05fb694d 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs @@ -118,7 +118,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Sampler.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/Config/TraceParamsBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/Config/TraceParamsBuilder.cs index d4d22366cb2..a94d75efb73 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Config/TraceParamsBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Config/TraceParamsBuilder.cs @@ -100,7 +100,7 @@ public TraceParamsBuilder SetMaxNumberOfLinks(int maxNumberOfLinks) /// If maximum values are not set or set to less than one. public TraceParams Build() { - string missing = string.Empty; + var missing = string.Empty; if (this.sampler == null) { missing += " sampler"; diff --git a/src/OpenTelemetry.Abstractions/Trace/Event.cs b/src/OpenTelemetry.Abstractions/Trace/Event.cs index db514f7d3cd..47e4b8d4246 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Event.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Event.cs @@ -89,7 +89,7 @@ public override bool Equals(object obj) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Name.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs index 182e3f913d1..5ac965c44a6 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs @@ -73,7 +73,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.AttributeMap.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs index 16add023e0a..d2871940b46 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs @@ -73,7 +73,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Links.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs index 26f25d33ea8..82628de9cf9 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Timestamp.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs index a8550733d21..881ed44f503 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs @@ -71,7 +71,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Events.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs b/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs index cc343f6a15a..52f271299f8 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs @@ -102,7 +102,7 @@ public override bool Equals(object obj) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Value.GetHashCode(); return h; @@ -126,22 +126,22 @@ public override TReturn Match( { if (typeof(T) == typeof(string)) { - string value = this.Value as string; + var value = this.Value as string; return stringFunction(value); } else if (typeof(T) == typeof(long)) { - long val = (long)(object)this.Value; + var val = (long)(object)this.Value; return longFunction(val); } else if (typeof(T) == typeof(bool)) { - bool val = (bool)(object)this.Value; + var val = (bool)(object)this.Value; return booleanFunction(val); } else if (typeof(T) == typeof(double)) { - double val = (double)(object)this.Value; + var val = (double)(object)this.Value; return doubleFunction(val); } diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index 84a6e9f3f69..6fa4a0008c0 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -83,7 +83,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Context.TraceId.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs b/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs index 872ae9fd10c..cc46ab3aceb 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs @@ -77,7 +77,7 @@ public static SpanContext Create(TraceId traceId, SpanId spanId, TraceOptions tr /// public override int GetHashCode() { - int result = 1; + var result = 1; result = (31 * result) + (this.TraceId == null ? 0 : this.TraceId.GetHashCode()); result = (31 * result) + (this.SpanId == null ? 0 : this.SpanId.GetHashCode()); result = (31 * result) + (this.TraceOptions == null ? 0 : this.TraceOptions.GetHashCode()); @@ -97,7 +97,7 @@ public override bool Equals(object obj) return false; } - SpanContext that = (SpanContext)obj; + var that = (SpanContext)obj; return this.TraceId.Equals(that.TraceId) && this.SpanId.Equals(that.SpanId) && this.TraceOptions.Equals(that.TraceOptions); diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index 47d2d6d7047..65e002d7796 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -213,7 +213,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Context.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanExtensions.cs b/src/OpenTelemetry.Abstractions/Trace/SpanExtensions.cs index 9982929099e..f3c0431b1bd 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanExtensions.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanExtensions.cs @@ -171,7 +171,7 @@ public static ISpan PutHttpStatusCode(this ISpan span, int statusCode, string re { span.PutHttpStatusCodeAttribute(statusCode); - Status newStatus = Status.Ok; + var newStatus = Status.Ok; if ((int)statusCode < 200) { diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanId.cs b/src/OpenTelemetry.Abstractions/Trace/SpanId.cs index 88c97f0da0d..c23b1e56e39 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanId.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanId.cs @@ -50,7 +50,7 @@ public byte[] Bytes { get { - byte[] copyOf = new byte[Size]; + var copyOf = new byte[Size]; Buffer.BlockCopy(this.bytes, 0, copyOf, 0, Size); return copyOf; } @@ -76,14 +76,14 @@ public static SpanId FromBytes(byte[] buffer) throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", Size, buffer.Length)); } - byte[] bytesCopied = new byte[Size]; + var bytesCopied = new byte[Size]; Buffer.BlockCopy(buffer, 0, bytesCopied, 0, Size); return new SpanId(bytesCopied); } public static SpanId FromBytes(byte[] src, int srcOffset) { - byte[] bytes = new byte[Size]; + var bytes = new byte[Size]; Buffer.BlockCopy(src, srcOffset, bytes, 0, Size); return new SpanId(bytes); } @@ -95,13 +95,13 @@ public static SpanId FromLowerBase16(string src) throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", 2 * Size, src.Length)); } - byte[] bytes = Arrays.StringToByteArray(src); + var bytes = Arrays.StringToByteArray(src); return new SpanId(bytes); } public static SpanId GenerateRandomId(IRandomGenerator random) { - byte[] bytes = new byte[Size]; + var bytes = new byte[Size]; do { random.NextBytes(bytes); @@ -143,7 +143,7 @@ public override bool Equals(object obj) return false; } - SpanId that = (SpanId)obj; + var that = (SpanId)obj; return Arrays.Equals(this.bytes, that.bytes); } @@ -164,12 +164,12 @@ public override string ToString() /// public int CompareTo(SpanId other) { - for (int i = 0; i < Size; i++) + for (var i = 0; i < Size; i++) { if (this.bytes[i] != other.bytes[i]) { - sbyte b1 = (sbyte)this.bytes[i]; - sbyte b2 = (sbyte)other.bytes[i]; + var b1 = (sbyte)this.bytes[i]; + var b2 = (sbyte)other.bytes[i]; return b1 < b2 ? -1 : 1; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Status.cs b/src/OpenTelemetry.Abstractions/Trace/Status.cs index 0b58d081b84..4b587208065 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Status.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Status.cs @@ -197,14 +197,14 @@ public override bool Equals(object obj) return false; } - Status that = (Status)obj; + var that = (Status)obj; return this.CanonicalCode == that.CanonicalCode && this.Description == that.Description; } /// public override int GetHashCode() { - int result = 1; + var result = 1; result = (31 * result) + this.CanonicalCode.GetHashCode(); result = (31 * result) + this.Description.GetHashCode(); return result; diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceId.cs b/src/OpenTelemetry.Abstractions/Trace/TraceId.cs index 64a678e9c5d..3e42b61b8a5 100644 --- a/src/OpenTelemetry.Abstractions/Trace/TraceId.cs +++ b/src/OpenTelemetry.Abstractions/Trace/TraceId.cs @@ -49,7 +49,7 @@ public byte[] Bytes { get { - byte[] copyOf = new byte[Size]; + var copyOf = new byte[Size]; Buffer.BlockCopy(this.bytes, 0, copyOf, 0, Size); return copyOf; } @@ -74,7 +74,7 @@ public long LowerLong get { long result = 0; - for (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { result <<= 8; #pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand @@ -103,14 +103,14 @@ public static TraceId FromBytes(byte[] buffer) throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", Size, buffer.Length)); } - byte[] bytesCopied = new byte[Size]; + var bytesCopied = new byte[Size]; Buffer.BlockCopy(buffer, 0, bytesCopied, 0, Size); return new TraceId(bytesCopied); } public static TraceId FromBytes(byte[] src, int srcOffset) { - byte[] bytes = new byte[Size]; + var bytes = new byte[Size]; Buffer.BlockCopy(src, srcOffset, bytes, 0, Size); return new TraceId(bytes); } @@ -122,13 +122,13 @@ public static TraceId FromLowerBase16(string src) throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", 2 * Size, src.Length)); } - byte[] bytes = Arrays.StringToByteArray(src); + var bytes = Arrays.StringToByteArray(src); return new TraceId(bytes); } public static TraceId GenerateRandomId(IRandomGenerator random) { - byte[] bytes = new byte[Size]; + var bytes = new byte[Size]; do { random.NextBytes(bytes); @@ -171,7 +171,7 @@ public override bool Equals(object obj) return false; } - TraceId that = (TraceId)obj; + var that = (TraceId)obj; return Arrays.Equals(this.bytes, that.bytes); } @@ -191,13 +191,13 @@ public override string ToString() public int CompareTo(TraceId other) { - TraceId that = other as TraceId; - for (int i = 0; i < Size; i++) + var that = other as TraceId; + for (var i = 0; i < Size; i++) { if (this.bytes[i] != that.bytes[i]) { - sbyte b1 = (sbyte)this.bytes[i]; - sbyte b2 = (sbyte)that.bytes[i]; + var b1 = (sbyte)this.bytes[i]; + var b2 = (sbyte)that.bytes[i]; return b1 < b2 ? -1 : 1; } diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs b/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs index 89a538e85d3..e6483b4e4d5 100644 --- a/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs +++ b/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs @@ -56,7 +56,7 @@ public byte[] Bytes { get { - byte[] bytes = new byte[Size]; + var bytes = new byte[Size]; bytes[0] = this.options; return bytes; } @@ -95,7 +95,7 @@ public static TraceOptions FromBytes(byte[] buffer) throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", Size, buffer.Length)); } - byte[] bytesCopied = new byte[Size]; + var bytesCopied = new byte[Size]; Buffer.BlockCopy(buffer, 0, bytesCopied, 0, Size); return new TraceOptions(bytesCopied[0]); } @@ -163,14 +163,14 @@ public override bool Equals(object obj) return false; } - TraceOptions that = (TraceOptions)obj; + var that = (TraceOptions)obj; return this.options == that.options; } /// public override int GetHashCode() { - int result = (31 * 1) + this.options; + var result = (31 * 1) + this.options; return result; } diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceState.cs b/src/OpenTelemetry.Abstractions/Trace/TraceState.cs index 730162f3f16..b49ad271097 100644 --- a/src/OpenTelemetry.Abstractions/Trace/TraceState.cs +++ b/src/OpenTelemetry.Abstractions/Trace/TraceState.cs @@ -69,7 +69,7 @@ public static TracestateBuilder Builder /// public string Get(string key) { - foreach (Entry entry in this.Entries) + foreach (var entry in this.Entries) { if (entry.Key.Equals(key)) { @@ -95,7 +95,7 @@ private static bool ValidateKey(string key) // can only contain lowercase letters a-z, digits 0-9, underscores _, dashes -, asterisks *, // forward slashes / and @ - int i = 0; + var i = 0; if (string.IsNullOrEmpty(key) || key.Length > KeyMaxSize @@ -108,7 +108,7 @@ private static bool ValidateKey(string key) // before for (i = 1; i < key.Length; i++) { - char c = key[i]; + var c = key[i]; if (c == '@') { @@ -147,7 +147,7 @@ private static bool ValidateKey(string key) for (; i < key.Length; i++) { - char c = key[i]; + var c = key[i]; if (!(c >= 'a' && c <= 'z') && !(c >= '0' && c <= '9') @@ -173,9 +173,9 @@ private static bool ValidateValue(string value) return false; } - for (int i = 0; i < value.Length; i++) + for (var i = 0; i < value.Length; i++) { - char c = value[i]; + var c = value[i]; if (c == ',' || c == '=' || c < ' ' /* '\u0020' */ || c > '~' /* '\u007E' */) { @@ -275,7 +275,7 @@ public TracestateBuilder Set(string key, string value) { // Initially create the Entry to validate input. - Entry entry = Entry.Create(key, value); + var entry = Entry.Create(key, value); if (this.entries == null) { @@ -283,7 +283,7 @@ public TracestateBuilder Set(string key, string value) this.entries = new List(this.parent.Entries); } - for (int i = 0; i < this.entries.Count; i++) + for (var i = 0; i < this.entries.Count; i++) { if (this.entries[i].Key.Equals(entry.Key)) { @@ -314,7 +314,7 @@ public TracestateBuilder Remove(string key) this.entries = new List(this.parent.Entries); } - for (int i = 0; i < this.entries.Count; i++) + for (var i = 0; i < this.entries.Count; i++) { if (this.entries[i].Key.Equals(key)) { diff --git a/src/OpenTelemetry.Abstractions/Utils/Arrays.cs b/src/OpenTelemetry.Abstractions/Utils/Arrays.cs index 58a95d05584..59ed7dfe6db 100644 --- a/src/OpenTelemetry.Abstractions/Utils/Arrays.cs +++ b/src/OpenTelemetry.Abstractions/Utils/Arrays.cs @@ -40,7 +40,7 @@ public static bool Equals(byte[] array1, byte[] array2) return false; } - for (int i = 0; i < array1.Length; i++) + for (var i = 0; i < array1.Length; i++) { if (array1[i] != array2[i]) { @@ -58,8 +58,8 @@ internal static int GetHashCode(byte[] array) return 0; } - int result = 1; - foreach (byte b in array) + var result = 1; + foreach (var b in array) { result = (31 * result) + b; } @@ -90,10 +90,10 @@ internal static int HexCharToInt(char c) // https://stackoverflow.com/a/24343727 internal static uint[] CreateLookupTable() { - uint[] table = new uint[256]; - for (int i = 0; i < 256; i++) + var table = new uint[256]; + for (var i = 0; i < 256; i++) { - string s = i.ToString("x2"); + var s = i.ToString("x2"); table[i] = (uint)s[0]; table[i] += (uint)s[1] << 16; } @@ -104,7 +104,7 @@ internal static uint[] CreateLookupTable() // https://stackoverflow.com/a/24343727 internal static char[] ByteToHexCharArray(byte b) { - char[] result = new char[2]; + var result = new char[2]; result[0] = (char)ByteToHexLookupTable[b]; result[1] = (char)(ByteToHexLookupTable[b] >> 16); @@ -119,12 +119,12 @@ internal static byte[] StringToByteArray(string src, int start = 0, int len = -1 len = src.Length; } - int size = len / 2; - byte[] bytes = new byte[size]; + var size = len / 2; + var bytes = new byte[size]; for (int i = 0, j = start; i < size; i++) { - int high = HexCharToInt(src[j++]); - int low = HexCharToInt(src[j++]); + var high = HexCharToInt(src[j++]); + var low = HexCharToInt(src[j++]); bytes[i] = (byte)(high << 4 | low); } @@ -133,8 +133,8 @@ internal static byte[] StringToByteArray(string src, int start = 0, int len = -1 internal static string ByteArrayToString(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < bytes.Length; i++) + var sb = new StringBuilder(); + for (var i = 0; i < bytes.Length; i++) { sb.Append(ByteToHexCharArray(bytes[i])); } diff --git a/src/OpenTelemetry.Abstractions/Utils/Collections.cs b/src/OpenTelemetry.Abstractions/Utils/Collections.cs index d63620d8034..c51e2837413 100644 --- a/src/OpenTelemetry.Abstractions/Utils/Collections.cs +++ b/src/OpenTelemetry.Abstractions/Utils/Collections.cs @@ -29,7 +29,7 @@ public static string ToString(IDictionary dict) return "null"; } - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); foreach (var kvp in dict) { sb.Append(kvp.Key.ToString()); @@ -48,7 +48,7 @@ public static string ToString(IEnumerable list) return "null"; } - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); foreach (var val in list) { if (val != null) diff --git a/src/OpenTelemetry.Abstractions/Utils/StringUtil.cs b/src/OpenTelemetry.Abstractions/Utils/StringUtil.cs index 89db426ba1d..dc10cbac992 100644 --- a/src/OpenTelemetry.Abstractions/Utils/StringUtil.cs +++ b/src/OpenTelemetry.Abstractions/Utils/StringUtil.cs @@ -20,7 +20,7 @@ internal static class StringUtil { public static bool IsPrintableString(string str) { - for (int i = 0; i < str.Length; i++) + for (var i = 0; i < str.Length; i++) { if (!IsPrintableChar(str[i])) { diff --git a/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs b/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs index 09395d67e01..d3702aa1b40 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs @@ -58,7 +58,7 @@ public void ExceptionInCustomSampler(string ex) /// private static string ToInvariantString(Exception exception) { - CultureInfo originalUICulture = Thread.CurrentThread.CurrentUICulture; + var originalUICulture = Thread.CurrentThread.CurrentUICulture; try { diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs index 77bdba4c9ba..4b643025fc0 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs @@ -50,7 +50,7 @@ public override void OnStartActivity(Activity activity, object payload) return; } - HttpRequest request = context.Request; + var request = context.Request; var ctx = this.Tracer.TextFormat.Extract( request, @@ -58,7 +58,7 @@ public override void OnStartActivity(Activity activity, object payload) // see the spec https://github.com/open-telemetry/OpenTelemetry-specs/blob/master/trace/HTTP.md - string path = (request.PathBase.HasValue || request.Path.HasValue) ? (request.PathBase + request.Path).ToString() : "/"; + var path = (request.PathBase.HasValue || request.Path.HasValue) ? (request.PathBase + request.Path).ToString() : "/"; ISpan span = null; this.Tracer.SpanBuilderWithParentContext(path, SpanKind.Server, ctx).SetSampler(this.SamplerFactory(request)).StartScopedSpan(out span); diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs index 9f7117a3cb7..0af3e0588c0 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs @@ -58,7 +58,7 @@ public void ExceptionInCustomSampler(string ex) /// private static string ToInvariantString(Exception exception) { - CultureInfo originalUICulture = Thread.CurrentThread.CurrentUICulture; + var originalUICulture = Thread.CurrentThread.CurrentUICulture; try { diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs index 565d5e4238e..ebb24c23e60 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs @@ -48,11 +48,11 @@ public override void OnStartActivity(Activity activity, object payload) return; } - this.Tracer.SpanBuilder(request.RequestUri.AbsolutePath, SpanKind.Client).SetSampler(this.SamplerFactory(request)).StartScopedSpan(out ISpan span); + this.Tracer.SpanBuilder(request.RequestUri.AbsolutePath, SpanKind.Client).SetSampler(this.SamplerFactory(request)).StartScopedSpan(out var span); span.PutHttpMethodAttribute(request.Method.ToString()); span.PutHttpHostAttribute(request.RequestUri.Host, request.RequestUri.Port); span.PutHttpPathAttribute(request.RequestUri.AbsolutePath); - request.Headers.TryGetValues("User-Agent", out IEnumerable userAgents); + request.Headers.TryGetValues("User-Agent", out var userAgents); span.PutHttpUserAgentAttribute(userAgents?.FirstOrDefault()); span.PutHttpRawUrlAttribute(request.RequestUri.OriginalString); diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs index 63cf37f12bf..862cacbcab4 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs @@ -32,7 +32,7 @@ public static void DrainSession(ISpan parentSpan, IEnumerable foreach (var command in sessionCommands) { - string name = command.Command; // Example: SET; + var name = command.Command; // Example: SET; if (string.IsNullOrEmpty(name)) { name = "name"; @@ -97,7 +97,7 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n // command.ElapsedTime; // 00:00:32.4988020 // TODO: make timestamp with the better precision - Timestamp startTimestamp = Timestamp.FromMillis(new DateTimeOffset(command.CommandCreated).ToUnixTimeMilliseconds()); + var startTimestamp = Timestamp.FromMillis(new DateTimeOffset(command.CommandCreated).ToUnixTimeMilliseconds()); var timestamp = new DateTimeOffset(command.CommandCreated).Add(command.CreationToEnqueued); var events = TimedEvents.Create( @@ -109,7 +109,7 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n }, droppedEventsCount: 0); - Timestamp endTimestamp = Timestamp.FromMillis(new DateTimeOffset(command.CommandCreated.Add(command.ElapsedTime)).ToUnixTimeMilliseconds()); + var endTimestamp = Timestamp.FromMillis(new DateTimeOffset(command.CommandCreated.Add(command.ElapsedTime)).ToUnixTimeMilliseconds()); // TODO: deal with the re-transmission // command.RetransmissionOf; @@ -145,8 +145,8 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n int? childSpanCount = 0; // TODO: this is strange that IProfiledCommand doesn't give the result - Status status = Status.Ok; - SpanKind kind = SpanKind.Client; + var status = Status.Ok; + var kind = SpanKind.Client; return SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); } diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs index acd2f4e835e..561d5681915 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs @@ -77,7 +77,7 @@ public void Start() this.tokenSource = new CancellationTokenSource(); - CancellationToken token = this.tokenSource.Token; + var token = this.tokenSource.Token; var metricsExporter = new MetricsExporterThread(this.telemetryConfiguration, this.viewManager, token, TimeSpan.FromMinutes(1)); this.workerThread = Task.Factory.StartNew((Action)metricsExporter.WorkerThread, TaskCreationOptions.LongRunning); diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs index a3d1775f71c..d5c7c3e1309 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs @@ -49,7 +49,7 @@ public void WorkerThread() { try { - Stopwatch sw = new Stopwatch(); + var sw = new Stopwatch(); while (!this.token.IsCancellationRequested) { @@ -89,7 +89,7 @@ internal void Export() Name = data.View.Name.AsString, }; - for (int i = 0; i < value.Key.Values.Count; i++) + for (var i = 0; i < value.Key.Values.Count; i++) { var name = data.View.Columns[i].Name; var val = value.Key.Values[i].AsString; diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs index 785f174a30a..65e27c8bbf6 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs @@ -421,7 +421,7 @@ private void OverwriteFieldsForHttpSpans( } else { - int idx = url.OriginalString.IndexOf('?'); + var idx = url.OriginalString.IndexOf('?'); if (idx != -1) { httpPath = url.OriginalString.Substring(0, idx); @@ -435,7 +435,7 @@ private void OverwriteFieldsForHttpSpans( if (url == null) { - string urlString = string.Empty; + var urlString = string.Empty; if (!string.IsNullOrEmpty(httpHost)) { urlString += "https://" + httpHost; diff --git a/src/OpenTelemetry.Exporter.Ocagent/Implementation/ExporterOcagentEventSource.cs b/src/OpenTelemetry.Exporter.Ocagent/Implementation/ExporterOcagentEventSource.cs index b71527ce14f..8a749811f50 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/Implementation/ExporterOcagentEventSource.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/Implementation/ExporterOcagentEventSource.cs @@ -47,7 +47,7 @@ public void FailedToConvertToProtoDefinitionError(string ex) /// private static string ToInvariantString(Exception exception) { - CultureInfo originalUICulture = Thread.CurrentThread.CurrentUICulture; + var originalUICulture = Thread.CurrentThread.CurrentUICulture; try { diff --git a/src/OpenTelemetry.Exporter.Ocagent/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Ocagent/Implementation/TraceExporterHandler.cs index 6fa99d1a96b..ddcbf9f4b8f 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/Implementation/TraceExporterHandler.cs @@ -95,7 +95,7 @@ public void Dispose() private static string GetAssemblyVersion(Assembly assembly) { - AssemblyFileVersionAttribute fileVersionAttr = assembly.GetCustomAttribute(); + var fileVersionAttr = assembly.GetCustomAttribute(); return fileVersionAttr?.Version ?? "0.0.0"; } @@ -128,7 +128,7 @@ private async Task RunAsync(CancellationToken cancellationToken) var duplexCall = this.traceClient.Export(); try { - bool firstRequest = true; + var firstRequest = true; while (!cancellationToken.IsCancellationRequested) { var spanExportRequest = new ExportTraceServiceRequest(); @@ -138,7 +138,7 @@ private async Task RunAsync(CancellationToken cancellationToken) } // Spans - bool hasSpans = false; + var hasSpans = false; while (spanExportRequest.Spans.Count < this.spanBatchSize) { diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/MetricsHttpServer.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/MetricsHttpServer.cs index 31b3de09674..18cce47bc2b 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/MetricsHttpServer.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/Implementation/MetricsHttpServer.cs @@ -88,7 +88,7 @@ public void WorkerThread() metricValueBuilder.WithValue, metricValueBuilder.WithValue); - for (int i = 0; i < value.Key.Values.Count; i++) + for (var i = 0; i < value.Key.Values.Count; i++) { metricValueBuilder.WithLabel(data.View.Columns[i].Name, value.Key.Values[i].AsString); } diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs index e30dff04f46..f3c89488684 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs @@ -206,7 +206,7 @@ private static string GetSafeMetricName(string name) // Label names may contain ASCII letters, numbers, as well as underscores. They must match the regex [a-zA-Z_][a-zA-Z0-9_]*. Label names beginning with __ are reserved for internal use. // Label values may contain any Unicode characters. - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if (!string.IsNullOrEmpty(name)) { @@ -231,9 +231,9 @@ private static string GetSafeMetricName(string name) } } - for (int i = 1; i < name.Length; ++i) + for (var i = 1; i < name.Length; ++i) { - char c = name[i]; + var c = name[i]; if (nameCharset.Contains(c)) { @@ -261,7 +261,7 @@ private static string GetSafeLabelName(string name) // Label names may contain ASCII letters, numbers, as well as underscores. They must match the regex [a-zA-Z_][a-zA-Z0-9_]*. Label names beginning with __ are reserved for internal use. // Label values may contain any Unicode characters. - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if (!string.IsNullOrEmpty(name)) { @@ -286,9 +286,9 @@ private static string GetSafeLabelName(string name) } } - for (int i = 1; i < name.Length; ++i) + for (var i = 1; i < name.Length; ++i) { - char c = name[i]; + var c = name[i]; if (labelCharset.Contains(c)) { diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs index 04cda56d051..5ad88ee986b 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporter.cs @@ -62,7 +62,7 @@ public void Start() this.tokenSource = new CancellationTokenSource(); - CancellationToken token = this.tokenSource.Token; + var token = this.tokenSource.Token; var metricsServer = new MetricsHttpServer(this.viewManager, this.options, token); this.workerThread = Task.Factory.StartNew((Action)metricsServer.WorkerThread, TaskCreationOptions.LongRunning); diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/ExporterStackdriverEventSource.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/ExporterStackdriverEventSource.cs index 3ead17440a1..d50a4b6b645 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/ExporterStackdriverEventSource.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/ExporterStackdriverEventSource.cs @@ -62,7 +62,7 @@ public void UnknownProblemWhileCreatingStackdriverTimeSeriesError(string ex) /// private static string ToInvariantString(Exception exception) { - CultureInfo originalUICulture = Thread.CurrentThread.CurrentUICulture; + var originalUICulture = Thread.CurrentThread.CurrentUICulture; try { diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs index 82a4528027d..74f5fca2fcb 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs @@ -44,7 +44,7 @@ public static string GetProjectId() } // Try to detect projectId from service account credential if it exists - string serviceAccountFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"); + var serviceAccountFilePath = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"); if (!string.IsNullOrEmpty(serviceAccountFilePath) && File.Exists(serviceAccountFilePath)) { using (var stream = new FileStream(serviceAccountFilePath, FileMode.Open, FileAccess.Read)) diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs index ffadcd90010..73d5fccf460 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs @@ -59,7 +59,7 @@ public static MetricKind ToMetricKind( public static ValueType ToValueType( this IMeasure measure, IAggregation aggregation) { - MetricKind metricKind = aggregation.ToMetricKind(); + var metricKind = aggregation.ToMetricKind(); if (aggregation is IDistribution && (metricKind == MetricKind.Cumulative || metricKind == MetricKind.Gauge)) return ValueType.Distribution; @@ -124,14 +124,14 @@ public static MetricDescriptor CreateMetricDescriptor( string displayNamePrefix) { var metricDescriptor = new MetricDescriptor(); - string viewName = view.Name.AsString; + var viewName = view.Name.AsString; metricDescriptor.Name = string.Format($"projects/{project.ProjectId}/metricDescriptors/{metricDescriptorTypeName}"); metricDescriptor.Type = metricDescriptorTypeName; metricDescriptor.Description = view.Description; metricDescriptor.DisplayName = GetDisplayName(viewName, displayNamePrefix); - foreach (TagKey tagKey in view.Columns) + foreach (var tagKey in view.Columns) { var labelDescriptor = tagKey.ToLabelDescriptor(); metricDescriptor.Labels.Add(labelDescriptor); @@ -223,19 +223,19 @@ public static Metric GetMetric( var metric = new Metric(); metric.Type = metricDescriptor.Type; - IReadOnlyList columns = view.Columns; + var columns = view.Columns; // Populate metric labels - for (int i = 0; i < tagValues.Count; i++) + for (var i = 0; i < tagValues.Count; i++) { - TagKey key = columns[i]; - TagValue value = tagValues[i]; + var key = columns[i]; + var value = tagValues[i]; if (value == null) { continue; } - string labelKey = GetStackdriverLabelKey(key.Name); + var labelKey = GetStackdriverLabelKey(key.Name); metric.Labels.Add(labelKey, value.AsString); } metric.Labels.Add(Constants.OpenTelemetry_TASK, Constants.OpenTelemetry_TASK_VALUE_DEFAULT); @@ -264,15 +264,15 @@ public static List CreateTimeSeriesList( return timeSeriesList; } - IView view = viewData.View; + var view = viewData.View; var startTime = viewData.Start.ToTimestamp(); // Each entry in AggregationMap will be converted into an independent TimeSeries object foreach (var entry in viewData.AggregationMap) { var timeSeries = new TimeSeries(); - IReadOnlyList labels = entry.Key.Values; - IAggregationData points = entry.Value; + var labels = entry.Key.Values; + var points = entry.Value; timeSeries.Resource = monitoredResource; timeSeries.ValueType = view.Measure.ToValueType(view.Aggregation); @@ -280,7 +280,7 @@ public static List CreateTimeSeriesList( timeSeries.Metric = GetMetric(view, labels, metricDescriptor, domain); - Point point = ExtractPointInInterval(viewData.Start, viewData.End, view.Aggregation, points); + var point = ExtractPointInInterval(viewData.Start, viewData.End, view.Aggregation, points); var timeSeriesPoints = new List { point }; timeSeries.Points.AddRange(timeSeriesPoints); diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs index 7f5e4bb9c42..bcee64904f0 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs @@ -97,7 +97,7 @@ static StackdriverStatsExporter() { try { - string assemblyPackageVersion = typeof(StackdriverStatsExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; + var assemblyPackageVersion = typeof(StackdriverStatsExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; USER_AGENT = $"OpenTelemetry-dotnet/{assemblyPackageVersion}"; } catch (Exception) @@ -143,7 +143,7 @@ private void DoWork() { try { - TimeSpan sleepTime = collectionInterval; + var sleepTime = collectionInterval; var stopWatch = new Stopwatch(); while (!tokenSource.IsCancellationRequested) @@ -188,12 +188,12 @@ private bool RegisterView(IView view) } registeredViews.Add(view.Name, view); - string metricDescriptorTypeName = GenerateMetricDescriptorTypeName(view.Name, domain); + var metricDescriptorTypeName = GenerateMetricDescriptorTypeName(view.Name, domain); // TODO - zeltser: don't need to create MetricDescriptor for RpcViewConstants once we defined // canonical metrics. Registration is required only for custom view definitions. Canonical // views should be pre-registered. - MetricDescriptor metricDescriptor = MetricsConversions.CreateMetricDescriptor( + var metricDescriptor = MetricsConversions.CreateMetricDescriptor( metricDescriptorTypeName, view, project, @@ -253,13 +253,13 @@ private void Export() var timeSeriesList = new List(); foreach (var viewData in viewDataList) { - MetricDescriptor metricDescriptor = metricDescriptors[viewData.View]; - List timeSeries = MetricsConversions.CreateTimeSeriesList(viewData, monitoredResource, metricDescriptor, domain); + var metricDescriptor = metricDescriptors[viewData.View]; + var timeSeries = MetricsConversions.CreateTimeSeriesList(viewData, monitoredResource, metricDescriptor, domain); timeSeriesList.AddRange(timeSeries); } // Perform the operation in batches of MAX_BATCH_EXPORT_SIZE - foreach (IEnumerable batchedTimeSeries in timeSeriesList.Partition(MAX_BATCH_EXPORT_SIZE)) + foreach (var batchedTimeSeries in timeSeriesList.Partition(MAX_BATCH_EXPORT_SIZE)) { var request = new CreateTimeSeriesRequest(); request.ProjectName = project; diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs index a3d37848e64..94c598b6b93 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs @@ -39,7 +39,7 @@ static class SpanExtensions /// public static Span ToSpan(this SpanData spanData, string projectId) { - string spanId = spanData.Context.SpanId.ToLowerBase16(); + var spanId = spanData.Context.SpanId.ToLowerBase16(); // Base span settings var span = new Span @@ -53,7 +53,7 @@ public static Span ToSpan(this SpanData spanData, string projectId) }; if (spanData.ParentSpanId != null) { - string parentSpanId = spanData.ParentSpanId.ToLowerBase16(); + var parentSpanId = spanData.ParentSpanId.ToLowerBase16(); if (!string.IsNullOrEmpty(parentSpanId)) { span.ParentSpanId = parentSpanId; @@ -138,7 +138,7 @@ public StackdriverTraceExporter(string projectId) // Set header mutation for every outgoing API call to Stackdriver so the BE knows // which version of OC client is calling it as well as which version of the exporter - CallSettings callSettings = CallSettings.FromHeaderMutation(StackdriverCallHeaderAppender); + var callSettings = CallSettings.FromHeaderMutation(StackdriverCallHeaderAppender); traceServiceSettings = new TraceServiceSettings(); traceServiceSettings.CallSettings = callSettings; } @@ -147,7 +147,7 @@ static StackdriverTraceExporter() { try { - string assemblyPackageVersion = typeof(StackdriverTraceExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; + var assemblyPackageVersion = typeof(StackdriverTraceExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; STACKDRIVER_EXPORTER_VERSION = assemblyPackageVersion; } catch (Exception) @@ -167,7 +167,7 @@ static StackdriverTraceExporter() public async Task ExportAsync(IEnumerable spanDataList) { - TraceServiceClient traceWriter = TraceServiceClient.Create(settings: traceServiceSettings); + var traceWriter = TraceServiceClient.Create(settings: traceServiceSettings); var batchSpansRequest = new BatchWriteSpansRequest { diff --git a/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs index dd1c450cfa6..9697a4bed6b 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs @@ -95,9 +95,9 @@ public void Start() // Register stats(metrics) exporter if (viewManager != null) { - GoogleCredential credential = GetGoogleCredential(); + var credential = GetGoogleCredential(); - StackdriverStatsConfiguration statsConfig = StackdriverStatsConfiguration.Default; + var statsConfig = StackdriverStatsConfiguration.Default; statsConfig.GoogleCredential = credential; if (statsConfig.ProjectId != projectId) { diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs b/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs index 5f8e4ad2fea..70ff24b5f89 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs @@ -46,7 +46,7 @@ public static IEnumerable> Partition(this IEnumerable sourc private static IEnumerable WalkPartition(IEnumerator source, int size) { yield return source.Current; - for (int i = 0; i < size && source.MoveNext(); i++) + for (var i = 0; i < size && source.MoveNext(); i++) { yield return source.Current; } diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index 8fffe4c7688..d5de756ab20 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -50,7 +50,7 @@ public TraceExporterHandler(ZipkinTraceExporterOptions options, HttpClient clien public async Task ExportAsync(IEnumerable spanDataList) { - List zipkinSpans = new List(); + var zipkinSpans = new List(); foreach (var data in spanDataList) { @@ -70,11 +70,11 @@ public async Task ExportAsync(IEnumerable spanDataList) internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint) { - SpanContext context = spanData.Context; - long startTimestamp = this.ToEpochMicroseconds(spanData.StartTimestamp); - long endTimestamp = this.ToEpochMicroseconds(spanData.EndTimestamp); + var context = spanData.Context; + var startTimestamp = this.ToEpochMicroseconds(spanData.StartTimestamp); + var endTimestamp = this.ToEpochMicroseconds(spanData.EndTimestamp); - ZipkinSpan.Builder spanBuilder = + var spanBuilder = ZipkinSpan.NewBuilder() .TraceId(this.EncodeTraceId(context.TraceId)) .Id(this.EncodeSpanId(context.SpanId)) @@ -94,7 +94,7 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint spanBuilder.PutTag(label.Key, this.AttributeValueToString(label.Value)); } - Status status = spanData.Status; + var status = spanData.Status; if (status != null) { @@ -116,8 +116,8 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint private long ToEpochMicroseconds(Timestamp timestamp) { - long nanos = (timestamp.Seconds * NanosPerSecond) + timestamp.Nanos; - long micros = nanos / 1000L; + var nanos = (timestamp.Seconds * NanosPerSecond) + timestamp.Nanos; + var micros = nanos / 1000L; return micros; } @@ -172,7 +172,7 @@ private Task SendSpansAsync(IEnumerable spans) private async Task DoPost(HttpClient client, HttpRequestMessage request) { - using (HttpResponseMessage response = await client.SendAsync(request)) + using (var response = await client.SendAsync(request)) { if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Accepted) @@ -191,7 +191,7 @@ private HttpRequestMessage GetHttpRequestMessage(HttpMethod method, Uri requestU private HttpContent GetRequestContent(IEnumerable toSerialize) { - string content = string.Empty; + var content = string.Empty; try { content = JsonConvert.SerializeObject(toSerialize); @@ -211,7 +211,7 @@ private ZipkinEndpoint GetLocalZipkinEndpoint() ServiceName = this.options.ServiceName, }; - string hostName = this.ResolveHostName(); + var hostName = this.ResolveHostName(); if (!string.IsNullOrEmpty(hostName)) { diff --git a/src/OpenTelemetry/Context/Propagation/B3Format.cs b/src/OpenTelemetry/Context/Propagation/B3Format.cs index 97917eea320..bcd2d38973f 100644 --- a/src/OpenTelemetry/Context/Propagation/B3Format.cs +++ b/src/OpenTelemetry/Context/Propagation/B3Format.cs @@ -69,7 +69,7 @@ public SpanContext Extract(T carrier, Func> ge try { TraceId traceId; - string traceIdStr = getter(carrier, XB3TraceId)?.FirstOrDefault(); + var traceIdStr = getter(carrier, XB3TraceId)?.FirstOrDefault(); if (traceIdStr != null) { if (traceIdStr.Length == TraceId.Size) @@ -86,7 +86,7 @@ public SpanContext Extract(T carrier, Func> ge } SpanId spanId; - string spanIdStr = getter(carrier, XB3SpanId)?.FirstOrDefault(); + var spanIdStr = getter(carrier, XB3SpanId)?.FirstOrDefault(); if (spanIdStr != null) { spanId = SpanId.FromLowerBase16(spanIdStr); @@ -96,7 +96,7 @@ public SpanContext Extract(T carrier, Func> ge throw new SpanContextParseException("Missing X_B3_SPAN_ID."); } - TraceOptions traceOptions = TraceOptions.Default; + var traceOptions = TraceOptions.Default; if (SampledValue.Equals(getter(carrier, XB3Sampled)?.FirstOrDefault()) || FlagsValue.Equals(getter(carrier, XB3Flags)?.FirstOrDefault())) { diff --git a/src/OpenTelemetry/Implementation/OpenTelemetryEventSource.cs b/src/OpenTelemetry/Implementation/OpenTelemetryEventSource.cs index a87357f5565..504d49cad62 100644 --- a/src/OpenTelemetry/Implementation/OpenTelemetryEventSource.cs +++ b/src/OpenTelemetry/Implementation/OpenTelemetryEventSource.cs @@ -62,7 +62,7 @@ public void FailedReadingEnvironmentVariableWarning(string environmentVariableNa /// private static string ToInvariantString(Exception exception) { - CultureInfo originalUICulture = Thread.CurrentThread.CurrentUICulture; + var originalUICulture = Thread.CurrentThread.CurrentUICulture; try { diff --git a/src/OpenTelemetry/Internal/VarInt.cs b/src/OpenTelemetry/Internal/VarInt.cs index 310780b9567..24867cc1a60 100644 --- a/src/OpenTelemetry/Internal/VarInt.cs +++ b/src/OpenTelemetry/Internal/VarInt.cs @@ -29,8 +29,8 @@ public static class VarInt public static int VarIntSize(int i) { - int result = 0; - uint ui = (uint)i; + var result = 0; + var ui = (uint)i; do { result++; @@ -42,8 +42,8 @@ public static int VarIntSize(int i) public static int GetVarInt(byte[] src, int offset, int[] dst) { - int result = 0; - int shift = 0; + var result = 0; + var shift = 0; int b; do { @@ -65,13 +65,13 @@ public static int GetVarInt(byte[] src, int offset, int[] dst) public static int PutVarInt(int v, byte[] sink, int offset) { - uint uv = (uint)v; + var uv = (uint)v; do { // Encode next 7 bits + terminator bit - uint bits = uv & 0x7F; + var bits = uv & 0x7F; uv >>= 7; - byte b = (byte)(bits + ((uv != 0) ? 0x80 : 0)); + var b = (byte)(bits + ((uv != 0) ? 0x80 : 0)); sink[offset++] = b; } while (uv != 0); @@ -143,8 +143,8 @@ public static int PutVarInt(int v, byte[] sink, int offset) */ public static int GetVarInt(Stream inputStream) { - int result = 0; - int shift = 0; + var result = 0; + var shift = 0; int b; do { @@ -165,15 +165,15 @@ public static int GetVarInt(Stream inputStream) public static void PutVarInt(int v, Stream outputStream) { - byte[] bytes = new byte[VarIntSize(v)]; + var bytes = new byte[VarIntSize(v)]; PutVarInt(v, bytes, 0); outputStream.Write(bytes, 0, bytes.Length); } public static int VarLongSize(long v) { - int result = 0; - ulong uv = (ulong)v; + var result = 0; + var uv = (ulong)v; do { result++; diff --git a/src/OpenTelemetry/Stats/Aggregations/Count.cs b/src/OpenTelemetry/Stats/Aggregations/Count.cs index 5f188de96fb..a7d630d3020 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Count.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Count.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; return h; } } diff --git a/src/OpenTelemetry/Stats/Aggregations/Distribution.cs b/src/OpenTelemetry/Stats/Aggregations/Distribution.cs index acd32a75c73..51723b805d5 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Distribution.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Distribution.cs @@ -75,7 +75,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.BucketBoundaries.GetHashCode(); return h; diff --git a/src/OpenTelemetry/Stats/Aggregations/LastValue.cs b/src/OpenTelemetry/Stats/Aggregations/LastValue.cs index 89da52385f8..2efe4a141b0 100644 --- a/src/OpenTelemetry/Stats/Aggregations/LastValue.cs +++ b/src/OpenTelemetry/Stats/Aggregations/LastValue.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; return h; } } diff --git a/src/OpenTelemetry/Stats/Aggregations/Mean.cs b/src/OpenTelemetry/Stats/Aggregations/Mean.cs index 8da5438ca97..4d64f06d655 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Mean.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Mean.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; return h; } } diff --git a/src/OpenTelemetry/Stats/Aggregations/Sum.cs b/src/OpenTelemetry/Stats/Aggregations/Sum.cs index d8d62178f10..65bb1834a68 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Sum.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Sum.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; return h; } } diff --git a/src/OpenTelemetry/Stats/BucketBoundaries.cs b/src/OpenTelemetry/Stats/BucketBoundaries.cs index 0fefd3bb3de..e856815bb6b 100644 --- a/src/OpenTelemetry/Stats/BucketBoundaries.cs +++ b/src/OpenTelemetry/Stats/BucketBoundaries.cs @@ -37,14 +37,14 @@ public static IBucketBoundaries Create(IEnumerable bucketBoundaries) throw new ArgumentNullException(nameof(bucketBoundaries)); } - List bucketBoundariesCopy = new List(bucketBoundaries); + var bucketBoundariesCopy = new List(bucketBoundaries); if (bucketBoundariesCopy.Count > 1) { - double lower = bucketBoundariesCopy[0]; - for (int i = 1; i < bucketBoundariesCopy.Count; i++) + var lower = bucketBoundariesCopy[0]; + for (var i = 1; i < bucketBoundariesCopy.Count; i++) { - double next = bucketBoundariesCopy[i]; + var next = bucketBoundariesCopy[i]; if (!(lower < next)) { throw new ArgumentOutOfRangeException("Bucket boundaries not sorted."); @@ -84,7 +84,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Boundaries.GetHashCode(); return h; diff --git a/src/OpenTelemetry/Stats/MeasureMapBuilder.cs b/src/OpenTelemetry/Stats/MeasureMapBuilder.cs index 86cb4f04f2f..817bda6c231 100644 --- a/src/OpenTelemetry/Stats/MeasureMapBuilder.cs +++ b/src/OpenTelemetry/Stats/MeasureMapBuilder.cs @@ -46,9 +46,9 @@ internal IEnumerable Build() // Note: this makes adding measurements quadratic but is fastest for the sizes of // MeasureMapInternals that we should see. We may want to go to a strategy of sort/eliminate // for larger MeasureMapInternals. - for (int i = this.measurements.Count - 1; i >= 0; i--) + for (var i = this.measurements.Count - 1; i >= 0; i--) { - for (int j = i - 1; j >= 0; j--) + for (var j = i - 1; j >= 0; j--) { if (this.measurements[i].Measure == this.measurements[j].Measure) { diff --git a/src/OpenTelemetry/Stats/MeasureToViewMap.cs b/src/OpenTelemetry/Stats/MeasureToViewMap.cs index b0b8a3b1daa..3c4ee1c6e05 100644 --- a/src/OpenTelemetry/Stats/MeasureToViewMap.cs +++ b/src/OpenTelemetry/Stats/MeasureToViewMap.cs @@ -42,7 +42,7 @@ internal ISet ExportedViews { get { - ISet views = this.exportedViews; + var views = this.exportedViews; if (views == null) { lock (this.lck) @@ -59,7 +59,7 @@ internal IViewData GetView(IViewName viewName, StatsCollectionState state) { lock (this.lck) { - MutableViewData view = this.GetMutableViewData(viewName); + var view = this.GetMutableViewData(viewName); return view?.ToViewData(DateTimeOffset.Now, state); } } @@ -70,7 +70,7 @@ internal void RegisterView(IView view) lock (this.lck) { this.exportedViews = null; - this.registeredViews.TryGetValue(view.Name, out IView existing); + this.registeredViews.TryGetValue(view.Name, out var existing); if (existing != null) { if (existing.Equals(view)) @@ -84,8 +84,8 @@ internal void RegisterView(IView view) } } - IMeasure measure = view.Measure; - this.registeredMeasures.TryGetValue(measure.Name, out IMeasure registeredMeasure); + var measure = view.Measure; + this.registeredMeasures.TryGetValue(measure.Name, out var registeredMeasure); if (registeredMeasure != null && !registeredMeasure.Equals(measure)) { throw new ArgumentException("A different measure with the same name is already registered: " + registeredMeasure); @@ -108,8 +108,8 @@ internal void Record(ITagContext tags, IEnumerable stats, DateTime { foreach (var measurement in stats) { - IMeasure measure = measurement.Measure; - this.registeredMeasures.TryGetValue(measure.Name, out IMeasure value); + var measure = measurement.Measure; + this.registeredMeasures.TryGetValue(measure.Name, out var value); if (!measure.Equals(value)) { // unregistered measures will be ignored. @@ -117,7 +117,7 @@ internal void Record(ITagContext tags, IEnumerable stats, DateTime } var views = this.mutableMap[measure.Name]; - foreach (MutableViewData view in views) + foreach (var view in views) { measurement.Match( (arg) => @@ -146,7 +146,7 @@ internal void ClearStats() { foreach (var entry in this.mutableMap) { - foreach (MutableViewData mutableViewData in entry.Value) + foreach (var mutableViewData in entry.Value) { mutableViewData.ClearStats(); } @@ -161,7 +161,7 @@ internal void ResumeStatsCollection(DateTimeOffset now) { foreach (var entry in this.mutableMap) { - foreach (MutableViewData mutableViewData in entry.Value) + foreach (var mutableViewData in entry.Value) { mutableViewData.ResumeStatsCollection(now); } @@ -191,16 +191,16 @@ private MutableViewData GetMutableViewData(IViewName viewName) { lock (this.lck) { - this.registeredViews.TryGetValue(viewName, out IView view); + this.registeredViews.TryGetValue(viewName, out var view); if (view == null) { return null; } - this.mutableMap.TryGetValue(view.Measure.Name, out ICollection views); + this.mutableMap.TryGetValue(view.Measure.Name, out var views); if (views != null) { - foreach (MutableViewData viewData in views) + foreach (var viewData in views) { if (viewData.View.Name.Equals(viewName)) { diff --git a/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs b/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs index d90ae4b26d6..171d1df8baf 100644 --- a/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs +++ b/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs @@ -85,7 +85,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Name.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Stats/Measures/MeasureLong.cs b/src/OpenTelemetry/Stats/Measures/MeasureLong.cs index f733d768520..cdcac40ed59 100644 --- a/src/OpenTelemetry/Stats/Measures/MeasureLong.cs +++ b/src/OpenTelemetry/Stats/Measures/MeasureLong.cs @@ -85,7 +85,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Name.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Stats/MutableCount.cs b/src/OpenTelemetry/Stats/MutableCount.cs index 7917da93ca7..b8afb83eb09 100644 --- a/src/OpenTelemetry/Stats/MutableCount.cs +++ b/src/OpenTelemetry/Stats/MutableCount.cs @@ -44,7 +44,7 @@ internal override void Combine(MutableAggregation other, double fraction) } var result = fraction * mutable.Count; - long rounded = (long)Math.Round(result); + var rounded = (long)Math.Round(result); this.Count += rounded; } diff --git a/src/OpenTelemetry/Stats/MutableDistribution.cs b/src/OpenTelemetry/Stats/MutableDistribution.cs index 9892ab8217a..de81f97e942 100644 --- a/src/OpenTelemetry/Stats/MutableDistribution.cs +++ b/src/OpenTelemetry/Stats/MutableDistribution.cs @@ -68,9 +68,9 @@ internal override void Add(double value) * https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance, or Knuth, "The Art of * Computer Programming", Vol. 2, page 323, 3rd edition) */ - double deltaFromMean = value - this.Mean; + var deltaFromMean = value - this.Mean; this.Mean += deltaFromMean / this.Count; - double deltaFromMean2 = value - this.Mean; + var deltaFromMean2 = value - this.Mean; this.SumOfSquaredDeviations += deltaFromMean * deltaFromMean2; if (value < this.Min) @@ -83,7 +83,7 @@ internal override void Add(double value) this.Max = value; } - for (int i = 0; i < this.BucketBoundaries.Boundaries.Count; i++) + for (var i = 0; i < this.BucketBoundaries.Boundaries.Count; i++) { if (value < this.BucketBoundaries.Boundaries[i]) { @@ -117,7 +117,7 @@ internal override void Combine(MutableAggregation other, double fraction) // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm. if (this.Count + mutableDistribution.Count > 0) { - double delta = mutableDistribution.Mean - this.Mean; + var delta = mutableDistribution.Mean - this.Mean; this.SumOfSquaredDeviations = this.SumOfSquaredDeviations + mutableDistribution.SumOfSquaredDeviations @@ -141,8 +141,8 @@ internal override void Combine(MutableAggregation other, double fraction) this.Max = mutableDistribution.Max; } - long[] bucketCounts = mutableDistribution.BucketCounts; - for (int i = 0; i < bucketCounts.Length; i++) + var bucketCounts = mutableDistribution.BucketCounts; + for (var i = 0; i < bucketCounts.Length; i++) { this.BucketCounts[i] += bucketCounts[i]; } diff --git a/src/OpenTelemetry/Stats/MutableLastValue.cs b/src/OpenTelemetry/Stats/MutableLastValue.cs index bc3afc9388b..74d28a09754 100644 --- a/src/OpenTelemetry/Stats/MutableLastValue.cs +++ b/src/OpenTelemetry/Stats/MutableLastValue.cs @@ -52,7 +52,7 @@ internal override void Combine(MutableAggregation other, double fraction) throw new ArgumentException("MutableLastValue expected."); } - MutableLastValue otherValue = (MutableLastValue)other; + var otherValue = (MutableLastValue)other; // Assume other is always newer than this, because we combined interval buckets in time order. // If there's a newer value, overwrite current value. diff --git a/src/OpenTelemetry/Stats/MutableMean.cs b/src/OpenTelemetry/Stats/MutableMean.cs index b6dc0482fbf..c88820830ce 100644 --- a/src/OpenTelemetry/Stats/MutableMean.cs +++ b/src/OpenTelemetry/Stats/MutableMean.cs @@ -68,7 +68,7 @@ internal override void Combine(MutableAggregation other, double fraction) } var result = fraction * mutable.Count; - long rounded = (long)Math.Round(result); + var rounded = (long)Math.Round(result); this.Count += rounded; this.Sum += mutable.Sum * fraction; diff --git a/src/OpenTelemetry/Stats/MutableViewData.cs b/src/OpenTelemetry/Stats/MutableViewData.cs index b7a4390075b..f79c41b6097 100644 --- a/src/OpenTelemetry/Stats/MutableViewData.cs +++ b/src/OpenTelemetry/Stats/MutableViewData.cs @@ -56,8 +56,8 @@ protected MutableViewData(IView view) private static Func CreateDistributionData { get; } = (s) => { - List boxedBucketCounts = new List(); - foreach (long bucketCount in s.BucketCounts) + var boxedBucketCounts = new List(); + foreach (var bucketCount in s.BucketCounts) { boxedBucketCounts.Add(bucketCount); } @@ -91,13 +91,13 @@ internal static IDictionary GetTagMap(ITagContext ctx) internal static IReadOnlyList GetTagValues(IDictionary tags, IReadOnlyList columns) { - List tagValues = new List(columns.Count); + var tagValues = new List(columns.Count); // Record all the measures in a "Greedy" way. // Every view aggregates every measure. This is similar to doing a GROUPBY view’s keys. - for (int i = 0; i < columns.Count; ++i) + for (var i = 0; i < columns.Count; ++i) { - TagKey tagKey = columns[i]; + var tagKey = columns[i]; if (!tags.ContainsKey(tagKey)) { // replace not found key values by null. diff --git a/src/OpenTelemetry/Stats/NoopViewManager.cs b/src/OpenTelemetry/Stats/NoopViewManager.cs index 46e3dc757d8..8a54274a1da 100644 --- a/src/OpenTelemetry/Stats/NoopViewManager.cs +++ b/src/OpenTelemetry/Stats/NoopViewManager.cs @@ -36,7 +36,7 @@ public override ISet AllExportedViews { get { - ISet views = this.exportedViews; + var views = this.exportedViews; if (views == null) { lock (this.registeredViews) @@ -60,7 +60,7 @@ public override void RegisterView(IView newView) lock (this.registeredViews) { this.exportedViews = null; - this.registeredViews.TryGetValue(newView.Name, out IView existing); + this.registeredViews.TryGetValue(newView.Name, out var existing); if (!(existing == null || newView.Equals(existing))) { throw new ArgumentException("A different view with the same name already exists."); @@ -82,7 +82,7 @@ public override IViewData GetView(IViewName name) lock (this.registeredViews) { - this.registeredViews.TryGetValue(name, out IView view); + this.registeredViews.TryGetValue(name, out var view); if (view == null) { return null; @@ -102,7 +102,7 @@ public override IViewData GetView(IViewName name) private static ISet FilterExportedViews(ICollection allViews) { ISet views = new HashSet(); - foreach (IView view in allViews) + foreach (var view in allViews) { // if (view.getWindow() instanceof View.AggregationWindow.Interval) { // continue; diff --git a/src/OpenTelemetry/Stats/StatsComponent.cs b/src/OpenTelemetry/Stats/StatsComponent.cs index 4014a0e3127..fe3a8f02ec3 100644 --- a/src/OpenTelemetry/Stats/StatsComponent.cs +++ b/src/OpenTelemetry/Stats/StatsComponent.cs @@ -33,7 +33,7 @@ public StatsComponent() public StatsComponent(IEventQueue queue) { - StatsManager statsManager = new StatsManager(queue, this.state); + var statsManager = new StatsManager(queue, this.state); this.viewManager = new ViewManager(statsManager); this.statsRecorder = new StatsRecorder(statsManager); } diff --git a/src/OpenTelemetry/Stats/StatsExtensions.cs b/src/OpenTelemetry/Stats/StatsExtensions.cs index 3f927a5f251..4c507574d0e 100644 --- a/src/OpenTelemetry/Stats/StatsExtensions.cs +++ b/src/OpenTelemetry/Stats/StatsExtensions.cs @@ -44,7 +44,7 @@ public static IAggregationData SumWithTags(this IViewData viewData, IEnumerable< public static IDictionary WithTags(this IDictionary aggMap, IEnumerable values) { - Dictionary results = new Dictionary(); + var results = new Dictionary(); foreach (var kvp in aggMap) { @@ -60,7 +60,7 @@ public static IDictionary WithTags(this IDictionary public static IAggregationData Sum(this IDictionary aggMap, IView view) { var sum = MutableViewData.CreateMutableAggregation(view.Aggregation); - foreach (IAggregationData agData in aggMap.Values) + foreach (var agData in aggMap.Values) { Sum(sum, agData); } @@ -159,7 +159,7 @@ private static void Sum(MutableAggregation combined, IAggregationData data) // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm. if (dist.Count + arg.Count > 0) { - double delta = arg.Mean - dist.Mean; + var delta = arg.Mean - dist.Mean; dist.SumOfSquaredDeviations = dist.SumOfSquaredDeviations + arg.SumOfSquaredDeviations @@ -183,8 +183,8 @@ private static void Sum(MutableAggregation combined, IAggregationData data) dist.Max = arg.Max; } - IReadOnlyList bucketCounts = arg.BucketCounts; - for (int i = 0; i < bucketCounts.Count; i++) + var bucketCounts = arg.BucketCounts; + for (var i = 0; i < bucketCounts.Count; i++) { dist.BucketCounts[i] += bucketCounts[i]; } diff --git a/src/OpenTelemetry/Stats/View.cs b/src/OpenTelemetry/Stats/View.cs index 815004e52bf..a06a7862f53 100644 --- a/src/OpenTelemetry/Stats/View.cs +++ b/src/OpenTelemetry/Stats/View.cs @@ -93,7 +93,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.Name.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Stats/ViewData.cs b/src/OpenTelemetry/Stats/ViewData.cs index ec37861b314..a60db008df2 100644 --- a/src/OpenTelemetry/Stats/ViewData.cs +++ b/src/OpenTelemetry/Stats/ViewData.cs @@ -91,7 +91,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.View.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Stats/ViewName.cs b/src/OpenTelemetry/Stats/ViewName.cs index ff7ce75978d..0dcff6e15a2 100644 --- a/src/OpenTelemetry/Stats/ViewName.cs +++ b/src/OpenTelemetry/Stats/ViewName.cs @@ -75,7 +75,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.AsString.GetHashCode(); return h; diff --git a/src/OpenTelemetry/Tags/Propagation/SerializationUtils.cs b/src/OpenTelemetry/Tags/Propagation/SerializationUtils.cs index 0af894c6de9..afbf730736b 100644 --- a/src/OpenTelemetry/Tags/Propagation/SerializationUtils.cs +++ b/src/OpenTelemetry/Tags/Propagation/SerializationUtils.cs @@ -36,10 +36,10 @@ internal static byte[] SerializeBinary(ITagContext tags) { // Use a ByteArrayDataOutput to avoid needing to handle IOExceptions. // ByteArrayDataOutput byteArrayDataOutput = ByteStreams.newDataOutput(); - MemoryStream byteArrayDataOutput = new MemoryStream(); + var byteArrayDataOutput = new MemoryStream(); byteArrayDataOutput.WriteByte(VersionId); - int totalChars = 0; // Here chars are equivalent to bytes, since we're using ascii chars. + var totalChars = 0; // Here chars are equivalent to bytes, since we're using ascii chars. foreach (var tag in tags) { totalChars += tag.Key.Name.Length; @@ -75,8 +75,8 @@ internal static ITagContext DeserializeBinary(byte[] bytes) throw new TagContextDeserializationException("Input byte[] can not be empty."); } - MemoryStream buffer = new MemoryStream(bytes); - int versionId = buffer.ReadByte(); + var buffer = new MemoryStream(bytes); + var versionId = buffer.ReadByte(); if (versionId > VersionId || versionId < 0) { throw new TagContextDeserializationException( @@ -94,15 +94,15 @@ internal static ITagContext DeserializeBinary(byte[] bytes) internal static IDictionary ParseTags(MemoryStream buffer) { IDictionary tags = new Dictionary(); - long limit = buffer.Length; - int totalChars = 0; // Here chars are equivalent to bytes, since we're using ascii chars. + var limit = buffer.Length; + var totalChars = 0; // Here chars are equivalent to bytes, since we're using ascii chars. while (buffer.Position < limit) { - int type = buffer.ReadByte(); + var type = buffer.ReadByte(); if (type == TagFieldId) { - TagKey key = CreateTagKey(DecodeString(buffer)); - TagValue val = CreateTagValue(key, DecodeString(buffer)); + var key = CreateTagKey(DecodeString(buffer)); + var val = CreateTagValue(key, DecodeString(buffer)); totalChars += key.Name.Length; totalChars += val.AsString.Length; tags[key] = val; @@ -170,16 +170,16 @@ private static void EncodeString(string input, MemoryStream byteArrayDataOutput) private static void PutVarInt(int input, MemoryStream byteArrayDataOutput) { - byte[] output = new byte[VarInt.VarIntSize(input)]; + var output = new byte[VarInt.VarIntSize(input)]; VarInt.PutVarInt(input, output, 0); byteArrayDataOutput.Write(output, 0, output.Length); } private static string DecodeString(MemoryStream buffer) { - int length = VarInt.GetVarInt(buffer); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < length; i++) + var length = VarInt.GetVarInt(buffer); + var builder = new StringBuilder(); + for (var i = 0; i < length; i++) { builder.Append((char)buffer.ReadByte()); } diff --git a/src/OpenTelemetry/Tags/TagContextBase.cs b/src/OpenTelemetry/Tags/TagContextBase.cs index 664c53b4ed9..e13046d54de 100644 --- a/src/OpenTelemetry/Tags/TagContextBase.cs +++ b/src/OpenTelemetry/Tags/TagContextBase.cs @@ -37,7 +37,7 @@ public override bool Equals(object other) return false; } - TagContextBase otherTags = (TagContextBase)other; + var otherTags = (TagContextBase)other; var t1Enumerator = this.GetEnumerator(); var t2Enumerator = otherTags.GetEnumerator(); @@ -69,7 +69,7 @@ public override bool Equals(object other) /// public override int GetHashCode() { - int hashCode = 0; + var hashCode = 0; foreach (var t in this) { hashCode += t.GetHashCode(); diff --git a/src/OpenTelemetry/Tags/Tagger.cs b/src/OpenTelemetry/Tags/Tagger.cs index 39ba7012f1a..bf1d25fe0a8 100644 --- a/src/OpenTelemetry/Tags/Tagger.cs +++ b/src/OpenTelemetry/Tags/Tagger.cs @@ -85,7 +85,7 @@ private static ITagContext ToTagContext(ITagContext tags) } else { - TagContextBuilder builder = new TagContextBuilder(); + var builder = new TagContextBuilder(); foreach (var tag in tags) { if (tag != null) @@ -107,7 +107,7 @@ private static ITagContextBuilder ToTagContextBuilder(ITagContext tags) } else { - TagContextBuilder builder = new TagContextBuilder(); + var builder = new TagContextBuilder(); foreach (var tag in tags) { if (tag != null) diff --git a/src/OpenTelemetry/Trace/EndSpanOptions.cs b/src/OpenTelemetry/Trace/EndSpanOptions.cs index 1c8dd820109..c13c3016174 100644 --- a/src/OpenTelemetry/Trace/EndSpanOptions.cs +++ b/src/OpenTelemetry/Trace/EndSpanOptions.cs @@ -75,7 +75,7 @@ public override bool Equals(object obj) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.SampleToLocalSpanStore ? 1231 : 1237; h *= 1000003; diff --git a/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs b/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs index 473192e9e3d..11c295ab8c7 100644 --- a/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs +++ b/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs @@ -58,7 +58,7 @@ public EndSpanOptionsBuilder SetStatus(Status status) /// Span options instance. public EndSpanOptions Build() { - string missing = string.Empty; + var missing = string.Empty; if (!this.sampleToLocalSpanStore.HasValue) { missing += " sampleToLocalSpanStore"; diff --git a/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs b/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs index c131364e51e..359973f67a6 100644 --- a/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs +++ b/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.NumRunningSpans; return h; diff --git a/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs b/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs index f71339b6a1a..24a8669cf93 100644 --- a/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs +++ b/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs @@ -79,7 +79,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.NumbersOfLatencySampledSpans.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Trace/Export/SpanExporter.cs b/src/OpenTelemetry/Trace/Export/SpanExporter.cs index 7b333f9d36a..e3bf9644e93 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporter.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporter.cs @@ -76,7 +76,7 @@ public override void Dispose() internal static ISpanExporter Create(int bufferSize, Duration scheduleDelay) { - SpanExporterWorker worker = new SpanExporterWorker(bufferSize, scheduleDelay); + var worker = new SpanExporterWorker(bufferSize, scheduleDelay); return new SpanExporter(worker); } } diff --git a/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs b/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs index 8831e8af808..becf77c0aa1 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs @@ -92,12 +92,12 @@ internal async Task ExportAsync(IEnumerable export, CancellationToken internal async void Run(object obj) { - List toExport = new List(); + var toExport = new List(); while (!this.shutdown) { try { - if (this.spans.TryTake(out ISpan item, this.scheduleDelay)) + if (this.spans.TryTake(out var item, this.scheduleDelay)) { // Build up list this.BuildList(item, toExport); @@ -129,7 +129,7 @@ internal void RegisterHandler(string name, IHandler handler) internal void UnregisterHandler(string name) { - this.serviceHandlers.TryRemove(name, out IHandler prev); + this.serviceHandlers.TryRemove(name, out var prev); } internal SpanData ToSpanData(ISpan span) diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs index 6e1173f28fc..4b0f69e2ba0 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs @@ -38,22 +38,22 @@ public override IRunningSpanStoreSummary Summary get { IEnumerable allRunningSpans = this.runningSpans.Copy(); - Dictionary numSpansPerName = new Dictionary(); + var numSpansPerName = new Dictionary(); foreach (var span in allRunningSpans) { - numSpansPerName.TryGetValue(span.Name, out int prevValue); + numSpansPerName.TryGetValue(span.Name, out var prevValue); numSpansPerName[span.Name] = prevValue + 1; } - Dictionary perSpanNameSummary = new Dictionary(); + var perSpanNameSummary = new Dictionary(); foreach (var it in numSpansPerName) { - int numRunningSpans = it.Value; + var numRunningSpans = it.Value; var runningPerSpanNameSummary = RunningPerSpanNameSummary.Create(numRunningSpans); perSpanNameSummary[it.Key] = runningPerSpanNameSummary; } - IRunningSpanStoreSummary summary = RunningSpanStoreSummary.Create(perSpanNameSummary); + var summary = RunningSpanStoreSummary.Create(perSpanNameSummary); return summary; } } @@ -62,8 +62,8 @@ public override IRunningSpanStoreSummary Summary public override IEnumerable GetRunningSpans(IRunningSpanStoreFilter filter) { IReadOnlyCollection allRunningSpans = this.runningSpans.Copy(); - int maxSpansToReturn = filter.MaxSpansToReturn == 0 ? allRunningSpans.Count : filter.MaxSpansToReturn; - List ret = new List(maxSpansToReturn); + var maxSpansToReturn = filter.MaxSpansToReturn == 0 ? allRunningSpans.Count : filter.MaxSpansToReturn; + var ret = new List(maxSpansToReturn); foreach (var span in allRunningSpans) { if (ret.Count == maxSpansToReturn) diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs index 73e0fd2a021..ac1ab678498 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs @@ -51,7 +51,7 @@ public override ISampledSpanStoreSummary Summary { get { - Dictionary ret = new Dictionary(); + var ret = new Dictionary(); lock (this.samples) { foreach (var it in this.samples) @@ -83,13 +83,13 @@ public override void ConsiderForSampling(ISpan ispan) { lock (this.samples) { - string spanName = span.Name; + var spanName = span.Name; if (span.IsSampleToLocalSpanStore && !this.samples.ContainsKey(spanName)) { this.samples[spanName] = new PerSpanNameSamples(); } - this.samples.TryGetValue(spanName, out PerSpanNameSamples perSpanNameSamples); + this.samples.TryGetValue(spanName, out var perSpanNameSamples); if (perSpanNameSamples != null) { perSpanNameSamples.ConsiderForSampling(span); @@ -101,21 +101,21 @@ public override void ConsiderForSampling(ISpan ispan) /// public override IEnumerable GetErrorSampledSpans(ISampledSpanStoreErrorFilter filter) { - int numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; - IEnumerable spans = Enumerable.Empty(); + var numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; + var spans = Enumerable.Empty(); // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. lock (this.samples) { - PerSpanNameSamples perSpanNameSamples = this.samples[filter.SpanName]; + var perSpanNameSamples = this.samples[filter.SpanName]; if (perSpanNameSamples != null) { spans = perSpanNameSamples.GetErrorSamples(filter.CanonicalCode, numSpansToReturn); } } - List ret = new List(spans.Count()); - foreach (SpanBase span in spans) + var ret = new List(spans.Count()); + foreach (var span in spans) { ret.Add(span.ToSpanData()); } @@ -126,21 +126,21 @@ public override IEnumerable GetErrorSampledSpans(ISampledSpanStoreErro /// public override IEnumerable GetLatencySampledSpans(ISampledSpanStoreLatencyFilter filter) { - int numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; - IEnumerable spans = Enumerable.Empty(); + var numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; + var spans = Enumerable.Empty(); // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. lock (this.samples) { - PerSpanNameSamples perSpanNameSamples = this.samples[filter.SpanName]; + var perSpanNameSamples = this.samples[filter.SpanName]; if (perSpanNameSamples != null) { spans = perSpanNameSamples.GetLatencySamples(filter.LatencyLower, filter.LatencyUpper, numSpansToReturn); } } - List ret = new List(spans.Count()); - foreach (SpanBase span in spans) + var ret = new List(spans.Count()); + foreach (var span in spans) { ret.Add(span.ToSpanData()); } @@ -164,7 +164,7 @@ internal void InternalUnregisterSpanNamesForCollection(ICollection spanN { lock (this.samples) { - foreach (string spanName in spanNames) + foreach (var spanName in spanNames) { this.samples.Remove(spanName); } @@ -175,7 +175,7 @@ internal void InternaltRegisterSpanNamesForCollection(ICollection spanNa { lock (this.samples) { - foreach (string spanName in spanNames) + foreach (var spanName in spanNames) { if (!this.samples.ContainsKey(spanName)) { @@ -201,9 +201,9 @@ public Bucket(int numSamples) public static void GetSamples( int maxSpansToReturn, ICollection output, EvictingQueue queue) { - SpanBase[] copy = queue.ToArray(); + var copy = queue.ToArray(); - foreach (SpanBase span in copy) + foreach (var span in copy) { if (output.Count >= maxSpansToReturn) { @@ -221,8 +221,8 @@ public static void GetSamplesFilteredByLatency( ICollection output, EvictingQueue queue) { - SpanBase[] copy = queue.ToArray(); - foreach (SpanBase span in copy) + var copy = queue.ToArray(); + foreach (var span in copy) { if (output.Count >= maxSpansToReturn) { @@ -293,13 +293,13 @@ private sealed class PerSpanNameSamples public PerSpanNameSamples() { this.latencyBuckets = new Bucket[NumLatencyBuckets]; - for (int i = 0; i < NumLatencyBuckets; i++) + for (var i = 0; i < NumLatencyBuckets; i++) { this.latencyBuckets[i] = new Bucket(NumSamplesPerLatencySamples); } this.errorBuckets = new Bucket[NumErrorBuckets]; - for (int i = 0; i < NumErrorBuckets; i++) + for (var i = 0; i < NumErrorBuckets; i++) { this.errorBuckets[i] = new Bucket(NumSamplesPerErrorSamples); } @@ -307,9 +307,9 @@ public PerSpanNameSamples() public Bucket GetLatencyBucket(TimeSpan latency) { - for (int i = 0; i < NumLatencyBuckets; i++) + for (var i = 0; i < NumLatencyBuckets; i++) { - ISampledLatencyBucketBoundaries boundaries = LatencyBucketBoundaries.Values[i]; + var boundaries = LatencyBucketBoundaries.Values[i]; if (latency >= boundaries.LatencyLower && latency < boundaries.LatencyUpper) { @@ -329,13 +329,13 @@ public Bucket GetErrorBucket(CanonicalCode code) public void ConsiderForSampling(SpanBase span) { - Status status = span.Status; + var status = span.Status; // Null status means running Span, this should not happen in production, but the library // should not crash because of this. if (status != null) { - Bucket bucket = + var bucket = status.IsOk ? this.GetLatencyBucket(span.Latency) : this.GetErrorBucket(status.CanonicalCode); @@ -351,7 +351,7 @@ public void ConsiderForSampling(SpanBase span) public IDictionary GetNumbersOfLatencySampledSpans() { IDictionary latencyBucketSummaries = new Dictionary(); - for (int i = 0; i < NumLatencyBuckets; i++) + for (var i = 0; i < NumLatencyBuckets; i++) { latencyBucketSummaries[LatencyBucketBoundaries.Values[i]] = this.latencyBuckets[i].GetNumSamples(); } @@ -362,7 +362,7 @@ public IDictionary GetNumbersOfLatencySamp public IDictionary GetNumbersOfErrorSampledSpans() { IDictionary errorBucketSummaries = new Dictionary(); - for (int i = 0; i < NumErrorBuckets; i++) + for (var i = 0; i < NumErrorBuckets; i++) { errorBucketSummaries[(CanonicalCode)i + 1] = this.errorBuckets[i].GetNumSamples(); } @@ -372,14 +372,14 @@ public IDictionary GetNumbersOfErrorSampledSpans() public IEnumerable GetErrorSamples(CanonicalCode? code, int maxSpansToReturn) { - List output = new List(maxSpansToReturn); + var output = new List(maxSpansToReturn); if (code.HasValue) { this.GetErrorBucket(code.Value).GetSamples(maxSpansToReturn, output); } else { - for (int i = 0; i < NumErrorBuckets; i++) + for (var i = 0; i < NumErrorBuckets; i++) { this.errorBuckets[i].GetSamples(maxSpansToReturn, output); } @@ -390,10 +390,10 @@ public IEnumerable GetErrorSamples(CanonicalCode? code, int maxSpansTo public IEnumerable GetLatencySamples(TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn) { - List output = new List(maxSpansToReturn); - for (int i = 0; i < NumLatencyBuckets; i++) + var output = new List(maxSpansToReturn); + for (var i = 0; i < NumLatencyBuckets; i++) { - ISampledLatencyBucketBoundaries boundaries = LatencyBucketBoundaries.Values[i]; + var boundaries = LatencyBucketBoundaries.Values[i]; if (latencyUpper >= boundaries.LatencyLower && latencyLower < boundaries.LatencyUpper) { diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs index c86e35db561..4a265fa1970 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs @@ -37,7 +37,7 @@ public override ISampledSpanStoreSummary Summary IDictionary result = new Dictionary(); lock (this.registeredSpanNames) { - foreach (string registeredSpanName in this.registeredSpanNames) + foreach (var registeredSpanName in this.registeredSpanNames) { result[registeredSpanName] = EmptyPerSpanNameSummary; } diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs index 2167153a1a5..77a28b153e2 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs @@ -69,7 +69,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.SpanName.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs index 05c49a3696c..2ddf980cf68 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs @@ -68,7 +68,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.PerSpanNameSummary.GetHashCode(); return h; diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs index 6aa7b8eb227..7ee64dff88c 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs @@ -79,7 +79,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.SpanName.GetHashCode(); h *= 1000003; diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs index abd9dd1c61f..3abb574c385 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs @@ -68,7 +68,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { - int h = 1; + var h = 1; h *= 1000003; h ^= this.PerSpanNameSummary.GetHashCode(); return h; diff --git a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs index 03b5245193f..3b16929566a 100644 --- a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs +++ b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs @@ -51,7 +51,7 @@ public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId span if (parentLinks != null) { // If any parent link is sampled keep the sampling decision. - foreach (ISpan parentLink in parentLinks) + foreach (var parentLink in parentLinks) { if (parentLink.Context.TraceOptions.IsSampled) { diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index 1fccf1f33d6..09e913e3824 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -345,11 +345,11 @@ public override SpanData ToSpanData() throw new InvalidOperationException("Getting SpanData for a Span without RECORD_EVENTS option."); } - Attributes attributesSpanData = this.attributes == null ? Attributes.Create(new Dictionary(), 0) + var attributesSpanData = this.attributes == null ? Attributes.Create(new Dictionary(), 0) : Attributes.Create(this.attributes, this.attributes.NumberOfDroppedAttributes); - ITimedEvents annotationsSpanData = CreateTimedEvents(this.InitializedEvents, this.TimestampConverter); - LinkList linksSpanData = this.links == null ? LinkList.Create(new List(), 0) : LinkList.Create(this.links.Events, this.links.NumberOfDroppedEvents); + var annotationsSpanData = CreateTimedEvents(this.InitializedEvents, this.TimestampConverter); + var linksSpanData = this.links == null ? LinkList.Create(new List(), 0) : LinkList.Create(this.links.Events, this.links.NumberOfDroppedEvents); return SpanData.Create( this.Context, @@ -449,7 +449,7 @@ private static ITimedEvents CreateTimedEvents(TraceEvents } var eventsList = new List>(events.Events.Count); - foreach (EventWithTime networkEvent in events.Events) + foreach (var networkEvent in events.Events) { eventsList.Add(networkEvent.ToSpanDataTimedEvent(timestampConverter)); } diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index e323ec95867..55f5d14f2c6 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -50,13 +50,13 @@ private SpanBuilder(string name, SpanKind kind, SpanBuilderOptions options, Span /// public override ISpan StartSpan() { - SpanContext parentContext = this.ParentSpanContext; + var parentContext = this.ParentSpanContext; Timer timestampConverter = null; if (this.ParentSpanContext == null) { // This is not a child of a remote Span. Get the parent SpanContext from the parent Span if // any. - ISpan parent = this.Parent; + var parent = this.Parent; if (parent != null) { parentContext = parent.Context; @@ -112,7 +112,7 @@ internal static ISpanBuilder Create(string name, SpanKind kind, SpanContext pare private static bool IsAnyParentLinkSampled(IEnumerable parentLinks) { - foreach (ISpan parentLink in parentLinks) + foreach (var parentLink in parentLinks) { if (parentLink.Context.TraceOptions.IsSampled) { @@ -127,8 +127,8 @@ private static void LinkSpans(ISpan span, IEnumerable parentLinks) { if (parentLinks.Any()) { - ILink childLink = Link.FromSpanContext(span.Context); - foreach (ISpan linkedSpan in parentLinks) + var childLink = Link.FromSpanContext(span.Context); + foreach (var linkedSpan in parentLinks) { linkedSpan.AddLink(childLink); span.AddLink(Link.FromSpanContext(linkedSpan.Context)); @@ -172,10 +172,10 @@ private ISpan StartSpanInternal( bool recordEvents, Timer timestampConverter) { - ITraceParams activeTraceParams = this.Options.TraceConfig.ActiveTraceParams; - IRandomGenerator random = this.Options.RandomHandler; + var activeTraceParams = this.Options.TraceConfig.ActiveTraceParams; + var random = this.Options.RandomHandler; TraceId traceId; - SpanId spanId = SpanId.GenerateRandomId(random); + var spanId = SpanId.GenerateRandomId(random); SpanId parentSpanId = null; TraceOptionsBuilder traceOptionsBuilder; if (parent == null || !parent.IsValid) @@ -201,15 +201,15 @@ private ISpan StartSpanInternal( traceId, spanId, activeTraceParams)); - TraceOptions traceOptions = traceOptionsBuilder.Build(); - SpanOptions spanOptions = SpanOptions.None; + var traceOptions = traceOptionsBuilder.Build(); + var spanOptions = SpanOptions.None; if (traceOptions.IsSampled || recordEvents) { spanOptions = SpanOptions.RecordEvents; } - ISpan span = Span.StartSpan( + var span = Span.StartSpan( SpanContext.Create(traceId, spanId, traceOptions, parent?.Tracestate ?? Tracestate.Empty), spanOptions, name, diff --git a/src/OpenTelemetry/Trace/TracerBase.cs b/src/OpenTelemetry/Trace/TracerBase.cs index 31f39b51cba..2b8be0e2d30 100644 --- a/src/OpenTelemetry/Trace/TracerBase.cs +++ b/src/OpenTelemetry/Trace/TracerBase.cs @@ -31,7 +31,7 @@ public ISpan CurrentSpan { get { - ISpan currentSpan = CurrentSpanUtils.CurrentSpan; + var currentSpan = CurrentSpanUtils.CurrentSpan; return currentSpan ?? BlankSpan.Instance; } } diff --git a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs index 1cc9dcbbb50..9e469567b5d 100644 --- a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs +++ b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs @@ -153,7 +153,7 @@ public void Clear() public bool Contains(KeyValuePair item) { - var result = this.TryGetValue(item.Key, out IAttributeValue value); + var result = this.TryGetValue(item.Key, out var value); if (result) { return value.Equals(item.Value); @@ -164,10 +164,10 @@ public bool Contains(KeyValuePair item) public void CopyTo(KeyValuePair[] array, int arrayIndex) { - DictionaryEntry[] entries = new DictionaryEntry[this.@delegate.Count]; + var entries = new DictionaryEntry[this.@delegate.Count]; this.@delegate.CopyTo(entries, 0); - for (int i = 0; i < entries.Length; i++) + for (var i = 0; i < entries.Length; i++) { array[i + arrayIndex] = new KeyValuePair((string)entries[i].Key, (IAttributeValue)entries[i].Value); } diff --git a/src/OpenTelemetry/Utils/Collections.cs b/src/OpenTelemetry/Utils/Collections.cs index 16c3685a7f5..a59e190c3bf 100644 --- a/src/OpenTelemetry/Utils/Collections.cs +++ b/src/OpenTelemetry/Utils/Collections.cs @@ -29,7 +29,7 @@ public static string ToString(IDictionary dict) return "null"; } - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); foreach (var kvp in dict) { sb.Append(kvp.Key.ToString()); @@ -48,7 +48,7 @@ public static string ToString(IEnumerable list) return "null"; } - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); foreach (var val in list) { if (val != null) diff --git a/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs b/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs index ee2671f5953..bbeddfcba69 100644 --- a/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs +++ b/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs @@ -102,8 +102,8 @@ public IReadOnlyList Copy() { lock (this.lck) { - List all = new List(this.size); - for (T e = this.head; e != null; e = e.Next) + var all = new List(this.size); + for (var e = this.head; e != null; e = e.Next) { all.Add(e); } diff --git a/src/OpenTelemetry/Utils/StringUtil.cs b/src/OpenTelemetry/Utils/StringUtil.cs index 89db426ba1d..dc10cbac992 100644 --- a/src/OpenTelemetry/Utils/StringUtil.cs +++ b/src/OpenTelemetry/Utils/StringUtil.cs @@ -20,7 +20,7 @@ internal static class StringUtil { public static bool IsPrintableString(string str) { - for (int i = 0; i < str.Length; i++) + for (var i = 0; i < str.Length; i++) { if (!IsPrintableChar(str[i])) { diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index bdf8e075c0d..0bca8d09fb2 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -67,7 +67,7 @@ void ConfigureTestServices(IServiceCollection services) => // Assert response.EnsureSuccessStatusCode(); // Status Code 200-299 - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { if (startEndHandler.Invocations.Count == 2) { @@ -125,7 +125,7 @@ public async Task SuccesfulTemplateControllerCallUsesParentContext() // Assert response.EnsureSuccessStatusCode(); // Status Code 200-299 - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { if (startEndHandler.Invocations.Count == 2) { diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index 2b5cae97914..9f15e789247 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -79,7 +79,7 @@ public async Task SuccesfulTemplateControllerCallGeneratesASpan() // ignore errors } - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { if (startEndHandler.Invocations.Count == 2) { diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs index 90cbff197a5..929a4d62b92 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -41,13 +41,13 @@ public async Task HttpDepenenciesCollectorInjectsHeadersAsync() ctx.Response.StatusCode = 200; ctx.Response.OutputStream.Close(); }, - out string host, - out int port); + out var host, + out var port); var url = $"http://{host}:{port}/"; - TraceId expectedTraceId = TraceId.Invalid; - SpanId expectedSpanId = SpanId.Invalid; + var expectedTraceId = TraceId.Invalid; + var expectedSpanId = SpanId.Invalid; using (serverLifeTime) { diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index e78b61a2864..900237b4c06 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -58,7 +58,7 @@ public class HttpOutTestCase private static IEnumerable readTestCases() { - Assembly assembly = Assembly.GetExecutingAssembly(); + var assembly = Assembly.GetExecutingAssembly(); var serializer = new JsonSerializer(); var input = serializer.Deserialize(new JsonTextReader(new StreamReader(assembly.GetManifestResourceStream("OpenTelemetry.Collector.Dependencies.Tests.http-out-test-cases.json")))); @@ -67,7 +67,7 @@ private static IEnumerable readTestCases() private static IEnumerable getArgumentsFromTestCaseObject(IEnumerable input) { - List result = new List(); + var result = new List(); foreach (var testCase in input) { @@ -97,8 +97,8 @@ public async Task HttpOutCallsAreCollectedSuccesfullyAsync(HttpOutTestCase tc) ctx.Response.StatusCode = tc.responseCode == 0 ? 200 : tc.responseCode; ctx.Response.OutputStream.Close(); }, - out string host, - out int port); + out var host, + out var port); var startEndHandler = new Mock(); var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null); diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs index 003ade39131..f56aac0e974 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs @@ -38,7 +38,7 @@ public RunningServer(Action action, string host, int port) this.cts = new CancellationTokenSource(); this.listener = new HttpListener(); - CancellationToken token = this.cts.Token; + var token = this.cts.Token; this.listener.Prefixes.Add($"http://{host}:{port}/"); this.listener.Start(); diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs index 28474eade2f..d419f82cf42 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs @@ -67,7 +67,7 @@ private ConcurrentQueue ConvertSpan(SpanData data) configuration.TelemetryChannel = channel; - TraceExporterHandler exporter = new TraceExporterHandler(configuration); + var exporter = new TraceExporterHandler(configuration); exporter.ExportAsync(new List { data }).Wait(); return sentItems; diff --git a/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs b/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs index f77cb0617c2..e1a97f41ee9 100644 --- a/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs @@ -64,7 +64,7 @@ public void TimestampFromMillis_Negative() [Fact] public void TimestampAddNanos() { - Timestamp timestamp = Timestamp.Create(1234, 223); + var timestamp = Timestamp.Create(1234, 223); Assert.Equal(timestamp, timestamp.AddNanos(0)); Assert.Equal(Timestamp.Create(1235, 0), timestamp.AddNanos(999999777)); Assert.Equal(Timestamp.Create(1235, 300200723), timestamp.AddNanos(1300200500)); @@ -77,7 +77,7 @@ public void TimestampAddNanos() [Fact] public void TimestampAddNanos_Negative() { - Timestamp timestamp = Timestamp.Create(1234, 223); + var timestamp = Timestamp.Create(1234, 223); Assert.Equal(Timestamp.Create(1234, 0), timestamp.AddNanos(-223)); Assert.Equal(Timestamp.Create(1233, 0), timestamp.AddNanos(-1000000223)); Assert.Equal(Timestamp.Create(1232, 699799723), timestamp.AddNanos(-1300200500)); @@ -89,7 +89,7 @@ public void TimestampAddNanos_Negative() [Fact] public void TimestampAddDuration() { - Timestamp timestamp = Timestamp.Create(1234, 223); + var timestamp = Timestamp.Create(1234, 223); Assert.Equal(Timestamp.Create(1235, 223), timestamp.AddDuration(Duration.Create(1, 0))); Assert.Equal(Timestamp.Create(1234, 224), timestamp.AddDuration(Duration.Create(0, 1))); Assert.Equal(Timestamp.Create(1235, 224), timestamp.AddDuration(Duration.Create(1, 1))); @@ -99,7 +99,7 @@ public void TimestampAddDuration() [Fact] public void TimestampAddDuration_Negative() { - Timestamp timestamp = Timestamp.Create(1234, 223); + var timestamp = Timestamp.Create(1234, 223); Assert.Equal(Timestamp.Create(0, 0), timestamp.AddDuration(Duration.Create(-1234, -223))); Assert.Equal(Timestamp.Create(1233, 223), timestamp.AddDuration(Duration.Create(-1, 0))); Assert.Equal(Timestamp.Create(1233, 222), timestamp.AddDuration(Duration.Create(-1, -1))); @@ -110,7 +110,7 @@ public void TimestampAddDuration_Negative() [Fact] public void TimestampSubtractTimestamp() { - Timestamp timestamp = Timestamp.Create(1234, 223); + var timestamp = Timestamp.Create(1234, 223); Assert.Equal(Duration.Create(1234, 223), timestamp.SubtractTimestamp(Timestamp.Create(0, 0))); Assert.Equal(Duration.Create(1, 0), timestamp.SubtractTimestamp(Timestamp.Create(1233, 223))); Assert.Equal(Duration.Create(1, 1), timestamp.SubtractTimestamp(Timestamp.Create(1233, 222))); @@ -121,7 +121,7 @@ public void TimestampSubtractTimestamp() [Fact] public void TimestampSubtractTimestamp_NegativeResult() { - Timestamp timestamp = Timestamp.Create(1234, 223); + var timestamp = Timestamp.Create(1234, 223); Assert.Equal(Duration.Create(-1, 0), timestamp.SubtractTimestamp(Timestamp.Create(1235, 223))); Assert.Equal(Duration.Create(0, -1), timestamp.SubtractTimestamp(Timestamp.Create(1234, 224))); Assert.Equal(Duration.Create(-1, -1), timestamp.SubtractTimestamp(Timestamp.Create(1235, 224))); diff --git a/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs b/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs index 77820078dd5..a5345cf3f73 100644 --- a/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs @@ -251,7 +251,7 @@ public void MergeResource_MultiLabelSource_MultiLabelTarget_FullOverlap() private static void AddLabels(Dictionary labels, int labelCount, int startIndex = 0) { - for (int i = startIndex; i < labelCount + startIndex; ++i) + for (var i = startIndex; i < labelCount + startIndex; ++i) { labels.Add($"{keyName}{i}", $"{valueName}{i}"); } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/AggregationDataTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/AggregationDataTest.cs index 2b09581fef6..b78798ab240 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/AggregationDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/AggregationDataTest.cs @@ -28,7 +28,7 @@ public class AggregationDataTest [Fact] public void TestCreateDistributionData() { - IDistributionData distributionData = + var distributionData = DistributionData.Create(7.7, 10, 1.1, 9.9, 32.2, new List() { 4L, 1L, 5L }); Assert.InRange(distributionData.Mean, 7.7 - TOLERANCE, 7.7 + TOLERANCE); @@ -116,7 +116,7 @@ public void TestEquals() [Fact] public void TestMatchAndGet() { - List aggregations = + var aggregations = new List() { SumDataDouble.Create(10.0), SumDataLong.Create(100000000), @@ -127,8 +127,8 @@ public void TestMatchAndGet() LastValueDataLong.Create(200000000L), }; - List actual = new List(); - foreach (IAggregationData aggregation in aggregations) + var actual = new List(); + foreach (var aggregation in aggregations) { aggregation.Match( (arg) => diff --git a/test/OpenTelemetry.Tests/Impl/Stats/AggregationTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/AggregationTest.cs index 86ce3d96268..befcbf6cf0c 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/AggregationTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/AggregationTest.cs @@ -26,8 +26,8 @@ public class AggregationTest [Fact] public void TestCreateDistribution() { - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(new List() { 0.1, 2.2, 33.3 }); - IDistribution distribution = Distribution.Create(bucketBoundaries); + var bucketBoundaries = BucketBoundaries.Create(new List() { 0.1, 2.2, 33.3 }); + var distribution = Distribution.Create(bucketBoundaries); Assert.Equal(bucketBoundaries, distribution.BucketBoundaries); } @@ -70,15 +70,15 @@ public void TestEquals() [Fact] public void TestMatch() { - List aggregations = + var aggregations = new List() { Sum.Create(), Count.Create(), Mean.Create(), Distribution.Create(BucketBoundaries.Create(new List() {-10.0, 1.0, 5.0 })), LastValue.Create(),}; - List actual = new List(); - foreach (IAggregation aggregation in aggregations) + var actual = new List(); + foreach (var aggregation in aggregations) { actual.Add( aggregation.Match( diff --git a/test/OpenTelemetry.Tests/Impl/Stats/BucketBoundariesTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/BucketBoundariesTest.cs index 261c5efcf81..e0fa2258e30 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/BucketBoundariesTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/BucketBoundariesTest.cs @@ -26,22 +26,22 @@ public class BucketBoundariesTest [Fact] public void TestConstructBoundaries() { - List buckets = new List() { 0.0, 1.0, 2.0 }; - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(buckets); + var buckets = new List() { 0.0, 1.0, 2.0 }; + var bucketBoundaries = BucketBoundaries.Create(buckets); Assert.Equal(buckets, bucketBoundaries.Boundaries); } [Fact] public void TestBoundariesDoesNotChangeWithOriginalList() { - List original = new List(); + var original = new List(); original.Add(0.0); original.Add(1.0); original.Add(2.0); - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(original); + var bucketBoundaries = BucketBoundaries.Create(original); original[2] = 3.0; original.Add(4.0); - List expected = new List() { 0.0, 1.0, 2.0 }; + var expected = new List() { 0.0, 1.0, 2.0 }; Assert.NotEqual(original, bucketBoundaries.Boundaries); Assert.Equal(expected, bucketBoundaries.Boundaries); } @@ -55,15 +55,15 @@ public void TestNullBoundaries() [Fact] public void TestUnsortedBoundaries() { - List buckets = new List() { 0.0, 1.0, 1.0 }; + var buckets = new List() { 0.0, 1.0, 1.0 }; Assert.Throws(() => BucketBoundaries.Create(buckets)); } [Fact] public void TestNoBoundaries() { - List buckets = new List(); - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(buckets); + var buckets = new List(); + var bucketBoundaries = BucketBoundaries.Create(buckets); Assert.Equal(buckets, bucketBoundaries.Boundaries); } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs index b7e054fbc31..70bb200cd1d 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs @@ -33,7 +33,7 @@ public void DefaultState() [Fact] public void SetState() { - CurrentStatsState state = new CurrentStatsState(); + var state = new CurrentStatsState(); Assert.True(state.Set(StatsCollectionState.DISABLED)); Assert.Equal(StatsCollectionState.DISABLED, state.Internal); Assert.True(state.Set(StatsCollectionState.ENABLED)); @@ -46,7 +46,7 @@ public void SetState() [Fact] public void PreventSettingStateAfterReadingState() { - CurrentStatsState state = new CurrentStatsState(); + var state = new CurrentStatsState(); var st = state.Value; Assert.Throws(() => state.Set(StatsCollectionState.DISABLED)); } @@ -59,7 +59,7 @@ public async Task PreventSettingStateAfterReadingState_IsThreadSafe() // (e.g. more/less machine load, faster/slower processors). // It will not incorrectly fail transiently though. - for (int i = 0; i < 10; i ++) + for (var i = 0; i < 10; i ++) { var state = new CurrentStatsState(); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs index 038b1ab352f..dcbc8ef2bd2 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs @@ -73,8 +73,8 @@ public void TestBuilderEmpty() public void TestBuilder() { var expected = new List(10); - MeasureMapBuilder builder = MeasureMapBuilder.Builder(); - for (int i = 1; i <= 10; i++) + var builder = MeasureMapBuilder.Builder(); + for (var i = 1; i <= 10; i++) { expected.Add(MeasurementDouble.Create(MakeSimpleMeasureDouble("m" + i), i * 11.1)); builder.Put(MakeSimpleMeasureDouble("m" + i), i * 11.1); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MeasureTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MeasureTest.cs index 9fac549807c..6d4f23d4331 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MeasureTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MeasureTest.cs @@ -32,14 +32,14 @@ public void TestConstants() [Fact] public void PreventTooLongMeasureName() { - char[] chars = new char[Measure.NameMaxLength + 1]; + var chars = new char[Measure.NameMaxLength + 1]; - for (int i = 0; i < chars.Length; i++) + for (var i = 0; i < chars.Length; i++) { chars[i] = 'a'; } - String longName = new string(chars); + var longName = new string(chars); Assert.Throws(() => MeasureDouble.Create(longName, "description", "1")); } @@ -84,12 +84,12 @@ public void TestMeasureLongEquals() [Fact] public void TestMatch() { - List measures = + var measures = new List() { MeasureDouble.Create("measure1", "description", "1"), MeasureLong.Create("measure2", "description", "1"),}; - List outputs = new List(); - foreach (IMeasure measure in measures) + var outputs = new List(); + foreach (var measure in measures) { outputs.Add( measure.Match( diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs index bbe6a506a18..407d67cb5c9 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs @@ -42,9 +42,9 @@ public class MeasureToViewMapTest [Fact] public void TestRegisterAndGetView() { - MeasureToViewMap measureToViewMap = new MeasureToViewMap(); + var measureToViewMap = new MeasureToViewMap(); measureToViewMap.RegisterView(VIEW); - IViewData viewData = measureToViewMap.GetView(VIEW_NAME, StatsCollectionState.ENABLED); + var viewData = measureToViewMap.GetView(VIEW_NAME, StatsCollectionState.ENABLED); Assert.Equal(VIEW, viewData.View); Assert.Empty(viewData.AggregationMap); } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MutableAggregationTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MutableAggregationTest.cs index 54b38b3324c..e3a6a0785cc 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MutableAggregationTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MutableAggregationTest.cs @@ -33,8 +33,8 @@ public void TestCreateEmpty() Assert.InRange(MutableMean.Create().Mean, 0 - TOLERANCE, 0 + TOLERANCE); Assert.True(Double.IsNaN(MutableLastValue.Create().LastValue)); - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(new List() { 0.1, 2.2, 33.3 }); - MutableDistribution mutableDistribution = MutableDistribution.Create(bucketBoundaries); + var bucketBoundaries = BucketBoundaries.Create(new List() { 0.1, 2.2, 33.3 }); + var mutableDistribution = MutableDistribution.Create(bucketBoundaries); Assert.InRange(mutableDistribution.Mean, 0, TOLERANCE); Assert.Equal(0, mutableDistribution.Count); Assert.Equal(double.PositiveInfinity, mutableDistribution.Min); @@ -53,8 +53,8 @@ public void TestNullBucketBoundaries() [Fact] public void TestNoBoundaries() { - List buckets = new List(); - MutableDistribution noBoundaries = MutableDistribution.Create(BucketBoundaries.Create(buckets)); + var buckets = new List(); + var noBoundaries = MutableDistribution.Create(BucketBoundaries.Create(buckets)); Assert.Single(noBoundaries.BucketCounts); Assert.Equal(0, noBoundaries.BucketCounts[0]); } @@ -62,7 +62,7 @@ public void TestNoBoundaries() [Fact] public void TestAdd() { - List aggregations = + var aggregations = new List(){ MutableSum.Create(), MutableCount.Create(), @@ -70,17 +70,17 @@ public void TestAdd() MutableDistribution.Create(BUCKET_BOUNDARIES), MutableLastValue.Create(),}; - List values = new List() { -1.0, 1.0, -5.0, 20.0, 5.0 }; + var values = new List() { -1.0, 1.0, -5.0, 20.0, 5.0 }; - foreach (double value in values) + foreach (var value in values) { - foreach (MutableAggregation aggregation in aggregations) + foreach (var aggregation in aggregations) { aggregation.Add(value); } } - foreach (MutableAggregation aggregation in aggregations) + foreach (var aggregation in aggregations) { aggregation.Match( (arg) => @@ -121,7 +121,7 @@ public void TestAdd() [Fact] public void TestMatch() { - List aggregations = + var aggregations = new List(){ MutableSum.Create(), MutableCount.Create(), @@ -129,8 +129,8 @@ public void TestMatch() MutableDistribution.Create(BUCKET_BOUNDARIES), MutableLastValue.Create(),}; - List actual = new List(); - foreach (MutableAggregation aggregation in aggregations) + var actual = new List(); + foreach (var aggregation in aggregations) { actual.Add( aggregation.Match( @@ -167,31 +167,31 @@ public void TestMatch() public void TestCombine_SumCountMean() { // combine() for Mutable Sum, Count and Mean will pick up fractional stats - List aggregations1 = + var aggregations1 = new List() { MutableSum.Create(), MutableCount.Create(), MutableMean.Create() }; - List aggregations2 = + var aggregations2 = new List() { MutableSum.Create(), MutableCount.Create(), MutableMean.Create() }; - foreach (double val in new List() { -1.0, -5.0 }) + foreach (var val in new List() { -1.0, -5.0 }) { - foreach (MutableAggregation aggregation in aggregations1) + foreach (var aggregation in aggregations1) { aggregation.Add(val); } } - foreach (double val in new List() { 10.0, 50.0 }) + foreach (var val in new List() { 10.0, 50.0 }) { - foreach (MutableAggregation aggregation in aggregations2) + foreach (var aggregation in aggregations2) { aggregation.Add(val); } } - List combined = + var combined = new List() { MutableSum.Create(), MutableCount.Create(), MutableMean.Create() }; - double fraction1 = 1.0; - double fraction2 = 0.6; - for (int i = 0; i < combined.Count; i++) + var fraction1 = 1.0; + var fraction2 = 0.6; + for (var i = 0; i < combined.Count; i++) { combined[i].Combine(aggregations1[i], fraction1); combined[i].Combine(aggregations2[i], fraction2); @@ -206,24 +206,24 @@ public void TestCombine_SumCountMean() public void TestCombine_Distribution() { // combine() for Mutable Distribution will ignore fractional stats - MutableDistribution distribution1 = MutableDistribution.Create(BUCKET_BOUNDARIES); - MutableDistribution distribution2 = MutableDistribution.Create(BUCKET_BOUNDARIES); - MutableDistribution distribution3 = MutableDistribution.Create(BUCKET_BOUNDARIES); + var distribution1 = MutableDistribution.Create(BUCKET_BOUNDARIES); + var distribution2 = MutableDistribution.Create(BUCKET_BOUNDARIES); + var distribution3 = MutableDistribution.Create(BUCKET_BOUNDARIES); - foreach (double val in new List() { 5.0, -5.0 }) + foreach (var val in new List() { 5.0, -5.0 }) { distribution1.Add(val); } - foreach (double val in new List() { 10.0, 20.0 }) + foreach (var val in new List() { 10.0, 20.0 }) { distribution2.Add(val); } - foreach (double val in new List() { -10.0, 15.0, -15.0, -20.0 }) + foreach (var val in new List() { -10.0, 15.0, -15.0, -20.0 }) { distribution3.Add(val); } - MutableDistribution combined = MutableDistribution.Create(BUCKET_BOUNDARIES); + var combined = MutableDistribution.Create(BUCKET_BOUNDARIES); combined.Combine(distribution1, 1.0); // distribution1 will be combined combined.Combine(distribution2, 0.6); // distribution2 will be ignored VerifyMutableDistribution(combined, 0, 2, -5, 5, 50.0, new long[] { 0, 1, 1, 0 }, TOLERANCE); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs index 041c684ef57..101b9747c4f 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs @@ -58,14 +58,14 @@ public void TestGetTagValues() [Fact] public void CreateMutableAggregation() { - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(new List() { -1.0, 0.0, 1.0 }); + var bucketBoundaries = BucketBoundaries.Create(new List() { -1.0, 0.0, 1.0 }); Assert.InRange(((MutableSum)MutableViewData.CreateMutableAggregation(Sum.Create())).Sum, 0.0 - EPSILON, 0.0 + EPSILON); Assert.Equal(0, ((MutableCount)MutableViewData.CreateMutableAggregation(Count.Create())).Count); Assert.InRange(((MutableMean)MutableViewData.CreateMutableAggregation(Mean.Create())).Mean, 0.0 - EPSILON, 0.0 + EPSILON); Assert.True(Double.IsNaN( ((MutableLastValue)MutableViewData.CreateMutableAggregation(LastValue.Create())).LastValue)); - MutableDistribution mutableDistribution = + var mutableDistribution = (MutableDistribution)MutableViewData.CreateMutableAggregation(Distribution.Create(bucketBoundaries)); Assert.Equal(double.PositiveInfinity, mutableDistribution.Min); Assert.Equal(double.NegativeInfinity, mutableDistribution.Max); @@ -76,24 +76,24 @@ public void CreateMutableAggregation() [Fact] public void CreateAggregationData() { - IBucketBoundaries bucketBoundaries = BucketBoundaries.Create(new List() { -1.0, 0.0, 1.0 }); - List mutableAggregations = + var bucketBoundaries = BucketBoundaries.Create(new List() { -1.0, 0.0, 1.0 }); + var mutableAggregations = new List() { MutableCount.Create(), MutableMean.Create(), MutableDistribution.Create(bucketBoundaries),}; - List aggregates = new List(); + var aggregates = new List(); aggregates.Add(MutableViewData.CreateAggregationData(MutableSum.Create(), MEASURE_DOUBLE)); aggregates.Add(MutableViewData.CreateAggregationData(MutableSum.Create(), MEASURE_LONG)); aggregates.Add(MutableViewData.CreateAggregationData(MutableLastValue.Create(), MEASURE_DOUBLE)); aggregates.Add(MutableViewData.CreateAggregationData(MutableLastValue.Create(), MEASURE_LONG)); - foreach (MutableAggregation mutableAggregation in mutableAggregations) + foreach (var mutableAggregation in mutableAggregations) { aggregates.Add(MutableViewData.CreateAggregationData(mutableAggregation, MEASURE_DOUBLE)); } - List expected = new List() + var expected = new List() { SumDataDouble.Create(0), SumDataLong.Create(0), diff --git a/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs index c96d52cbe75..1b0ee127264 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs @@ -90,7 +90,7 @@ public void NoopStatsRecorder_RecordWithCurrentContext() [Fact] public void NoopStatsRecorder_Record_DisallowNullTagContext() { - IMeasureMap measureMap = NoopStats.NoopStatsRecorder.NewMeasureMap(); + var measureMap = NoopStats.NoopStatsRecorder.NewMeasureMap(); Assert.Throws(() => measureMap.Record(null)); } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs index 95fba382541..fcf20da8283 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs @@ -40,13 +40,13 @@ public class NoopViewManagerTest [Fact] public void NoopViewManager_RegisterView_DisallowRegisteringDifferentViewWithSameName() { - IView view1 = + var view1 = View.Create( VIEW_NAME, "description 1", MEASURE, AGGREGATION, new List { KEY }); - IView view2 = + var view2 = View.Create( VIEW_NAME, "description 2", MEASURE, AGGREGATION, new List { KEY }); - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view1); try @@ -62,10 +62,10 @@ public void NoopViewManager_RegisterView_DisallowRegisteringDifferentViewWithSam [Fact] public void NoopViewManager_RegisterView_AllowRegisteringSameViewTwice() { - IView view = + var view = View.Create( VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view); viewManager.RegisterView(view); } @@ -73,27 +73,27 @@ public void NoopViewManager_RegisterView_AllowRegisteringSameViewTwice() [Fact] public void NoopViewManager_RegisterView_DisallowNull() { - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); Assert.Throws(() => viewManager.RegisterView(null)); } [Fact] public void NoopViewManager_GetView_GettingNonExistentViewReturnsNull() { - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); Assert.Null(viewManager.GetView(VIEW_NAME)); } [Fact] public void NoopViewManager_GetView_Cumulative() { - IView view = + var view = View.Create( VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); Assert.Equal(view, viewData.View); Assert.Empty(viewData.AggregationMap); Assert.Equal(DateTimeOffset.MinValue, viewData.Start); @@ -104,13 +104,13 @@ public void NoopViewManager_GetView_Cumulative() [Fact] public void noopViewManager_GetView_Interval() { - IView view = + var view = View.Create( VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); Assert.Equal(view, viewData.View); Assert.Empty(viewData.AggregationMap); Assert.Equal(DateTimeOffset.MinValue, viewData.Start); @@ -121,23 +121,23 @@ public void noopViewManager_GetView_Interval() [Fact] public void NoopViewManager_GetView_DisallowNull() { - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); Assert.Throws(() => viewManager.GetView(null)); } [Fact] public void GetAllExportedViews() { - IViewManager viewManager = NoopStats.NewNoopViewManager(); + var viewManager = NoopStats.NewNoopViewManager(); Assert.Empty(viewManager.AllExportedViews); - IView cumulativeView1 = + var cumulativeView1 = View.Create( ViewName.Create("View 1"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); - IView cumulativeView2 = + var cumulativeView2 = View.Create( ViewName.Create("View 2"), VIEW_DESCRIPTION, @@ -158,14 +158,14 @@ public void GetAllExportedViews() [Fact] public void GetAllExportedViews_ResultIsUnmodifiable() { - IViewManager viewManager = NoopStats.NewNoopViewManager(); - IView view1 = + var viewManager = NoopStats.NewNoopViewManager(); + var view1 = View.Create( ViewName.Create("View 1"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); viewManager.RegisterView(view1); - ISet exported = viewManager.AllExportedViews; + var exported = viewManager.AllExportedViews; - IView view2 = + var view2 = View.Create( ViewName.Create("View 2"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); Assert.Throws(() => exported.Add(view2)); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs index f4cd46f559e..25776692e64 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs @@ -42,22 +42,22 @@ public void Main() var tagsComponent = new TagsComponent(); var tagger = tagsComponent.Tagger; - TagKey FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); - TagKey FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); - TagKey FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); + var FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); + var FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); + var FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); - IMeasureLong VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); + var VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); - IViewName VIDEO_SIZE_BY_FRONTEND_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend"); - IView VIDEO_SIZE_BY_FRONTEND_VIEW = View.Create( + var VIDEO_SIZE_BY_FRONTEND_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend"); + var VIDEO_SIZE_BY_FRONTEND_VIEW = View.Create( VIDEO_SIZE_BY_FRONTEND_VIEW_NAME, "processed video size over time", VIDEO_SIZE, Distribution.Create(BucketBoundaries.Create(new List() { 0.0, 256.0, 65536.0 })), new List() { FRONTEND_KEY}); - IViewName VIDEO_SIZE_ALL_VIEW_NAME = ViewName.Create("my.org/views/video_size_all"); - IView VIDEO_SIZE_VIEW_ALL = View.Create( + var VIDEO_SIZE_ALL_VIEW_NAME = ViewName.Create("my.org/views/video_size_all"); + var VIDEO_SIZE_VIEW_ALL = View.Create( VIDEO_SIZE_ALL_VIEW_NAME, "processed video size over time", VIDEO_SIZE, @@ -65,16 +65,16 @@ public void Main() new List() { }); - IViewName VIDEO_SIZE_TOTAL_VIEW_NAME = ViewName.Create("my.org/views/video_size_total"); - IView VIDEO_SIZE_TOTAL = View.Create( + var VIDEO_SIZE_TOTAL_VIEW_NAME = ViewName.Create("my.org/views/video_size_total"); + var VIDEO_SIZE_TOTAL = View.Create( VIDEO_SIZE_TOTAL_VIEW_NAME, "total video size over time", VIDEO_SIZE, Sum.Create(), new List() { FRONTEND_KEY}); - IViewName VIDEOS_PROCESSED_VIEW_NAME = ViewName.Create("my.org/views/videos_processed"); - IView VIDEOS_PROCESSED = View.Create( + var VIDEOS_PROCESSED_VIEW_NAME = ViewName.Create("my.org/views/videos_processed"); + var VIDEOS_PROCESSED = View.Create( VIDEOS_PROCESSED_VIEW_NAME, "total video processed", VIDEO_SIZE, @@ -86,17 +86,17 @@ public void Main() viewManager.RegisterView(VIDEO_SIZE_TOTAL); viewManager.RegisterView(VIDEOS_PROCESSED); - ITagContext context1 = tagger + var context1 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front1")) .Build(); - ITagContext context2 = tagger + var context2 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front2")) .Build(); long sum = 0; - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { sum = sum + (25648 * i); if (i % 2 == 0) @@ -108,19 +108,19 @@ public void Main() } } - IViewData viewDataByFrontend = viewManager.GetView(VIDEO_SIZE_BY_FRONTEND_VIEW_NAME); + var viewDataByFrontend = viewManager.GetView(VIDEO_SIZE_BY_FRONTEND_VIEW_NAME); var viewDataAggMap = viewDataByFrontend.AggregationMap.ToList(); output.WriteLine(viewDataByFrontend.ToString()); - IViewData viewDataAll = viewManager.GetView(VIDEO_SIZE_ALL_VIEW_NAME); + var viewDataAll = viewManager.GetView(VIDEO_SIZE_ALL_VIEW_NAME); var viewDataAggMapAll = viewDataAll.AggregationMap.ToList(); output.WriteLine(viewDataAll.ToString()); - IViewData viewData1 = viewManager.GetView(VIDEO_SIZE_TOTAL_VIEW_NAME); + var viewData1 = viewManager.GetView(VIDEO_SIZE_TOTAL_VIEW_NAME); var viewData1AggMap = viewData1.AggregationMap.ToList(); output.WriteLine(viewData1.ToString()); - IViewData viewData2 = viewManager.GetView(VIDEOS_PROCESSED_VIEW_NAME); + var viewData2 = viewManager.GetView(VIDEOS_PROCESSED_VIEW_NAME); var viewData2AggMap = viewData2.AggregationMap.ToList(); output.WriteLine(viewData2.ToString()); @@ -136,14 +136,14 @@ public void Main2() var tagsComponent = new TagsComponent(); var tagger = tagsComponent.Tagger; - TagKey FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); - TagKey FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); - TagKey FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); + var FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); + var FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); + var FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); - IMeasureLong VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); + var VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); - IViewName VIDEO_SIZE_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend"); - IView VIDEO_SIZE_VIEW = View.Create( + var VIDEO_SIZE_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend"); + var VIDEO_SIZE_VIEW = View.Create( VIDEO_SIZE_VIEW_NAME, "processed video size over time", VIDEO_SIZE, @@ -154,19 +154,19 @@ public void Main2() viewManager.RegisterView(VIDEO_SIZE_VIEW); - ITagContext context1 = tagger + var context1 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front1")) .Put(FRONTEND_OS_KEY, TagValue.Create("windows")) .Build(); - ITagContext context2 = tagger + var context2 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front2")) .Put(FRONTEND_OS_VERSION_KEY, TagValue.Create("1.1.1")) .Build(); long sum = 0; - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) { sum = sum + (25648 * i); if (i % 2 == 0) @@ -179,10 +179,10 @@ public void Main2() } } - IViewData videoSizeView = viewManager.GetView(VIDEO_SIZE_VIEW_NAME); + var videoSizeView = viewManager.GetView(VIDEO_SIZE_VIEW_NAME); var viewDataAggMap = videoSizeView.AggregationMap.ToList(); var view = viewManager.AllExportedViews.ToList()[0]; - for (int i = 0; i < view.Columns.Count; i++) + for (var i = 0; i < view.Columns.Count; i++) { output.WriteLine(view.Columns[i] + "=" + GetTagValues(i, viewDataAggMap)); } @@ -208,7 +208,7 @@ public void Main2() private string GetTagValues(int i, List> viewDataAggMap) { - string result = string.Empty; + var result = string.Empty; foreach (var kvp in viewDataAggMap) { var val = kvp.Key.Values[i]; diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs index bfe1a2e3103..1cef855a6bb 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs @@ -49,7 +49,7 @@ public StatsRecorderTest() [Fact] public void Record_CurrentContextNotSet() { - IView view = + var view = View.Create( VIEW_NAME, "description", @@ -58,7 +58,7 @@ public void Record_CurrentContextNotSet() new List() { KEY }); viewManager.RegisterView(view); statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 1.0).Record(); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); // record() should have used the default TagContext, so the tag value should be null. ICollection expected = new List() { TagValues.Create(new List() { null }) }; @@ -68,7 +68,7 @@ public void Record_CurrentContextNotSet() [Fact] public void Record_CurrentContextSet() { - IView view = + var view = View.Create( VIEW_NAME, "description", @@ -87,7 +87,7 @@ public void Record_CurrentContextSet() { AsyncLocalContext.CurrentTagContext = orig; } - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); // record() should have used the given TagContext. ICollection expected = new List() { TagValues.Create(new List() { VALUE }) }; @@ -97,7 +97,7 @@ public void Record_CurrentContextSet() [Fact] public void Record_UnregisteredMeasure() { - IView view = + var view = View.Create( VIEW_NAME, "description", @@ -112,7 +112,7 @@ public void Record_UnregisteredMeasure() .Put(MEASURE_DOUBLE_NO_VIEW_2, 3.0) .Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); // There should be one entry. var tv = TagValues.Create(new List() { VALUE }); @@ -125,7 +125,7 @@ public void Record_UnregisteredMeasure() [Fact] public void RecordTwice() { - IView view = + var view = View.Create( VIEW_NAME, "description", @@ -134,10 +134,10 @@ public void RecordTwice() new List() { KEY }); viewManager.RegisterView(view); - IMeasureMap statsRecord = statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 1.0); + var statsRecord = statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 1.0); statsRecord.Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); statsRecord.Record(new SimpleTagContext(Tag.Create(KEY, VALUE_2))); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); // There should be two entries. var tv = TagValues.Create(new List() { VALUE }); @@ -156,7 +156,7 @@ public void RecordTwice() [Fact] public void Record_StatsDisabled() { - IView view = + var view = View.Create( VIEW_NAME, "description", @@ -176,7 +176,7 @@ public void Record_StatsDisabled() [Fact] public void Record_StatsReenabled() { - IView view = + var view = View.Create( VIEW_NAME, "description", @@ -201,7 +201,7 @@ public void Record_StatsReenabled() .NewMeasureMap() .Put(MEASURE_DOUBLE, 4.0) .Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); - TagValues tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(VIEW_NAME).AggregationMap, new Dictionary() diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs index 1a8776523b1..fbdb3fff915 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs @@ -30,8 +30,8 @@ internal static class StatsTestUtil internal static IAggregationData CreateAggregationData(IAggregation aggregation, IMeasure measure, params double[] values) { - MutableAggregation mutableAggregation = MutableViewData.CreateMutableAggregation(aggregation); - foreach (double value in values) + var mutableAggregation = MutableViewData.CreateMutableAggregation(aggregation); + foreach (var value in values) { mutableAggregation.Add(value); } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewDataTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewDataTest.cs index 507678aec76..3652ac79de6 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewDataTest.cs @@ -64,10 +64,10 @@ public class ViewDataTest [Fact] public void TestCumulativeViewData() { - IView view = View.Create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS); + var view = View.Create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS); var start = DateTimeOffset.FromUnixTimeMilliseconds(1000); var end = DateTimeOffset.FromUnixTimeMilliseconds(2000); - IViewData viewData = ViewData.Create(view, ENTRIES, start, end); + var viewData = ViewData.Create(view, ENTRIES, start, end); Assert.Equal(view, viewData.View); Assert.Equal(ENTRIES, viewData.AggregationMap); } @@ -88,25 +88,25 @@ public void TestCumulativeViewData() [Fact] public void TestViewDataEquals() { - IView cumulativeView = + var cumulativeView = View.Create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS); // View intervalView = // View.Create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR); // new EqualsTester() // .addEqualityGroup( - IViewData data1 = ViewData.Create( + var data1 = ViewData.Create( cumulativeView, ENTRIES, DateTimeOffset.FromUnixTimeMilliseconds(1000), DateTimeOffset.FromUnixTimeMilliseconds(2000)); - IViewData data2 = ViewData.Create( + var data2 = ViewData.Create( cumulativeView, ENTRIES, DateTimeOffset.FromUnixTimeMilliseconds(1000), DateTimeOffset.FromUnixTimeMilliseconds(2000)); Assert.Equal(data1, data2); // .addEqualityGroup( - IViewData data3 = ViewData.Create( + var data3 = ViewData.Create( cumulativeView, ENTRIES, DateTimeOffset.FromUnixTimeMilliseconds(1000), DateTimeOffset.FromUnixTimeMilliseconds(3000)); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs index 5255a704cf3..be1c4f5c0f0 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs @@ -90,7 +90,7 @@ private static IView CreateCumulativeView( [Fact] public void TestRegisterAndGetCumulativeView() { - IView view = CreateCumulativeView(); + var view = CreateCumulativeView(); viewManager.RegisterView(view); Assert.Equal(view, viewManager.GetView(VIEW_NAME).View); Assert.Empty(viewManager.GetView(VIEW_NAME).AggregationMap); @@ -101,10 +101,10 @@ public void TestRegisterAndGetCumulativeView() public void TestGetAllExportedViews() { Assert.Empty(viewManager.AllExportedViews); - IView cumulativeView1 = + var cumulativeView1 = CreateCumulativeView( ViewName.Create("View 1"), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - IView cumulativeView2 = + var cumulativeView2 = CreateCumulativeView( ViewName.Create("View 2"), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); // View intervalView = @@ -127,7 +127,7 @@ public void TestGetAllExportedViews() [Fact] public void GetAllExportedViewsResultIsUnmodifiable() { - IView view1 = + var view1 = View.Create( ViewName.Create("View 1"), VIEW_DESCRIPTION, @@ -135,9 +135,9 @@ public void GetAllExportedViewsResultIsUnmodifiable() DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view1); - ISet exported = viewManager.AllExportedViews; + var exported = viewManager.AllExportedViews; - IView view2 = + var view2 = View.Create( ViewName.Create("View 2"), VIEW_DESCRIPTION, @@ -168,7 +168,7 @@ public void GetAllExportedViewsResultIsUnmodifiable() [Fact] public void AllowRegisteringSameViewTwice() { - IView view = CreateCumulativeView(); + var view = CreateCumulativeView(); viewManager.RegisterView(view); viewManager.RegisterView(view); Assert.Equal(view, viewManager.GetView(VIEW_NAME).View); @@ -177,14 +177,14 @@ public void AllowRegisteringSameViewTwice() [Fact] public void PreventRegisteringDifferentViewWithSameName() { - IView view1 = + var view1 = View.Create( VIEW_NAME, "View description.", MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - IView view2 = + var view2 = View.Create( VIEW_NAME, "This is a different description.", @@ -197,12 +197,12 @@ public void PreventRegisteringDifferentViewWithSameName() [Fact] public void PreventRegisteringDifferentMeasureWithSameName() { - IMeasureDouble measure1 = MeasureDouble.Create("measure", "description", "1"); - IMeasureLong measure2 = MeasureLong.Create("measure", "description", "1"); - IView view1 = + var measure1 = MeasureDouble.Create("measure", "description", "1"); + var measure2 = MeasureLong.Create("measure", "description", "1"); + var view1 = View.Create( VIEW_NAME, VIEW_DESCRIPTION, measure1, DISTRIBUTION, new List() { KEY }); - IView view2 = + var view2 = View.Create( VIEW_NAME_2, VIEW_DESCRIPTION, measure2, DISTRIBUTION, new List() { KEY }); TestFailedToRegisterView(view1, view2, "A different measure with the same name is already registered"); @@ -263,14 +263,14 @@ public void TestRecordLong_Lastvalue_Cumulative() private void TestRecordCumulative(IMeasure measure, IAggregation aggregation, params double[] values) { - IView view = CreateCumulativeView(VIEW_NAME, measure, aggregation, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, measure, aggregation, new List() { KEY }); viewManager.RegisterView(view); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); - foreach (double val in values) + var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + foreach (var val in values) { PutToMeasureMap(statsRecorder.NewMeasureMap(), measure, val).Record(tags); } - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); Assert.Equal(view, viewData.View); var tv = TagValues.Create(new List() { VALUE }); @@ -287,11 +287,11 @@ private void TestRecordCumulative(IMeasure measure, IAggregation aggregation, pa [Fact] public void GetViewDoesNotClearStats() { - IView view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 0.1).Record(tags); - IViewData viewData1 = viewManager.GetView(VIEW_NAME); + var viewData1 = viewManager.GetView(VIEW_NAME); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, @@ -302,7 +302,7 @@ public void GetViewDoesNotClearStats() EPSILON); statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 0.2).Record(tags); - IViewData viewData2 = viewManager.GetView(VIEW_NAME); + var viewData2 = viewManager.GetView(VIEW_NAME); // The second view should have the same start time as the first view, and it should include both // Recorded values: @@ -333,7 +333,7 @@ public void TestRecordCumulativeMultipleTagValues() .NewMeasureMap() .Put(MEASURE_DOUBLE, 50.0) .Record(tagger.EmptyBuilder.Put(KEY, VALUE_2).Build()); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); var tv = TagValues.Create(new List() { VALUE }); var tv2 = TagValues.Create(new List() { VALUE_2 }); StatsTestUtil.AssertAggregationMapEquals( @@ -365,7 +365,7 @@ public void TestRecordWithEmptyStatsContext() CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY })); // DEFAULT doesn't have tags, but the view has tag key "KEY". statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 10.0).Record(tagger.Empty); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); var tv = TagValues.Create(new List() { MutableViewData.UnknownTagValue }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -403,9 +403,9 @@ public void TestRecord_MeasureTypeNotMatch() private void TestRecord_MeasureNotMatch(IMeasure measure1, IMeasure measure2, double value) { viewManager.RegisterView(CreateCumulativeView(VIEW_NAME, measure1, MEAN, new List() { KEY })); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); PutToMeasureMap(statsRecorder.NewMeasureMap(), measure2, value).Record(tags); - IViewData view = viewManager.GetView(VIEW_NAME); + var view = viewManager.GetView(VIEW_NAME); Assert.Empty(view.AggregationMap); } @@ -422,7 +422,7 @@ public void TestRecordWithTagsThatDoNotMatchViewData() .NewMeasureMap() .Put(MEASURE_DOUBLE, 50.0) .Record(tagger.EmptyBuilder.Put(TagKey.Create("another wrong key"), VALUE).Build()); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); var tv = TagValues.Create(new List() { MutableViewData.UnknownTagValue }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -440,8 +440,8 @@ public void TestRecordWithTagsThatDoNotMatchViewData() [Fact] public void TestViewDataWithMultipleTagKeys() { - TagKey key1 = TagKey.Create("Key-1"); - TagKey key2 = TagKey.Create("Key-2"); + var key1 = TagKey.Create("Key-1"); + var key2 = TagKey.Create("Key-2"); viewManager.RegisterView( CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { key1, key2 })); statsRecorder @@ -480,7 +480,7 @@ public void TestViewDataWithMultipleTagKeys() .Put(key1, TagValue.Create("v1")) .Put(key2, TagValue.Create("v10")) .Build()); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); var tv1 = TagValues.Create(new List() { TagValue.Create("v1"), TagValue.Create("v10") }); var tv2 = TagValues.Create(new List() { TagValue.Create("v1"), TagValue.Create("v20") }); var tv3 = TagValues.Create(new List() { TagValue.Create("v2"), TagValue.Create("v10") }); @@ -498,9 +498,9 @@ public void TestViewDataWithMultipleTagKeys() [Fact] public void TestMultipleViewSameMeasure() { - IView view1 = + var view1 = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - IView view2 = + var view2 = CreateCumulativeView(VIEW_NAME_2, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view1); viewManager.RegisterView(view2); @@ -508,8 +508,8 @@ public void TestMultipleViewSameMeasure() .NewMeasureMap() .Put(MEASURE_DOUBLE, 5.0) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - IViewData viewData1 = viewManager.GetView(VIEW_NAME); - IViewData viewData2 = viewManager.GetView(VIEW_NAME_2); + var viewData1 = viewManager.GetView(VIEW_NAME); + var viewData2 = viewManager.GetView(VIEW_NAME_2); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, @@ -550,18 +550,18 @@ public void TestMultipleViews_DifferentMeasureTypes() private void TestMultipleViews_DifferentMeasures(IMeasure measure1, IMeasure measure2, double value1, double value2) { - IView view1 = CreateCumulativeView(VIEW_NAME, measure1, DISTRIBUTION, new List() { KEY }); - IView view2 = + var view1 = CreateCumulativeView(VIEW_NAME, measure1, DISTRIBUTION, new List() { KEY }); + var view2 = CreateCumulativeView(VIEW_NAME_2, measure2, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view1); viewManager.RegisterView(view2); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); - IMeasureMap measureMap = statsRecorder.NewMeasureMap(); + var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + var measureMap = statsRecorder.NewMeasureMap(); PutToMeasureMap(measureMap, measure1, value1); PutToMeasureMap(measureMap, measure2, value2); measureMap.Record(tags); - IViewData viewData1 = viewManager.GetView(VIEW_NAME); - IViewData viewData2 = viewManager.GetView(VIEW_NAME_2); + var viewData1 = viewManager.GetView(VIEW_NAME); + var viewData2 = viewManager.GetView(VIEW_NAME_2); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, @@ -585,13 +585,13 @@ public void TestGetCumulativeViewDataWithEmptyBucketBoundaries() { IAggregation noHistogram = Distribution.Create(BucketBoundaries.Create(Enumerable.Empty())); - IView view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, noHistogram, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, noHistogram, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -605,13 +605,13 @@ public void TestGetCumulativeViewDataWithEmptyBucketBoundaries() [Fact] public void TestGetCumulativeViewDataWithoutBucketBoundaries() { - IView view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - IViewData viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(VIEW_NAME); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -626,7 +626,7 @@ public void TestGetCumulativeViewDataWithoutBucketBoundaries() public void RegisterRecordAndGetView_StatsDisabled() { statsComponent.State = StatsCollectionState.DISABLED; - IView view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() @@ -640,13 +640,13 @@ public void RegisterRecordAndGetView_StatsReenabled() { statsComponent.State = StatsCollectionState.DISABLED; statsComponent.State = StatsCollectionState.ENABLED; - IView view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - TagValues tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(VIEW_NAME).AggregationMap, new Dictionary() @@ -660,7 +660,7 @@ public void RegisterRecordAndGetView_StatsReenabled() public void RegisterViewWithStatsDisabled_RecordAndGetViewWithStatsEnabled() { statsComponent.State = StatsCollectionState.DISABLED; - IView view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); // view will still be registered. statsComponent.State = StatsCollectionState.ENABLED; @@ -668,7 +668,7 @@ public void RegisterViewWithStatsDisabled_RecordAndGetViewWithStatsEnabled() .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - TagValues tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(VIEW_NAME).AggregationMap, new Dictionary() @@ -682,14 +682,14 @@ public void RegisterViewWithStatsDisabled_RecordAndGetViewWithStatsEnabled() public void RegisterDifferentViewWithSameNameWithStatsDisabled() { statsComponent.State = StatsCollectionState.DISABLED; - IView view1 = + var view1 = View.Create( VIEW_NAME, "View description.", MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - IView view2 = + var view2 = View.Create( VIEW_NAME, "This is a different description.", @@ -704,7 +704,7 @@ public void RegisterDifferentViewWithSameNameWithStatsDisabled() [Fact] public void SettingStateToDisabledWillClearStats_Cumulative() { - IView cumulativeView = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + var cumulativeView = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); SettingStateToDisabledWillClearStats(cumulativeView); } @@ -725,14 +725,14 @@ public void SettingStateToDisabledWillClearStats_Cumulative() private void SettingStateToDisabledWillClearStats(IView view) { // TODO: deal with timestamp validation - Timestamp timestamp1 = Timestamp.Create(1, 0); + var timestamp1 = Timestamp.Create(1, 0); //clock.Time = timestamp1; viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - TagValues tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(view.Name).AggregationMap, new Dictionary() @@ -741,20 +741,20 @@ private void SettingStateToDisabledWillClearStats(IView view) }, EPSILON); - Timestamp timestamp2 = Timestamp.Create(2, 0); + var timestamp2 = Timestamp.Create(2, 0); //clock.Time = timestamp2; statsComponent.State = StatsCollectionState.DISABLED; // This will clear stats. Assert.Equal(StatsTestUtil.CreateEmptyViewData(view), viewManager.GetView(view.Name)); - Timestamp timestamp3 = Timestamp.Create(3, 0); + var timestamp3 = Timestamp.Create(3, 0); //clock.Time = timestamp3; statsComponent.State = StatsCollectionState.ENABLED; - Timestamp timestamp4 = Timestamp.Create(4, 0); + var timestamp4 = Timestamp.Create(4, 0); //clock.Time = timestamp4; // This ViewData does not have any stats, but it should not be an empty ViewData, since it has // non-zero TimeStamps. - IViewData viewData = viewManager.GetView(view.Name); + var viewData = viewManager.GetView(view.Name); Assert.Empty(viewData.AggregationMap); //Assert.Equal(timestamp3, viewData.Start); //Assert.Equal(timestamp4, viewData.End); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs index 7f68c813013..9a713de0840 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs @@ -48,7 +48,7 @@ public void TestConstants() [Fact] public void TestDistributionView() { - IView view = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); + var view = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); Assert.Equal(NAME, view.Name); Assert.Equal(DESCRIPTION, view.Description); Assert.Equal(MEASURE.Name, view.Measure.Name); @@ -63,10 +63,10 @@ public void TestDistributionView() public void testViewEquals() { - IView view1 = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); - IView view2 = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); + var view1 = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); + var view2 = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); Assert.Equal(view1, view2); - IView view3 = View.Create(NAME, DESCRIPTION + 2, MEASURE, MEAN, keys); + var view3 = View.Create(NAME, DESCRIPTION + 2, MEASURE, MEAN, keys); Assert.NotEqual(view1, view3); Assert.NotEqual(view2, view3); @@ -92,13 +92,13 @@ public void PreventNullViewName() [Fact] public void PreventTooLongViewName() { - char[] chars = new char[ViewName.NameMaxLength + 1]; - for (int i = 0; i < chars.Length; i++) + var chars = new char[ViewName.NameMaxLength + 1]; + for (var i = 0; i < chars.Length; i++) { chars[i] = 'a'; } - String longName = new String(chars); + var longName = new String(chars); Assert.Throws(() => ViewName.Create(longName)); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs index addc30df4a2..28889e0df4a 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs @@ -30,7 +30,7 @@ public class CurrentTagContextUtilsTest [Fact] public void TestGetCurrentTagContext_DefaultContext() { - ITagContext tags = CurrentTagContextUtils.CurrentTagContext; + var tags = CurrentTagContextUtils.CurrentTagContext; Assert.NotNull(tags); Assert.Empty(TagsTestUtil.TagContextToList(tags)); } @@ -42,7 +42,7 @@ public void TestGetCurrentTagContext_ContextSetToNull() AsyncLocalContext.CurrentTagContext = null; try { - ITagContext tags = CurrentTagContextUtils.CurrentTagContext; + var tags = CurrentTagContextUtils.CurrentTagContext; Assert.NotNull(tags); Assert.Empty(TagsTestUtil.TagContextToList(tags)); } @@ -57,7 +57,7 @@ public void TestWithTagContext() { Assert.Empty(TagsTestUtil.TagContextToList(CurrentTagContextUtils.CurrentTagContext)); - IScope scopedTags = CurrentTagContextUtils.WithTagContext(tagContext); + var scopedTags = CurrentTagContextUtils.WithTagContext(tagContext); try { Assert.Same(tagContext, CurrentTagContextUtils.CurrentTagContext); diff --git a/test/OpenTelemetry.Tests/Impl/Tags/CurrentTaggingStateTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/CurrentTaggingStateTest.cs index 84946aba9bb..1023f33f466 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/CurrentTaggingStateTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/CurrentTaggingStateTest.cs @@ -30,7 +30,7 @@ public void DefaultState() [Fact] public void SetState() { - CurrentTaggingState state = new CurrentTaggingState(); + var state = new CurrentTaggingState(); state.Set(TaggingState.DISABLED); Assert.Equal(TaggingState.DISABLED, state.Internal); state.Set(TaggingState.ENABLED); @@ -41,7 +41,7 @@ public void SetState() [Fact] public void PreventSettingStateAfterReadingState() { - CurrentTaggingState state = new CurrentTaggingState(); + var state = new CurrentTaggingState(); var current = state.Value; Assert.Throws(() => state.Set(TaggingState.DISABLED)); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs index a9224619d81..bec6cddc274 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs @@ -43,7 +43,7 @@ public void NoopTagsComponent() [Fact] public void NoopTagger() { - ITagger noopTagger = NoopTags.NoopTagger; + var noopTagger = NoopTags.NoopTagger; Assert.Same(NoopTags.NoopTagContext, noopTagger.Empty); Assert.Same(NoopTags.NoopTagContext, noopTagger.CurrentTagContext); Assert.Same(NoopTags.NoopTagContextBuilder, noopTagger.EmptyBuilder); @@ -55,14 +55,14 @@ public void NoopTagger() [Fact] public void NoopTagger_ToBuilder_DisallowsNull() { - ITagger noopTagger = NoopTags.NoopTagger; + var noopTagger = NoopTags.NoopTagger; Assert.Throws(() => noopTagger.ToBuilder(null)); } [Fact] public void NoopTagger_WithTagContext_DisallowsNull() { - ITagger noopTagger = NoopTags.NoopTagger; + var noopTagger = NoopTags.NoopTagger; Assert.Throws(() => noopTagger.WithTagContext(null)); } @@ -78,21 +78,21 @@ public void NoopTagContextBuilder() [Fact] public void NoopTagContextBuilder_Put_DisallowsNullKey() { - ITagContextBuilder noopBuilder = NoopTags.NoopTagContextBuilder; + var noopBuilder = NoopTags.NoopTagContextBuilder; Assert.Throws(() => noopBuilder.Put(null, VALUE)); } [Fact] public void NoopTagContextBuilder_Put_DisallowsNullValue() { - ITagContextBuilder noopBuilder = NoopTags.NoopTagContextBuilder; + var noopBuilder = NoopTags.NoopTagContextBuilder; Assert.Throws(() => noopBuilder.Put(KEY, null)); } [Fact] public void NoopTagContextBuilder_Remove_DisallowsNullKey() { - ITagContextBuilder noopBuilder = NoopTags.NoopTagContextBuilder; + var noopBuilder = NoopTags.NoopTagContextBuilder; Assert.Throws(() => noopBuilder.Remove(null)); } @@ -118,14 +118,14 @@ public void NoopTagContextBinarySerializer() [Fact] public void NoopTagContextBinarySerializer_ToByteArray_DisallowsNull() { - ITagContextBinarySerializer noopSerializer = NoopTags.NoopTagContextBinarySerializer; + var noopSerializer = NoopTags.NoopTagContextBinarySerializer; Assert.Throws(() => noopSerializer.ToByteArray(null)); } [Fact] public void NoopTagContextBinarySerializer_FromByteArray_DisallowsNull() { - ITagContextBinarySerializer noopSerializer = NoopTags.NoopTagContextBinarySerializer; + var noopSerializer = NoopTags.NoopTagContextBinarySerializer; Assert.Throws(() => noopSerializer.FromByteArray(null)); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationExceptionTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationExceptionTest.cs index 4175060d8a6..ca3f3514d80 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationExceptionTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationExceptionTest.cs @@ -30,8 +30,8 @@ public void CreateWithMessage() [Fact] public void CreateWithMessageAndCause() { - Exception cause = new Exception(); - TagContextDeserializationException exception = new TagContextDeserializationException("my message", cause); + var cause = new Exception(); + var exception = new TagContextDeserializationException("my message", cause); Assert.Equal("my message", exception.Message); Assert.Equal(cause, exception.InnerException); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs index e6b1d4c2be7..435325c6103 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs @@ -46,8 +46,8 @@ public void TestConstants() [Fact] public void TestDeserializeNoTags() { - ITagContext expected = tagger.Empty; - ITagContext actual = serializer.FromByteArray(new byte[] { SerializationUtils.VersionId }); // One byte that represents Version ID. + var expected = tagger.Empty; + var actual = serializer.FromByteArray(new byte[] { SerializationUtils.VersionId }); // One byte that represents Version ID. Assert.Equal(expected, actual); } @@ -60,9 +60,9 @@ public void TestDeserializeEmptyByteArrayThrowException() [Fact] public void TestDeserializeTooLargeByteArrayThrowException() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); - for (int i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8 - 1; i++) { + for (var i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8 - 1; i++) { // Each tag will be with format {key : "0123", value : "0123"}, so the length of it is 8. String str; if (i < 10) @@ -87,7 +87,7 @@ public void TestDeserializeTooLargeByteArrayThrowException() // more than limit. EncodeTagToOutPut("last", "last1", output); - byte[] bytes = output.ToArray(); + var bytes = output.ToArray(); Assert.Throws(() => serializer.FromByteArray(bytes)); } @@ -97,9 +97,9 @@ public void TestDeserializeTooLargeByteArrayThrowException() [Fact] public void TestDeserializeTooLargeByteArrayThrowException_WithDuplicateTagKeys() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); - for (int i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8 - 1; i++) { + for (var i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8 - 1; i++) { // Each tag will be with format {key : "key_", value : "0123"}, so the length of it is 8. String str; if (i < 10) @@ -124,7 +124,7 @@ public void TestDeserializeTooLargeByteArrayThrowException_WithDuplicateTagKeys( // more than limit. EncodeTagToOutPut("key_", "last1", output); - byte[] bytes = output.ToArray(); + var bytes = output.ToArray(); Assert.Throws(() => serializer.FromByteArray(bytes)); } @@ -132,12 +132,12 @@ public void TestDeserializeTooLargeByteArrayThrowException_WithDuplicateTagKeys( [Fact] public void TestDeserializeInvalidTagKey() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); // Encode an invalid tag key and a valid tag value: EncodeTagToOutPut("\u0002key", "value", output); - byte[] bytes = output.ToArray(); + var bytes = output.ToArray(); Assert.Throws(() => serializer.FromByteArray(bytes)); @@ -146,12 +146,12 @@ public void TestDeserializeInvalidTagKey() [Fact] public void TestDeserializeInvalidTagValue() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); // Encode a valid tag key and an invalid tag value: EncodeTagToOutPut("my key", "val\u0003", output); - byte[] bytes = output.ToArray(); + var bytes = output.ToArray(); Assert.Throws(() => serializer.FromByteArray(bytes)); @@ -160,21 +160,21 @@ public void TestDeserializeInvalidTagValue() [Fact] public void TestDeserializeOneTag() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key", "Value", output); - ITagContext expected = tagger.EmptyBuilder.Put(TagKey.Create("Key"), TagValue.Create("Value")).Build(); + var expected = tagger.EmptyBuilder.Put(TagKey.Create("Key"), TagValue.Create("Value")).Build(); Assert.Equal(expected, serializer.FromByteArray(output.ToArray())); } [Fact] public void TestDeserializeMultipleTags() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key2", "Value2", output); - ITagContext expected = + var expected = tagger .EmptyBuilder .Put(TagKey.Create("Key1"), TagValue.Create("Value1")) @@ -186,11 +186,11 @@ public void TestDeserializeMultipleTags() [Fact] public void TestDeserializeDuplicateKeys() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key1", "Value2", output); - ITagContext expected = + var expected = tagger.EmptyBuilder.Put(TagKey.Create("Key1"), TagValue.Create("Value2")).Build(); Assert.Equal(expected, serializer.FromByteArray(output.ToArray())); @@ -199,14 +199,14 @@ public void TestDeserializeDuplicateKeys() [Fact] public void TestDeserializeNonConsecutiveDuplicateKeys() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key2", "Value2", output); EncodeTagToOutPut("Key3", "Value3", output); EncodeTagToOutPut("Key1", "Value4", output); EncodeTagToOutPut("Key2", "Value5", output); - ITagContext expected = + var expected = tagger .EmptyBuilder .Put(TagKey.Create("Key1"), TagValue.Create("Value4")) @@ -219,11 +219,11 @@ public void TestDeserializeNonConsecutiveDuplicateKeys() [Fact] public void TestDeserializeDuplicateTags() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key1", "Value1", output); - ITagContext expected = + var expected = tagger.EmptyBuilder.Put(TagKey.Create("Key1"), TagValue.Create("Value1")).Build(); Assert.Equal(expected, serializer.FromByteArray(output.ToArray())); } @@ -231,14 +231,14 @@ public void TestDeserializeDuplicateTags() [Fact] public void TestDeserializeNonConsecutiveDuplicateTags() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key2", "Value2", output); EncodeTagToOutPut("Key3", "Value3", output); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key2", "Value2", output); - ITagContext expected = + var expected = tagger .EmptyBuilder .Put(TagKey.Create("Key1"), TagValue.Create("Value1")) @@ -251,7 +251,7 @@ public void TestDeserializeNonConsecutiveDuplicateTags() [Fact] public void StopParsingAtUnknownField() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); EncodeTagToOutPut("Key1", "Value1", output); EncodeTagToOutPut("Key2", "Value2", output); @@ -263,7 +263,7 @@ public void StopParsingAtUnknownField() EncodeTagToOutPut("Key3", "Value3", output); // key 3 should not be included - ITagContext expected = + var expected = tagger .EmptyBuilder .Put(TagKey.Create("Key1"), TagValue.Create("Value1")) @@ -275,7 +275,7 @@ public void StopParsingAtUnknownField() [Fact] public void StopParsingAtUnknownTagAtStart() { - MemoryStream output = new MemoryStream(); + var output = new MemoryStream(); output.WriteByte(SerializationUtils.VersionId); // Write unknown field ID 1. @@ -321,11 +321,11 @@ private static void EncodeTagToOutPut(String key, String value, MemoryStream out private static void EncodeString(String input, MemoryStream output) { - int length = input.Length; - byte[] bytes = new byte[VarInt.VarIntSize(length)]; + var length = input.Length; + var bytes = new byte[VarInt.VarIntSize(length)]; VarInt.PutVarInt(length, bytes, 0); output.Write(bytes, 0, bytes.Length); - byte[] inPutBytes = Encoding.UTF8.GetBytes(input); + var inPutBytes = Encoding.UTF8.GetBytes(input); output.Write(inPutBytes, 0, inPutBytes.Length); } } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs index daf4f27dec8..3af3113e89f 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs @@ -53,8 +53,8 @@ public void TestRoundtripSerialization_NormalTagContext() [Fact] public void TestRoundtrip_TagContextWithMaximumSize() { - ITagContextBuilder builder = tagger.EmptyBuilder; - for (int i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8; i++) + var builder = tagger.EmptyBuilder; + for (var i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8; i++) { // Each tag will be with format {key : "0123", value : "0123"}, so the length of it is 8. // Add 1024 tags, the total size should just be 8192. @@ -82,8 +82,8 @@ public void TestRoundtrip_TagContextWithMaximumSize() private void TestRoundtripSerialization(ITagContext expected) { - byte[] bytes = serializer.ToByteArray(expected); - ITagContext actual = serializer.FromByteArray(bytes); + var bytes = serializer.ToByteArray(expected); + var actual = serializer.FromByteArray(bytes); Assert.Equal(expected, actual); } } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationExceptionTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationExceptionTest.cs index 2b7f95d8623..4f3a4987d2b 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationExceptionTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationExceptionTest.cs @@ -30,8 +30,8 @@ public void CreateWithMessage() [Fact] public void CreateWithMessageAndCause() { - Exception cause = new Exception(); - TagContextSerializationException exception = new TagContextSerializationException("my message", cause); + var cause = new Exception(); + var exception = new TagContextSerializationException("my message", cause); Assert.Equal("my message", exception.Message); Assert.Equal(cause, exception.InnerException); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs index 8ca15782d1e..3733d183cc6 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs @@ -73,8 +73,8 @@ public void TestSerializeWithMultipleTags() [Fact] public void TestSerializeTooLargeTagContext() { - ITagContextBuilder builder = tagger.EmptyBuilder; - for (int i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8 - 1; i++) { + var builder = tagger.EmptyBuilder; + for (var i = 0; i < SerializationUtils.TagContextSerializedSizeLimit / 8 - 1; i++) { // Each tag will be with format {key : "0123", value : "0123"}, so the length of it is 8. String str; if (i < 10) @@ -99,27 +99,27 @@ public void TestSerializeTooLargeTagContext() // more than limit. builder.Put(TagKey.Create("last"), TagValue.Create("last1")); - ITagContext tagContext = builder.Build(); + var tagContext = builder.Build(); Assert.Throws(() => serializer.ToByteArray(tagContext)); } private void TestSerialize(params Tag[] tags) { - ITagContextBuilder builder = tagger.EmptyBuilder; + var builder = tagger.EmptyBuilder; foreach (var tag in tags) { builder.Put(tag.Key, tag.Value); } - byte[] actual = serializer.ToByteArray(builder.Build()); + var actual = serializer.ToByteArray(builder.Build()); var tagsList = tags.ToList(); var tagPermutation = Permutate(tagsList, tagsList.Count); ISet possibleOutPuts = new HashSet(); foreach (List list in tagPermutation) { - MemoryStream expected = new MemoryStream(); + var expected = new MemoryStream(); expected.WriteByte(SerializationUtils.VersionId); - foreach (Tag tag in list) { + foreach (var tag in list) { expected.WriteByte(SerializationUtils.TagFieldId); EncodeString(tag.Key.Name, expected); EncodeString(tag.Value.AsString, expected); @@ -140,7 +140,7 @@ private static void EncodeString(String input, MemoryStream byteArrayOutPutStrea internal static void RotateRight(IList sequence, int count) { - object tmp = sequence[count - 1]; + var tmp = sequence[count - 1]; sequence.RemoveAt(count - 1); sequence.Insert(0, tmp); } @@ -153,7 +153,7 @@ internal static IEnumerable Permutate(IList sequence, int count) } else { - for (int i = 0; i < count; i++) + for (var i = 0; i < count; i++) { foreach (var perm in Permutate(sequence, count - 1)) { diff --git a/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs index a418959a810..589b96000f8 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs @@ -33,7 +33,7 @@ public class ScopedTagContextsTest [Fact] public void DefaultTagContext() { - ITagContext defaultTagContext = tagger.CurrentTagContext; + var defaultTagContext = tagger.CurrentTagContext; Assert.Empty(TagsTestUtil.TagContextToList(defaultTagContext)); Assert.IsType(defaultTagContext); } @@ -42,8 +42,8 @@ public void DefaultTagContext() public void WithTagContext() { Assert.Empty(TagsTestUtil.TagContextToList(tagger.CurrentTagContext)); - ITagContext scopedTags = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).Build(); - IScope scope = tagger.WithTagContext(scopedTags); + var scopedTags = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).Build(); + var scope = tagger.WithTagContext(scopedTags); try { Assert.Same(scopedTags, tagger.CurrentTagContext); @@ -58,11 +58,11 @@ public void WithTagContext() [Fact] public void CreateBuilderFromCurrentTags() { - ITagContext scopedTags = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).Build(); - IScope scope = tagger.WithTagContext(scopedTags); + var scopedTags = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).Build(); + var scope = tagger.WithTagContext(scopedTags); try { - ITagContext newTags = tagger.CurrentBuilder.Put(KEY_2, VALUE_2).Build(); + var newTags = tagger.CurrentBuilder.Put(KEY_2, VALUE_2).Build(); Assert.Equal(new List() { Tag.Create(KEY_1, VALUE_1), Tag.Create(KEY_2, VALUE_2) }, TagsTestUtil.TagContextToList(newTags)); Assert.Same(scopedTags, tagger.CurrentTagContext); @@ -77,7 +77,7 @@ public void CreateBuilderFromCurrentTags() public void SetCurrentTagsWithBuilder() { Assert.Empty(TagsTestUtil.TagContextToList(tagger.CurrentTagContext)); - IScope scope = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).BuildScoped(); + var scope = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).BuildScoped(); try { Assert.Equal(new List() { Tag.Create(KEY_1, VALUE_1) }, TagsTestUtil.TagContextToList(tagger.CurrentTagContext)); @@ -92,11 +92,11 @@ public void SetCurrentTagsWithBuilder() [Fact] public void AddToCurrentTagsWithBuilder() { - ITagContext scopedTags = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).Build(); - IScope scope1 = tagger.WithTagContext(scopedTags); + var scopedTags = tagger.EmptyBuilder.Put(KEY_1, VALUE_1).Build(); + var scope1 = tagger.WithTagContext(scopedTags); try { - IScope scope2 = tagger.CurrentBuilder.Put(KEY_2, VALUE_2).BuildScoped(); + var scope2 = tagger.CurrentBuilder.Put(KEY_2, VALUE_2).BuildScoped(); try { Assert.Equal(new List() { Tag.Create(KEY_1, VALUE_1), Tag.Create(KEY_2, VALUE_2) }, diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagContextTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagContextTest.cs index 2cc72320dec..fc89011852c 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TagContextTest.cs @@ -34,21 +34,21 @@ public class TagContextTest [Fact] public void getTags_empty() { - TagContext tags = new TagContext(new Dictionary()); + var tags = new TagContext(new Dictionary()); Assert.Empty(tags.Tags); } [Fact] public void getTags_nonEmpty() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 }, { K2, V2 } }); + var tags = new TagContext(new Dictionary() { { K1, V1 }, { K2, V2 } }); Assert.Equal(new Dictionary() { { K1, V1 }, { K2, V2 } }, tags.Tags); } [Fact] public void Put_NewKey() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 } }); + var tags = new TagContext(new Dictionary() { { K1, V1 } }); Assert.Equal(new Dictionary() { { K1, V1 }, { K2, V2 } }, ((TagContext)tagger.ToBuilder(tags).Put(K2, V2).Build()).Tags); } @@ -56,7 +56,7 @@ public void Put_NewKey() [Fact] public void Put_ExistingKey() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 } }); + var tags = new TagContext(new Dictionary() { { K1, V1 } }); Assert.Equal(new Dictionary() { { K1, V2 } }, ((TagContext)tagger.ToBuilder(tags).Put(K1, V2).Build()).Tags); } @@ -64,50 +64,50 @@ public void Put_ExistingKey() [Fact] public void Put_NullKey() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 } }); - ITagContextBuilder builder = tagger.ToBuilder(tags); + var tags = new TagContext(new Dictionary() { { K1, V1 } }); + var builder = tagger.ToBuilder(tags); Assert.Throws(() => builder.Put(null, V2)); } [Fact] public void Put_NullValue() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 } }); - ITagContextBuilder builder = tagger.ToBuilder(tags); + var tags = new TagContext(new Dictionary() { { K1, V1 } }); + var builder = tagger.ToBuilder(tags); Assert.Throws(() => builder.Put(K2, null)); } [Fact] public void Remove_ExistingKey() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 }, { K2, V2 } }); + var tags = new TagContext(new Dictionary() { { K1, V1 }, { K2, V2 } }); Assert.Equal(new Dictionary() { { K2, V2 } }, ((TagContext)tagger.ToBuilder(tags).Remove(K1).Build()).Tags); } [Fact] public void Remove_DifferentKey() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 } }); + var tags = new TagContext(new Dictionary() { { K1, V1 } }); Assert.Equal(new Dictionary() { { K1, V1 } }, ((TagContext)tagger.ToBuilder(tags).Remove(K2).Build()).Tags); } [Fact] public void Remove_NullKey() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 } }); - ITagContextBuilder builder = tagger.ToBuilder(tags); + var tags = new TagContext(new Dictionary() { { K1, V1 } }); + var builder = tagger.ToBuilder(tags); Assert.Throws(() => builder.Remove(null)); } [Fact] public void TestIterator() { - TagContext tags = new TagContext(new Dictionary() { { K1, V1 }, { K2, V2 } }); + var tags = new TagContext(new Dictionary() { { K1, V1 }, { K2, V2 } }); var i = tags.GetEnumerator(); Assert.True(i.MoveNext()); - Tag tag1 = i.Current; + var tag1 = i.Current; Assert.True(i.MoveNext()); - Tag tag2 = i.Current; + var tag2 = i.Current; Assert.False(i.MoveNext()); Assert.Equal(new List() { Tag.Create(K1, V1), Tag.Create(K2, V2)}, new List() { tag1, tag2 }); diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagKeyTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagKeyTest.cs index b56109451de..30b879ddb81 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagKeyTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TagKeyTest.cs @@ -36,26 +36,26 @@ public void TestGetName() [Fact] public void Create_AllowTagKeyNameWithMaxLength() { - char[] chars = new char[TagKey.MaxLength]; - for (int i = 0; i < chars.Length; i++) + var chars = new char[TagKey.MaxLength]; + for (var i = 0; i < chars.Length; i++) { chars[i] = 'k'; } - String key = new String(chars); + var key = new String(chars); Assert.Equal(key, TagKey.Create(key).Name); } [Fact] public void Create_DisallowTagKeyNameOverMaxLength() { - char[] chars = new char[TagKey.MaxLength + 1]; - for (int i = 0; i < chars.Length; i++) + var chars = new char[TagKey.MaxLength + 1]; + for (var i = 0; i < chars.Length; i++) { chars[i] = 'k'; } - String key = new String(chars); + var key = new String(chars); Assert.Throws(() => TagKey.Create(key)); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagTest.cs index 5dd56f64305..f134605044f 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TagTest.cs @@ -29,10 +29,10 @@ public void TestGetKey() [Fact] public void TestTagEquals() { - Tag tag1 = Tag.Create(TagKey.Create("Key"), TagValue.Create("foo")); - Tag tag2 = Tag.Create(TagKey.Create("Key"), TagValue.Create("foo")); - Tag tag3 = Tag.Create(TagKey.Create("Key"), TagValue.Create("bar")); - Tag tag4 = Tag.Create(TagKey.Create("Key2"), TagValue.Create("foo")); + var tag1 = Tag.Create(TagKey.Create("Key"), TagValue.Create("foo")); + var tag2 = Tag.Create(TagKey.Create("Key"), TagValue.Create("foo")); + var tag3 = Tag.Create(TagKey.Create("Key"), TagValue.Create("bar")); + var tag4 = Tag.Create(TagKey.Create("Key2"), TagValue.Create("foo")); Assert.Equal(tag1, tag2); Assert.NotEqual(tag1, tag3); Assert.NotEqual(tag1, tag4); diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagValueTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagValueTest.cs index ab539656aef..69d2aca20ce 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagValueTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TagValueTest.cs @@ -36,33 +36,33 @@ public void TestAsString() [Fact] public void Create_AllowTagValueWithMaxLength() { - char[] chars = new char[TagValue.MaxLength]; - for (int i = 0; i < chars.Length; i++) + var chars = new char[TagValue.MaxLength]; + for (var i = 0; i < chars.Length; i++) { chars[i] = 'v'; } - String value = new String(chars); + var value = new String(chars); Assert.Equal(value, TagValue.Create(value).AsString); } [Fact] public void Create_DisallowTagValueOverMaxLength() { - char[] chars = new char[TagValue.MaxLength + 1]; - for (int i = 0; i < chars.Length; i++) + var chars = new char[TagValue.MaxLength + 1]; + for (var i = 0; i < chars.Length; i++) { chars[i] = 'v'; } - String value = new String(chars); + var value = new String(chars); Assert.Throws(() => TagValue.Create(value)); } [Fact] public void DisallowTagValueWithUnprintableChars() { - String value = "\u02ab\u03cd"; + var value = "\u02ab\u03cd"; Assert.Throws(() => TagValue.Create(value)); } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs index d6234e3e39c..a8187b15430 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs @@ -61,7 +61,7 @@ public void Empty() [Fact] public void EmptyBuilder() { - ITagContextBuilder builder = tagger.EmptyBuilder; + var builder = tagger.EmptyBuilder; Assert.IsType(builder); Assert.Empty(TagsTestUtil.TagContextToList(builder.Build())); } @@ -88,7 +88,7 @@ public void EmptyBuilder() public void CurrentBuilder() { ITagContext tags = new SimpleTagContext(TAG1, TAG2, TAG3); - ITagContextBuilder result = GetResultOfCurrentBuilder(tags); + var result = GetResultOfCurrentBuilder(tags); Assert.IsType(result); Assert.Equal(new List() { TAG1, TAG2, TAG3 }, TagsTestUtil.TagContextToList(result.Build())); } @@ -96,7 +96,7 @@ public void CurrentBuilder() [Fact] public void CurrentBuilder_DefaultIsEmpty() { - ITagContextBuilder currentBuilder = tagger.CurrentBuilder; + var currentBuilder = tagger.CurrentBuilder; Assert.IsType(currentBuilder); Assert.Empty(TagsTestUtil.TagContextToList(currentBuilder.Build())); } @@ -104,10 +104,10 @@ public void CurrentBuilder_DefaultIsEmpty() [Fact] public void CurrentBuilder_RemoveDuplicateTags() { - Tag tag1 = Tag.Create(K1, V1); - Tag tag2 = Tag.Create(K1, V2); + var tag1 = Tag.Create(K1, V1); + var tag2 = Tag.Create(K1, V2); ITagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2); - ITagContextBuilder result = GetResultOfCurrentBuilder(tagContextWithDuplicateTags); + var result = GetResultOfCurrentBuilder(tagContextWithDuplicateTags); Assert.Equal(new List() { tag2 }, TagsTestUtil.TagContextToList(result.Build())); } @@ -115,7 +115,7 @@ public void CurrentBuilder_RemoveDuplicateTags() public void CurrentBuilder_SkipNullTag() { ITagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2); - ITagContextBuilder result = GetResultOfCurrentBuilder(tagContextWithNullTag); + var result = GetResultOfCurrentBuilder(tagContextWithNullTag); Assert.Equal(new List() { TAG1, TAG2 }, TagsTestUtil.TagContextToList(result.Build())); } @@ -141,7 +141,7 @@ public void CurrentBuilder_SkipNullTag() private ITagContextBuilder GetResultOfCurrentBuilder(ITagContext tagsToSet) { - ITagContext orig = AsyncLocalContext.CurrentTagContext; // Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagsToSet).attach(); + var orig = AsyncLocalContext.CurrentTagContext; // Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagsToSet).attach(); AsyncLocalContext.CurrentTagContext = tagsToSet; try { @@ -157,7 +157,7 @@ private ITagContextBuilder GetResultOfCurrentBuilder(ITagContext tagsToSet) public void ToBuilder_ConvertUnknownTagContextToTagContext() { ITagContext unknownTagContext = new SimpleTagContext(TAG1, TAG2, TAG3); - ITagContext newTagContext = tagger.ToBuilder(unknownTagContext).Build(); + var newTagContext = tagger.ToBuilder(unknownTagContext).Build(); Assert.Equal(new List() { TAG1, TAG2, TAG3 }, TagsTestUtil.TagContextToList(newTagContext)); Assert.IsType(newTagContext); } @@ -165,10 +165,10 @@ public void ToBuilder_ConvertUnknownTagContextToTagContext() [Fact] public void ToBuilder_RemoveDuplicatesFromUnknownTagContext() { - Tag tag1 = Tag.Create(K1, V1); - Tag tag2 = Tag.Create(K1, V2); + var tag1 = Tag.Create(K1, V1); + var tag2 = Tag.Create(K1, V2); ITagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2); - ITagContext newTagContext = tagger.ToBuilder(tagContextWithDuplicateTags).Build(); + var newTagContext = tagger.ToBuilder(tagContextWithDuplicateTags).Build(); Assert.Equal(new List() { tag2 }, TagsTestUtil.TagContextToList(newTagContext)); } @@ -176,7 +176,7 @@ public void ToBuilder_RemoveDuplicatesFromUnknownTagContext() public void ToBuilder_SkipNullTag() { ITagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2); - ITagContext newTagContext = tagger.ToBuilder(tagContextWithNullTag).Build(); + var newTagContext = tagger.ToBuilder(tagContextWithNullTag).Build(); Assert.Equal(new List() { TAG1, TAG2 }, TagsTestUtil.TagContextToList(newTagContext)); } @@ -203,7 +203,7 @@ public void ToBuilder_SkipNullTag() [Fact] public void GetCurrentTagContext_DefaultIsEmptyTagContext() { - ITagContext currentTagContext = tagger.CurrentTagContext; + var currentTagContext = tagger.CurrentTagContext; Assert.Empty(TagsTestUtil.TagContextToList(currentTagContext)); Assert.IsType(currentTagContext); } @@ -212,7 +212,7 @@ public void GetCurrentTagContext_DefaultIsEmptyTagContext() public void GetCurrentTagContext_ConvertUnknownTagContextToTagContext() { ITagContext unknownTagContext = new SimpleTagContext(TAG1, TAG2, TAG3); - ITagContext result = GetResultOfGetCurrentTagContext(unknownTagContext); + var result = GetResultOfGetCurrentTagContext(unknownTagContext); Assert.IsType(result); Assert.Equal(new List() { TAG1, TAG2, TAG3 }, TagsTestUtil.TagContextToList(result)); } @@ -220,10 +220,10 @@ public void GetCurrentTagContext_ConvertUnknownTagContextToTagContext() [Fact] public void GetCurrentTagContext_RemoveDuplicatesFromUnknownTagContext() { - Tag tag1 = Tag.Create(K1, V1); - Tag tag2 = Tag.Create(K1, V2); + var tag1 = Tag.Create(K1, V1); + var tag2 = Tag.Create(K1, V2); ITagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2); - ITagContext result = GetResultOfGetCurrentTagContext(tagContextWithDuplicateTags); + var result = GetResultOfGetCurrentTagContext(tagContextWithDuplicateTags); Assert.Equal(new List() { tag2 }, TagsTestUtil.TagContextToList(result)); } @@ -231,7 +231,7 @@ public void GetCurrentTagContext_RemoveDuplicatesFromUnknownTagContext() public void GetCurrentTagContext_SkipNullTag() { ITagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2); - ITagContext result = GetResultOfGetCurrentTagContext(tagContextWithNullTag); + var result = GetResultOfGetCurrentTagContext(tagContextWithNullTag); Assert.Equal(new List() { TAG1, TAG2 }, TagsTestUtil.TagContextToList(result)); } @@ -255,7 +255,7 @@ public void GetCurrentTagContext_SkipNullTag() private ITagContext GetResultOfGetCurrentTagContext(ITagContext tagsToSet) { - ITagContext orig = AsyncLocalContext.CurrentTagContext; + var orig = AsyncLocalContext.CurrentTagContext; AsyncLocalContext.CurrentTagContext = tagsToSet; // Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagsToSet).attach(); try @@ -272,7 +272,7 @@ private ITagContext GetResultOfGetCurrentTagContext(ITagContext tagsToSet) public void WithTagContext_ConvertUnknownTagContextToTagContext() { ITagContext unknownTagContext = new SimpleTagContext(TAG1, TAG2, TAG3); - ITagContext result = GetResultOfWithTagContext(unknownTagContext); + var result = GetResultOfWithTagContext(unknownTagContext); Assert.IsType(result); Assert.Equal(new List() { TAG1, TAG2, TAG3 }, TagsTestUtil.TagContextToList(result)); } @@ -280,10 +280,10 @@ public void WithTagContext_ConvertUnknownTagContextToTagContext() [Fact] public void WithTagContext_RemoveDuplicatesFromUnknownTagContext() { - Tag tag1 = Tag.Create(K1, V1); - Tag tag2 = Tag.Create(K1, V2); + var tag1 = Tag.Create(K1, V1); + var tag2 = Tag.Create(K1, V2); ITagContext tagContextWithDuplicateTags = new SimpleTagContext(tag1, tag2); - ITagContext result = GetResultOfWithTagContext(tagContextWithDuplicateTags); + var result = GetResultOfWithTagContext(tagContextWithDuplicateTags); Assert.Equal(new List() { tag2 }, TagsTestUtil.TagContextToList(result)); } @@ -291,7 +291,7 @@ public void WithTagContext_RemoveDuplicatesFromUnknownTagContext() public void WithTagContext_SkipNullTag() { ITagContext tagContextWithNullTag = new SimpleTagContext(TAG1, null, TAG2); - ITagContext result = GetResultOfWithTagContext(tagContextWithNullTag); + var result = GetResultOfWithTagContext(tagContextWithNullTag); Assert.Equal(new List() { TAG1, TAG2 }, TagsTestUtil.TagContextToList(result)); } @@ -321,7 +321,7 @@ public void WithTagContext_SkipNullTag() private ITagContext GetResultOfWithTagContext(ITagContext tagsToSet) { - IScope scope = tagger.WithTagContext(tagsToSet); + var scope = tagger.WithTagContext(tagsToSet); try { return AsyncLocalContext.CurrentTagContext; diff --git a/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs index 6f4e85cde43..ab28fce1566 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs @@ -24,7 +24,7 @@ public class AttributeValueTest [Fact] public void StringAttributeValue() { - IAttributeValue attribute = AttributeValue.Create("MyStringAttributeValue"); + var attribute = AttributeValue.Create("MyStringAttributeValue"); attribute.Apply((stringValue) => { Assert.Equal("MyStringAttributeValue", stringValue); @@ -35,7 +35,7 @@ public void StringAttributeValue() [Fact] public void BooleanAttributeValue() { - IAttributeValue attribute = AttributeValue.Create(true); + var attribute = AttributeValue.Create(true); attribute.Apply((boolValue) => { Assert.True(boolValue); @@ -46,7 +46,7 @@ public void BooleanAttributeValue() [Fact] public void LongAttributeValue() { - IAttributeValue attribute = AttributeValue.Create(123456L); + var attribute = AttributeValue.Create(123456L); attribute.Apply((longValue) => { Assert.Equal(123456L, longValue); @@ -68,11 +68,11 @@ public void DoubleAttributeValue() [Fact] public void AttributeValue_ToString() { - IAttributeValue attribute = AttributeValue.Create("MyStringAttributeValue"); + var attribute = AttributeValue.Create("MyStringAttributeValue"); Assert.Contains("MyStringAttributeValue", attribute.ToString()); - IAttributeValue attribute2 = AttributeValue.Create(true); + var attribute2 = AttributeValue.Create(true); Assert.Contains("True", attribute2.ToString()); - IAttributeValue attribute3 = AttributeValue.Create(123456L); + var attribute3 = AttributeValue.Create(123456L); Assert.Contains("123456", attribute3.ToString()); } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs index 88caa913015..b64b4fa00cf 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs @@ -32,7 +32,7 @@ public void ActiveTraceParams_NoOpImplementation() [Fact] public void UpdateActiveTraceParams_NoOpImplementation() { - TraceParams traceParams = + var traceParams = TraceParams.Default .ToBuilder() .SetSampler(Samplers.AlwaysSample) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigTest.cs index d765e1ea97f..7ec9e0a555f 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigTest.cs @@ -32,7 +32,7 @@ public void DefaultActiveTraceParams() [Fact] public void UpdateTraceParams() { - TraceParams traceParams = + var traceParams = TraceParams.Default .ToBuilder() .SetSampler(Samplers.AlwaysSample) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceParamsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceParamsTest.cs index 19d0a88f916..8f95f0913be 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceParamsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceParamsTest.cs @@ -67,7 +67,7 @@ public void updateTraceParams_NonPositiveMaxNumberOfLinks() [Fact] public void UpdateTraceParams_All() { - TraceParams traceParams = + var traceParams = TraceParams.Default .ToBuilder() .SetSampler(Samplers.AlwaysSample) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index 990fbcf2eee..8fa4ab493c5 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -53,7 +53,7 @@ public void CurrentSpan_WhenNoContext() public void WithSpan_CloseDetaches() { Assert.Null(CurrentSpanUtils.CurrentSpan); - IScope ws = CurrentSpanUtils.WithSpan(span, false); + var ws = CurrentSpanUtils.WithSpan(span, false); try { Assert.Same(span, CurrentSpanUtils.CurrentSpan); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs index bf41f31c3fd..065f9bd1b6f 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs @@ -30,14 +30,14 @@ public void EndSpanOptions_DefaultOptions() [Fact] public void SetStatus_Ok() { - EndSpanOptions endSpanOptions = EndSpanOptions.Builder().SetStatus(Status.Ok).Build(); + var endSpanOptions = EndSpanOptions.Builder().SetStatus(Status.Ok).Build(); Assert.Equal(Status.Ok, endSpanOptions.Status); } [Fact] public void SetStatus_Error() { - EndSpanOptions endSpanOptions = + var endSpanOptions = EndSpanOptions.Builder() .SetStatus(Status.Cancelled.WithDescription("ThisIsAnError")) .Build(); @@ -47,7 +47,7 @@ public void SetStatus_Error() [Fact] public void SetSampleToLocalSpanStore() { - EndSpanOptions endSpanOptions = + var endSpanOptions = EndSpanOptions.Builder().SetSampleToLocalSpanStore(true).Build(); Assert.True(endSpanOptions.SampleToLocalSpanStore); } @@ -70,7 +70,7 @@ public void EndSpanOptions_EqualsAndHashCode() [Fact] public void EndSpanOptions_ToString() { - EndSpanOptions endSpanOptions = + var endSpanOptions = EndSpanOptions.Builder() .SetStatus(Status.Cancelled.WithDescription("ThisIsAnError")) .Build(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs index 26b07364ae8..9d2b4dfe0eb 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs @@ -32,7 +32,7 @@ public void FromDescription_NullDescription() [Fact] public void FromDescription() { - IEvent @event = Event.Create("MyEventText"); + var @event = Event.Create("MyEventText"); Assert.Equal("MyEventText", @event.Name); Assert.Equal(0, @event.Attributes.Count); } @@ -52,10 +52,10 @@ public void FromDescriptionAndAttributes_NullAttributes() [Fact] public void FromDescriptionAndAttributes() { - Dictionary attributes = new Dictionary(); + var attributes = new Dictionary(); attributes.Add( "MyStringAttributeKey", AttributeValue.Create("MyStringAttributeValue")); - IEvent @event = Event.Create("MyEventText", attributes); + var @event = Event.Create("MyEventText", attributes); Assert.Equal("MyEventText", @event.Name); Assert.Equal(attributes, @event.Attributes); } @@ -63,7 +63,7 @@ public void FromDescriptionAndAttributes() [Fact] public void FromDescriptionAndAttributes_EmptyAttributes() { - IEvent @event = + var @event = Event.Create( "MyEventText", new Dictionary()); Assert.Equal("MyEventText", @event.Name); @@ -92,9 +92,9 @@ public void Event_EqualsAndHashCode() [Fact] public void Event_ToString() { - IEvent @event = Event.Create("MyEventText"); + var @event = Event.Create("MyEventText"); Assert.Contains("MyEventText", @event.ToString()); - Dictionary attributes = new Dictionary(); + var attributes = new Dictionary(); attributes.Add( "MyStringAttributeKey", AttributeValue.Create("MyStringAttributeValue")); @event = Event.Create("MyEventText2", attributes); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs index d4ca0c9e92d..ffd064388ff 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs @@ -40,7 +40,7 @@ public InProcessRunningSpanStoreTest() private ISpan CreateSpan(string spanName) { - SpanContext spanContext = + var spanContext = SpanContext.Create( TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), @@ -59,8 +59,8 @@ private ISpan CreateSpan(string spanName) [Fact] public void GetSummary_SpansWithDifferentNames() { - ISpan span1 = CreateSpan(SPAN_NAME_1); - ISpan span2 = CreateSpan(SPAN_NAME_2); + var span1 = CreateSpan(SPAN_NAME_1); + var span2 = CreateSpan(SPAN_NAME_2); Assert.Equal(2, activeSpansExporter.Summary.PerSpanNameSummary.Count); Assert.Equal(1, activeSpansExporter @@ -87,9 +87,9 @@ public void GetSummary_SpansWithDifferentNames() [Fact] public void GetSummary_SpansWithSameName() { - ISpan span1 = CreateSpan(SPAN_NAME_1); - ISpan span2 = CreateSpan(SPAN_NAME_1); - ISpan span3 = CreateSpan(SPAN_NAME_1); + var span1 = CreateSpan(SPAN_NAME_1); + var span2 = CreateSpan(SPAN_NAME_1); + var span3 = CreateSpan(SPAN_NAME_1); Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); Assert.Equal(3, activeSpansExporter @@ -117,8 +117,8 @@ public void GetSummary_SpansWithSameName() [Fact] public void GetActiveSpans_SpansWithDifferentNames() { - Span span1 = CreateSpan(SPAN_NAME_1) as Span; - Span span2 = CreateSpan(SPAN_NAME_2) as Span; + var span1 = CreateSpan(SPAN_NAME_1) as Span; + var span2 = CreateSpan(SPAN_NAME_2) as Span; Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SPAN_NAME_1, 0))); Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SPAN_NAME_1, 2))); Assert.Contains(span2.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SPAN_NAME_2, 0))); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs index 84da9bdb323..b74c906a072 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs @@ -64,9 +64,9 @@ public InProcessSampledSpanStoreTest() public void AddSpansWithRegisteredNamesInAllLatencyBuckets() { AddSpanNameToAllLatencyBuckets(REGISTERED_SPAN_NAME); - IDictionary perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; + var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); - IDictionary latencyBucketsSummaries = perSpanNameSummary[REGISTERED_SPAN_NAME].NumbersOfLatencySampledSpans; + var latencyBucketsSummaries = perSpanNameSummary[REGISTERED_SPAN_NAME].NumbersOfLatencySampledSpans; Assert.Equal(LatencyBucketBoundaries.Values.Count, latencyBucketsSummaries.Count); foreach (var it in latencyBucketsSummaries) { @@ -78,7 +78,7 @@ public void AddSpansWithRegisteredNamesInAllLatencyBuckets() public void AddSpansWithoutRegisteredNamesInAllLatencyBuckets() { AddSpanNameToAllLatencyBuckets(NOT_REGISTERED_SPAN_NAME); - IDictionary perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; + var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); Assert.False(perSpanNameSummary.ContainsKey(NOT_REGISTERED_SPAN_NAME)); } @@ -119,9 +119,9 @@ public void RegisterSpanNamesViaSpanBuilderOption() public void AddSpansWithRegisteredNamesInAllErrorBuckets() { AddSpanNameToAllErrorBuckets(REGISTERED_SPAN_NAME); - IDictionary perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; + var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); - IDictionary errorBucketsSummaries = perSpanNameSummary[REGISTERED_SPAN_NAME].NumbersOfErrorSampledSpans; + var errorBucketsSummaries = perSpanNameSummary[REGISTERED_SPAN_NAME].NumbersOfErrorSampledSpans; var ccCount = Enum.GetValues(typeof(CanonicalCode)).Cast().Count(); Assert.Equal(ccCount - 1, errorBucketsSummaries.Count); foreach (var it in errorBucketsSummaries) @@ -134,7 +134,7 @@ public void AddSpansWithRegisteredNamesInAllErrorBuckets() public void AddSpansWithoutRegisteredNamesInAllErrorBuckets() { AddSpanNameToAllErrorBuckets(NOT_REGISTERED_SPAN_NAME); - IDictionary perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; + var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); Assert.False(perSpanNameSummary.ContainsKey(NOT_REGISTERED_SPAN_NAME)); } @@ -142,7 +142,7 @@ public void AddSpansWithoutRegisteredNamesInAllErrorBuckets() [Fact] public void GetErrorSampledSpans() { - Span span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); var samples = @@ -155,12 +155,12 @@ public void GetErrorSampledSpans() [Fact] public void GetErrorSampledSpans_MaxSpansToReturn() { - Span span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span1.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); - Span span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span2.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); var samples = @@ -174,10 +174,10 @@ public void GetErrorSampledSpans_MaxSpansToReturn() [Fact] public void GetErrorSampledSpans_NullCode() { - Span span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span1.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); - Span span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span2.End(EndSpanOptions.Builder().SetStatus(Status.Unknown).Build()); var samples = @@ -190,10 +190,10 @@ public void GetErrorSampledSpans_NullCode() [Fact] public void GetErrorSampledSpans_NullCode_MaxSpansToReturn() { - Span span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span1.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); - Span span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); span2.End(EndSpanOptions.Builder().SetStatus(Status.Unknown).Build()); var samples = @@ -205,7 +205,7 @@ public void GetErrorSampledSpans_NullCode_MaxSpansToReturn() [Fact] public void GetLatencySampledSpans() { - Span span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = @@ -222,7 +222,7 @@ public void GetLatencySampledSpans() [Fact] public void GetLatencySampledSpans_ExclusiveUpperBound() { - Span span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = @@ -238,7 +238,7 @@ public void GetLatencySampledSpans_ExclusiveUpperBound() [Fact] public void GetLatencySampledSpans_InclusiveLowerBound() { - Span span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = @@ -255,12 +255,12 @@ public void GetLatencySampledSpans_InclusiveLowerBound() [Fact] public void GetLatencySampledSpans_QueryBetweenMultipleBuckets() { - Span span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span1.End(); // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); - Span span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(2000); // 200 microseconds span2.End(); var samples = @@ -278,12 +278,12 @@ public void GetLatencySampledSpans_QueryBetweenMultipleBuckets() [Fact] public void GetLatencySampledSpans_MaxSpansToReturn() { - Span span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span1.End(); // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); - Span span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(2000); // 200 microseconds span2.End(); var samples = @@ -300,7 +300,7 @@ public void GetLatencySampledSpans_MaxSpansToReturn() [Fact] public void IgnoreNegativeSpanLatency() { - Span span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval -= TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = @@ -349,7 +349,7 @@ private void AddSpanNameToAllLatencyBuckets(string spanName) private void AddSpanNameToAllErrorBuckets(String spanName) { - foreach (CanonicalCode code in Enum.GetValues(typeof(CanonicalCode)).Cast()) + foreach (var code in Enum.GetValues(typeof(CanonicalCode)).Cast()) { if (code != CanonicalCode.Ok) { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs index 7625633c711..dc419b1fa56 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs @@ -27,7 +27,7 @@ public class NoopRunningSpanStoreTest [Fact] public void NoopRunningSpanStore_GetSummary() { - IRunningSpanStoreSummary summary = runningSpanStore.Summary; + var summary = runningSpanStore.Summary; Assert.Empty(summary.PerSpanNameSummary); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs index 47d813d7b45..f09b089503c 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs @@ -30,9 +30,9 @@ public class NoopSampledSpanStoreTest public void NoopSampledSpanStore_RegisterUnregisterAndGetSummary() { // should return empty before register - ISampledSpanStore sampledSpanStore = + var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; - ISampledSpanStoreSummary summary = sampledSpanStore.Summary; + var summary = sampledSpanStore.Summary; Assert.Empty(summary.PerSpanNameSummary); // should return non-empty summaries with zero latency/error sampled spans after register @@ -60,7 +60,7 @@ public void NoopSampledSpanStore_RegisterUnregisterAndGetSummary() [Fact] public void NoopSampledSpanStore_GetLatencySampledSpans() { - ISampledSpanStore sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; + var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; var latencySampledSpans = sampledSpanStore.GetLatencySampledSpans( SampledSpanStoreLatencyFilter.Create("TestLatencyFilter", TimeSpan.Zero, TimeSpan.Zero, 0)); @@ -70,7 +70,7 @@ public void NoopSampledSpanStore_GetLatencySampledSpans() [Fact] public void NoopSampledSpanStore_GetErrorSampledSpans() { - ISampledSpanStore sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; + var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; var errorSampledSpans = sampledSpanStore.GetErrorSampledSpans( SampledSpanStoreErrorFilter.Create("TestErrorFilter", null, 0)); @@ -80,9 +80,9 @@ public void NoopSampledSpanStore_GetErrorSampledSpans() [Fact] public void NoopSampledSpanStore_GetRegisteredSpanNamesForCollection() { - ISampledSpanStore sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; + var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; sampledSpanStore.RegisterSpanNamesForCollection(new List() { "TestSpan3", "TestSpan4" }); - ISet registeredSpanNames = sampledSpanStore.RegisteredSpanNamesForCollection; + var registeredSpanNames = sampledSpanStore.RegisteredSpanNamesForCollection; Assert.Equal(2, registeredSpanNames.Count); Assert.Contains(registeredSpanNames, (item) => { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index 2649917ee8e..de17ce9eb76 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -67,7 +67,7 @@ public SpanDataTest() [Fact] public void SpanData_AllValues() { - SpanData spanData = + var spanData = SpanData.Create( spanContext, parentSpanId, @@ -97,7 +97,7 @@ public void SpanData_AllValues() [Fact] public void SpanData_RootActiveSpan() { - SpanData spanData = + var spanData = SpanData.Create( spanContext, null, @@ -127,7 +127,7 @@ public void SpanData_RootActiveSpan() [Fact] public void SpanData_AllDataEmpty() { - SpanData spanData = + var spanData = SpanData.Create( spanContext, parentSpanId, @@ -158,7 +158,7 @@ public void SpanData_AllDataEmpty() [Fact] public void SpanDataEquals() { - SpanData allSpanData1 = + var allSpanData1 = SpanData.Create( spanContext, parentSpanId, @@ -172,7 +172,7 @@ public void SpanDataEquals() status, SPAN_KIND, endTimestamp); - SpanData allSpanData2 = + var allSpanData2 = SpanData.Create( spanContext, parentSpanId, @@ -186,7 +186,7 @@ public void SpanDataEquals() status, SPAN_KIND, endTimestamp); - SpanData emptySpanData = + var emptySpanData = SpanData.Create( spanContext, parentSpanId, @@ -210,7 +210,7 @@ public void SpanDataEquals() [Fact] public void SpanData_ToString() { - string spanDataString = + var spanDataString = SpanData.Create( spanContext, parentSpanId, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index c5987d01ea8..aae2cccb870 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -55,7 +55,7 @@ public SpanExporterTest() private Span CreateSampledEndedSpan(string spanName) { - ISpan span = + var span = Span.StartSpan( sampledSpanContext, recordSpanOptions, @@ -71,7 +71,7 @@ private Span CreateSampledEndedSpan(string spanName) private Span CreateNotSampledEndedSpan(string spanName) { - ISpan span = + var span = Span.StartSpan( notSampledSpanContext, recordSpanOptions, @@ -88,8 +88,8 @@ private Span CreateNotSampledEndedSpan(string spanName) [Fact] public void ExportDifferentSampledSpans() { - Span span1 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span2 = CreateSampledEndedSpan(SPAN_NAME_2); + var span1 = CreateSampledEndedSpan(SPAN_NAME_1); + var span2 = CreateSampledEndedSpan(SPAN_NAME_2); var exported = serviceHandler.WaitForExport(2); Assert.Equal(2, exported.Count()); Assert.Contains(span1.ToSpanData(), exported); @@ -99,12 +99,12 @@ public void ExportDifferentSampledSpans() [Fact] public void ExportMoreSpansThanTheBufferSize() { - Span span1 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span2 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span3 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span4 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span5 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span6 = CreateSampledEndedSpan(SPAN_NAME_1); + var span1 = CreateSampledEndedSpan(SPAN_NAME_1); + var span2 = CreateSampledEndedSpan(SPAN_NAME_1); + var span3 = CreateSampledEndedSpan(SPAN_NAME_1); + var span4 = CreateSampledEndedSpan(SPAN_NAME_1); + var span5 = CreateSampledEndedSpan(SPAN_NAME_1); + var span6 = CreateSampledEndedSpan(SPAN_NAME_1); var exported = serviceHandler.WaitForExport(6); Assert.Equal(6, exported.Count()); Assert.Contains(span1.ToSpanData(), exported); @@ -120,7 +120,7 @@ public void ExportMoreSpansThanTheBufferSize() public void InterruptWorkerThreadStops() { - Thread serviceExporterThread = ((SpanExporter)spanExporter).ServiceExporterThread; + var serviceExporterThread = ((SpanExporter)spanExporter).ServiceExporterThread; spanExporter.Dispose(); // serviceExporterThread.Interrupt(); // Test that the worker thread will stop. @@ -136,13 +136,13 @@ public void ServiceHandlerThrowsException() // .when(mockServiceHandler) // .export(anyListOf(SpanData)); spanExporter.RegisterHandler("mock.service", mockServiceHandler); - Span span1 = CreateSampledEndedSpan(SPAN_NAME_1); + var span1 = CreateSampledEndedSpan(SPAN_NAME_1); var exported = serviceHandler.WaitForExport(1); Assert.Single(exported); Assert.Contains(span1.ToSpanData(), exported); // assertThat(exported).containsExactly(span1.toSpanData()); // Continue to export after the exception was received. - Span span2 = CreateSampledEndedSpan(SPAN_NAME_1); + var span2 = CreateSampledEndedSpan(SPAN_NAME_1); exported = serviceHandler.WaitForExport(1); Assert.Single(exported); Assert.Contains(span2.ToSpanData(), exported); @@ -152,10 +152,10 @@ public void ServiceHandlerThrowsException() [Fact] public void ExportSpansToMultipleServices() { - TestHandler serviceHandler2 = new TestHandler(); + var serviceHandler2 = new TestHandler(); spanExporter.RegisterHandler("test.service2", serviceHandler2); - Span span1 = CreateSampledEndedSpan(SPAN_NAME_1); - Span span2 = CreateSampledEndedSpan(SPAN_NAME_2); + var span1 = CreateSampledEndedSpan(SPAN_NAME_1); + var span2 = CreateSampledEndedSpan(SPAN_NAME_2); var exported1 = serviceHandler.WaitForExport(2); var exported2 = serviceHandler2.WaitForExport(2); Assert.Equal(2, exported1.Count()); @@ -169,8 +169,8 @@ public void ExportSpansToMultipleServices() [Fact] public void ExportNotSampledSpans() { - Span span1 = CreateNotSampledEndedSpan(SPAN_NAME_1); - Span span2 = CreateSampledEndedSpan(SPAN_NAME_2); + var span1 = CreateNotSampledEndedSpan(SPAN_NAME_1); + var span2 = CreateSampledEndedSpan(SPAN_NAME_2); // Spans are recorded and exported in the same order as they are ended, we test that a non // sampled span is not exported by creating and ending a sampled span after a non sampled span // and checking that the first exported span is the sampled span (the non sampled did not get diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs index bf6a8bd1d51..2a401705bd5 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs @@ -34,7 +34,7 @@ public void EmptyList() [Fact] public void AddRemoveAdd_SameElement() { - FakeElement element = new FakeElement(); + var element = new FakeElement(); intrusiveList.AddElement(element); Assert.Equal(1, intrusiveList.Count); intrusiveList.RemoveElement(element); @@ -46,9 +46,9 @@ public void AddRemoveAdd_SameElement() [Fact] public void addAndRemoveElements() { - FakeElement element1 = new FakeElement(); - FakeElement element2 = new FakeElement(); - FakeElement element3 = new FakeElement(); + var element1 = new FakeElement(); + var element2 = new FakeElement(); + var element3 = new FakeElement(); intrusiveList.AddElement(element1); intrusiveList.AddElement(element2); intrusiveList.AddElement(element3); @@ -88,7 +88,7 @@ public void addAndRemoveElements() [Fact] public void AddAlreadyAddedElement() { - FakeElement element = new FakeElement(); + var element = new FakeElement(); intrusiveList.AddElement(element); Assert.Throws(() => intrusiveList.AddElement(element)); @@ -97,7 +97,7 @@ public void AddAlreadyAddedElement() [Fact] public void removeNotAddedElement() { - FakeElement element = new FakeElement(); + var element = new FakeElement(); Assert.Throws(() => intrusiveList.RemoveElement(element)); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index f35a7ad2732..159542b41f0 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -40,7 +40,7 @@ public LinkTest() [Fact] public void FromSpanContext_ChildLink() { - ILink link = Link.FromSpanContext(spanContext); + var link = Link.FromSpanContext(spanContext); Assert.Equal(spanContext.TraceId, link.Context.TraceId); Assert.Equal(spanContext.SpanId, link.Context.SpanId); } @@ -48,7 +48,7 @@ public void FromSpanContext_ChildLink() [Fact] public void FromSpanContext_ChildLink_WithAttributes() { - ILink link = Link.FromSpanContext(spanContext, attributesMap); + var link = Link.FromSpanContext(spanContext, attributesMap); Assert.Equal(spanContext.TraceId, link.Context.TraceId); Assert.Equal(spanContext.SpanId, link.Context.SpanId); Assert.Equal(attributesMap, link.Attributes); @@ -57,7 +57,7 @@ public void FromSpanContext_ChildLink_WithAttributes() [Fact] public void FromSpanContext_ParentLink() { - ILink link = Link.FromSpanContext(spanContext); + var link = Link.FromSpanContext(spanContext); Assert.Equal(spanContext.TraceId, link.Context.TraceId); Assert.Equal(spanContext.SpanId, link.Context.SpanId); } @@ -65,7 +65,7 @@ public void FromSpanContext_ParentLink() [Fact] public void FromSpanContext_ParentLink_WithAttributes() { - ILink link = Link.FromSpanContext(spanContext, attributesMap); + var link = Link.FromSpanContext(spanContext, attributesMap); Assert.Equal(spanContext.TraceId, link.Context.TraceId); Assert.Equal(spanContext.SpanId, link.Context.SpanId); Assert.Equal(attributesMap, link.Attributes); @@ -95,7 +95,7 @@ public void Link_EqualsAndHashCode() [Fact] public void Link_ToString() { - ILink link = Link.FromSpanContext(spanContext, attributesMap); + var link = Link.FromSpanContext(spanContext, attributesMap); Assert.Contains(spanContext.TraceId.ToString(), link.ToString()); Assert.Contains(spanContext.SpanId.ToString(), link.ToString()); Assert.Contains(Collections.ToString(attributesMap), link.ToString()); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs index f770dc1f97a..18beaacaa79 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs @@ -36,7 +36,7 @@ public class B3FormatTest private static readonly Action, string, string> setter = (d, k, v) => d[k] = v; - private static readonly Func, string, IEnumerable> getter = (d, k) => { d.TryGetValue(k, out string v); return new string[] { v }; }; + private static readonly Func, string, IEnumerable> getter = (d, k) => { d.TryGetValue(k, out var v); return new string[] { v }; }; ITestOutputHelper _output; public B3FormatTest(ITestOutputHelper output) @@ -69,7 +69,7 @@ public void ParseMissingSampledAndMissingFlag() IDictionary headersNotSampled = new Dictionary(); headersNotSampled.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); headersNotSampled.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); - SpanContext spanContext = SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty); + var spanContext = SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty); Assert.Equal(spanContext, b3Format.Extract(headersNotSampled, getter)); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs index 87d7dff03d2..1f9989988bc 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs @@ -38,7 +38,7 @@ public class BinaryFormatTest private void TestSpanContextConversion(SpanContext spanContext) { - SpanContext propagatedBinarySpanContext = binaryFormat.FromByteArray(binaryFormat.ToByteArray(spanContext)); + var propagatedBinarySpanContext = binaryFormat.FromByteArray(binaryFormat.ToByteArray(spanContext)); Assert.Equal(spanContext, propagatedBinarySpanContext); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/SpanContextParseExceptionTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/SpanContextParseExceptionTest.cs index fa87c1b9acb..323eaa3e4ed 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/SpanContextParseExceptionTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/SpanContextParseExceptionTest.cs @@ -30,8 +30,8 @@ public void CreateWithMessage() [Fact] public void createWithMessageAndCause() { - Exception cause = new Exception(); - SpanContextParseException parseException = new SpanContextParseException("my message", cause); + var cause = new Exception(); + var parseException = new SpanContextParseException("my message", cause); Assert.Equal("my message", parseException.Message); Assert.Equal(cause, parseException.InnerException); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs index 8fbac4046b8..4fd3835291b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs @@ -27,7 +27,7 @@ public class TraceContextTest [Fact] public void TraceContextFormatCanParseExampleFromSpec() { - Dictionary headers = new Dictionary() + var headers = new Dictionary() { { "traceparent", "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01" }, { "tracestate", "congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4,rojo=00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01" }, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs index 8401b3d7fbc..417ef6ffd3b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs @@ -184,7 +184,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() ISampler defaultProbability = ProbabilitySampler.Create(0.0001); // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; - TraceId notSampledtraceId = + var notSampledtraceId = TraceId.FromBytes( new byte[] { @@ -214,7 +214,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() new List())); // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long // is less than probability * Long.MAX_VALUE; - TraceId sampledtraceId = + var sampledtraceId = TraceId.FromBytes( new byte[] { @@ -261,9 +261,9 @@ public void ProbabilitySampler_ToString() private static void AssertSamplerSamplesWithProbability( ISampler sampler, SpanContext parent, IEnumerable parentLinks, double probability) { - RandomGenerator random = new RandomGenerator(1234); - int count = 0; // Count of spans with sampling enabled - for (int i = 0; i < NUM_SAMPLE_TRIES; i++) + var random = new RandomGenerator(1234); + var count = 0; // Count of spans with sampling enabled + for (var i = 0; i < NUM_SAMPLE_TRIES; i++) { if (sampler.ShouldSample( parent, @@ -275,7 +275,7 @@ private static void AssertSamplerSamplesWithProbability( count++; } } - double proportionSampled = (double)count / NUM_SAMPLE_TRIES; + var proportionSampled = (double)count / NUM_SAMPLE_TRIES; // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. Assert.True(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs index 425ff3cbc53..26013874883 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs @@ -71,7 +71,7 @@ public void GetContextAndOptions() public void PutAttributeCallsAddAttributeByDefault() { var mockSpan = new Mock(spanContext, spanOptions) { CallBase = true }; - TestSpan span = mockSpan.Object; + var span = mockSpan.Object; IAttributeValue val = AttributeValue.Create(true); span.SetAttribute("MyKey", val); span.End(); @@ -90,10 +90,10 @@ public void EndCallsEndWithDefaultOptions() [Fact] public void AddEventDefaultImplementation() { - Mock mockSpan = new Mock(); + var mockSpan = new Mock(); var span = mockSpan.Object; - IEvent @event = Event.Create("MyEvent"); + var @event = Event.Create("MyEvent"); span.AddEvent(@event); mockSpan.Verify((s) => s.AddEvent(@event)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs index ca7052b7ddb..dbf3b6ce9c3 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs @@ -37,7 +37,7 @@ public SpanBuilderBaseTest() public void StartScopedSpan() { Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - IScope scope = spanBuilder.Object.StartScopedSpan(); + var scope = spanBuilder.Object.StartScopedSpan(); try { Assert.Same(span.Object, tracer.CurrentSpan); @@ -55,7 +55,7 @@ public void StartScopedSpan_WithParam() { Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - IScope scope = spanBuilder.Object.StartScopedSpan(out ISpan outSpan); + var scope = spanBuilder.Object.StartScopedSpan(out var outSpan); try { Assert.Same(outSpan, tracer.CurrentSpan); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 49c94f844d5..4682a8d573e 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -52,7 +52,7 @@ public void StartSpanNullParent() Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.True(span.Context.TraceOptions.IsSampled); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Null(spanData.ParentSpanId); Assert.InRange(spanData.StartTimestamp, Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(-1, 0)), Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(1, 0))); Assert.Equal(SPAN_NAME, spanData.Name); @@ -69,7 +69,7 @@ public void StartSpanNullParentWithRecordEvents() Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.False(span.Context.TraceOptions.IsSampled); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Null(spanData.ParentSpanId); } @@ -93,7 +93,7 @@ public void StartChildSpan() Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.IsRecordingEvents); Assert.True(rootSpan.Context.TraceOptions.IsSampled); - ISpan childSpan = + var childSpan = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan, spanBuilderOptions).StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); @@ -109,39 +109,39 @@ public void StartSpan_NullParent() Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.True(span.Context.TraceOptions.IsSampled); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Null(spanData.ParentSpanId); } [Fact] public void StartSpanInvalidParent() { - ISpan span = + var span = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, SpanContext.Blank, spanBuilderOptions) .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.True(span.Context.TraceOptions.IsSampled); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Null(spanData.ParentSpanId); } [Fact] public void StartRemoteSpan() { - SpanContext spanContext = + var spanContext = SpanContext.Create( TraceId.GenerateRandomId(randomHandler), SpanId.GenerateRandomId(randomHandler), TraceOptions.Default, Tracestate.Empty); - ISpan span = + var span = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, spanContext, spanBuilderOptions) .SetRecordEvents(true) .StartSpan(); Assert.True(span.Context.IsValid); Assert.Equal(spanContext.TraceId, span.Context.TraceId); Assert.False(span.Context.TraceOptions.IsSampled); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext.SpanId, spanData.ParentSpanId); } @@ -177,7 +177,7 @@ public void StartRemoteChildSpan_WithSpecifiedSampler() Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.Context.TraceOptions.IsSampled); // Apply given sampler before default sampler for spans with remote parent. - ISpan childSpan = + var childSpan = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan.Context, spanBuilderOptions) .SetSampler(Samplers.NeverSample) .StartSpan(); @@ -196,7 +196,7 @@ public void StartRemoteChildSpan_WithoutSpecifiedSampler() Assert.True(rootSpan.Context.IsValid); Assert.False(rootSpan.Context.TraceOptions.IsSampled); // Apply default sampler (always true in the tests) for spans with remote parent. - ISpan childSpan = + var childSpan = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan.Context, spanBuilderOptions) .StartSpan(); Assert.True(childSpan.Context.IsValid); @@ -214,7 +214,7 @@ public void StartChildSpan_WithSpecifiedSampler() Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.Context.TraceOptions.IsSampled); // Apply the given sampler for child spans. - ISpan childSpan = + var childSpan = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan, spanBuilderOptions) .SetSampler(Samplers.NeverSample) .StartSpan(); @@ -233,7 +233,7 @@ public void StartChildSpan_WithoutSpecifiedSampler() Assert.True(rootSpan.Context.IsValid); Assert.False(rootSpan.Context.TraceOptions.IsSampled); // Don't apply the default sampler (always true) for child spans. - ISpan childSpan = + var childSpan = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan, spanBuilderOptions).StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); @@ -254,7 +254,7 @@ public void StartChildSpan_SampledLinkedParent() .StartSpan(); Assert.True(rootSpanSampled.Context.TraceOptions.IsSampled); // Sampled because the linked parent is sampled. - ISpan childSpan = + var childSpan = SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpanUnsampled, spanBuilderOptions) .SetParentLinks(new List() { rootSpanSampled }) .StartSpan(); @@ -270,7 +270,7 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() configMock.Setup((c) => c.ActiveTraceParams).Returns(TraceParams.Default); // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; - TraceId traceId = + var traceId = TraceId.FromBytes( new byte[] { @@ -293,7 +293,7 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() }); // If parent is sampled then the remote child must be sampled. - ISpan childSpan = + var childSpan = SpanBuilder.Create( SPAN_NAME, SpanKind.Internal, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 2ae336cbd9f..8746bc91502 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -89,7 +89,7 @@ public void ToSpanData_NoRecordEvents() [Fact] public void NoEventsRecordedAfterEnd() { - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, @@ -112,7 +112,7 @@ public void NoEventsRecordedAfterEnd() span.AddEvent(Event.Create(EVENT_DESCRIPTION)); span.AddEvent(EVENT_DESCRIPTION, attributes); span.AddLink(Link.FromSpanContext(spanContext)); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(timestamp, spanData.StartTimestamp); Assert.Empty(spanData.Attributes.AttributeMap); Assert.Empty(spanData.Events.Events); @@ -124,7 +124,7 @@ public void NoEventsRecordedAfterEnd() [Fact] public void ToSpanData_ActiveSpan() { - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, @@ -149,9 +149,9 @@ public void ToSpanData_ActiveSpan() span.AddEvent(EVENT_DESCRIPTION, attributes); interval = TimeSpan.FromMilliseconds(300); interval = TimeSpan.FromMilliseconds(400); - ILink link = Link.FromSpanContext(spanContext); + var link = Link.FromSpanContext(spanContext); span.AddLink(link); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); Assert.Equal(SPAN_NAME, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); @@ -202,12 +202,12 @@ public void GoSpanData_EndedSpan() interval = TimeSpan.FromMilliseconds(200); span.AddEvent(EVENT_DESCRIPTION, attributes); interval = TimeSpan.FromMilliseconds(300); - ILink link = Link.FromSpanContext(spanContext); + var link = Link.FromSpanContext(spanContext); span.AddLink(link); interval = TimeSpan.FromMilliseconds(400); span.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); Assert.Equal(SPAN_NAME, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); @@ -285,10 +285,10 @@ public void status_ViaEndSpanOptions() [Fact] public void DroppingAttributes() { - int maxNumberOfAttributes = 8; - TraceParams traceParams = + var maxNumberOfAttributes = 8; + var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfAttributes(maxNumberOfAttributes).Build(); - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, @@ -298,7 +298,7 @@ public void DroppingAttributes() traceParams, startEndHandler, timestampConverter); - for (int i = 0; i < 2 * maxNumberOfAttributes; i++) + for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { IDictionary attributes = new Dictionary(); attributes.Add("MyStringAttributeKey" + i, AttributeValue.LongAttributeValue(i)); @@ -308,10 +308,10 @@ public void DroppingAttributes() } } - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); - for (int i = 0; i < maxNumberOfAttributes; i++) + for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), @@ -323,7 +323,7 @@ public void DroppingAttributes() spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); - for (int i = 0; i < maxNumberOfAttributes; i++) + for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), @@ -336,10 +336,10 @@ public void DroppingAttributes() [Fact] public void DroppingAndAddingAttributes() { - int maxNumberOfAttributes = 8; - TraceParams traceParams = + var maxNumberOfAttributes = 8; + var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfAttributes(maxNumberOfAttributes).Build(); - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, @@ -349,7 +349,7 @@ public void DroppingAndAddingAttributes() traceParams, startEndHandler, timestampConverter); - for (int i = 0; i < 2 * maxNumberOfAttributes; i++) + for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { IDictionary attributes = new Dictionary(); attributes.Add("MyStringAttributeKey" + i, AttributeValue.LongAttributeValue(i)); @@ -359,10 +359,10 @@ public void DroppingAndAddingAttributes() } } - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); - for (int i = 0; i < maxNumberOfAttributes; i++) + for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), @@ -370,7 +370,7 @@ public void DroppingAndAddingAttributes() .Attributes .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); } - for (int i = 0; i < maxNumberOfAttributes / 2; i++) + for (var i = 0; i < maxNumberOfAttributes / 2; i++) { IDictionary attributes = new Dictionary(); attributes.Add("MyStringAttributeKey" + i, AttributeValue.LongAttributeValue(i)); @@ -384,7 +384,7 @@ public void DroppingAndAddingAttributes() Assert.Equal(maxNumberOfAttributes * 3 / 2, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); // Test that we still have in the attributes map the latest maxNumberOfAttributes / 2 entries. - for (int i = 0; i < maxNumberOfAttributes / 2; i++) + for (var i = 0; i < maxNumberOfAttributes / 2; i++) { Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes * 3 / 2), @@ -393,7 +393,7 @@ public void DroppingAndAddingAttributes() .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2)]); } // Test that we have the newest re-added initial entries. - for (int i = 0; i < maxNumberOfAttributes / 2; i++) + for (var i = 0; i < maxNumberOfAttributes / 2; i++) { Assert.Equal(AttributeValue.LongAttributeValue(i), spanData.Attributes.AttributeMap["MyStringAttributeKey" + i]); } @@ -402,10 +402,10 @@ public void DroppingAndAddingAttributes() [Fact] public void DroppingEvents() { - int maxNumberOfEvents = 8; - TraceParams traceParams = + var maxNumberOfEvents = 8; + var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfEvents(maxNumberOfEvents).Build(); - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, @@ -415,14 +415,14 @@ public void DroppingEvents() traceParams, startEndHandler, timestampConverter); - IEvent testEvent = Event.Create(EVENT_DESCRIPTION); - int i = 0; + var testEvent = Event.Create(EVENT_DESCRIPTION); + var i = 0; for (i = 0; i < 2 * maxNumberOfEvents; i++) { span.AddEvent(testEvent); interval += TimeSpan.FromMilliseconds(100); } - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); Assert.Equal(maxNumberOfEvents, spanData.Events.Events.Count()); i = 0; @@ -448,10 +448,10 @@ public void DroppingEvents() [Fact] public void DroppingLinks() { - int maxNumberOfLinks = 8; - TraceParams traceParams = + var maxNumberOfLinks = 8; + var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfLinks(maxNumberOfLinks).Build(); - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, @@ -461,12 +461,12 @@ public void DroppingLinks() traceParams, startEndHandler, timestampConverter); - ILink link = Link.FromSpanContext(spanContext); - for (int i = 0; i < 2 * maxNumberOfLinks; i++) + var link = Link.FromSpanContext(spanContext); + for (var i = 0; i < 2 * maxNumberOfLinks; i++) { span.AddLink(link); } - SpanData spanData = ((Span)span).ToSpanData(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfLinks, spanData.Links.DroppedLinksCount); Assert.Equal(maxNumberOfLinks, spanData.Links.Links.Count()); foreach (var actualLink in spanData.Links.Links) @@ -499,7 +499,7 @@ public void SampleToLocalSpanStore() span.End(EndSpanOptions.Builder().SetSampleToLocalSpanStore(true).Build()); Assert.True(((Span)span).IsSampleToLocalSpanStore); - ISpan span2 = + var span2 = Span.StartSpan( spanContext, recordSpanOptions, @@ -523,7 +523,7 @@ public void SampleToLocalSpanStore() [Fact] public void SampleToLocalSpanStore_RunningSpan() { - ISpan span = + var span = Span.StartSpan( spanContext, recordSpanOptions, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/StatusTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/StatusTest.cs index 36c32a6d55a..b4de76e3516 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/StatusTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/StatusTest.cs @@ -31,7 +31,7 @@ public void Status_Ok() [Fact] public void CreateStatus_WithDescription() { - Status status = Status.Unknown.WithDescription("This is an error."); + var status = Status.Unknown.WithDescription("This is an error."); Assert.Equal(CanonicalCode.Unknown, status.CanonicalCode); Assert.Equal("This is an error.", status.Description); Assert.False(status.IsOk); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs index b9d0b44ae87..344519bad08 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs @@ -50,7 +50,7 @@ public void WithSpan_NullSpan() public void GetCurrentSpan_WithSpan() { Assert.Same(BlankSpan.Instance, noopTracer.CurrentSpan); - IScope ws = noopTracer.WithSpan(span); + var ws = noopTracer.WithSpan(span); try { Assert.Same(span, noopTracer.CurrentSpan); @@ -151,7 +151,7 @@ public void DefaultSpanBuilderWithParentContext() [Fact] public void StartSpanWithParentFromContext() { - IScope ws = tracer.WithSpan(span); + var ws = tracer.WithSpan(span); try { Assert.Same(span, tracer.CurrentSpan); @@ -167,7 +167,7 @@ public void StartSpanWithParentFromContext() [Fact] public void StartSpanWithInvalidParentFromContext() { - IScope ws = tracer.WithSpan(BlankSpan.Instance); + var ws = tracer.WithSpan(BlankSpan.Instance); try { Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index 0543f5a1a3a..1fab1dc6bf1 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -39,14 +39,14 @@ public TracerTest() [Fact] public void CreateSpanBuilder() { - ISpanBuilder spanBuilder = tracer.SpanBuilderWithParent(SPAN_NAME, parent: BlankSpan.Instance); + var spanBuilder = tracer.SpanBuilderWithParent(SPAN_NAME, parent: BlankSpan.Instance); Assert.IsType(spanBuilder); } [Fact] public void CreateSpanBuilderWithRemoteParet() { - ISpanBuilder spanBuilder = tracer.SpanBuilderWithParentContext(SPAN_NAME, parentContext: SpanContext.Blank); + var spanBuilder = tracer.SpanBuilderWithParentContext(SPAN_NAME, parentContext: SpanContext.Blank); Assert.IsType(spanBuilder); } } diff --git a/test/TestApp.AspNetCore.2.0/Controllers/ForwardController.cs b/test/TestApp.AspNetCore.2.0/Controllers/ForwardController.cs index 8437f61f934..7d0a7646a18 100644 --- a/test/TestApp.AspNetCore.2.0/Controllers/ForwardController.cs +++ b/test/TestApp.AspNetCore.2.0/Controllers/ForwardController.cs @@ -35,7 +35,7 @@ private async Task CallNextAsync(string url, Data[] arguments) { if (url != null) { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url) + var request = new HttpRequestMessage(HttpMethod.Post, url) { Content = new StringContent(JsonConvert.SerializeObject(arguments), Encoding.UTF8, "application/json"), }; From cfd233c9cae249891fa615a3bb6f74da44bd5423 Mon Sep 17 00:00:00 2001 From: Sergey Kanzhelev Date: Tue, 25 Jun 2019 22:47:56 -0700 Subject: [PATCH 04/41] moved Stats away to SDK (#121) --- ...enTelemetry.Exporter.ApplicationInsights.csproj | 2 +- .../OpenTelemetry.Exporter.Prometheus.csproj | 2 +- .../Implementation/MetricsConversions.cs | 6 +++--- .../Implementation/StackdriverTraceExporter.cs | 14 +++++++------- .../OpenTelemetry.Exporter.Stackdriver.csproj | 2 +- .../Stats/Aggregations/ICount.cs | 0 .../Stats/Aggregations/ICountData.cs | 0 .../Stats/Aggregations/IDistribution.cs | 0 .../Stats/Aggregations/IDistributionData.cs | 0 .../Stats/Aggregations/ILastValue.cs | 0 .../Stats/Aggregations/ILastValueDataDouble.cs | 0 .../Stats/Aggregations/ILastValueDataLong.cs | 0 .../Stats/Aggregations/IMean.cs | 0 .../Stats/Aggregations/IMeanData.cs | 0 .../Stats/Aggregations/ISum.cs | 0 .../Stats/Aggregations/ISumDataDouble.cs | 0 .../Stats/Aggregations/ISumDataLong.cs | 0 .../Stats/IAggregation.cs | 0 .../Stats/IAggregationData.cs | 0 .../Stats/IBucketBoundaries.cs | 0 .../Stats/IMeasure.cs | 0 .../Stats/IMeasureMap.cs | 0 .../Stats/IMeasurement.cs | 0 .../Stats/IStatsComponent.cs | 0 .../Stats/IStatsRecorder.cs | 0 .../Stats/IView.cs | 0 .../Stats/IViewData.cs | 0 .../Stats/IViewManager.cs | 0 .../Stats/IViewName.cs | 0 .../Stats/Measurements/IMeasurementDouble.cs | 0 .../Stats/Measurements/IMeasurementLong.cs | 0 .../Stats/Measures/IMeasureDouble.cs | 0 .../Stats/Measures/IMeasureLong.cs | 0 .../Stats/StatsCollectionState.cs | 0 34 files changed, 13 insertions(+), 13 deletions(-) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ICount.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ICountData.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/IDistribution.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/IDistributionData.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ILastValue.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ILastValueDataDouble.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ILastValueDataLong.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/IMean.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/IMeanData.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ISum.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ISumDataDouble.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Aggregations/ISumDataLong.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IAggregation.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IAggregationData.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IBucketBoundaries.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IMeasure.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IMeasureMap.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IMeasurement.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IStatsComponent.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IStatsRecorder.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IView.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IViewData.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IViewManager.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/IViewName.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Measurements/IMeasurementDouble.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Measurements/IMeasurementLong.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Measures/IMeasureDouble.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/Measures/IMeasureLong.cs (100%) rename src/{OpenTelemetry.Abstractions => OpenTelemetry}/Stats/StatsCollectionState.cs (100%) diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj b/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj index 7f2e40a6250..f56d57ee129 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj b/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj index 6a2006be075..5a86702073c 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj @@ -7,6 +7,6 @@ - + diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs index 73d5fccf460..5376b3f9ad7 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs @@ -89,12 +89,12 @@ public static LabelDescriptor ToLabelDescriptor(this TagKey tagKey) return labelDescriptor; } - public static Distribution CreateDistribution( + public static Google.Api.Distribution CreateDistribution( IDistributionData distributionData, IBucketBoundaries bucketBoundaries) { var bucketOptions = bucketBoundaries.ToBucketOptions(); - var distribution = new Distribution + var distribution = new Google.Api.Distribution { BucketOptions = bucketOptions, BucketCounts = { CreateBucketCounts(distributionData.BucketCounts) }, @@ -333,4 +333,4 @@ internal static string GetStackdriverLabelKey(string label) return label.Replace('/', '_'); } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs index 94c598b6b93..da6e0f85057 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs @@ -37,12 +37,12 @@ static class SpanExtensions /// Span in OpenTelemetry format /// Google Cloud Platform Project Id /// - public static Span ToSpan(this SpanData spanData, string projectId) + public static Google.Cloud.Trace.V2.Span ToSpan(this SpanData spanData, string projectId) { var spanId = spanData.Context.SpanId.ToLowerBase16(); // Base span settings - var span = new Span + var span = new Google.Cloud.Trace.V2.Span { SpanName = new SpanName(projectId, spanData.Context.TraceId.ToLowerBase16(), spanId), SpanId = spanId, @@ -63,7 +63,7 @@ public static Span ToSpan(this SpanData spanData, string projectId) // Span Links if (spanData.Links != null) { - span.Links = new Span.Types.Links + span.Links = new Google.Cloud.Trace.V2.Span.Types.Links { DroppedLinksCount = spanData.Links.DroppedLinksCount, Link = { spanData.Links.Links.Select(l => l.ToLink()) } @@ -73,7 +73,7 @@ public static Span ToSpan(this SpanData spanData, string projectId) // Span Attributes if (spanData.Attributes != null) { - span.Attributes = new Span.Types.Attributes + span.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes { DroppedAttributesCount = spanData.Attributes != null ? spanData.Attributes.DroppedAttributesCount : 0, @@ -86,15 +86,15 @@ public static Span ToSpan(this SpanData spanData, string projectId) return span; } - public static Span.Types.Link ToLink(this ILink link) + public static Google.Cloud.Trace.V2.Span.Types.Link ToLink(this ILink link) { - var ret = new Span.Types.Link(); + var ret = new Google.Cloud.Trace.V2.Span.Types.Link(); ret.SpanId = link.Context.SpanId.ToLowerBase16(); ret.TraceId = link.Context.TraceId.ToLowerBase16(); if (link.Attributes != null) { - ret.Attributes = new Span.Types.Attributes + ret.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes { DroppedAttributesCount = OpenTelemetry.Trace.Config.TraceParams.Default.MaxNumberOfAttributes - link.Attributes.Count, diff --git a/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj b/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj index 6991961c1a0..eb58484c84d 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj +++ b/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj @@ -17,6 +17,6 @@ - + diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ICount.cs b/src/OpenTelemetry/Stats/Aggregations/ICount.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ICount.cs rename to src/OpenTelemetry/Stats/Aggregations/ICount.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ICountData.cs b/src/OpenTelemetry/Stats/Aggregations/ICountData.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ICountData.cs rename to src/OpenTelemetry/Stats/Aggregations/ICountData.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/IDistribution.cs b/src/OpenTelemetry/Stats/Aggregations/IDistribution.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/IDistribution.cs rename to src/OpenTelemetry/Stats/Aggregations/IDistribution.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/IDistributionData.cs b/src/OpenTelemetry/Stats/Aggregations/IDistributionData.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/IDistributionData.cs rename to src/OpenTelemetry/Stats/Aggregations/IDistributionData.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ILastValue.cs b/src/OpenTelemetry/Stats/Aggregations/ILastValue.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ILastValue.cs rename to src/OpenTelemetry/Stats/Aggregations/ILastValue.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ILastValueDataDouble.cs b/src/OpenTelemetry/Stats/Aggregations/ILastValueDataDouble.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ILastValueDataDouble.cs rename to src/OpenTelemetry/Stats/Aggregations/ILastValueDataDouble.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ILastValueDataLong.cs b/src/OpenTelemetry/Stats/Aggregations/ILastValueDataLong.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ILastValueDataLong.cs rename to src/OpenTelemetry/Stats/Aggregations/ILastValueDataLong.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/IMean.cs b/src/OpenTelemetry/Stats/Aggregations/IMean.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/IMean.cs rename to src/OpenTelemetry/Stats/Aggregations/IMean.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/IMeanData.cs b/src/OpenTelemetry/Stats/Aggregations/IMeanData.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/IMeanData.cs rename to src/OpenTelemetry/Stats/Aggregations/IMeanData.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ISum.cs b/src/OpenTelemetry/Stats/Aggregations/ISum.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ISum.cs rename to src/OpenTelemetry/Stats/Aggregations/ISum.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ISumDataDouble.cs b/src/OpenTelemetry/Stats/Aggregations/ISumDataDouble.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ISumDataDouble.cs rename to src/OpenTelemetry/Stats/Aggregations/ISumDataDouble.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Aggregations/ISumDataLong.cs b/src/OpenTelemetry/Stats/Aggregations/ISumDataLong.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Aggregations/ISumDataLong.cs rename to src/OpenTelemetry/Stats/Aggregations/ISumDataLong.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IAggregation.cs b/src/OpenTelemetry/Stats/IAggregation.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IAggregation.cs rename to src/OpenTelemetry/Stats/IAggregation.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IAggregationData.cs b/src/OpenTelemetry/Stats/IAggregationData.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IAggregationData.cs rename to src/OpenTelemetry/Stats/IAggregationData.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IBucketBoundaries.cs b/src/OpenTelemetry/Stats/IBucketBoundaries.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IBucketBoundaries.cs rename to src/OpenTelemetry/Stats/IBucketBoundaries.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IMeasure.cs b/src/OpenTelemetry/Stats/IMeasure.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IMeasure.cs rename to src/OpenTelemetry/Stats/IMeasure.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IMeasureMap.cs b/src/OpenTelemetry/Stats/IMeasureMap.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IMeasureMap.cs rename to src/OpenTelemetry/Stats/IMeasureMap.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IMeasurement.cs b/src/OpenTelemetry/Stats/IMeasurement.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IMeasurement.cs rename to src/OpenTelemetry/Stats/IMeasurement.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IStatsComponent.cs b/src/OpenTelemetry/Stats/IStatsComponent.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IStatsComponent.cs rename to src/OpenTelemetry/Stats/IStatsComponent.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IStatsRecorder.cs b/src/OpenTelemetry/Stats/IStatsRecorder.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IStatsRecorder.cs rename to src/OpenTelemetry/Stats/IStatsRecorder.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IView.cs b/src/OpenTelemetry/Stats/IView.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IView.cs rename to src/OpenTelemetry/Stats/IView.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IViewData.cs b/src/OpenTelemetry/Stats/IViewData.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IViewData.cs rename to src/OpenTelemetry/Stats/IViewData.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IViewManager.cs b/src/OpenTelemetry/Stats/IViewManager.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IViewManager.cs rename to src/OpenTelemetry/Stats/IViewManager.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/IViewName.cs b/src/OpenTelemetry/Stats/IViewName.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/IViewName.cs rename to src/OpenTelemetry/Stats/IViewName.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Measurements/IMeasurementDouble.cs b/src/OpenTelemetry/Stats/Measurements/IMeasurementDouble.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Measurements/IMeasurementDouble.cs rename to src/OpenTelemetry/Stats/Measurements/IMeasurementDouble.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Measurements/IMeasurementLong.cs b/src/OpenTelemetry/Stats/Measurements/IMeasurementLong.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Measurements/IMeasurementLong.cs rename to src/OpenTelemetry/Stats/Measurements/IMeasurementLong.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Measures/IMeasureDouble.cs b/src/OpenTelemetry/Stats/Measures/IMeasureDouble.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Measures/IMeasureDouble.cs rename to src/OpenTelemetry/Stats/Measures/IMeasureDouble.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/Measures/IMeasureLong.cs b/src/OpenTelemetry/Stats/Measures/IMeasureLong.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/Measures/IMeasureLong.cs rename to src/OpenTelemetry/Stats/Measures/IMeasureLong.cs diff --git a/src/OpenTelemetry.Abstractions/Stats/StatsCollectionState.cs b/src/OpenTelemetry/Stats/StatsCollectionState.cs similarity index 100% rename from src/OpenTelemetry.Abstractions/Stats/StatsCollectionState.cs rename to src/OpenTelemetry/Stats/StatsCollectionState.cs From 0554756e8c1c5027fb7afa913eef9ffb56c360a2 Mon Sep 17 00:00:00 2001 From: ysma500 <32311542+ysma500@users.noreply.github.com> Date: Wed, 26 Jun 2019 01:54:37 -0400 Subject: [PATCH 05/41] Change open census to OpenTelemetry in readme file + Update prometheus quick guide in readme (#123) * Changed open census to OpenTelemetry in readme file * Added + wildcard, updated sample and readme to reflect sample --- README.md | 4 ++-- samples/Exporters/TestPrometheus.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2a245937097..63bb8cfc441 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ We encourage contributions. Use tags [up-for-grabs][up-for-grabs-issues] and ## OpenTelemetry QuickStart: collecting data -You can use Open Census API to instrument code and report data. Or use one of +You can use OpenTelemetry API to instrument code and report data. Or use one of automatic data collection modules. ### Using ASP.NET Core incoming requests collector @@ -199,7 +199,7 @@ Configure Prometheus exporter to have stats collected by Prometheus. var exporter = new PrometheusExporter( new PrometheusExporterOptions() { - Url = new Uri("http://localhost:9184/metrics/") + Url = "http://+:9184/metrics/" }, Stats.ViewManager); diff --git a/samples/Exporters/TestPrometheus.cs b/samples/Exporters/TestPrometheus.cs index e89758a9e44..ac42c482a1e 100644 --- a/samples/Exporters/TestPrometheus.cs +++ b/samples/Exporters/TestPrometheus.cs @@ -36,7 +36,7 @@ internal static object Run() var exporter = new PrometheusExporter( new PrometheusExporterOptions() { - Url = "http://localhost:9184/metrics/" + Url = "http://+:9184/metrics/" // "+" is a wildcard used to listen to all hostnames }, Stats.ViewManager); From 3538e05f0eed9df008d30e82a70bef11bd579bb5 Mon Sep 17 00:00:00 2001 From: ysma500 <32311542+ysma500@users.noreply.github.com> Date: Thu, 27 Jun 2019 01:07:19 -0400 Subject: [PATCH 06/41] Reroute urls to fix 404 on sample links (#126) --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 63bb8cfc441..bdf4fc21b85 100644 --- a/README.md +++ b/README.md @@ -323,8 +323,9 @@ deprecate it for 18 months before removing it, if possible. [GKE]: https://codelabs.developers.google.com/codelabs/cloud-kubernetes-aspnetcore/index.html?index=..%2F..index#0 [gcp-auth]: https://cloud.google.com/docs/authentication/getting-started [semver]: http://semver.org/ -[ai-sample]: https://github.com/open-telemetry/OpenTelemetry-dotnet/blob/master/src/Samples/TestApplicationInsights.cs -[stackdriver-sample]: https://github.com/open-telemetry/OpenTelemetry-dotnet/blob/master/src/Samples/TestStackdriver.cs -[zipkin-sample]: https://github.com/open-telemetry/OpenTelemetry-dotnet/blob/master/src/Samples/TestZipkin.cs +[ai-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestApplicationInsights.cs +[stackdriver-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestStackdriver.cs +[zipkin-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestZipkin.cs [prometheus-get-started]: https://prometheus.io/docs/introduction/first_steps/ -[prometheus-sample]: https://github.com/open-telemetry/OpenTelemetry-dotnet/blob/master/src/Samples/TestPrometheus.cs +[prometheus-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestPrometheus.cs + From 42e9566b7bcffc6b04cba54b14ef8a95ca5a36a9 Mon Sep 17 00:00:00 2001 From: Sergey Kanzhelev Date: Sat, 29 Jun 2019 22:42:34 -0700 Subject: [PATCH 07/41] Metrics interfaces (#127) * first metrics * added metrics * implement default meter * measures * adderssed code review * adderssed code review * pascal case for enum --- .../Metrics/DefaultMeter.cs | 298 ++++++++++++++++++ .../Metrics/ICounterDouble.cs | 28 ++ .../Metrics/ICounterLong.cs | 28 ++ .../Metrics/IGaugeDouble.cs | 28 ++ .../Metrics/IGaugeLong.cs | 28 ++ .../Metrics/IMeasure.cs | 35 ++ .../Metrics/IMeasurement.cs | 25 ++ .../Metrics/IMeter.cs | 71 +++++ .../Metrics/IMetric{T}.cs | 72 +++++ .../Implementation/ICounterDoubleBuilder.cs | 25 ++ .../ICounterDoubleTimeSeries.cs | 28 ++ .../Implementation/ICounterLongBuilder.cs | 25 ++ .../Implementation/ICounterLongTimeSeries.cs | 28 ++ .../Implementation/IGaugeDoubleBuilder.cs | 25 ++ .../Implementation/IGaugeDoubleTimeSeries.cs | 28 ++ .../Implementation/IGaugeLongBuilder.cs | 25 ++ .../Implementation/IGaugeLongTimeSeries.cs | 28 ++ .../Metrics/Implementation/IMeasureBuilder.cs | 53 ++++ .../Implementation/IMetricBuilder{T}.cs | 76 +++++ .../Metrics/Implementation/MeasureType.cs | 31 ++ .../Metrics/LabelKey.cs | 53 ++++ 21 files changed, 1038 insertions(+) create mode 100644 src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/ICounterDouble.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/ICounterLong.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/IGaugeDouble.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/IGaugeLong.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/IMeasure.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/IMeasurement.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/IMeter.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleBuilder.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleTimeSeries.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongBuilder.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongTimeSeries.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleBuilder.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleTimeSeries.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongBuilder.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongTimeSeries.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/IMetricBuilder{T}.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/Implementation/MeasureType.cs create mode 100644 src/OpenTelemetry.Abstractions/Metrics/LabelKey.cs diff --git a/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs b/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs new file mode 100644 index 00000000000..c623f256ece --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs @@ -0,0 +1,298 @@ +// +// 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.Metrics +{ + using System; + using System.Collections.Generic; + using System.Net.NetworkInformation; + using OpenTelemetry.Metrics.Implementation; + using OpenTelemetry.Resources; + using OpenTelemetry.Tags; + using OpenTelemetry.Trace; + + /// + /// No-op implementation of a meter interface. + /// + public class DefaultMeter : IMeter + { + private static CounterDoubleBuilder counterDoubleBuilder = new CounterDoubleBuilder(); + private static CounterLongBuilder counterLongBuilder = new CounterLongBuilder(); + private static GaugeDoubleBuilder gaugeDoubleBuilder = new GaugeDoubleBuilder(); + private static GaugeLongBuilder gaugeLongBuilder = new GaugeLongBuilder(); + private static MeasureBuilder measureBuilder = new MeasureBuilder(); + + /// + public ICounterDoubleBuilder GetCounterDoubleBuilder(string name) => counterDoubleBuilder; + + /// + public ICounterLongBuilder GetCounterLongBuilder(string name) => counterLongBuilder; + + /// + public IGaugeDoubleBuilder GetGaugeDoubleBuilder(string name) => gaugeDoubleBuilder; + + /// + public IGaugeLongBuilder GetGaugeLongBuilder(string name) => gaugeLongBuilder; + + /// + public IMeasureBuilder GetMeasureBuilder(string name) => measureBuilder; + + /// + public void Record(IEnumerable measurements) + { + } + + /// + public void Record(IEnumerable measurements, ITagContext tagContext) + { + } + + /// + public void Record(IEnumerable measurements, ITagContext tagContext, SpanContext spanContext) + { + } + + private class CounterDoubleTimeSeries : ICounterDoubleTimeSeries + { + public void Add(double delta) + { + } + + public void Set(double val) + { + } + } + + private class CounterDouble : ICounterDouble + { + private static CounterDoubleTimeSeries timeSeries = new CounterDoubleTimeSeries(); + + public void Clear() + { + } + + public ICounterDoubleTimeSeries GetDefaultTimeSeries() => timeSeries; + + public ICounterDoubleTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + + public void RemoveTimeSeries(IEnumerable labelValues) + { + } + + public void SetCallback(Action metricUpdater) + { + } + } + + private class CounterDoubleBuilder : ICounterDoubleBuilder + { + private static CounterDouble counterDouble = new CounterDouble(); + + public IMetric Build() => counterDouble; + + public IMetricBuilder SetComponent(string component) => this; + + public IMetricBuilder SetConstantLabels(IDictionary constantLabels) => this; + + public IMetricBuilder SetDescription(string description) => this; + + public IMetricBuilder SetLabelKeys(IEnumerable labelKeys) => this; + + public IMetricBuilder SetResource(Resource resource) => this; + + public IMetricBuilder SetUnit(string unit) => this; + } + + private class CounterLongTimeSeries : ICounterLongTimeSeries + { + public void Add(long delta) + { + } + + public void Set(long val) + { + } + } + + private class CounterLong : ICounterLong + { + private static CounterLongTimeSeries timeSeries = new CounterLongTimeSeries(); + + public void Clear() + { + } + + public ICounterLongTimeSeries GetDefaultTimeSeries() => timeSeries; + + public ICounterLongTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + + public void RemoveTimeSeries(IEnumerable labelValues) + { + } + + public void SetCallback(Action metricUpdater) + { + } + } + + private class CounterLongBuilder : ICounterLongBuilder + { + private static CounterLong counterLong = new CounterLong(); + + public IMetric Build() => counterLong; + + public IMetricBuilder SetComponent(string component) => this; + + public IMetricBuilder SetConstantLabels(IDictionary constantLabels) => this; + + public IMetricBuilder SetDescription(string description) => this; + + public IMetricBuilder SetLabelKeys(IEnumerable labelKeys) => this; + + public IMetricBuilder SetResource(Resource resource) => this; + + public IMetricBuilder SetUnit(string unit) => this; + } + + private class GaugeDoubleTimeSeries : IGaugeDoubleTimeSeries + { + public void Add(double delta) + { + } + + public void Set(double val) + { + } + } + + private class GaugeDouble : IGaugeDouble + { + private static GaugeDoubleTimeSeries timeSeries = new GaugeDoubleTimeSeries(); + + public void Clear() + { + } + + public IGaugeDoubleTimeSeries GetDefaultTimeSeries() => timeSeries; + + public IGaugeDoubleTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + + public void RemoveTimeSeries(IEnumerable labelValues) + { + } + + public void SetCallback(Action metricUpdater) + { + } + } + + private class GaugeDoubleBuilder : IGaugeDoubleBuilder + { + private static GaugeDouble gaugeDouble = new GaugeDouble(); + + public IMetric Build() => gaugeDouble; + + public IMetricBuilder SetComponent(string component) => this; + + public IMetricBuilder SetConstantLabels(IDictionary constantLabels) => this; + + public IMetricBuilder SetDescription(string description) => this; + + public IMetricBuilder SetLabelKeys(IEnumerable labelKeys) => this; + + public IMetricBuilder SetResource(Resource resource) => this; + + public IMetricBuilder SetUnit(string unit) => this; + } + + private class GaugeLongTimeSeries : IGaugeLongTimeSeries + { + public void Add(long delta) + { + } + + public void Set(long val) + { + } + } + + private class GaugeLong : IGaugeLong + { + private static GaugeLongTimeSeries timeSeries = new GaugeLongTimeSeries(); + + public void Clear() + { + } + + public IGaugeLongTimeSeries GetDefaultTimeSeries() => timeSeries; + + public IGaugeLongTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + + public void RemoveTimeSeries(IEnumerable labelValues) + { + } + + public void SetCallback(Action metricUpdater) + { + } + } + + private class GaugeLongBuilder : IGaugeLongBuilder + { + private static GaugeLong counterLong = new GaugeLong(); + + public IMetric Build() => counterLong; + + public IMetricBuilder SetComponent(string component) => this; + + public IMetricBuilder SetConstantLabels(IDictionary constantLabels) => this; + + public IMetricBuilder SetDescription(string description) => this; + + public IMetricBuilder SetLabelKeys(IEnumerable labelKeys) => this; + + public IMetricBuilder SetResource(Resource resource) => this; + + public IMetricBuilder SetUnit(string unit) => this; + } + + private class Measurement : IMeasurement + { + } + + private class Measure : IMeasure + { + private static IMeasurement measurement = new Measurement(); + + public IMeasurement CreateDoubleMeasurement(double value) => measurement; + + public IMeasurement CreateLongMeasurement(long value) => measurement; + } + + private class MeasureBuilder : IMeasureBuilder + { + private static Measure measure = new Measure(); + + public IMeasure Build() => measure; + + public IMeasureBuilder SetDescription(string description) => this; + + public IMeasureBuilder SetType(MeasureType type) => this; + + public IMeasureBuilder SetUnit(string unit) => this; + } + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/ICounterDouble.cs b/src/OpenTelemetry.Abstractions/Metrics/ICounterDouble.cs new file mode 100644 index 00000000000..7694e10474f --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/ICounterDouble.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics +{ + using OpenTelemetry.Metrics.Implementation; + + /// + /// Counter metric, to report instantaneous measurement of a double value. Cumulative values can go + /// up or stay the same, but can never go down.Cumulative values cannot be negative. + /// + public interface ICounterDouble : IMetric + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/ICounterLong.cs b/src/OpenTelemetry.Abstractions/Metrics/ICounterLong.cs new file mode 100644 index 00000000000..d1cb99a35d8 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/ICounterLong.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics +{ + using OpenTelemetry.Metrics.Implementation; + + /// + /// Counter metric, to report instantaneous measurement of a double value. Cumulative values can go + /// up or stay the same, but can never go down.Cumulative values cannot be negative. + /// + public interface ICounterLong : IMetric + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/IGaugeDouble.cs b/src/OpenTelemetry.Abstractions/Metrics/IGaugeDouble.cs new file mode 100644 index 00000000000..b584fcfc2fa --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/IGaugeDouble.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics +{ + using OpenTelemetry.Metrics.Implementation; + + /// + /// Gauge metric, to report instantaneous measurement of a double value. Cumulative values can go + /// up or down. + /// + public interface IGaugeDouble : IMetric + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/IGaugeLong.cs b/src/OpenTelemetry.Abstractions/Metrics/IGaugeLong.cs new file mode 100644 index 00000000000..6fd9c4d04ed --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/IGaugeLong.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics +{ + using OpenTelemetry.Metrics.Implementation; + + /// + /// Gauge metric, to report instantaneous measurement of a double value. Cumulative values can go + /// up or stay the same, but can never go down.Cumulative values cannot be negative. + /// + public interface IGaugeLong : IMetric + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/IMeasure.cs b/src/OpenTelemetry.Abstractions/Metrics/IMeasure.cs new file mode 100644 index 00000000000..bc4a6ee74d2 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/IMeasure.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.Metrics +{ + public interface IMeasure + { + /// + /// Records the measurement of this . + /// + /// Value to be recorded. + /// Measurement representing this value. + IMeasurement CreateDoubleMeasurement(double value); + + /// + /// Records the measurement of this . + /// + /// Value to be recorded. + /// Measurement representing this value. + IMeasurement CreateLongMeasurement(long value); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/IMeasurement.cs b/src/OpenTelemetry.Abstractions/Metrics/IMeasurement.cs new file mode 100644 index 00000000000..90318f0ffe5 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/IMeasurement.cs @@ -0,0 +1,25 @@ +// +// 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.Metrics +{ + /// + /// Immutable representation of a measurement. + /// + public interface IMeasurement + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs b/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs new file mode 100644 index 00000000000..6043037ae9d --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs @@ -0,0 +1,71 @@ +// +// 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.Metrics +{ + using System.Collections; + using System.Collections.Generic; + using OpenTelemetry.Metrics.Implementation; + using OpenTelemetry.Tags; + using OpenTelemetry.Trace; + + /// + /// Returns a builder for . + /// + public interface IMeter + { + /// + /// Gets the builder for . + /// + /// Name of the counter. + /// The builder for the . + ICounterDoubleBuilder GetCounterDoubleBuilder(string name); + + /// + /// Gets the builder for . + /// + /// Name of the counter. + /// The builder for the . + ICounterLongBuilder GetCounterLongBuilder(string name); + + /// + /// Gets the builder for . + /// + /// Name of the counter. + /// The builder for the . + IGaugeDoubleBuilder GetGaugeDoubleBuilder(string name); + + /// + /// Gets the builder for . + /// + /// Name of the counter. + /// The builder for the . + IGaugeLongBuilder GetGaugeLongBuilder(string name); + + /// + /// Gets the builder for the . + /// + /// The name of the . + /// The to build the . + IMeasureBuilder GetMeasureBuilder(string name); + + void Record(IEnumerable measurements); + + void Record(IEnumerable measurements, ITagContext tagContext); + + void Record(IEnumerable measurements, ITagContext tagContext, SpanContext spanContext); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs b/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs new file mode 100644 index 00000000000..c461fd8e3f5 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs @@ -0,0 +1,72 @@ +// +// 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.Metrics +{ + using System; + using System.Collections.Generic; + using OpenTelemetry.Resources; + + /// + /// Base interface for all metrics defined in this package. + /// + /// Type of the time series of the metric. + public interface IMetric + { + /// + /// Creates a time series and returns a time series if the specified labelValues + /// is not already associated with this metric, else returns an existing time series. + /// + /// It is recommended to keep a reference to the time series instead of always calling this + /// method for every operations. + /// + /// + /// The list of label values. The number of label values must be the same to + /// that of the label keys passed to. + /// + /// A time series the value of single metric. + T GetOrCreateTimeSeries(IEnumerable labelValues); + + /// + /// Returns a time series for a metric with all labels not set (default label values). + /// + /// A time series for a metric with all labels not set (default label values) + T GetDefaultTimeSeries(); + + /// + /// Sets a callback that gets executed every time before exporting this metric. Used to + /// implement pull-based metric. + /// + /// Evaluation is deferred until needed, if this is not exported then it will never be called. + /// + /// The callback to be executed before export. + void SetCallback(Action metricUpdater); + + /// + /// Removes the time series from the metric, if it is present. i.e. references to previous time series + /// are invalid (not part of the metric). + /// + /// If value is missing for one of the predefined keys null must be used for that value. + /// + /// The list of label values + void RemoveTimeSeries(IEnumerable labelValues); + + /// + /// Removes all time series from the metric. i.e. references to all previous time series are invalid (not part of the metric). + /// + void Clear(); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleBuilder.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleBuilder.cs new file mode 100644 index 00000000000..e5c935cbd8b --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleBuilder.cs @@ -0,0 +1,25 @@ +// +// 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.Metrics.Implementation +{ + /// + /// The builder for the . + /// + public interface ICounterDoubleBuilder : IMetricBuilder + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleTimeSeries.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleTimeSeries.cs new file mode 100644 index 00000000000..31e33658c1a --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterDoubleTimeSeries.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics.Implementation +{ + /// + /// Time series type for . + /// + public interface ICounterDoubleTimeSeries + { + void Add(double delta); + + void Set(double val); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongBuilder.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongBuilder.cs new file mode 100644 index 00000000000..3b37e488422 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongBuilder.cs @@ -0,0 +1,25 @@ +// +// 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.Metrics.Implementation +{ + /// + /// The builder for the . + /// + public interface ICounterLongBuilder : IMetricBuilder + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongTimeSeries.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongTimeSeries.cs new file mode 100644 index 00000000000..0200ebd08db --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/ICounterLongTimeSeries.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics.Implementation +{ + /// + /// Time series type for . + /// + public interface ICounterLongTimeSeries + { + void Add(long delta); + + void Set(long val); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleBuilder.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleBuilder.cs new file mode 100644 index 00000000000..97abcdffdb0 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleBuilder.cs @@ -0,0 +1,25 @@ +// +// 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.Metrics.Implementation +{ + /// + /// The builder for the . + /// + public interface IGaugeDoubleBuilder : IMetricBuilder + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleTimeSeries.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleTimeSeries.cs new file mode 100644 index 00000000000..d2b44a6917d --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeDoubleTimeSeries.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics.Implementation +{ + /// + /// Time series type for . + /// + public interface IGaugeDoubleTimeSeries + { + void Add(double delta); + + void Set(double val); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongBuilder.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongBuilder.cs new file mode 100644 index 00000000000..54c31a1e288 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongBuilder.cs @@ -0,0 +1,25 @@ +// +// 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.Metrics.Implementation +{ + /// + /// The builder for the . + /// + public interface IGaugeLongBuilder : IMetricBuilder + { + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongTimeSeries.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongTimeSeries.cs new file mode 100644 index 00000000000..1fb581ca384 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IGaugeLongTimeSeries.cs @@ -0,0 +1,28 @@ +// +// 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.Metrics.Implementation +{ + /// + /// Time series type for . + /// + public interface IGaugeLongTimeSeries + { + void Add(long delta); + + void Set(long val); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs new file mode 100644 index 00000000000..65d828c48d1 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs @@ -0,0 +1,53 @@ +// +// 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.Metrics.Implementation +{ + using System; + + /// + /// Builder for the . + /// + public interface IMeasureBuilder + { + /// + /// Sets the description of the . + /// + /// The detailed description of the . + /// This builder object. + IMeasureBuilder SetDescription(string description); + + /// + /// Sets the description of the . + /// + /// The detailed description of the . + /// This builder object. + IMeasureBuilder SetUnit(string unit); + + /// + /// Sets the corresponding to the underlying value of the . + /// + /// The detailed description of the . + /// This builder object. + IMeasureBuilder SetType(MeasureType type); + + /// + /// Builds the . + /// + /// The object. + IMeasure Build(); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMetricBuilder{T}.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMetricBuilder{T}.cs new file mode 100644 index 00000000000..7a7ef777c0e --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMetricBuilder{T}.cs @@ -0,0 +1,76 @@ +// +// 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.Metrics.Implementation +{ + using System.Collections.Generic; + using OpenTelemetry.Resources; + + /// + /// Metric builder interface. + /// + /// Type of time series in metric. + public interface IMetricBuilder + { + /// + /// Sets the description of the . + /// + /// Description of the metric. + /// This builder instance. + IMetricBuilder SetDescription(string description); + + /// + /// Sets the description of the . + /// + /// Unit of the metric. + /// This builder instance. + IMetricBuilder SetUnit(string unit); + + /// + /// Sets the description of the . + /// + /// List of keys for dynamic labels. + /// This builder instance. + IMetricBuilder SetLabelKeys(IEnumerable labelKeys); + + /// + /// Sets the description of the . + /// + /// Set of labels with values. + /// This builder instance. + IMetricBuilder SetConstantLabels(IDictionary constantLabels); + + /// + /// Sets the description of the . + /// + /// Component reporting this metric. + /// This builder instance. + IMetricBuilder SetComponent(string component); + + /// + /// Sets the description of the . + /// + /// Resource associated with the metric. + /// This builder instance. + IMetricBuilder SetResource(Resource resource); + + /// + /// Builds the . + /// + /// The new instance of . + IMetric Build(); + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/MeasureType.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/MeasureType.cs new file mode 100644 index 00000000000..d00e65bd07b --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/MeasureType.cs @@ -0,0 +1,31 @@ +// +// 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.Metrics.Implementation +{ + public enum MeasureType + { + /// + /// Long type values. + /// + Long, + + /// + /// Double type values. + /// + Double, + } +} diff --git a/src/OpenTelemetry.Abstractions/Metrics/LabelKey.cs b/src/OpenTelemetry.Abstractions/Metrics/LabelKey.cs new file mode 100644 index 00000000000..fc9014e7dfa --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Metrics/LabelKey.cs @@ -0,0 +1,53 @@ +// +// 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.Metrics +{ + /// + /// The key of a label associated with a . + /// + public sealed class LabelKey + { + private LabelKey() + { + } + + /// + /// Gets a key of the label. + /// + public string Key { get; private set; } + + /// + /// Gets a human-readable description of what this label key represents. + /// + public string Description { get; private set; } + + /// + /// Creates a new instance of a . + /// + /// The key of the label. + /// A human-readable description of what this label key represents. + /// A new instance of . + public static LabelKey Create(string key, string description) + { + return new LabelKey() + { + Key = key, + Description = description, + }; + } + } +} From 843fc3e225ef5a24b1ce7e0c9e6e0b4f46f92120 Mon Sep 17 00:00:00 2001 From: Michael Ingold Date: Tue, 9 Jul 2019 07:32:22 +0200 Subject: [PATCH 08/41] Code Cleanups (#131) * reordered all usings (SA1208) * Use trailing comma in multi-line initializers (SA1413) * SA1005 Single line comment should begin with a space. * SA1028 Code should not contain trailing whitespace * A1101 Prefix local calls with this * SA1500 Braces for multi-line statements should not share line * SA1505 An opening brace should not be followed by a blank line. * SA1513 Closing brace should be followed by blank line * SA1517 Code should not contain blank lines at start of file * A1507 Code should not contain multiple blank lines in a row * SA1503 Braces should not be omitted * SA1508 A closing brace should not be preceded by a blank line * SA1210 Using directives should be ordered alphabetically by the namespaces * IDE0065 Removed unnecessary usings * SA1633 The file header is missing or not located at the top of the file. * IDE0044 Make field readonly * SA1311 Static readonly fields should begin with upper-case letter * IDE0060 Remove unused parameter 'options' if it is not part of a shipped public API * various IDE warnings cleaned up * SA1400 Element should declare an access modifier * SA1402 File may only contain a single type * SA1638 File header file name documentation should match file name * SA1629 Documentation text should end with a period * various code uncommon style warnings fixes * SA1137 Elements should have the same indentation * SA1648 inheritdoc should be used with inheriting class * SA1616 Element return value documentation should have text * SA1310 Field should not contain an underscore * Various documentation rule violations fixed * SA1614 Element parameter documentation should have text * SA1137 Elements should have the same indentation * Various documentation rule violations fixed * CS1574 XML comment has cref attribute that could not be resolved * CS1572 XML comment has a param tag for, but there is no parameter by that name * SA1204 Static members should appear before non-static members * SA1201 A property should not follow a method * SA1201 A constructor should not follow a property * SA1202 'public' members should come before 'private' members * SA1202 'internal' members should come before 'private' members * SA1202 'protected' members should come before 'private' members * CS0168 The variable 'ex' is declared but never used * Moved to implicit version resolution, as stated in the warning from the dotnet sdk * various cleanups and project structure * CS1591 disabled for the entire solution * removed `[assembly: System.CLSCompliant(true)]` from contributed projects * Fixed various async snafus. * removed version.props from proj file * enabled TreatWarningsAsErrors --- OpenTelemetry.proj | 1 - build/Common.prod.props | 10 +- build/OpenTelemetry.prod.loose.ruleset | 1 + build/Version.props | 30 -- samples/Exporters/Exporters.csproj | 6 +- samples/Exporters/Program.cs | 92 +++-- samples/Exporters/TestApplicationInsights.cs | 38 +- samples/Exporters/TestHttpClient.cs | 26 +- samples/Exporters/TestPrometheus.cs | 40 +- samples/Exporters/TestRedis.cs | 33 +- samples/Exporters/TestStackdriver.cs | 36 +- samples/Exporters/TestZipkin.cs | 19 +- .../Context/Propagation/TraceContextFormat.cs | 4 +- .../Metrics/DefaultMeter.cs | 71 ++-- .../Metrics/IMeter.cs | 1 - .../Metrics/IMetric{T}.cs | 5 +- .../Metrics/Implementation/IMeasureBuilder.cs | 2 - .../OpenTelemetry.Abstractions.csproj | 4 - .../Resources/Resource.cs | 6 +- .../Trace/Export/ISpanExporter.cs | 1 - src/OpenTelemetry.Abstractions/Trace/ISpan.cs | 4 +- .../Utils/Collections.cs | 1 - .../AspNetCoreCollectorEventSource.cs | 2 - .../AssemblyInfo.cs | 17 - .../Implementation/HttpInListener.cs | 1 - .../DiagnosticSourceListener.cs | 4 +- .../RequestsCollector.cs | 4 - .../RequestsCollectorOptions.cs | 7 +- .../DependenciesCollector.cs | 1 - .../DependenciesCollectorEventSource.cs | 2 - .../DependenciesCollectorOptions.cs | 6 +- .../HttpHandlerDiagnosticListener.cs | 3 - .../DiagnosticSourceListener.cs | 4 +- .../AssemblyInfo.cs | 4 +- .../StackExchangeRedisCallsCollector.cs | 3 +- .../Implementation/TraceExporterHandler.cs | 341 +++++++++--------- .../Properties/AssemblyInfo.cs | 4 +- .../Implementation/PrometheusMetricBuilder.cs | 20 +- .../PrometheusExporterOptions.cs | 2 - .../Implementation/Constants.cs | 42 +-- .../GoogleCloudResourceUtils.cs | 22 +- .../Implementation/MetricsConversions.cs | 186 +++++----- .../Implementation/SpanExtensions.cs | 121 +++++++ .../StackdriverStatsConfiguration.cs | 58 +-- .../StackdriverStatsExporter.cs | 270 +++++++------- .../StackdriverTraceExporter.cs | 144 ++------ .../StackdriverExporter.cs | 71 ++-- .../Utils/CommonUtils.cs | 14 +- .../Utils/ProtoExtensions.cs | 10 +- .../AssemblyInfo.cs | 3 - src/OpenTelemetry/Internal/VarInt.cs | 192 ++-------- src/OpenTelemetry/Stats/MeasureToViewMap.cs | 5 +- src/OpenTelemetry/Stats/MutableViewData.cs | 35 +- src/OpenTelemetry/Stats/Stats.cs | 10 +- .../Tags/Unsafe/AsyncLocalContext.cs | 10 +- src/OpenTelemetry/Trace/CurrentSpanUtils.cs | 12 +- .../Trace/Export/NoopSpanExporter.cs | 1 - .../Trace/Export/SpanExporter.cs | 5 +- .../Trace/Export/SpanExporterBase.cs | 1 - .../SpanStore/InProcessSampledSpanStore.cs | 6 +- src/OpenTelemetry/Trace/Internal/BlankSpan.cs | 1 - .../Trace/Internal/RandomGenerator.cs | 1 + src/OpenTelemetry/Trace/NoopTracer.cs | 8 +- .../Trace/Sampler/ProbabilitySampler.cs | 62 ++-- src/OpenTelemetry/Trace/SpanBase.cs | 5 +- src/OpenTelemetry/Trace/SpanBuilderBase.cs | 10 +- src/OpenTelemetry/Trace/Tracer.cs | 1 + src/OpenTelemetry/Trace/TracerBase.cs | 2 +- src/OpenTelemetry/Trace/Tracing.cs | 11 +- .../BasicTests.cs | 2 - ...stsCollectionsIsAccordingToTheSpecTests.cs | 3 +- ...elemetry.Collector.AspNetCore.Tests.csproj | 2 +- .../BasicTests.cs | 1 - .../HttpClientTests.cs | 2 - .../TestServer.cs | 2 +- ...ofilerEntryToSpanConverterSamplingTests.cs | 2 - .../RedisProfilerEntryToSpanConverterTests.cs | 1 - .../StackExchangeRedisCallsCollectorTests.cs | 3 +- .../StackdriverStatsConfigurationTests.cs | 6 +- .../Impl/Resources/ResourceTest.cs | 2 +- .../Impl/Stats/CurrentStatsStateTest.cs | 2 +- .../Impl/Stats/MeasureToViewMapTest.cs | 1 - .../Impl/Stats/QuickStartExampleTest.cs | 2 +- .../Impl/Stats/StatsRecorderTest.cs | 6 +- .../Impl/Stats/ViewManagerTest.cs | 16 +- .../Impl/Tags/CurrentTagContextUtilsTest.cs | 1 - .../Impl/Tags/NoopTagsTest.cs | 1 - .../Impl/Tags/ScopedTagContextsTest.cs | 1 - .../Impl/Tags/TaggerTest.cs | 1 - .../Impl/Testing/Export/TestHandler.cs | 5 +- .../Impl/Trace/Config/TraceConfigBaseTest.cs | 2 +- .../Impl/Trace/CurrentSpanUtilsTest.cs | 9 +- .../Export/InProcessRunningSpanStoreTest.cs | 2 +- .../Export/InProcessSampledSpanStoreTest.cs | 2 +- .../Trace/Export/NoopRunningSpanStoreTest.cs | 1 - .../Impl/Trace/Export/SpanDataTest.cs | 6 +- .../Impl/Trace/Export/SpanExporterTest.cs | 1 - .../Impl/Trace/Propagation/B3FormatTest.cs | 2 +- .../Impl/Trace/SpanBaseTest.cs | 9 +- .../Impl/Trace/SpanBuilderBaseTest.cs | 7 +- .../Impl/Trace/SpanBuilderTest.cs | 9 +- .../Impl/Trace/SpanTest.cs | 3 +- .../Impl/Trace/TraceComponentTest.cs | 2 - .../Impl/Trace/TracerBaseTest.cs | 7 +- .../Impl/Trace/TracerTest.cs | 6 +- .../Impl/Trace/TracingTest.cs | 1 - test/TestApp.AspNetCore.2.0/Startup.cs | 1 - .../TestApp.AspNetCore.2.0.csproj | 2 +- 108 files changed, 1121 insertions(+), 1188 deletions(-) delete mode 100644 build/Version.props delete mode 100644 src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs create mode 100644 src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs diff --git a/OpenTelemetry.proj b/OpenTelemetry.proj index 3ef311bca47..acb97f30bf5 100644 --- a/OpenTelemetry.proj +++ b/OpenTelemetry.proj @@ -1,6 +1,5 @@ - diff --git a/build/Common.prod.props b/build/Common.prod.props index 9440a5f8ead..467404ca146 100644 --- a/build/Common.prod.props +++ b/build/Common.prod.props @@ -1,9 +1,16 @@ - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + $(MSBuildThisFileDirectory)/OpenTelemetry.prod.ruleset + $(NoWarn),1573,1591,1712 $(Build_ArtifactStagingDirectory) true @@ -13,6 +20,7 @@ $(MSBuildThisFileDirectory)/debug.snk false $(DefineConstants);SIGNED + true diff --git a/build/OpenTelemetry.prod.loose.ruleset b/build/OpenTelemetry.prod.loose.ruleset index 0a90ff6246f..936300e85b9 100644 --- a/build/OpenTelemetry.prod.loose.ruleset +++ b/build/OpenTelemetry.prod.loose.ruleset @@ -168,5 +168,6 @@ + \ No newline at end of file diff --git a/build/Version.props b/build/Version.props deleted file mode 100644 index ad0da62b812..00000000000 --- a/build/Version.props +++ /dev/null @@ -1,30 +0,0 @@ - - - - - 0 - 1 - 0 - - alpha - - 2018-08-25 - - $([MSBuild]::Divide($([System.DateTime]::Now.Subtract($([System.DateTime]::Parse($(SemanticVersionDate)))).TotalMinutes), 5).ToString('F0')) - - - - $(SemanticVersionMajor).$(SemanticVersionMinor).$(SemanticVersionPatch) - $(PreReleaseMilestone)-$(PreReleaseVersion) - $(SemanticVersionMajor).$(SemanticVersionMinor).$(SemanticVersionPatch).$(PreReleaseVersion) - - \ No newline at end of file diff --git a/samples/Exporters/Exporters.csproj b/samples/Exporters/Exporters.csproj index 5ab15de94b2..32b518a9608 100644 --- a/samples/Exporters/Exporters.csproj +++ b/samples/Exporters/Exporters.csproj @@ -1,11 +1,15 @@  - + Exe netcoreapp2.1 + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'OpenTelemetry.sln'))/build/OpenTelemetry.prod.loose.ruleset + + diff --git a/samples/Exporters/Program.cs b/samples/Exporters/Program.cs index c18e220d456..b03c75bcbf9 100644 --- a/samples/Exporters/Program.cs +++ b/samples/Exporters/Program.cs @@ -1,71 +1,91 @@ -namespace Samples +// +// 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 Samples { - using CommandLine; using System; + using CommandLine; + + /// + /// Main samples entry point. + /// + public class Program + { + /// + /// Main method - invoke this using command line. + /// For example: + /// + /// Samples.dll zipkin http://localhost:9411/api/v2/spans + /// Sample.dll appInsights + /// Sample.dll prometheus. + /// + /// Arguments from command line. + public static void Main(string[] args) + { + Parser.Default.ParseArguments(args) + .MapResult( + (ZipkinOptions options) => TestZipkin.Run(options.Uri), + (ApplicationInsightsOptions options) => TestApplicationInsights.Run(), + (PrometheusOptions options) => TestPrometheus.Run(), + (HttpClientOptions options) => TestHttpClient.Run(), + (RedisOptions options) => TestRedis.Run(options.Uri), + (StackdriverOptions options) => TestStackdriver.Run(options.ProjectId), + errs => 1); + + Console.ReadLine(); + } + } [Verb("stackdriver", HelpText = "Specify the options required to test Stackdriver exporter", Hidden = false)] - class StackdriverOptions +#pragma warning disable SA1402 // File may only contain a single type + internal class StackdriverOptions { [Option('p', "projectId", HelpText = "Please specify the projectId of your GCP project", Required = true)] public string ProjectId { get; set; } } [Verb("zipkin", HelpText = "Specify the options required to test Zipkin exporter")] - class ZipkinOptions + internal class ZipkinOptions { [Option('u', "uri", HelpText = "Please specify the uri of Zipkin backend", Required = true)] public string Uri { get; set; } } [Verb("appInsights", HelpText = "Specify the options required to test ApplicationInsights")] - class ApplicationInsightsOptions + internal class ApplicationInsightsOptions { } [Verb("prometheus", HelpText = "Specify the options required to test Prometheus")] - class PrometheusOptions + internal class PrometheusOptions { } [Verb("httpclient", HelpText = "Specify the options required to test HttpClient")] - class HttpClientOptions + internal class HttpClientOptions { } [Verb("redis", HelpText = "Specify the options required to test Redis with Zipkin")] - class RedisOptions + internal class RedisOptions { [Option('u', "uri", HelpText = "Please specify the uri of Zipkin backend", Required = true)] public string Uri { get; set; } } - /// - /// Main samples entry point. - /// - public class Program - { - /// - /// Main method - invoke this using command line. - /// For example: - /// - /// Samples.dll zipkin http://localhost:9411/api/v2/spans - /// Sample.dll appInsights - /// Sample.dll prometheus - /// - /// Arguments from command line. - public static void Main(string[] args) - { - Parser.Default.ParseArguments(args) - .MapResult( - (ZipkinOptions options) => TestZipkin.Run(options.Uri), - (ApplicationInsightsOptions options) => TestApplicationInsights.Run(), - (PrometheusOptions options) => TestPrometheus.Run(), - (HttpClientOptions options) => TestHttpClient.Run(), - (RedisOptions options) => TestRedis.Run(options.Uri), - (StackdriverOptions options) => TestStackdriver.Run(options.ProjectId), - errs => 1); +#pragma warning restore SA1402 // File may only contain a single type - Console.ReadLine(); - } - } } diff --git a/samples/Exporters/TestApplicationInsights.cs b/samples/Exporters/TestApplicationInsights.cs index 1b7cd86eeff..d6b4b47af55 100644 --- a/samples/Exporters/TestApplicationInsights.cs +++ b/samples/Exporters/TestApplicationInsights.cs @@ -1,4 +1,20 @@ -namespace Samples +// +// 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 Samples { using System; using System.Collections.Generic; @@ -14,19 +30,19 @@ internal class TestApplicationInsights { - private static ITracer tracer = Tracing.Tracer; - private static ITagger tagger = Tags.Tagger; + private static readonly ITracer Tracer = Tracing.Tracer; + private static readonly ITagger Tagger = Tags.Tagger; - private static IStatsRecorder statsRecorder = Stats.StatsRecorder; + private static readonly IStatsRecorder StatsRecorder = Stats.StatsRecorder; private static readonly IMeasureLong VideoSize = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "By"); private static readonly TagKey FrontendKey = TagKey.Create("my.org/keys/frontend"); - private static long MiB = 1 << 20; + private static readonly long MiB = 1 << 20; private static readonly IViewName VideoSizeViewName = ViewName.Create("my.org/views/video_size"); private static readonly IView VideoSizeView = View.Create( - VideoSizeViewName, + VideoSizeViewName, "processed video size over time", VideoSize, Distribution.Create(BucketBoundaries.Create(new List() { 0.0, 16.0 * MiB, 256.0 * MiB })), @@ -38,9 +54,9 @@ internal static object Run() var exporter = new ApplicationInsightsExporter(Tracing.ExportComponent, Stats.ViewManager, TelemetryConfiguration.Active); exporter.Start(); - var tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); + var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); - var spanBuilder = tracer + var spanBuilder = Tracer .SpanBuilder("incoming request") .SetRecordEvents(true) .SetSampler(Samplers.AlwaysSample); @@ -51,10 +67,10 @@ internal static object Run() { using (var scopedSpan = spanBuilder.StartScopedSpan()) { - tracer.CurrentSpan.AddEvent("Start processing video."); + Tracer.CurrentSpan.AddEvent("Start processing video."); Thread.Sleep(TimeSpan.FromMilliseconds(10)); - statsRecorder.NewMeasureMap().Put(VideoSize, 25 * MiB).Record(); - tracer.CurrentSpan.AddEvent("Finished processing video."); + StatsRecorder.NewMeasureMap().Put(VideoSize, 25 * MiB).Record(); + Tracer.CurrentSpan.AddEvent("Finished processing video."); } } diff --git a/samples/Exporters/TestHttpClient.cs b/samples/Exporters/TestHttpClient.cs index 3103d114d3e..eec1f62077f 100644 --- a/samples/Exporters/TestHttpClient.cs +++ b/samples/Exporters/TestHttpClient.cs @@ -1,22 +1,37 @@ -namespace Samples +// +// 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 Samples { using System; using System.Net.Http; using OpenTelemetry.Collector.Dependencies; using OpenTelemetry.Exporter.Zipkin; using OpenTelemetry.Trace; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Sampler; internal class TestHttpClient { - private static ITracer tracer = Tracing.Tracer; + private static readonly ITracer Tracer = Tracing.Tracer; internal static object Run() { Console.WriteLine("Hello World!"); - var collector = new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample); + var collector = new DependenciesCollector(new DependenciesCollectorOptions(), Tracer, Samplers.AlwaysSample); var exporter = new ZipkinTraceExporter( new ZipkinTraceExporterOptions() @@ -27,8 +42,7 @@ internal static object Run() Tracing.ExportComponent); exporter.Start(); - var scope = tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartScopedSpan(); - //Thread.Sleep(TimeSpan.FromSeconds(1)); + var scope = Tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartScopedSpan(); var client = new HttpClient(); var t = client.GetStringAsync("http://bing.com"); diff --git a/samples/Exporters/TestPrometheus.cs b/samples/Exporters/TestPrometheus.cs index ac42c482a1e..61a8fa89534 100644 --- a/samples/Exporters/TestPrometheus.cs +++ b/samples/Exporters/TestPrometheus.cs @@ -1,26 +1,42 @@ -namespace Samples +// +// 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 Samples { + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; using OpenTelemetry.Exporter.Prometheus; using OpenTelemetry.Stats; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; using OpenTelemetry.Trace; - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; internal class TestPrometheus { - private static ITracer tracer = Tracing.Tracer; - private static ITagger tagger = Tags.Tagger; + private static readonly ITracer Tracer = Tracing.Tracer; + private static readonly ITagger Tagger = Tags.Tagger; - private static IStatsRecorder statsRecorder = Stats.StatsRecorder; + private static readonly IStatsRecorder StatsRecorder = Stats.StatsRecorder; private static readonly IMeasureLong VideoSize = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "By"); private static readonly TagKey FrontendKey = TagKey.Create("my.org/keys/frontend"); - private static long MiB = 1 << 20; + private static readonly long MiB = 1 << 20; private static readonly IViewName VideoSizeViewName = ViewName.Create("my.org/views/video_size"); @@ -36,7 +52,7 @@ internal static object Run() var exporter = new PrometheusExporter( new PrometheusExporterOptions() { - Url = "http://+:9184/metrics/" // "+" is a wildcard used to listen to all hostnames + Url = "http://+:9184/metrics/", // "+" is a wildcard used to listen to all hostnames }, Stats.ViewManager); @@ -44,7 +60,7 @@ internal static object Run() try { - var tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); + var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); Stats.ViewManager.RegisterView(VideoSizeView); @@ -58,7 +74,7 @@ internal static object Run() using (var scopedTags = tagContextBuilder.BuildScoped()) { r.NextBytes(values); - statsRecorder.NewMeasureMap().Put(VideoSize, values[0] * MiB).Record(); + StatsRecorder.NewMeasureMap().Put(VideoSize, values[0] * MiB).Record(); Thread.Sleep(TimeSpan.FromSeconds(1)); } } diff --git a/samples/Exporters/TestRedis.cs b/samples/Exporters/TestRedis.cs index 8cafe783148..72c5ab7cd77 100644 --- a/samples/Exporters/TestRedis.cs +++ b/samples/Exporters/TestRedis.cs @@ -1,4 +1,20 @@ -namespace Samples +// +// 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 Samples { using System; using System.Collections.Generic; @@ -6,7 +22,6 @@ using OpenTelemetry.Collector.StackExchangeRedis; using OpenTelemetry.Exporter.Zipkin; using OpenTelemetry.Trace; - using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Sampler; using StackExchange.Redis; @@ -36,7 +51,7 @@ internal static object Run(string zipkinUri) // but if not - you can use it as follows: var tracer = Tracing.Tracer; - var collector = new StackExchangeRedisCallsCollector(null, tracer, null, Tracing.ExportComponent); + var collector = new StackExchangeRedisCallsCollector(tracer, null, Tracing.ExportComponent); // connect to the server var connection = ConnectionMultiplexer.Connect("localhost:6379"); @@ -45,14 +60,13 @@ internal static object Run(string zipkinUri) // select a database (by default, DB = 0) var db = connection.GetDatabase(); - // 4. Create a scoped span. It will end automatically when using statement ends using (var scope = tracer.SpanBuilder("Main").StartScopedSpan()) { Console.WriteLine("About to do a busy work"); for (var i = 0; i < 10; i++) { - DoWork(db, i); + DoWork(db); } } @@ -62,7 +76,7 @@ internal static object Run(string zipkinUri) return null; } - private static void DoWork(IDatabase db, int i) + private static void DoWork(IDatabase db) { // 6. Get the global singleton Tracer object var tracer = Tracing.Tracer; @@ -86,7 +100,6 @@ private static void DoWork(IDatabase db, int i) var myVal = db.StringGet("key"); Console.WriteLine(myVal); - } catch (ArgumentOutOfRangeException e) { @@ -95,8 +108,10 @@ private static void DoWork(IDatabase db, int i) } // 7. Annotate our span to capture metadata about our operation - var attributes = new Dictionary(); - attributes.Add("use", AttributeValue.StringAttributeValue("demo")); + var attributes = new Dictionary + { + { "use", AttributeValue.StringAttributeValue("demo") }, + }; span.AddEvent("Invoking DoWork", attributes); } } diff --git a/samples/Exporters/TestStackdriver.cs b/samples/Exporters/TestStackdriver.cs index 6f2b8faa186..802a1844754 100644 --- a/samples/Exporters/TestStackdriver.cs +++ b/samples/Exporters/TestStackdriver.cs @@ -1,4 +1,20 @@ -namespace Samples +// +// 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 Samples { using System; using System.Collections.Generic; @@ -13,14 +29,14 @@ internal class TestStackdriver { - private static ITracer tracer = Tracing.Tracer; - private static ITagger tagger = Tags.Tagger; + private static readonly ITracer Tracer = Tracing.Tracer; + private static readonly ITagger Tagger = Tags.Tagger; - private static IStatsRecorder statsRecorder = Stats.StatsRecorder; + private static readonly IStatsRecorder StatsRecorder = Stats.StatsRecorder; private static readonly IMeasureDouble VideoSize = MeasureDouble.Create("my_org/measure/video_size", "size of processed videos", "MiB"); private static readonly TagKey FrontendKey = TagKey.Create("my_org/keys/frontend"); - private static long MiB = 1 << 20; + private static readonly long MiB = 1 << 20; private static readonly IViewName VideoSizeViewName = ViewName.Create("my_org/views/video_size"); @@ -34,14 +50,14 @@ internal class TestStackdriver internal static object Run(string projectId) { var exporter = new StackdriverExporter( - projectId, + projectId, Tracing.ExportComponent, Stats.ViewManager); exporter.Start(); - var tagContextBuilder = tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); + var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); - var spanBuilder = tracer + var spanBuilder = Tracer .SpanBuilder("incoming request") .SetRecordEvents(true) .SetSampler(Samplers.AlwaysSample); @@ -52,10 +68,10 @@ internal static object Run(string projectId) { using (var scopedSpan = spanBuilder.StartScopedSpan()) { - tracer.CurrentSpan.AddEvent("Processing video."); + Tracer.CurrentSpan.AddEvent("Processing video."); Thread.Sleep(TimeSpan.FromMilliseconds(10)); - statsRecorder.NewMeasureMap() + StatsRecorder.NewMeasureMap() .Put(VideoSize, 25 * MiB) .Record(); } diff --git a/samples/Exporters/TestZipkin.cs b/samples/Exporters/TestZipkin.cs index 6b75082d6b3..f9912ffb5a9 100644 --- a/samples/Exporters/TestZipkin.cs +++ b/samples/Exporters/TestZipkin.cs @@ -1,11 +1,26 @@ -namespace Samples +// +// 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 Samples { using System; using System.Collections.Generic; using System.Threading; using OpenTelemetry.Exporter.Zipkin; using OpenTelemetry.Trace; - using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Sampler; internal class TestZipkin diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs index 350c567307e..ed8baad6f3b 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs @@ -145,7 +145,7 @@ public SpanContext Extract(T carrier, Func> ge tracestateResult = tracestateBuilder.Build(); } } - catch (Exception ex) + catch (Exception) { // failure to parse tracestate should not disregard traceparent // TODO: logging @@ -153,7 +153,7 @@ public SpanContext Extract(T carrier, Func> ge return SpanContext.Create(traceId, spanId, traceoptions, tracestateResult); } - catch (Exception ex) + catch (Exception) { // TODO: logging } diff --git a/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs b/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs index c623f256ece..370f66cf433 100644 --- a/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs +++ b/src/OpenTelemetry.Abstractions/Metrics/DefaultMeter.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Metrics { using System; using System.Collections.Generic; - using System.Net.NetworkInformation; using OpenTelemetry.Metrics.Implementation; using OpenTelemetry.Resources; using OpenTelemetry.Tags; @@ -29,26 +28,26 @@ namespace OpenTelemetry.Metrics /// public class DefaultMeter : IMeter { - private static CounterDoubleBuilder counterDoubleBuilder = new CounterDoubleBuilder(); - private static CounterLongBuilder counterLongBuilder = new CounterLongBuilder(); - private static GaugeDoubleBuilder gaugeDoubleBuilder = new GaugeDoubleBuilder(); - private static GaugeLongBuilder gaugeLongBuilder = new GaugeLongBuilder(); - private static MeasureBuilder measureBuilder = new MeasureBuilder(); + private static readonly CounterDoubleBuilder CounterDoubleBuilderValue = new CounterDoubleBuilder(); + private static readonly CounterLongBuilder CounterLongBuilderValue = new CounterLongBuilder(); + private static readonly GaugeDoubleBuilder GaugeDoubleBuilderValue = new GaugeDoubleBuilder(); + private static readonly GaugeLongBuilder GaugeLongBuilderValue = new GaugeLongBuilder(); + private static readonly MeasureBuilder MeasureBuilderValue = new MeasureBuilder(); /// - public ICounterDoubleBuilder GetCounterDoubleBuilder(string name) => counterDoubleBuilder; + public ICounterDoubleBuilder GetCounterDoubleBuilder(string name) => CounterDoubleBuilderValue; /// - public ICounterLongBuilder GetCounterLongBuilder(string name) => counterLongBuilder; + public ICounterLongBuilder GetCounterLongBuilder(string name) => CounterLongBuilderValue; /// - public IGaugeDoubleBuilder GetGaugeDoubleBuilder(string name) => gaugeDoubleBuilder; + public IGaugeDoubleBuilder GetGaugeDoubleBuilder(string name) => GaugeDoubleBuilderValue; /// - public IGaugeLongBuilder GetGaugeLongBuilder(string name) => gaugeLongBuilder; + public IGaugeLongBuilder GetGaugeLongBuilder(string name) => GaugeLongBuilderValue; /// - public IMeasureBuilder GetMeasureBuilder(string name) => measureBuilder; + public IMeasureBuilder GetMeasureBuilder(string name) => MeasureBuilderValue; /// public void Record(IEnumerable measurements) @@ -78,15 +77,15 @@ public void Set(double val) private class CounterDouble : ICounterDouble { - private static CounterDoubleTimeSeries timeSeries = new CounterDoubleTimeSeries(); + private static readonly CounterDoubleTimeSeries TimeSeries = new CounterDoubleTimeSeries(); public void Clear() { } - public ICounterDoubleTimeSeries GetDefaultTimeSeries() => timeSeries; + public ICounterDoubleTimeSeries GetDefaultTimeSeries() => TimeSeries; - public ICounterDoubleTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + public ICounterDoubleTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => TimeSeries; public void RemoveTimeSeries(IEnumerable labelValues) { @@ -99,9 +98,9 @@ public void SetCallback(Action metricUpdater) private class CounterDoubleBuilder : ICounterDoubleBuilder { - private static CounterDouble counterDouble = new CounterDouble(); + private static readonly CounterDouble CounterDouble = new CounterDouble(); - public IMetric Build() => counterDouble; + public IMetric Build() => CounterDouble; public IMetricBuilder SetComponent(string component) => this; @@ -129,15 +128,15 @@ public void Set(long val) private class CounterLong : ICounterLong { - private static CounterLongTimeSeries timeSeries = new CounterLongTimeSeries(); + private static readonly CounterLongTimeSeries TimeSeries = new CounterLongTimeSeries(); public void Clear() { } - public ICounterLongTimeSeries GetDefaultTimeSeries() => timeSeries; + public ICounterLongTimeSeries GetDefaultTimeSeries() => TimeSeries; - public ICounterLongTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + public ICounterLongTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => TimeSeries; public void RemoveTimeSeries(IEnumerable labelValues) { @@ -150,9 +149,9 @@ public void SetCallback(Action metricUpdater) private class CounterLongBuilder : ICounterLongBuilder { - private static CounterLong counterLong = new CounterLong(); + private static readonly CounterLong CounterLong = new CounterLong(); - public IMetric Build() => counterLong; + public IMetric Build() => CounterLong; public IMetricBuilder SetComponent(string component) => this; @@ -180,15 +179,15 @@ public void Set(double val) private class GaugeDouble : IGaugeDouble { - private static GaugeDoubleTimeSeries timeSeries = new GaugeDoubleTimeSeries(); + private static readonly GaugeDoubleTimeSeries TimeSeries = new GaugeDoubleTimeSeries(); public void Clear() { } - public IGaugeDoubleTimeSeries GetDefaultTimeSeries() => timeSeries; + public IGaugeDoubleTimeSeries GetDefaultTimeSeries() => TimeSeries; - public IGaugeDoubleTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + public IGaugeDoubleTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => TimeSeries; public void RemoveTimeSeries(IEnumerable labelValues) { @@ -201,9 +200,9 @@ public void SetCallback(Action metricUpdater) private class GaugeDoubleBuilder : IGaugeDoubleBuilder { - private static GaugeDouble gaugeDouble = new GaugeDouble(); + private static readonly GaugeDouble GaugeDouble = new GaugeDouble(); - public IMetric Build() => gaugeDouble; + public IMetric Build() => GaugeDouble; public IMetricBuilder SetComponent(string component) => this; @@ -231,15 +230,15 @@ public void Set(long val) private class GaugeLong : IGaugeLong { - private static GaugeLongTimeSeries timeSeries = new GaugeLongTimeSeries(); + private static readonly GaugeLongTimeSeries TimeSeries = new GaugeLongTimeSeries(); public void Clear() { } - public IGaugeLongTimeSeries GetDefaultTimeSeries() => timeSeries; + public IGaugeLongTimeSeries GetDefaultTimeSeries() => TimeSeries; - public IGaugeLongTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => timeSeries; + public IGaugeLongTimeSeries GetOrCreateTimeSeries(IEnumerable labelValues) => TimeSeries; public void RemoveTimeSeries(IEnumerable labelValues) { @@ -252,9 +251,9 @@ public void SetCallback(Action metricUpdater) private class GaugeLongBuilder : IGaugeLongBuilder { - private static GaugeLong counterLong = new GaugeLong(); + private static readonly GaugeLong CounterLong = new GaugeLong(); - public IMetric Build() => counterLong; + public IMetric Build() => CounterLong; public IMetricBuilder SetComponent(string component) => this; @@ -275,18 +274,18 @@ private class Measurement : IMeasurement private class Measure : IMeasure { - private static IMeasurement measurement = new Measurement(); + private static readonly IMeasurement Measurement = new Measurement(); - public IMeasurement CreateDoubleMeasurement(double value) => measurement; + public IMeasurement CreateDoubleMeasurement(double value) => Measurement; - public IMeasurement CreateLongMeasurement(long value) => measurement; + public IMeasurement CreateLongMeasurement(long value) => Measurement; } private class MeasureBuilder : IMeasureBuilder { - private static Measure measure = new Measure(); + private static readonly Measure Measure = new Measure(); - public IMeasure Build() => measure; + public IMeasure Build() => Measure; public IMeasureBuilder SetDescription(string description) => this; diff --git a/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs b/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs index 6043037ae9d..2d29f3dc9aa 100644 --- a/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs +++ b/src/OpenTelemetry.Abstractions/Metrics/IMeter.cs @@ -16,7 +16,6 @@ namespace OpenTelemetry.Metrics { - using System.Collections; using System.Collections.Generic; using OpenTelemetry.Metrics.Implementation; using OpenTelemetry.Tags; diff --git a/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs b/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs index c461fd8e3f5..70d1d50248f 100644 --- a/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs +++ b/src/OpenTelemetry.Abstractions/Metrics/IMetric{T}.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Metrics { using System; using System.Collections.Generic; - using OpenTelemetry.Resources; /// /// Base interface for all metrics defined in this package. @@ -43,7 +42,7 @@ public interface IMetric /// /// Returns a time series for a metric with all labels not set (default label values). /// - /// A time series for a metric with all labels not set (default label values) + /// A time series for a metric with all labels not set (default label values). T GetDefaultTimeSeries(); /// @@ -61,7 +60,7 @@ public interface IMetric /// /// If value is missing for one of the predefined keys null must be used for that value. /// - /// The list of label values + /// The list of label values. void RemoveTimeSeries(IEnumerable labelValues); /// diff --git a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs index 65d828c48d1..8781814251a 100644 --- a/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Metrics/Implementation/IMeasureBuilder.cs @@ -16,8 +16,6 @@ namespace OpenTelemetry.Metrics.Implementation { - using System; - /// /// Builder for the . /// diff --git a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj index 5effc81e81f..5627e7283e8 100644 --- a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj +++ b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj @@ -5,8 +5,4 @@ OpenTelemetry .NET API abstractions OpenTelemetry - - - - \ No newline at end of file diff --git a/src/OpenTelemetry.Abstractions/Resources/Resource.cs b/src/OpenTelemetry.Abstractions/Resources/Resource.cs index dea29ca542a..6f6f0f67914 100644 --- a/src/OpenTelemetry.Abstractions/Resources/Resource.cs +++ b/src/OpenTelemetry.Abstractions/Resources/Resource.cs @@ -50,7 +50,7 @@ internal Resource(IDictionary labels) /// /// Returns a new . /// - /// An of labels that describe the resource. + /// An of labels that describe the resource. /// . public static Resource Create(IDictionary labels) { @@ -58,10 +58,10 @@ public static Resource Create(IDictionary labels) } /// - /// Returns a new, merged by merging the current with the + /// Returns a new, merged by merging the current with the. /// other . In case of a collision the current takes precedence. /// - /// The that will be merged with this. + /// The that will be merged with. this. /// . public Resource Merge(Resource other) { diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/ISpanExporter.cs b/src/OpenTelemetry.Abstractions/Trace/Export/ISpanExporter.cs index 5222f1ca335..edf52639afc 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/ISpanExporter.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/ISpanExporter.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Trace.Export { using System; - using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/OpenTelemetry.Abstractions/Trace/ISpan.cs b/src/OpenTelemetry.Abstractions/Trace/ISpan.cs index 71fdb095254..ac8991e90aa 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISpan.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISpan.cs @@ -49,10 +49,10 @@ public interface ISpan bool HasEnded { get; } /// - /// Updates the name. + /// Updates the name. /// /// If used, this will override the name provided via . - /// Upon this update, any sampling behavior based on name will depend on the + /// Upon this update, any sampling behavior based on name will depend on the /// implementation. /// /// Name of the span. diff --git a/src/OpenTelemetry.Abstractions/Utils/Collections.cs b/src/OpenTelemetry.Abstractions/Utils/Collections.cs index c51e2837413..8b85a7b7dc4 100644 --- a/src/OpenTelemetry.Abstractions/Utils/Collections.cs +++ b/src/OpenTelemetry.Abstractions/Utils/Collections.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Abstractions.Utils { using System.Collections.Generic; - using System.Linq; using System.Text; internal static class Collections diff --git a/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs b/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs index d3702aa1b40..4f4fa6d07a9 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs @@ -17,10 +17,8 @@ namespace OpenTelemetry.Collector.AspNetCore { using System; - using System.Collections.Generic; using System.Diagnostics.Tracing; using System.Globalization; - using System.Text; using System.Threading; /// diff --git a/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs b/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs deleted file mode 100644 index 69dc126db66..00000000000 --- a/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs +++ /dev/null @@ -1,17 +0,0 @@ -// -// 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. -// - -[assembly: System.CLSCompliant(true)] diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs index 4b643025fc0..3b43f70ed04 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs @@ -23,7 +23,6 @@ namespace OpenTelemetry.Collector.AspNetCore.Implementation using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using OpenTelemetry.Collector.AspNetCore.Common; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace; internal class HttpInListener : ListenerHandler diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceListener.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceListener.cs index cb9f6bcddf4..c7075312a5d 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceListener.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceListener.cs @@ -68,7 +68,7 @@ public void OnNext(KeyValuePair value) this.handler.OnCustom(value.Key, Activity.Current, value.Value); } } - catch (Exception e) + catch (Exception) { // Debug.WriteLine(e); // TODO: make sure to output the handler name as part of error message @@ -80,4 +80,4 @@ public void Dispose() this.Subscription?.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs index 304f0f6ae7e..c80122c4f17 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs @@ -18,12 +18,9 @@ namespace OpenTelemetry.Collector.AspNetCore { using System; using System.Collections.Generic; - using System.Globalization; - using System.Threading; using Microsoft.AspNetCore.Http; using OpenTelemetry.Collector.AspNetCore.Common; using OpenTelemetry.Collector.AspNetCore.Implementation; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace; /// @@ -39,7 +36,6 @@ public class RequestsCollector : IDisposable /// Configuration options for dependencies collector. /// Tracer to record traced with. /// Sampler to use to sample dependency calls. - /// Wire context propagation component. public RequestsCollector(RequestsCollectorOptions options, ITracer tracer, ISampler sampler) { this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber( diff --git a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollectorOptions.cs b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollectorOptions.cs index 58244b77f77..10d6cf6508c 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollectorOptions.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollectorOptions.cs @@ -19,22 +19,21 @@ namespace OpenTelemetry.Collector.AspNetCore using System; using Microsoft.AspNetCore.Http; using OpenTelemetry.Trace; - using OpenTelemetry.Trace.Sampler; /// /// Options for dependencies collector. /// public class RequestsCollectorOptions { - private static Func defaultSampler = (req) => { return null; }; + private static readonly Func DefaultSampler = (req) => { return null; }; /// /// Initializes a new instance of the class. /// - /// Custom sampling function, if any + /// Custom sampling function, if any. public RequestsCollectorOptions(Func sampler = null) { - this.CustomSampler = sampler ?? defaultSampler; + this.CustomSampler = sampler ?? DefaultSampler; } /// diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs index 84f7b477d18..e241b1b83fc 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs @@ -21,7 +21,6 @@ namespace OpenTelemetry.Collector.Dependencies using System.Net.Http; using OpenTelemetry.Collector.Dependencies.Common; using OpenTelemetry.Collector.Dependencies.Implementation; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace; /// diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs index 0af3e0588c0..8d5fc997183 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs @@ -17,10 +17,8 @@ namespace OpenTelemetry.Collector.Dependencies { using System; - using System.Collections.Generic; using System.Diagnostics.Tracing; using System.Globalization; - using System.Text; using System.Threading; /// diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorOptions.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorOptions.cs index dbb374112bc..53fcbc806e1 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorOptions.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorOptions.cs @@ -26,15 +26,15 @@ namespace OpenTelemetry.Collector.Dependencies /// public class DependenciesCollectorOptions { - private static Func defaultSampler = (req) => { return ((req.RequestUri != null) && req.RequestUri.ToString().Contains("zipkin.azurewebsites.net")) ? Samplers.NeverSample : null; }; + private static readonly Func DefaultSampler = (req) => { return ((req.RequestUri != null) && req.RequestUri.ToString().Contains("zipkin.azurewebsites.net")) ? Samplers.NeverSample : null; }; /// /// Initializes a new instance of the class. /// - /// Custom sampling function, if any + /// Custom sampling function, if any. public DependenciesCollectorOptions(Func sampler = null) { - this.CustomSampler = sampler ?? defaultSampler; + this.CustomSampler = sampler ?? DefaultSampler; } /// diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs index ebb24c23e60..dafcb50db36 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs @@ -17,16 +17,13 @@ namespace OpenTelemetry.Collector.Dependencies.Implementation { using System; - using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using OpenTelemetry.Collector.Dependencies.Common; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace; - using OpenTelemetry.Trace.Sampler; internal class HttpHandlerDiagnosticListener : ListenerHandler { diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs index 9b33e9080ad..0c651192bc6 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs @@ -68,7 +68,7 @@ public void OnNext(KeyValuePair value) this.handler.OnCustom(value.Key, Activity.Current, value.Value); } } - catch (Exception e) + catch (Exception) { // Debug.WriteLine(e); // TODO: make sure to output the handler name as part of error message @@ -80,4 +80,4 @@ public void Dispose() this.Subscription?.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/AssemblyInfo.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/AssemblyInfo.cs index 06753060332..ac6cad9668e 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/AssemblyInfo.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/AssemblyInfo.cs @@ -17,8 +17,6 @@ using System; using System.Runtime.CompilerServices; -[assembly:CLSCompliant(true)] - [assembly: InternalsVisibleTo("OpenTelemetry.Collector.StackExchangeRedis.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)] @@ -34,4 +32,4 @@ internal static class AssemblyInfo public const string PublicKey = ""; public const string MoqPublicKey = ""; } -#endif \ No newline at end of file +#endif diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs index 7ccd4227d24..0194a3c97e0 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs @@ -44,11 +44,10 @@ public class StackExchangeRedisCallsCollector : 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. /// TEMPORARY: handler to send data to. - public StackExchangeRedisCallsCollector(StackExchangeRedisCallsCollectorOptions options, ITracer tracer, ISampler sampler, IExportComponent exportComponent) + public StackExchangeRedisCallsCollector(ITracer tracer, ISampler sampler, IExportComponent exportComponent) { this.tracer = tracer; this.exporter = exportComponent; diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs index 65e27c8bbf6..8f2e3ebdd51 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs @@ -36,119 +36,77 @@ public TraceExporterHandler(TelemetryConfiguration telemetryConfiguration) this.telemetryClient = new TelemetryClient(telemetryConfiguration); } - public async Task ExportAsync(IEnumerable spanDataList) + public Task ExportAsync(IEnumerable spanDataList) { - await Task.Run(async () => + foreach (var span in spanDataList) { - foreach (var span in spanDataList) + this.ExtractGenericProperties( + span, + out var resultKind, + out var timestamp, + out var name, + out var resultCode, + out var props, + out var traceId, + out var spanId, + out var parentId, + out var tracestate, + out var success, + out var duration); + + string data = null; + string target = null; + string type = null; + string userAgent = null; + + IAttributeValue spanKindAttr = null; + IAttributeValue errorAttr = null; + IAttributeValue httpStatusCodeAttr = null; + IAttributeValue httpMethodAttr = null; + IAttributeValue httpPathAttr = null; + IAttributeValue httpHostAttr = null; + IAttributeValue httpUrlAttr = null; + IAttributeValue httpUserAgentAttr = null; + IAttributeValue httpRouteAttr = null; + IAttributeValue httpPortAttr = null; + + foreach (var attr in span.Attributes.AttributeMap) { - this.ExtractGenericProperties( - span, - out var resultKind, - out var timestamp, - out var name, - out var resultCode, - out var props, - out var traceId, - out var spanId, - out var parentId, - out var tracestate, - out var success, - out var duration); - - string data = null; - string target = null; - string type = null; - string userAgent = null; - - IAttributeValue spanKindAttr = null; - IAttributeValue errorAttr = null; - IAttributeValue httpStatusCodeAttr = null; - IAttributeValue httpMethodAttr = null; - IAttributeValue httpPathAttr = null; - IAttributeValue httpHostAttr = null; - IAttributeValue httpUrlAttr = null; - IAttributeValue httpUserAgentAttr = null; - IAttributeValue httpRouteAttr = null; - IAttributeValue httpPortAttr = null; - - foreach (var attr in span.Attributes.AttributeMap) - { - var key = attr.Key; - - switch (attr.Key) - { - case "span.kind": - spanKindAttr = attr.Value; - break; - case "error": - errorAttr = attr.Value; - break; - case "http.method": - httpMethodAttr = attr.Value; - break; - case "http.path": - httpPathAttr = attr.Value; - break; - case "http.host": - httpHostAttr = attr.Value; - break; - case "http.url": - httpUrlAttr = attr.Value; - break; - case "http.status_code": - httpStatusCodeAttr = attr.Value; - break; - case "http.user_agent": - httpUserAgentAttr = attr.Value; - break; - case "http.route": - httpRouteAttr = attr.Value; - break; - case "http.port": - httpPortAttr = attr.Value; - break; - default: - var value = attr.Value.Match( - (s) => { return s; }, - (b) => { return b.ToString(); }, - (l) => { return l.ToString(); }, - (d) => { return d.ToString(); }, - (obj) => { return obj.ToString(); }); - - AddPropertyWithAdjustedName(props, attr.Key, value); - - break; - } - } - - var linkId = 0; - foreach (var link in span.Links.Links) - { - AddPropertyWithAdjustedName(props, "link" + linkId + "_traceId", link.Context.TraceId.ToLowerBase16()); - AddPropertyWithAdjustedName(props, "link" + linkId + "_spanId", link.Context.SpanId.ToLowerBase16()); - - foreach (var attr in link.Attributes) - { - AddPropertyWithAdjustedName(props, "link" + linkId + "_" + attr.Key, attr.Value.Match((s) => s, (b) => b.ToString(), (l) => l.ToString(), (d) => d.ToString(), (obj) => obj.ToString())); - } + var key = attr.Key; - ++linkId; - } - - foreach (var t in span.Events.Events) + switch (attr.Key) { - var log = new TraceTelemetry(t.Event.Name); - - if (t.Timestamp != null) - { - var logTimestamp = DateTimeOffset.FromUnixTimeSeconds(t.Timestamp.Seconds); - logTimestamp = logTimestamp.Add(TimeSpan.FromTicks(t.Timestamp.Nanos / 100)); - log.Timestamp = logTimestamp; - } - - foreach (var attr in t.Event.Attributes) - { + case "span.kind": + spanKindAttr = attr.Value; + break; + case "error": + errorAttr = attr.Value; + break; + case "http.method": + httpMethodAttr = attr.Value; + break; + case "http.path": + httpPathAttr = attr.Value; + break; + case "http.host": + httpHostAttr = attr.Value; + break; + case "http.url": + httpUrlAttr = attr.Value; + break; + case "http.status_code": + httpStatusCodeAttr = attr.Value; + break; + case "http.user_agent": + httpUserAgentAttr = attr.Value; + break; + case "http.route": + httpRouteAttr = attr.Value; + break; + case "http.port": + httpPortAttr = attr.Value; + break; + default: var value = attr.Value.Match( (s) => { return s; }, (b) => { return b.ToString(); }, @@ -156,89 +114,132 @@ await Task.Run(async () => (d) => { return d.ToString(); }, (obj) => { return obj.ToString(); }); - AddPropertyWithAdjustedName(log.Properties, attr.Key, value); - } - - log.Context.Operation.Id = traceId; - log.Context.Operation.ParentId = string.Concat("|", traceId, ".", spanId, "."); + AddPropertyWithAdjustedName(props, attr.Key, value); - this.telemetryClient.Track(log); + break; } + } - this.OverwriteSpanKindFromAttribute(spanKindAttr, ref resultKind); - this.OverwriteErrorAttribute(errorAttr, ref success); - this.OverwriteFieldsForHttpSpans( - httpMethodAttr, - httpUrlAttr, - httpHostAttr, - httpPathAttr, - httpStatusCodeAttr, - httpUserAgentAttr, - httpRouteAttr, - httpPortAttr, - ref name, - ref resultCode, - ref data, - ref target, - ref type, - ref userAgent); - - // BUILDING resulting telemetry - OperationTelemetry result; - if (resultKind == SpanKind.Client || resultKind == SpanKind.Producer) - { - var resultD = new DependencyTelemetry(); - resultD.ResultCode = resultCode; - resultD.Data = data; - resultD.Target = target; - resultD.Type = type; + var linkId = 0; + foreach (var link in span.Links.Links) + { + AddPropertyWithAdjustedName(props, "link" + linkId + "_traceId", link.Context.TraceId.ToLowerBase16()); + AddPropertyWithAdjustedName(props, "link" + linkId + "_spanId", link.Context.SpanId.ToLowerBase16()); - result = resultD; - } - else + foreach (var attr in link.Attributes) { - var resultR = new RequestTelemetry(); - resultR.ResponseCode = resultCode; - Uri.TryCreate(data, UriKind.RelativeOrAbsolute, out var url); - resultR.Url = url; - result = resultR; + AddPropertyWithAdjustedName(props, "link" + linkId + "_" + attr.Key, attr.Value.Match((s) => s, (b) => b.ToString(), (l) => l.ToString(), (d) => d.ToString(), (obj) => obj.ToString())); } - result.Success = success; + ++linkId; + } - result.Timestamp = timestamp; - result.Name = name; - result.Context.Operation.Id = traceId; - result.Context.User.UserAgent = userAgent; + foreach (var t in span.Events.Events) + { + var log = new TraceTelemetry(t.Event.Name); - foreach (var prop in props) + if (t.Timestamp != null) { - AddPropertyWithAdjustedName(result.Properties, prop.Key, prop.Value); + var logTimestamp = DateTimeOffset.FromUnixTimeSeconds(t.Timestamp.Seconds); + logTimestamp = logTimestamp.Add(TimeSpan.FromTicks(t.Timestamp.Nanos / 100)); + log.Timestamp = logTimestamp; } - if (parentId != null) + foreach (var attr in t.Event.Attributes) { - result.Context.Operation.ParentId = string.Concat("|", traceId, ".", parentId, "."); + var value = attr.Value.Match( + (s) => { return s; }, + (b) => { return b.ToString(); }, + (l) => { return l.ToString(); }, + (d) => { return d.ToString(); }, + (obj) => { return obj.ToString(); }); + + AddPropertyWithAdjustedName(log.Properties, attr.Key, value); } - // TODO: I don't understant why this concatanation is required - result.Id = string.Concat("|", traceId, ".", spanId, "."); + log.Context.Operation.Id = traceId; + log.Context.Operation.ParentId = string.Concat("|", traceId, ".", spanId, "."); - foreach (var ts in tracestate.Entries) + this.telemetryClient.Track(log); + } + + this.OverwriteSpanKindFromAttribute(spanKindAttr, ref resultKind); + this.OverwriteErrorAttribute(errorAttr, ref success); + this.OverwriteFieldsForHttpSpans( + httpMethodAttr, + httpUrlAttr, + httpHostAttr, + httpPathAttr, + httpStatusCodeAttr, + httpUserAgentAttr, + httpRouteAttr, + httpPortAttr, + ref name, + ref resultCode, + ref data, + ref target, + ref type, + ref userAgent); + + // BUILDING resulting telemetry + OperationTelemetry result; + if (resultKind == SpanKind.Client || resultKind == SpanKind.Producer) + { + var resultD = new DependencyTelemetry { - result.Properties[ts.Key] = ts.Value; - } + ResultCode = resultCode, + Data = data, + Target = target, + Type = type, + }; + + result = resultD; + } + else + { + var resultR = new RequestTelemetry(); + resultR.ResponseCode = resultCode; + Uri.TryCreate(data, UriKind.RelativeOrAbsolute, out var url); + resultR.Url = url; + result = resultR; + } - result.Duration = duration; + result.Success = success; - // TODO: deal with those: - // span.ChildSpanCount - // span.Context.IsValid; - // span.Context.TraceOptions; + result.Timestamp = timestamp; + result.Name = name; + result.Context.Operation.Id = traceId; + result.Context.User.UserAgent = userAgent; - this.telemetryClient.Track(result); + foreach (var prop in props) + { + AddPropertyWithAdjustedName(result.Properties, prop.Key, prop.Value); + } + + if (parentId != null) + { + result.Context.Operation.ParentId = string.Concat("|", traceId, ".", parentId, "."); } - }); + + // TODO: I don't understant why this concatanation is required + result.Id = string.Concat("|", traceId, ".", spanId, "."); + + foreach (var ts in tracestate.Entries) + { + result.Properties[ts.Key] = ts.Value; + } + + result.Duration = duration; + + // TODO: deal with those: + // span.ChildSpanCount + // span.Context.IsValid; + // span.Context.TraceOptions; + + this.telemetryClient.Track(result); + } + + return Task.CompletedTask; } private static void AddPropertyWithAdjustedName(IDictionary props, string name, string value) diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Properties/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Properties/AssemblyInfo.cs index 3f468d95e04..c9f01a2a54b 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Properties/AssemblyInfo.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Properties/AssemblyInfo.cs @@ -16,8 +16,6 @@ using System.Runtime.CompilerServices; -[assembly: System.CLSCompliant(true)] - [assembly: InternalsVisibleTo("OpenTelemetry.Exporter.ApplicationInsights.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)] @@ -33,4 +31,4 @@ internal static class AssemblyInfo public const string PublicKey = ""; public const string MoqPublicKey = ""; } -#endif \ No newline at end of file +#endif diff --git a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs index f3c89488684..f325f82a926 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/Implementation/PrometheusMetricBuilder.cs @@ -28,14 +28,14 @@ internal class PrometheusMetricBuilder { public static readonly string ContentType = "text/plain; version = 0.0.4"; - private static char[] firstCharacterNameCharset = new char[] + private static readonly char[] FirstCharacterNameCharset = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', ':', }; - private static char[] nameCharset = new char[] + private static readonly char[] NameCharset = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', @@ -43,14 +43,14 @@ internal class PrometheusMetricBuilder '_', ':', }; - private static char[] firstCharacterLabelCharset = new char[] + private static readonly char[] FirstCharacterLabelCharset = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', }; - private static char[] labelCharset = new char[] + private static readonly char[] LabelCharset = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', @@ -211,7 +211,7 @@ private static string GetSafeMetricName(string name) if (!string.IsNullOrEmpty(name)) { var firstChar = name[0]; - if (firstCharacterNameCharset.Contains(firstChar)) + if (FirstCharacterNameCharset.Contains(firstChar)) { sb.Append(firstChar); } @@ -219,7 +219,7 @@ private static string GetSafeMetricName(string name) { firstChar = firstChar.ToString().ToLowerInvariant()[0]; - if (firstCharacterNameCharset.Contains(firstChar)) + if (FirstCharacterNameCharset.Contains(firstChar)) { sb.Append(firstChar); } @@ -235,7 +235,7 @@ private static string GetSafeMetricName(string name) { var c = name[i]; - if (nameCharset.Contains(c)) + if (NameCharset.Contains(c)) { sb.Append(c); } @@ -266,7 +266,7 @@ private static string GetSafeLabelName(string name) if (!string.IsNullOrEmpty(name)) { var firstChar = name[0]; - if (firstCharacterLabelCharset.Contains(firstChar)) + if (FirstCharacterLabelCharset.Contains(firstChar)) { sb.Append(firstChar); } @@ -274,7 +274,7 @@ private static string GetSafeLabelName(string name) { firstChar = firstChar.ToString().ToLowerInvariant()[0]; - if (firstCharacterLabelCharset.Contains(firstChar)) + if (FirstCharacterLabelCharset.Contains(firstChar)) { sb.Append(firstChar); } @@ -290,7 +290,7 @@ private static string GetSafeLabelName(string name) { var c = name[i]; - if (labelCharset.Contains(c)) + if (LabelCharset.Contains(c)) { sb.Append(c); } diff --git a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs index 5e653c2d81b..50898a4579c 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/PrometheusExporterOptions.cs @@ -16,8 +16,6 @@ namespace OpenTelemetry.Exporter.Prometheus { - using System; - /// /// Options to run prometheus exporter. /// diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/Constants.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/Constants.cs index d64bbf9e64e..d497c358df2 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/Constants.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/Constants.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,30 +20,30 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation internal class Constants { - public static readonly string PACKAGE_VERSION_UNDEFINED = "undefined"; + public static readonly string PackagVersionUndefined = "undefined"; - public static readonly string LABEL_DESCRIPTION = "OpenTelemetry TagKey"; - public static readonly string OpenTelemetry_TASK = "OpenTelemetry_task"; - public static readonly string OpenTelemetry_TASK_DESCRIPTION = "OpenTelemetry task identifier"; + public static readonly string LabelDescription = "OpenTelemetry TagKey"; + public static readonly string OpenTelemetryTask = "OpenTelemetry_task"; + public static readonly string OpenTelemetryTaskDescription = "OpenTelemetry task identifier"; - public static readonly string GCP_GKE_CONTAINER = "k8s_container"; - public static readonly string GCP_GCE_INSTANCE = "gce_instance"; - public static readonly string AWS_EC2_INSTANCE = "aws_ec2_instance"; - public static readonly string GLOBAL = "global"; + public static readonly string GcpGkeContainer = "k8s_container"; + public static readonly string GcpGceInstance = "gce_instance"; + public static readonly string AwsEc2Instance = "aws_ec2_instance"; + public static readonly string Global = "global"; - public static readonly string PROJECT_ID_LABEL_KEY = "project_id"; - public static readonly string OpenTelemetry_TASK_VALUE_DEFAULT = GenerateDefaultTaskValue(); + public static readonly string ProjectIdLabelKey = "project_id"; + public static readonly string OpenTelemetryTaskValueDefault = GenerateDefaultTaskValue(); - public static readonly string GCP_GCE_INSTANCE_TYPE = "cloud.google.com/gce/instance"; - public static readonly string GCP_INSTANCE_ID_KEY = "cloud.google.com/gce/instance_id"; - public static readonly string GCP_ACCOUNT_ID_KEY = "cloud.google.com/gce/project_id"; - public static readonly string GCP_ZONE_KEY = "cloud.google.com/gce/zone"; + public static readonly string GceGcpInstanceType = "cloud.google.com/gce/instance"; + public static readonly string GcpInstanceIdKey = "cloud.google.com/gce/instance_id"; + public static readonly string GcpAccountIdKey = "cloud.google.com/gce/project_id"; + public static readonly string GcpZoneKey = "cloud.google.com/gce/zone"; - public static readonly string K8S_CONTAINER_TYPE = "k8s.io/container"; - public static readonly string K8S_CLUSTER_NAME_KEY = "k8s.io/cluster/name"; - public static readonly string K8S_CONTAINER_NAME_KEY = "k8s.io/container/name"; - public static readonly string K8S_NAMESPACE_NAME_KEY = "k8s.io/namespace/name"; - public static readonly string K8S_POD_NAME_KEY = "k8s.io/pod/name"; + public static readonly string K8sContainerType = "k8s.io/container"; + public static readonly string K8sClusterNameKey = "k8s.io/cluster/name"; + public static readonly string K8sContainerNameKey = "k8s.io/container/name"; + public static readonly string K8sNamespaceNameKey = "k8s.io/namespace/name"; + public static readonly string K8sPodNameKey = "k8s.io/pod/name"; private static string GenerateDefaultTaskValue() { @@ -51,4 +51,4 @@ private static string GenerateDefaultTaskValue() return $"dotnet-{System.Diagnostics.Process.GetCurrentProcess().Id}@{Environment.MachineName}"; } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs index 74f5fca2fcb..de2efbebc84 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/GoogleCloudResourceUtils.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,13 +16,12 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation { - using Google.Api; using System; - using System.Collections.Generic; using System.IO; + using Google.Api; /// - /// Utility methods for working with Google Cloud Resources + /// Utility methods for working with Google Cloud Resources. /// public static class GoogleCloudResourceUtils { @@ -30,9 +29,9 @@ public static class GoogleCloudResourceUtils /// Detects Google Cloud ProjectId based on the environment on which the code runs. /// Supports GCE/GKE/GAE and projectId tied to service account /// In case the code runs in a different environment, - /// the method returns null + /// the method returns null. /// - /// Google Cloud Project ID + /// Google Cloud Project ID. public static string GetProjectId() { // Try to detect projectId from the environment where the code is running @@ -59,14 +58,15 @@ public static string GetProjectId() } /// - /// Determining the resource to which the metrics belong + /// Determining the resource to which the metrics belong. /// - /// Stackdriver Monitored Resource + /// The project id. + /// Stackdriver Monitored Resource. public static MonitoredResource GetDefaultResource(string projectId) { var resource = new MonitoredResource(); - resource.Type = Constants.GLOBAL; - resource.Labels.Add(Constants.PROJECT_ID_LABEL_KEY, projectId); + resource.Type = Constants.Global; + resource.Labels.Add(Constants.ProjectIdLabelKey, projectId); // TODO - zeltser - setting monitored resource labels for detected resource // along with all the other metadata @@ -74,4 +74,4 @@ public static MonitoredResource GetDefaultResource(string projectId) return resource; } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs index 5376b3f9ad7..7bed6c09936 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation { + using System.Collections.Generic; using Google.Api; using Google.Cloud.Monitoring.V3; using Google.Protobuf.WellKnownTypes; @@ -24,20 +25,19 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; - using System.Collections.Generic; using static Google.Api.Distribution.Types; using static Google.Api.MetricDescriptor.Types; /// - /// Conversion methods from OpenTelemetry Stats API to Stackdriver Metrics API + /// Conversion methods from OpenTelemetry Stats API to Stackdriver Metrics API. /// internal static class MetricsConversions { /// - /// Converts between OpenTelemetry aggregation and Stackdriver metric kind + /// Converts between OpenTelemetry aggregation and Stackdriver metric kind. /// - /// Stats Aggregation - /// Stackdriver Metric Kind + /// Stats Aggregation. + /// Stackdriver Metric Kind. public static MetricKind ToMetricKind( this IAggregation aggregation) { @@ -51,17 +51,19 @@ public static MetricKind ToMetricKind( } /// - /// Converts from OpenTelemetry Measure+Aggregation to Stackdriver's ValueType + /// Converts from OpenTelemetry Measure+Aggregation to Stackdriver's ValueType. /// - /// OpenTelemetry Measure definition - /// OpenTelemetry Aggregation definition - /// + /// OpenTelemetry Measure definition. + /// OpenTelemetry Aggregation definition. + /// . public static ValueType ToValueType( this IMeasure measure, IAggregation aggregation) { var metricKind = aggregation.ToMetricKind(); if (aggregation is IDistribution && (metricKind == MetricKind.Cumulative || metricKind == MetricKind.Gauge)) + { return ValueType.Distribution; + } if (measure is IMeasureDouble && (metricKind == MetricKind.Cumulative || metricKind == MetricKind.Gauge)) { @@ -82,7 +84,7 @@ public static LabelDescriptor ToLabelDescriptor(this TagKey tagKey) var labelDescriptor = new LabelDescriptor(); labelDescriptor.Key = GetStackdriverLabelKey(tagKey.Name); - labelDescriptor.Description = Constants.LABEL_DESCRIPTION; + labelDescriptor.Description = Constants.LabelDescription; // TODO - zeltser - Now we only support string tags labelDescriptor.ValueType = LabelDescriptor.Types.ValueType.String; @@ -101,21 +103,21 @@ public static Google.Api.Distribution CreateDistribution( Count = distributionData.Count, Mean = distributionData.Mean, SumOfSquaredDeviation = distributionData.SumOfSquaredDeviations, - Range = new Range { Max = distributionData.Max, Min = distributionData.Min } + Range = new Range { Max = distributionData.Max, Min = distributionData.Min }, }; return distribution; } /// - /// Creates Stackdriver MetricDescriptor from OpenTelemetry View + /// Creates Stackdriver MetricDescriptor from OpenTelemetry View. /// - /// Metric Descriptor full type name - /// OpenTelemetry View - /// Google Cloud Project Name - /// - /// - /// + /// Metric Descriptor full type name. + /// OpenTelemetry View. + /// Google Cloud Project Name. + /// The Domain. + /// Display Name Prefix. + /// . public static MetricDescriptor CreateMetricDescriptor( string metricDescriptorTypeName, IView view, @@ -136,11 +138,12 @@ public static MetricDescriptor CreateMetricDescriptor( var labelDescriptor = tagKey.ToLabelDescriptor(); metricDescriptor.Labels.Add(labelDescriptor); } + metricDescriptor.Labels.Add( new LabelDescriptor { - Key = Constants.OpenTelemetry_TASK, - Description = Constants.OpenTelemetry_TASK_DESCRIPTION, + Key = Constants.OpenTelemetryTask, + Description = Constants.OpenTelemetryTaskDescription, ValueType = LabelDescriptor.Types.ValueType.String, }); @@ -161,59 +164,22 @@ public static TypedValue CreateTypedValue( v => new TypedValue { Int64Value = v.Sum }, // Long v => new TypedValue { Int64Value = v.Count }, // Count v => new TypedValue { DoubleValue = v.Count }, // Mean - v => new TypedValue { DistributionValue = CreateDistribution(v, ((IDistribution)aggregation).BucketBoundaries) }, //Distribution + v => new TypedValue { DistributionValue = CreateDistribution(v, ((IDistribution)aggregation).BucketBoundaries) }, // Distribution v => new TypedValue { DoubleValue = v.LastValue }, // LastValue Double v => new TypedValue { Int64Value = v.LastValue }, // LastValue Long v => new TypedValue { BoolValue = false }); // Default } - /// - /// Create a list of counts for Stackdriver from the list of counts in OpenTelemetry - /// - /// OpenTelemetry list of counts - /// - private static IEnumerable CreateBucketCounts(IReadOnlyList bucketCounts) - { - // The first bucket (underflow bucket) should always be 0 count because the Metrics first bucket - // is [0, first_bound) but Stackdriver distribution consists of an underflow bucket (number 0). - var ret = new List(); - ret.Add(0L); - ret.AddRange(bucketCounts); - return ret; - } - - /// - /// Converts to Stackdriver's - /// - /// - /// - private static BucketOptions ToBucketOptions(this IBucketBoundaries bucketBoundaries) - { - // The first bucket bound should be 0.0 because the Metrics first bucket is - // [0, first_bound) but Stackdriver monitoring bucket bounds begin with -infinity - // (first bucket is (-infinity, 0)) - var bucketOptions = new BucketOptions - { - ExplicitBuckets = new BucketOptions.Types.Explicit - { - Bounds = { 0.0 } - } - }; - bucketOptions.ExplicitBuckets.Bounds.AddRange(bucketBoundaries.Boundaries); - - return bucketOptions; - } - // Create a Metric using the TagKeys and TagValues. /// - /// Generate Stackdriver Metric from OpenTelemetry View + /// Generate Stackdriver Metric from OpenTelemetry View. /// - /// - /// - /// Stackdriver Metric Descriptor - /// - /// + /// A . + /// A list of . + /// Stackdriver Metric Descriptor. + /// The domain. + /// . public static Metric GetMetric( IView view, IReadOnlyList tagValues, @@ -238,7 +204,8 @@ public static Metric GetMetric( var labelKey = GetStackdriverLabelKey(key.Name); metric.Labels.Add(labelKey, value.AsString); } - metric.Labels.Add(Constants.OpenTelemetry_TASK, Constants.OpenTelemetry_TASK_VALUE_DEFAULT); + + metric.Labels.Add(Constants.OpenTelemetryTask, Constants.OpenTelemetryTaskValueDefault); // TODO - zeltser - make sure all the labels from the metric descriptor were fulfilled return metric; @@ -247,11 +214,11 @@ public static Metric GetMetric( /// /// Convert ViewData to a list of TimeSeries, so that ViewData can be uploaded to Stackdriver. /// - /// OpenTelemetry View - /// Stackdriver Metric Descriptor - /// Stackdriver Resource to which the metrics belong - /// The metrics domain (namespace) - /// + /// OpenTelemetry View. + /// Stackdriver Resource to which the metrics belong. + /// Stackdriver Metric Descriptor. + /// The metrics domain (namespace). + /// . public static List CreateTimeSeriesList( IViewData viewData, MonitoredResource monitoredResource, @@ -290,6 +257,31 @@ public static List CreateTimeSeriesList( return timeSeriesList; } + internal static string GetUnit(IAggregation aggregation, IMeasure measure) + { + if (aggregation is ICount) + { + return "1"; + } + + return measure.Unit; + } + + internal static string GetDisplayName(string viewName, string displayNamePrefix) + { + return displayNamePrefix + viewName; + } + + /// + /// Creates Stackdriver Label name. + /// + /// OpenTelemetry label. + /// Label name that complies with Stackdriver label naming rules. + internal static string GetStackdriverLabelKey(string label) + { + return label.Replace('/', '_'); + } + private static Point ExtractPointInInterval( System.DateTimeOffset startTime, System.DateTimeOffset endTime, @@ -299,38 +291,50 @@ private static Point ExtractPointInInterval( return new Point { Value = CreateTypedValue(aggregation, points), - Interval = CreateTimeInterval(startTime, endTime) + Interval = CreateTimeInterval(startTime, endTime), }; } - private static TimeInterval CreateTimeInterval(System.DateTimeOffset start, System.DateTimeOffset end) + /// + /// Create a list of counts for Stackdriver from the list of counts in OpenTelemetry. + /// + /// OpenTelemetry list of counts. + /// . + private static IEnumerable CreateBucketCounts(IReadOnlyList bucketCounts) { - return new TimeInterval { StartTime = start.ToTimestamp(), EndTime = end.ToTimestamp() }; + // The first bucket (underflow bucket) should always be 0 count because the Metrics first bucket + // is [0, first_bound) but Stackdriver distribution consists of an underflow bucket (number 0). + var ret = new List(); + ret.Add(0L); + ret.AddRange(bucketCounts); + return ret; } - internal static string GetUnit(IAggregation aggregation, IMeasure measure) + /// + /// Converts to Stackdriver's . + /// + /// A representing the bucket boundaries. + /// . + private static BucketOptions ToBucketOptions(this IBucketBoundaries bucketBoundaries) { - if (aggregation is ICount) + // The first bucket bound should be 0.0 because the Metrics first bucket is + // [0, first_bound) but Stackdriver monitoring bucket bounds begin with -infinity + // (first bucket is (-infinity, 0)) + var bucketOptions = new BucketOptions { - return "1"; - } - - return measure.Unit; - } + ExplicitBuckets = new BucketOptions.Types.Explicit + { + Bounds = { 0.0 }, + }, + }; + bucketOptions.ExplicitBuckets.Bounds.AddRange(bucketBoundaries.Boundaries); - internal static string GetDisplayName(string viewName, string displayNamePrefix) - { - return displayNamePrefix + viewName; + return bucketOptions; } - /// - /// Creates Stackdriver Label name - /// - /// OpenTelemetry label - /// Label name that complies with Stackdriver label naming rules - internal static string GetStackdriverLabelKey(string label) + private static TimeInterval CreateTimeInterval(System.DateTimeOffset start, System.DateTimeOffset end) { - return label.Replace('/', '_'); + return new TimeInterval { StartTime = start.ToTimestamp(), EndTime = end.ToTimestamp() }; } } } diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs new file mode 100644 index 00000000000..f7ac0d61145 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs @@ -0,0 +1,121 @@ +// +// 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.Exporter.Stackdriver.Implementation +{ + using System.Linq; + using Google.Cloud.Trace.V2; + using OpenTelemetry.Exporter.Stackdriver.Utils; + using OpenTelemetry.Trace; + + internal static class SpanExtensions + { + /// + /// Translating to Stackdriver's Span + /// According to specifications. + /// + /// Span in OpenTelemetry format. + /// Google Cloud Platform Project Id. + /// . + public static Google.Cloud.Trace.V2.Span ToSpan(this SpanData spanData, string projectId) + { + var spanId = spanData.Context.SpanId.ToLowerBase16(); + + // Base span settings + var span = new Google.Cloud.Trace.V2.Span + { + SpanName = new SpanName(projectId, spanData.Context.TraceId.ToLowerBase16(), spanId), + SpanId = spanId, + DisplayName = new TruncatableString { Value = spanData.Name }, + StartTime = spanData.StartTimestamp.ToTimestamp(), + EndTime = spanData.EndTimestamp.ToTimestamp(), + ChildSpanCount = spanData.ChildSpanCount, + }; + if (spanData.ParentSpanId != null) + { + var parentSpanId = spanData.ParentSpanId.ToLowerBase16(); + if (!string.IsNullOrEmpty(parentSpanId)) + { + span.ParentSpanId = parentSpanId; + } + } + + // Span Links + if (spanData.Links != null) + { + span.Links = new Google.Cloud.Trace.V2.Span.Types.Links + { + DroppedLinksCount = spanData.Links.DroppedLinksCount, + Link = { spanData.Links.Links.Select(l => l.ToLink()) }, + }; + } + + // Span Attributes + if (spanData.Attributes != null) + { + span.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes + { + DroppedAttributesCount = spanData.Attributes != null ? spanData.Attributes.DroppedAttributesCount : 0, + + AttributeMap = + { + spanData.Attributes?.AttributeMap?.ToDictionary( + s => s.Key, + s => s.Value?.ToAttributeValue()), + }, + }; + } + + return span; + } + + public static Google.Cloud.Trace.V2.Span.Types.Link ToLink(this ILink link) + { + var ret = new Google.Cloud.Trace.V2.Span.Types.Link(); + ret.SpanId = link.Context.SpanId.ToLowerBase16(); + ret.TraceId = link.Context.TraceId.ToLowerBase16(); + + if (link.Attributes != null) + { + ret.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes + { + DroppedAttributesCount = OpenTelemetry.Trace.Config.TraceParams.Default.MaxNumberOfAttributes - link.Attributes.Count, + + AttributeMap = + { + link.Attributes.ToDictionary( + att => att.Key, + att => att.Value.ToAttributeValue()), + }, + }; + } + + return ret; + } + + public static Google.Cloud.Trace.V2.AttributeValue ToAttributeValue(this IAttributeValue av) + { + var ret = av.Match( + (s) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = s } }, + (b) => new Google.Cloud.Trace.V2.AttributeValue() { BoolValue = b }, + (l) => new Google.Cloud.Trace.V2.AttributeValue() { IntValue = l }, + (d) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = d.ToString() } }, + (obj) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = obj.ToString() } }); + + return ret; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsConfiguration.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsConfiguration.cs index 8a5e9072426..537c4aedfac 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsConfiguration.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsConfiguration.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,62 +16,62 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation { + using System; using Google.Api; using Google.Apis.Auth.OAuth2; - using System; /// - /// Configuration for exporting stats into Stackdriver + /// Configuration for exporting stats into Stackdriver. /// public class StackdriverStatsConfiguration { - private static readonly TimeSpan DEFAULT_INTERVAL = TimeSpan.FromMinutes(1); + private static readonly TimeSpan DefaultInterval = TimeSpan.FromMinutes(1); + + /// + /// Gets default Stats Configuration for Stackdriver. + /// + public static StackdriverStatsConfiguration Default + { + get + { + var defaultConfig = new StackdriverStatsConfiguration + { + ExportInterval = DefaultInterval, + ProjectId = GoogleCloudResourceUtils.GetProjectId(), + MetricNamePrefix = string.Empty, + }; + + defaultConfig.MonitoredResource = GoogleCloudResourceUtils.GetDefaultResource(defaultConfig.ProjectId); + return defaultConfig; + } + } /// - /// Frequency of the export operation + /// Gets or sets frequency of the export operation. /// public TimeSpan ExportInterval { get; set; } /// - /// The prefix to append to every OpenTelemetry metric name in Stackdriver + /// Gets or sets the prefix to append to every OpenTelemetry metric name in Stackdriver. /// public string MetricNamePrefix { get; set; } /// - /// Google Cloud Project Id + /// Gets or sets google Cloud Project Id. /// public string ProjectId { get; set; } /// - /// Credential used to authenticate against Google Stackdriver Monitoring APIs + /// Gets or sets credential used to authenticate against Google Stackdriver Monitoring APIs. /// public GoogleCredential GoogleCredential { get; set; } /// - /// Monitored Resource associated with metrics collection. + /// Gets or sets monitored Resource associated with metrics collection. /// By default, the exporter detects the environment where the export is happening, /// such as GKE/AWS/GCE. If the exporter is running on a different environment, /// monitored resource will be identified as "general". /// public MonitoredResource MonitoredResource { get; set; } - - /// - /// Default Stats Configuration for Stackdriver - /// - public static StackdriverStatsConfiguration Default - { - get - { - var defaultConfig = new StackdriverStatsConfiguration - { - ExportInterval = DEFAULT_INTERVAL, - ProjectId = GoogleCloudResourceUtils.GetProjectId(), - MetricNamePrefix = string.Empty, - }; - - defaultConfig.MonitoredResource = GoogleCloudResourceUtils.GetDefaultResource(defaultConfig.ProjectId); - return defaultConfig; - } - } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs index bcee64904f0..874333d3bd7 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverStatsExporter.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,13 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Reflection; + using System.Threading; + using System.Threading.Tasks; using Google.Api; using Google.Api.Gax; using Google.Api.Gax.Grpc; @@ -25,13 +32,6 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation using Grpc.Core; using OpenTelemetry.Exporter.Stackdriver.Utils; using OpenTelemetry.Stats; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Reflection; - using System.Threading; - using System.Threading.Tasks; internal class StackdriverStatsExporter { @@ -45,31 +45,48 @@ internal class StackdriverStatsExporter private MetricServiceClient metricServiceClient; private CancellationTokenSource tokenSource; - private const int MAX_BATCH_EXPORT_SIZE = 200; - private static readonly string DEFAULT_DISPLAY_NAME_PREFIX = "OpenTelemetry/"; - private static readonly string CUSTOM_METRIC_DOMAIN = "custom.googleapis.com/"; - private static readonly string CUSTOM_OpenTelemetry_DOMAIN = CUSTOM_METRIC_DOMAIN + "OpenTelemetry/"; +#pragma warning disable SA1203 // Sensible grouping is more important than ordering by accessability +#pragma warning disable SA1214 // Readonly fields should appear before non-readonly fields + private const int MaxBatchExportSize = 200; + private static readonly string DefaultDisplayNamePrefix = "OpenTelemetry/"; + private static readonly string CustomMetricsDomain = "custom.googleapis.com/"; + private static readonly string CustomOpenTelemetryDomain = CustomMetricsDomain + "OpenTelemetry/"; - private static readonly string USER_AGENT_KEY = "user-agent"; - private static string USER_AGENT; + private static readonly string UserAgentKey = "user-agent"; + private static readonly string UserAgent; private readonly string domain; private readonly string displayNamePrefix; private bool isStarted; - /// - /// Interval between two subsequent stats collection operations - /// - private TimeSpan collectionInterval = TimeSpan.FromMinutes(1); + /// + /// Interval between two subsequent stats collection operations. + /// + private readonly TimeSpan collectionInterval = TimeSpan.FromMinutes(1); /// /// Interval within which the cancellation should be honored - /// from the point it was requested + /// from the point it was requested. /// private readonly TimeSpan cancellationInterval = TimeSpan.FromSeconds(3); - private object locker = new object(); + private readonly object locker = new object(); +#pragma warning restore SA1203 // Constants should appear before fields +#pragma warning restore SA1214 // Sensible grouping is more important than ordering by accessability + + static StackdriverStatsExporter() + { + try + { + var assemblyPackageVersion = typeof(StackdriverStatsExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; + UserAgent = $"OpenTelemetry-dotnet/{assemblyPackageVersion}"; + } + catch (Exception) + { + UserAgent = $"OpenTelemetry-dotnet/{Constants.PackagVersionUndefined}"; + } + } public StackdriverStatsExporter( IViewManager viewManager, @@ -84,89 +101,127 @@ public StackdriverStatsExporter( message: "Export interval can't be zero. Typically it's 1 minute"); this.viewManager = viewManager; - monitoredResource = configuration.MonitoredResource; - collectionInterval = configuration.ExportInterval; - project = new ProjectName(configuration.ProjectId); - credential = configuration.GoogleCredential; + this.monitoredResource = configuration.MonitoredResource; + this.collectionInterval = configuration.ExportInterval; + this.project = new ProjectName(configuration.ProjectId); + this.credential = configuration.GoogleCredential; - domain = GetDomain(configuration.MetricNamePrefix); - displayNamePrefix = GetDisplayNamePrefix(configuration.MetricNamePrefix); - } - - static StackdriverStatsExporter() - { - try - { - var assemblyPackageVersion = typeof(StackdriverStatsExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; - USER_AGENT = $"OpenTelemetry-dotnet/{assemblyPackageVersion}"; - } - catch (Exception) - { - USER_AGENT = $"OpenTelemetry-dotnet/{Constants.PACKAGE_VERSION_UNDEFINED}"; - } + this.domain = GetDomain(configuration.MetricNamePrefix); + this.displayNamePrefix = this.GetDisplayNamePrefix(configuration.MetricNamePrefix); } public void Start() { - lock (locker) + lock (this.locker) { - if (!isStarted) + if (!this.isStarted) { - tokenSource = new CancellationTokenSource(); - metricServiceClient = CreateMetricServiceClient(credential, tokenSource); + this.tokenSource = new CancellationTokenSource(); + this.metricServiceClient = CreateMetricServiceClient(this.credential, this.tokenSource); - Task.Factory.StartNew(DoWork, tokenSource.Token); + Task.Factory.StartNew(this.DoWork, this.tokenSource.Token); - isStarted = true; + this.isStarted = true; } } } public void Stop() { - lock (locker) + lock (this.locker) { - if (!isStarted) + if (!this.isStarted) { return; } - tokenSource.Cancel(); + this.tokenSource.Cancel(); + } + } + + private static MetricServiceClient CreateMetricServiceClient(GoogleCredential credential, CancellationTokenSource tokenSource) + { + // Make sure to add OpenTelemetry header to every outgoing call to Stackdriver APIs + Action addOpenTelemetryHeader = m => m.Add(UserAgentKey, UserAgent); + var callSettings = new CallSettings( + cancellationToken: tokenSource.Token, + credentials: null, + timing: null, + headerMutation: addOpenTelemetryHeader, + writeOptions: WriteOptions.Default, + propagationToken: null); + + var channel = new Channel( + MetricServiceClient.DefaultEndpoint.ToString(), + credential.ToChannelCredentials()); + + var metricServiceSettings = new MetricServiceSettings() + { + CallSettings = callSettings, + }; + + return MetricServiceClient.Create(channel, settings: metricServiceSettings); + } + + private static string GetDomain(string metricNamePrefix) + { + string domain; + if (string.IsNullOrEmpty(metricNamePrefix)) + { + domain = CustomOpenTelemetryDomain; + } + else + { + if (!metricNamePrefix.EndsWith("/")) + { + domain = metricNamePrefix + '/'; + } + else + { + domain = metricNamePrefix; + } } + + return domain; + } + + private static string GenerateMetricDescriptorTypeName(IViewName viewName, string domain) + { + return domain + viewName.AsString; } /// /// Periodic operation happening on a dedicated thread that is - /// capturing the metrics collected within a collection interval + /// capturing the metrics collected within a collection interval. /// private void DoWork() { try { - var sleepTime = collectionInterval; + var sleepTime = this.collectionInterval; var stopWatch = new Stopwatch(); - while (!tokenSource.IsCancellationRequested) + while (!this.tokenSource.IsCancellationRequested) { // Calculate the duration of collection iteration stopWatch.Start(); // Collect metrics - Export(); + this.Export(); stopWatch.Stop(); // Adjust the wait time - reduce export operation duration - sleepTime = collectionInterval.Subtract(stopWatch.Elapsed); + sleepTime = this.collectionInterval.Subtract(stopWatch.Elapsed); sleepTime = sleepTime.Duration(); // If the cancellation was requested, we should honor // that within the cancellation interval, so we wait in // intervals of - while (sleepTime > cancellationInterval && !tokenSource.IsCancellationRequested) + while (sleepTime > this.cancellationInterval && !this.tokenSource.IsCancellationRequested) { - Thread.Sleep(cancellationInterval); - sleepTime = sleepTime.Subtract(cancellationInterval); + Thread.Sleep(this.cancellationInterval); + sleepTime = sleepTime.Subtract(this.cancellationInterval); } Thread.Sleep(sleepTime); @@ -181,14 +236,15 @@ private void DoWork() private bool RegisterView(IView view) { IView existing = null; - if (registeredViews.TryGetValue(view.Name, out existing)) + if (this.registeredViews.TryGetValue(view.Name, out existing)) { // Ignore views that are already registered. return existing.Equals(view); } - registeredViews.Add(view.Name, view); - var metricDescriptorTypeName = GenerateMetricDescriptorTypeName(view.Name, domain); + this.registeredViews.Add(view.Name, view); + + var metricDescriptorTypeName = GenerateMetricDescriptorTypeName(view.Name, this.domain); // TODO - zeltser: don't need to create MetricDescriptor for RpcViewConstants once we defined // canonical metrics. Registration is required only for custom view definitions. Canonical @@ -196,9 +252,9 @@ private bool RegisterView(IView view) var metricDescriptor = MetricsConversions.CreateMetricDescriptor( metricDescriptorTypeName, view, - project, - domain, - displayNamePrefix); + this.project, + this.domain, + this.displayNamePrefix); if (metricDescriptor == null) { @@ -207,11 +263,12 @@ private bool RegisterView(IView view) } // Cache metric descriptor and ensure it exists in Stackdriver - if (!metricDescriptors.ContainsKey(view)) + if (!this.metricDescriptors.ContainsKey(view)) { - metricDescriptors.Add(view, metricDescriptor); + this.metricDescriptors.Add(view, metricDescriptor); } - return EnsureMetricDescriptorExists(metricDescriptor); + + return this.EnsureMetricDescriptorExists(metricDescriptor); } private bool EnsureMetricDescriptorExists(MetricDescriptor metricDescriptor) @@ -219,9 +276,9 @@ private bool EnsureMetricDescriptorExists(MetricDescriptor metricDescriptor) try { var request = new CreateMetricDescriptorRequest(); - request.ProjectName = project; + request.ProjectName = this.project; request.MetricDescriptor = metricDescriptor; - metricServiceClient.CreateMetricDescriptor(request); + this.metricServiceClient.CreateMetricDescriptor(request); } catch (RpcException e) { @@ -240,11 +297,11 @@ private bool EnsureMetricDescriptorExists(MetricDescriptor metricDescriptor) private void Export() { var viewDataList = new List(); - foreach (var view in viewManager.AllExportedViews) + foreach (var view in this.viewManager.AllExportedViews) { - if (RegisterView(view)) + if (this.RegisterView(view)) { - var data = viewManager.GetView(view.Name); + var data = this.viewManager.GetView(view.Name); viewDataList.Add(data); } } @@ -253,21 +310,21 @@ private void Export() var timeSeriesList = new List(); foreach (var viewData in viewDataList) { - var metricDescriptor = metricDescriptors[viewData.View]; - var timeSeries = MetricsConversions.CreateTimeSeriesList(viewData, monitoredResource, metricDescriptor, domain); + var metricDescriptor = this.metricDescriptors[viewData.View]; + var timeSeries = MetricsConversions.CreateTimeSeriesList(viewData, this.monitoredResource, metricDescriptor, this.domain); timeSeriesList.AddRange(timeSeries); } // Perform the operation in batches of MAX_BATCH_EXPORT_SIZE - foreach (var batchedTimeSeries in timeSeriesList.Partition(MAX_BATCH_EXPORT_SIZE)) + foreach (var batchedTimeSeries in timeSeriesList.Partition(MaxBatchExportSize)) { var request = new CreateTimeSeriesRequest(); - request.ProjectName = project; + request.ProjectName = this.project; request.TimeSeries.AddRange(batchedTimeSeries); try { - metricServiceClient.CreateTimeSeries(request); + this.metricServiceClient.CreateTimeSeries(request); } catch (RpcException e) { @@ -276,56 +333,11 @@ private void Export() } } - private static MetricServiceClient CreateMetricServiceClient(GoogleCredential credential, CancellationTokenSource tokenSource) - { - // Make sure to add OpenTelemetry header to every outgoing call to Stackdriver APIs - Action addOpenTelemetryHeader = m => m.Add(USER_AGENT_KEY, USER_AGENT); - var callSettings = new CallSettings( - cancellationToken: tokenSource.Token, - credentials: null, - timing: null, - headerMutation: addOpenTelemetryHeader, - writeOptions: WriteOptions.Default, - propagationToken: null); - - var channel = new Channel( - MetricServiceClient.DefaultEndpoint.ToString(), - credential.ToChannelCredentials()); - - var metricServiceSettings = new MetricServiceSettings() - { - CallSettings = callSettings - }; - - return MetricServiceClient.Create(channel, settings: metricServiceSettings); - } - - private static string GetDomain(string metricNamePrefix) - { - string domain; - if (string.IsNullOrEmpty(metricNamePrefix)) - { - domain = CUSTOM_OpenTelemetry_DOMAIN; - } - else - { - if (!metricNamePrefix.EndsWith("/")) - { - domain = metricNamePrefix + '/'; - } - else - { - domain = metricNamePrefix; - } - } - return domain; - } - private string GetDisplayNamePrefix(string metricNamePrefix) { if (metricNamePrefix == null) { - return DEFAULT_DISPLAY_NAME_PREFIX; + return DefaultDisplayNamePrefix; } else { @@ -333,30 +345,34 @@ private string GetDisplayNamePrefix(string metricNamePrefix) { metricNamePrefix += '/'; } + return metricNamePrefix; } } - private static string GenerateMetricDescriptorTypeName(IViewName viewName, string domain) - { - return domain + viewName.AsString; - } - /// - /// Comparison between two OpenTelemetry Views + /// Comparison between two OpenTelemetry Views. /// private class ViewNameComparer : IEqualityComparer { public bool Equals(IView x, IView y) { if (x == null && y == null) + { return true; + } else if (x == null || y == null) + { return false; + } else if (x.Name.AsString.Equals(y.Name.AsString)) + { return true; + } else + { return false; + } } public int GetHashCode(IView obj) diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs index da6e0f85057..44cc6998355 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/StackdriverTraceExporter.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,165 +28,71 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation using OpenTelemetry.Trace; using OpenTelemetry.Trace.Export; - static class SpanExtensions - { - /// - /// Translating to Stackdriver's Span - /// According to specifications - /// - /// Span in OpenTelemetry format - /// Google Cloud Platform Project Id - /// - public static Google.Cloud.Trace.V2.Span ToSpan(this SpanData spanData, string projectId) - { - var spanId = spanData.Context.SpanId.ToLowerBase16(); - - // Base span settings - var span = new Google.Cloud.Trace.V2.Span - { - SpanName = new SpanName(projectId, spanData.Context.TraceId.ToLowerBase16(), spanId), - SpanId = spanId, - DisplayName = new TruncatableString { Value = spanData.Name }, - StartTime = spanData.StartTimestamp.ToTimestamp(), - EndTime = spanData.EndTimestamp.ToTimestamp(), - ChildSpanCount = spanData.ChildSpanCount, - }; - if (spanData.ParentSpanId != null) - { - var parentSpanId = spanData.ParentSpanId.ToLowerBase16(); - if (!string.IsNullOrEmpty(parentSpanId)) - { - span.ParentSpanId = parentSpanId; - } - } - - // Span Links - if (spanData.Links != null) - { - span.Links = new Google.Cloud.Trace.V2.Span.Types.Links - { - DroppedLinksCount = spanData.Links.DroppedLinksCount, - Link = { spanData.Links.Links.Select(l => l.ToLink()) } - }; - } - - // Span Attributes - if (spanData.Attributes != null) - { - span.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes - { - DroppedAttributesCount = spanData.Attributes != null ? spanData.Attributes.DroppedAttributesCount : 0, - - AttributeMap = { spanData.Attributes?.AttributeMap?.ToDictionary( - s => s.Key, - s => s.Value?.ToAttributeValue()) }, - }; - } - - return span; - } - - public static Google.Cloud.Trace.V2.Span.Types.Link ToLink(this ILink link) - { - var ret = new Google.Cloud.Trace.V2.Span.Types.Link(); - ret.SpanId = link.Context.SpanId.ToLowerBase16(); - ret.TraceId = link.Context.TraceId.ToLowerBase16(); - - if (link.Attributes != null) - { - ret.Attributes = new Google.Cloud.Trace.V2.Span.Types.Attributes - { - - DroppedAttributesCount = OpenTelemetry.Trace.Config.TraceParams.Default.MaxNumberOfAttributes - link.Attributes.Count, - - AttributeMap = { link.Attributes.ToDictionary( - att => att.Key, - att => att.Value.ToAttributeValue()) } - }; - } - - return ret; - } - - public static Google.Cloud.Trace.V2.AttributeValue ToAttributeValue(this IAttributeValue av) - { - var ret = av.Match( - (s) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = s } }, - (b) => new Google.Cloud.Trace.V2.AttributeValue() { BoolValue = b }, - (l) => new Google.Cloud.Trace.V2.AttributeValue() { IntValue = l }, - (d) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = d.ToString() } }, - (obj) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = obj.ToString() } }); - - return ret; - } - } - /// - /// Exports a group of spans to Stackdriver + /// Exports a group of spans to Stackdriver. /// internal class StackdriverTraceExporter : IHandler { - private static string STACKDRIVER_EXPORTER_VERSION; - private static string OpenTelemetry_EXPORTER_VERSION; + private static readonly string StackdriverExportVersion; + private static readonly string OpenTelemetryExporterVersion; private readonly Google.Api.Gax.ResourceNames.ProjectName googleCloudProjectId; private readonly TraceServiceSettings traceServiceSettings; - public StackdriverTraceExporter(string projectId) - { - googleCloudProjectId = new Google.Api.Gax.ResourceNames.ProjectName(projectId); - - // Set header mutation for every outgoing API call to Stackdriver so the BE knows - // which version of OC client is calling it as well as which version of the exporter - var callSettings = CallSettings.FromHeaderMutation(StackdriverCallHeaderAppender); - traceServiceSettings = new TraceServiceSettings(); - traceServiceSettings.CallSettings = callSettings; - } - static StackdriverTraceExporter() { try { var assemblyPackageVersion = typeof(StackdriverTraceExporter).GetTypeInfo().Assembly.GetCustomAttributes().First().InformationalVersion; - STACKDRIVER_EXPORTER_VERSION = assemblyPackageVersion; + StackdriverExportVersion = assemblyPackageVersion; } catch (Exception) { - STACKDRIVER_EXPORTER_VERSION = $"{Constants.PACKAGE_VERSION_UNDEFINED}"; + StackdriverExportVersion = $"{Constants.PackagVersionUndefined}"; } try { - OpenTelemetry_EXPORTER_VERSION = Assembly.GetCallingAssembly().GetName().Version.ToString(); + OpenTelemetryExporterVersion = Assembly.GetCallingAssembly().GetName().Version.ToString(); } catch (Exception) { - OpenTelemetry_EXPORTER_VERSION = $"{Constants.PACKAGE_VERSION_UNDEFINED}"; + OpenTelemetryExporterVersion = $"{Constants.PackagVersionUndefined}"; } } + public StackdriverTraceExporter(string projectId) + { + this.googleCloudProjectId = new Google.Api.Gax.ResourceNames.ProjectName(projectId); + + // Set header mutation for every outgoing API call to Stackdriver so the BE knows + // which version of OC client is calling it as well as which version of the exporter + var callSettings = CallSettings.FromHeaderMutation(StackdriverCallHeaderAppender); + this.traceServiceSettings = new TraceServiceSettings(); + this.traceServiceSettings.CallSettings = callSettings; + } + public async Task ExportAsync(IEnumerable spanDataList) { - var traceWriter = TraceServiceClient.Create(settings: traceServiceSettings); + var traceWriter = TraceServiceClient.Create(settings: this.traceServiceSettings); var batchSpansRequest = new BatchWriteSpansRequest { - ProjectName = googleCloudProjectId, - Spans = { spanDataList.Select(s => s.ToSpan(googleCloudProjectId.ProjectId)) }, + ProjectName = this.googleCloudProjectId, + Spans = { spanDataList.Select(s => s.ToSpan(this.googleCloudProjectId.ProjectId)) }, }; await traceWriter.BatchWriteSpansAsync(batchSpansRequest); } /// - /// Appends OpenTelemetry headers for every outgoing request to Stackdriver Backend + /// Appends OpenTelemetry headers for every outgoing request to Stackdriver Backend. /// - /// The metadata that is sent with every outgoing http request + /// The metadata that is sent with every outgoing http request. private static void StackdriverCallHeaderAppender(Metadata metadata) { - metadata.Add("AGENT_LABEL_KEY", "g.co/agent"); - metadata.Add("AGENT_LABEL_VALUE_STRING", $"{OpenTelemetry_EXPORTER_VERSION}; stackdriver-exporter {STACKDRIVER_EXPORTER_VERSION}"); + metadata.Add("AGENT_LABEL_VALUE_STRING", $"{OpenTelemetryExporterVersion}; stackdriver-exporter {StackdriverExportVersion}"); } } } diff --git a/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs index 9697a4bed6b..9e220f2d2c7 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs @@ -1,5 +1,4 @@ - -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +24,7 @@ namespace OpenTelemetry.Exporter.Stackdriver using OpenTelemetry.Trace.Export; /// - /// Implementation of the exporter to Stackdriver + /// Implementation of the exporter to Stackdriver. /// public class StackdriverExporter { @@ -35,16 +34,16 @@ public class StackdriverExporter private readonly IViewManager viewManager; private readonly string projectId; private readonly string jsonPath; + private readonly object locker = new object(); private StackdriverStatsExporter statsExporter; - private object locker = new object(); private bool isInitialized = false; /// /// Initializes a new instance of the class. /// - /// Google Cloud ProjectId that is used to send data to Stackdriver - /// Exporter to get traces from - /// View manager to get the stats from + /// Google Cloud ProjectId that is used to send data to Stackdriver. + /// Exporter to get traces from. + /// View manager to get the stats from. public StackdriverExporter( string projectId, IExportComponent exportComponent, @@ -55,10 +54,10 @@ public StackdriverExporter( /// /// Initializes a new instance of the class. /// - /// Google Cloud ProjectId that is used to send data to Stackdriver - /// File path to the json file containing the service credential used to authenticate against Stackdriver APIs - /// Exporter to get traces from - /// View manager to get the stats from + /// Google Cloud ProjectId that is used to send data to Stackdriver. + /// File path to the json file containing the service credential used to authenticate against Stackdriver APIs. + /// Exporter to get traces from. + /// View manager to get the stats from. public StackdriverExporter( string projectId, string jsonPath, @@ -74,87 +73,87 @@ public StackdriverExporter( } /// - /// Starts the exporter + /// Starts the exporter. /// public void Start() { - lock (locker) + lock (this.locker) { - if (isInitialized) + if (this.isInitialized) { return; } // Register trace exporter - if (exportComponent != null) + if (this.exportComponent != null) { - var traceExporter = new StackdriverTraceExporter(projectId); - exportComponent.SpanExporter.RegisterHandler(ExporterName, traceExporter); + var traceExporter = new StackdriverTraceExporter(this.projectId); + this.exportComponent.SpanExporter.RegisterHandler(ExporterName, traceExporter); } // Register stats(metrics) exporter - if (viewManager != null) + if (this.viewManager != null) { - var credential = GetGoogleCredential(); + var credential = this.GetGoogleCredential(); var statsConfig = StackdriverStatsConfiguration.Default; statsConfig.GoogleCredential = credential; - if (statsConfig.ProjectId != projectId) + if (statsConfig.ProjectId != this.projectId) { - statsConfig.ProjectId = projectId; - statsConfig.MonitoredResource = GoogleCloudResourceUtils.GetDefaultResource(projectId); + statsConfig.ProjectId = this.projectId; + statsConfig.MonitoredResource = GoogleCloudResourceUtils.GetDefaultResource(this.projectId); } - statsExporter = new StackdriverStatsExporter(viewManager, statsConfig); - statsExporter.Start(); + this.statsExporter = new StackdriverStatsExporter(this.viewManager, statsConfig); + this.statsExporter.Start(); } - isInitialized = true; + this.isInitialized = true; } } /// - /// Stops the exporter + /// Stops the exporter. /// public void Stop() { - lock (locker) + lock (this.locker) { - if (!isInitialized) + if (!this.isInitialized) { return; } // Stop tracing exporter - if (exportComponent != null) + if (this.exportComponent != null) { - exportComponent.SpanExporter.UnregisterHandler(ExporterName); + this.exportComponent.SpanExporter.UnregisterHandler(ExporterName); } // Stop metrics exporter - if (statsExporter != null) + if (this.statsExporter != null) { - statsExporter.Stop(); + this.statsExporter.Stop(); } - isInitialized = false; + this.isInitialized = false; } } private GoogleCredential GetGoogleCredential() { GoogleCredential credential; - if (string.IsNullOrEmpty(jsonPath)) + if (string.IsNullOrEmpty(this.jsonPath)) { credential = GoogleCredential.GetApplicationDefault(); } else { - credential = GoogleCredential.FromFile(jsonPath) + credential = GoogleCredential.FromFile(this.jsonPath) .CreateScoped(MetricServiceClient.DefaultScopes); } return credential; } } -} \ No newline at end of file +} diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs b/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs index 70ff24b5f89..28a5a309b0d 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Utils/CommonUtils.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,22 +16,20 @@ namespace OpenTelemetry.Exporter.Stackdriver.Utils { - using System; using System.Collections.Generic; - using System.Linq; /// - /// Common Utility Methods that are not metrics/trace specific + /// Common Utility Methods that are not metrics/trace specific. /// public static class CommonUtils { /// /// Divide the source list into batches of lists of given size. /// - /// The type of the list - /// The list - /// Size of the batch - /// + /// The type of the list. + /// The list. + /// Size of the batch. + /// . public static IEnumerable> Partition(this IEnumerable source, int size) { using (var enumerator = source.GetEnumerator()) diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs index 54f68b6148a..0dcc47ec88f 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,15 +20,15 @@ namespace OpenTelemetry.Exporter.Stackdriver.Utils /// /// Translation methods from OpenTelemetry structures to common - /// Protobuf structures + /// Protobuf structures. /// public static class ProtoExtensions { /// - /// Translates OpenTelemetry Timestamp to Protobuf's timestamp + /// Translates OpenTelemetry Timestamp to Protobuf's timestamp. /// - /// OpenTelemetry timestamp - /// Protobuf's timestamp + /// OpenTelemetry timestamp. + /// Protobuf's timestamp. public static Google.Protobuf.WellKnownTypes.Timestamp ToTimestamp(this Timestamp timestamp) { return new Google.Protobuf.WellKnownTypes.Timestamp { Seconds = timestamp.Seconds, Nanos = timestamp.Nanos }; diff --git a/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs index 98e32acb4e5..19a0d2f9e69 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs @@ -13,7 +13,4 @@ // See the License for the specific language governing permissions and // limitations under the License. // - -using System.Runtime.CompilerServices; - [assembly: System.CLSCompliant(true)] diff --git a/src/OpenTelemetry/Internal/VarInt.cs b/src/OpenTelemetry/Internal/VarInt.cs index 24867cc1a60..70fb59afc09 100644 --- a/src/OpenTelemetry/Internal/VarInt.cs +++ b/src/OpenTelemetry/Internal/VarInt.cs @@ -21,10 +21,14 @@ namespace OpenTelemetry.Internal public static class VarInt { - /** Maximum encoded size of 32-bit positive integers (in bytes) */ + /// + /// Maximum encoded size of 32-bit positive integers (in bytes). + /// public const int MaxVarintSize = 5; - /** maximum encoded size of 64-bit longs, and negative 32-bit ints (in bytes) */ + /// + /// maximum encoded size of 64-bit longs, and negative 32-bit ints (in bytes). + /// public const int MaxVarlongSize = 10; public static int VarIntSize(int i) @@ -63,6 +67,13 @@ public static int GetVarInt(byte[] src, int offset, int[] dst) return offset; } + /// + /// Writes an into into an array at a specific offset. + /// + /// The value to write. + /// The array to write to. + /// The offset at which to place the value. + /// The offset. public static int PutVarInt(int v, byte[] sink, int offset) { var uv = (uint)v; @@ -78,69 +89,11 @@ public static int PutVarInt(int v, byte[] sink, int offset) return offset; } - // public static int getVarInt(ByteBuffer src) - // { - // int tmp; - // if ((tmp = src.get()) >= 0) - // { - // return tmp; - // } - // int result = tmp & 0x7f; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 7; - // } - // else - // { - // result |= (tmp & 0x7f) << 7; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 14; - // } - // else - // { - // result |= (tmp & 0x7f) << 14; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 21; - // } - // else - // { - // result |= (tmp & 0x7f) << 21; - // result |= (tmp = src.get()) << 28; - // while (tmp < 0) - // { - // // We get into this loop only in the case of overflow. - // // By doing this, we can call getVarInt() instead of - // // getVarLong() when we only need an int. - // tmp = src.get(); - // } - // } - // } - // } - // return result; - // } - - // public static void putVarInt(int v, ByteBuffer sink) - // { - // while (true) - // { - // int bits = v & 0x7f; - // v >>>= 7; - // if (v == 0) - // { - // sink.put((byte)bits); - // return; - // } - // sink.put((byte)(bits | 0x80)); - // } - // } - - /** - * Reads a varint from the given InputStream and returns the decoded value as an int. - * - * @param inputStream the InputStream to read from - */ + /// + /// Gets an integer from a stream. + /// + /// The stream to read from. + /// The int. public static int GetVarInt(Stream inputStream) { var result = 0; @@ -163,115 +116,16 @@ public static int GetVarInt(Stream inputStream) return result; } + /// + /// Writes an integer to a stream. + /// + /// The value. + /// The stream to write to. public static void PutVarInt(int v, Stream outputStream) { var bytes = new byte[VarIntSize(v)]; PutVarInt(v, bytes, 0); outputStream.Write(bytes, 0, bytes.Length); } - - public static int VarLongSize(long v) - { - var result = 0; - var uv = (ulong)v; - do - { - result++; - uv >>= 7; - } - while (uv != 0); - return result; - } - - // public static long GetVarLong(ByteBuffer src) - // { - // long tmp; - // if ((tmp = src.get()) >= 0) - // { - // return tmp; - // } - // long result = tmp & 0x7f; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 7; - // } - // else - // { - // result |= (tmp & 0x7f) << 7; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 14; - // } - // else - // { - // result |= (tmp & 0x7f) << 14; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 21; - // } - // else - // { - // result |= (tmp & 0x7f) << 21; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 28; - // } - // else - // { - // result |= (tmp & 0x7f) << 28; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 35; - // } - // else - // { - // result |= (tmp & 0x7f) << 35; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 42; - // } - // else - // { - // result |= (tmp & 0x7f) << 42; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 49; - // } - // else - // { - // result |= (tmp & 0x7f) << 49; - // if ((tmp = src.get()) >= 0) - // { - // result |= tmp << 56; - // } - // else - // { - // result |= (tmp & 0x7f) << 56; - // result |= ((long)src.get()) << 63; - // } - // } - // } - // } - // } - // } - // } - // } - // return result; - // } - - // public static void PutVarLong(long v, ByteBuffer sink) - // { - // while (true) - // { - // int bits = ((int)v) & 0x7f; - // v >>>= 7; - // if (v == 0) - // { - // sink.put((byte)bits); - // return; - // } - // sink.put((byte)(bits | 0x80)); - // } - // } } } diff --git a/src/OpenTelemetry/Stats/MeasureToViewMap.cs b/src/OpenTelemetry/Stats/MeasureToViewMap.cs index 3c4ee1c6e05..736275c6d87 100644 --- a/src/OpenTelemetry/Stats/MeasureToViewMap.cs +++ b/src/OpenTelemetry/Stats/MeasureToViewMap.cs @@ -64,7 +64,10 @@ internal IViewData GetView(IViewName viewName, StatsCollectionState state) } } - /** Enable stats collection for the given {@link View}. */ + /// + /// Enable stats collection for the given . + /// + /// The view. internal void RegisterView(IView view) { lock (this.lck) diff --git a/src/OpenTelemetry/Stats/MutableViewData.cs b/src/OpenTelemetry/Stats/MutableViewData.cs index f79c41b6097..350e6b25c06 100644 --- a/src/OpenTelemetry/Stats/MutableViewData.cs +++ b/src/OpenTelemetry/Stats/MutableViewData.cs @@ -192,24 +192,43 @@ internal static MutableViewData Create(IView view, DateTimeOffset start) return new CumulativeMutableViewData(view, start); } - /** Record double stats with the given tags. */ + /// + /// Record double stats with the given tags. + /// + /// The . + /// The value. + /// The time of recording. internal abstract void Record(ITagContext context, double value, DateTimeOffset timestamp); - /** Record long stats with the given tags. */ - internal void Record(ITagContext tags, long value, DateTimeOffset timestamp) + /// + /// Record long stats with the given tags. + /// + /// The . + /// The value. + /// The time of recording. + internal void Record(ITagContext tagContext, long value, DateTimeOffset timestamp) { // TODO(songya): shall we check for precision loss here? - this.Record(tags, (double)value, timestamp); + this.Record(tagContext, (double)value, timestamp); } - /** Convert this {@link MutableViewData} to {@link ViewData}. */ + /// + /// Convert this to . + /// + /// The current time. + /// The stats' collection state. internal abstract IViewData ToViewData(DateTimeOffset now, StatsCollectionState state); - // Clear recorded stats. + /// + /// Clear recorded stats. + /// internal abstract void ClearStats(); - // Resume stats collection, and reset Start Timestamp (for CumulativeMutableViewData), or refresh - // bucket list (for InternalMutableViewData). + /// + /// Resume stats collection, and reset Start Timestamp (for CumulativeMutableViewData), or refresh + /// bucket list (for InternalMutableViewData). + /// + /// The current time. internal abstract void ResumeStatsCollection(DateTimeOffset now); } } diff --git a/src/OpenTelemetry/Stats/Stats.cs b/src/OpenTelemetry/Stats/Stats.cs index f1fa61c9f17..1468612e56f 100644 --- a/src/OpenTelemetry/Stats/Stats.cs +++ b/src/OpenTelemetry/Stats/Stats.cs @@ -18,9 +18,9 @@ namespace OpenTelemetry.Stats { public class Stats { - private static Stats stats = new Stats(); + private static readonly Stats StatsValue = new Stats(); - private IStatsComponent statsComponent = new StatsComponent(); + private readonly IStatsComponent statsComponent = new StatsComponent(); internal Stats() : this(true) @@ -43,7 +43,7 @@ public static IStatsRecorder StatsRecorder { get { - return stats.statsComponent.StatsRecorder; + return StatsValue.statsComponent.StatsRecorder; } } @@ -51,7 +51,7 @@ public static IViewManager ViewManager { get { - return stats.statsComponent.ViewManager; + return StatsValue.statsComponent.ViewManager; } } @@ -59,7 +59,7 @@ public static StatsCollectionState State { get { - return stats.statsComponent.State; + return StatsValue.statsComponent.State; } } } diff --git a/src/OpenTelemetry/Tags/Unsafe/AsyncLocalContext.cs b/src/OpenTelemetry/Tags/Unsafe/AsyncLocalContext.cs index 0f881ae9f6d..ed7f37d9a1e 100644 --- a/src/OpenTelemetry/Tags/Unsafe/AsyncLocalContext.cs +++ b/src/OpenTelemetry/Tags/Unsafe/AsyncLocalContext.cs @@ -23,29 +23,29 @@ internal static class AsyncLocalContext { private static readonly ITagContext EmptyTagContextInstance = new EmptyTagContext(); - private static AsyncLocal context = new AsyncLocal(); + private static readonly AsyncLocal Context = new AsyncLocal(); public static ITagContext CurrentTagContext { get { - if (context.Value == null) + if (Context.Value == null) { return EmptyTagContextInstance; } - return context.Value; + return Context.Value; } set { if (value == EmptyTagContextInstance) { - context.Value = null; + Context.Value = null; } else { - context.Value = value; + Context.Value = value; } } } diff --git a/src/OpenTelemetry/Trace/CurrentSpanUtils.cs b/src/OpenTelemetry/Trace/CurrentSpanUtils.cs index 1a1beb5f4e4..4f93356484d 100644 --- a/src/OpenTelemetry/Trace/CurrentSpanUtils.cs +++ b/src/OpenTelemetry/Trace/CurrentSpanUtils.cs @@ -21,13 +21,13 @@ namespace OpenTelemetry.Trace internal static class CurrentSpanUtils { - private static AsyncLocal asyncLocalContext = new AsyncLocal(); + private static readonly AsyncLocal AsyncLocalContext = new AsyncLocal(); public static ISpan CurrentSpan { get { - return asyncLocalContext.Value; + return AsyncLocalContext.Value; } } @@ -46,14 +46,14 @@ public ScopeInSpan(ISpan span, bool endSpan) { this.span = span; this.endSpan = endSpan; - this.origContext = asyncLocalContext.Value; - asyncLocalContext.Value = span; + this.origContext = AsyncLocalContext.Value; + AsyncLocalContext.Value = span; } public void Dispose() { - var current = asyncLocalContext.Value; - asyncLocalContext.Value = this.origContext; + var current = AsyncLocalContext.Value; + AsyncLocalContext.Value = this.origContext; if (current != this.origContext) { diff --git a/src/OpenTelemetry/Trace/Export/NoopSpanExporter.cs b/src/OpenTelemetry/Trace/Export/NoopSpanExporter.cs index dc32e66fad4..8825c2e1ca4 100644 --- a/src/OpenTelemetry/Trace/Export/NoopSpanExporter.cs +++ b/src/OpenTelemetry/Trace/Export/NoopSpanExporter.cs @@ -16,7 +16,6 @@ namespace OpenTelemetry.Trace.Export { - using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/OpenTelemetry/Trace/Export/SpanExporter.cs b/src/OpenTelemetry/Trace/Export/SpanExporter.cs index e3bf9644e93..dc7081dd366 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporter.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporter.cs @@ -16,7 +16,6 @@ namespace OpenTelemetry.Trace.Export { - using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using OpenTelemetry.Common; @@ -54,9 +53,7 @@ public override void AddSpan(ISpan span) /// public override Task ExportAsync(SpanData export, CancellationToken token) { - this.worker.ExportAsync(export, token); - - return Task.CompletedTask; + return this.worker.ExportAsync(export, token); } public override void RegisterHandler(string name, IHandler handler) diff --git a/src/OpenTelemetry/Trace/Export/SpanExporterBase.cs b/src/OpenTelemetry/Trace/Export/SpanExporterBase.cs index 1120ff1e161..2690f3be87a 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporterBase.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporterBase.cs @@ -16,7 +16,6 @@ namespace OpenTelemetry.Trace.Export { - using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs index ac1ab678498..35e81ecb28d 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs @@ -35,7 +35,7 @@ public sealed class InProcessSampledSpanStore : SampledSpanStoreBase (NumSamplesPerLatencySamples * NumLatencyBuckets) + (NumSamplesPerErrorSamples * NumErrorBuckets); - private static TimeSpan timeBetweenSamples = TimeSpan.FromSeconds(1); + private static readonly TimeSpan TimeBetweenSamples = TimeSpan.FromSeconds(1); private readonly IEventQueue eventQueue; private readonly Dictionary samples; @@ -245,7 +245,7 @@ public void ConsiderForSampling(SpanBase span) // Need to compare by doing the subtraction all the time because in case of an overflow, // this may never sample again (at least for the next ~200 years). No real chance to // overflow two times because that means the process runs for ~200 years. - if (spanEndTime - this.lastSampledTime > timeBetweenSamples) + if (spanEndTime - this.lastSampledTime > TimeBetweenSamples) { this.sampledSpansQueue.Add(span); this.lastSampledTime = spanEndTime; @@ -256,7 +256,7 @@ public void ConsiderForSampling(SpanBase span) // Need to compare by doing the subtraction all the time because in case of an overflow, // this may never sample again (at least for the next ~200 years). No real chance to // overflow two times because that means the process runs for ~200 years. - if (spanEndTime - this.lastNotSampledTime > timeBetweenSamples) + if (spanEndTime - this.lastNotSampledTime > TimeBetweenSamples) { this.notSampledSpansQueue.Add(span); this.lastNotSampledTime = spanEndTime; diff --git a/src/OpenTelemetry/Trace/Internal/BlankSpan.cs b/src/OpenTelemetry/Trace/Internal/BlankSpan.cs index 4b5b632ee63..ece384d9e74 100644 --- a/src/OpenTelemetry/Trace/Internal/BlankSpan.cs +++ b/src/OpenTelemetry/Trace/Internal/BlankSpan.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Trace.Internal { using System; using System.Collections.Generic; - using OpenTelemetry.Trace.Export; internal sealed class BlankSpan : SpanBase { diff --git a/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs b/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs index 3794fa69ce0..fe1e1db8c9f 100644 --- a/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs +++ b/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs @@ -38,6 +38,7 @@ internal RandomGenerator() /// You might get the same values if a random is accessed from different threads. /// Use only for unit tests... /// + /// The seeds value for the rng. internal RandomGenerator(int seed) { this.sameSeed = true; diff --git a/src/OpenTelemetry/Trace/NoopTracer.cs b/src/OpenTelemetry/Trace/NoopTracer.cs index b8db01e2c69..4f923d00554 100644 --- a/src/OpenTelemetry/Trace/NoopTracer.cs +++ b/src/OpenTelemetry/Trace/NoopTracer.cs @@ -23,8 +23,8 @@ namespace OpenTelemetry.Trace /// public sealed class NoopTracer : TracerBase, ITracer { - private static IBinaryFormat binaryFormat = new BinaryFormat(); - private static ITextFormat textFormat = new TraceContextFormat(); + private static readonly IBinaryFormat BinaryFormatValue = new BinaryFormat(); + private static readonly ITextFormat TextFormatValue = new TraceContextFormat(); internal NoopTracer() { @@ -35,7 +35,7 @@ public override IBinaryFormat BinaryFormat { get { - return binaryFormat; + return BinaryFormatValue; } } @@ -44,7 +44,7 @@ public override ITextFormat TextFormat { get { - return textFormat; + return TextFormatValue; } } diff --git a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs index 3b16929566a..e6c61af624c 100644 --- a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs +++ b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs @@ -40,6 +40,35 @@ public string Description public long IdUpperBound { get; } + public static ProbabilitySampler Create(double probability) + { + if (probability < 0.0 || probability > 1.0) + { + throw new ArgumentOutOfRangeException("probability must be in range [0.0, 1.0]"); + } + + long idUpperBound; + + // Special case the limits, to avoid any possible issues with lack of precision across + // double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees + // that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since + // Math.Abs(Long.MIN_VALUE) == Long.MIN_VALUE. + if (probability == 0.0) + { + idUpperBound = long.MinValue; + } + else if (probability == 1.0) + { + idUpperBound = long.MaxValue; + } + else + { + idUpperBound = (long)(probability * long.MaxValue); + } + + return new ProbabilitySampler(probability, idUpperBound); + } + public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) { // If the parent is sampled keep the sampling decision. @@ -79,7 +108,7 @@ public override string ToString() + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) @@ -96,7 +125,7 @@ public override bool Equals(object o) return false; } - /// + /// public override int GetHashCode() { long h = 1; @@ -106,34 +135,5 @@ public override int GetHashCode() h ^= (this.IdUpperBound >> 32) ^ this.IdUpperBound; return (int)h; } - - public static ProbabilitySampler Create(double probability) - { - if (probability < 0.0 || probability > 1.0) - { - throw new ArgumentOutOfRangeException("probability must be in range [0.0, 1.0]"); - } - - long idUpperBound; - - // Special case the limits, to avoid any possible issues with lack of precision across - // double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees - // that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since - // Math.Abs(Long.MIN_VALUE) == Long.MIN_VALUE. - if (probability == 0.0) - { - idUpperBound = long.MinValue; - } - else if (probability == 1.0) - { - idUpperBound = long.MaxValue; - } - else - { - idUpperBound = (long)(probability * long.MaxValue); - } - - return new ProbabilitySampler(probability, idUpperBound); - } } } diff --git a/src/OpenTelemetry/Trace/SpanBase.cs b/src/OpenTelemetry/Trace/SpanBase.cs index 8e704b06264..dab0f13a43b 100644 --- a/src/OpenTelemetry/Trace/SpanBase.cs +++ b/src/OpenTelemetry/Trace/SpanBase.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Trace { using System; using System.Collections.Generic; - using OpenTelemetry.Trace.Export; using OpenTelemetry.Utils; /// @@ -54,7 +53,7 @@ protected SpanBase(SpanContext context, SpanOptions options = SpanOptions.None) } /// - /// Gets the span name. Use to explicitly set the span name. + /// Gets or sets the span name. Use to explicitly set the span name. /// public abstract string Name { get; protected set; } @@ -127,7 +126,7 @@ public void AddEvent(string name) /// public abstract void AddLink(ILink link); - /// + /// public abstract void End(EndSpanOptions options); /// diff --git a/src/OpenTelemetry/Trace/SpanBuilderBase.cs b/src/OpenTelemetry/Trace/SpanBuilderBase.cs index 774404b32d1..53e6f232ed1 100644 --- a/src/OpenTelemetry/Trace/SpanBuilderBase.cs +++ b/src/OpenTelemetry/Trace/SpanBuilderBase.cs @@ -21,17 +21,17 @@ namespace OpenTelemetry.Trace public abstract class SpanBuilderBase : ISpanBuilder { - private SpanBuilderBase() + protected SpanBuilderBase(SpanKind kind) { + this.Kind = kind; } - protected SpanKind Kind { get; private set; } - - protected SpanBuilderBase(SpanKind kind) + private SpanBuilderBase() { - this.Kind = kind; } + protected SpanKind Kind { get; private set; } + public abstract ISpanBuilder SetSampler(ISampler sampler); public abstract ISpanBuilder SetParentLinks(IEnumerable parentLinks); diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 4b5544d59b4..f8941aa9dd2 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -39,6 +39,7 @@ public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler this.spanBuilderOptions = new SpanBuilderOptions(randomGenerator, startEndHandler, traceConfig); this.binaryFormat = binaryFormat ?? new BinaryFormat(); this.textFormat = textFormat ?? new TraceContextFormat(); + this.exportComponent = exportComponent; } /// diff --git a/src/OpenTelemetry/Trace/TracerBase.cs b/src/OpenTelemetry/Trace/TracerBase.cs index 2b8be0e2d30..e2869554d59 100644 --- a/src/OpenTelemetry/Trace/TracerBase.cs +++ b/src/OpenTelemetry/Trace/TracerBase.cs @@ -43,7 +43,7 @@ public ISpan CurrentSpan public abstract ITextFormat TextFormat { get; } /// - /// No-op tracer. + /// Gets no-op tracer. /// internal static NoopTracer NoopTracer { diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index 60fda4b936e..e76782bd280 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -16,7 +16,6 @@ namespace OpenTelemetry.Trace { - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; @@ -27,9 +26,9 @@ namespace OpenTelemetry.Trace /// public sealed class Tracing { - private static Tracing tracing = new Tracing(); + private static readonly Tracing TracingValue = new Tracing(); - private ITraceComponent traceComponent = null; + private readonly ITraceComponent traceComponent = null; internal Tracing() { @@ -39,16 +38,16 @@ internal Tracing() /// /// Gets the tracer to record spans. /// - public static ITracer Tracer => tracing.traceComponent.Tracer; + public static ITracer Tracer => TracingValue.traceComponent.Tracer; /// /// Gets the export component to upload spans to. /// - public static IExportComponent ExportComponent => tracing.traceComponent.ExportComponent; + public static IExportComponent ExportComponent => TracingValue.traceComponent.ExportComponent; /// /// Gets the tracer configuration. /// - public static ITraceConfig TraceConfig => tracing.traceComponent.TraceConfig; + public static ITraceConfig TraceConfig => TracingValue.traceComponent.TraceConfig; } } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index 0bca8d09fb2..a6f81f5850f 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -24,14 +24,12 @@ namespace OpenTelemetry.Collector.AspNetCore.Tests using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; - using OpenTelemetry.Common; using Moq; using Microsoft.AspNetCore.TestHost; using System; using OpenTelemetry.Context.Propagation; using Microsoft.AspNetCore.Http; using System.Collections.Generic; - using System.Text; // See https://github.com/aspnet/Docs/tree/master/aspnetcore/test/integration-tests/samples/2.x/IntegrationTestsSample public class BasicTests diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index 9f15e789247..90cb12b4bc0 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -24,7 +24,6 @@ namespace OpenTelemetry.Collector.AspNetCore.Tests using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; - using OpenTelemetry.Common; using Moq; using Microsoft.AspNetCore.TestHost; using System; @@ -74,7 +73,7 @@ public async Task SuccesfulTemplateControllerCallGeneratesASpan() // Act var response = await client.GetAsync("/api/values"); } - catch (Exception ex) + catch (Exception) { // ignore errors } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj b/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj index 25978d81626..ac64a261c1b 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj @@ -29,7 +29,7 @@ - + diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs index 929a4d62b92..29f5f1d2f77 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Collector.Dependencies.Tests { using Moq; - using OpenTelemetry.Common; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index 900237b4c06..d2a5c1cb8ca 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -18,11 +18,9 @@ namespace OpenTelemetry.Collector.Dependencies.Tests { using Moq; using Newtonsoft.Json; - using OpenTelemetry.Common; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Sampler; using System; using System.Collections.Generic; diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs index f56aac0e974..8e978af1709 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/TestServer.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Collector.Dependencies.Tests public class TestServer { - private static Random GlobalRandom = new Random(); + private static readonly Random GlobalRandom = new Random(); private class RunningServer : IDisposable { diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs index b861a14dd56..7b2129c064c 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs @@ -18,9 +18,7 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation { using Moq; using OpenTelemetry.Trace; - using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; - using StackExchange.Redis.Profiling; using System.Collections.Generic; using Xunit; diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index f3f0641cc94..69d37394869 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -24,7 +24,6 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation using System; using OpenTelemetry.Common; using System.Collections.Generic; - using OpenTelemetry.Trace.Export; public class RedisProfilerEntryToSpanConverterTests { diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs index 50ce38ccb2a..235d15160ca 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Collector.StackExchangeRedis { using Moq; - using OpenTelemetry.Common; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; @@ -33,7 +32,7 @@ public async void ProfilerSessionUsesTheSameDefault() var startEndHandler = new Mock(); var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null); - using (var collector = new StackExchangeRedisCallsCollector(null, tracer, null, null)) + using (var collector = new StackExchangeRedisCallsCollector(tracer, null, null)) { var profilerFactory = collector.GetProfilerSessionsFactory(); var first = profilerFactory(); diff --git a/test/OpenTelemetry.Exporter.Stackdriver.Tests/Impl/StackdriverStatsConfigurationTests.cs b/test/OpenTelemetry.Exporter.Stackdriver.Tests/Impl/StackdriverStatsConfigurationTests.cs index 2dc5591b9fb..2d2e9423387 100644 --- a/test/OpenTelemetry.Exporter.Stackdriver.Tests/Impl/StackdriverStatsConfigurationTests.cs +++ b/test/OpenTelemetry.Exporter.Stackdriver.Tests/Impl/StackdriverStatsConfigurationTests.cs @@ -54,15 +54,15 @@ public void StatsConfiguration_ByDefault_MonitoredResourceIsGlobal() { Assert.NotNull(StackdriverStatsConfiguration.Default.MonitoredResource); - Assert.Equal(Constants.GLOBAL, StackdriverStatsConfiguration.Default.MonitoredResource.Type); + Assert.Equal(Constants.Global, StackdriverStatsConfiguration.Default.MonitoredResource.Type); Assert.NotNull(StackdriverStatsConfiguration.Default.MonitoredResource.Labels); Assert.True(StackdriverStatsConfiguration.Default.MonitoredResource.Labels.ContainsKey("project_id")); - Assert.True(StackdriverStatsConfiguration.Default.MonitoredResource.Labels.ContainsKey(Constants.PROJECT_ID_LABEL_KEY)); + Assert.True(StackdriverStatsConfiguration.Default.MonitoredResource.Labels.ContainsKey(Constants.ProjectIdLabelKey)); Assert.Equal( StackdriverStatsConfiguration.Default.ProjectId, - StackdriverStatsConfiguration.Default.MonitoredResource.Labels[Constants.PROJECT_ID_LABEL_KEY]); + StackdriverStatsConfiguration.Default.MonitoredResource.Labels[Constants.ProjectIdLabelKey]); } } } \ No newline at end of file diff --git a/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs b/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs index a5345cf3f73..78733032819 100644 --- a/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Resources/ResourceTest.cs @@ -26,7 +26,7 @@ public class ResourceTest { private const string keyName = "key"; private const string valueName = "value"; - private static Random random = new Random(); + private static readonly Random random = new Random(); [Fact] public static void CreateResource_NullLabelCollection() diff --git a/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs index 70bb200cd1d..b8a23fb9397 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/CurrentStatsStateTest.cs @@ -66,7 +66,7 @@ public async Task PreventSettingStateAfterReadingState_IsThreadSafe() using (var cts = new CancellationTokenSource()) { var _ = Task.Run( - async () => + () => { while (!cts.IsCancellationRequested) { diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs index 407d67cb5c9..eb5edb2e055 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MeasureToViewMapTest.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Stats.Test { using System.Collections.Generic; - using OpenTelemetry.Common; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; diff --git a/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs index 25776692e64..8deda0e66f4 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs @@ -26,7 +26,7 @@ namespace OpenTelemetry.Stats.Test public class QuickStartExampleTest { - ITestOutputHelper output; + readonly ITestOutputHelper output; public QuickStartExampleTest(ITestOutputHelper output) { diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs index 1cef855a6bb..9eb776f3eaa 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs @@ -35,9 +35,9 @@ public class StatsRecorderTest private static readonly IMeasureDouble MEASURE_DOUBLE_NO_VIEW_2 = MeasureDouble.Create("my measurement no view 2", "description", "us"); private static readonly IViewName VIEW_NAME = ViewName.Create("my view"); - private StatsComponent statsComponent; - private IViewManager viewManager; - private IStatsRecorder statsRecorder; + private readonly StatsComponent statsComponent; + private readonly IViewManager viewManager; + private readonly IStatsRecorder statsRecorder; public StatsRecorderTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs index be1c4f5c0f0..cb186efdcb1 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs @@ -428,11 +428,13 @@ public void TestRecordWithTagsThatDoNotMatchViewData() viewData.AggregationMap, new Dictionary() { - // Won't Record the unregistered tag key, for missing registered keys will use default - // tag value : "unknown/not set". - { tv, - // Should Record stats with default tag value: "KEY" : "unknown/not set". - StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0, 50.0) }, + // Won't Record the unregistered tag key, for missing registered keys will use default + // tag value : "unknown/not set". + { + tv, + // Should Record stats with default tag value: "KEY" : "unknown/not set". + StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0, 50.0) + }, }, EPSILON); } @@ -491,7 +493,7 @@ public void TestViewDataWithMultipleTagKeys() { tv1, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 1.1, 4.4) }, { tv2, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 2.2) }, { tv3, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 3.3)}, - }, + }, EPSILON); } @@ -568,7 +570,7 @@ private void TestMultipleViews_DifferentMeasures(IMeasure measure1, IMeasure mea new Dictionary() { {tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, measure1, value1) }, - }, + }, EPSILON); StatsTestUtil.AssertAggregationMapEquals( diff --git a/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs index 28889e0df4a..3ce726c965a 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/CurrentTagContextUtilsTest.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Tags.Test { using System.Collections.Generic; - using OpenTelemetry.Context; using OpenTelemetry.Tags.Unsafe; using Xunit; diff --git a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs index bec6cddc274..98bfb427370 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs @@ -21,7 +21,6 @@ namespace OpenTelemetry.Tags.Test using System.Collections.Generic; using System.Linq; using OpenTelemetry.Internal; - using OpenTelemetry.Tags.Propagation; using Xunit; public class NoopTagsTest diff --git a/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs index 589b96000f8..e5d4130d6a6 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/ScopedTagContextsTest.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Tags.Test { using System.Collections.Generic; - using OpenTelemetry.Context; using Xunit; public class ScopedTagContextsTest diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs index a8187b15430..fdb4134e546 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Tags.Test { using System.Collections.Generic; - using OpenTelemetry.Context; using OpenTelemetry.Tags.Unsafe; using Xunit; diff --git a/test/OpenTelemetry.Tests/Impl/Testing/Export/TestHandler.cs b/test/OpenTelemetry.Tests/Impl/Testing/Export/TestHandler.cs index 390c8619310..f1d8840cf82 100644 --- a/test/OpenTelemetry.Tests/Impl/Testing/Export/TestHandler.cs +++ b/test/OpenTelemetry.Tests/Impl/Testing/Export/TestHandler.cs @@ -28,14 +28,15 @@ public class TestHandler : IHandler private readonly object monitor = new object(); private readonly List spanDataList = new List(); - public async Task ExportAsync(IEnumerable data) + public Task ExportAsync(IEnumerable data) { lock (monitor) { this.spanDataList.AddRange(data); Monitor.PulseAll(monitor); } - + + return Task.CompletedTask; } public IEnumerable WaitForExport(int numberOfSpans) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs index b64b4fa00cf..3a5319aa618 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Config/TraceConfigBaseTest.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Trace.Config.Test public class TraceConfigBaseTest { - ITraceConfig traceConfig = TraceConfigBase.NoopTraceConfig; + readonly ITraceConfig traceConfig = TraceConfigBase.NoopTraceConfig; [Fact] public void ActiveTraceParams_NoOpImplementation() diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index 8fa4ab493c5..5c813d327f7 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -17,16 +17,15 @@ namespace OpenTelemetry.Trace.Test { using Moq; - using OpenTelemetry.Context; using OpenTelemetry.Trace.Internal; using Xunit; public class CurrentSpanUtilsTest { - private ISpan span; - private RandomGenerator random; - private SpanContext spanContext; - private SpanOptions spanOptions; + private readonly ISpan span; + private readonly RandomGenerator random; + private readonly SpanContext spanContext; + private readonly SpanOptions spanOptions; public CurrentSpanUtilsTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs index ffd064388ff..ed3f29d1cfb 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs @@ -31,7 +31,7 @@ public class InProcessRunningSpanStoreTest private readonly ISpanExporter sampledSpansServiceExporter = SpanExporter.Create(4, Duration.Create(1, 0)); private readonly InProcessRunningSpanStore activeSpansExporter = new InProcessRunningSpanStore(); private readonly StartEndHandler startEndHandler; - private SpanOptions recordSpanOptions = SpanOptions.RecordEvents; + private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; public InProcessRunningSpanStoreTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs index b74c906a072..a16403a51a8 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs @@ -364,7 +364,7 @@ private void AddSpanNameToAllErrorBuckets(String spanName) class TestStartEndHandler : IStartEndHandler { - InProcessSampledSpanStore sampleStore; + readonly InProcessSampledSpanStore sampleStore; public TestStartEndHandler(InProcessSampledSpanStore store) { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs index dc419b1fa56..4ea728827ec 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Trace.Export.Test { using System; - using System.Collections.Generic; using Xunit; public class NoopRunningSpanStoreTest diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index de17ce9eb76..9c594fc793c 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -43,9 +43,9 @@ public class SpanDataTest private readonly List> eventList = new List>(); private readonly List linksList = new List(); - private IAttributes attributes; - private ITimedEvents events; - private LinkList links; + private readonly IAttributes attributes; + private readonly ITimedEvents events; + private readonly LinkList links; public SpanDataTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index aae2cccb870..81bae9d0fe8 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -24,7 +24,6 @@ namespace OpenTelemetry.Trace.Export.Test using Moq; using OpenTelemetry.Common; using OpenTelemetry.Internal; - using OpenTelemetry.Resources; using OpenTelemetry.Testing.Export; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs index 18beaacaa79..0409754739a 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs @@ -37,7 +37,7 @@ public class B3FormatTest private static readonly Action, string, string> setter = (d, k, v) => d[k] = v; private static readonly Func, string, IEnumerable> getter = (d, k) => { d.TryGetValue(k, out var v); return new string[] { v }; }; - ITestOutputHelper _output; + readonly ITestOutputHelper _output; public B3FormatTest(ITestOutputHelper output) { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs index 26013874883..964c0d6a1e0 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs @@ -17,17 +17,16 @@ namespace OpenTelemetry.Trace.Test { using System; - using System.Collections.Generic; using Moq; using OpenTelemetry.Trace.Internal; using Xunit; public class SpanBaseTest { - private RandomGenerator random; - private SpanContext spanContext; - private SpanContext notSampledSpanContext; - private SpanOptions spanOptions; + private readonly RandomGenerator random; + private readonly SpanContext spanContext; + private readonly SpanContext notSampledSpanContext; + private readonly SpanOptions spanOptions; public SpanBaseTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs index dbf3b6ce9c3..7837f7ce898 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs @@ -17,15 +17,14 @@ namespace OpenTelemetry.Trace.Test { using Moq; - using OpenTelemetry.Context; using OpenTelemetry.Trace.Internal; using Xunit; public class SpanBuilderBaseTest { - private ITracer tracer; - private Mock spanBuilder = new Mock(SpanKind.Internal); - private Mock span = new Mock(); + private readonly ITracer tracer; + private readonly Mock spanBuilder = new Mock(SpanKind.Internal); + private readonly Mock span = new Mock(); public SpanBuilderBaseTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 4682a8d573e..48cec0cc764 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -21,18 +21,17 @@ namespace OpenTelemetry.Trace.Test using Moq; using OpenTelemetry.Common; using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Sampler; using Xunit; public class SpanBuilderTest { private static readonly String SPAN_NAME = "MySpanName"; - private SpanBuilderOptions spanBuilderOptions; - private TraceParams alwaysSampleTraceParams = TraceParams.Default.ToBuilder().SetSampler(Samplers.AlwaysSample).Build(); + private readonly SpanBuilderOptions spanBuilderOptions; + private readonly TraceParams alwaysSampleTraceParams = TraceParams.Default.ToBuilder().SetSampler(Samplers.AlwaysSample).Build(); private readonly IRandomGenerator randomHandler = new FakeRandomHandler(); - private IStartEndHandler startEndHandler = Mock.Of(); - private ITraceConfig traceConfig = Mock.Of(); + private readonly IStartEndHandler startEndHandler = Mock.Of(); + private readonly ITraceConfig traceConfig = Mock.Of(); public SpanBuilderTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 8746bc91502..9dddee99da3 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -23,7 +23,6 @@ namespace OpenTelemetry.Trace.Test using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; using Xunit; @@ -42,7 +41,7 @@ public class SpanTest private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; private readonly IDictionary attributes = new Dictionary(); private readonly IDictionary expectedAttributes; - private IStartEndHandler startEndHandler = Mock.Of(); + private readonly IStartEndHandler startEndHandler = Mock.Of(); public SpanTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs index b2680457a7f..110a9804d8b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs @@ -16,11 +16,9 @@ namespace OpenTelemetry.Trace.Test { - using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; - using OpenTelemetry.Context.Propagation; using Xunit; public class TraceComponentTest diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs index 344519bad08..678905342e3 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Trace.Test { using System; using Moq; - using OpenTelemetry.Context; using OpenTelemetry.Trace.Internal; using Xunit; @@ -26,9 +25,9 @@ public class TracerBaseTest { private static readonly ITracer noopTracer = TracerBase.NoopTracer; private static readonly string SPAN_NAME = "MySpanName"; - private TracerBase tracer = Mock.Of(); - private SpanBuilderBase spanBuilder = new Mock(SpanKind.Internal).Object; - private SpanBase span = Mock.Of(); + private readonly TracerBase tracer = Mock.Of(); + private readonly SpanBuilderBase spanBuilder = new Mock(SpanKind.Internal).Object; + private readonly SpanBase span = Mock.Of(); public TracerBaseTest() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index 1fab1dc6bf1..ef58992fa15 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -24,9 +24,9 @@ namespace OpenTelemetry.Trace.Test public class TracerTest { private const string SPAN_NAME = "MySpanName"; - private IStartEndHandler startEndHandler; - private ITraceConfig traceConfig; - private Tracer tracer; + private readonly IStartEndHandler startEndHandler; + private readonly ITraceConfig traceConfig; + private readonly Tracer tracer; public TracerTest() diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs index 1549c66dd39..2b9a10ebb9e 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Trace.Test { using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; - using OpenTelemetry.Context.Propagation; using Xunit; public class TracingTest diff --git a/test/TestApp.AspNetCore.2.0/Startup.cs b/test/TestApp.AspNetCore.2.0/Startup.cs index 6ecb3e91064..97107641ae3 100644 --- a/test/TestApp.AspNetCore.2.0/Startup.cs +++ b/test/TestApp.AspNetCore.2.0/Startup.cs @@ -22,7 +22,6 @@ using OpenTelemetry.Collector.AspNetCore; using OpenTelemetry.Collector.Dependencies; using OpenTelemetry.Trace; -using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Sampler; using System.Net.Http; using OpenTelemetry.Exporter.Ocagent; diff --git a/test/TestApp.AspNetCore.2.0/TestApp.AspNetCore.2.0.csproj b/test/TestApp.AspNetCore.2.0/TestApp.AspNetCore.2.0.csproj index 1dd516c4fad..7e389737fd8 100644 --- a/test/TestApp.AspNetCore.2.0/TestApp.AspNetCore.2.0.csproj +++ b/test/TestApp.AspNetCore.2.0/TestApp.AspNetCore.2.0.csproj @@ -11,7 +11,7 @@ - + From 023e8615108336d58c221e5beb82c12a0bfb6e62 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 8 Jul 2019 23:43:34 -0700 Subject: [PATCH 09/41] Align with spec on ISpanBuilder and ITracer (#133) * Align with spec on ISpanBuilder and ITraces * add bad args tests on SpanBuilder --- samples/Exporters/TestApplicationInsights.cs | 4 +- samples/Exporters/TestHttpClient.cs | 40 +- samples/Exporters/TestRedis.cs | 4 +- samples/Exporters/TestStackdriver.cs | 4 +- samples/Exporters/TestZipkin.cs | 4 +- .../Context/Propagation/TraceContextFormat.cs | 6 +- .../Internal/BlankSpan.cs | 169 ++++++++ .../Trace/ISampler.cs | 6 +- src/OpenTelemetry.Abstractions/Trace/ISpan.cs | 4 +- .../Trace/ISpanBuilder.cs | 67 +++- .../Trace/ITracer.cs | 21 +- .../Trace}/NoopScope.cs | 19 +- .../Trace/NoopSpanBuilder.cs | 130 +++++++ .../Trace/NoopTracer.cs | 43 +-- .../Sampler/Internal/AlwaysSampleSampler.cs | 11 +- .../Sampler/Internal/NeverSampleSampler.cs | 12 +- .../Implementation/HttpInListener.cs | 14 +- .../HttpHandlerDiagnosticListener.cs | 7 +- .../Tags/NoopTagContextBuilder.cs | 2 +- src/OpenTelemetry/Tags/NoopTagger.cs | 2 +- src/OpenTelemetry/Tags/Tagger.cs | 2 +- src/OpenTelemetry/Trace/CurrentSpanUtils.cs | 9 +- .../SpanStore/InProcessRunningSpanStore.cs | 12 +- .../SpanStore/InProcessSampledSpanStore.cs | 36 +- src/OpenTelemetry/Trace/Internal/BlankSpan.cs | 117 ------ src/OpenTelemetry/Trace/NoopSpanBuilder.cs | 63 --- .../Trace/Sampler/ProbabilitySampler.cs | 17 +- src/OpenTelemetry/Trace/Span.cs | 170 ++++++-- src/OpenTelemetry/Trace/SpanBase.cs | 164 -------- src/OpenTelemetry/Trace/SpanBuilder.cs | 283 ++++++++------ src/OpenTelemetry/Trace/SpanBuilderBase.cs | 54 --- src/OpenTelemetry/Trace/Tracer.cs | 35 +- src/OpenTelemetry/Trace/TracerBase.cs | 82 ---- ...ofilerEntryToSpanConverterSamplingTests.cs | 10 +- .../RedisProfilerEntryToSpanConverterTests.cs | 2 +- .../Impl/Tags/NoopTagsTest.cs | 2 + .../Impl/Trace/BlankSpanTest.cs | 31 +- .../Impl/Trace/CurrentSpanUtilsTest.cs | 2 +- .../Export/InProcessSampledSpanStoreTest.cs | 39 +- .../Impl/Trace/NoopSpanBuilderTests.cs | 47 +++ .../Impl/Trace/NoopTracerTests.cs | 66 ++++ .../Trace/Propagation/TraceContextTest.cs | 34 +- .../Impl/Trace/Sampler/SamplersTest.cs | 50 +-- .../Impl/Trace/SpanBaseTest.cs | 101 ----- .../Impl/Trace/SpanBuilderBaseTest.cs | 70 ---- .../Impl/Trace/SpanBuilderTest.cs | 364 +++++++++++++----- .../Impl/Trace/SpanTest.cs | 140 +++++-- .../Impl/Trace/TestSpan.cs | 49 +-- .../Impl/Trace/TracerBaseTest.cs | 182 --------- .../Impl/Trace/TracerTest.cs | 53 ++- .../Impl/Trace/TracingTest.cs | 2 +- 51 files changed, 1463 insertions(+), 1394 deletions(-) create mode 100644 src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs rename src/{OpenTelemetry/Internal => OpenTelemetry.Abstractions/Trace}/NoopScope.cs (77%) create mode 100644 src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs rename src/{OpenTelemetry => OpenTelemetry.Abstractions}/Trace/NoopTracer.cs (53%) delete mode 100644 src/OpenTelemetry/Trace/Internal/BlankSpan.cs delete mode 100644 src/OpenTelemetry/Trace/NoopSpanBuilder.cs delete mode 100644 src/OpenTelemetry/Trace/SpanBase.cs delete mode 100644 src/OpenTelemetry/Trace/SpanBuilderBase.cs delete mode 100644 src/OpenTelemetry/Trace/TracerBase.cs create mode 100644 test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs create mode 100644 test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs diff --git a/samples/Exporters/TestApplicationInsights.cs b/samples/Exporters/TestApplicationInsights.cs index d6b4b47af55..315af97fa5a 100644 --- a/samples/Exporters/TestApplicationInsights.cs +++ b/samples/Exporters/TestApplicationInsights.cs @@ -63,9 +63,9 @@ internal static object Run() Stats.ViewManager.RegisterView(VideoSizeView); - using (var scopedTags = tagContextBuilder.BuildScoped()) + using (tagContextBuilder.BuildScoped()) { - using (var scopedSpan = spanBuilder.StartScopedSpan()) + using (Tracer.WithSpan(spanBuilder.StartSpan())) { Tracer.CurrentSpan.AddEvent("Start processing video."); Thread.Sleep(TimeSpan.FromMilliseconds(10)); diff --git a/samples/Exporters/TestHttpClient.cs b/samples/Exporters/TestHttpClient.cs index eec1f62077f..4e2ed713abb 100644 --- a/samples/Exporters/TestHttpClient.cs +++ b/samples/Exporters/TestHttpClient.cs @@ -31,29 +31,29 @@ internal static object Run() { Console.WriteLine("Hello World!"); - var collector = new DependenciesCollector(new DependenciesCollectorOptions(), Tracer, Samplers.AlwaysSample); - - var exporter = new ZipkinTraceExporter( - new ZipkinTraceExporterOptions() + using (new DependenciesCollector(new DependenciesCollectorOptions(), Tracer, Samplers.AlwaysSample)) + { + var exporter = new ZipkinTraceExporter( + new ZipkinTraceExporterOptions() + { + Endpoint = new Uri("https://zipkin.azurewebsites.net/api/v2/spans"), + ServiceName = typeof(Program).Assembly.GetName().Name, + }, + Tracing.ExportComponent); + exporter.Start(); + + using (Tracer.WithSpan(Tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartSpan())) { - Endpoint = new Uri("https://zipkin.azurewebsites.net/api/v2/spans"), - ServiceName = typeof(Program).Assembly.GetName().Name, - }, - Tracing.ExportComponent); - exporter.Start(); - - var scope = Tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartScopedSpan(); - - var client = new HttpClient(); - var t = client.GetStringAsync("http://bing.com"); - - t.Wait(); - - scope.Dispose(); + using (var client = new HttpClient()) + { + client.GetStringAsync("http://bing.com").GetAwaiter().GetResult(); + } + } - Console.ReadLine(); + Console.ReadLine(); - return null; + return null; + } } } } diff --git a/samples/Exporters/TestRedis.cs b/samples/Exporters/TestRedis.cs index 72c5ab7cd77..b0787ae317a 100644 --- a/samples/Exporters/TestRedis.cs +++ b/samples/Exporters/TestRedis.cs @@ -61,7 +61,7 @@ internal static object Run(string zipkinUri) var db = connection.GetDatabase(); // 4. Create a scoped span. It will end automatically when using statement ends - using (var scope = tracer.SpanBuilder("Main").StartScopedSpan()) + using (tracer.WithSpan(tracer.SpanBuilder("Main").StartSpan())) { Console.WriteLine("About to do a busy work"); for (var i = 0; i < 10; i++) @@ -84,7 +84,7 @@ private static void DoWork(IDatabase db) // 7. 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 // a child span. - using (var scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) + using (tracer.WithSpan(tracer.SpanBuilder("DoWork").StartSpan())) { // Simulate some work. var span = tracer.CurrentSpan; diff --git a/samples/Exporters/TestStackdriver.cs b/samples/Exporters/TestStackdriver.cs index 802a1844754..97bff278763 100644 --- a/samples/Exporters/TestStackdriver.cs +++ b/samples/Exporters/TestStackdriver.cs @@ -64,9 +64,9 @@ internal static object Run(string projectId) Stats.ViewManager.RegisterView(VideoSizeView); - using (var scopedTags = tagContextBuilder.BuildScoped()) + using (tagContextBuilder.BuildScoped()) { - using (var scopedSpan = spanBuilder.StartScopedSpan()) + using (Tracer.WithSpan(spanBuilder.StartSpan())) { Tracer.CurrentSpan.AddEvent("Processing video."); Thread.Sleep(TimeSpan.FromMilliseconds(10)); diff --git a/samples/Exporters/TestZipkin.cs b/samples/Exporters/TestZipkin.cs index f9912ffb5a9..3e898b85354 100644 --- a/samples/Exporters/TestZipkin.cs +++ b/samples/Exporters/TestZipkin.cs @@ -50,7 +50,7 @@ internal static object Run(string zipkinUri) var tracer = Tracing.Tracer; // 4. Create a scoped span. It will end automatically when using statement ends - using (var scope = tracer.SpanBuilder("Main").StartScopedSpan()) + using (tracer.WithSpan(tracer.SpanBuilder("Main").StartSpan())) { Console.WriteLine("About to do a busy work"); for (var i = 0; i < 10; i++) @@ -73,7 +73,7 @@ private static void DoWork(int i) // 7. 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 // a child span. - using (var scope = tracer.SpanBuilder("DoWork").StartScopedSpan()) + using (tracer.WithSpan(tracer.SpanBuilder("DoWork").StartSpan())) { // Simulate some work. var span = tracer.CurrentSpan; diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs index ed8baad6f3b..f8042318847 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs @@ -50,7 +50,7 @@ public SpanContext Extract(T carrier, Func> ge if (traceparentCollection.Count() > 1) { // multiple traceparent are not allowed - return null; + return SpanContext.Blank; } var traceparent = traceparentCollection?.FirstOrDefault(); @@ -58,7 +58,7 @@ public SpanContext Extract(T carrier, Func> ge if (!traceparentParsed) { - return null; + return SpanContext.Blank; } var tracestateResult = Tracestate.Empty; @@ -159,7 +159,7 @@ public SpanContext Extract(T carrier, Func> ge } // in case of exception indicate to upstream that there is no parseable context from the top - return null; + return SpanContext.Blank; } /// diff --git a/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs b/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs new file mode 100644 index 00000000000..3d76ff39573 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs @@ -0,0 +1,169 @@ +// +// 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; + using System.Collections.Generic; + + /// + /// Blank span. + /// + public sealed class BlankSpan : ISpan + { + /// + /// Blank span instance. + /// + public static readonly BlankSpan Instance = new BlankSpan(); + + private BlankSpan() + { + } + + /// + public SpanContext Context => SpanContext.Blank; + + /// + public bool IsRecordingEvents => false; + + /// + public Status Status + { + get => Status.Ok; + + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + } + } + + /// + public bool HasEnded { get; } + + /// + public void UpdateName(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + } + + /// + public void SetAttribute(string key, IAttributeValue value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + } + + /// + public void SetAttribute(string key, string value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + } + + /// + public void SetAttribute(string key, long value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + } + + /// + public void SetAttribute(string key, double value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + } + + /// + public void SetAttribute(string key, bool value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + } + + /// + public void AddEvent(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + } + + /// + public void AddEvent(string name, IDictionary attributes) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (attributes == null) + { + throw new ArgumentNullException(nameof(attributes)); + } + } + + /// + public void AddEvent(IEvent newEvent) + { + if (newEvent == null) + { + throw new ArgumentNullException(nameof(newEvent)); + } + } + + /// + public void AddLink(ILink link) + { + if (link == null) + { + throw new ArgumentNullException(nameof(link)); + } + } + + /// + public void End() + { + } + } +} diff --git a/src/OpenTelemetry.Abstractions/Trace/ISampler.cs b/src/OpenTelemetry.Abstractions/Trace/ISampler.cs index eac86f18788..9b97f960051 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISampler.cs @@ -37,10 +37,10 @@ public interface ISampler /// Name of a span to be created. Note, that the name of the span is settable. /// So this name can be changed later and implementation should assume that. /// Typical example of a name change is when representing incoming http request - /// has a name of url path and then being updated with route name when rouing complete. + /// has a name of url path and then being updated with route name when routing complete. /// - /// Links associated with the parent span. + /// Links associated with the span. /// True of span needs to be created. False otherwise. - bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks); + bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable links); } } diff --git a/src/OpenTelemetry.Abstractions/Trace/ISpan.cs b/src/OpenTelemetry.Abstractions/Trace/ISpan.cs index ac8991e90aa..edad4cd84d3 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISpan.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISpan.cs @@ -20,7 +20,7 @@ namespace OpenTelemetry.Trace /// /// Span represents the execution of the certain span of code or span of time between two events which is part of - /// a distributed trace and has result of execution, context of executuion and other properties. + /// a distributed trace and has result of execution, context of execution and other properties. /// /// This class is mostly write only. Span should not be used to exchange information. Only to add properties /// to it for monitoring purposes. It will be converted to SpanData that is readable. @@ -103,7 +103,7 @@ public interface ISpan /// Adds a single with the attributes to the . /// /// Event name. - /// of attributes name/value pairs associted with the . + /// of attributes name/value pairs associated with the . void AddEvent(string name, IDictionary attributes); /// diff --git a/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs index 389b0662724..9f89a5d88f3 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Trace { using System.Collections.Generic; - using OpenTelemetry.Context; /// /// Span builder. @@ -32,38 +31,68 @@ public interface ISpanBuilder ISpanBuilder SetSampler(ISampler sampler); /// - /// Set the parent links on the span. + /// Sets the to use as a parent for the new span. + /// Any parent that was set previously will be discarded. /// - /// Parent links to set on span. + /// to set. /// This span builder for chaining. - ISpanBuilder SetParentLinks(IEnumerable parentLinks); + ISpanBuilder SetParent(ISpan parent); /// - /// Set the record events value. + /// Sets the remote to use as a parent for the new span. + /// Any parent that was set previously will be discarded. /// - /// Value indicating whether to record span. + /// to set. /// This span builder for chaining. - ISpanBuilder SetRecordEvents(bool recordEvents); + ISpanBuilder SetParent(SpanContext remoteParent); /// - /// Starts the span. + /// Makes the result span to become a root for a new trace. + /// Any parent that was set previously will be discarded. /// - /// Span that was just started. - ISpan StartSpan(); + /// This span builder for chaining. + ISpanBuilder SetNoParent(); + + /// + /// Set on the span. + /// + /// to set. + /// This span builder for chaining. + ISpanBuilder SetSpanKind(SpanKind spanKind); + + /// + /// Set the on the span. + /// + /// context to set on span. + /// This span builder for chaining. + ISpanBuilder AddLink(SpanContext spanContext); /// - /// Starts the span and set it as a current on the current context. + /// Set the on the span. /// - /// Scoped event to control the scope of span in the context. - /// Dispose to stop the span and disassiciate it from the current context. - IScope StartScopedSpan(); + /// to set on span. + /// This span builder for chaining. + ISpanBuilder AddLink(ILink link); + + /// + /// Set the on the span. + /// + /// context. + /// The attributes of the . + /// This span builder for chaining. + ISpanBuilder AddLink(SpanContext context, IDictionary attributes); /// - /// Starts the span and set it as a current on the current context, setting the out param to current span. + /// Set the record events value. /// - /// Current span. - /// Scoped event to control the scope of span in the context. - /// Dispose to stop the span and disassiciate it from the current context. - IScope StartScopedSpan(out ISpan currentSpan); + /// Value indicating whether to record span. + /// This span builder for chaining. + ISpanBuilder SetRecordEvents(bool recordEvents); + + /// + /// Starts the span. + /// + /// Span that was just started. + ISpan StartSpan(); } } diff --git a/src/OpenTelemetry.Abstractions/Trace/ITracer.cs b/src/OpenTelemetry.Abstractions/Trace/ITracer.cs index 8307ca1a082..164e3ae0519 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ITracer.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ITracer.cs @@ -50,27 +50,8 @@ public interface ITracer /// Gets the span builder for the span with the given name. /// /// Span name. - /// Span kind. /// Span builder for the span with the given name. - ISpanBuilder SpanBuilder(string spanName, SpanKind spanKind = SpanKind.Internal); - - /// - /// Gets the span builder for the span with the given name and parent. - /// - /// Span name. - /// Span kind. - /// Parent of the span. - /// Span builder for the span with the given name and specified parent. - ISpanBuilder SpanBuilderWithParent(string name, SpanKind kind = SpanKind.Internal, ISpan parent = null); - - /// - /// Gets the span builder for the span with the give name and remote parent context. - /// - /// Span name. - /// Span kind. - /// Remote parent context extracted from the wire. - /// Span builder for the span with the given name and specified parent span context. - ISpanBuilder SpanBuilderWithParentContext(string name, SpanKind kind = SpanKind.Internal, SpanContext parentContext = null); + ISpanBuilder SpanBuilder(string spanName); /// /// Records . This API allows to send a pre-populated span object to the diff --git a/src/OpenTelemetry/Internal/NoopScope.cs b/src/OpenTelemetry.Abstractions/Trace/NoopScope.cs similarity index 77% rename from src/OpenTelemetry/Internal/NoopScope.cs rename to src/OpenTelemetry.Abstractions/Trace/NoopScope.cs index 15111e357fc..bcb009ded6a 100644 --- a/src/OpenTelemetry/Internal/NoopScope.cs +++ b/src/OpenTelemetry.Abstractions/Trace/NoopScope.cs @@ -14,26 +14,25 @@ // limitations under the License. // -namespace OpenTelemetry.Internal +namespace OpenTelemetry.Trace { using OpenTelemetry.Context; + /// + /// No-op scope. + /// public sealed class NoopScope : IScope { - public static readonly IScope NoopInstance = new NoopScope(); + /// + /// Gets Instance of the noop scope. + /// + public static IScope Instance = new NoopScope(); private NoopScope() { } - public static IScope Instance - { - get - { - return NoopInstance; - } - } - + /// public void Dispose() { } diff --git a/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs new file mode 100644 index 00000000000..97b484c1300 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs @@ -0,0 +1,130 @@ +// +// 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; + using System.Collections.Generic; + + /// + /// No-op span builder. + /// + public class NoopSpanBuilder : ISpanBuilder + { + internal NoopSpanBuilder(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + } + + /// + public ISpanBuilder SetRecordEvents(bool recordEvents) + { + return this; + } + + /// + public ISpan StartSpan() + { + return BlankSpan.Instance; + } + + /// + public ISpanBuilder SetSampler(ISampler sampler) + { + if (sampler == null) + { + throw new ArgumentNullException(nameof(sampler)); + } + + return this; + } + + /// + public ISpanBuilder SetParent(ISpan parent) + { + if (parent == null) + { + throw new ArgumentNullException(nameof(parent)); + } + + return this; + } + + /// + public ISpanBuilder SetParent(SpanContext remoteParent) + { + if (remoteParent == null) + { + throw new ArgumentNullException(nameof(remoteParent)); + } + + return this; + } + + /// + public ISpanBuilder SetNoParent() + { + return this; + } + + /// + public ISpanBuilder SetSpanKind(SpanKind spanKind) + { + return this; + } + + /// + public ISpanBuilder AddLink(SpanContext spanContext) + { + if (spanContext == null) + { + throw new ArgumentNullException(nameof(spanContext)); + } + + return this; + } + + /// + public ISpanBuilder AddLink(ILink link) + { + if (link == null) + { + throw new ArgumentNullException(nameof(link)); + } + + return this; + } + + /// + public ISpanBuilder AddLink(SpanContext context, IDictionary attributes) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (attributes == null) + { + throw new ArgumentNullException(nameof(attributes)); + } + + return this; + } + } +} diff --git a/src/OpenTelemetry/Trace/NoopTracer.cs b/src/OpenTelemetry.Abstractions/Trace/NoopTracer.cs similarity index 53% rename from src/OpenTelemetry/Trace/NoopTracer.cs rename to src/OpenTelemetry.Abstractions/Trace/NoopTracer.cs index 4f923d00554..2bd46c53b54 100644 --- a/src/OpenTelemetry/Trace/NoopTracer.cs +++ b/src/OpenTelemetry.Abstractions/Trace/NoopTracer.cs @@ -16,53 +16,52 @@ namespace OpenTelemetry.Trace { + using System; + using OpenTelemetry.Context; using OpenTelemetry.Context.Propagation; /// /// No-op tracer. /// - public sealed class NoopTracer : TracerBase, ITracer + public sealed class NoopTracer : ITracer { - private static readonly IBinaryFormat BinaryFormatValue = new BinaryFormat(); - private static readonly ITextFormat TextFormatValue = new TraceContextFormat(); + /// + /// Instance of the noop tracer. + /// + public static readonly NoopTracer Instance = new NoopTracer(); internal NoopTracer() { } /// - public override IBinaryFormat BinaryFormat - { - get - { - return BinaryFormatValue; - } - } + public ISpan CurrentSpan => BlankSpan.Instance; /// - public override ITextFormat TextFormat - { - get - { - return TextFormatValue; - } - } + public IBinaryFormat BinaryFormat => new BinaryFormat(); + + /// + public ITextFormat TextFormat => new TraceContextFormat(); /// - public override ISpanBuilder SpanBuilderWithParent(string name, SpanKind kind = SpanKind.Internal, ISpan parent = null) + public IScope WithSpan(ISpan span) { - return NoopSpanBuilder.SetParent(name, kind, parent); + return NoopScope.Instance; } /// - public override ISpanBuilder SpanBuilderWithParentContext(string name, SpanKind kind = SpanKind.Internal, SpanContext parentContext = null) + public ISpanBuilder SpanBuilder(string spanName) { - return NoopSpanBuilder.SetParent(name, kind, parentContext); + return new NoopSpanBuilder(spanName); } /// - public override void RecordSpanData(SpanData span) + public void RecordSpanData(SpanData span) { + if (span == null) + { + throw new ArgumentNullException(nameof(span)); + } } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs index e9707187067..1bf8221c7c0 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs @@ -24,15 +24,10 @@ internal AlwaysSampleSampler() { } - public string Description - { - get - { - return this.ToString(); - } - } + public string Description => this.ToString(); - public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) + /// + public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) { return true; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs index 68540ba51a4..22b1b856b9e 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs @@ -18,21 +18,17 @@ namespace OpenTelemetry.Trace.Sampler.Internal { using System.Collections.Generic; + /// internal sealed class NeverSampleSampler : ISampler { internal NeverSampleSampler() { } - public string Description - { - get - { - return this.ToString(); - } - } + public string Description => this.ToString(); - public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) + /// + public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable links) { return false; } diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs index 3b43f70ed04..0e7c3f0c0b5 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs @@ -59,13 +59,13 @@ public override void OnStartActivity(Activity activity, object payload) var path = (request.PathBase.HasValue || request.Path.HasValue) ? (request.PathBase + request.Path).ToString() : "/"; - ISpan span = null; - this.Tracer.SpanBuilderWithParentContext(path, SpanKind.Server, ctx).SetSampler(this.SamplerFactory(request)).StartScopedSpan(out span); - if (span == null) - { - // Debug.WriteLine("span is null"); - return; - } + ISpan span = this.Tracer.SpanBuilder(path) + .SetSpanKind(SpanKind.Server) + .SetParent(ctx) + .SetSampler(this.SamplerFactory(request)) + .StartSpan(); + + this.Tracer.WithSpan(span); // Note, route is missing at this stage. It will be available later diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs index dafcb50db36..aef890c8bcd 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs @@ -45,7 +45,12 @@ public override void OnStartActivity(Activity activity, object payload) return; } - this.Tracer.SpanBuilder(request.RequestUri.AbsolutePath, SpanKind.Client).SetSampler(this.SamplerFactory(request)).StartScopedSpan(out var span); + var span = this.Tracer.SpanBuilder(request.RequestUri.AbsolutePath) + .SetSpanKind(SpanKind.Client) + .SetSampler(this.SamplerFactory(request)) + .StartSpan(); + this.Tracer.WithSpan(span); + span.PutHttpMethodAttribute(request.Method.ToString()); span.PutHttpHostAttribute(request.RequestUri.Host, request.RequestUri.Port); span.PutHttpPathAttribute(request.RequestUri.AbsolutePath); diff --git a/src/OpenTelemetry/Tags/NoopTagContextBuilder.cs b/src/OpenTelemetry/Tags/NoopTagContextBuilder.cs index 0d3267584c1..8097eb90737 100644 --- a/src/OpenTelemetry/Tags/NoopTagContextBuilder.cs +++ b/src/OpenTelemetry/Tags/NoopTagContextBuilder.cs @@ -18,7 +18,7 @@ namespace OpenTelemetry.Tags { using System; using OpenTelemetry.Context; - using OpenTelemetry.Internal; + using OpenTelemetry.Trace; internal sealed class NoopTagContextBuilder : TagContextBuilderBase { diff --git a/src/OpenTelemetry/Tags/NoopTagger.cs b/src/OpenTelemetry/Tags/NoopTagger.cs index 6312b82c47a..44b340e999e 100644 --- a/src/OpenTelemetry/Tags/NoopTagger.cs +++ b/src/OpenTelemetry/Tags/NoopTagger.cs @@ -18,7 +18,7 @@ namespace OpenTelemetry.Tags { using System; using OpenTelemetry.Context; - using OpenTelemetry.Internal; + using OpenTelemetry.Trace; internal sealed class NoopTagger : TaggerBase { diff --git a/src/OpenTelemetry/Tags/Tagger.cs b/src/OpenTelemetry/Tags/Tagger.cs index bf1d25fe0a8..52c37def6b9 100644 --- a/src/OpenTelemetry/Tags/Tagger.cs +++ b/src/OpenTelemetry/Tags/Tagger.cs @@ -17,7 +17,7 @@ namespace OpenTelemetry.Tags { using OpenTelemetry.Context; - using OpenTelemetry.Internal; + using OpenTelemetry.Trace; public sealed class Tagger : TaggerBase { diff --git a/src/OpenTelemetry/Trace/CurrentSpanUtils.cs b/src/OpenTelemetry/Trace/CurrentSpanUtils.cs index 4f93356484d..7bfcae89b0c 100644 --- a/src/OpenTelemetry/Trace/CurrentSpanUtils.cs +++ b/src/OpenTelemetry/Trace/CurrentSpanUtils.cs @@ -18,18 +18,13 @@ namespace OpenTelemetry.Trace { using System.Threading; using OpenTelemetry.Context; + using OpenTelemetry.Trace.Internal; internal static class CurrentSpanUtils { private static readonly AsyncLocal AsyncLocalContext = new AsyncLocal(); - public static ISpan CurrentSpan - { - get - { - return AsyncLocalContext.Value; - } - } + public static ISpan CurrentSpan => AsyncLocalContext.Value; public static IScope WithSpan(ISpan span, bool endSpan) { diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs index 4b0f69e2ba0..fa7be4f662c 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs @@ -22,14 +22,14 @@ namespace OpenTelemetry.Trace.Export /// public sealed class InProcessRunningSpanStore : RunningSpanStoreBase { - private readonly ConcurrentIntrusiveList runningSpans; + private readonly ConcurrentIntrusiveList runningSpans; /// /// Constructs a new . /// public InProcessRunningSpanStore() { - this.runningSpans = new ConcurrentIntrusiveList(); + this.runningSpans = new ConcurrentIntrusiveList(); } /// @@ -37,7 +37,7 @@ public override IRunningSpanStoreSummary Summary { get { - IEnumerable allRunningSpans = this.runningSpans.Copy(); + IEnumerable allRunningSpans = this.runningSpans.Copy(); var numSpansPerName = new Dictionary(); foreach (var span in allRunningSpans) { @@ -61,7 +61,7 @@ public override IRunningSpanStoreSummary Summary /// public override IEnumerable GetRunningSpans(IRunningSpanStoreFilter filter) { - IReadOnlyCollection allRunningSpans = this.runningSpans.Copy(); + IReadOnlyCollection allRunningSpans = this.runningSpans.Copy(); var maxSpansToReturn = filter.MaxSpansToReturn == 0 ? allRunningSpans.Count : filter.MaxSpansToReturn; var ret = new List(maxSpansToReturn); foreach (var span in allRunningSpans) @@ -83,7 +83,7 @@ public override IEnumerable GetRunningSpans(IRunningSpanStoreFilter fi /// public override void OnEnd(ISpan span) { - if (span is SpanBase spanBase) + if (span is Span spanBase) { this.runningSpans.RemoveElement(spanBase); } @@ -92,7 +92,7 @@ public override void OnEnd(ISpan span) /// public override void OnStart(ISpan span) { - if (span is SpanBase spanBase) + if (span is Span spanBase) { this.runningSpans.AddElement(spanBase); } diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs index 35e81ecb28d..9f52ed5ab79 100644 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs +++ b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs @@ -79,7 +79,7 @@ public override ISet RegisteredSpanNamesForCollection /// public override void ConsiderForSampling(ISpan ispan) { - if (ispan is SpanBase span) + if (ispan is Span span) { lock (this.samples) { @@ -102,7 +102,7 @@ public override void ConsiderForSampling(ISpan ispan) public override IEnumerable GetErrorSampledSpans(ISampledSpanStoreErrorFilter filter) { var numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; - var spans = Enumerable.Empty(); + var spans = Enumerable.Empty(); // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. lock (this.samples) @@ -127,7 +127,7 @@ public override IEnumerable GetErrorSampledSpans(ISampledSpanStoreErro public override IEnumerable GetLatencySampledSpans(ISampledSpanStoreLatencyFilter filter) { var numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; - var spans = Enumerable.Empty(); + var spans = Enumerable.Empty(); // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. lock (this.samples) @@ -187,19 +187,19 @@ internal void InternaltRegisterSpanNamesForCollection(ICollection spanNa private sealed class Bucket { - private readonly EvictingQueue sampledSpansQueue; - private readonly EvictingQueue notSampledSpansQueue; + private readonly EvictingQueue sampledSpansQueue; + private readonly EvictingQueue notSampledSpansQueue; private DateTimeOffset lastSampledTime; private DateTimeOffset lastNotSampledTime; public Bucket(int numSamples) { - this.sampledSpansQueue = new EvictingQueue(numSamples); - this.notSampledSpansQueue = new EvictingQueue(numSamples); + this.sampledSpansQueue = new EvictingQueue(numSamples); + this.notSampledSpansQueue = new EvictingQueue(numSamples); } public static void GetSamples( - int maxSpansToReturn, ICollection output, EvictingQueue queue) + int maxSpansToReturn, ICollection output, EvictingQueue queue) { var copy = queue.ToArray(); @@ -218,8 +218,8 @@ public static void GetSamplesFilteredByLatency( TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn, - ICollection output, - EvictingQueue queue) + ICollection output, + EvictingQueue queue) { var copy = queue.ToArray(); foreach (var span in copy) @@ -237,7 +237,7 @@ public static void GetSamplesFilteredByLatency( } } - public void ConsiderForSampling(SpanBase span) + public void ConsiderForSampling(Span span) { var spanEndTime = span.EndTime; if (span.Context.TraceOptions.IsSampled) @@ -264,14 +264,14 @@ public void ConsiderForSampling(SpanBase span) } } - public void GetSamples(int maxSpansToReturn, ICollection output) + public void GetSamples(int maxSpansToReturn, ICollection output) { GetSamples(maxSpansToReturn, output, this.sampledSpansQueue); GetSamples(maxSpansToReturn, output, this.notSampledSpansQueue); } public void GetSamplesFilteredByLatency( - TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn, ICollection output) + TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn, ICollection output) { GetSamplesFilteredByLatency( latencyLower, latencyUpper, maxSpansToReturn, output, this.sampledSpansQueue); @@ -327,7 +327,7 @@ public Bucket GetErrorBucket(CanonicalCode code) return this.errorBuckets[(int)code - 1]; } - public void ConsiderForSampling(SpanBase span) + public void ConsiderForSampling(Span span) { var status = span.Status; @@ -370,9 +370,9 @@ public IDictionary GetNumbersOfErrorSampledSpans() return errorBucketSummaries; } - public IEnumerable GetErrorSamples(CanonicalCode? code, int maxSpansToReturn) + public IEnumerable GetErrorSamples(CanonicalCode? code, int maxSpansToReturn) { - var output = new List(maxSpansToReturn); + var output = new List(maxSpansToReturn); if (code.HasValue) { this.GetErrorBucket(code.Value).GetSamples(maxSpansToReturn, output); @@ -388,9 +388,9 @@ public IEnumerable GetErrorSamples(CanonicalCode? code, int maxSpansTo return output; } - public IEnumerable GetLatencySamples(TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn) + public IEnumerable GetLatencySamples(TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn) { - var output = new List(maxSpansToReturn); + var output = new List(maxSpansToReturn); for (var i = 0; i < NumLatencyBuckets; i++) { var boundaries = LatencyBucketBoundaries.Values[i]; diff --git a/src/OpenTelemetry/Trace/Internal/BlankSpan.cs b/src/OpenTelemetry/Trace/Internal/BlankSpan.cs deleted file mode 100644 index ece384d9e74..00000000000 --- a/src/OpenTelemetry/Trace/Internal/BlankSpan.cs +++ /dev/null @@ -1,117 +0,0 @@ -// -// 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.Internal -{ - using System; - using System.Collections.Generic; - - internal sealed class BlankSpan : SpanBase - { - public static readonly BlankSpan Instance = new BlankSpan(); - - private BlankSpan() - : base(SpanContext.Blank, default(SpanOptions)) - { - } - - public override string Name { get; protected set; } - - public override Status Status { get; set; } - - public override DateTimeOffset EndTime - { - get - { - return DateTimeOffset.MinValue; - } - } - - public override TimeSpan Latency - { - get - { - return TimeSpan.Zero; - } - } - - public override bool IsSampleToLocalSpanStore - { - get - { - return false; - } - } - - public override SpanId ParentSpanId - { - get - { - return null; - } - } - - public override bool HasEnded => true; - - public override bool IsRecordingEvents => false; - - public override void SetAttribute(string key, IAttributeValue value) - { - } - - public override void AddEvent(string name, IDictionary attributes) - { - } - - public override void AddEvent(IEvent addEvent) - { - } - - public override void AddLink(ILink link) - { - } - - public override void End(EndSpanOptions options) - { - } - - public override string ToString() - { - return "BlankSpan"; - } - - public override SpanData ToSpanData() - { - return null; - } - - public override void SetAttribute(string key, string value) - { - } - - public override void SetAttribute(string key, long value) - { - } - - public override void SetAttribute(string key, double value) - { - } - - public override void SetAttribute(string key, bool value) - { - } - } -} diff --git a/src/OpenTelemetry/Trace/NoopSpanBuilder.cs b/src/OpenTelemetry/Trace/NoopSpanBuilder.cs deleted file mode 100644 index e8d4f583962..00000000000 --- a/src/OpenTelemetry/Trace/NoopSpanBuilder.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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; - using System.Collections.Generic; - using OpenTelemetry.Trace.Internal; - - public class NoopSpanBuilder : SpanBuilderBase - { - private NoopSpanBuilder(string name, SpanKind kind) : base(kind) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - } - - public override ISpan StartSpan() - { - return BlankSpan.Instance; - } - - public override ISpanBuilder SetSampler(ISampler sampler) - { - return this; - } - - public override ISpanBuilder SetParentLinks(IEnumerable parentLinks) - { - return this; - } - - public override ISpanBuilder SetRecordEvents(bool recordEvents) - { - return this; - } - - internal static ISpanBuilder SetParent(string name, SpanKind kind, ISpan parent = null) - { - return new NoopSpanBuilder(name, kind); - } - - internal static ISpanBuilder SetParent(string name, SpanKind kind, SpanContext parentContext = null) - { - return new NoopSpanBuilder(name, kind); - } - } -} diff --git a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs index e6c61af624c..60e99c7903e 100644 --- a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs +++ b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs @@ -20,6 +20,7 @@ namespace OpenTelemetry.Trace.Sampler using System.Collections.Generic; using OpenTelemetry.Utils; + /// public sealed class ProbabilitySampler : ISampler { private ProbabilitySampler(double probability, long idUpperBound) @@ -28,13 +29,8 @@ private ProbabilitySampler(double probability, long idUpperBound) this.IdUpperBound = idUpperBound; } - public string Description - { - get - { - return string.Format("ProbabilitySampler({0:F6})", this.Probability); - } - } + /// + public string Description => $"ProbabilitySampler({this.Probability:F6})"; public double Probability { get; } @@ -69,7 +65,8 @@ public static ProbabilitySampler Create(double probability) return new ProbabilitySampler(probability, idUpperBound); } - public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) + /// + public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable links) { // If the parent is sampled keep the sampling decision. if (parentContext != null && parentContext.TraceOptions.IsSampled) @@ -77,10 +74,10 @@ public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId span return true; } - if (parentLinks != null) + if (links != null) { // If any parent link is sampled keep the sampling decision. - foreach (var parentLink in parentLinks) + foreach (var parentLink in links) { if (parentLink.Context.TraceOptions.IsSampled) { diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index 09e913e3824..e68a8fc0a5d 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -25,8 +25,10 @@ namespace OpenTelemetry.Trace using OpenTelemetry.Trace.Export; using OpenTelemetry.Utils; - /// - public sealed class Span : SpanBase + /// + /// Span implementation. + /// + public sealed class Span : ISpan, IElement { private readonly SpanId parentSpanId; private readonly ITraceParams traceParams; @@ -50,8 +52,9 @@ private Span( ITraceParams traceParams, IStartEndHandler startEndHandler, Timer timestampConverter) - : base(context, options) { + this.Context = context; + this.Options = options; this.parentSpanId = parentSpanId; this.Name = name; this.traceParams = traceParams ?? throw new ArgumentNullException(nameof(traceParams)); @@ -79,11 +82,20 @@ private Span( } } + public SpanContext Context { get; } + + public SpanOptions Options { get; } + + public string Name { get; private set; } + /// - public override string Name { get; protected set; } + public Span Next { get; set; } + + /// + public Span Previous { get; set; } /// - public override Status Status + public Status Status { get { @@ -108,13 +120,12 @@ public override Status Status return; } - this.status = value; + this.status = value ?? throw new ArgumentNullException(nameof(value)); } } } - /// - public override DateTimeOffset EndTime + public DateTimeOffset EndTime { get { @@ -125,8 +136,7 @@ public override DateTimeOffset EndTime } } - /// - public override TimeSpan Latency + public TimeSpan Latency { get { @@ -137,8 +147,7 @@ public override TimeSpan Latency } } - /// - public override bool IsSampleToLocalSpanStore + public bool IsSampleToLocalSpanStore { get { @@ -152,22 +161,22 @@ public override bool IsSampleToLocalSpanStore return this.sampleToLocalSpanStore; } } + + set + { + lock (this.@lock) + { + this.sampleToLocalSpanStore = value; + } + } } - /// - public override SpanId ParentSpanId => this.parentSpanId; + public SpanId ParentSpanId => this.parentSpanId; - /// - public override bool HasEnded => this.hasBeenEnded; + public bool HasEnded => this.hasBeenEnded; /// - public override bool IsRecordingEvents - { - get - { - return this.Options.HasFlag(SpanOptions.RecordEvents); - } - } + public bool IsRecordingEvents => this.Options.HasFlag(SpanOptions.RecordEvents); /// /// Gets or sets span kind. @@ -218,9 +227,25 @@ private TraceEvents InitializedLinks private Status StatusWithDefault => this.status ?? Trace.Status.Ok; + /// + public void UpdateName(string name) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + } + /// - public override void SetAttribute(string key, IAttributeValue value) + public void SetAttribute(string key, IAttributeValue value) { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + if (!this.IsRecordingEvents) { return; @@ -239,8 +264,43 @@ public override void SetAttribute(string key, IAttributeValue value) } /// - public override void AddEvent(string name, IDictionary attributes) + public void AddEvent(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (!this.IsRecordingEvents) + { + return; + } + + lock (this.@lock) + { + if (this.hasBeenEnded) + { + // logger.log(Level.FINE, "Calling AddEvent() on an ended Span."); + return; + } + + this.InitializedEvents.AddEvent(new EventWithTime(this.TimestampConverter.Now, Event.Create(name))); + } + } + + /// + public void AddEvent(string name, IDictionary eventAttributes) { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (eventAttributes == null) + { + throw new ArgumentNullException(nameof(eventAttributes)); + } + if (!this.IsRecordingEvents) { return; @@ -254,13 +314,18 @@ public override void AddEvent(string name, IDictionary return; } - this.InitializedEvents.AddEvent(new EventWithTime(this.TimestampConverter.Now, Event.Create(name, attributes))); + this.InitializedEvents.AddEvent(new EventWithTime(this.TimestampConverter.Now, Event.Create(name, eventAttributes))); } } /// - public override void AddEvent(IEvent addEvent) + public void AddEvent(IEvent addEvent) { + if (addEvent == null) + { + throw new ArgumentNullException(nameof(addEvent)); + } + if (!this.IsRecordingEvents) { return; @@ -284,8 +349,13 @@ public override void AddEvent(IEvent addEvent) } /// - public override void AddLink(ILink link) + public void AddLink(ILink link) { + if (link == null) + { + throw new ArgumentNullException(nameof(link)); + } + if (!this.IsRecordingEvents) { return; @@ -309,7 +379,7 @@ public override void AddLink(ILink link) } /// - public override void End(EndSpanOptions options) + public void End() { if (!this.IsRecordingEvents) { @@ -324,12 +394,6 @@ public override void End(EndSpanOptions options) return; } - if (options.Status != null) - { - this.status = options.Status; - } - - this.sampleToLocalSpanStore = options.SampleToLocalSpanStore; this.endTime = this.TimestampConverter.Now; this.hasBeenEnded = true; } @@ -337,8 +401,7 @@ public override void End(EndSpanOptions options) this.startEndHandler.OnEnd(this); } - /// - public override SpanData ToSpanData() + public SpanData ToSpanData() { if (!this.IsRecordingEvents) { @@ -367,8 +430,18 @@ public override SpanData ToSpanData() } /// - public override void SetAttribute(string key, string value) + public void SetAttribute(string key, string value) { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + if (!this.IsRecordingEvents) { return; @@ -378,8 +451,13 @@ public override void SetAttribute(string key, string value) } /// - public override void SetAttribute(string key, long value) + public void SetAttribute(string key, long value) { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + if (!this.IsRecordingEvents) { return; @@ -389,8 +467,13 @@ public override void SetAttribute(string key, long value) } /// - public override void SetAttribute(string key, double value) + public void SetAttribute(string key, double value) { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + if (!this.IsRecordingEvents) { return; @@ -400,8 +483,13 @@ public override void SetAttribute(string key, double value) } /// - public override void SetAttribute(string key, bool value) + public void SetAttribute(string key, bool value) { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + if (!this.IsRecordingEvents) { return; diff --git a/src/OpenTelemetry/Trace/SpanBase.cs b/src/OpenTelemetry/Trace/SpanBase.cs deleted file mode 100644 index dab0f13a43b..00000000000 --- a/src/OpenTelemetry/Trace/SpanBase.cs +++ /dev/null @@ -1,164 +0,0 @@ -// -// 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; - using System.Collections.Generic; - using OpenTelemetry.Utils; - - /// - /// Span base class. - /// - public abstract class SpanBase : ISpan, IElement - { - private static readonly IDictionary EmptyAttributes = new Dictionary(); - - internal SpanBase() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Span context. - /// Span creation options. - protected SpanBase(SpanContext context, SpanOptions options = SpanOptions.None) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (context.TraceOptions.IsSampled && !options.HasFlag(SpanOptions.RecordEvents)) - { - throw new ArgumentOutOfRangeException("Span is sampled, but does not have RECORD_EVENTS set."); - } - - this.Context = context; - this.Options = options; - } - - /// - /// Gets or sets the span name. Use to explicitly set the span name. - /// - public abstract string Name { get; protected set; } - - /// - public virtual SpanContext Context { get; } - - /// - /// Gets the span options. - /// - public virtual SpanOptions Options { get; } - - /// - public abstract Status Status { get; set; } - - /// - public SpanBase Next { get; set; } - - /// - public SpanBase Previous { get; set; } - - /// - /// Gets the span end time. - /// - public abstract DateTimeOffset EndTime { get; } - - /// - /// Gets the latency (difference beteen stat and end time). - /// - public abstract TimeSpan Latency { get; } - - /// - /// Gets a value indicating whether span stored in local store. - /// - public abstract bool IsSampleToLocalSpanStore { get; } - - /// - /// Gets the parent span id. - /// - public abstract SpanId ParentSpanId { get; } - - /// - /// Gets a value indicating whether this span was already stopped. - /// - public abstract bool HasEnded { get; } - - /// - public abstract bool IsRecordingEvents { get; } - - /// - public void UpdateName(string name) - { - this.Name = name; - } - - /// - public abstract void SetAttribute(string key, IAttributeValue value); - - /// - public void AddEvent(string name) - { - this.AddEvent(name, EmptyAttributes); - } - - /// - public abstract void AddEvent(string name, IDictionary attributes); - - /// - public abstract void AddEvent(IEvent addEvent); - - /// - public abstract void AddLink(ILink link); - - /// - public abstract void End(EndSpanOptions options); - - /// - public void End() - { - this.End(EndSpanOptions.Default); - } - - /// - public override string ToString() - { - return "Span[" + - this.Name + - "]"; - } - - /// - /// Converts this span into span data for exporting purposes. - /// - /// Span Data corresponding current span. - public abstract SpanData ToSpanData(); - - /// - public abstract void SetAttribute(string key, string value); - - /// - public abstract void SetAttribute(string key, long value); - - /// - public abstract void SetAttribute(string key, double value); - - /// - public abstract void SetAttribute(string key, bool value); - } -} diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index 55f5d14f2c6..7b6f11eeed9 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -18,120 +18,209 @@ namespace OpenTelemetry.Trace { using System; using System.Collections.Generic; - using System.Linq; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; /// - public class SpanBuilder : SpanBuilderBase + public class SpanBuilder : ISpanBuilder { - private SpanBuilder(string name, SpanKind kind, SpanBuilderOptions options, SpanContext parentContext = null, ISpan parent = null) : base(kind) + private readonly SpanBuilderOptions options; + private readonly string name; + + private SpanKind kind; + private ISpan parent; + private SpanContext parentSpanContext; + private ParentType parentType = ParentType.CurrentSpan; + private ISampler sampler; + private List links; + private bool recordEvents; + private Timer timestampConverter; + + internal SpanBuilder(string name, SpanBuilderOptions options) { - this.Name = name ?? throw new ArgumentNullException(nameof(name)); - this.Parent = parent; - this.ParentSpanContext = parentContext; - this.Options = options; + this.name = name ?? throw new ArgumentNullException(nameof(name)); + this.options = options; } - private SpanBuilderOptions Options { get; set; } - - private string Name { get; set; } + private enum ParentType + { + CurrentSpan, + ExplicitParent, + ExplicitRemoteParent, + NoParent, + } - private ISpan Parent { get; set; } + /// + public ISpanBuilder SetSampler(ISampler sampler) + { + this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler)); + return this; + } - private SpanContext ParentSpanContext { get; set; } + /// + public ISpanBuilder SetParent(ISpan parent) + { + this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); + this.parentType = ParentType.ExplicitParent; + this.timestampConverter = ((Span)parent)?.TimestampConverter; + this.parentSpanContext = null; + return this; + } - private ISampler Sampler { get; set; } + /// + public ISpanBuilder SetParent(SpanContext remoteParent) + { + this.parentSpanContext = remoteParent ?? throw new ArgumentNullException(nameof(remoteParent)); + this.parent = null; + this.parentType = ParentType.ExplicitRemoteParent; + return this; + } - private IEnumerable ParentLinks { get; set; } = Enumerable.Empty(); + /// + public ISpanBuilder SetNoParent() + { + this.parentType = ParentType.NoParent; + this.parentSpanContext = null; + this.parentSpanContext = null; + return this; + } - private bool RecordEvents { get; set; } + /// + public ISpanBuilder SetSpanKind(SpanKind spanKind) + { + this.kind = spanKind; + return this; + } /// - public override ISpan StartSpan() + public ISpanBuilder AddLink(SpanContext spanContext) { - var parentContext = this.ParentSpanContext; - Timer timestampConverter = null; - if (this.ParentSpanContext == null) + if (spanContext == null) { - // This is not a child of a remote Span. Get the parent SpanContext from the parent Span if - // any. - var parent = this.Parent; - if (parent != null) - { - parentContext = parent.Context; - - // Pass the timestamp converter from the parent to ensure that the recorded events are in - // the right order. Implementation uses System.nanoTime() which is monotonically increasing. - if (parent is Span) - { - timestampConverter = ((Span)parent).TimestampConverter; - } - } + throw new ArgumentNullException(nameof(spanContext)); } - return this.StartSpanInternal( - parentContext, - this.Name, - this.Sampler, - this.ParentLinks, - this.RecordEvents, - timestampConverter); + return this.AddLink(Link.FromSpanContext(spanContext)); } /// - public override ISpanBuilder SetSampler(ISampler sampler) + public ISpanBuilder AddLink(SpanContext spanContext, IDictionary attributes) { - this.Sampler = sampler ?? throw new ArgumentNullException(nameof(sampler)); - return this; + if (spanContext == null) + { + throw new ArgumentNullException(nameof(spanContext)); + } + + if (attributes == null) + { + throw new ArgumentNullException(nameof(attributes)); + } + + return this.AddLink(Link.FromSpanContext(spanContext, attributes)); } /// - public override ISpanBuilder SetParentLinks(IEnumerable parentLinks) + public ISpanBuilder AddLink(ILink link) { - this.ParentLinks = parentLinks ?? throw new ArgumentNullException(nameof(parentLinks)); + if (link == null) + { + throw new ArgumentNullException(nameof(link)); + } + + if (this.links == null) + { + this.links = new List(); + } + + this.links.Add(link); + return this; } /// - public override ISpanBuilder SetRecordEvents(bool recordEvents) + public ISpanBuilder SetRecordEvents(bool recordEvents) { - this.RecordEvents = recordEvents; + this.recordEvents = recordEvents; return this; } - internal static ISpanBuilder Create(string name, SpanKind kind, ISpan parent, SpanBuilderOptions options) + /// + public ISpan StartSpan() { - return new SpanBuilder(name, kind, options, null, parent); - } + SpanContext parentContext = FindParent(this.parentType, this.parent, this.parentSpanContext); + var activeTraceParams = this.options.TraceConfig.ActiveTraceParams; + var random = this.options.RandomHandler; + TraceId traceId; + var spanId = SpanId.GenerateRandomId(random); + SpanId parentSpanId = null; + TraceOptionsBuilder traceOptionsBuilder; + if (parentContext == null || !parentContext.IsValid) + { + // New root span. + traceId = TraceId.GenerateRandomId(random); + traceOptionsBuilder = TraceOptions.Builder(); + } + else + { + // New child span. + traceId = parentContext.TraceId; + parentSpanId = parentContext.SpanId; + traceOptionsBuilder = TraceOptions.Builder(parentContext.TraceOptions); + } - internal static ISpanBuilder Create(string name, SpanKind kind, SpanContext parentContext, SpanBuilderOptions options) - { - return new SpanBuilder(name, kind, options, parentContext, null); + traceOptionsBuilder.SetIsSampled( + MakeSamplingDecision( + parentContext, + this.name, + this.sampler, + this.links, + traceId, + spanId, + activeTraceParams)); + var traceOptions = traceOptionsBuilder.Build(); + var spanOptions = SpanOptions.None; + + if (traceOptions.IsSampled || this.recordEvents) + { + spanOptions = SpanOptions.RecordEvents; + } + + var span = Span.StartSpan( + SpanContext.Create(traceId, spanId, traceOptions, parentContext?.Tracestate ?? Tracestate.Empty), + spanOptions, + this.name, + this.kind, + parentSpanId, + activeTraceParams, + this.options.StartEndHandler, + this.timestampConverter); + LinkSpans(span, this.links); + return span; } - private static bool IsAnyParentLinkSampled(IEnumerable parentLinks) + private static bool IsAnyParentLinkSampled(List parentLinks) { - foreach (var parentLink in parentLinks) + if (parentLinks != null) { - if (parentLink.Context.TraceOptions.IsSampled) + foreach (var parentLink in parentLinks) { - return true; + if (parentLink.Context.TraceOptions.IsSampled) + { + return true; + } } } return false; } - private static void LinkSpans(ISpan span, IEnumerable parentLinks) + private static void LinkSpans(ISpan span, List parentLinks) { - if (parentLinks.Any()) + if (parentLinks != null) { - var childLink = Link.FromSpanContext(span.Context); - foreach (var linkedSpan in parentLinks) + foreach (var link in parentLinks) { - linkedSpan.AddLink(childLink); - span.AddLink(Link.FromSpanContext(linkedSpan.Context)); + span.AddLink(link); } } } @@ -140,7 +229,7 @@ private static bool MakeSamplingDecision( SpanContext parent, string name, ISampler sampler, - IEnumerable parentLinks, + List parentLinks, TraceId traceId, SpanId spanId, ITraceParams activeTraceParams) @@ -164,62 +253,22 @@ private static bool MakeSamplingDecision( return parent.TraceOptions.IsSampled || IsAnyParentLinkSampled(parentLinks); } - private ISpan StartSpanInternal( - SpanContext parent, - string name, - ISampler sampler, - IEnumerable parentLinks, - bool recordEvents, - Timer timestampConverter) + private static SpanContext FindParent(ParentType parentType, ISpan explicitParent, SpanContext remoteParent) { - var activeTraceParams = this.Options.TraceConfig.ActiveTraceParams; - var random = this.Options.RandomHandler; - TraceId traceId; - var spanId = SpanId.GenerateRandomId(random); - SpanId parentSpanId = null; - TraceOptionsBuilder traceOptionsBuilder; - if (parent == null || !parent.IsValid) - { - // New root span. - traceId = TraceId.GenerateRandomId(random); - traceOptionsBuilder = TraceOptions.Builder(); - } - else + switch (parentType) { - // New child span. - traceId = parent.TraceId; - parentSpanId = parent.SpanId; - traceOptionsBuilder = TraceOptions.Builder(parent.TraceOptions); + case ParentType.NoParent: + return null; + case ParentType.CurrentSpan: + ISpan currentSpan = CurrentSpanUtils.CurrentSpan; + return currentSpan?.Context; + case ParentType.ExplicitParent: + return explicitParent?.Context; + case ParentType.ExplicitRemoteParent: + return remoteParent; + default: + throw new ArgumentException($"Unknown parentType {parentType}"); } - - traceOptionsBuilder.SetIsSampled( - MakeSamplingDecision( - parent, - name, - sampler, - parentLinks, - traceId, - spanId, - activeTraceParams)); - var traceOptions = traceOptionsBuilder.Build(); - var spanOptions = SpanOptions.None; - - if (traceOptions.IsSampled || recordEvents) - { - spanOptions = SpanOptions.RecordEvents; - } - - var span = Span.StartSpan( - SpanContext.Create(traceId, spanId, traceOptions, parent?.Tracestate ?? Tracestate.Empty), - spanOptions, - name, - this.Kind, - parentSpanId, - activeTraceParams, - this.Options.StartEndHandler, - timestampConverter); - LinkSpans(span, parentLinks); - return span; } } } diff --git a/src/OpenTelemetry/Trace/SpanBuilderBase.cs b/src/OpenTelemetry/Trace/SpanBuilderBase.cs deleted file mode 100644 index 53e6f232ed1..00000000000 --- a/src/OpenTelemetry/Trace/SpanBuilderBase.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// 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.Context; - - public abstract class SpanBuilderBase : ISpanBuilder - { - protected SpanBuilderBase(SpanKind kind) - { - this.Kind = kind; - } - - private SpanBuilderBase() - { - } - - protected SpanKind Kind { get; private set; } - - public abstract ISpanBuilder SetSampler(ISampler sampler); - - public abstract ISpanBuilder SetParentLinks(IEnumerable parentLinks); - - public abstract ISpanBuilder SetRecordEvents(bool recordEvents); - - public abstract ISpan StartSpan(); - - public IScope StartScopedSpan() - { - return CurrentSpanUtils.WithSpan(this.StartSpan(), true); - } - - public IScope StartScopedSpan(out ISpan currentSpan) - { - currentSpan = this.StartSpan(); - return CurrentSpanUtils.WithSpan(currentSpan, true); - } - } -} diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index f8941aa9dd2..b44c8d9aa36 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -16,18 +16,19 @@ namespace OpenTelemetry.Trace { + using System; using System.Threading; + using OpenTelemetry.Context; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; + using OpenTelemetry.Trace.Internal; /// - public sealed class Tracer : TracerBase + public sealed class Tracer : ITracer { private readonly SpanBuilderOptions spanBuilderOptions; private readonly IExportComponent exportComponent; - private readonly IBinaryFormat binaryFormat; - private readonly ITextFormat textFormat; public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent) : this(randomGenerator, startEndHandler, traceConfig, exportComponent, null, null) @@ -37,33 +38,41 @@ public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent, IBinaryFormat binaryFormat, ITextFormat textFormat) { this.spanBuilderOptions = new SpanBuilderOptions(randomGenerator, startEndHandler, traceConfig); - this.binaryFormat = binaryFormat ?? new BinaryFormat(); - this.textFormat = textFormat ?? new TraceContextFormat(); + this.BinaryFormat = binaryFormat ?? new BinaryFormat(); + this.TextFormat = textFormat ?? new TraceContextFormat(); this.exportComponent = exportComponent; } /// - public override IBinaryFormat BinaryFormat => this.binaryFormat; + public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan ?? BlankSpan.Instance; /// - public override ITextFormat TextFormat => this.textFormat; + public IBinaryFormat BinaryFormat { get; } /// - public override void RecordSpanData(SpanData span) + public ITextFormat TextFormat { get; } + + /// + public IScope WithSpan(ISpan span) { - this.exportComponent.SpanExporter.ExportAsync(span, CancellationToken.None); + if (span == null) + { + throw new ArgumentNullException(nameof(span)); + } + + return CurrentSpanUtils.WithSpan(span, true); } /// - public override ISpanBuilder SpanBuilderWithParent(string name, SpanKind kind = SpanKind.Internal, ISpan parent = null) + public ISpanBuilder SpanBuilder(string spanName) { - return Trace.SpanBuilder.Create(name, kind, parent, this.spanBuilderOptions); + return new SpanBuilder(spanName, this.spanBuilderOptions); } /// - public override ISpanBuilder SpanBuilderWithParentContext(string name, SpanKind kind = SpanKind.Internal, SpanContext parentContext = null) + public void RecordSpanData(SpanData span) { - return Trace.SpanBuilder.Create(name, kind, parentContext, this.spanBuilderOptions); + this.exportComponent.SpanExporter.ExportAsync(span, CancellationToken.None); } } } diff --git a/src/OpenTelemetry/Trace/TracerBase.cs b/src/OpenTelemetry/Trace/TracerBase.cs deleted file mode 100644 index e2869554d59..00000000000 --- a/src/OpenTelemetry/Trace/TracerBase.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// 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; - using OpenTelemetry.Context; - using OpenTelemetry.Context.Propagation; - using OpenTelemetry.Trace.Internal; - - /// - public abstract class TracerBase : ITracer - { - private static readonly NoopTracer NoopTracerInstance = new NoopTracer(); - - /// - public ISpan CurrentSpan - { - get - { - var currentSpan = CurrentSpanUtils.CurrentSpan; - return currentSpan ?? BlankSpan.Instance; - } - } - - /// - public abstract IBinaryFormat BinaryFormat { get; } - - /// - public abstract ITextFormat TextFormat { get; } - - /// - /// Gets no-op tracer. - /// - internal static NoopTracer NoopTracer - { - get - { - return NoopTracerInstance; - } - } - - /// - public IScope WithSpan(ISpan span) - { - if (span == null) - { - throw new ArgumentNullException(nameof(span)); - } - - return CurrentSpanUtils.WithSpan(span, false); - } - - /// - public ISpanBuilder SpanBuilder(string spanName, SpanKind spanKind = SpanKind.Internal) - { - return this.SpanBuilderWithParent(spanName, spanKind, CurrentSpanUtils.CurrentSpan); - } - - /// - public abstract ISpanBuilder SpanBuilderWithParent(string spanName, SpanKind spanKind = SpanKind.Internal, ISpan parent = null); - - /// - public abstract ISpanBuilder SpanBuilderWithParentContext(string spanName, SpanKind spanKind = SpanKind.Internal, SpanContext remoteParentSpanContext = null); - - /// - public abstract void RecordSpanData(SpanData span); - } -} diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs index 7b2129c064c..3593e9ec80b 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs @@ -33,7 +33,7 @@ public void ShouldSampleRespectsSamplerChoice() It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny>())).Returns(true); + It.IsAny>())).Returns(true); Assert.True(RedisProfilerEntryToSpanConverter.ShouldSample(SpanContext.Blank, "SET", m.Object, out var context, out var parentId)); @@ -43,7 +43,7 @@ public void ShouldSampleRespectsSamplerChoice() It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny>())).Returns(false); + It.IsAny>())).Returns(false); Assert.False(RedisProfilerEntryToSpanConverter.ShouldSample(SpanContext.Blank, "SET", m.Object, out context, out parentId)); } @@ -68,7 +68,7 @@ public void ShouldSamplePassesArgumentsToSamplerAndReturnsInContext() It.Is(y => y == traceId && y == context.TraceId), It.Is(y => y.IsValid && y == context.SpanId), It.Is(y => y == "SET"), - It.Is>(y => y == null))); + It.Is>(y => y == null))); } [Fact] @@ -80,7 +80,7 @@ public void ShouldSampleGeneratesNewTraceIdForInvalidContext() It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny>())).Returns((SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) => parentContext.TraceOptions.IsSampled); + It.IsAny>())).Returns((SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) => parentContext.TraceOptions.IsSampled); RedisProfilerEntryToSpanConverter.ShouldSample(SpanContext.Blank, "SET", m.Object, out var context, out var parentId); @@ -89,7 +89,7 @@ public void ShouldSampleGeneratesNewTraceIdForInvalidContext() It.Is(y => y.IsValid && y == context.TraceId), It.Is(y => y.IsValid && y == context.SpanId), It.Is(y => y == "SET"), - It.Is>(y => y == null))); + It.Is>(y => y == null))); Assert.Equal(TraceOptions.Default, context.TraceOptions); } diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index 69d37394869..4cc7cade42f 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -33,7 +33,7 @@ public void DrainSessionUsesCommandAsName() var parentSpan = BlankSpan.Instance; var profiledCommand = new Mock(); var sampler = new Mock(); - sampler.Setup(x => x.ShouldSample(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())).Returns(true); + sampler.Setup(x => x.ShouldSample(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())).Returns(true); profiledCommand.Setup(m => m.Command).Returns("SET"); var result = new List(); RedisProfilerEntryToSpanConverter.DrainSession(parentSpan, new IProfiledCommand[] { profiledCommand.Object }, sampler.Object, result); diff --git a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs index 98bfb427370..ccd3391fdd6 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using OpenTelemetry.Trace; + namespace OpenTelemetry.Tags.Test { using System; diff --git a/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs index 1ad2e214262..8c55220bb99 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs @@ -14,21 +14,15 @@ // limitations under the License. // +using System; + namespace OpenTelemetry.Trace.Test { using System.Collections.Generic; - using OpenTelemetry.Trace.Internal; using Xunit; public class BlankSpanTest { - [Fact] - public void HasInvalidContextAndDefaultSpanOptions() - { - Assert.Equal(SpanContext.Blank, BlankSpan.Instance.Context); - Assert.True(BlankSpan.Instance.Options.HasFlag(SpanOptions.None)); - } - [Fact] public void DoNotCrash() { @@ -60,9 +54,28 @@ public void DoNotCrash() BlankSpan.Instance.AddEvent(Event.Create("MyEvent")); BlankSpan.Instance.AddLink( Link.FromSpanContext(SpanContext.Blank)); + + Assert.False(BlankSpan.Instance.Context.IsValid); + Assert.False(BlankSpan.Instance.IsRecordingEvents); + Assert.Equal(Status.Ok, BlankSpan.Instance.Status); BlankSpan.Instance.Status = Status.Ok; - BlankSpan.Instance.End(EndSpanOptions.Default); BlankSpan.Instance.End(); } + + [Fact] + public void BadArguments() + { + Assert.Throws(() => BlankSpan.Instance.Status = null); + Assert.Throws(() => BlankSpan.Instance.UpdateName(null)); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, string.Empty)); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(string.Empty, (IAttributeValue)null)); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, AttributeValue.StringAttributeValue("foo"))); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, 1L)); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, 0.1d)); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, true)); + Assert.Throws(() => BlankSpan.Instance.AddEvent((string)null)); + Assert.Throws(() => BlankSpan.Instance.AddEvent((IEvent)null)); + Assert.Throws(() => BlankSpan.Instance.AddLink(null)); + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index 5c813d327f7..e6163921fd0 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -38,7 +38,7 @@ public CurrentSpanUtilsTest() Tracestate.Empty); spanOptions = SpanOptions.RecordEvents; - var mockSpan = new Mock(spanContext, spanOptions) { CallBase = true }; + var mockSpan = new Mock() { CallBase = true }; span = mockSpan.Object; } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs index a16403a51a8..a2d1c1ddf0d 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs @@ -107,7 +107,9 @@ public void RegisterSpanNamesViaSpanBuilderOption() Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); - CreateSampledSpan(NOT_REGISTERED_SPAN_NAME).End(EndSpanOptions.Builder().SetSampleToLocalSpanStore(true).Build()); + var span = CreateSampledSpan(NOT_REGISTERED_SPAN_NAME); + span.IsSampleToLocalSpanStore = true; + span.End(); Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); Assert.Contains(NOT_REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); @@ -144,7 +146,9 @@ public void GetErrorSampledSpans() { var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); + span.Status = Status.Cancelled; + span.End(); + var samples = sampleStore.GetErrorSampledSpans( SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, CanonicalCode.Cancelled, 0)); @@ -157,12 +161,16 @@ public void GetErrorSampledSpans_MaxSpansToReturn() { var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span1.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); + span1.Status = Status.Cancelled; + span1.End(); + // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span2.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); + span2.Status = Status.Cancelled; + span2.End(); + var samples = sampleStore.GetErrorSampledSpans( SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, CanonicalCode.Cancelled, 1)); @@ -176,10 +184,15 @@ public void GetErrorSampledSpans_NullCode() { var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span1.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); + + span1.Status = Status.Cancelled;; + span1.End(); + var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span2.End(EndSpanOptions.Builder().SetStatus(Status.Unknown).Build()); + span2.Status = Status.Unknown; + span2.End(); + var samples = sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, null, 0)); Assert.Equal(2, samples.Count()); @@ -192,10 +205,13 @@ public void GetErrorSampledSpans_NullCode_MaxSpansToReturn() { var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span1.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); + span1.Status = Status.Cancelled; + span1.End(); var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; interval += TimeSpan.FromTicks(10); - span2.End(EndSpanOptions.Builder().SetStatus(Status.Unknown).Build()); + span2.Status = Status.Unknown; + span2.End(); + var samples = sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, null, 1)); Assert.Single(samples); @@ -356,8 +372,11 @@ private void AddSpanNameToAllErrorBuckets(String spanName) var sampledSpan = CreateSampledSpan(spanName); var notSampledSpan = CreateNotSampledSpan(spanName); interval += TimeSpan.FromTicks(10); - sampledSpan.End(EndSpanOptions.Builder().SetStatus(code.ToStatus()).Build()); - notSampledSpan.End(EndSpanOptions.Builder().SetStatus(code.ToStatus()).Build()); + + sampledSpan.Status = code.ToStatus(); + notSampledSpan.Status = code.ToStatus(); + sampledSpan.End(); + notSampledSpan.End(); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs new file mode 100644 index 00000000000..e3d1b17349e --- /dev/null +++ b/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs @@ -0,0 +1,47 @@ +// +// 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 System; + +namespace OpenTelemetry.Tests.Impl.Trace +{ + using OpenTelemetry.Trace; + using Xunit; + + public class NoopSpanBuilderTests + { + [Fact] + public void NoopSpanBuilder_BadArguments() + { + Assert.Throws(() => new NoopSpanBuilder(null)); + + var spanBuilder = new NoopSpanBuilder("foo"); + Assert.Throws(() => spanBuilder.SetParent((ISpan)null)); + Assert.Throws(() => spanBuilder.SetParent((SpanContext)null)); + Assert.Throws(() => spanBuilder.SetSampler(null)); + Assert.Throws(() => spanBuilder.AddLink((ILink)null)); + Assert.Throws(() => spanBuilder.AddLink((SpanContext)null)); + Assert.Throws(() => spanBuilder.AddLink(null, null)); + Assert.Throws(() => spanBuilder.AddLink(SpanContext.Blank, null)); + } + + [Fact] + public void NoopSpanBuilder_Ok() + { + Assert.Same(BlankSpan.Instance, new NoopSpanBuilder("foo").StartSpan()); + } + } +} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs new file mode 100644 index 00000000000..b1e38a0ce44 --- /dev/null +++ b/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs @@ -0,0 +1,66 @@ +// +// 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.Tests.Impl.Trace +{ + using System; + using OpenTelemetry.Common; + using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Trace; + using Xunit; + + public class NoopTracerTests + { + [Fact] + public void NoopTracer_CurrentSpan() + { + Assert.Same(BlankSpan.Instance, NoopTracer.Instance.CurrentSpan); + } + + [Fact] + public void NoopTracer_WithSpan() + { + Assert.Same(NoopScope.Instance, NoopTracer.Instance.WithSpan(BlankSpan.Instance)); + } + + [Fact] + public void NoopTracer_SpanBuilder() + { + Assert.IsType(NoopTracer.Instance.SpanBuilder("foo")); + } + + [Fact] + public void NoopTracer_Formats() + { + Assert.NotNull(NoopTracer.Instance.TextFormat); + Assert.NotNull(NoopTracer.Instance.BinaryFormat); + Assert.IsAssignableFrom(NoopTracer.Instance.TextFormat); + Assert.IsAssignableFrom(NoopTracer.Instance.BinaryFormat); + } + + [Fact] + public void NoopTracer_RecordData() + { + Assert.Throws(() => NoopTracer.Instance.RecordSpanData(null)); + + // does not throw + NoopTracer.Instance.RecordSpanData(SpanData.Create(SpanContext.Blank, null, Resource.Empty, "foo", Timestamp.Zero, null, null, null, null, Status.Ok, SpanKind.Internal, Timestamp.Zero)); + } + } +} + diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs index 4fd3835291b..9e322ebbb5b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs @@ -29,12 +29,15 @@ public void TraceContextFormatCanParseExampleFromSpec() { var headers = new Dictionary() { - { "traceparent", "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01" }, - { "tracestate", "congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4,rojo=00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01" }, + {"traceparent", "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"}, + { + "tracestate", + "congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4,rojo=00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01" + }, }; var f = new TraceContextFormat(); - var ctx = f.Extract(headers, (h, n) => new string[] { h[n] } ); + var ctx = f.Extract(headers, (h, n) => new string[] {h[n]}); Assert.Equal(TraceId.FromLowerBase16("0af7651916cd43dd8448eb211c80319c"), ctx.TraceId); Assert.Equal(SpanId.FromLowerBase16("b9c7c989f97918e1"), ctx.SpanId); @@ -52,5 +55,30 @@ public void TraceContextFormatCanParseExampleFromSpec() Assert.Equal("rojo", last.Key); Assert.Equal("00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01", last.Value); } + + [Fact] + public void TraceContextFormat_IsBlankIfNoHeader() + { + var headers = new Dictionary(); + + var f = new TraceContextFormat(); + var ctx = f.Extract(headers, (h, n) => new string[] { h[n] }); + + Assert.Same(SpanContext.Blank, ctx); + } + + [Fact] + public void TraceContextFormat_IsBlankIfInvalid() + { + var headers = new Dictionary + { + {"traceparent", "00-xyz7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"} + }; + + var f = new TraceContextFormat(); + var ctx = f.Extract(headers, (h, n) => new string[] { h[n] }); + + Assert.Same(SpanContext.Blank, ctx); + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs index 417ef6ffd3b..74f3d80dd65 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs @@ -33,7 +33,7 @@ public class SamplersTest private readonly SpanId spanId; private readonly SpanContext sampledSpanContext; private readonly SpanContext notSampledSpanContext; - private readonly ISpan sampledSpan; + private readonly ILink sampledLink; public SamplersTest() { @@ -42,7 +42,7 @@ public SamplersTest() spanId = SpanId.GenerateRandomId(random); sampledSpanContext = SpanContext.Create(traceId, parentSpanId, TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty); notSampledSpanContext = SpanContext.Create(traceId, parentSpanId, TraceOptions.Default, Tracestate.Empty); - sampledSpan = new TestSpan(sampledSpanContext, SpanOptions.RecordEvents); + sampledLink = Link.FromSpanContext(sampledSpanContext); } [Fact] @@ -56,7 +56,7 @@ public void AlwaysSampleSampler_AlwaysReturnTrue() traceId, spanId, "Another name", - new List())); + null)); // Not sampled parent. Assert.True( @@ -66,7 +66,7 @@ public void AlwaysSampleSampler_AlwaysReturnTrue() traceId, spanId, "Yet another name", - new List())); + null)); } @@ -87,7 +87,7 @@ public void NeverSampleSampler_AlwaysReturnFalse() traceId, spanId, "bar", - new List())); + null)); // Not sampled parent. Assert.False( Samplers.NeverSample @@ -96,7 +96,7 @@ public void NeverSampleSampler_AlwaysReturnFalse() traceId, spanId, "quux", - new List())); + null)); } [Fact] @@ -123,19 +123,19 @@ public void ProbabilitySampler_DifferentProbabilities_NotSampledParent() { ISampler neverSample = ProbabilitySampler.Create(0.0); AssertSamplerSamplesWithProbability( - neverSample, notSampledSpanContext, new List(), 0.0); + neverSample, notSampledSpanContext, null, 0.0); ISampler alwaysSample = ProbabilitySampler.Create(1.0); AssertSamplerSamplesWithProbability( - alwaysSample, notSampledSpanContext, new List(), 1.0); + alwaysSample, notSampledSpanContext, null, 1.0); ISampler fiftyPercentSample = ProbabilitySampler.Create(0.5); AssertSamplerSamplesWithProbability( - fiftyPercentSample, notSampledSpanContext, new List(), 0.5); + fiftyPercentSample, notSampledSpanContext, null, 0.5); ISampler twentyPercentSample = ProbabilitySampler.Create(0.2); AssertSamplerSamplesWithProbability( - twentyPercentSample, notSampledSpanContext, new List(), 0.2); + twentyPercentSample, notSampledSpanContext, null, 0.2); ISampler twoThirdsSample = ProbabilitySampler.Create(2.0 / 3.0); AssertSamplerSamplesWithProbability( - twoThirdsSample, notSampledSpanContext, new List(), 2.0 / 3.0); + twoThirdsSample, notSampledSpanContext, null, 2.0 / 3.0); } [Fact] @@ -143,19 +143,19 @@ public void ProbabilitySampler_DifferentProbabilities_SampledParent() { ISampler neverSample = ProbabilitySampler.Create(0.0); AssertSamplerSamplesWithProbability( - neverSample, sampledSpanContext, new List(), 1.0); + neverSample, sampledSpanContext, null, 1.0); ISampler alwaysSample = ProbabilitySampler.Create(1.0); AssertSamplerSamplesWithProbability( - alwaysSample, sampledSpanContext, new List(), 1.0); + alwaysSample, sampledSpanContext, null, 1.0); ISampler fiftyPercentSample = ProbabilitySampler.Create(0.5); AssertSamplerSamplesWithProbability( - fiftyPercentSample, sampledSpanContext, new List(), 1.0); + fiftyPercentSample, sampledSpanContext, null, 1.0); ISampler twentyPercentSample = ProbabilitySampler.Create(0.2); AssertSamplerSamplesWithProbability( - twentyPercentSample, sampledSpanContext, new List(), 1.0); + twentyPercentSample, sampledSpanContext, null, 1.0); ISampler twoThirdsSample = ProbabilitySampler.Create(2.0 / 3.0); AssertSamplerSamplesWithProbability( - twoThirdsSample, sampledSpanContext, new List(), 1.0); + twoThirdsSample, sampledSpanContext, null, 1.0); } [Fact] @@ -163,19 +163,19 @@ public void ProbabilitySampler_DifferentProbabilities_SampledParentLink() { ISampler neverSample = ProbabilitySampler.Create(0.0); AssertSamplerSamplesWithProbability( - neverSample, notSampledSpanContext, new List() { sampledSpan }, 1.0); + neverSample, notSampledSpanContext, new List() { sampledLink }, 1.0); ISampler alwaysSample = ProbabilitySampler.Create(1.0); AssertSamplerSamplesWithProbability( - alwaysSample, notSampledSpanContext, new List() { sampledSpan }, 1.0); + alwaysSample, notSampledSpanContext, new List() { sampledLink }, 1.0); ISampler fiftyPercentSample = ProbabilitySampler.Create(0.5); AssertSamplerSamplesWithProbability( - fiftyPercentSample, notSampledSpanContext, new List() { sampledSpan }, 1.0); + fiftyPercentSample, notSampledSpanContext, new List() { sampledLink }, 1.0); ISampler twentyPercentSample = ProbabilitySampler.Create(0.2); AssertSamplerSamplesWithProbability( - twentyPercentSample, notSampledSpanContext, new List() { sampledSpan }, 1.0); + twentyPercentSample, notSampledSpanContext, new List() { sampledLink }, 1.0); ISampler twoThirdsSample = ProbabilitySampler.Create(2.0 / 3.0); AssertSamplerSamplesWithProbability( - twoThirdsSample, notSampledSpanContext, new List() { sampledSpan }, 1.0); + twoThirdsSample, notSampledSpanContext, new List() { sampledLink }, 1.0); } [Fact] @@ -211,7 +211,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() notSampledtraceId, SpanId.GenerateRandomId(random), SPAN_NAME, - new List())); + null)); // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long // is less than probability * Long.MAX_VALUE; var sampledtraceId = @@ -241,7 +241,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() sampledtraceId, SpanId.GenerateRandomId(random), SPAN_NAME, - new List())); + null)); } [Fact] @@ -259,7 +259,7 @@ public void ProbabilitySampler_ToString() // Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs. private static void AssertSamplerSamplesWithProbability( - ISampler sampler, SpanContext parent, IEnumerable parentLinks, double probability) + ISampler sampler, SpanContext parent, List links, double probability) { var random = new RandomGenerator(1234); var count = 0; // Count of spans with sampling enabled @@ -270,7 +270,7 @@ private static void AssertSamplerSamplesWithProbability( TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), SPAN_NAME, - parentLinks)) + links)) { count++; } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs deleted file mode 100644 index 964c0d6a1e0..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBaseTest.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// 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.Test -{ - using System; - using Moq; - using OpenTelemetry.Trace.Internal; - using Xunit; - - public class SpanBaseTest - { - private readonly RandomGenerator random; - private readonly SpanContext spanContext; - private readonly SpanContext notSampledSpanContext; - private readonly SpanOptions spanOptions; - - public SpanBaseTest() - { - random = new RandomGenerator(1234); - spanContext = - SpanContext.Create( - TraceId.GenerateRandomId(random), - SpanId.GenerateRandomId(random), - TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty); - notSampledSpanContext = - SpanContext.Create( - TraceId.GenerateRandomId(random), - SpanId.GenerateRandomId(random), - TraceOptions.Default, Tracestate.Empty); - spanOptions = SpanOptions.RecordEvents; - } - - [Fact] - public void NewSpan_WithNullContext() - { - Assert.Throws(() => new TestSpan(null, default(SpanOptions))); - } - - - [Fact] - public void GetOptions_WhenNullOptions() - { - var span = new TestSpan(notSampledSpanContext, default(SpanOptions)); - Assert.Equal(SpanOptions.None, span.Options); - } - - [Fact] - public void GetContextAndOptions() - { - var span = new TestSpan(spanContext, spanOptions); - Assert.Equal(spanContext, span.Context); - Assert.Equal(spanOptions, span.Options); - } - - [Fact] - public void PutAttributeCallsAddAttributeByDefault() - { - var mockSpan = new Mock(spanContext, spanOptions) { CallBase = true }; - var span = mockSpan.Object; - IAttributeValue val = AttributeValue.Create(true); - span.SetAttribute("MyKey", val); - span.End(); - mockSpan.Verify((s) => s.SetAttribute(It.Is((arg) => arg == "MyKey"), It.Is((v) => v == val))); - } - - [Fact] - public void EndCallsEndWithDefaultOptions() - { - var mockSpan = new Mock(spanContext, spanOptions) { CallBase = true }; - var span = mockSpan.Object; - span.End(); - mockSpan.Verify((s) => s.End(EndSpanOptions.Default)); - } - - [Fact] - public void AddEventDefaultImplementation() - { - var mockSpan = new Mock(); - var span = mockSpan.Object; - - var @event = Event.Create("MyEvent"); - span.AddEvent(@event); - - mockSpan.Verify((s) => s.AddEvent(@event)); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs deleted file mode 100644 index 7837f7ce898..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderBaseTest.cs +++ /dev/null @@ -1,70 +0,0 @@ -// -// 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.Test -{ - using Moq; - using OpenTelemetry.Trace.Internal; - using Xunit; - - public class SpanBuilderBaseTest - { - private readonly ITracer tracer; - private readonly Mock spanBuilder = new Mock(SpanKind.Internal); - private readonly Mock span = new Mock(); - - public SpanBuilderBaseTest() - { - tracer = Tracing.Tracer; - spanBuilder.Setup((b) => b.StartSpan()).Returns(span.Object); - } - - [Fact] - public void StartScopedSpan() - { - Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - var scope = spanBuilder.Object.StartScopedSpan(); - try - { - Assert.Same(span.Object, tracer.CurrentSpan); - } - finally - { - scope.Dispose(); - } - span.Verify(s => s.End(EndSpanOptions.Default)); - Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - } - - [Fact] - public void StartScopedSpan_WithParam() - { - Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - - var scope = spanBuilder.Object.StartScopedSpan(out var outSpan); - try - { - Assert.Same(outSpan, tracer.CurrentSpan); - } - finally - { - scope.Dispose(); - } - span.Verify(s => s.End(EndSpanOptions.Default)); - Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 48cec0cc764..135efbb4042 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Trace.Test { using System; - using System.Collections.Generic; using Moq; using OpenTelemetry.Common; using OpenTelemetry.Trace.Config; @@ -26,7 +25,7 @@ namespace OpenTelemetry.Trace.Test public class SpanBuilderTest { - private static readonly String SPAN_NAME = "MySpanName"; + private static readonly string SpanName = "MySpanName"; private readonly SpanBuilderOptions spanBuilderOptions; private readonly TraceParams alwaysSampleTraceParams = TraceParams.Default.ToBuilder().SetSampler(Samplers.AlwaysSample).Build(); private readonly IRandomGenerator randomHandler = new FakeRandomHandler(); @@ -46,25 +45,108 @@ public SpanBuilderTest() [Fact] public void StartSpanNullParent() { - var span = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions).StartSpan(); + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetNoParent() + .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.True(span.Context.TraceOptions.IsSampled); var spanData = ((Span)span).ToSpanData(); Assert.Null(spanData.ParentSpanId); Assert.InRange(spanData.StartTimestamp, Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(-1, 0)), Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(1, 0))); - Assert.Equal(SPAN_NAME, spanData.Name); + Assert.Equal(SpanName, spanData.Name); + } + + [Fact] + public void StartSpanLastParentWins1() + { + var spanContext = + SpanContext.Create( + TraceId.GenerateRandomId(randomHandler), + SpanId.GenerateRandomId(randomHandler), + TraceOptions.Default, Tracestate.Empty); + + var span = (Span) new SpanBuilder(SpanName, spanBuilderOptions) + .SetNoParent() + .SetParent(spanContext) + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.Equal(spanContext.TraceId, span.Context.TraceId); + Assert.Equal(spanContext.SpanId, span.ParentSpanId); + } + + [Fact] + public void StartSpanLastParentWins2() + { + var spanContext = + SpanContext.Create( + TraceId.GenerateRandomId(randomHandler), + SpanId.GenerateRandomId(randomHandler), + TraceOptions.Default, Tracestate.Empty); + + var span = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetParent(spanContext) + .SetNoParent() + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.NotEqual(spanContext.TraceId, span.Context.TraceId); + Assert.Null(span.ParentSpanId); + } + + [Fact] + public void StartSpanLastParentWins3() + { + var spanContext = + SpanContext.Create( + TraceId.GenerateRandomId(randomHandler), + SpanId.GenerateRandomId(randomHandler), + TraceOptions.Default, Tracestate.Empty); + var rootSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .StartSpan(); + + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetParent(spanContext) + .SetParent(rootSpan) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); + Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId); + } + + [Fact] + public void StartSpanLastParentWins4() + { + var spanContext = + SpanContext.Create( + TraceId.GenerateRandomId(randomHandler), + SpanId.GenerateRandomId(randomHandler), + TraceOptions.Default, Tracestate.Empty); + var rootSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .StartSpan(); + + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetParent(rootSpan) + .SetParent(spanContext) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(spanContext.TraceId, childSpan.Context.TraceId); + Assert.Equal(spanContext.SpanId, childSpan.ParentSpanId); } [Fact] public void StartSpanNullParentWithRecordEvents() { - var span = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .SetRecordEvents(true) - .StartSpan(); + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetRecordEvents(true) + .SetNoParent() + .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.False(span.Context.TraceOptions.IsSampled); @@ -75,10 +157,11 @@ public void StartSpanNullParentWithRecordEvents() [Fact] public void StartSpanNullParentNoRecordOptions() { - var span = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetNoParent() + .StartSpan(); Assert.True(span.Context.IsValid); Assert.False(span.IsRecordingEvents); Assert.False(span.Context.TraceOptions.IsSampled); @@ -87,13 +170,19 @@ public void StartSpanNullParentNoRecordOptions() [Fact] public void StartChildSpan() { - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions).StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetNoParent() + .StartSpan(); Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.IsRecordingEvents); Assert.True(rootSpan.Context.TraceOptions.IsSampled); - var childSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan, spanBuilderOptions).StartSpan(); + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(Trace.SpanKind.Internal) + .SetParent(rootSpan) + .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.Equal(rootSpan.Context.SpanId, ((Span)childSpan).ToSpanData().ParentSpanId); @@ -101,10 +190,13 @@ public void StartChildSpan() } [Fact] - public void StartSpan_NullParent() + public void StartSpan_ExplicitNoParent() { - var span = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (SpanContext)null, spanBuilderOptions).StartSpan(); + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetNoParent() + .StartSpan(); + Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.True(span.Context.TraceOptions.IsSampled); @@ -113,11 +205,59 @@ public void StartSpan_NullParent() } [Fact] - public void StartSpanInvalidParent() + public void StartSpan_NoParent() { - var span = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, SpanContext.Blank, spanBuilderOptions) + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.True(span.IsRecordingEvents); + Assert.True(span.Context.TraceOptions.IsSampled); + var spanData = ((Span)span).ToSpanData(); + Assert.Null(spanData.ParentSpanId); + } + + [Fact] + public void StartSpan_CurrentSpanParent() + { + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .StartSpan(); + using (CurrentSpanUtils.WithSpan(rootSpan, true)) + { + var childSpan = (Span) new SpanBuilder(SpanName, spanBuilderOptions) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); + Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId); + } + } + + [Fact] + public void StartSpan_NoParentInScopeOfCurrentSpan() + { + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .StartSpan(); + using (CurrentSpanUtils.WithSpan(rootSpan, true)) + { + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetNoParent() .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.NotEqual(rootSpan.Context.TraceId, childSpan.Context.TraceId); + Assert.Null(childSpan.ParentSpanId); + } + } + + [Fact] + public void StartSpanInvalidParent() + { + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(SpanContext.Blank) + .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); Assert.True(span.Context.TraceOptions.IsSampled); @@ -133,10 +273,13 @@ public void StartRemoteSpan() TraceId.GenerateRandomId(randomHandler), SpanId.GenerateRandomId(randomHandler), TraceOptions.Default, Tracestate.Empty); - var span = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, spanContext, spanBuilderOptions) - .SetRecordEvents(true) - .StartSpan(); + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(spanContext) + .SetRecordEvents(true) + .StartSpan(); + Assert.True(span.Context.IsValid); Assert.Equal(spanContext.TraceId, span.Context.TraceId); Assert.False(span.Context.TraceOptions.IsSampled); @@ -148,10 +291,12 @@ public void StartRemoteSpan() public void StartRootSpan_WithSpecifiedSampler() { // Apply given sampler before default sampler for root spans. - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetNoParent() + .SetSampler(Samplers.NeverSample) + .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.False(rootSpan.Context.TraceOptions.IsSampled); } @@ -160,8 +305,11 @@ public void StartRootSpan_WithSpecifiedSampler() public void StartRootSpan_WithoutSpecifiedSampler() { // Apply default sampler (always true in the tests) for root spans. - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions).StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetNoParent() + .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.Context.TraceOptions.IsSampled); } @@ -169,17 +317,21 @@ public void StartRootSpan_WithoutSpecifiedSampler() [Fact] public void StartRemoteChildSpan_WithSpecifiedSampler() { - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.AlwaysSample) - .StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.AlwaysSample) + .SetNoParent() + .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.Context.TraceOptions.IsSampled); // Apply given sampler before default sampler for spans with remote parent. - var childSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan.Context, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetParent(rootSpan.Context) + .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); @@ -188,16 +340,20 @@ public void StartRemoteChildSpan_WithSpecifiedSampler() [Fact] public void StartRemoteChildSpan_WithoutSpecifiedSampler() { - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetNoParent() + .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.False(rootSpan.Context.TraceOptions.IsSampled); // Apply default sampler (always true in the tests) for spans with remote parent. - var childSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan.Context, spanBuilderOptions) - .StartSpan(); + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(rootSpan.Context) + .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); @@ -206,17 +362,22 @@ public void StartRemoteChildSpan_WithoutSpecifiedSampler() [Fact] public void StartChildSpan_WithSpecifiedSampler() { - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.AlwaysSample) - .StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.AlwaysSample) + .SetNoParent() + .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.Context.TraceOptions.IsSampled); // Apply the given sampler for child spans. - var childSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetParent(rootSpan) + .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); @@ -225,15 +386,20 @@ public void StartChildSpan_WithSpecifiedSampler() [Fact] public void StartChildSpan_WithoutSpecifiedSampler() { - var rootSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetNoParent() + .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.False(rootSpan.Context.TraceOptions.IsSampled); // Don't apply the default sampler (always true) for child spans. - var childSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpan, spanBuilderOptions).StartSpan(); + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(rootSpan) + .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); @@ -242,21 +408,28 @@ public void StartChildSpan_WithoutSpecifiedSampler() [Fact] public void StartChildSpan_SampledLinkedParent() { - var rootSpanUnsampled = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) - .SetSampler(Samplers.NeverSample) - .StartSpan(); + var rootSpanUnsampled = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetSampler(Samplers.NeverSample) + .SetNoParent() + .StartSpan(); + Assert.False(rootSpanUnsampled.Context.TraceOptions.IsSampled); var rootSpanSampled = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, (ISpan)null, spanBuilderOptions) + new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) .SetSampler(Samplers.AlwaysSample) + .SetNoParent() .StartSpan(); + Assert.True(rootSpanSampled.Context.TraceOptions.IsSampled); // Sampled because the linked parent is sampled. - var childSpan = - SpanBuilder.Create(SPAN_NAME, SpanKind.Internal, rootSpanUnsampled, spanBuilderOptions) - .SetParentLinks(new List() { rootSpanSampled }) - .StartSpan(); + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .AddLink(Link.FromSpanContext(rootSpanSampled.Context)) + .SetParent(rootSpanUnsampled) + .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpanUnsampled.Context.TraceId, childSpan.Context.TraceId); Assert.True(childSpan.Context.TraceOptions.IsSampled); @@ -293,15 +466,14 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() // If parent is sampled then the remote child must be sampled. var childSpan = - SpanBuilder.Create( - SPAN_NAME, - SpanKind.Internal, - SpanContext.Create( - traceId, - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty), - spanBuilderOptions) + new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(SpanContext.Create( + traceId, + SpanId.GenerateRandomId(randomHandler), + TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty)) .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); Assert.True(childSpan.Context.TraceOptions.IsSampled); @@ -311,21 +483,35 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() // If parent is not sampled then the remote child must be not sampled. childSpan = - SpanBuilder.Create( - SPAN_NAME, - SpanKind.Internal, - SpanContext.Create( - traceId, - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, Tracestate.Empty), - spanBuilderOptions) + new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(SpanContext.Create( + traceId, + SpanId.GenerateRandomId(randomHandler), + TraceOptions.Default, + Tracestate.Empty)) .StartSpan(); + Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); Assert.False(childSpan.Context.TraceOptions.IsSampled); childSpan.End(); } + [Fact] + public void SpanBuilder_BadArguments() + { + var spanBuilder = new SpanBuilder(SpanName, spanBuilderOptions); + + Assert.Throws(() => spanBuilder.SetParent((ISpan)null)); + Assert.Throws(() => spanBuilder.SetParent((SpanContext)null)); + Assert.Throws(() => spanBuilder.SetSampler(null)); + Assert.Throws(() => spanBuilder.AddLink((ILink)null)); + Assert.Throws(() => spanBuilder.AddLink((SpanContext)null)); + Assert.Throws(() => spanBuilder.AddLink(null, null)); + Assert.Throws(() => spanBuilder.AddLink(SpanContext.Blank, null)); + } + class FakeRandomHandler : IRandomGenerator { private readonly Random random; @@ -335,7 +521,7 @@ public FakeRandomHandler() this.random = new Random(1234); } - public Random current() + public Random Current() { return random; } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 9dddee99da3..369714c4dd9 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -47,7 +47,8 @@ public SpanTest() { timestamp = Timestamp.FromDateTimeOffset(startTime); timestampConverter = Timer.StartNew(startTime, () => interval); - spanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), OpenTelemetry.Trace.TraceOptions.Default, Tracestate.Empty); + spanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), + OpenTelemetry.Trace.TraceOptions.Default, Tracestate.Empty); parentSpanId = SpanId.GenerateRandomId(random); attributes.Add( "MyStringAttributeKey", AttributeValue.StringAttributeValue("MyStringAttributeValue")); @@ -77,6 +78,7 @@ public void ToSpanData_NoRecordEvents() { span.SetAttribute(attribute.Key, attribute.Value); } + span.AddEvent(Event.Create(EVENT_DESCRIPTION)); span.AddEvent(EVENT_DESCRIPTION, attributes); span.AddLink(Link.FromSpanContext(spanContext)); @@ -105,6 +107,7 @@ public void NoEventsRecordedAfterEnd() { span.SetAttribute(attribute.Key, attribute.Value); } + span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); @@ -133,7 +136,7 @@ public void ToSpanData_ActiveSpan() TraceParams.Default, startEndHandler, timestampConverter); - + span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); @@ -155,12 +158,14 @@ public void ToSpanData_ActiveSpan() Assert.Equal(SPAN_NAME, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); + Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), spanData.Events.Events.ToList()[0].Timestamp); + Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), + spanData.Events.Events.ToList()[0].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION), spanData.Events.Events.ToList()[0].Event); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), spanData.Events.Events.ToList()[1].Timestamp); + Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), + spanData.Events.Events.ToList()[1].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); @@ -170,8 +175,7 @@ public void ToSpanData_ActiveSpan() Assert.Null(spanData.EndTimestamp); var startEndMock = Mock.Get(startEndHandler); - var spanBase = span as SpanBase; - startEndMock.Verify(s => s.OnStart(spanBase), Times.Once); + startEndMock.Verify(s => s.OnStart(span), Times.Once); } [Fact] @@ -187,7 +191,7 @@ public void GoSpanData_EndedSpan() TraceParams.Default, startEndHandler, timestampConverter); - + span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); @@ -204,8 +208,9 @@ public void GoSpanData_EndedSpan() var link = Link.FromSpanContext(spanContext); span.AddLink(link); interval = TimeSpan.FromMilliseconds(400); - span.End(EndSpanOptions.Builder().SetStatus(Status.Cancelled).Build()); - + span.Status = Status.Cancelled; + span.End(); + var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); Assert.Equal(SPAN_NAME, spanData.Name); @@ -214,9 +219,11 @@ public void GoSpanData_EndedSpan() Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), spanData.Events.Events.ToList()[0].Timestamp); + Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), + spanData.Events.Events.ToList()[0].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION), spanData.Events.Events.ToList()[0].Event); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), spanData.Events.Events.ToList()[1].Timestamp); + Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), + spanData.Events.Events.ToList()[1].Timestamp); Assert.Equal(Event.Create(EVENT_DESCRIPTION, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); @@ -226,9 +233,8 @@ public void GoSpanData_EndedSpan() Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(400))), spanData.EndTimestamp); var startEndMock = Mock.Get(startEndHandler); - var spanBase = span as SpanBase; - startEndMock.Verify(s => s.OnStart(spanBase), Times.Once); - startEndMock.Verify(s => s.OnEnd(spanBase), Times.Once); + startEndMock.Verify(s => s.OnStart(span), Times.Once); + startEndMock.Verify(s => s.OnEnd(span), Times.Once); } [Fact] @@ -252,8 +258,7 @@ public void Status_ViaSetStatus() Assert.Equal(Status.Cancelled, span.Status); var startEndMock = Mock.Get(startEndHandler); - var spanBase = span as SpanBase; - startEndMock.Verify(s => s.OnStart(spanBase), Times.Once); + startEndMock.Verify(s => s.OnStart(span), Times.Once); } [Fact] @@ -273,12 +278,12 @@ public void status_ViaEndSpanOptions() Assert.Equal(Status.Ok, span.Status); ((Span)span).Status = Status.Cancelled; Assert.Equal(Status.Cancelled, span.Status); - span.End(EndSpanOptions.Builder().SetStatus(Status.Aborted).Build()); + span.Status = Status.Aborted; + span.End(); Assert.Equal(Status.Aborted, span.Status); var startEndMock = Mock.Get(startEndHandler); - var spanBase = span as SpanBase; - startEndMock.Verify(s => s.OnStart(spanBase), Times.Once); + startEndMock.Verify(s => s.OnStart(span), Times.Once); } [Fact] @@ -307,6 +312,7 @@ public void DroppingAttributes() } } + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); @@ -315,9 +321,10 @@ public void DroppingAttributes() Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), spanData - .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); + .Attributes + .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); } + span.End(); spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); @@ -327,8 +334,8 @@ public void DroppingAttributes() Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), spanData - .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); + .Attributes + .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); } } @@ -358,6 +365,7 @@ public void DroppingAndAddingAttributes() } } + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); @@ -366,9 +374,10 @@ public void DroppingAndAddingAttributes() Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), spanData - .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); + .Attributes + .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); } + for (var i = 0; i < maxNumberOfAttributes / 2; i++) { IDictionary attributes = new Dictionary(); @@ -379,6 +388,7 @@ public void DroppingAndAddingAttributes() } } + spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes * 3 / 2, spanData.Attributes.DroppedAttributesCount); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); @@ -388,13 +398,15 @@ public void DroppingAndAddingAttributes() Assert.Equal( AttributeValue.LongAttributeValue(i + maxNumberOfAttributes * 3 / 2), spanData - .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2)]); + .Attributes + .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2)]); } + // Test that we have the newest re-added initial entries. for (var i = 0; i < maxNumberOfAttributes / 2; i++) { - Assert.Equal(AttributeValue.LongAttributeValue(i), spanData.Attributes.AttributeMap["MyStringAttributeKey" + i]); + Assert.Equal(AttributeValue.LongAttributeValue(i), + spanData.Attributes.AttributeMap["MyStringAttributeKey" + i]); } } @@ -421,16 +433,20 @@ public void DroppingEvents() span.AddEvent(testEvent); interval += TimeSpan.FromMilliseconds(100); } + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); Assert.Equal(maxNumberOfEvents, spanData.Events.Events.Count()); i = 0; foreach (var te in spanData.Events.Events) { - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), te.Timestamp); + Assert.Equal( + timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), + te.Timestamp); Assert.Equal(testEvent, te.Event); i++; } + span.End(); spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); @@ -438,7 +454,9 @@ public void DroppingEvents() i = 0; foreach (var te in spanData.Events.Events) { - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), te.Timestamp); + Assert.Equal( + timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), + te.Timestamp); Assert.Equal(testEvent, te.Event); i++; } @@ -465,13 +483,15 @@ public void DroppingLinks() { span.AddLink(link); } + var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfLinks, spanData.Links.DroppedLinksCount); Assert.Equal(maxNumberOfLinks, spanData.Links.Links.Count()); foreach (var actualLink in spanData.Links.Links) - { + { Assert.Equal(link, actualLink); } + span.End(); spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfLinks, spanData.Links.DroppedLinksCount); @@ -495,7 +515,8 @@ public void SampleToLocalSpanStore() TraceParams.Default, startEndHandler, timestampConverter); - span.End(EndSpanOptions.Builder().SetSampleToLocalSpanStore(true).Build()); + span.IsSampleToLocalSpanStore = true; + span.End(); Assert.True(((Span)span).IsSampleToLocalSpanStore); var span2 = @@ -513,10 +534,9 @@ public void SampleToLocalSpanStore() Assert.False(((Span)span2).IsSampleToLocalSpanStore); var startEndMock = Mock.Get(startEndHandler); - var spanBase = span as SpanBase; - startEndMock.Verify(s => s.OnEnd(spanBase), Times.Exactly(1)); - var spanBase2 = span2 as SpanBase; - startEndMock.Verify(s => s.OnEnd(spanBase2), Times.Exactly(1)); + + startEndMock.Verify(s => s.OnEnd(span), Times.Exactly(1)); + startEndMock.Verify(s => s.OnEnd(span2), Times.Exactly(1)); } [Fact] @@ -535,5 +555,51 @@ public void SampleToLocalSpanStore_RunningSpan() Assert.Throws(() => ((Span)span).IsSampleToLocalSpanStore); } + + [Fact] + public void BadArguments() + { + var span = + Span.StartSpan( + spanContext, + recordSpanOptions, + SPAN_NAME, + SpanKind.Internal, + parentSpanId, + TraceParams.Default, + startEndHandler, + timestampConverter); + + Assert.Throws(() => span.Status = null); + Assert.Throws(() => span.UpdateName(null)); + Assert.Throws(() => span.SetAttribute(null, string.Empty)); + Assert.Throws(() => span.SetAttribute(string.Empty, (IAttributeValue)null)); + Assert.Throws(() => + span.SetAttribute(null, AttributeValue.StringAttributeValue("foo"))); + Assert.Throws(() => span.SetAttribute(null, 1L)); + Assert.Throws(() => span.SetAttribute(null, 0.1d)); + Assert.Throws(() => span.SetAttribute(null, true)); + Assert.Throws(() => span.AddEvent((string)null)); + Assert.Throws(() => span.AddEvent((IEvent)null)); + Assert.Throws(() => span.AddLink(null)); + } + + [Fact] + public void SetSampleTo() + { + var span = (Span)Span.StartSpan( + spanContext, + recordSpanOptions, + SPAN_NAME, + SpanKind.Internal, + parentSpanId, + TraceParams.Default, + startEndHandler, + timestampConverter); + + span.IsSampleToLocalSpanStore = true; + span.End(); + Assert.True(span.IsSampleToLocalSpanStore); + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs b/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs index f227affc1e0..9fbcd9ba9ad 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs @@ -19,68 +19,59 @@ namespace OpenTelemetry.Trace.Test using System; using System.Collections.Generic; - public class TestSpan : SpanBase + public class TestSpan : ISpan { - public TestSpan(SpanContext context, SpanOptions options) - : base(context, options) + public TestSpan() { } - public override DateTimeOffset EndTime { get; } - - public override TimeSpan Latency { get; } - - public override bool IsSampleToLocalSpanStore { get; } - - public override Status Status { get; set; } - - public override string Name { get; protected set; } - - public override SpanId ParentSpanId { get; } - - public override bool HasEnded => true; - - public override bool IsRecordingEvents => this.Options.HasFlag(SpanOptions.RecordEvents); + public SpanContext Context { get; } + public bool IsRecordingEvents { get; } + public Status Status { get; set; } + public bool HasEnded { get; } + public void UpdateName(string name) + { + throw new NotImplementedException(); + } - public override void AddEvent(string name, IDictionary attributes) + public void SetAttribute(string key, IAttributeValue value) { } - public override void AddEvent(IEvent addEvent) + public void SetAttribute(string key, string value) { } - public override void AddLink(ILink link) + public void SetAttribute(string key, long value) { } - public override void End(EndSpanOptions options) + public void SetAttribute(string key, double value) { } - public override void SetAttribute(string key, IAttributeValue value) + public void SetAttribute(string key, bool value) { } - public override void SetAttribute(string key, string value) + public void AddEvent(string name) { } - public override void SetAttribute(string key, long value) + public void AddEvent(string name, IDictionary attributes) { } - public override void SetAttribute(string key, double value) + public void AddEvent(IEvent newEvent) { } - public override void SetAttribute(string key, bool value) + public void AddLink(ILink link) { } - public override SpanData ToSpanData() + public void End() { - return null; } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs deleted file mode 100644 index 678905342e3..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerBaseTest.cs +++ /dev/null @@ -1,182 +0,0 @@ -// -// 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.Test -{ - using System; - using Moq; - using OpenTelemetry.Trace.Internal; - using Xunit; - - public class TracerBaseTest - { - private static readonly ITracer noopTracer = TracerBase.NoopTracer; - private static readonly string SPAN_NAME = "MySpanName"; - private readonly TracerBase tracer = Mock.Of(); - private readonly SpanBuilderBase spanBuilder = new Mock(SpanKind.Internal).Object; - private readonly SpanBase span = Mock.Of(); - - public TracerBaseTest() - { - } - - [Fact] - public void DefaultGetCurrentSpan() - { - Assert.Equal(BlankSpan.Instance, noopTracer.CurrentSpan); - } - - [Fact] - public void WithSpan_NullSpan() - { - Assert.Throws(() => noopTracer.WithSpan(null)); - } - - [Fact] - public void GetCurrentSpan_WithSpan() - { - Assert.Same(BlankSpan.Instance, noopTracer.CurrentSpan); - var ws = noopTracer.WithSpan(span); - try - { - Assert.Same(span, noopTracer.CurrentSpan); - } - finally - { - ws.Dispose(); - } - Assert.Same(BlankSpan.Instance, noopTracer.CurrentSpan); - } - - // [Fact] - // public void wrapRunnable() - // { - // Runnable runnable; - // Assert.Equal(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.Instance); - // runnable = - // tracer.withSpan( - // span, - // new Runnable() { - // @Override - // public void run() - // { - // Assert.Equal(noopTracer.getCurrentSpan()).isSameAs(span); - // } - // }); - // // When we run the runnable we will have the span in the current Context. - // runnable.run(); - // verifyZeroInteractions(span); - // Assert.Equal(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.Instance); - // } - - // [Fact] - // public void wrapCallable() throws Exception - // { - // readonly Object ret = new Object(); - // Callable callable; - // Assert.Equal(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.Instance); - // callable = - // tracer.withSpan( - // span, - // new Callable() { - // @Override - // public Object call() throws Exception - // { - // Assert.Equal(noopTracer.getCurrentSpan()).isSameAs(span); - // return ret; - // } - // }); - // // When we call the callable we will have the span in the current Context. - // Assert.Equal(callable.call()).isEqualTo(ret); - // verifyZeroInteractions(span); - // Assert.Equal(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.Instance); - // } - - [Fact] - public void SpanBuilderWithName_NullName() - { - Assert.Throws(() => noopTracer.SpanBuilder(null)); - } - - [Fact] - public void DefaultSpanBuilderWithName() - { - Assert.Same(BlankSpan.Instance, noopTracer.SpanBuilder(SPAN_NAME).StartSpan()); - } - - [Fact] - public void SpanBuilderWithParentAndName_NullName() - { - Assert.Throws(() => noopTracer.SpanBuilderWithParent(name: null, parent: null)); - } - - [Fact] - public void DefaultSpanBuilderWithParentAndName() - { - Assert.Same(BlankSpan.Instance, noopTracer.SpanBuilderWithParent(SPAN_NAME, parent: null).StartSpan()); - } - - [Fact] - public void DefaultSpanBuilderWithParentContext_NullName() - { - Assert.Throws(() => noopTracer.SpanBuilderWithParentContext(null, parentContext: null)); - } - - [Fact] - public void DefaultSpanBuilderWithParentContext_NullParent() - { - Assert.Same(BlankSpan.Instance, noopTracer.SpanBuilderWithParentContext(SPAN_NAME, parentContext: null).StartSpan()); - } - - [Fact] - public void DefaultSpanBuilderWithParentContext() - { - Assert.Same(BlankSpan.Instance, noopTracer.SpanBuilderWithParentContext(SPAN_NAME, parentContext: SpanContext.Blank).StartSpan()); - } - - [Fact] - public void StartSpanWithParentFromContext() - { - var ws = tracer.WithSpan(span); - try - { - Assert.Same(span, tracer.CurrentSpan); - Mock.Get(tracer).Setup((tracer) => tracer.SpanBuilderWithParent(SPAN_NAME, SpanKind.Internal, span)).Returns(spanBuilder); - Assert.Same(spanBuilder, tracer.SpanBuilder(SPAN_NAME)); - } - finally - { - ws.Dispose(); - } - } - - [Fact] - public void StartSpanWithInvalidParentFromContext() - { - var ws = tracer.WithSpan(BlankSpan.Instance); - try - { - Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); - Mock.Get(tracer).Setup((t) => t.SpanBuilderWithParent(SPAN_NAME, SpanKind.Internal, BlankSpan.Instance)).Returns(spanBuilder); - Assert.Same(spanBuilder, tracer.SpanBuilder(SPAN_NAME)); - } - finally - { - ws.Dispose(); - } - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index ef58992fa15..66f7fad7323 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -14,8 +14,11 @@ // limitations under the License. // +using OpenTelemetry.Trace.Sampler; + namespace OpenTelemetry.Trace.Test { + using System; using Moq; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; @@ -23,7 +26,7 @@ namespace OpenTelemetry.Trace.Test public class TracerTest { - private const string SPAN_NAME = "MySpanName"; + private const string SpanName = "MySpanName"; private readonly IStartEndHandler startEndHandler; private readonly ITraceConfig traceConfig; private readonly Tracer tracer; @@ -39,15 +42,55 @@ public TracerTest() [Fact] public void CreateSpanBuilder() { - var spanBuilder = tracer.SpanBuilderWithParent(SPAN_NAME, parent: BlankSpan.Instance); + var spanBuilder = tracer.SpanBuilder(SpanName); Assert.IsType(spanBuilder); } [Fact] - public void CreateSpanBuilderWithRemoteParet() + public void CreateSpanBuilderWithNullName() { - var spanBuilder = tracer.SpanBuilderWithParentContext(SPAN_NAME, parentContext: SpanContext.Blank); - Assert.IsType(spanBuilder); + Assert.Throws(() => tracer.SpanBuilder(null)); + } + + [Fact] + public void GetCurrentSpanBlank() + { + Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); + } + + [Fact] + public void GetCurrentSpan() + { + var traceParams = Mock.Of(); + Mock.Get(traceParams).Setup(p => p.Sampler).Returns(Samplers.AlwaysSample); + Mock.Get(traceConfig).Setup(c => c.ActiveTraceParams).Returns(traceParams); + + var span = tracer.SpanBuilder("foo").StartSpan(); + using (tracer.WithSpan(span)) + { + Assert.Same(span, tracer.CurrentSpan); + } + Assert.Same(BlankSpan.Instance, tracer.CurrentSpan); + } + + [Fact] + public void WithSpanNull() + { + Assert.Throws(() => tracer.WithSpan(null)); + } + + [Fact] + public void GetTextFormat() + { + Assert.NotNull(tracer.TextFormat); + } + + [Fact] + public void GetBinaryFormat() + { + Assert.NotNull(tracer.BinaryFormat); } + + // TODO test for sampler } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs index 2b9a10ebb9e..6b997344b22 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs @@ -58,7 +58,7 @@ public class TracingTest [Fact(Skip = "need to fix the way tracer being instantiated")] public void DefaultTracer() { - Assert.Same(Tracer.NoopTracer, Tracing.Tracer); + Assert.Same(NoopTracer.Instance, Tracing.Tracer); } [Fact(Skip = "need to fix the way tracer being instantiated")] From e511e843c997833f4c483dc240174bc6a14c3f7a Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 10 Jul 2019 00:11:06 -0700 Subject: [PATCH 10/41] Add prerequisites to CONTRIBUTING (#141) --- CONTRIBUTING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b71bb710aab..12b56566220 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,6 +42,12 @@ Remember to always work in a branch of your local copy, as you might otherwise h Please also see [GitHub workflow](https://github.com/open-telemetry/community/blob/master/CONTRIBUTING.md#github-workflow) section of general project contributing guide. +### Prerequisites + +* Git client and command line tools. You may use Visual Studio to clone the repo, but we use [SourceLink](https://github.com/dotnet/sourcelink) to build and it needs git. +* Visual Studio 2017+ or VS Code +* .NET Framework 4.6+ and .NET Core 2.1+ + ### Build You can use Visual Studio 2017+ or VS Code to contribute. Just open root folder From 9523c3110c3d0f4a460157f54ff84814bf6785f3 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 11 Jul 2019 12:10:38 -0700 Subject: [PATCH 11/41] Use ActivityTraceId and ActivitySpanId (#136) --- Directory.Build.props | 1 + .../Context/Propagation/BinaryFormat.cs | 46 ++-- .../Context/Propagation/TraceContextFormat.cs | 75 ++++--- .../OpenTelemetry.Abstractions.csproj | 4 + .../Properties/AssemblyInfo.cs | 4 +- .../Trace/ISampler.cs | 3 +- src/OpenTelemetry.Abstractions/Trace/Link.cs | 4 +- .../Sampler/Internal/AlwaysSampleSampler.cs | 3 +- .../Sampler/Internal/NeverSampleSampler.cs | 3 +- .../Trace/SpanContext.cs | 44 ++-- .../Trace/SpanData.cs | 11 +- .../Trace/SpanId.cs | 181 --------------- .../Trace/TraceId.cs | 209 ------------------ .../Trace/TraceOptions.cs | 200 ----------------- .../Trace/TraceOptionsBuilder.cs | 64 ------ .../Utils/Arrays.cs | 145 ------------ .../AssemblyInfo.cs} | 10 +- .../OpenTelemetry.Collector.AspNetCore.csproj | 1 - .../AssemblyInfo.cs | 2 - ...penTelemetry.Collector.Dependencies.csproj | 1 - .../RedisProfilerEntryToSpanConverter.cs | 27 ++- .../StackExchangeRedisCallsCollector.cs | 4 +- .../Implementation/TraceExporterHandler.cs | 13 +- ...ataExtentions.cs => SpanDataExtensions.cs} | 37 +++- .../AssemblyInfo.cs | 2 - .../Implementation/SpanExtensions.cs | 10 +- .../AssemblyInfo.cs | 1 - .../Implementation/TraceExporterHandler.cs | 13 +- .../Implementation/ZipkinSpan.cs | 8 +- .../Context/Propagation/B3Format.cs | 25 ++- src/OpenTelemetry/Properties/AssemblyInfo.cs | 4 +- .../SpanStore/InProcessSampledSpanStore.cs | 3 +- .../Trace/Internal/RandomGenerator.cs | 58 ----- .../Trace/Internal/StartEndHandler.cs | 5 +- .../Trace/Sampler/ProbabilitySampler.cs | 25 ++- src/OpenTelemetry/Trace/Span.cs | 11 +- src/OpenTelemetry/Trace/SpanBuilder.cs | 40 ++-- src/OpenTelemetry/Trace/SpanBuilderOptions.cs | 5 +- src/OpenTelemetry/Trace/TraceComponent.cs | 7 +- src/OpenTelemetry/Trace/Tracer.cs | 8 +- src/OpenTelemetry/Trace/Tracing.cs | 2 +- .../BasicTests.cs | 11 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 2 +- .../BasicTests.cs | 7 +- .../HttpClientTests.cs | 2 +- ...ofilerEntryToSpanConverterSamplingTests.cs | 30 +-- .../RedisProfilerEntryToSpanConverterTests.cs | 12 +- .../StackExchangeRedisCallsCollectorTests.cs | 2 +- .../TraceExporterHandlerTests.cs | 49 ++-- .../Impl/Trace/CurrentSpanUtilsTest.cs | 15 +- .../Export/InProcessRunningSpanStoreTest.cs | 49 ++-- .../Export/InProcessSampledSpanStoreTest.cs | 17 +- .../Impl/Trace/Export/SpanDataTest.cs | 12 +- .../Impl/Trace/Export/SpanExporterTest.cs | 10 +- .../Impl/Trace/LinkTest.cs | 4 +- .../Impl/Trace/NoopTracerTests.cs | 2 +- .../Impl/Trace/Propagation/B3FormatTest.cs | 79 +++---- .../Trace/Propagation/BinaryFormatTest.cs | 31 +-- .../Trace/Propagation/TraceContextTest.cs | 9 +- .../Impl/Trace/Sampler/SamplersTest.cs | 33 ++- .../Impl/Trace/SpanBuilderTest.cs | 164 ++++++-------- .../Impl/Trace/SpanContextTest.cs | 59 ++--- .../Impl/Trace/SpanIdTest.cs | 93 -------- .../Impl/Trace/SpanTest.cs | 75 +++---- .../Impl/Trace/TraceComponentTest.cs | 2 +- .../Impl/Trace/TraceIdTest.cs | 96 -------- .../Impl/Trace/TraceOptionsTest.cs | 82 ------- .../Impl/Trace/TracerTest.cs | 2 +- 68 files changed, 589 insertions(+), 1679 deletions(-) delete mode 100644 src/OpenTelemetry.Abstractions/Trace/SpanId.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/TraceId.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/TraceOptionsBuilder.cs delete mode 100644 src/OpenTelemetry.Abstractions/Utils/Arrays.cs rename src/{OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs => OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs} (75%) rename src/OpenTelemetry.Exporter.Ocagent/Implementation/{SpanDataExtentions.cs => SpanDataExtensions.cs} (81%) delete mode 100644 src/OpenTelemetry/Trace/Internal/RandomGenerator.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/SpanIdTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/TraceIdTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/TraceOptionsTest.cs diff --git a/Directory.Build.props b/Directory.Build.props index 3dcd994492e..abd99817026 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,5 +2,6 @@ git https://github.com/open-telemetry/opentelemetry-dotnet + 7.3 \ No newline at end of file diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs index ebcda32141c..f4a661e793b 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs @@ -17,12 +17,16 @@ namespace OpenTelemetry.Context.Propagation { using System; + using System.Diagnostics; using OpenTelemetry.Trace; public class BinaryFormat : IBinaryFormat { private const byte VersionId = 0; private const int VersionIdOffset = 0; + private const int TraceIdSize = 16; + private const int SpanIdSize = 8; + private const int TraceOptionsSize = 1; // The version_id/field_id size in bytes. private const byte IdSize = 1; @@ -30,12 +34,12 @@ public class BinaryFormat : IBinaryFormat private const int TraceIdFieldIdOffset = VersionIdOffset + IdSize; private const int TraceIdOffset = TraceIdFieldIdOffset + IdSize; private const byte SpanIdFieldId = 1; - private const int SpaneIdFieldIdOffset = TraceIdOffset + TraceId.Size; + private const int SpaneIdFieldIdOffset = TraceIdOffset + TraceIdSize; private const int SpanIdOffset = SpaneIdFieldIdOffset + IdSize; private const byte TraceOptionsFieldId = 2; - private const int TraceOptionFieldIdOffset = SpanIdOffset + SpanId.Size; + private const int TraceOptionFieldIdOffset = SpanIdOffset + SpanIdSize; private const int TraceOptionOffset = TraceOptionFieldIdOffset + IdSize; - private const int FormatLength = (4 * IdSize) + TraceId.Size + SpanId.Size + TraceOptions.Size; + private const int FormatLength = (4 * IdSize) + TraceIdSize + SpanIdSize + TraceOptionsSize; public SpanContext FromByteArray(byte[] bytes) { @@ -49,28 +53,29 @@ public SpanContext FromByteArray(byte[] bytes) throw new SpanContextParseException("Unsupported version."); } - var traceId = TraceId.Invalid; - var spanId = SpanId.Invalid; - var traceOptions = TraceOptions.Default; + ActivityTraceId traceId = default; + ActivitySpanId spanId = default; + var traceOptions = ActivityTraceFlags.None; + var traceparentBytes = new ReadOnlySpan(bytes); var pos = 1; try { if (bytes.Length > pos && bytes[pos] == TraceIdFieldId) { - traceId = TraceId.FromBytes(bytes, pos + IdSize); - pos += IdSize + TraceId.Size; + traceId = ActivityTraceId.CreateFromBytes(traceparentBytes.Slice(pos + IdSize, 16)); + pos += IdSize + TraceIdSize; } if (bytes.Length > pos && bytes[pos] == SpanIdFieldId) { - spanId = SpanId.FromBytes(bytes, pos + IdSize); - pos += IdSize + SpanId.Size; + spanId = ActivitySpanId.CreateFromBytes(traceparentBytes.Slice(pos + IdSize, 8)); + pos += IdSize + SpanIdSize; } if (bytes.Length > pos && bytes[pos] == TraceOptionsFieldId) { - traceOptions = TraceOptions.FromBytes(bytes, pos + IdSize); + traceOptions = (ActivityTraceFlags)traceparentBytes[pos + IdSize]; } return SpanContext.Create(traceId, spanId, traceOptions, Tracestate.Empty); @@ -88,15 +93,16 @@ public byte[] ToByteArray(SpanContext spanContext) throw new ArgumentNullException(nameof(spanContext)); } - var bytes = new byte[FormatLength]; - bytes[VersionIdOffset] = VersionId; - bytes[TraceIdFieldIdOffset] = TraceIdFieldId; - spanContext.TraceId.CopyBytesTo(bytes, TraceIdOffset); - bytes[SpaneIdFieldIdOffset] = SpanIdFieldId; - spanContext.SpanId.CopyBytesTo(bytes, SpanIdOffset); - bytes[TraceOptionFieldIdOffset] = TraceOptionsFieldId; - spanContext.TraceOptions.CopyBytesTo(bytes, TraceOptionOffset); - return bytes; + Span spanBytes = stackalloc byte[FormatLength]; + spanBytes[VersionIdOffset] = VersionId; + spanBytes[TraceIdFieldIdOffset] = TraceIdFieldId; + spanBytes[SpaneIdFieldIdOffset] = SpanIdFieldId; + spanBytes[TraceOptionFieldIdOffset] = TraceOptionsFieldId; + spanBytes[TraceOptionOffset] = (byte)spanContext.TraceOptions; + spanContext.TraceId.CopyTo(spanBytes.Slice(TraceIdOffset)); + spanContext.SpanId.CopyTo(spanBytes.Slice(SpanIdOffset)); + + return spanBytes.ToArray(); } } } diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs index f8042318847..bd56c1a817d 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Context.Propagation { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Text; using OpenTelemetry.Trace; @@ -35,6 +36,7 @@ public class TraceContextFormat : ITextFormat private static readonly int SpanIdLength = "00f067aa0ba902b7".Length; private static readonly int VersionAndTraceIdAndSpanIdLength = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-".Length; private static readonly int OptionsLength = "00".Length; + private static readonly int TraceparentLengthV0 = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-00".Length; /// public ISet Fields => new HashSet { "tracestate", "traceparent" }; @@ -47,13 +49,13 @@ public SpanContext Extract(T carrier, Func> ge var traceparentCollection = getter(carrier, "traceparent"); var tracestateCollection = getter(carrier, "tracestate"); - if (traceparentCollection.Count() > 1) + if (traceparentCollection != null && traceparentCollection.Count() > 1) { // multiple traceparent are not allowed return SpanContext.Blank; } - var traceparent = traceparentCollection?.FirstOrDefault(); + var traceparent = traceparentCollection.First(); var traceparentParsed = this.TryExtractTraceparent(traceparent, out var traceId, out var spanId, out var traceoptions); if (!traceparentParsed) @@ -165,8 +167,8 @@ public SpanContext Extract(T carrier, Func> ge /// public void Inject(SpanContext spanContext, T carrier, Action setter) { - var traceparent = string.Concat("00-", spanContext.TraceId.ToLowerBase16(), "-", spanContext.SpanId.ToLowerBase16()); - traceparent = string.Concat(traceparent, spanContext.TraceOptions.IsSampled ? "-01" : "-00"); + var traceparent = string.Concat("00-", spanContext.TraceId.ToHexString(), "-", spanContext.SpanId.ToHexString()); + traceparent = string.Concat(traceparent, (spanContext.TraceOptions & ActivityTraceFlags.Recorded) != 0 ? "-01" : "-00"); setter(carrier, "traceparent", traceparent); @@ -193,50 +195,51 @@ public void Inject(SpanContext spanContext, T carrier, Action 0) + if (version0 > 0) { // expected version is 00 // for higher versions - best attempt parsing of trace id, span id, etc. bestAttempt = true; } - if (traceparent.Length < VersionAndTraceIdLength || traceparent[VersionAndTraceIdLength - 1] != '-') + if (traceparent[VersionAndTraceIdLength - 1] != '-') { return false; } try { - traceId = TraceId.FromBytes(Arrays.StringToByteArray(traceparent, VersionPrefixIdLength, TraceIdLength)); + traceId = ActivityTraceId.CreateFromString(traceparent.AsSpan().Slice(VersionPrefixIdLength, TraceIdLength)); } catch (ArgumentOutOfRangeException) { @@ -244,14 +247,14 @@ private bool TryExtractTraceparent(string traceparent, out TraceId traceId, out return false; } - if (traceparent.Length < VersionAndTraceIdAndSpanIdLength || traceparent[VersionAndTraceIdAndSpanIdLength - 1] != '-') + if (traceparent[VersionAndTraceIdAndSpanIdLength - 1] != '-') { return false; } try { - spanId = SpanId.FromBytes(Arrays.StringToByteArray(traceparent, VersionAndTraceIdLength, SpanIdLength)); + spanId = ActivitySpanId.CreateFromString(traceparent.AsSpan().Slice(VersionAndTraceIdLength, SpanIdLength)); } catch (ArgumentOutOfRangeException) { @@ -259,16 +262,13 @@ private bool TryExtractTraceparent(string traceparent, out TraceId traceId, out return false; } - if (traceparent.Length < VersionAndTraceIdAndSpanIdLength + OptionsLength) - { - return false; - } - - byte[] optionsArray; + byte options0; + byte options1; try { - optionsArray = Arrays.StringToByteArray(traceparent, VersionAndTraceIdAndSpanIdLength, OptionsLength); + options0 = this.HexCharToByte(traceparent[VersionAndTraceIdAndSpanIdLength]); + options1 = this.HexCharToByte(traceparent[VersionAndTraceIdAndSpanIdLength]); } catch (ArgumentOutOfRangeException) { @@ -276,9 +276,9 @@ private bool TryExtractTraceparent(string traceparent, out TraceId traceId, out return false; } - if ((optionsArray[0] | 1) == 1) + if ((options0 | 1) == 1) { - traceoptions = TraceOptions.Builder().SetIsSampled(true).Build(); + traceoptions |= ActivityTraceFlags.Recorded; } if ((!bestAttempt) && (traceparent.Length != VersionAndTraceIdAndSpanIdLength + OptionsLength)) @@ -288,8 +288,7 @@ private bool TryExtractTraceparent(string traceparent, out TraceId traceId, out if (bestAttempt) { - if ((traceparent.Length > VersionAndTraceIdAndSpanIdLength + OptionsLength) && - (traceparent[VersionAndTraceIdAndSpanIdLength + OptionsLength] != '-')) + if ((traceparent.Length > TraceparentLengthV0) && (traceparent[TraceparentLengthV0] != '-')) { return false; } @@ -297,5 +296,25 @@ private bool TryExtractTraceparent(string traceparent, out TraceId traceId, out return true; } + + private byte HexCharToByte(char c) + { + if ((c >= '0') && (c <= '9')) + { + return (byte)(c - '0'); + } + + if ((c >= 'a') && (c <= 'f')) + { + return (byte)(c - 'a' + 10); + } + + if ((c >= 'A') && (c <= 'F')) + { + return (byte)(c - 'A' + 10); + } + + throw new ArgumentOutOfRangeException("Invalid character: " + c); + } } } diff --git a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj index 5627e7283e8..d8b5a12eacf 100644 --- a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj +++ b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj @@ -5,4 +5,8 @@ OpenTelemetry .NET API abstractions OpenTelemetry + + + + \ No newline at end of file diff --git a/src/OpenTelemetry.Abstractions/Properties/AssemblyInfo.cs b/src/OpenTelemetry.Abstractions/Properties/AssemblyInfo.cs index 42f8afafa48..3c66417ce38 100644 --- a/src/OpenTelemetry.Abstractions/Properties/AssemblyInfo.cs +++ b/src/OpenTelemetry.Abstractions/Properties/AssemblyInfo.cs @@ -16,8 +16,6 @@ using System.Runtime.CompilerServices; -[assembly: System.CLSCompliant(true)] - [assembly: InternalsVisibleTo("OpenTelemetry.Tests" + AssemblyInfo.PublicKey)] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)] @@ -33,4 +31,4 @@ internal static class AssemblyInfo public const string PublicKey = ""; public const string MoqPublicKey = ""; } -#endif \ No newline at end of file +#endif diff --git a/src/OpenTelemetry.Abstractions/Trace/ISampler.cs b/src/OpenTelemetry.Abstractions/Trace/ISampler.cs index 9b97f960051..bcb0a16e5e4 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISampler.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace { using System.Collections.Generic; + using System.Diagnostics; /// /// Sampler to reduce data volume. This sampler executes before Span object was created. @@ -41,6 +42,6 @@ public interface ISampler /// /// Links associated with the span. /// True of span needs to be created. False otherwise. - bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable links); + bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IEnumerable links); } } diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index 6fa4a0008c0..dcd6d02e19f 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -56,8 +56,8 @@ public static ILink FromSpanContext(SpanContext context, IDictionary this.ToString(); /// - public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) + public bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IEnumerable parentLinks) { return true; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs index 22b1b856b9e..d34c8a7e785 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace.Sampler.Internal { using System.Collections.Generic; + using System.Diagnostics; /// internal sealed class NeverSampleSampler : ISampler @@ -28,7 +29,7 @@ internal NeverSampleSampler() public string Description => this.ToString(); /// - public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable links) + public bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IEnumerable links) { return false; } diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs b/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs index cc46ab3aceb..fc61f93202a 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs @@ -16,19 +16,21 @@ namespace OpenTelemetry.Trace { + using System.Diagnostics; + /// /// A class that represents a span context. A span context contains the state that must propagate to - /// child and across process boundaries. It contains the identifiers - /// and associated with the and a set of . + /// child and across process boundaries. It contains the identifiers + /// and associated with the and a set of . /// public sealed class SpanContext { /// /// A blank that can be used for no-op operations. /// - public static readonly SpanContext Blank = new SpanContext(Trace.TraceId.Invalid, Trace.SpanId.Invalid, TraceOptions.Default, Tracestate.Empty); + public static readonly SpanContext Blank = new SpanContext(default(ActivityTraceId), default(ActivitySpanId), ActivityTraceFlags.None, Tracestate.Empty); - private SpanContext(TraceId traceId, SpanId spanId, TraceOptions traceOptions, Tracestate tracestate) + private SpanContext(ActivityTraceId traceId, ActivitySpanId spanId, ActivityTraceFlags traceOptions, Tracestate tracestate) { this.TraceId = traceId; this.SpanId = spanId; @@ -37,24 +39,24 @@ private SpanContext(TraceId traceId, SpanId spanId, TraceOptions traceOptions, T } /// - /// Gets the associated with this . + /// Gets the associated with this . /// - public TraceId TraceId { get; } + public ActivityTraceId TraceId { get; } /// - /// Gets the associated with this . + /// Gets the associated with this . /// - public SpanId SpanId { get; } + public ActivitySpanId SpanId { get; } /// /// Gets the associated with this . /// - public TraceOptions TraceOptions { get; } + public ActivityTraceFlags TraceOptions { get; } /// /// Gets a value indicating whether this is valid. /// - public bool IsValid => this.TraceId.IsValid && this.SpanId.IsValid; + public bool IsValid => this.IsTraceIdValid(this.TraceId) && this.IsSpanIdValid(this.SpanId); /// /// Gets the associated with this . @@ -64,12 +66,12 @@ private SpanContext(TraceId traceId, SpanId spanId, TraceOptions traceOptions, T /// /// Creates a new with the given identifiers and options. /// - /// The to associate with the . - /// The to associate with the . + /// The to associate with the . + /// The to associate with the . /// The to associate with the . /// The to associate with the . /// A new with the given identifiers and options. - public static SpanContext Create(TraceId traceId, SpanId spanId, TraceOptions traceOptions, Tracestate tracestate) + public static SpanContext Create(ActivityTraceId traceId, ActivitySpanId spanId, ActivityTraceFlags traceOptions, Tracestate tracestate) { return new SpanContext(traceId, spanId, traceOptions, tracestate); } @@ -78,9 +80,9 @@ public static SpanContext Create(TraceId traceId, SpanId spanId, TraceOptions tr public override int GetHashCode() { var result = 1; - result = (31 * result) + (this.TraceId == null ? 0 : this.TraceId.GetHashCode()); - result = (31 * result) + (this.SpanId == null ? 0 : this.SpanId.GetHashCode()); - result = (31 * result) + (this.TraceOptions == null ? 0 : this.TraceOptions.GetHashCode()); + result = (31 * result) + this.TraceId.GetHashCode(); + result = (31 * result) + this.SpanId.GetHashCode(); + result = (31 * result) + this.TraceOptions.GetHashCode(); return result; } @@ -112,5 +114,15 @@ public override string ToString() + "traceOptions=" + this.TraceOptions + "}"; } + + private bool IsTraceIdValid(ActivityTraceId traceId) + { + return traceId != default; + } + + private bool IsSpanIdValid(ActivitySpanId spanId) + { + return spanId != default; + } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index 65e002d7796..c9f1aa42b28 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Trace { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using OpenTelemetry.Common; using OpenTelemetry.Resources; @@ -30,7 +31,7 @@ public class SpanData { internal SpanData( SpanContext context, - SpanId parentSpanId, + ActivitySpanId parentSpanId, Resource resource, string name, Timestamp startTimestamp, @@ -62,9 +63,9 @@ internal SpanData( public SpanContext Context { get; } /// - /// Gets the parent . + /// Gets the parent . /// - public SpanId ParentSpanId { get; } + public ActivitySpanId ParentSpanId { get; } /// /// Gets the this span was executed on. @@ -120,7 +121,7 @@ internal SpanData( /// Returns a new immutable . /// /// The of the . - /// The parent of the . null if the is a root. + /// The parent of the . null if the is a root. /// The this span was executed on. /// The name of the . /// The start of the . @@ -134,7 +135,7 @@ internal SpanData( /// A new immutable . public static SpanData Create( SpanContext context, - SpanId parentSpanId, + ActivitySpanId parentSpanId, Resource resource, string name, Timestamp startTimestamp, diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanId.cs b/src/OpenTelemetry.Abstractions/Trace/SpanId.cs deleted file mode 100644 index c23b1e56e39..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/SpanId.cs +++ /dev/null @@ -1,181 +0,0 @@ -// -// 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; - using OpenTelemetry.Utils; - - /// - /// Span identifier. - /// - public sealed class SpanId : IComparable - { - public const int Size = 8; - - private static readonly SpanId InvalidSpanId = new SpanId(new byte[Size]); - - private readonly byte[] bytes; - - private SpanId(byte[] bytes) - { - this.bytes = bytes; - } - - public static SpanId Invalid - { - get - { - return InvalidSpanId; - } - } - - /// - /// Gets the span identifier as bytes. - /// - public byte[] Bytes - { - get - { - var copyOf = new byte[Size]; - Buffer.BlockCopy(this.bytes, 0, copyOf, 0, Size); - return copyOf; - } - } - - /// - /// Gets a value indicating whether span identifier is valid. - /// - public bool IsValid - { - get { return !Arrays.Equals(this.bytes, InvalidSpanId.bytes); } - } - - public static SpanId FromBytes(byte[] buffer) - { - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - if (buffer.Length != Size) - { - throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", Size, buffer.Length)); - } - - var bytesCopied = new byte[Size]; - Buffer.BlockCopy(buffer, 0, bytesCopied, 0, Size); - return new SpanId(bytesCopied); - } - - public static SpanId FromBytes(byte[] src, int srcOffset) - { - var bytes = new byte[Size]; - Buffer.BlockCopy(src, srcOffset, bytes, 0, Size); - return new SpanId(bytes); - } - - public static SpanId FromLowerBase16(string src) - { - if (src.Length != 2 * Size) - { - throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", 2 * Size, src.Length)); - } - - var bytes = Arrays.StringToByteArray(src); - return new SpanId(bytes); - } - - public static SpanId GenerateRandomId(IRandomGenerator random) - { - var bytes = new byte[Size]; - do - { - random.NextBytes(bytes); - } - while (Arrays.Equals(bytes, InvalidSpanId.bytes)); - return new SpanId(bytes); - } - - /// - /// Copy span id as bytes into destination byte array. - /// - /// Destination byte array. - /// Offset to start writing from. - public void CopyBytesTo(byte[] dest, int destOffset) - { - Buffer.BlockCopy(this.bytes, 0, dest, destOffset, Size); - } - - /// - /// Gets the span identifier as a string. - /// - /// String representation of Span identifier. - public string ToLowerBase16() - { - var bytes = this.Bytes; - return Arrays.ByteArrayToString(bytes); - } - - /// - public override bool Equals(object obj) - { - if (obj == this) - { - return true; - } - - if (!(obj is SpanId)) - { - return false; - } - - var that = (SpanId)obj; - return Arrays.Equals(this.bytes, that.bytes); - } - - /// - public override int GetHashCode() - { - return Arrays.GetHashCode(this.bytes); - } - - /// - public override string ToString() - { - return "SpanId{" - + "bytes=" + this.ToLowerBase16() - + "}"; - } - - /// - public int CompareTo(SpanId other) - { - for (var i = 0; i < Size; i++) - { - if (this.bytes[i] != other.bytes[i]) - { - var b1 = (sbyte)this.bytes[i]; - var b2 = (sbyte)other.bytes[i]; - - return b1 < b2 ? -1 : 1; - } - } - - return 0; - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceId.cs b/src/OpenTelemetry.Abstractions/Trace/TraceId.cs deleted file mode 100644 index 3e42b61b8a5..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/TraceId.cs +++ /dev/null @@ -1,209 +0,0 @@ -// -// 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; - using OpenTelemetry.Utils; - - /// - /// Trace ID. - /// - public sealed class TraceId : IComparable - { - public const int Size = 16; - private static readonly TraceId InvalidTraceId = new TraceId(new byte[Size]); - - private readonly byte[] bytes; - - private TraceId(byte[] bytes) - { - this.bytes = bytes; - } - - public static TraceId Invalid - { - get - { - return InvalidTraceId; - } - } - - /// - /// Gets the bytes representation of a trace id. - /// - public byte[] Bytes - { - get - { - var copyOf = new byte[Size]; - Buffer.BlockCopy(this.bytes, 0, copyOf, 0, Size); - return copyOf; - } - } - - /// - /// Gets a value indicating whether trace if is valid. - /// - public bool IsValid - { - get - { - return !Arrays.Equals(this.bytes, InvalidTraceId.bytes); - } - } - - /// - /// Gets the lower long of the trace ID. - /// - public long LowerLong - { - get - { - long result = 0; - for (var i = 0; i < 8; i++) - { - result <<= 8; -#pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand - result |= this.bytes[i] & 0xff; -#pragma warning restore CS0675 // Bitwise-or operator used on a sign-extended operand - } - - if (result < 0) - { - return -result; - } - - return result; - } - } - - public static TraceId FromBytes(byte[] buffer) - { - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - if (buffer.Length != Size) - { - throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", Size, buffer.Length)); - } - - var bytesCopied = new byte[Size]; - Buffer.BlockCopy(buffer, 0, bytesCopied, 0, Size); - return new TraceId(bytesCopied); - } - - public static TraceId FromBytes(byte[] src, int srcOffset) - { - var bytes = new byte[Size]; - Buffer.BlockCopy(src, srcOffset, bytes, 0, Size); - return new TraceId(bytes); - } - - public static TraceId FromLowerBase16(string src) - { - if (src.Length != 2 * Size) - { - throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", 2 * Size, src.Length)); - } - - var bytes = Arrays.StringToByteArray(src); - return new TraceId(bytes); - } - - public static TraceId GenerateRandomId(IRandomGenerator random) - { - var bytes = new byte[Size]; - do - { - random.NextBytes(bytes); - } - while (Arrays.Equals(bytes, InvalidTraceId.bytes)); - return new TraceId(bytes); - } - - /// - /// Copy trace ID as bytes into the destination bytes array at a given offset. - /// - /// Destination bytes array. - /// Desitnation bytes array offset. - public void CopyBytesTo(byte[] dest, int destOffset) - { - Buffer.BlockCopy(this.bytes, 0, dest, destOffset, Size); - } - - /// - /// Gets the lower base 16 representaiton of the trace id. - /// - /// Canonical string representation of a trace id. - public string ToLowerBase16() - { - var bytes = this.Bytes; - var result = Arrays.ByteArrayToString(bytes); - return result; - } - - /// - public override bool Equals(object obj) - { - if (obj == this) - { - return true; - } - - if (!(obj is TraceId)) - { - return false; - } - - var that = (TraceId)obj; - return Arrays.Equals(this.bytes, that.bytes); - } - - /// - public override int GetHashCode() - { - return Arrays.GetHashCode(this.bytes); - } - - /// - public override string ToString() - { - return "TraceId{" - + "bytes=" + this.ToLowerBase16() - + "}"; - } - - public int CompareTo(TraceId other) - { - var that = other as TraceId; - for (var i = 0; i < Size; i++) - { - if (this.bytes[i] != that.bytes[i]) - { - var b1 = (sbyte)this.bytes[i]; - var b2 = (sbyte)that.bytes[i]; - - return b1 < b2 ? -1 : 1; - } - } - - return 0; - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs b/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs deleted file mode 100644 index e6483b4e4d5..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/TraceOptions.cs +++ /dev/null @@ -1,200 +0,0 @@ -// -// 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; - - /// - /// Trace options. - /// - public sealed class TraceOptions - { - /// - /// Size of trace options flag. - /// - public const int Size = 1; - - /// - /// Default trace options. Nothing set. - /// - public static readonly TraceOptions Default = new TraceOptions(DefaultOptions); - - /// - /// Sampled trace options. - /// - public static readonly TraceOptions Sampled = new TraceOptions(1); - - internal const byte DefaultOptions = 0; - - internal const byte IsSampledBit = 0x1; - - private byte options; - - internal TraceOptions(byte options) - { - this.options = options; - } - - /// - /// Gets the bytes representation of a trace options. - /// - public byte[] Bytes - { - get - { - var bytes = new byte[Size]; - bytes[0] = this.options; - return bytes; - } - } - - /// - /// Gets a value indicating whether span is sampled or not. - /// - public bool IsSampled - { - get - { - return this.HasOption(IsSampledBit); - } - } - - internal sbyte Options - { - get { return (sbyte)this.options; } - } - - /// - /// Deserializes trace options from bytes. - /// - /// Buffer to deserialize. - /// Trace options deserialized from the bytes array. - public static TraceOptions FromBytes(byte[] buffer) - { - if (buffer == null) - { - throw new ArgumentNullException("buffer"); - } - - if (buffer.Length != Size) - { - throw new ArgumentOutOfRangeException(string.Format("Invalid size: expected {0}, got {1}", Size, buffer.Length)); - } - - var bytesCopied = new byte[Size]; - Buffer.BlockCopy(buffer, 0, bytesCopied, 0, Size); - return new TraceOptions(bytesCopied[0]); - } - - /// - /// Trace options from bytes with the given offset. - /// - /// Buffer to sdeserialize trace optiosn from. - /// Buffer offset. - /// Trace options deserialized from the buffer. - public static TraceOptions FromBytes(byte[] src, int srcOffset) - { - if (srcOffset < 0 || srcOffset >= src.Length) - { - throw new IndexOutOfRangeException("srcOffset"); - } - - return new TraceOptions(src[srcOffset]); - } - - /// - /// Gets the trace options builder. - /// - /// Trace options builder. - public static TraceOptionsBuilder Builder() - { - return new TraceOptionsBuilder(DefaultOptions); - } - - /// - /// Trace options builder pre-initialized from the given trace options instance. - /// - /// Trace options to pre-initialize the builder. - /// Trace options builder. - public static TraceOptionsBuilder Builder(TraceOptions traceOptions) - { - return new TraceOptionsBuilder(traceOptions.options); - } - - /// - /// Serializes trace options into bytes array at a given offset. - /// - /// Destination to serialize value to. - /// Destintion offset. - public void CopyBytesTo(byte[] dest, int destOffset) - { - if (destOffset < 0 || destOffset >= dest.Length) - { - throw new IndexOutOfRangeException("destOffset"); - } - - dest[destOffset] = this.options; - } - - /// - public override bool Equals(object obj) - { - if (obj == this) - { - return true; - } - - if (!(obj is TraceOptions)) - { - return false; - } - - var that = (TraceOptions)obj; - return this.options == that.options; - } - - /// - public override int GetHashCode() - { - var result = (31 * 1) + this.options; - return result; - } - - /// - public override string ToString() - { - return "TraceOptions{" - + "sampled=" + this.IsSampled - + "}"; - } - - private bool HasOption(int mask) - { - return (this.options & mask) != 0; - } - - private void ClearOption(int mask) - { - this.options = (byte)(this.options & ~mask); - } - - private void SetOption(int mask) - { - this.options = (byte)(this.options | mask); - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceOptionsBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/TraceOptionsBuilder.cs deleted file mode 100644 index 09d3e72cbd8..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/TraceOptionsBuilder.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// 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 -{ - /// - /// Trace options builder. - /// - public class TraceOptionsBuilder - { - private byte options; - - internal TraceOptionsBuilder() - : this(TraceOptions.DefaultOptions) - { - } - - internal TraceOptionsBuilder(byte options) - { - this.options = options; - } - - /// - /// Sets is sampled flag. - /// - /// New value for the isSampled flag. - /// This builder for operations chaining. - public TraceOptionsBuilder SetIsSampled(bool isSampled) - { - if (isSampled) - { - this.options = (byte)(this.options | TraceOptions.IsSampledBit); - } - else - { - this.options = (byte)(this.options & ~TraceOptions.IsSampledBit); - } - - return this; - } - - /// - /// Builds span options from the values provided. - /// - /// Span options built by this builder. - public TraceOptions Build() - { - return new TraceOptions(this.options); - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Utils/Arrays.cs b/src/OpenTelemetry.Abstractions/Utils/Arrays.cs deleted file mode 100644 index 59ed7dfe6db..00000000000 --- a/src/OpenTelemetry.Abstractions/Utils/Arrays.cs +++ /dev/null @@ -1,145 +0,0 @@ -// -// 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.Utils -{ - using System; - using System.Text; - - internal static class Arrays - { - private static readonly uint[] ByteToHexLookupTable = CreateLookupTable(); - - public static bool Equals(byte[] array1, byte[] array2) - { - if (array1 == array2) - { - return true; - } - - if (array1 == null || array2 == null) - { - return false; - } - - if (array2.Length != array1.Length) - { - return false; - } - - for (var i = 0; i < array1.Length; i++) - { - if (array1[i] != array2[i]) - { - return false; - } - } - - return true; - } - - internal static int GetHashCode(byte[] array) - { - if (array == null) - { - return 0; - } - - var result = 1; - foreach (var b in array) - { - result = (31 * result) + b; - } - - return result; - } - - internal static int HexCharToInt(char c) - { - if ((c >= '0') && (c <= '9')) - { - return c - '0'; - } - - if ((c >= 'a') && (c <= 'f')) - { - return c - 'a' + 10; - } - - if ((c >= 'A') && (c <= 'F')) - { - return c - 'A' + 10; - } - - throw new ArgumentOutOfRangeException("Invalid character: " + c); - } - - // https://stackoverflow.com/a/24343727 - internal static uint[] CreateLookupTable() - { - var table = new uint[256]; - for (var i = 0; i < 256; i++) - { - var s = i.ToString("x2"); - table[i] = (uint)s[0]; - table[i] += (uint)s[1] << 16; - } - - return table; - } - - // https://stackoverflow.com/a/24343727 - internal static char[] ByteToHexCharArray(byte b) - { - var result = new char[2]; - - result[0] = (char)ByteToHexLookupTable[b]; - result[1] = (char)(ByteToHexLookupTable[b] >> 16); - - return result; - } - - internal static byte[] StringToByteArray(string src, int start = 0, int len = -1) - { - if (len == -1) - { - len = src.Length; - } - - var size = len / 2; - var bytes = new byte[size]; - for (int i = 0, j = start; i < size; i++) - { - var high = HexCharToInt(src[j++]); - var low = HexCharToInt(src[j++]); - bytes[i] = (byte)(high << 4 | low); - } - - return bytes; - } - - internal static string ByteArrayToString(byte[] bytes) - { - var sb = new StringBuilder(); - for (var i = 0; i < bytes.Length; i++) - { - sb.Append(ByteToHexCharArray(bytes[i])); - } - - return sb.ToString(); - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs b/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs similarity index 75% rename from src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs rename to src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs index a7b79c2b755..23da982fdad 100644 --- a/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,11 +13,3 @@ // See the License for the specific language governing permissions and // limitations under the License. // - -namespace OpenTelemetry.Trace -{ - public interface IRandomGenerator - { - void NextBytes(byte[] bytes); - } -} diff --git a/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj b/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj index e086dc0da8c..9fbdadc7244 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj +++ b/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj @@ -8,7 +8,6 @@ - diff --git a/src/OpenTelemetry.Collector.Dependencies/AssemblyInfo.cs b/src/OpenTelemetry.Collector.Dependencies/AssemblyInfo.cs index 69dc126db66..23da982fdad 100644 --- a/src/OpenTelemetry.Collector.Dependencies/AssemblyInfo.cs +++ b/src/OpenTelemetry.Collector.Dependencies/AssemblyInfo.cs @@ -13,5 +13,3 @@ // See the License for the specific language governing permissions and // limitations under the License. // - -[assembly: System.CLSCompliant(true)] diff --git a/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj b/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj index 8645907dcf3..9ffc850c8b1 100644 --- a/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj +++ b/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj @@ -12,7 +12,6 @@ - diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs index 862cacbcab4..bf3d8135bab 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation { using System; using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Common; using OpenTelemetry.Resources; using OpenTelemetry.Trace; @@ -46,12 +47,12 @@ public static void DrainSession(ISpan parentSpan, IEnumerable } } - internal static bool ShouldSample(SpanContext parentContext, string name, ISampler sampler, out SpanContext context, out SpanId parentSpanId) + internal static bool ShouldSample(SpanContext parentContext, string name, ISampler sampler, out SpanContext context, out ActivitySpanId parentSpanId) { - var traceId = TraceId.Invalid; + ActivityTraceId traceId = default; var tracestate = Tracestate.Empty; - parentSpanId = SpanId.Invalid; - var parentOptions = TraceOptions.Default; + parentSpanId = default; + var parentOptions = ActivityTraceFlags.None; if (parentContext.IsValid) { @@ -61,19 +62,21 @@ internal static bool ShouldSample(SpanContext parentContext, string name, ISampl } else { - traceId = TraceId.FromBytes(Guid.NewGuid().ToByteArray()); + traceId = ActivityTraceId.CreateRandom(); } - var result = parentOptions.IsSampled; - var spanId = SpanId.FromBytes(Guid.NewGuid().ToByteArray(), 8); - var traceOptions = TraceOptions.Default; + var result = (parentOptions & ActivityTraceFlags.Recorded) != 0; + var spanId = ActivitySpanId.CreateRandom(); + var traceOptions = ActivityTraceFlags.None; if (sampler != null) { - var builder = TraceOptions.Builder(parentContext.TraceOptions); + traceOptions = parentContext.TraceOptions; result = sampler.ShouldSample(parentContext, traceId, spanId, name, null); - builder = builder.SetIsSampled(result); - traceOptions = builder.Build(); + if (result) + { + traceOptions |= ActivityTraceFlags.Recorded; + } } context = SpanContext.Create(traceId, spanId, traceOptions, parentContext.Tracestate); @@ -81,7 +84,7 @@ internal static bool ShouldSample(SpanContext parentContext, string name, ISampl return result; } - internal static SpanData ProfiledCommandToSpanData(SpanContext context, string name, SpanId parentSpanId, IProfiledCommand command) + internal static SpanData ProfiledCommandToSpanData(SpanContext context, string name, ActivitySpanId parentSpanId, IProfiledCommand command) { // use https://github.com/opentracing/specification/blob/master/semantic_conventions.md for now diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs index 0194a3c97e0..c9d752905a6 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs @@ -86,8 +86,8 @@ public Func GetProfilerSessionsFactory() } // TODO: As a performance optimization the check for sampling may be implemented here - // The problem with this approach would be that SpanId cannot be generated here - // So if sampler uses SpanId in algorithm - results would be inconsistent + // The problem with this approach would be that ActivitySpanId cannot be generated here + // So if sampler uses ActivitySpanId in algorithm - results would be inconsistent var session = this.cache.GetOrAdd(span, (s) => new ProfilingSession(s)); return session; }; diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs index 8f2e3ebdd51..e273ffad11e 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs @@ -73,7 +73,6 @@ public Task ExportAsync(IEnumerable spanDataList) foreach (var attr in span.Attributes.AttributeMap) { var key = attr.Key; - switch (attr.Key) { case "span.kind": @@ -123,8 +122,8 @@ public Task ExportAsync(IEnumerable spanDataList) var linkId = 0; foreach (var link in span.Links.Links) { - AddPropertyWithAdjustedName(props, "link" + linkId + "_traceId", link.Context.TraceId.ToLowerBase16()); - AddPropertyWithAdjustedName(props, "link" + linkId + "_spanId", link.Context.SpanId.ToLowerBase16()); + AddPropertyWithAdjustedName(props, "link" + linkId + "_traceId", link.Context.TraceId.ToHexString()); + AddPropertyWithAdjustedName(props, "link" + linkId + "_spanId", link.Context.SpanId.ToHexString()); foreach (var attr in link.Attributes) { @@ -273,12 +272,12 @@ private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, ou props = new Dictionary(); - traceId = span.Context.TraceId.ToLowerBase16(); - spanId = span.Context.SpanId.ToLowerBase16(); + traceId = span.Context.TraceId.ToHexString(); + spanId = span.Context.SpanId.ToHexString(); parentId = null; - if (span.ParentSpanId != null && span.ParentSpanId.IsValid) + if (span.ParentSpanId != default) { - parentId = span.ParentSpanId.ToLowerBase16(); + parentId = span.ParentSpanId.ToHexString(); } resultCode = null; diff --git a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtentions.cs b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs similarity index 81% rename from src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtentions.cs rename to src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs index 628ed93cbc5..382583934e6 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtentions.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,12 +27,27 @@ namespace OpenTelemetry.Exporter.Ocagent.Implementation using OpenTelemetry.Trace; using OpenTelemetry.Trace.Export; - internal static class SpanDataExtentions + internal static class SpanDataExtensions { internal static Span ToProtoSpan(this SpanData spanData) { try { + // protobuf doesn't understand Span yet: https://github.com/protocolbuffers/protobuf/issues/3431 + Span traceIdBytes = stackalloc byte[16]; + Span spanIdBytes = stackalloc byte[8]; + + spanData.Context.TraceId.CopyTo(traceIdBytes); + spanData.Context.SpanId.CopyTo(spanIdBytes); + + var parentSpanIdString = ByteString.Empty; + if (spanData.ParentSpanId != default) + { + Span parentSpanIdBytes = stackalloc byte[8]; + spanData.ParentSpanId.CopyTo(parentSpanIdBytes); + parentSpanIdString = ByteString.CopyFrom(parentSpanIdBytes.ToArray()); + } + return new Span { Name = new TruncatableString { Value = spanData.Name }, @@ -40,10 +55,9 @@ internal static Span ToProtoSpan(this SpanData spanData) // TODO: Utilize new Span.Types.SpanKind below when updated protos are incorporated, also confirm default for SpanKind.Internal Kind = spanData.Kind == SpanKind.Client || spanData.Kind == SpanKind.Producer ? Span.Types.SpanKind.Client : Span.Types.SpanKind.Server, - TraceId = ByteString.CopyFrom(spanData.Context.TraceId.Bytes), - SpanId = ByteString.CopyFrom(spanData.Context.SpanId.Bytes), - ParentSpanId = - ByteString.CopyFrom(spanData.ParentSpanId?.Bytes ?? new byte[0]), + TraceId = ByteString.CopyFrom(traceIdBytes.ToArray()), + SpanId = ByteString.CopyFrom(spanIdBytes.ToArray()), + ParentSpanId = parentSpanIdString, StartTime = new Timestamp { @@ -119,11 +133,18 @@ private static Span.Types.TimeEvents FromITimeEvents(ITimedEvents events private static Span.Types.Link FromILink(ILink source) { + // protobuf doesn't understand Span yet: https://github.com/protocolbuffers/protobuf/issues/3431 + Span traceIdBytes = stackalloc byte[16]; + Span spanIdBytes = stackalloc byte[8]; + + source.Context.TraceId.CopyTo(traceIdBytes); + source.Context.SpanId.CopyTo(spanIdBytes); + var result = new Span.Types.Link { Attributes = FromIAttributeMap(source.Attributes), - TraceId = ByteString.CopyFrom(source.Context.TraceId.Bytes), - SpanId = ByteString.CopyFrom(source.Context.SpanId.Bytes), + TraceId = ByteString.CopyFrom(traceIdBytes.ToArray()), + SpanId = ByteString.CopyFrom(spanIdBytes.ToArray()), }; return result; diff --git a/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs index 69dc126db66..23da982fdad 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs +++ b/src/OpenTelemetry.Exporter.Prometheus/AssemblyInfo.cs @@ -13,5 +13,3 @@ // See the License for the specific language governing permissions and // limitations under the License. // - -[assembly: System.CLSCompliant(true)] diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs index f7ac0d61145..b0ceefcdecc 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs @@ -32,12 +32,12 @@ internal static class SpanExtensions /// . public static Google.Cloud.Trace.V2.Span ToSpan(this SpanData spanData, string projectId) { - var spanId = spanData.Context.SpanId.ToLowerBase16(); + var spanId = spanData.Context.SpanId.ToHexString(); // Base span settings var span = new Google.Cloud.Trace.V2.Span { - SpanName = new SpanName(projectId, spanData.Context.TraceId.ToLowerBase16(), spanId), + SpanName = new SpanName(projectId, spanData.Context.TraceId.ToHexString(), spanId), SpanId = spanId, DisplayName = new TruncatableString { Value = spanData.Name }, StartTime = spanData.StartTimestamp.ToTimestamp(), @@ -46,7 +46,7 @@ public static Google.Cloud.Trace.V2.Span ToSpan(this SpanData spanData, string p }; if (spanData.ParentSpanId != null) { - var parentSpanId = spanData.ParentSpanId.ToLowerBase16(); + var parentSpanId = spanData.ParentSpanId.ToHexString(); if (!string.IsNullOrEmpty(parentSpanId)) { span.ParentSpanId = parentSpanId; @@ -85,8 +85,8 @@ public static Google.Cloud.Trace.V2.Span ToSpan(this SpanData spanData, string p public static Google.Cloud.Trace.V2.Span.Types.Link ToLink(this ILink link) { var ret = new Google.Cloud.Trace.V2.Span.Types.Link(); - ret.SpanId = link.Context.SpanId.ToLowerBase16(); - ret.TraceId = link.Context.TraceId.ToLowerBase16(); + ret.SpanId = link.Context.SpanId.ToHexString(); + ret.TraceId = link.Context.TraceId.ToHexString(); if (link.Attributes != null) { diff --git a/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs index 19a0d2f9e69..23da982fdad 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/AssemblyInfo.cs @@ -13,4 +13,3 @@ // See the License for the specific language governing permissions and // limitations under the License. // -[assembly: System.CLSCompliant(true)] diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index d5de756ab20..3239292ab96 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Net; using System.Net.Http; using System.Net.Sockets; @@ -76,7 +77,7 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint var spanBuilder = ZipkinSpan.NewBuilder() - .TraceId(this.EncodeTraceId(context.TraceId)) + .ActivityTraceId(this.EncodeTraceId(context.TraceId)) .Id(this.EncodeSpanId(context.SpanId)) .Kind(this.ToSpanKind(spanData)) .Name(spanData.Name) @@ -84,7 +85,7 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint .Duration(endTimestamp - startTimestamp) .LocalEndpoint(localEndpoint); - if (spanData.ParentSpanId != null && spanData.ParentSpanId.IsValid) + if (spanData.ParentSpanId != default) { spanBuilder.ParentId(this.EncodeSpanId(spanData.ParentSpanId)); } @@ -131,9 +132,9 @@ private string AttributeValueToString(IAttributeValue attributeValue) (arg) => { return null; }); } - private string EncodeTraceId(TraceId traceId) + private string EncodeTraceId(ActivityTraceId traceId) { - var id = traceId.ToLowerBase16(); + var id = traceId.ToHexString(); if (id.Length > 16 && this.options.UseShortTraceIds) { @@ -143,9 +144,9 @@ private string EncodeTraceId(TraceId traceId) return id; } - private string EncodeSpanId(SpanId spanId) + private string EncodeSpanId(ActivitySpanId spanId) { - return spanId.ToLowerBase16(); + return spanId.ToHexString(); } private ZipkinSpanKind ToSpanKind(SpanData spanData) diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs index 48b9976fe81..07691a5c077 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation internal class ZipkinSpan { [JsonProperty("traceId")] - public string TraceId { get; set; } + public string ActivityTraceId { get; set; } [JsonProperty("parentId")] public string ParentId { get; set; } @@ -72,9 +72,9 @@ public class Builder { private readonly ZipkinSpan result = new ZipkinSpan(); - internal Builder TraceId(string val) + internal Builder ActivityTraceId(string val) { - this.result.TraceId = val; + this.result.ActivityTraceId = val; return this; } @@ -169,7 +169,7 @@ internal Builder AddAnnotation(long timestamp, string value) internal ZipkinSpan Build() { - if (this.result.TraceId == null) + if (this.result.ActivityTraceId == null) { throw new ArgumentException("Trace ID should not be null"); } diff --git a/src/OpenTelemetry/Context/Propagation/B3Format.cs b/src/OpenTelemetry/Context/Propagation/B3Format.cs index bcd2d38973f..a8d2928573b 100644 --- a/src/OpenTelemetry/Context/Propagation/B3Format.cs +++ b/src/OpenTelemetry/Context/Propagation/B3Format.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Context.Propagation { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using OpenTelemetry.Trace; @@ -32,8 +33,8 @@ public sealed class B3Format : ITextFormat internal static readonly string XB3Sampled = "X-B3-Sampled"; internal static readonly string XB3Flags = "X-B3-Flags"; - // Used as the upper TraceId.SIZE hex characters of the traceID. B3-propagation used to send - // TraceId.SIZE hex characters (8-bytes traceId) in the past. + // Used as the upper ActivityTraceId.SIZE hex characters of the traceID. B3-propagation used to send + // ActivityTraceId.SIZE hex characters (8-bytes traceId) in the past. internal static readonly string UpperTraceId = "0000000000000000"; // Sampled value via the X_B3_SAMPLED header. @@ -68,39 +69,39 @@ public SpanContext Extract(T carrier, Func> ge try { - TraceId traceId; + ActivityTraceId traceId; var traceIdStr = getter(carrier, XB3TraceId)?.FirstOrDefault(); if (traceIdStr != null) { - if (traceIdStr.Length == TraceId.Size) + if (traceIdStr.Length == 16) { // This is an 8-byte traceID. traceIdStr = UpperTraceId + traceIdStr; } - traceId = TraceId.FromLowerBase16(traceIdStr); + traceId = ActivityTraceId.CreateFromString(traceIdStr.AsSpan()); } else { throw new SpanContextParseException("Missing X_B3_TRACE_ID."); } - SpanId spanId; + ActivitySpanId spanId; var spanIdStr = getter(carrier, XB3SpanId)?.FirstOrDefault(); if (spanIdStr != null) { - spanId = SpanId.FromLowerBase16(spanIdStr); + spanId = ActivitySpanId.CreateFromString(spanIdStr.AsSpan()); } else { throw new SpanContextParseException("Missing X_B3_SPAN_ID."); } - var traceOptions = TraceOptions.Default; + var traceOptions = ActivityTraceFlags.None; if (SampledValue.Equals(getter(carrier, XB3Sampled)?.FirstOrDefault()) || FlagsValue.Equals(getter(carrier, XB3Flags)?.FirstOrDefault())) { - traceOptions = TraceOptions.Builder().SetIsSampled(true).Build(); + traceOptions |= ActivityTraceFlags.Recorded; } return SpanContext.Create(traceId, spanId, traceOptions, Tracestate.Empty); @@ -129,9 +130,9 @@ public void Inject(SpanContext spanContext, T carrier, Action -// 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.Internal -{ - using System; - - internal class RandomGenerator : IRandomGenerator - { - private static readonly Random Global = new Random(); - - [ThreadStatic] - private static Random local; - - private readonly int seed; - private readonly bool sameSeed; - - internal RandomGenerator() - { - this.sameSeed = false; - } - - /// - /// This constructur uses the same seed for all the thread static random objects. - /// You might get the same values if a random is accessed from different threads. - /// Use only for unit tests... - /// - /// The seeds value for the rng. - internal RandomGenerator(int seed) - { - this.sameSeed = true; - this.seed = seed; - } - - public void NextBytes(byte[] bytes) - { - if (local == null) - { - local = new Random(this.sameSeed ? this.seed : Global.Next()); - } - - local.NextBytes(bytes); - } - } -} diff --git a/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs b/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs index 66027fb7b65..60f3e355ae5 100644 --- a/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs +++ b/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs @@ -16,6 +16,7 @@ namespace OpenTelemetry.Trace.Internal { + using System.Diagnostics; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Export; @@ -42,7 +43,7 @@ public StartEndHandler(ISpanExporter spanExporter, IRunningSpanStore runningSpan public void OnEnd(ISpan span) { if ((span.IsRecordingEvents && this.enqueueEventForNonSampledSpans) - || span.Context.TraceOptions.IsSampled) + || (span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) { this.eventQueue.Enqueue(new SpanEndEvent(span, this.spanExporter, this.runningSpanStore, this.sampledSpanStore)); } @@ -97,7 +98,7 @@ public SpanEndEvent( public void Process() { - if (this.span.Context.TraceOptions.IsSampled) + if ((this.span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) { this.spanExporter.AddSpan(this.span); } diff --git a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs index 60e99c7903e..06a13a0322f 100644 --- a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs +++ b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Trace.Sampler { using System; using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Utils; /// @@ -66,10 +67,10 @@ public static ProbabilitySampler Create(double probability) } /// - public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable links) + public bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IEnumerable links) { // If the parent is sampled keep the sampling decision. - if (parentContext != null && parentContext.TraceOptions.IsSampled) + if (parentContext != null && (parentContext.TraceOptions & ActivityTraceFlags.Recorded) != 0) { return true; } @@ -79,7 +80,7 @@ public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId span // If any parent link is sampled keep the sampling decision. foreach (var parentLink in links) { - if (parentLink.Context.TraceOptions.IsSampled) + if ((parentLink.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) { return true; } @@ -93,7 +94,9 @@ public bool ShouldSample(SpanContext parentContext, TraceId traceId, SpanId span // while allowing for a (very) small chance of *not* sampling if the id == Long.MAX_VALUE. // This is considered a reasonable tradeoff for the simplicity/performance requirements (this // code is executed in-line for every Span creation). - return Math.Abs(traceId.LowerLong) < this.IdUpperBound; + Span traceIdBytes = stackalloc byte[16]; + traceId.CopyTo(traceIdBytes); + return Math.Abs(this.GetLowerLong(traceIdBytes)) < this.IdUpperBound; } /// @@ -132,5 +135,19 @@ public override int GetHashCode() h ^= (this.IdUpperBound >> 32) ^ this.IdUpperBound; return (int)h; } + + public long GetLowerLong(ReadOnlySpan bytes) + { + long result = 0; + for (var i = 0; i < 8; i++) + { + result <<= 8; +#pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand + result |= bytes[i] & 0xff; +#pragma warning restore CS0675 // Bitwise-or operator used on a sign-extended operand + } + + return result; + } } } diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index e68a8fc0a5d..0ea7dee2401 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Trace { using System; using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Resources; @@ -30,7 +31,7 @@ namespace OpenTelemetry.Trace /// public sealed class Span : ISpan, IElement { - private readonly SpanId parentSpanId; + private readonly ActivitySpanId parentSpanId; private readonly ITraceParams traceParams; private readonly IStartEndHandler startEndHandler; private readonly DateTimeOffset startTime; @@ -48,7 +49,7 @@ private Span( SpanOptions options, string name, SpanKind spanKind, - SpanId parentSpanId, + ActivitySpanId parentSpanId, ITraceParams traceParams, IStartEndHandler startEndHandler, Timer timestampConverter) @@ -171,7 +172,7 @@ public bool IsSampleToLocalSpanStore } } - public SpanId ParentSpanId => this.parentSpanId; + public ActivitySpanId ParentSpanId => this.parentSpanId; public bool HasEnded => this.hasBeenEnded; @@ -225,7 +226,7 @@ private TraceEvents InitializedLinks } } - private Status StatusWithDefault => this.status ?? Trace.Status.Ok; + private Status StatusWithDefault => this.status ?? Status.Ok; /// public void UpdateName(string name) @@ -503,7 +504,7 @@ internal static ISpan StartSpan( SpanOptions options, string name, SpanKind spanKind, - SpanId parentSpanId, + ActivitySpanId parentSpanId, ITraceParams traceParams, IStartEndHandler startEndHandler, Timer timestampConverter) diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index 7b6f11eeed9..397ae59d2e9 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Trace { using System; using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; @@ -149,41 +150,44 @@ public ISpan StartSpan() { SpanContext parentContext = FindParent(this.parentType, this.parent, this.parentSpanContext); var activeTraceParams = this.options.TraceConfig.ActiveTraceParams; - var random = this.options.RandomHandler; - TraceId traceId; - var spanId = SpanId.GenerateRandomId(random); - SpanId parentSpanId = null; - TraceOptionsBuilder traceOptionsBuilder; + ActivityTraceId traceId; + var spanId = ActivitySpanId.CreateRandom(); + + ActivitySpanId parentSpanId = default; + ActivityTraceFlags traceOptions = ActivityTraceFlags.None; + if (parentContext == null || !parentContext.IsValid) { // New root span. - traceId = TraceId.GenerateRandomId(random); - traceOptionsBuilder = TraceOptions.Builder(); + traceId = ActivityTraceId.CreateRandom(); } else { // New child span. traceId = parentContext.TraceId; parentSpanId = parentContext.SpanId; - traceOptionsBuilder = TraceOptions.Builder(parentContext.TraceOptions); + traceOptions = parentContext.TraceOptions; } - traceOptionsBuilder.SetIsSampled( - MakeSamplingDecision( + bool sampledIn = MakeSamplingDecision( parentContext, this.name, this.sampler, this.links, traceId, spanId, - activeTraceParams)); - var traceOptions = traceOptionsBuilder.Build(); - var spanOptions = SpanOptions.None; + activeTraceParams); - if (traceOptions.IsSampled || this.recordEvents) + var spanOptions = SpanOptions.None; + if (sampledIn || this.recordEvents) { + traceOptions |= ActivityTraceFlags.Recorded; spanOptions = SpanOptions.RecordEvents; } + else + { + traceOptions &= ~ActivityTraceFlags.Recorded; + } var span = Span.StartSpan( SpanContext.Create(traceId, spanId, traceOptions, parentContext?.Tracestate ?? Tracestate.Empty), @@ -204,7 +208,7 @@ private static bool IsAnyParentLinkSampled(List parentLinks) { foreach (var parentLink in parentLinks) { - if (parentLink.Context.TraceOptions.IsSampled) + if ((parentLink.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) { return true; } @@ -230,8 +234,8 @@ private static bool MakeSamplingDecision( string name, ISampler sampler, List parentLinks, - TraceId traceId, - SpanId spanId, + ActivityTraceId traceId, + ActivitySpanId spanId, ITraceParams activeTraceParams) { // If users set a specific sampler in the SpanBuilder, use it. @@ -250,7 +254,7 @@ private static bool MakeSamplingDecision( } // Parent is always different than null because otherwise we use the default sampler. - return parent.TraceOptions.IsSampled || IsAnyParentLinkSampled(parentLinks); + return (parent.TraceOptions & ActivityTraceFlags.Recorded) != 0 || IsAnyParentLinkSampled(parentLinks); } private static SpanContext FindParent(ParentType parentType, ISpan explicitParent, SpanContext remoteParent) diff --git a/src/OpenTelemetry/Trace/SpanBuilderOptions.cs b/src/OpenTelemetry/Trace/SpanBuilderOptions.cs index b1acd82c022..f1ff88707d9 100644 --- a/src/OpenTelemetry/Trace/SpanBuilderOptions.cs +++ b/src/OpenTelemetry/Trace/SpanBuilderOptions.cs @@ -20,15 +20,12 @@ namespace OpenTelemetry.Trace internal class SpanBuilderOptions { - internal SpanBuilderOptions(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig) + internal SpanBuilderOptions(IStartEndHandler startEndHandler, ITraceConfig traceConfig) { - this.RandomHandler = randomGenerator; this.StartEndHandler = startEndHandler; this.TraceConfig = traceConfig; } - internal IRandomGenerator RandomHandler { get; } - internal IStartEndHandler StartEndHandler { get; } internal ITraceConfig TraceConfig { get; } diff --git a/src/OpenTelemetry/Trace/TraceComponent.cs b/src/OpenTelemetry/Trace/TraceComponent.cs index 9eed9a59a02..adda5bee61b 100644 --- a/src/OpenTelemetry/Trace/TraceComponent.cs +++ b/src/OpenTelemetry/Trace/TraceComponent.cs @@ -30,16 +30,15 @@ public sealed class TraceComponent : ITraceComponent /// Initializes a new instance of the class. /// public TraceComponent() - : this(new RandomGenerator(), new SimpleEventQueue()) + : this(new SimpleEventQueue()) { } /// /// Initializes a new instance of the class. /// - /// Random numbers generator. /// Event queue to use before the exporter. - public TraceComponent(IRandomGenerator randomHandler, IEventQueue eventQueue) + public TraceComponent(IEventQueue eventQueue) { this.TraceConfig = new Config.TraceConfig(); @@ -59,7 +58,7 @@ public TraceComponent(IRandomGenerator randomHandler, IEventQueue eventQueue) ((ExportComponent)this.ExportComponent).RunningSpanStore, ((ExportComponent)this.ExportComponent).SampledSpanStore, eventQueue); - this.Tracer = new Tracer(randomHandler, startEndHandler, this.TraceConfig, null); + this.Tracer = new Tracer(startEndHandler, this.TraceConfig, null); } /// diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index b44c8d9aa36..2e56a94debc 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -30,14 +30,14 @@ public sealed class Tracer : ITracer private readonly SpanBuilderOptions spanBuilderOptions; private readonly IExportComponent exportComponent; - public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent) - : this(randomGenerator, startEndHandler, traceConfig, exportComponent, null, null) + public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent) + : this(startEndHandler, traceConfig, exportComponent, null, null) { } - public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent, IBinaryFormat binaryFormat, ITextFormat textFormat) + public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent, IBinaryFormat binaryFormat, ITextFormat textFormat) { - this.spanBuilderOptions = new SpanBuilderOptions(randomGenerator, startEndHandler, traceConfig); + this.spanBuilderOptions = new SpanBuilderOptions(startEndHandler, traceConfig); this.BinaryFormat = binaryFormat ?? new BinaryFormat(); this.TextFormat = textFormat ?? new TraceContextFormat(); this.exportComponent = exportComponent; diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index e76782bd280..40d7dadc823 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -32,7 +32,7 @@ public sealed class Tracing internal Tracing() { - this.traceComponent = new TraceComponent(new RandomGenerator(), new SimpleEventQueue()); + this.traceComponent = new TraceComponent(new SimpleEventQueue()); } /// diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index a6f81f5850f..2f8b9380315 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -27,6 +27,7 @@ namespace OpenTelemetry.Collector.AspNetCore.Tests using Moq; using Microsoft.AspNetCore.TestHost; using System; + using System.Diagnostics; using OpenTelemetry.Context.Propagation; using Microsoft.AspNetCore.Http; using System.Collections.Generic; @@ -47,7 +48,7 @@ public BasicTests(WebApplicationFactory factory) public async Task SuccesfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); void ConfigureTestServices(IServiceCollection services) => services.AddSingleton(tracer); @@ -92,18 +93,18 @@ public async Task SuccesfulTemplateControllerCallUsesParentContext() { var startEndHandler = new Mock(); - var expectedTraceId = TraceId.GenerateRandomId(new RandomGenerator()); - var expectedSpanId = SpanId.GenerateRandomId(new RandomGenerator()); + var expectedTraceId = ActivityTraceId.CreateRandom(); + var expectedSpanId = ActivitySpanId.CreateRandom(); var tf = new Mock(); tf.Setup(m => m.Extract(It.IsAny(), It.IsAny>>())).Returns(SpanContext.Create( expectedTraceId, expectedSpanId, - TraceOptions.Default, + ActivityTraceFlags.None, Tracestate.Empty )); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null, null, tf.Object); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); // 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 90cb12b4bc0..2a8a091e116 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -55,7 +55,7 @@ public override async Task ProcessAsync(HttpContext context) public async Task SuccesfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); // 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 29f5f1d2f77..ebb496df0e7 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -23,6 +23,7 @@ namespace OpenTelemetry.Collector.Dependencies.Tests using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Sampler; using System; + using System.Diagnostics; using System.Net.Http; using System.Threading.Tasks; using Xunit; @@ -45,8 +46,8 @@ public async Task HttpDepenenciesCollectorInjectsHeadersAsync() var url = $"http://{host}:{port}/"; - var expectedTraceId = TraceId.Invalid; - var expectedSpanId = SpanId.Invalid; + ActivityTraceId expectedTraceId = default; + ActivitySpanId expectedSpanId = default; using (serverLifeTime) { @@ -59,7 +60,7 @@ public async Task HttpDepenenciesCollectorInjectsHeadersAsync() expectedSpanId = sc.SpanId; }); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null, null, tf.Object); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); using (var dc = new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) { diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index d2a5c1cb8ca..3a01b3aa740 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -99,7 +99,7 @@ public async Task HttpOutCallsAreCollectedSuccesfullyAsync(HttpOutTestCase tc) out var port); var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); tc.url = NormaizeValues(tc.url, host, port); using (serverLifeTime) diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs index 3593e9ec80b..50cf6593012 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterSamplingTests.cs @@ -16,6 +16,7 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation { + using System.Diagnostics; using Moq; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Internal; @@ -30,8 +31,8 @@ public void ShouldSampleRespectsSamplerChoice() var m = new Mock(); m.Setup(x => x.ShouldSample( It.IsAny(), - It.IsAny(), - It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>())).Returns(true); @@ -40,8 +41,8 @@ public void ShouldSampleRespectsSamplerChoice() m = new Mock(); m.Setup(x => x.ShouldSample( It.IsAny(), - It.IsAny(), - It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>())).Returns(false); @@ -58,15 +59,14 @@ public void ShouldSampleDoesntThrowWithoutSampler() public void ShouldSamplePassesArgumentsToSamplerAndReturnsInContext() { var m = new Mock(); - var r = new RandomGenerator(); - var traceId = TraceId.GenerateRandomId(r); - var parentContext = SpanContext.Create(traceId, SpanId.GenerateRandomId(r), TraceOptions.Sampled, Tracestate.Builder.Set("a", "b").Build()); + var traceId = ActivityTraceId.CreateRandom(); + var parentContext = SpanContext.Create(traceId, ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, Tracestate.Builder.Set("a", "b").Build()); RedisProfilerEntryToSpanConverter.ShouldSample(parentContext, "SET", m.Object, out var context, out var parentId); m.Verify(x => x.ShouldSample( It.Is(y => y == parentContext), - It.Is(y => y == traceId && y == context.TraceId), - It.Is(y => y.IsValid && y == context.SpanId), + It.Is(y => y == traceId && y == context.TraceId), + It.Is(y => y != default && y == context.SpanId), It.Is(y => y == "SET"), It.Is>(y => y == null))); } @@ -77,21 +77,21 @@ public void ShouldSampleGeneratesNewTraceIdForInvalidContext() var m = new Mock(); m.Setup(x => x.ShouldSample( It.IsAny(), - It.IsAny(), - It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), - It.IsAny>())).Returns((SpanContext parentContext, TraceId traceId, SpanId spanId, string name, IEnumerable parentLinks) => parentContext.TraceOptions.IsSampled); + It.IsAny>())).Returns((SpanContext parentContext, ActivityTraceId traceId, ActivitySpanId spanId, string name, IEnumerable parentLinks) => (parentContext.TraceOptions & ActivityTraceFlags.Recorded) != 0); RedisProfilerEntryToSpanConverter.ShouldSample(SpanContext.Blank, "SET", m.Object, out var context, out var parentId); m.Verify(x => x.ShouldSample( It.Is(y => y == SpanContext.Blank), - It.Is(y => y.IsValid && y == context.TraceId), - It.Is(y => y.IsValid && y == context.SpanId), + It.Is(y => y != default && y == context.TraceId), + It.Is(y => y != default && y == context.SpanId), It.Is(y => y == "SET"), It.Is>(y => y == null))); - Assert.Equal(TraceOptions.Default, context.TraceOptions); + Assert.Equal(ActivityTraceFlags.None, context.TraceOptions); } } } diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index 4cc7cade42f..b1ae129ffb0 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -20,8 +20,8 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation using Moq; using StackExchange.Redis.Profiling; using Xunit; - using OpenTelemetry.Trace.Internal; using System; + using System.Diagnostics; using OpenTelemetry.Common; using System.Collections.Generic; @@ -33,7 +33,7 @@ public void DrainSessionUsesCommandAsName() var parentSpan = BlankSpan.Instance; var profiledCommand = new Mock(); var sampler = new Mock(); - sampler.Setup(x => x.ShouldSample(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())).Returns(true); + sampler.Setup(x => x.ShouldSample(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())).Returns(true); profiledCommand.Setup(m => m.Command).Returns("SET"); var result = new List(); RedisProfilerEntryToSpanConverter.DrainSession(parentSpan, new IProfiledCommand[] { profiledCommand.Object }, sampler.Object, result); @@ -47,7 +47,7 @@ public void ProfiledCommandToSpanDataUsesTimestampAsStartTime() var profiledCommand = new Mock(); var now = DateTimeOffset.Now; profiledCommand.Setup(m => m.CommandCreated).Returns(now.DateTime); - var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", SpanId.Invalid, profiledCommand.Object); + var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); Assert.Equal(Timestamp.FromMillis(now.ToUnixTimeMilliseconds()), result.StartTimestamp); } @@ -55,7 +55,7 @@ public void ProfiledCommandToSpanDataUsesTimestampAsStartTime() public void ProfiledCommandToSpanDataSetsDbTypeAttributeAsRedis() { var profiledCommand = new Mock(); - var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", SpanId.Invalid, profiledCommand.Object); + var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); Assert.Contains("db.type", result.Attributes.AttributeMap.Keys); Assert.Equal(AttributeValue.StringAttributeValue("redis"), result.Attributes.AttributeMap["db.type"]); } @@ -65,7 +65,7 @@ public void ProfiledCommandToSpanDataUsesCommandAsDbStatementAttribute() { var profiledCommand = new Mock(); profiledCommand.Setup(m => m.Command).Returns("SET"); - var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "another name", SpanId.Invalid, profiledCommand.Object); + var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "another name", default, profiledCommand.Object); Assert.Contains("db.statement", result.Attributes.AttributeMap.Keys); Assert.Equal(AttributeValue.StringAttributeValue("SET"), result.Attributes.AttributeMap["db.statement"]); } @@ -76,7 +76,7 @@ public void ProfiledCommandToSpanDataUsesFlagsForFlagsAttribute() var profiledCommand = new Mock(); var expectedFlags = StackExchange.Redis.CommandFlags.FireAndForget | StackExchange.Redis.CommandFlags.NoRedirect; profiledCommand.Setup(m => m.Flags).Returns(expectedFlags); - var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", SpanId.Invalid, profiledCommand.Object); + var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); Assert.Contains("redis.flags", result.Attributes.AttributeMap.Keys); Assert.Equal(AttributeValue.StringAttributeValue("None, FireAndForget, NoRedirect"), result.Attributes.AttributeMap["redis.flags"]); } diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs index 235d15160ca..2cc7074ee50 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs @@ -30,7 +30,7 @@ public class StackExchangeRedisCallsCollectorTests public async void ProfilerSessionUsesTheSameDefault() { var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); using (var collector = new StackExchangeRedisCallsCollector(tracer, null, null)) { diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs index d419f82cf42..f5e2189d56f 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs @@ -27,6 +27,7 @@ namespace OpenTelemetry.Exporter.ApplicationInsights.Tests using System; using System.Collections.Concurrent; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Threading; using Xunit; @@ -43,13 +44,7 @@ public class OpenTelemetryTelemetryConverterTests private DateTimeOffset nowDateTimeOffset; - private Timestamp NowTimestamp - { - get - { - return Timestamp.FromDateTimeOffset(nowDateTimeOffset); - } - } + private Timestamp NowTimestamp => Timestamp.FromDateTimeOffset(nowDateTimeOffset); public OpenTelemetryTelemetryConverterTests() { @@ -142,7 +137,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithParent() // ARRANGE this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - parentSpanId = SpanId.FromBytes(this.testParentSpanIdBytes); + parentSpanId = ActivitySpanId.CreateFromBytes(this.testParentSpanIdBytes); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -159,7 +154,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithInvalidParent( // ARRANGE this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - parentSpanId = SpanId.Invalid; + parentSpanId = default; var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -433,7 +428,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyWithParent() // ARRANGE this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - parentSpanId = SpanId.FromBytes(this.testParentSpanIdBytes); + parentSpanId = ActivitySpanId.CreateFromBytes(this.testParentSpanIdBytes); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); // ACT @@ -599,7 +594,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnOtherSpanKi public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnSpanKindProperty() { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - parentSpanId = SpanId.FromBytes(this.testParentSpanIdBytes); + parentSpanId = ActivitySpanId.CreateFromBytes(this.testParentSpanIdBytes); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); var sentItems = this.ConvertSpan(span); @@ -612,7 +607,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyBasedOnSpanKind { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - parentSpanId = SpanId.FromBytes(this.testParentSpanIdBytes); + parentSpanId = ActivitySpanId.CreateFromBytes(this.testParentSpanIdBytes); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); var sentItems = this.ConvertSpan(span); @@ -1293,11 +1288,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyWithLinks() new List() { Link.FromSpanContext( - SpanContext.Create(TraceId.FromBytes(link0TraceIdBytes), SpanId.FromBytes(link0SpanIdBytes), TraceOptions.Default, Tracestate.Empty)), + SpanContext.Create(ActivityTraceId.CreateFromBytes(link0TraceIdBytes), ActivitySpanId.CreateFromBytes(link0SpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty)), Link.FromSpanContext( - SpanContext.Create(TraceId.FromBytes(link1TraceIdBytes), SpanId.FromBytes(link1SpanIdBytes), TraceOptions.Default, Tracestate.Empty)), + SpanContext.Create(ActivityTraceId.CreateFromBytes(link1TraceIdBytes), ActivitySpanId.CreateFromBytes(link1SpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty)), Link.FromSpanContext( - SpanContext.Create(TraceId.FromBytes(link2TraceIdBytes), SpanId.FromBytes(link2SpanIdBytes), TraceOptions.Default, Tracestate.Empty)), + SpanContext.Create(ActivityTraceId.CreateFromBytes(link2TraceIdBytes), ActivitySpanId.CreateFromBytes(link2SpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty)), }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1336,9 +1331,9 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyWithLinksAndAtt { Link.FromSpanContext( SpanContext.Create( - TraceId.FromBytes(GenerateRandomId(16).Item2), - SpanId.FromBytes(GenerateRandomId(8).Item2), - TraceOptions.Default, + ActivityTraceId.CreateFromBytes(GenerateRandomId(16).Item2), + ActivitySpanId.CreateFromBytes(GenerateRandomId(8).Item2), + ActivityTraceFlags.None, Tracestate.Empty), new Dictionary() { @@ -1384,11 +1379,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithLinks() links = LinkList.Create(new List() { Link.FromSpanContext( - SpanContext.Create(TraceId.FromBytes(link0TraceIdBytes), SpanId.FromBytes(link0SpanIdBytes), TraceOptions.Default, Tracestate.Empty)), + SpanContext.Create(ActivityTraceId.CreateFromBytes(link0TraceIdBytes), ActivitySpanId.CreateFromBytes(link0SpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty)), Link.FromSpanContext( - SpanContext.Create(TraceId.FromBytes(link1TraceIdBytes), SpanId.FromBytes(link1SpanIdBytes), TraceOptions.Default, Tracestate.Empty)), + SpanContext.Create(ActivityTraceId.CreateFromBytes(link1TraceIdBytes), ActivitySpanId.CreateFromBytes(link1SpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty)), Link.FromSpanContext( - SpanContext.Create(TraceId.FromBytes(link2TraceIdBytes), SpanId.FromBytes(link2SpanIdBytes), TraceOptions.Default, Tracestate.Empty)), + SpanContext.Create(ActivityTraceId.CreateFromBytes(link2TraceIdBytes), ActivitySpanId.CreateFromBytes(link2SpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty)), }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1427,9 +1422,9 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithLinksAndAttrib { Link.FromSpanContext( SpanContext.Create( - TraceId.FromBytes(GenerateRandomId(16).Item2), - SpanId.FromBytes(GenerateRandomId(8).Item2), - TraceOptions.Default, + ActivityTraceId.CreateFromBytes(GenerateRandomId(16).Item2), + ActivitySpanId.CreateFromBytes(GenerateRandomId(8).Item2), + ActivityTraceFlags.None, Tracestate.Empty), new Dictionary() { @@ -1864,7 +1859,7 @@ internal static string GetAssemblyVersionString() private void GetDefaults( out SpanContext context, - out SpanId parentSpanId, + out ActivitySpanId parentSpanId, out Resource resource, out string name, out Timestamp startTimestamp, @@ -1876,8 +1871,8 @@ private void GetDefaults( out SpanKind kind, out Timestamp endTimestamp) { - context = SpanContext.Create(TraceId.FromBytes(this.testTraceIdBytes), SpanId.FromBytes(this.testSpanIdBytes), TraceOptions.Default, Tracestate.Empty); - parentSpanId = SpanId.Invalid; + context = SpanContext.Create(ActivityTraceId.CreateFromBytes(this.testTraceIdBytes), ActivitySpanId.CreateFromBytes(this.testSpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty); + parentSpanId = default; resource = Resource.Empty; name = "spanName"; startTimestamp = NowTimestamp.AddDuration(Duration.Create(TimeSpan.FromSeconds(-1))); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index e6163921fd0..c1ecfbc134e 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -16,25 +16,24 @@ namespace OpenTelemetry.Trace.Test { + using System.Diagnostics; using Moq; using OpenTelemetry.Trace.Internal; using Xunit; public class CurrentSpanUtilsTest { - private readonly ISpan span; - private readonly RandomGenerator random; - private readonly SpanContext spanContext; - private readonly SpanOptions spanOptions; + private ISpan span; + private SpanContext spanContext; + private SpanOptions spanOptions; public CurrentSpanUtilsTest() { - random = new RandomGenerator(1234); spanContext = SpanContext.Create( - TraceId.GenerateRandomId(random), - SpanId.GenerateRandomId(random), - TraceOptions.Builder().SetIsSampled(true).Build(), + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.Recorded, Tracestate.Empty); spanOptions = SpanOptions.RecordEvents; diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs index ed3f29d1cfb..fef31b33af6 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs @@ -16,6 +16,7 @@ namespace OpenTelemetry.Trace.Export.Test { + using System.Diagnostics; using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; @@ -24,10 +25,8 @@ namespace OpenTelemetry.Trace.Export.Test public class InProcessRunningSpanStoreTest { - - private static readonly string SPAN_NAME_1 = "MySpanName/1"; - private static readonly string SPAN_NAME_2 = "MySpanName/2"; - private readonly RandomGenerator random = new RandomGenerator(1234); + private const string SpanName1 = "MySpanName/1"; + private const string SpanName2 = "MySpanName/2"; private readonly ISpanExporter sampledSpansServiceExporter = SpanExporter.Create(4, Duration.Create(1, 0)); private readonly InProcessRunningSpanStore activeSpansExporter = new InProcessRunningSpanStore(); private readonly StartEndHandler startEndHandler; @@ -42,15 +41,15 @@ private ISpan CreateSpan(string spanName) { var spanContext = SpanContext.Create( - TraceId.GenerateRandomId(random), - SpanId.GenerateRandomId(random), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); return Span.StartSpan( spanContext, recordSpanOptions, spanName, SpanKind.Internal, - SpanId.GenerateRandomId(random), + ActivitySpanId.CreateRandom(), TraceParams.Default, startEndHandler, null); @@ -59,26 +58,26 @@ private ISpan CreateSpan(string spanName) [Fact] public void GetSummary_SpansWithDifferentNames() { - var span1 = CreateSpan(SPAN_NAME_1); - var span2 = CreateSpan(SPAN_NAME_2); + var span1 = CreateSpan(SpanName1); + var span2 = CreateSpan(SpanName2); Assert.Equal(2, activeSpansExporter.Summary.PerSpanNameSummary.Count); Assert.Equal(1, activeSpansExporter .Summary - .PerSpanNameSummary[SPAN_NAME_1] + .PerSpanNameSummary[SpanName1] .NumRunningSpans); Assert.Equal(1, activeSpansExporter .Summary - .PerSpanNameSummary[SPAN_NAME_2] + .PerSpanNameSummary[SpanName2] .NumRunningSpans); span1.End(); Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); - Assert.False(activeSpansExporter.Summary.PerSpanNameSummary.ContainsKey(SPAN_NAME_1)); + Assert.False(activeSpansExporter.Summary.PerSpanNameSummary.ContainsKey(SpanName1)); Assert.Equal(1, activeSpansExporter .Summary - .PerSpanNameSummary[SPAN_NAME_2] + .PerSpanNameSummary[SpanName2] .NumRunningSpans); span2.End(); Assert.Equal(0, activeSpansExporter.Summary.PerSpanNameSummary.Count); @@ -87,28 +86,28 @@ public void GetSummary_SpansWithDifferentNames() [Fact] public void GetSummary_SpansWithSameName() { - var span1 = CreateSpan(SPAN_NAME_1); - var span2 = CreateSpan(SPAN_NAME_1); - var span3 = CreateSpan(SPAN_NAME_1); + var span1 = CreateSpan(SpanName1); + var span2 = CreateSpan(SpanName1); + var span3 = CreateSpan(SpanName1); Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); Assert.Equal(3, activeSpansExporter .Summary - .PerSpanNameSummary[SPAN_NAME_1] + .PerSpanNameSummary[SpanName1] .NumRunningSpans); span1.End(); Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); Assert.Equal(2, activeSpansExporter .Summary - .PerSpanNameSummary[SPAN_NAME_1] + .PerSpanNameSummary[SpanName1] .NumRunningSpans); span2.End(); Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); Assert.Equal(1, activeSpansExporter .Summary - .PerSpanNameSummary[SPAN_NAME_1] + .PerSpanNameSummary[SpanName1] .NumRunningSpans); span3.End(); Assert.Equal(0, activeSpansExporter.Summary.PerSpanNameSummary.Count); @@ -117,11 +116,11 @@ public void GetSummary_SpansWithSameName() [Fact] public void GetActiveSpans_SpansWithDifferentNames() { - var span1 = CreateSpan(SPAN_NAME_1) as Span; - var span2 = CreateSpan(SPAN_NAME_2) as Span; - Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SPAN_NAME_1, 0))); - Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SPAN_NAME_1, 2))); - Assert.Contains(span2.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SPAN_NAME_2, 0))); + var span1 = CreateSpan(SpanName1) as Span; + var span2 = CreateSpan(SpanName2) as Span; + Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SpanName1, 0))); + Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SpanName1, 2))); + Assert.Contains(span2.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SpanName2, 0))); span1.End(); span2.End(); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs index a2d1c1ddf0d..229fea3d6e9 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs @@ -18,24 +18,23 @@ namespace OpenTelemetry.Trace.Export.Test { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Internal; using OpenTelemetry.Utils; using Xunit; public class InProcessSampledSpanStoreTest { - private static readonly String REGISTERED_SPAN_NAME = "MySpanName/1"; - private static readonly String NOT_REGISTERED_SPAN_NAME = "MySpanName/2"; - private readonly RandomGenerator random = new RandomGenerator(1234); + private static readonly string REGISTERED_SPAN_NAME = "MySpanName/1"; + private static readonly string NOT_REGISTERED_SPAN_NAME = "MySpanName/2"; private readonly SpanContext sampledSpanContext; private readonly SpanContext notSampledSpanContext; - private readonly SpanId parentSpanId; + private readonly ActivitySpanId parentSpanId; private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; private TimeSpan interval = TimeSpan.FromMilliseconds(0); private readonly DateTimeOffset startTime = DateTimeOffset.Now; @@ -51,15 +50,13 @@ public InProcessSampledSpanStoreTest() { timestamp = Timestamp.FromDateTimeOffset(startTime); timestampConverter = Timer.StartNew(startTime, () => interval); - sampledSpanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty); - notSampledSpanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), TraceOptions.Default, Tracestate.Empty); - parentSpanId = SpanId.GenerateRandomId(random); + sampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, Tracestate.Empty); + notSampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); + parentSpanId = ActivitySpanId.CreateRandom(); startEndHandler = new TestStartEndHandler(sampleStore); sampleStore.RegisterSpanNamesForCollection(new List() { REGISTERED_SPAN_NAME }); } - - [Fact] public void AddSpansWithRegisteredNamesInAllLatencyBuckets() { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index 9c594fc793c..7023dfacd19 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace.Export.Test { using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Common; using OpenTelemetry.Resources; using OpenTelemetry.Trace.Internal; @@ -35,9 +36,8 @@ public class SpanDataTest private static readonly Timestamp endTimestamp = Timestamp.Create(123, 460); private static readonly IEvent spanEvent = Event.Create(EVENT_TEXT); private static readonly Status status = Status.DeadlineExceeded.WithDescription("TooSlow"); - private readonly IRandomGenerator random = new RandomGenerator(1234); private readonly SpanContext spanContext; - private readonly SpanId parentSpanId; + private readonly ActivitySpanId parentSpanId; private readonly Resource resource = Resource.Empty; private readonly IDictionary attributesMap = new Dictionary(); private readonly List> eventList = new List>(); @@ -49,8 +49,8 @@ public class SpanDataTest public SpanDataTest() { - spanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), TraceOptions.Default, Tracestate.Empty); - parentSpanId = SpanId.GenerateRandomId(random); + spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); + parentSpanId = ActivitySpanId.CreateRandom(); attributesMap.Add("MyAttributeKey1", AttributeValue.LongAttributeValue(10)); attributesMap.Add("MyAttributeKey2", AttributeValue.BooleanAttributeValue(true)); @@ -100,7 +100,7 @@ public void SpanData_RootActiveSpan() var spanData = SpanData.Create( spanContext, - null, + default, resource, SPAN_NAME, startTimestamp, @@ -112,7 +112,7 @@ public void SpanData_RootActiveSpan() SPAN_KIND, null); Assert.Equal(spanContext, spanData.Context); - Assert.Null(spanData.ParentSpanId); + Assert.True(spanData.ParentSpanId == default); Assert.Equal(resource, spanData.Resource); Assert.Equal(SPAN_NAME, spanData.Name); Assert.Equal(startTimestamp, spanData.StartTimestamp); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index 81bae9d0fe8..37f7a5d98b6 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Trace.Export.Test { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -33,7 +34,6 @@ public class SpanExporterTest { private const String SPAN_NAME_1 = "MySpanName/1"; private const String SPAN_NAME_2 = "MySpanName/2"; - private readonly RandomGenerator random = new RandomGenerator(1234); private readonly SpanContext sampledSpanContext; private readonly SpanContext notSampledSpanContext; private readonly ISpanExporter spanExporter = SpanExporter.Create(4, Duration.Create(1, 0)); @@ -45,8 +45,8 @@ public class SpanExporterTest public SpanExporterTest() { - sampledSpanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty); - notSampledSpanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), TraceOptions.Default, Tracestate.Empty); + sampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, Tracestate.Empty); + notSampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); startEndHandler = new StartEndHandler(spanExporter, runningSpanStore, null, new SimpleEventQueue()); spanExporter.RegisterHandler("test.service", serviceHandler); @@ -60,7 +60,7 @@ private Span CreateSampledEndedSpan(string spanName) recordSpanOptions, spanName, SpanKind.Internal, - null, + default, TraceParams.Default, startEndHandler, null); @@ -76,7 +76,7 @@ private Span CreateNotSampledEndedSpan(string spanName) recordSpanOptions, spanName, SpanKind.Internal, - null, + default, TraceParams.Default, startEndHandler, null); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index 159542b41f0..a27dad9cf1e 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace.Test { using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Trace.Internal; using OpenTelemetry.Utils; using Xunit; @@ -24,13 +25,12 @@ namespace OpenTelemetry.Trace.Test public class LinkTest { private readonly IDictionary attributesMap = new Dictionary(); - private readonly IRandomGenerator random = new RandomGenerator(1234); private readonly SpanContext spanContext; public LinkTest() { - spanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), TraceOptions.Default, Tracestate.Empty); ; + spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); ; attributesMap.Add("MyAttributeKey0", AttributeValue.Create("MyStringAttribute")); attributesMap.Add("MyAttributeKey1", AttributeValue.Create(10)); attributesMap.Add("MyAttributeKey2", AttributeValue.Create(true)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs index b1e38a0ce44..57f1e69fbb7 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs @@ -59,7 +59,7 @@ public void NoopTracer_RecordData() Assert.Throws(() => NoopTracer.Instance.RecordSpanData(null)); // does not throw - NoopTracer.Instance.RecordSpanData(SpanData.Create(SpanContext.Blank, null, Resource.Empty, "foo", Timestamp.Zero, null, null, null, null, Status.Ok, SpanKind.Internal, Timestamp.Zero)); + NoopTracer.Instance.RecordSpanData(SpanData.Create(SpanContext.Blank, default, Resource.Empty, "foo", Timestamp.Zero, null, null, null, null, Status.Ok, SpanKind.Internal, Timestamp.Zero)); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs index 0409754739a..ccdf656c0da 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/B3FormatTest.cs @@ -18,20 +18,21 @@ namespace OpenTelemetry.Context.Propagation.Test { using System; using System.Collections.Generic; + using System.Diagnostics; using OpenTelemetry.Trace; using Xunit; using Xunit.Abstractions; public class B3FormatTest { - private static readonly string TRACE_ID_BASE16 = "ff000000000000000000000000000041"; - private static readonly TraceId TRACE_ID = TraceId.FromLowerBase16(TRACE_ID_BASE16); - private static readonly string TRACE_ID_BASE16_EIGHT_BYTES = "0000000000000041"; - private static readonly TraceId TRACE_ID_EIGHT_BYTES = TraceId.FromLowerBase16("0000000000000000" + TRACE_ID_BASE16_EIGHT_BYTES); - private static readonly string SPAN_ID_BASE16 = "ff00000000000041"; - private static readonly SpanId SPAN_ID = SpanId.FromLowerBase16(SPAN_ID_BASE16); - private static readonly byte[] TRACE_OPTIONS_BYTES = new byte[] { 1 }; - private static readonly TraceOptions TRACE_OPTIONS = TraceOptions.FromBytes(TRACE_OPTIONS_BYTES); + private static readonly string TraceIdBase16 = "ff000000000000000000000000000041"; + private static readonly ActivityTraceId TraceId = ActivityTraceId.CreateFromString(TraceIdBase16.AsSpan()); + private static readonly string TraceIdBase16EightBytes = "0000000000000041"; + private static readonly ActivityTraceId TraceIdEightBytes = ActivityTraceId.CreateFromString(("0000000000000000" + TraceIdBase16EightBytes).AsSpan()); + private static readonly string SpanIdBase16 = "ff00000000000041"; + private static readonly ActivitySpanId SpanId = ActivitySpanId.CreateFromString(SpanIdBase16.AsSpan()); + + private static readonly ActivityTraceFlags TraceOptions = ActivityTraceFlags.Recorded; private readonly B3Format b3Format = new B3Format(); @@ -49,27 +50,27 @@ public B3FormatTest(ITestOutputHelper output) public void Serialize_SampledContext() { IDictionary carrier = new Dictionary(); - b3Format.Inject(SpanContext.Create(TRACE_ID, SPAN_ID, TRACE_OPTIONS, Tracestate.Empty), carrier, setter); - ContainsExactly(carrier, new Dictionary() { { B3Format.XB3TraceId, TRACE_ID_BASE16 }, { B3Format.XB3SpanId, SPAN_ID_BASE16 }, { B3Format.XB3Sampled, "1" } }); + b3Format.Inject(SpanContext.Create(TraceId, SpanId, TraceOptions, Tracestate.Empty), carrier, setter); + ContainsExactly(carrier, new Dictionary() { { B3Format.XB3TraceId, TraceIdBase16 }, { B3Format.XB3SpanId, SpanIdBase16 }, { B3Format.XB3Sampled, "1" } }); } [Fact] public void Serialize_NotSampledContext() { IDictionary carrier = new Dictionary(); - var context = SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty); + var context = SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.None, Tracestate.Empty); _output.WriteLine(context.ToString()); b3Format.Inject(context, carrier, setter); - ContainsExactly(carrier, new Dictionary() { { B3Format.XB3TraceId, TRACE_ID_BASE16 }, { B3Format.XB3SpanId, SPAN_ID_BASE16 } }); + ContainsExactly(carrier, new Dictionary() { { B3Format.XB3TraceId, TraceIdBase16 }, { B3Format.XB3SpanId, SpanIdBase16 } }); } [Fact] public void ParseMissingSampledAndMissingFlag() { IDictionary headersNotSampled = new Dictionary(); - headersNotSampled.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); - headersNotSampled.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); - var spanContext = SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty); + headersNotSampled.Add(B3Format.XB3TraceId, TraceIdBase16); + headersNotSampled.Add(B3Format.XB3SpanId, SpanIdBase16); + var spanContext = SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.None, Tracestate.Empty); Assert.Equal(spanContext, b3Format.Extract(headersNotSampled, getter)); } @@ -77,59 +78,59 @@ public void ParseMissingSampledAndMissingFlag() public void ParseSampled() { IDictionary headersSampled = new Dictionary(); - headersSampled.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); - headersSampled.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + headersSampled.Add(B3Format.XB3TraceId, TraceIdBase16); + headersSampled.Add(B3Format.XB3SpanId, SpanIdBase16); headersSampled.Add(B3Format.XB3Sampled, "1"); - Assert.Equal(SpanContext.Create(TRACE_ID, SPAN_ID, TRACE_OPTIONS, Tracestate.Empty), b3Format.Extract(headersSampled, getter)); + Assert.Equal(SpanContext.Create(TraceId, SpanId, TraceOptions, Tracestate.Empty), b3Format.Extract(headersSampled, getter)); } [Fact] public void ParseZeroSampled() { IDictionary headersNotSampled = new Dictionary(); - headersNotSampled.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); - headersNotSampled.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + headersNotSampled.Add(B3Format.XB3TraceId, TraceIdBase16); + headersNotSampled.Add(B3Format.XB3SpanId, SpanIdBase16); headersNotSampled.Add(B3Format.XB3Sampled, "0"); - Assert.Equal(SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty), b3Format.Extract(headersNotSampled, getter)); + Assert.Equal(SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.None, Tracestate.Empty), b3Format.Extract(headersNotSampled, getter)); } [Fact] public void ParseFlag() { IDictionary headersFlagSampled = new Dictionary(); - headersFlagSampled.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); - headersFlagSampled.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + headersFlagSampled.Add(B3Format.XB3TraceId, TraceIdBase16); + headersFlagSampled.Add(B3Format.XB3SpanId, SpanIdBase16); headersFlagSampled.Add(B3Format.XB3Flags, "1"); - Assert.Equal(SpanContext.Create(TRACE_ID, SPAN_ID, TRACE_OPTIONS, Tracestate.Empty), b3Format.Extract(headersFlagSampled, getter)); + Assert.Equal(SpanContext.Create(TraceId, SpanId, TraceOptions, Tracestate.Empty), b3Format.Extract(headersFlagSampled, getter)); } [Fact] public void ParseZeroFlag() { IDictionary headersFlagNotSampled = new Dictionary(); - headersFlagNotSampled.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); - headersFlagNotSampled.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + headersFlagNotSampled.Add(B3Format.XB3TraceId, TraceIdBase16); + headersFlagNotSampled.Add(B3Format.XB3SpanId, SpanIdBase16); headersFlagNotSampled.Add(B3Format.XB3Flags, "0"); - Assert.Equal(SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty), b3Format.Extract(headersFlagNotSampled, getter)); + Assert.Equal(SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.None, Tracestate.Empty), b3Format.Extract(headersFlagNotSampled, getter)); } [Fact] public void ParseEightBytesTraceId() { IDictionary headersEightBytes = new Dictionary(); - headersEightBytes.Add(B3Format.XB3TraceId, TRACE_ID_BASE16_EIGHT_BYTES); - headersEightBytes.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + headersEightBytes.Add(B3Format.XB3TraceId, TraceIdBase16EightBytes); + headersEightBytes.Add(B3Format.XB3SpanId, SpanIdBase16); headersEightBytes.Add(B3Format.XB3Sampled, "1"); - Assert.Equal(SpanContext.Create(TRACE_ID_EIGHT_BYTES, SPAN_ID, TRACE_OPTIONS, Tracestate.Empty), b3Format.Extract(headersEightBytes, getter)); + Assert.Equal(SpanContext.Create(TraceIdEightBytes, SpanId, TraceOptions, Tracestate.Empty), b3Format.Extract(headersEightBytes, getter)); } [Fact] public void ParseEightBytesTraceId_NotSampledSpanContext() { IDictionary headersEightBytes = new Dictionary(); - headersEightBytes.Add(B3Format.XB3TraceId, TRACE_ID_BASE16_EIGHT_BYTES); - headersEightBytes.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); - Assert.Equal(SpanContext.Create(TRACE_ID_EIGHT_BYTES, SPAN_ID, TraceOptions.Default, Tracestate.Empty), b3Format.Extract(headersEightBytes, getter)); + headersEightBytes.Add(B3Format.XB3TraceId, TraceIdBase16EightBytes); + headersEightBytes.Add(B3Format.XB3SpanId, SpanIdBase16); + Assert.Equal(SpanContext.Create(TraceIdEightBytes, SpanId, ActivityTraceFlags.None, Tracestate.Empty), b3Format.Extract(headersEightBytes, getter)); } [Fact] @@ -137,7 +138,7 @@ public void ParseInvalidTraceId() { IDictionary invalidHeaders = new Dictionary(); invalidHeaders.Add(B3Format.XB3TraceId, "abcdefghijklmnop"); - invalidHeaders.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + invalidHeaders.Add(B3Format.XB3SpanId, SpanIdBase16); Assert.Throws(() => b3Format.Extract(invalidHeaders, getter)); } @@ -146,7 +147,7 @@ public void ParseInvalidTraceId_Size() { IDictionary invalidHeaders = new Dictionary(); invalidHeaders.Add(B3Format.XB3TraceId, "0123456789abcdef00"); - invalidHeaders.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + invalidHeaders.Add(B3Format.XB3SpanId, SpanIdBase16); Assert.Throws(() => b3Format.Extract(invalidHeaders, getter)); } @@ -154,7 +155,7 @@ public void ParseInvalidTraceId_Size() public void ParseMissingTraceId() { IDictionary invalidHeaders = new Dictionary(); - invalidHeaders.Add(B3Format.XB3SpanId, SPAN_ID_BASE16); + invalidHeaders.Add(B3Format.XB3SpanId, SpanIdBase16); Assert.Throws(() => b3Format.Extract(invalidHeaders, getter)); } @@ -162,7 +163,7 @@ public void ParseMissingTraceId() public void ParseInvalidSpanId() { IDictionary invalidHeaders = new Dictionary(); - invalidHeaders.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); + invalidHeaders.Add(B3Format.XB3TraceId, TraceIdBase16); invalidHeaders.Add(B3Format.XB3SpanId, "abcdefghijklmnop"); Assert.Throws(() => b3Format.Extract(invalidHeaders, getter)); } @@ -171,7 +172,7 @@ public void ParseInvalidSpanId() public void ParseInvalidSpanId_Size() { IDictionary invalidHeaders = new Dictionary(); - invalidHeaders.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); + invalidHeaders.Add(B3Format.XB3TraceId, TraceIdBase16); invalidHeaders.Add(B3Format.XB3SpanId, "0123456789abcdef00"); Assert.Throws(() => b3Format.Extract(invalidHeaders, getter)); } @@ -180,7 +181,7 @@ public void ParseInvalidSpanId_Size() public void ParseMissingSpanId() { IDictionary invalidHeaders = new Dictionary(); - invalidHeaders.Add(B3Format.XB3TraceId, TRACE_ID_BASE16); + invalidHeaders.Add(B3Format.XB3TraceId, TraceIdBase16); Assert.Throws(() => b3Format.Extract(invalidHeaders, getter)); } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs index 1f9989988bc..dd85bb1d9ab 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs @@ -16,6 +16,7 @@ namespace OpenTelemetry.Context.Propagation.Test { + using System.Diagnostics; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace; using System; @@ -23,16 +24,16 @@ namespace OpenTelemetry.Context.Propagation.Test public class BinaryFormatTest { - private static readonly byte[] TRACE_ID_BYTES = new byte[] { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }; - private static readonly TraceId TRACE_ID = TraceId.FromBytes(TRACE_ID_BYTES); - private static readonly byte[] SPAN_ID_BYTES = new byte[] { 97, 98, 99, 100, 101, 102, 103, 104 }; - private static readonly SpanId SPAN_ID = SpanId.FromBytes(SPAN_ID_BYTES); - private static readonly byte[] TRACE_OPTIONS_BYTES = new byte[] { 1 }; - private static readonly TraceOptions TRACE_OPTIONS = TraceOptions.FromBytes(TRACE_OPTIONS_BYTES); - private static readonly byte[] EXAMPLE_BYTES = + private static readonly byte[] TraceIdBytes = new byte[] { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }; + private static readonly ActivityTraceId TraceId = ActivityTraceId.CreateFromBytes(TraceIdBytes); + private static readonly byte[] SpanIdBytes = new byte[] { 97, 98, 99, 100, 101, 102, 103, 104 }; + private static readonly ActivitySpanId SpanId = ActivitySpanId.CreateFromBytes(SpanIdBytes); + private static readonly byte[] TraceOptionsBytes = new byte[] { 1 }; + private static readonly ActivityTraceFlags TraceOptions = ActivityTraceFlags.Recorded; + private static readonly byte[] ExampleBytes = new byte[] {0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97, 98, 99, 100,101, 102, 103, 104, 2, 1}; - private static readonly SpanContext EXAMPLE_SPAN_CONTEXT = SpanContext.Create(TRACE_ID, SPAN_ID, TRACE_OPTIONS, Tracestate.Empty); + private static readonly SpanContext ExampleSpanContext = SpanContext.Create(TraceId, SpanId, TraceOptions, Tracestate.Empty); private readonly BinaryFormat binaryFormat = new BinaryFormat(); @@ -46,13 +47,13 @@ private void TestSpanContextConversion(SpanContext spanContext) public void Propagate_SpanContextTracingEnabled() { TestSpanContextConversion( - SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty)); + SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.Recorded, Tracestate.Empty)); } [Fact] public void Propagate_SpanContextNoTracing() { - TestSpanContextConversion(SpanContext.Create(TRACE_ID, SPAN_ID, TraceOptions.Default, Tracestate.Empty)); + TestSpanContextConversion(SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.None, Tracestate.Empty)); } [Fact] @@ -73,7 +74,7 @@ public void ToBinaryValue_InvalidSpanContext() [Fact] public void FromBinaryValue_BinaryExampleValue() { - Assert.Equal(EXAMPLE_SPAN_CONTEXT, binaryFormat.FromByteArray(EXAMPLE_BYTES)); + Assert.Equal(ExampleSpanContext, binaryFormat.FromByteArray(ExampleBytes)); } [Fact] @@ -103,7 +104,7 @@ public void FromBinaryValue_UnsupportedVersionId() public void FromBinaryValue_UnsupportedFieldIdFirst() { Assert.Equal( - SpanContext.Create(TraceId.Invalid, SpanId.Invalid, TraceOptions.Default, Tracestate.Empty), + SpanContext.Create(default, default, ActivityTraceFlags.None, Tracestate.Empty), binaryFormat.FromByteArray( new byte[] { @@ -117,9 +118,9 @@ public void FromBinaryValue_UnsupportedFieldIdSecond() { Assert.Equal( SpanContext.Create( - TraceId.FromBytes(new byte[] { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }), - SpanId.Invalid, - TraceOptions.Default, Tracestate.Empty), + ActivityTraceId.CreateFromBytes(new byte[] { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }), + default, + ActivityTraceFlags.None, Tracestate.Empty), binaryFormat.FromByteArray( new byte[] { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs index 9e322ebbb5b..a10eb193def 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs @@ -14,9 +14,12 @@ // limitations under the License. // +using System; + namespace OpenTelemetry.Impl.Trace.Propagation { using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using OpenTelemetry.Trace; using OpenTelemetry.Context.Propagation; @@ -39,9 +42,9 @@ public void TraceContextFormatCanParseExampleFromSpec() var f = new TraceContextFormat(); var ctx = f.Extract(headers, (h, n) => new string[] {h[n]}); - Assert.Equal(TraceId.FromLowerBase16("0af7651916cd43dd8448eb211c80319c"), ctx.TraceId); - Assert.Equal(SpanId.FromLowerBase16("b9c7c989f97918e1"), ctx.SpanId); - Assert.True(ctx.TraceOptions.IsSampled); + Assert.Equal(ActivityTraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c".AsSpan()), ctx.TraceId); + Assert.Equal(ActivitySpanId.CreateFromString("b9c7c989f97918e1".AsSpan()), ctx.SpanId); + Assert.True((ctx.TraceOptions & ActivityTraceFlags.Recorded) != 0); Assert.Equal(2, ctx.Tracestate.Entries.Count()); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs index 74f3d80dd65..8cc384ee9db 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Sampler/SamplersTest.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace.Sampler.Test { using System; + using System.Diagnostics; using System.Collections.Generic; using System.Globalization; using OpenTelemetry.Trace.Internal; @@ -27,21 +28,20 @@ public class SamplersTest { private static readonly String SPAN_NAME = "MySpanName"; private static readonly int NUM_SAMPLE_TRIES = 1000; - private readonly IRandomGenerator random = new RandomGenerator(1234); - private readonly TraceId traceId; - private readonly SpanId parentSpanId; - private readonly SpanId spanId; + private readonly ActivityTraceId traceId; + private readonly ActivitySpanId parentSpanId; + private readonly ActivitySpanId spanId; private readonly SpanContext sampledSpanContext; private readonly SpanContext notSampledSpanContext; private readonly ILink sampledLink; public SamplersTest() { - traceId = TraceId.GenerateRandomId(random); - parentSpanId = SpanId.GenerateRandomId(random); - spanId = SpanId.GenerateRandomId(random); - sampledSpanContext = SpanContext.Create(traceId, parentSpanId, TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty); - notSampledSpanContext = SpanContext.Create(traceId, parentSpanId, TraceOptions.Default, Tracestate.Empty); + traceId = ActivityTraceId.CreateRandom(); + parentSpanId = ActivitySpanId.CreateRandom(); + spanId = ActivitySpanId.CreateRandom(); + sampledSpanContext = SpanContext.Create(traceId, parentSpanId, ActivityTraceFlags.Recorded, Tracestate.Empty); + notSampledSpanContext = SpanContext.Create(traceId, parentSpanId, ActivityTraceFlags.None, Tracestate.Empty); sampledLink = Link.FromSpanContext(sampledSpanContext); } @@ -185,7 +185,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; var notSampledtraceId = - TraceId.FromBytes( + ActivityTraceId.CreateFromBytes( new byte[] { 0x8F, @@ -209,13 +209,13 @@ public void ProbabilitySampler_SampleBasedOnTraceId() defaultProbability.ShouldSample( null, notSampledtraceId, - SpanId.GenerateRandomId(random), + ActivitySpanId.CreateRandom(), SPAN_NAME, null)); // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long // is less than probability * Long.MAX_VALUE; var sampledtraceId = - TraceId.FromBytes( + ActivityTraceId.CreateFromBytes( new byte[] { 0x00, @@ -239,7 +239,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() defaultProbability.ShouldSample( null, sampledtraceId, - SpanId.GenerateRandomId(random), + ActivitySpanId.CreateRandom(), SPAN_NAME, null)); } @@ -247,7 +247,7 @@ public void ProbabilitySampler_SampleBasedOnTraceId() [Fact] public void ProbabilitySampler_getDescription() { - Assert.Equal(String.Format("ProbabilitySampler({0:F6})", 0.5), ProbabilitySampler.Create(0.5).Description); + Assert.Equal($"ProbabilitySampler({0.5:F6})", ProbabilitySampler.Create(0.5).Description); } [Fact] @@ -261,14 +261,13 @@ public void ProbabilitySampler_ToString() private static void AssertSamplerSamplesWithProbability( ISampler sampler, SpanContext parent, List links, double probability) { - var random = new RandomGenerator(1234); var count = 0; // Count of spans with sampling enabled for (var i = 0; i < NUM_SAMPLE_TRIES; i++) { if (sampler.ShouldSample( parent, - TraceId.GenerateRandomId(random), - SpanId.GenerateRandomId(random), + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), SPAN_NAME, links)) { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 135efbb4042..c50f7dc6c91 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace.Test { using System; + using System.Diagnostics; using Moq; using OpenTelemetry.Common; using OpenTelemetry.Trace.Config; @@ -27,8 +28,10 @@ public class SpanBuilderTest { private static readonly string SpanName = "MySpanName"; private readonly SpanBuilderOptions spanBuilderOptions; - private readonly TraceParams alwaysSampleTraceParams = TraceParams.Default.ToBuilder().SetSampler(Samplers.AlwaysSample).Build(); - private readonly IRandomGenerator randomHandler = new FakeRandomHandler(); + + private readonly TraceParams alwaysSampleTraceParams = + TraceParams.Default.ToBuilder().SetSampler(Samplers.AlwaysSample).Build(); + private readonly IStartEndHandler startEndHandler = Mock.Of(); private readonly ITraceConfig traceConfig = Mock.Of(); @@ -36,7 +39,7 @@ public SpanBuilderTest() { // MockitoAnnotations.initMocks(this); spanBuilderOptions = - new SpanBuilderOptions(randomHandler, startEndHandler, traceConfig); + new SpanBuilderOptions(startEndHandler, traceConfig); var configMock = Mock.Get(traceConfig); configMock.Setup((c) => c.ActiveTraceParams).Returns(alwaysSampleTraceParams); // when(traceConfig.getActiveTraceParams()).thenReturn(alwaysSampleTraceParams); @@ -51,10 +54,12 @@ public void StartSpanNullParent() .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); - Assert.True(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); - Assert.Null(spanData.ParentSpanId); - Assert.InRange(spanData.StartTimestamp, Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(-1, 0)), Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(1, 0))); + Assert.True(spanData.ParentSpanId == default); + Assert.InRange(spanData.StartTimestamp, + Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(-1, 0)), + Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(1, 0))); Assert.Equal(SpanName, spanData.Name); } @@ -63,11 +68,11 @@ public void StartSpanLastParentWins1() { var spanContext = SpanContext.Create( - TraceId.GenerateRandomId(randomHandler), - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); - var span = (Span) new SpanBuilder(SpanName, spanBuilderOptions) + var span = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .SetNoParent() .SetParent(spanContext) .StartSpan(); @@ -82,9 +87,9 @@ public void StartSpanLastParentWins2() { var spanContext = SpanContext.Create( - TraceId.GenerateRandomId(randomHandler), - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); var span = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .SetParent(spanContext) @@ -93,7 +98,7 @@ public void StartSpanLastParentWins2() Assert.True(span.Context.IsValid); Assert.NotEqual(spanContext.TraceId, span.Context.TraceId); - Assert.Null(span.ParentSpanId); + Assert.True(span.ParentSpanId == default); } [Fact] @@ -101,9 +106,9 @@ public void StartSpanLastParentWins3() { var spanContext = SpanContext.Create( - TraceId.GenerateRandomId(randomHandler), - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); var rootSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .StartSpan(); @@ -122,9 +127,9 @@ public void StartSpanLastParentWins4() { var spanContext = SpanContext.Create( - TraceId.GenerateRandomId(randomHandler), - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); var rootSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .StartSpan(); @@ -149,9 +154,9 @@ public void StartSpanNullParentWithRecordEvents() .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); - Assert.False(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); - Assert.Null(spanData.ParentSpanId); + Assert.True(spanData.ParentSpanId == default); } [Fact] @@ -164,7 +169,7 @@ public void StartSpanNullParentNoRecordOptions() .StartSpan(); Assert.True(span.Context.IsValid); Assert.False(span.IsRecordingEvents); - Assert.False(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); } [Fact] @@ -176,10 +181,10 @@ public void StartChildSpan() .StartSpan(); Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.IsRecordingEvents); - Assert.True(rootSpan.Context.TraceOptions.IsSampled); + Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) - .SetSpanKind(Trace.SpanKind.Internal) + .SetSpanKind(SpanKind.Internal) .SetParent(rootSpan) .StartSpan(); @@ -199,9 +204,9 @@ public void StartSpan_ExplicitNoParent() Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); - Assert.True(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); - Assert.Null(spanData.ParentSpanId); + Assert.True(spanData.ParentSpanId == default); } [Fact] @@ -213,9 +218,9 @@ public void StartSpan_NoParent() Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); - Assert.True(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); - Assert.Null(spanData.ParentSpanId); + Assert.True(spanData.ParentSpanId == default); } [Fact] @@ -225,7 +230,7 @@ public void StartSpan_CurrentSpanParent() .StartSpan(); using (CurrentSpanUtils.WithSpan(rootSpan, true)) { - var childSpan = (Span) new SpanBuilder(SpanName, spanBuilderOptions) + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .StartSpan(); Assert.True(childSpan.Context.IsValid); @@ -247,7 +252,7 @@ public void StartSpan_NoParentInScopeOfCurrentSpan() Assert.True(childSpan.Context.IsValid); Assert.NotEqual(rootSpan.Context.TraceId, childSpan.Context.TraceId); - Assert.Null(childSpan.ParentSpanId); + Assert.True(childSpan.ParentSpanId == default); } } @@ -260,9 +265,9 @@ public void StartSpanInvalidParent() .StartSpan(); Assert.True(span.Context.IsValid); Assert.True(span.IsRecordingEvents); - Assert.True(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); - Assert.Null(spanData.ParentSpanId); + Assert.True(spanData.ParentSpanId == default); } [Fact] @@ -270,9 +275,9 @@ public void StartRemoteSpan() { var spanContext = SpanContext.Create( - TraceId.GenerateRandomId(randomHandler), - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); var span = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -282,7 +287,7 @@ public void StartRemoteSpan() Assert.True(span.Context.IsValid); Assert.Equal(spanContext.TraceId, span.Context.TraceId); - Assert.False(span.Context.TraceOptions.IsSampled); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext.SpanId, spanData.ParentSpanId); } @@ -298,7 +303,7 @@ public void StartRootSpan_WithSpecifiedSampler() .StartSpan(); Assert.True(rootSpan.Context.IsValid); - Assert.False(rootSpan.Context.TraceOptions.IsSampled); + Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); } [Fact] @@ -311,7 +316,7 @@ public void StartRootSpan_WithoutSpecifiedSampler() .StartSpan(); Assert.True(rootSpan.Context.IsValid); - Assert.True(rootSpan.Context.TraceOptions.IsSampled); + Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); } [Fact] @@ -324,7 +329,7 @@ public void StartRemoteChildSpan_WithSpecifiedSampler() .StartSpan(); Assert.True(rootSpan.Context.IsValid); - Assert.True(rootSpan.Context.TraceOptions.IsSampled); + Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); // Apply given sampler before default sampler for spans with remote parent. var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -334,7 +339,7 @@ public void StartRemoteChildSpan_WithSpecifiedSampler() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); - Assert.False(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); } [Fact] @@ -347,7 +352,7 @@ public void StartRemoteChildSpan_WithoutSpecifiedSampler() .StartSpan(); Assert.True(rootSpan.Context.IsValid); - Assert.False(rootSpan.Context.TraceOptions.IsSampled); + 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, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -356,7 +361,7 @@ public void StartRemoteChildSpan_WithoutSpecifiedSampler() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); - Assert.False(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); } [Fact] @@ -369,7 +374,7 @@ public void StartChildSpan_WithSpecifiedSampler() .StartSpan(); Assert.True(rootSpan.Context.IsValid); - Assert.True(rootSpan.Context.TraceOptions.IsSampled); + Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); // Apply the given sampler for child spans. var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) @@ -380,7 +385,7 @@ public void StartChildSpan_WithSpecifiedSampler() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); - Assert.False(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); } [Fact] @@ -393,7 +398,8 @@ public void StartChildSpan_WithoutSpecifiedSampler() .StartSpan(); Assert.True(rootSpan.Context.IsValid); - Assert.False(rootSpan.Context.TraceOptions.IsSampled); + Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); + // Don't apply the default sampler (always true) for child spans. var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -402,7 +408,7 @@ public void StartChildSpan_WithoutSpecifiedSampler() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); - Assert.False(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); } [Fact] @@ -413,8 +419,8 @@ public void StartChildSpan_SampledLinkedParent() .SetSampler(Samplers.NeverSample) .SetNoParent() .StartSpan(); - - Assert.False(rootSpanUnsampled.Context.TraceOptions.IsSampled); + + Assert.True((rootSpanUnsampled.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); var rootSpanSampled = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -422,7 +428,7 @@ public void StartChildSpan_SampledLinkedParent() .SetNoParent() .StartSpan(); - Assert.True(rootSpanSampled.Context.TraceOptions.IsSampled); + Assert.True((rootSpanSampled.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); // Sampled because the linked parent is sampled. var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -432,7 +438,7 @@ public void StartChildSpan_SampledLinkedParent() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpanUnsampled.Context.TraceId, childSpan.Context.TraceId); - Assert.True(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); } [Fact] @@ -443,26 +449,8 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long // is not less than probability * Long.MAX_VALUE; var traceId = - TraceId.FromBytes( - new byte[] - { - 0x8F, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }); + ActivityTraceId.CreateFromBytes( + new byte[] {0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0,}); // If parent is sampled then the remote child must be sampled. var childSpan = @@ -470,13 +458,14 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Create( traceId, - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty)) + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.Recorded, + Tracestate.Empty)) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); - Assert.True(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); childSpan.End(); Assert.Equal(TraceParams.Default, traceConfig.ActiveTraceParams); @@ -487,14 +476,14 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() .SetSpanKind(SpanKind.Internal) .SetParent(SpanContext.Create( traceId, - SpanId.GenerateRandomId(randomHandler), - TraceOptions.Default, + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty)) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(traceId, childSpan.Context.TraceId); - Assert.False(childSpan.Context.TraceOptions.IsSampled); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0); childSpan.End(); } @@ -511,26 +500,5 @@ public void SpanBuilder_BadArguments() Assert.Throws(() => spanBuilder.AddLink(null, null)); Assert.Throws(() => spanBuilder.AddLink(SpanContext.Blank, null)); } - - class FakeRandomHandler : IRandomGenerator - { - private readonly Random random; - - public FakeRandomHandler() - { - this.random = new Random(1234); - } - - public Random Current() - { - return random; - } - - public void NextBytes(byte[] bytes) - { - random.NextBytes(bytes); - } - } } - } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanContextTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanContextTest.cs index 3eaa4ef7349..630bcb3aa87 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanContextTest.cs @@ -16,6 +16,7 @@ namespace OpenTelemetry.Trace.Test { + using System.Diagnostics; using Xunit; public class SpanContextTest @@ -30,22 +31,22 @@ public class SpanContextTest private static readonly byte[] secondSpanIdBytes = new byte[] { (byte)'0', 0, 0, 0, 0, 0, 0, 0 }; private static readonly SpanContext first = SpanContext.Create( - TraceId.FromBytes(firstTraceIdBytes), - SpanId.FromBytes(firstSpanIdBytes), - TraceOptions.Default, Tracestate.Empty); + ActivityTraceId.CreateFromBytes(firstTraceIdBytes), + ActivitySpanId.CreateFromBytes(firstSpanIdBytes), + ActivityTraceFlags.None, Tracestate.Empty); private static readonly SpanContext second = SpanContext.Create( - TraceId.FromBytes(secondTraceIdBytes), - SpanId.FromBytes(secondSpanIdBytes), - TraceOptions.Builder().SetIsSampled(true).Build(), Tracestate.Empty); + ActivityTraceId.CreateFromBytes(secondTraceIdBytes), + ActivitySpanId.CreateFromBytes(secondSpanIdBytes), + ActivityTraceFlags.Recorded, Tracestate.Empty); [Fact] public void InvalidSpanContext() { - Assert.Equal(TraceId.Invalid, SpanContext.Blank.TraceId); - Assert.Equal(SpanId.Invalid, SpanContext.Blank.SpanId); - Assert.Equal(TraceOptions.Default, SpanContext.Blank.TraceOptions); + Assert.Equal(default, SpanContext.Blank.TraceId); + Assert.Equal(default, SpanContext.Blank.SpanId); + Assert.Equal(ActivityTraceFlags.None, SpanContext.Blank.TraceOptions); } [Fact] @@ -54,11 +55,11 @@ public void IsValid() Assert.False(SpanContext.Blank.IsValid); Assert.False( SpanContext.Create( - TraceId.FromBytes(firstTraceIdBytes), SpanId.Invalid, TraceOptions.Default, Tracestate.Empty) + ActivityTraceId.CreateFromBytes(firstTraceIdBytes), default, ActivityTraceFlags.None, Tracestate.Empty) .IsValid); Assert.False( SpanContext.Create( - TraceId.Invalid, SpanId.FromBytes(firstSpanIdBytes), TraceOptions.Default, Tracestate.Empty) + default, ActivitySpanId.CreateFromBytes(firstSpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty) .IsValid); Assert.True(first.IsValid); Assert.True(second.IsValid); @@ -67,22 +68,22 @@ public void IsValid() [Fact] public void GetTraceId() { - Assert.Equal(TraceId.FromBytes(firstTraceIdBytes), first.TraceId); - Assert.Equal(TraceId.FromBytes(secondTraceIdBytes), second.TraceId); + Assert.Equal(ActivityTraceId.CreateFromBytes(firstTraceIdBytes), first.TraceId); + Assert.Equal(ActivityTraceId.CreateFromBytes(secondTraceIdBytes), second.TraceId); } [Fact] public void GetSpanId() { - Assert.Equal(SpanId.FromBytes(firstSpanIdBytes), first.SpanId); - Assert.Equal(SpanId.FromBytes(secondSpanIdBytes), second.SpanId); + Assert.Equal(ActivitySpanId.CreateFromBytes(firstSpanIdBytes), first.SpanId); + Assert.Equal(ActivitySpanId.CreateFromBytes(secondSpanIdBytes), second.SpanId); } [Fact] public void GetTraceOptions() { - Assert.Equal(TraceOptions.Default, first.TraceOptions); - Assert.Equal(TraceOptions.Builder().SetIsSampled(true).Build(), second.TraceOptions); + Assert.Equal(ActivityTraceFlags.None, first.TraceOptions); + Assert.Equal(ActivityTraceFlags.Recorded, second.TraceOptions); } [Fact] @@ -92,18 +93,18 @@ public void SpanContext_EqualsAndHashCode() // tester.addEqualityGroup( // first, // SpanContext.create( - // TraceId.FromBytes(firstTraceIdBytes), - // SpanId.FromBytes(firstSpanIdBytes), + // ActivityTraceId.CreateFromBytes(firstTraceIdBytes), + // ActivitySpanId.CreateFromBytes(firstSpanIdBytes), // TraceOptions.DEFAULT), // SpanContext.create( - // TraceId.FromBytes(firstTraceIdBytes), - // SpanId.FromBytes(firstSpanIdBytes), + // ActivityTraceId.CreateFromBytes(firstTraceIdBytes), + // ActivitySpanId.CreateFromBytes(firstSpanIdBytes), // TraceOptions.builder().setIsSampled(false).build())); // tester.addEqualityGroup( // second, // SpanContext.create( - // TraceId.FromBytes(secondTraceIdBytes), - // SpanId.FromBytes(secondSpanIdBytes), + // ActivityTraceId.CreateFromBytes(secondTraceIdBytes), + // ActivitySpanId.CreateFromBytes(secondSpanIdBytes), // TraceOptions.builder().setIsSampled(true).build())); // tester.testEquals(); } @@ -111,12 +112,12 @@ public void SpanContext_EqualsAndHashCode() [Fact] public void SpanContext_ToString() { - Assert.Contains(TraceId.FromBytes(firstTraceIdBytes).ToString(), first.ToString()); - Assert.Contains(SpanId.FromBytes(firstSpanIdBytes).ToString(), first.ToString()); - Assert.Contains(TraceOptions.Default.ToString(), first.ToString()); - Assert.Contains(TraceId.FromBytes(secondTraceIdBytes).ToString(), second.ToString()); - Assert.Contains(SpanId.FromBytes(secondSpanIdBytes).ToString(), second.ToString()); - Assert.Contains(TraceOptions.Builder().SetIsSampled(true).Build().ToString(), second.ToString()); + Assert.Contains(ActivityTraceId.CreateFromBytes(firstTraceIdBytes).ToString(), first.ToString()); + Assert.Contains(ActivitySpanId.CreateFromBytes(firstSpanIdBytes).ToString(), first.ToString()); + Assert.Contains(ActivityTraceFlags.None.ToString(), first.ToString()); + Assert.Contains(ActivityTraceId.CreateFromBytes(secondTraceIdBytes).ToString(), second.ToString()); + Assert.Contains(ActivitySpanId.CreateFromBytes(secondSpanIdBytes).ToString(), second.ToString()); + Assert.Contains(ActivityTraceFlags.Recorded.ToString(), second.ToString()); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanIdTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanIdTest.cs deleted file mode 100644 index 08f8aba260d..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanIdTest.cs +++ /dev/null @@ -1,93 +0,0 @@ -// -// 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.Test -{ - using Xunit; - - public class SpanIdTest - { - private static readonly byte[] firstBytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)'a' }; - private static readonly byte[] secondBytes = new byte[] { 0xFF, 0, 0, 0, 0, 0, 0, (byte)'A' }; - private static readonly SpanId first = SpanId.FromBytes(firstBytes); - private static readonly SpanId second = SpanId.FromBytes(secondBytes); - - [Fact] - public void invalidSpanId() - { - Assert.Equal(new byte[8], SpanId.Invalid.Bytes); - } - - [Fact] - public void IsValid() - { - Assert.False(SpanId.Invalid.IsValid); - Assert.True(first.IsValid); - Assert.True(second.IsValid); - } - - [Fact] - public void FromLowerBase16() - { - Assert.Equal(SpanId.Invalid, SpanId.FromLowerBase16("0000000000000000")); - Assert.Equal(first, SpanId.FromLowerBase16("0000000000000061")); - Assert.Equal(second, SpanId.FromLowerBase16("ff00000000000041")); - } - - [Fact] - public void ToLowerBase16() - { - Assert.Equal("0000000000000000", SpanId.Invalid.ToLowerBase16()); - Assert.Equal("0000000000000061", first.ToLowerBase16()); - Assert.Equal("ff00000000000041", second.ToLowerBase16()); - } - - [Fact] - public void Bytes() - { - Assert.Equal(firstBytes, first.Bytes); - Assert.Equal(secondBytes, second.Bytes); - - } - - [Fact] - public void SpanId_CompareTo() - { - Assert.Equal(1, first.CompareTo(second)); - Assert.Equal(-1, second.CompareTo(first)); - Assert.Equal(0, first.CompareTo(SpanId.FromBytes(firstBytes))); - } - - [Fact] - public void SpanId_EqualsAndHashCode() - { - // EqualsTester tester = new EqualsTester(); - // tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); - // tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); - // tester.addEqualityGroup( - // second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); - // tester.testEquals(); - } - - [Fact] - public void SpanId_ToString() - { - Assert.Contains("0000000000000000", SpanId.Invalid.ToString()); - Assert.Contains("0000000000000061", first.ToString()); - Assert.Contains("ff00000000000041", second.ToString()); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 369714c4dd9..fe2e3e4761a 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -18,21 +18,22 @@ namespace OpenTelemetry.Trace.Test { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using Moq; using OpenTelemetry.Common; using OpenTelemetry.Internal; + using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; using Xunit; public class SpanTest { - private static readonly String SPAN_NAME = "MySpanName"; - private static readonly String EVENT_DESCRIPTION = "MyEvent"; - private readonly RandomGenerator random = new RandomGenerator(1234); + private const string SpanName = "MySpanName"; + private const string EventDescription = "MyEvent"; private readonly SpanContext spanContext; - private readonly SpanId parentSpanId; + private readonly ActivitySpanId parentSpanId; private TimeSpan interval = TimeSpan.FromMilliseconds(0); private readonly DateTimeOffset startTime = DateTimeOffset.Now; private readonly Timestamp timestamp; @@ -47,9 +48,9 @@ public SpanTest() { timestamp = Timestamp.FromDateTimeOffset(startTime); timestampConverter = Timer.StartNew(startTime, () => interval); - spanContext = SpanContext.Create(TraceId.GenerateRandomId(random), SpanId.GenerateRandomId(random), - OpenTelemetry.Trace.TraceOptions.Default, Tracestate.Empty); - parentSpanId = SpanId.GenerateRandomId(random); + spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); + parentSpanId = ActivitySpanId.CreateRandom(); attributes.Add( "MyStringAttributeKey", AttributeValue.StringAttributeValue("MyStringAttributeValue")); attributes.Add("MyLongAttributeKey", AttributeValue.LongAttributeValue(123L)); @@ -67,7 +68,7 @@ public void ToSpanData_NoRecordEvents() Span.StartSpan( spanContext, noRecordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -79,8 +80,8 @@ public void ToSpanData_NoRecordEvents() span.SetAttribute(attribute.Key, attribute.Value); } - span.AddEvent(Event.Create(EVENT_DESCRIPTION)); - span.AddEvent(EVENT_DESCRIPTION, attributes); + span.AddEvent(Event.Create(EventDescription)); + span.AddEvent(EventDescription, attributes); span.AddLink(Link.FromSpanContext(spanContext)); span.End(); // exception.expect(IllegalStateException); @@ -94,7 +95,7 @@ public void NoEventsRecordedAfterEnd() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -111,8 +112,8 @@ public void NoEventsRecordedAfterEnd() span.SetAttribute( "MySingleStringAttributeKey", AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); - span.AddEvent(Event.Create(EVENT_DESCRIPTION)); - span.AddEvent(EVENT_DESCRIPTION, attributes); + span.AddEvent(Event.Create(EventDescription)); + span.AddEvent(EventDescription, attributes); span.AddLink(Link.FromSpanContext(spanContext)); var spanData = ((Span)span).ToSpanData(); Assert.Equal(timestamp, spanData.StartTimestamp); @@ -130,7 +131,7 @@ public void ToSpanData_ActiveSpan() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -146,16 +147,16 @@ public void ToSpanData_ActiveSpan() } interval = TimeSpan.FromMilliseconds(100); - span.AddEvent(Event.Create(EVENT_DESCRIPTION)); + span.AddEvent(Event.Create(EventDescription)); interval = TimeSpan.FromMilliseconds(200); - span.AddEvent(EVENT_DESCRIPTION, attributes); + span.AddEvent(EventDescription, attributes); interval = TimeSpan.FromMilliseconds(300); interval = TimeSpan.FromMilliseconds(400); var link = Link.FromSpanContext(spanContext); span.AddLink(link); var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); - Assert.Equal(SPAN_NAME, spanData.Name); + Assert.Equal(SpanName, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); @@ -163,10 +164,10 @@ public void ToSpanData_ActiveSpan() Assert.Equal(2, spanData.Events.Events.Count()); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), spanData.Events.Events.ToList()[0].Timestamp); - Assert.Equal(Event.Create(EVENT_DESCRIPTION), spanData.Events.Events.ToList()[0].Event); + Assert.Equal(Event.Create(EventDescription), spanData.Events.Events.ToList()[0].Event); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), spanData.Events.Events.ToList()[1].Timestamp); - Assert.Equal(Event.Create(EVENT_DESCRIPTION, attributes), spanData.Events.Events.ToList()[1].Event); + Assert.Equal(Event.Create(EventDescription, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); Assert.Equal(link, spanData.Links.Links.First()); @@ -185,7 +186,7 @@ public void GoSpanData_EndedSpan() (Span)Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -201,9 +202,9 @@ public void GoSpanData_EndedSpan() } interval = TimeSpan.FromMilliseconds(100); - span.AddEvent(Event.Create(EVENT_DESCRIPTION)); + span.AddEvent(Event.Create(EventDescription)); interval = TimeSpan.FromMilliseconds(200); - span.AddEvent(EVENT_DESCRIPTION, attributes); + span.AddEvent(EventDescription, attributes); interval = TimeSpan.FromMilliseconds(300); var link = Link.FromSpanContext(spanContext); span.AddLink(link); @@ -213,7 +214,7 @@ public void GoSpanData_EndedSpan() var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext, spanData.Context); - Assert.Equal(SPAN_NAME, spanData.Name); + Assert.Equal(SpanName, spanData.Name); Assert.Equal(parentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); @@ -221,10 +222,10 @@ public void GoSpanData_EndedSpan() Assert.Equal(2, spanData.Events.Events.Count()); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), spanData.Events.Events.ToList()[0].Timestamp); - Assert.Equal(Event.Create(EVENT_DESCRIPTION), spanData.Events.Events.ToList()[0].Event); + Assert.Equal(Event.Create(EventDescription), spanData.Events.Events.ToList()[0].Event); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), spanData.Events.Events.ToList()[1].Timestamp); - Assert.Equal(Event.Create(EVENT_DESCRIPTION, attributes), spanData.Events.Events.ToList()[1].Event); + Assert.Equal(Event.Create(EventDescription, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); Assert.Equal(link, spanData.Links.Links.First()); @@ -244,7 +245,7 @@ public void Status_ViaSetStatus() (Span)Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -268,7 +269,7 @@ public void status_ViaEndSpanOptions() (Span)Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -296,7 +297,7 @@ public void DroppingAttributes() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, traceParams, @@ -349,7 +350,7 @@ public void DroppingAndAddingAttributes() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, traceParams, @@ -420,13 +421,13 @@ public void DroppingEvents() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, traceParams, startEndHandler, timestampConverter); - var testEvent = Event.Create(EVENT_DESCRIPTION); + var testEvent = Event.Create(EventDescription); var i = 0; for (i = 0; i < 2 * maxNumberOfEvents; i++) { @@ -472,7 +473,7 @@ public void DroppingLinks() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, traceParams, @@ -509,7 +510,7 @@ public void SampleToLocalSpanStore() (Span)Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -523,7 +524,7 @@ public void SampleToLocalSpanStore() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -546,7 +547,7 @@ public void SampleToLocalSpanStore_RunningSpan() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -563,7 +564,7 @@ public void BadArguments() Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, @@ -590,7 +591,7 @@ public void SetSampleTo() var span = (Span)Span.StartSpan( spanContext, recordSpanOptions, - SPAN_NAME, + SpanName, SpanKind.Internal, parentSpanId, TraceParams.Default, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs index 110a9804d8b..b341e2e543b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs @@ -23,7 +23,7 @@ namespace OpenTelemetry.Trace.Test public class TraceComponentTest { - private readonly TraceComponent traceComponent = new TraceComponent(new RandomGenerator(), new SimpleEventQueue()); + private readonly TraceComponent traceComponent = new TraceComponent(new SimpleEventQueue()); [Fact] public void ImplementationOfTracer() diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TraceIdTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TraceIdTest.cs deleted file mode 100644 index 74e2c3433e6..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/TraceIdTest.cs +++ /dev/null @@ -1,96 +0,0 @@ -// -// 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.Test -{ - using Xunit; - - public class TraceIdTest - { - private static readonly byte[] firstBytes = - new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)'a' }; - - private static readonly byte[] secondBytes = - new byte[] { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)'A' }; - - private static readonly TraceId first = TraceId.FromBytes(firstBytes); - private static readonly TraceId second = TraceId.FromBytes(secondBytes); - - [Fact] - public void invalidTraceId() - { - Assert.Equal(new byte[16], TraceId.Invalid.Bytes); - } - - [Fact] - public void IsValid() - { - Assert.False(TraceId.Invalid.IsValid); - Assert.True(first.IsValid); - Assert.True(second.IsValid); - } - - [Fact] - public void Bytes() - { - Assert.Equal(firstBytes, first.Bytes); - Assert.Equal(secondBytes, second.Bytes); - } - - [Fact] - public void FromLowerBase16() - { - Assert.Equal(TraceId.Invalid, TraceId.FromLowerBase16("00000000000000000000000000000000")); - Assert.Equal(first, TraceId.FromLowerBase16("00000000000000000000000000000061")); - Assert.Equal(second, TraceId.FromLowerBase16("ff000000000000000000000000000041")); - } - - [Fact] - public void ToLowerBase16() - { - Assert.Equal("00000000000000000000000000000000", TraceId.Invalid.ToLowerBase16()); - Assert.Equal("00000000000000000000000000000061", first.ToLowerBase16()); - Assert.Equal("ff000000000000000000000000000041", second.ToLowerBase16()); - } - - [Fact] - public void TraceId_CompareTo() - { - Assert.Equal(1, first.CompareTo(second)); - Assert.Equal(-1, second.CompareTo(first)); - Assert.Equal(0, first.CompareTo(TraceId.FromBytes(firstBytes))); - } - - [Fact] - public void TraceId_EqualsAndHashCode() - { - // EqualsTester tester = new EqualsTester(); - // tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); - // tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); - // tester.addEqualityGroup( - // second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); - // tester.testEquals(); - } - - [Fact] - public void TraceId_ToString() - { - Assert.Contains("00000000000000000000000000000000", TraceId.Invalid.ToString()); - Assert.Contains("00000000000000000000000000000061", first.ToString()); - Assert.Contains("ff000000000000000000000000000041", second.ToString()); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TraceOptionsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TraceOptionsTest.cs deleted file mode 100644 index 90d14f18cd1..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/TraceOptionsTest.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// 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.Test -{ - using Xunit; - - public class TraceOptionsTest - { - private static readonly byte[] firstBytes = { 0xff }; - private static readonly byte[] secondBytes = { 1 }; - private static readonly byte[] thirdBytes = { 6 }; - - [Fact] - public void getOptions() - { - Assert.Equal(0, TraceOptions.Default.Options); - Assert.Equal(0, TraceOptions.Builder().SetIsSampled(false).Build().Options); - Assert.Equal(1, TraceOptions.Builder().SetIsSampled(true).Build().Options); - Assert.Equal(0, TraceOptions.Builder().SetIsSampled(true).SetIsSampled(false).Build().Options); - Assert.Equal(-1, TraceOptions.FromBytes(firstBytes).Options); - Assert.Equal(1, TraceOptions.FromBytes(secondBytes).Options); - Assert.Equal(6, TraceOptions.FromBytes(thirdBytes).Options); - } - - [Fact] - public void IsSampled() - { - Assert.False(TraceOptions.Default.IsSampled); - Assert.True(TraceOptions.Builder().SetIsSampled(true).Build().IsSampled); - } - - [Fact] - public void ToFromBytes() - { - Assert.Equal(firstBytes, TraceOptions.FromBytes(firstBytes).Bytes); - Assert.Equal(secondBytes, TraceOptions.FromBytes(secondBytes).Bytes); - Assert.Equal(thirdBytes, TraceOptions.FromBytes(thirdBytes).Bytes); - } - - [Fact] - public void Builder_FromOptions() - { - Assert.Equal(6 | 1, - TraceOptions.Builder(TraceOptions.FromBytes(thirdBytes)) - .SetIsSampled(true) - .Build() - .Options); - } - - [Fact] - public void traceOptions_EqualsAndHashCode() - { - // EqualsTester tester = new EqualsTester(); - // tester.addEqualityGroup(TraceOptions.DEFAULT); - // tester.addEqualityGroup( - // TraceOptions.FromBytes(secondBytes), TraceOptions.Builder().SetIsSampled(true).build()); - // tester.addEqualityGroup(TraceOptions.FromBytes(firstBytes)); - // tester.testEquals(); - } - - [Fact] - public void traceOptions_ToString() - { - Assert.Contains("sampled=False", TraceOptions.Default.ToString()); - Assert.Contains("sampled=True", TraceOptions.Builder().SetIsSampled(true).Build().ToString()); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index 66f7fad7323..ab5c19dfab1 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -36,7 +36,7 @@ public TracerTest() { startEndHandler = Mock.Of(); traceConfig = Mock.Of(); - tracer = new Tracer(new RandomGenerator(), startEndHandler, traceConfig, null); + tracer = new Tracer(startEndHandler, traceConfig, null); } [Fact] From 4b273d46a4fba8e6b53804934bd0bfd39d318df8 Mon Sep 17 00:00:00 2001 From: Tim Wegner Date: Thu, 11 Jul 2019 21:53:12 -0700 Subject: [PATCH 12/41] Dev/twegner/issue 18 (#111) * Rmoving ITraceComponent and TraceComponent * Removing ITagsComponent, TagsComponentBase and TagsComponent * REmoving ITagPropagationComponent, TagPropagationComponentBase and TagPropagationComponent * Removing IStatsComponent, StatsComponentBase and StatsComponent * Addressing test failures since updates have allowed rules on duplicates to be enforced. * Test updates, wrok in progress * Resolving some unit test failrues * Resolving some unit test failrues * Simplify map to list * Addressing final set of unit test failures * Updating for feedback * Addressing tests that were relying on specific order * Updating for feedback * Addressing merge issues * Resolving build and test failures introduced in merge * Resolving additional build and test issues * Fixing unresolved dependencies --- samples/Exporters/TestApplicationInsights.cs | 9 +- .../Tags/ITagsComponent.cs | 41 --- .../Propagation/ITagPropagationComponent.cs | 29 -- .../Trace/IRandomGenerator.cs} | 12 +- .../Trace/ITraceComponent.cs | 42 --- .../Stats/CumulativeMutableViewData.cs | 3 +- src/OpenTelemetry/Stats/IStatsComponent.cs | 39 --- src/OpenTelemetry/Stats/MeasureMap.cs | 3 +- src/OpenTelemetry/Stats/MeasureToViewMap.cs | 175 ++++------ src/OpenTelemetry/Stats/NoopStats.cs | 5 - src/OpenTelemetry/Stats/NoopStatsComponent.cs | 53 --- src/OpenTelemetry/Stats/Stats.cs | 50 ++- src/OpenTelemetry/Stats/StatsComponent.cs | 80 ----- src/OpenTelemetry/Stats/StatsComponentBase.cs | 27 -- .../Tags/NoopTagPropagationComponent.cs | 33 -- src/OpenTelemetry/Tags/NoopTags.cs | 13 - src/OpenTelemetry/Tags/NoopTagsComponent.cs | 49 --- .../Propagation/TagPropagationComponent.cs | 33 -- src/OpenTelemetry/Tags/Tags.cs | 40 +-- src/OpenTelemetry/Tags/TagsComponent.cs | 50 --- src/OpenTelemetry/Tags/TagsComponentBase.cs | 29 -- .../Trace/Internal/RandomGenerator.cs | 58 ++++ src/OpenTelemetry/Trace/SpanBuilderOptions.cs | 5 +- src/OpenTelemetry/Trace/TraceComponent.cs | 73 ---- src/OpenTelemetry/Trace/Tracer.cs | 53 ++- src/OpenTelemetry/Trace/Tracing.cs | 44 ++- .../BasicTests.cs | 6 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 2 +- ...elemetry.Collector.AspNetCore.Tests.csproj | 2 +- .../BasicTests.cs | 2 +- .../HttpClientTests.cs | 2 +- .../StackExchangeRedisCallsCollectorTests.cs | 2 +- .../Impl/Stats/NoopStatsTest.cs | 41 --- .../Impl/Stats/QuickStartExampleTest.cs | 84 +++-- .../Impl/Stats/StatsComponentTest.cs | 65 ---- .../Impl/Stats/StatsRecorderTest.cs | 89 +++-- .../Impl/Stats/StatsTestUtil.cs | 19 +- .../Impl/Stats/ViewManagerTest.cs | 328 ++++++++++-------- .../Impl/Tags/NoopTagsTest.cs | 15 - .../TagContextBinarySerializerTest.cs | 5 +- .../TagContextDeserializationTest.cs | 9 +- .../Propagation/TagContextRoundtripTest.cs | 9 +- .../TagContextSerializationTest.cs | 9 +- .../Impl/Tags/TaggerTest.cs | 5 +- .../Impl/Tags/TagsComponentBaseTest.cs | 31 -- .../Impl/Tags/TagsDefaultTest.cs | 7 - .../OpenTelemetry.Tests/Impl/Tags/TagsTest.cs | 8 +- .../Impl/Trace/SpanBuilderTest.cs | 3 +- .../Impl/Trace/TraceComponentTest.cs | 40 --- .../Impl/Trace/TracerTest.cs | 2 +- test/TestApp.AspNetCore.2.0/Startup.cs | 2 +- 51 files changed, 607 insertions(+), 1228 deletions(-) delete mode 100644 src/OpenTelemetry.Abstractions/Tags/ITagsComponent.cs delete mode 100644 src/OpenTelemetry.Abstractions/Tags/Propagation/ITagPropagationComponent.cs rename src/{OpenTelemetry/Tags/Propagation/TagPropagationComponentBase.cs => OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs} (63%) delete mode 100644 src/OpenTelemetry.Abstractions/Trace/ITraceComponent.cs delete mode 100644 src/OpenTelemetry/Stats/IStatsComponent.cs delete mode 100644 src/OpenTelemetry/Stats/NoopStatsComponent.cs delete mode 100644 src/OpenTelemetry/Stats/StatsComponent.cs delete mode 100644 src/OpenTelemetry/Stats/StatsComponentBase.cs delete mode 100644 src/OpenTelemetry/Tags/NoopTagPropagationComponent.cs delete mode 100644 src/OpenTelemetry/Tags/NoopTagsComponent.cs delete mode 100644 src/OpenTelemetry/Tags/Propagation/TagPropagationComponent.cs delete mode 100644 src/OpenTelemetry/Tags/TagsComponent.cs delete mode 100644 src/OpenTelemetry/Tags/TagsComponentBase.cs create mode 100644 src/OpenTelemetry/Trace/Internal/RandomGenerator.cs delete mode 100644 src/OpenTelemetry/Trace/TraceComponent.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Stats/StatsComponentTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Tags/TagsComponentBaseTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs diff --git a/samples/Exporters/TestApplicationInsights.cs b/samples/Exporters/TestApplicationInsights.cs index 315af97fa5a..4ef62531c65 100644 --- a/samples/Exporters/TestApplicationInsights.cs +++ b/samples/Exporters/TestApplicationInsights.cs @@ -21,11 +21,13 @@ namespace Samples using System.Threading; using Microsoft.ApplicationInsights.Extensibility; using OpenTelemetry.Exporter.ApplicationInsights; + using OpenTelemetry.Internal; using OpenTelemetry.Stats; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Sampler; internal class TestApplicationInsights @@ -50,8 +52,11 @@ internal class TestApplicationInsights internal static object Run() { + SimpleEventQueue eventQueue = new SimpleEventQueue(); + ExportComponent exportComponent = ExportComponent.CreateWithInProcessStores(eventQueue); + TelemetryConfiguration.Active.InstrumentationKey = "instrumentation-key"; - var exporter = new ApplicationInsightsExporter(Tracing.ExportComponent, Stats.ViewManager, TelemetryConfiguration.Active); + var exporter = new ApplicationInsightsExporter(exportComponent, Stats.ViewManager, TelemetryConfiguration.Active); exporter.Start(); var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); @@ -83,6 +88,8 @@ internal static object Run() Console.WriteLine("Done... wait for events to arrive to backend!"); Console.ReadLine(); + exportComponent.SpanExporter.Dispose(); + return null; } } diff --git a/src/OpenTelemetry.Abstractions/Tags/ITagsComponent.cs b/src/OpenTelemetry.Abstractions/Tags/ITagsComponent.cs deleted file mode 100644 index d80548baebc..00000000000 --- a/src/OpenTelemetry.Abstractions/Tags/ITagsComponent.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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.Tags -{ - using OpenTelemetry.Tags.Propagation; - - /// - /// Tagger configuration. - /// - public interface ITagsComponent - { - /// - /// Gets the tagger to operate with tags. - /// - ITagger Tagger { get; } - - /// - /// Gets the propagation component to use to serialize and deserialize tags on the wire. - /// - ITagPropagationComponent TagPropagationComponent { get; } - - /// - /// Gets the state of tagging API - enabled or disabled. - /// - TaggingState State { get; } - } -} \ No newline at end of file diff --git a/src/OpenTelemetry.Abstractions/Tags/Propagation/ITagPropagationComponent.cs b/src/OpenTelemetry.Abstractions/Tags/Propagation/ITagPropagationComponent.cs deleted file mode 100644 index 63ce92d1037..00000000000 --- a/src/OpenTelemetry.Abstractions/Tags/Propagation/ITagPropagationComponent.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// 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.Tags.Propagation -{ - /// - /// Stores configuration of various propagation serializers for tags. - /// - public interface ITagPropagationComponent - { - /// - /// Gets binary serializer/deserializer for tags. - /// - ITagContextBinarySerializer BinarySerializer { get; } - } -} diff --git a/src/OpenTelemetry/Tags/Propagation/TagPropagationComponentBase.cs b/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs similarity index 63% rename from src/OpenTelemetry/Tags/Propagation/TagPropagationComponentBase.cs rename to src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs index fad841d2577..a7b79c2b755 100644 --- a/src/OpenTelemetry/Tags/Propagation/TagPropagationComponentBase.cs +++ b/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,10 @@ // limitations under the License. // -namespace OpenTelemetry.Tags.Propagation +namespace OpenTelemetry.Trace { - public abstract class TagPropagationComponentBase : ITagPropagationComponent + public interface IRandomGenerator { - protected TagPropagationComponentBase() - { - } - - public abstract ITagContextBinarySerializer BinarySerializer { get; } + void NextBytes(byte[] bytes); } } diff --git a/src/OpenTelemetry.Abstractions/Trace/ITraceComponent.cs b/src/OpenTelemetry.Abstractions/Trace/ITraceComponent.cs deleted file mode 100644 index 9e3857b8bd1..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/ITraceComponent.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// 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.Trace.Config; - using OpenTelemetry.Trace.Export; - - /// - /// Trace component holds all the extensibility points required for distributed tracing. - /// - public interface ITraceComponent - { - /// - /// Gets the tracer to record Spans. - /// - ITracer Tracer { get; } - - /// - /// Gets the trace config. - /// - ITraceConfig TraceConfig { get; } - - /// - /// Gets the exporter to use to upload spans. - /// - IExportComponent ExportComponent { get; } - } -} diff --git a/src/OpenTelemetry/Stats/CumulativeMutableViewData.cs b/src/OpenTelemetry/Stats/CumulativeMutableViewData.cs index f04825d45ce..3204ba7f91e 100644 --- a/src/OpenTelemetry/Stats/CumulativeMutableViewData.cs +++ b/src/OpenTelemetry/Stats/CumulativeMutableViewData.cs @@ -17,12 +17,13 @@ namespace OpenTelemetry.Stats { using System; + using System.Collections.Concurrent; using System.Collections.Generic; using OpenTelemetry.Tags; internal class CumulativeMutableViewData : MutableViewData { - private readonly IDictionary tagValueAggregationMap = new Dictionary(); + private readonly IDictionary tagValueAggregationMap = new ConcurrentDictionary(); private DateTimeOffset start; internal CumulativeMutableViewData(IView view, DateTimeOffset start) diff --git a/src/OpenTelemetry/Stats/IStatsComponent.cs b/src/OpenTelemetry/Stats/IStatsComponent.cs deleted file mode 100644 index 1ce99a97902..00000000000 --- a/src/OpenTelemetry/Stats/IStatsComponent.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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.Stats -{ - /// - /// Stats recording configuration. - /// - public interface IStatsComponent - { - /// - /// Gets the view manager that holds current set of aggregators. - /// - IViewManager ViewManager { get; } - - /// - /// Gets the stats recorder to record values to. - /// - IStatsRecorder StatsRecorder { get; } - - /// - /// Gets the state of the state collection. - /// - StatsCollectionState State { get; } - } -} diff --git a/src/OpenTelemetry/Stats/MeasureMap.cs b/src/OpenTelemetry/Stats/MeasureMap.cs index c78d45989be..76c0b548185 100644 --- a/src/OpenTelemetry/Stats/MeasureMap.cs +++ b/src/OpenTelemetry/Stats/MeasureMap.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Stats { using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; + using OpenTelemetry.Tags.Unsafe; internal sealed class MeasureMap : MeasureMapBase { @@ -44,7 +45,7 @@ public override IMeasureMap Put(IMeasureLong measure, long value) public override void Record() { // Use the context key directly, to avoid depending on the tags implementation. - this.Record(CurrentTagContextUtils.CurrentTagContext); + this.Record(AsyncLocalContext.CurrentTagContext); } public override void Record(ITagContext tags) diff --git a/src/OpenTelemetry/Stats/MeasureToViewMap.cs b/src/OpenTelemetry/Stats/MeasureToViewMap.cs index 736275c6d87..aa5a6fb4ae3 100644 --- a/src/OpenTelemetry/Stats/MeasureToViewMap.cs +++ b/src/OpenTelemetry/Stats/MeasureToViewMap.cs @@ -17,19 +17,19 @@ namespace OpenTelemetry.Stats { using System; + using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using OpenTelemetry.Tags; internal sealed class MeasureToViewMap { - private readonly object lck = new object(); - private readonly IDictionary> mutableMap = new Dictionary>(); + private readonly IDictionary> mutableMap = new ConcurrentDictionary>(); - private readonly IDictionary registeredViews = new Dictionary(); + private readonly IDictionary registeredViews = new ConcurrentDictionary(); // TODO(songya): consider adding a Measure.Name class - private readonly IDictionary registeredMeasures = new Dictionary(); + private readonly IDictionary registeredMeasures = new ConcurrentDictionary(); // Cached set of exported views. It must be set to null whenever a view is registered or // unregistered. @@ -45,10 +45,7 @@ internal ISet ExportedViews var views = this.exportedViews; if (views == null) { - lock (this.lck) - { - this.exportedViews = views = FilterExportedViews(this.registeredViews.Values); - } + this.exportedViews = views = FilterExportedViews(this.registeredViews.Values); } return views; @@ -57,11 +54,8 @@ internal ISet ExportedViews internal IViewData GetView(IViewName viewName, StatsCollectionState state) { - lock (this.lck) - { - var view = this.GetMutableViewData(viewName); - return view?.ToViewData(DateTimeOffset.Now, state); - } + var view = this.GetMutableViewData(viewName); + return view?.ToViewData(DateTimeOffset.Now, state); } /// @@ -70,74 +64,68 @@ internal IViewData GetView(IViewName viewName, StatsCollectionState state) /// The view. internal void RegisterView(IView view) { - lock (this.lck) + this.exportedViews = null; + this.registeredViews.TryGetValue(view.Name, out var existing); + if (existing != null) { - this.exportedViews = null; - this.registeredViews.TryGetValue(view.Name, out var existing); - if (existing != null) + if (existing.Equals(view)) { - if (existing.Equals(view)) - { - // Ignore views that are already registered. - return; - } - else - { - throw new ArgumentException("A different view with the same name is already registered: " + existing); - } + // Ignore views that are already registered. + return; } - - var measure = view.Measure; - this.registeredMeasures.TryGetValue(measure.Name, out var registeredMeasure); - if (registeredMeasure != null && !registeredMeasure.Equals(measure)) + else { - throw new ArgumentException("A different measure with the same name is already registered: " + registeredMeasure); + throw new ArgumentException("A different view with the same name is already registered: " + existing); } + } - this.registeredViews.Add(view.Name, view); - if (registeredMeasure == null) - { - this.registeredMeasures.Add(measure.Name, measure); - } + var measure = view.Measure; + this.registeredMeasures.TryGetValue(measure.Name, out var registeredMeasure); + if (registeredMeasure != null && !registeredMeasure.Equals(measure)) + { + throw new ArgumentException("A different measure with the same name is already registered: " + registeredMeasure); + } - this.AddMutableViewData(view.Measure.Name, MutableViewData.Create(view, DateTimeOffset.Now)); + this.registeredViews.Add(view.Name, view); + if (registeredMeasure == null) + { + this.registeredMeasures.Add(measure.Name, measure); } + + this.AddMutableViewData(view.Measure.Name, MutableViewData.Create(view, DateTimeOffset.Now)); } // Records stats with a set of tags. internal void Record(ITagContext tags, IEnumerable stats, DateTimeOffset timestamp) { - lock (this.lck) + foreach (var measurement in stats) { - foreach (var measurement in stats) + var measure = measurement.Measure; + this.registeredMeasures.TryGetValue(measure.Name, out var value); + if (!measure.Equals(value)) { - var measure = measurement.Measure; - this.registeredMeasures.TryGetValue(measure.Name, out var value); - if (!measure.Equals(value)) - { - // unregistered measures will be ignored. - continue; - } + // unregistered measures will be ignored. + continue; + } - var views = this.mutableMap[measure.Name]; - foreach (var view in views) - { - measurement.Match( - (arg) => - { - view.Record(tags, arg.Value, timestamp); - return null; - }, - (arg) => - { - view.Record(tags, arg.Value, timestamp); - return null; - }, - (arg) => - { - throw new ArgumentException(); - }); - } + var views = this.mutableMap[measure.Name]; + foreach (var view in views) + { + measurement.Match( + (arg) => + { + view.Record(tags, arg.Value, timestamp); + return null; + }, + (arg) => + { + view.Record(tags, arg.Value, timestamp); + return null; + }, + (arg) => + { + throw new ArgumentException(); + }); } } } @@ -145,14 +133,11 @@ internal void Record(ITagContext tags, IEnumerable stats, DateTime // Clear stats for all the current MutableViewData internal void ClearStats() { - lock (this.lck) + foreach (var entry in this.mutableMap) { - foreach (var entry in this.mutableMap) + foreach (var mutableViewData in entry.Value) { - foreach (var mutableViewData in entry.Value) - { - mutableViewData.ClearStats(); - } + mutableViewData.ClearStats(); } } } @@ -160,14 +145,11 @@ internal void ClearStats() // Resume stats collection for all MutableViewData. internal void ResumeStatsCollection(DateTimeOffset now) { - lock (this.lck) + foreach (var entry in this.mutableMap) { - foreach (var entry in this.mutableMap) + foreach (var mutableViewData in entry.Value) { - foreach (var mutableViewData in entry.Value) - { - mutableViewData.ResumeStatsCollection(now); - } + mutableViewData.ResumeStatsCollection(now); } } } @@ -192,34 +174,31 @@ private void AddMutableViewData(string name, MutableViewData mutableViewData) private MutableViewData GetMutableViewData(IViewName viewName) { - lock (this.lck) + this.registeredViews.TryGetValue(viewName, out var view); + if (view == null) { - this.registeredViews.TryGetValue(viewName, out var view); - if (view == null) - { - return null; - } + return null; + } - this.mutableMap.TryGetValue(view.Measure.Name, out var views); - if (views != null) + this.mutableMap.TryGetValue(view.Measure.Name, out var views); + if (views != null) + { + foreach (var viewData in views) { - foreach (var viewData in views) + if (viewData.View.Name.Equals(viewName)) { - if (viewData.View.Name.Equals(viewName)) - { - return viewData; - } + return viewData; } } - - throw new InvalidOperationException( - "Internal error: Not recording stats for view: \"" - + viewName - + "\" registeredViews=" - + this.registeredViews - + ", mutableMap=" - + this.mutableMap); } + + throw new InvalidOperationException( + "Internal error: Not recording stats for view: \"" + + viewName + + "\" registeredViews=" + + this.registeredViews + + ", mutableMap=" + + this.mutableMap); } } } diff --git a/src/OpenTelemetry/Stats/NoopStats.cs b/src/OpenTelemetry/Stats/NoopStats.cs index 7c8f6e64d13..27eacda499e 100644 --- a/src/OpenTelemetry/Stats/NoopStats.cs +++ b/src/OpenTelemetry/Stats/NoopStats.cs @@ -38,11 +38,6 @@ internal static IMeasureMap NoopMeasureMap } } - internal static IStatsComponent NewNoopStatsComponent() - { - return new NoopStatsComponent(); - } - internal static IViewManager NewNoopViewManager() { return new NoopViewManager(); diff --git a/src/OpenTelemetry/Stats/NoopStatsComponent.cs b/src/OpenTelemetry/Stats/NoopStatsComponent.cs deleted file mode 100644 index 5ad05558744..00000000000 --- a/src/OpenTelemetry/Stats/NoopStatsComponent.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// 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.Stats -{ - internal sealed class NoopStatsComponent : StatsComponentBase - { - private readonly IViewManager viewManager = NoopStats.NewNoopViewManager(); - - // private volatile bool isRead; - public override IViewManager ViewManager - { - get - { - return this.viewManager; - } - } - - public override IStatsRecorder StatsRecorder - { - get - { - return NoopStats.NoopStatsRecorder; - } - } - - public override StatsCollectionState State - { - get - { - // isRead = true; - return StatsCollectionState.DISABLED; - } - - set - { - } - } - } -} diff --git a/src/OpenTelemetry/Stats/Stats.cs b/src/OpenTelemetry/Stats/Stats.cs index 1468612e56f..989075879ce 100644 --- a/src/OpenTelemetry/Stats/Stats.cs +++ b/src/OpenTelemetry/Stats/Stats.cs @@ -16,34 +16,29 @@ namespace OpenTelemetry.Stats { + using OpenTelemetry.Internal; + public class Stats { private static readonly Stats StatsValue = new Stats(); - private readonly IStatsComponent statsComponent = new StatsComponent(); + private readonly CurrentStatsState state = new CurrentStatsState(); + private readonly StatsManager statsManager; + private readonly IViewManager viewManager; + private readonly IStatsRecorder statsRecorder; internal Stats() - : this(true) - { - } - - internal Stats(bool enabled) { - if (enabled) - { - this.statsComponent = new StatsComponent(); - } - else - { - this.statsComponent = NoopStats.NewNoopStatsComponent(); - } + this.statsManager = new StatsManager(new SimpleEventQueue(), this.state); + this.viewManager = new ViewManager(this.statsManager); + this.statsRecorder = new StatsRecorder(this.statsManager); } public static IStatsRecorder StatsRecorder { get { - return StatsValue.statsComponent.StatsRecorder; + return StatsValue.statsRecorder; } } @@ -51,7 +46,7 @@ public static IViewManager ViewManager { get { - return StatsValue.statsComponent.ViewManager; + return StatsValue.viewManager; } } @@ -59,7 +54,28 @@ public static StatsCollectionState State { get { - return StatsValue.statsComponent.State; + return StatsValue.state.Value; + } + + set + { + if (!(StatsValue.viewManager is ViewManager manager)) + { + return; + } + + var result = StatsValue.state.Set(value); + if (result) + { + if (value == StatsCollectionState.DISABLED) + { + manager.ClearStats(); + } + else + { + manager.ResumeStatsCollection(); + } + } } } } diff --git a/src/OpenTelemetry/Stats/StatsComponent.cs b/src/OpenTelemetry/Stats/StatsComponent.cs deleted file mode 100644 index fe3a8f02ec3..00000000000 --- a/src/OpenTelemetry/Stats/StatsComponent.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// 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.Stats -{ - using OpenTelemetry.Internal; - - public class StatsComponent : StatsComponentBase - { - // The StatsCollectionState shared between the StatsComponent, StatsRecorder and ViewManager. - private readonly CurrentStatsState state = new CurrentStatsState(); - - private readonly IViewManager viewManager; - private readonly IStatsRecorder statsRecorder; - - public StatsComponent() - : this(new SimpleEventQueue()) - { - } - - public StatsComponent(IEventQueue queue) - { - var statsManager = new StatsManager(queue, this.state); - this.viewManager = new ViewManager(statsManager); - this.statsRecorder = new StatsRecorder(statsManager); - } - - public override IViewManager ViewManager - { - get { return this.viewManager; } - } - - public override IStatsRecorder StatsRecorder - { - get { return this.statsRecorder; } - } - - public override StatsCollectionState State - { - get - { - return this.state.Value; - } - - set - { - if (!(this.viewManager is ViewManager manager)) - { - return; - } - - var result = this.state.Set(value); - if (result) - { - if (value == StatsCollectionState.DISABLED) - { - manager.ClearStats(); - } - else - { - manager.ResumeStatsCollection(); - } - } - } - } - } -} diff --git a/src/OpenTelemetry/Stats/StatsComponentBase.cs b/src/OpenTelemetry/Stats/StatsComponentBase.cs deleted file mode 100644 index 760ddf08b07..00000000000 --- a/src/OpenTelemetry/Stats/StatsComponentBase.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// 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.Stats -{ - public abstract class StatsComponentBase : IStatsComponent - { - public abstract IViewManager ViewManager { get; } - - public abstract IStatsRecorder StatsRecorder { get; } - - public abstract StatsCollectionState State { get; set; } - } -} diff --git a/src/OpenTelemetry/Tags/NoopTagPropagationComponent.cs b/src/OpenTelemetry/Tags/NoopTagPropagationComponent.cs deleted file mode 100644 index 242aedb4b23..00000000000 --- a/src/OpenTelemetry/Tags/NoopTagPropagationComponent.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// 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.Tags -{ - using OpenTelemetry.Tags.Propagation; - - public class NoopTagPropagationComponent : TagPropagationComponentBase - { - internal static readonly ITagPropagationComponent Instance = new NoopTagPropagationComponent(); - - public override ITagContextBinarySerializer BinarySerializer - { - get - { - return NoopTags.NoopTagContextBinarySerializer; - } - } - } -} diff --git a/src/OpenTelemetry/Tags/NoopTags.cs b/src/OpenTelemetry/Tags/NoopTags.cs index ada11f90191..2bdcd1f8d71 100644 --- a/src/OpenTelemetry/Tags/NoopTags.cs +++ b/src/OpenTelemetry/Tags/NoopTags.cs @@ -44,14 +44,6 @@ internal static ITagContext NoopTagContext } } - internal static ITagPropagationComponent NoopTagPropagationComponent - { - get - { - return OpenTelemetry.Tags.NoopTagPropagationComponent.Instance; - } - } - internal static ITagContextBinarySerializer NoopTagContextBinarySerializer { get @@ -59,10 +51,5 @@ internal static ITagContextBinarySerializer NoopTagContextBinarySerializer return OpenTelemetry.Tags.NoopTagContextBinarySerializer.Instance; } } - - internal static ITagsComponent NewNoopTagsComponent() - { - return new NoopTagsComponent(); - } } } diff --git a/src/OpenTelemetry/Tags/NoopTagsComponent.cs b/src/OpenTelemetry/Tags/NoopTagsComponent.cs deleted file mode 100644 index 86d88210e75..00000000000 --- a/src/OpenTelemetry/Tags/NoopTagsComponent.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// 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.Tags -{ - using OpenTelemetry.Tags.Propagation; - - public sealed class NoopTagsComponent : TagsComponentBase - { - // private volatile bool isRead; - public override ITagger Tagger - { - get - { - return NoopTags.NoopTagger; - } - } - - public override ITagPropagationComponent TagPropagationComponent - { - get - { - return NoopTags.NoopTagPropagationComponent; - } - } - - public override TaggingState State - { - get - { - // isRead = true; - return TaggingState.DISABLED; - } - } - } -} diff --git a/src/OpenTelemetry/Tags/Propagation/TagPropagationComponent.cs b/src/OpenTelemetry/Tags/Propagation/TagPropagationComponent.cs deleted file mode 100644 index 3e88a40d87a..00000000000 --- a/src/OpenTelemetry/Tags/Propagation/TagPropagationComponent.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// 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.Tags.Propagation -{ - public sealed class TagPropagationComponent : TagPropagationComponentBase - { - private readonly ITagContextBinarySerializer tagContextBinarySerializer; - - public TagPropagationComponent(CurrentTaggingState state) - { - this.tagContextBinarySerializer = new TagContextBinarySerializer(state); - } - - public override ITagContextBinarySerializer BinarySerializer - { - get { return this.tagContextBinarySerializer; } - } - } -} diff --git a/src/OpenTelemetry/Tags/Tags.cs b/src/OpenTelemetry/Tags/Tags.cs index 4a87acc1781..26e72c07aa6 100644 --- a/src/OpenTelemetry/Tags/Tags.cs +++ b/src/OpenTelemetry/Tags/Tags.cs @@ -24,59 +24,51 @@ public sealed class Tags private static Tags tags; - private readonly ITagsComponent tagsComponent = new TagsComponent(); - - internal Tags(bool enabled) - { - if (enabled) - { - this.tagsComponent = new TagsComponent(); - } - else - { - this.tagsComponent = NoopTags.NewNoopTagsComponent(); - } - } + private readonly CurrentTaggingState state; + private readonly ITagger tagger; + private readonly ITagContextBinarySerializer tagContextBinarySerializer; internal Tags() - : this(false) { + this.state = new CurrentTaggingState(); + this.tagger = new Tagger(this.state); + this.tagContextBinarySerializer = new TagContextBinarySerializer(this.state); } public static ITagger Tagger { get { - Initialize(true); - return tags.tagsComponent.Tagger; + Initialize(); + return tags.tagger; } } - public static ITagPropagationComponent TagPropagationComponent + public static TaggingState State { get { - Initialize(false); - return tags.tagsComponent.TagPropagationComponent; + Initialize(); + return tags.state.Value; } } - public static TaggingState State + public static ITagContextBinarySerializer BinarySerializer { get { - Initialize(false); - return tags.tagsComponent.State; + Initialize(); + return tags.tagContextBinarySerializer; } } - internal static void Initialize(bool enabled) + internal static void Initialize() { if (tags == null) { lock (Lock) { - tags = tags ?? new Tags(enabled); + tags = tags ?? new Tags(); } } } diff --git a/src/OpenTelemetry/Tags/TagsComponent.cs b/src/OpenTelemetry/Tags/TagsComponent.cs deleted file mode 100644 index 37ab8ded368..00000000000 --- a/src/OpenTelemetry/Tags/TagsComponent.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// 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.Tags -{ - using OpenTelemetry.Tags.Propagation; - - public class TagsComponent : TagsComponentBase - { - // The TaggingState shared between the TagsComponent, Tagger, and TagPropagationComponent - private readonly CurrentTaggingState state; - private readonly ITagger tagger; - private readonly ITagPropagationComponent tagPropagationComponent; - - public TagsComponent() - { - this.state = new CurrentTaggingState(); - this.tagger = new Tagger(this.state); - this.tagPropagationComponent = new TagPropagationComponent(this.state); - } - - public override ITagger Tagger - { - get { return this.tagger; } - } - - public override ITagPropagationComponent TagPropagationComponent - { - get { return this.tagPropagationComponent; } - } - - public override TaggingState State - { - get { return this.state.Value; } - } - } -} diff --git a/src/OpenTelemetry/Tags/TagsComponentBase.cs b/src/OpenTelemetry/Tags/TagsComponentBase.cs deleted file mode 100644 index 97a9860a8b5..00000000000 --- a/src/OpenTelemetry/Tags/TagsComponentBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// 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.Tags -{ - using OpenTelemetry.Tags.Propagation; - - public abstract class TagsComponentBase : ITagsComponent - { - public abstract ITagger Tagger { get; } - - public abstract ITagPropagationComponent TagPropagationComponent { get; } - - public abstract TaggingState State { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs b/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs new file mode 100644 index 00000000000..30a834ba164 --- /dev/null +++ b/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs @@ -0,0 +1,58 @@ +// +// 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.Internal +{ + using System; + + internal class RandomGenerator : IRandomGenerator + { + private static readonly Random Global = new Random(); + + [ThreadStatic] + private static Random local; + + private readonly int seed; + private readonly bool sameSeed; + + internal RandomGenerator() + { + this.sameSeed = false; + } + + /// + /// This constructur uses the same seed for all the thread static random objects. + /// You might get the same values if a random is accessed from different threads. + /// Use only for unit tests... + /// + /// Value to seed for . + internal RandomGenerator(int seed) + { + this.sameSeed = true; + this.seed = seed; + } + + public void NextBytes(byte[] bytes) + { + if (local == null) + { + local = new Random(this.sameSeed ? this.seed : Global.Next()); + } + + local.NextBytes(bytes); + } + } +} diff --git a/src/OpenTelemetry/Trace/SpanBuilderOptions.cs b/src/OpenTelemetry/Trace/SpanBuilderOptions.cs index f1ff88707d9..b1acd82c022 100644 --- a/src/OpenTelemetry/Trace/SpanBuilderOptions.cs +++ b/src/OpenTelemetry/Trace/SpanBuilderOptions.cs @@ -20,12 +20,15 @@ namespace OpenTelemetry.Trace internal class SpanBuilderOptions { - internal SpanBuilderOptions(IStartEndHandler startEndHandler, ITraceConfig traceConfig) + internal SpanBuilderOptions(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig) { + this.RandomHandler = randomGenerator; this.StartEndHandler = startEndHandler; this.TraceConfig = traceConfig; } + internal IRandomGenerator RandomHandler { get; } + internal IStartEndHandler StartEndHandler { get; } internal ITraceConfig TraceConfig { get; } diff --git a/src/OpenTelemetry/Trace/TraceComponent.cs b/src/OpenTelemetry/Trace/TraceComponent.cs deleted file mode 100644 index adda5bee61b..00000000000 --- a/src/OpenTelemetry/Trace/TraceComponent.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// 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.Internal; - using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Export; - using OpenTelemetry.Trace.Internal; - - /// - /// Trace component holds all the extensibility points required for distributed tracing. - /// - public sealed class TraceComponent : ITraceComponent - { - /// - /// Initializes a new instance of the class. - /// - public TraceComponent() - : this(new SimpleEventQueue()) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Event queue to use before the exporter. - public TraceComponent(IEventQueue eventQueue) - { - this.TraceConfig = new Config.TraceConfig(); - - // TODO(bdrutu): Add a config/argument for supportInProcessStores. - if (eventQueue is SimpleEventQueue) - { - this.ExportComponent = Export.ExportComponent.CreateWithoutInProcessStores(eventQueue); - } - else - { - this.ExportComponent = Export.ExportComponent.CreateWithInProcessStores(eventQueue); - } - - IStartEndHandler startEndHandler = - new StartEndHandler( - this.ExportComponent.SpanExporter, - ((ExportComponent)this.ExportComponent).RunningSpanStore, - ((ExportComponent)this.ExportComponent).SampledSpanStore, - eventQueue); - this.Tracer = new Tracer(startEndHandler, this.TraceConfig, null); - } - - /// - public ITracer Tracer { get; } - - /// - public IExportComponent ExportComponent { get; } - - /// - public ITraceConfig TraceConfig { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 2e56a94debc..8f707be1819 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -18,29 +18,49 @@ namespace OpenTelemetry.Trace { using System; using System.Threading; + using OpenTelemetry.Common; using OpenTelemetry.Context; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; - using OpenTelemetry.Trace.Internal; /// public sealed class Tracer : ITracer { + private const int ExporterBufferSize = 32; + + // Enforces that trace export exports data at least once every 5 seconds. + private static readonly Duration ExporterScheduleDelay = Duration.Create(5, 0); + private readonly SpanBuilderOptions spanBuilderOptions; - private readonly IExportComponent exportComponent; + private readonly SpanExporter spanExporter; - public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent) - : this(startEndHandler, traceConfig, exportComponent, null, null) + /// + /// Creates an instance of . + /// + /// Span id generator. + /// Start/end event handler. + /// Trace configuration. + public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig) + : this(randomGenerator, startEndHandler, traceConfig, null, null, null) { } - public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExportComponent exportComponent, IBinaryFormat binaryFormat, ITextFormat textFormat) + /// + /// Creates an instance of . + /// + /// Span id generator. + /// Start/end event handler. + /// Trace configuration. + /// Exporter for span. + /// Binary format context propagator. + /// Text format context propagator. + public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig, SpanExporter spanExporter, IBinaryFormat binaryFormat, ITextFormat textFormat) { - this.spanBuilderOptions = new SpanBuilderOptions(startEndHandler, traceConfig); + this.spanBuilderOptions = new SpanBuilderOptions(randomGenerator, startEndHandler, traceConfig); + this.spanExporter = spanExporter ?? (SpanExporter)SpanExporter.Create(ExporterBufferSize, ExporterScheduleDelay); this.BinaryFormat = binaryFormat ?? new BinaryFormat(); this.TextFormat = textFormat ?? new TraceContextFormat(); - this.exportComponent = exportComponent; } /// @@ -53,14 +73,9 @@ public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, IExpor public ITextFormat TextFormat { get; } /// - public IScope WithSpan(ISpan span) + public void RecordSpanData(SpanData span) { - if (span == null) - { - throw new ArgumentNullException(nameof(span)); - } - - return CurrentSpanUtils.WithSpan(span, true); + this.spanExporter.ExportAsync(span, CancellationToken.None); } /// @@ -69,10 +84,14 @@ public ISpanBuilder SpanBuilder(string spanName) return new SpanBuilder(spanName, this.spanBuilderOptions); } - /// - public void RecordSpanData(SpanData span) + public IScope WithSpan(ISpan span) { - this.exportComponent.SpanExporter.ExportAsync(span, CancellationToken.None); + if (span == null) + { + throw new ArgumentNullException(nameof(span)); + } + + return CurrentSpanUtils.WithSpan(span, false); } } } diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index 40d7dadc823..ded0a9bbda2 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -16,38 +16,60 @@ namespace OpenTelemetry.Trace { + using System.Runtime.CompilerServices; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Internal; /// - /// Helper class that provides easy to use static constructor of the default tracer component. + /// Class that manages a global instance of the . /// public sealed class Tracing { - private static readonly Tracing TracingValue = new Tracing(); - - private readonly ITraceComponent traceComponent = null; + private static Tracing tracingValue = new Tracing(); + private static Tracer tracer; internal Tracing() { - this.traceComponent = new TraceComponent(new SimpleEventQueue()); + IRandomGenerator randomHandler = new RandomGenerator(); + IEventQueue eventQueue = new SimpleEventQueue(); + + TraceConfig = new Config.TraceConfig(); + + // TODO(bdrutu): Add a config/argument for supportInProcessStores. + if (eventQueue is SimpleEventQueue) + { + ExportComponent = Export.ExportComponent.CreateWithoutInProcessStores(eventQueue); + } + else + { + ExportComponent = Export.ExportComponent.CreateWithInProcessStores(eventQueue); + } + + IStartEndHandler startEndHandler = + new StartEndHandler( + ExportComponent.SpanExporter, + ((ExportComponent)ExportComponent).RunningSpanStore, + ((ExportComponent)ExportComponent).SampledSpanStore, + eventQueue); + + tracer = new Tracer(randomHandler, startEndHandler, TraceConfig); } - /// + /// /// Gets the tracer to record spans. /// - public static ITracer Tracer => TracingValue.traceComponent.Tracer; + public static ITracer Tracer => (ITracer)tracer; /// - /// Gets the export component to upload spans to. + /// Gets the exporter to use to upload spans. /// - public static IExportComponent ExportComponent => TracingValue.traceComponent.ExportComponent; + public static IExportComponent ExportComponent { get; private set; } /// - /// Gets the tracer configuration. + /// Gets the trace config. /// - public static ITraceConfig TraceConfig => TracingValue.traceComponent.TraceConfig; + public static ITraceConfig TraceConfig { get; private set; } } } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index 2f8b9380315..0fd6f28f430 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -27,10 +27,10 @@ namespace OpenTelemetry.Collector.AspNetCore.Tests using Moq; using Microsoft.AspNetCore.TestHost; using System; - using System.Diagnostics; using OpenTelemetry.Context.Propagation; using Microsoft.AspNetCore.Http; using System.Collections.Generic; + using System.Diagnostics; // See https://github.com/aspnet/Docs/tree/master/aspnetcore/test/integration-tests/samples/2.x/IntegrationTestsSample public class BasicTests @@ -48,7 +48,7 @@ public BasicTests(WebApplicationFactory factory) public async Task SuccesfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); void ConfigureTestServices(IServiceCollection services) => services.AddSingleton(tracer); @@ -104,7 +104,7 @@ public async Task SuccesfulTemplateControllerCallUsesParentContext() Tracestate.Empty )); - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); + var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null, null, tf.Object); // 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 2a8a091e116..ea6ed663c4f 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -55,7 +55,7 @@ public override async Task ProcessAsync(HttpContext context) public async Task SuccesfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); // Arrange using (var client = this.factory diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj b/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj index ac64a261c1b..742ddbe114a 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj @@ -29,7 +29,7 @@ - + diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs index ebb496df0e7..b4e7835f512 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -60,7 +60,7 @@ public async Task HttpDepenenciesCollectorInjectsHeadersAsync() expectedSpanId = sc.SpanId; }); - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); + var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null, null, tf.Object); using (var dc = new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) { diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index 3a01b3aa740..ba62ce4b412 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -99,7 +99,7 @@ public async Task HttpOutCallsAreCollectedSuccesfullyAsync(HttpOutTestCase tc) out var port); var startEndHandler = new Mock(); - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); tc.url = NormaizeValues(tc.url, host, port); using (serverLifeTime) diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs index 2cc7074ee50..e1454b67fdc 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs @@ -30,7 +30,7 @@ public class StackExchangeRedisCallsCollectorTests public async void ProfilerSessionUsesTheSameDefault() { var startEndHandler = new Mock(); - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null); + var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); using (var collector = new StackExchangeRedisCallsCollector(tracer, null, null)) { diff --git a/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs index 1b0ee127264..f5245a7967f 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/NoopStatsTest.cs @@ -30,47 +30,6 @@ public class NoopStatsTest private readonly ITagContext tagContext = new TestTagContext(); - - [Fact] - public void NoopStatsComponent() - { - Assert.Same(NoopStats.NoopStatsRecorder, NoopStats.NewNoopStatsComponent().StatsRecorder); - Assert.Equal(NoopStats.NewNoopViewManager().GetType(), NoopStats.NewNoopStatsComponent().ViewManager.GetType()); - } - - [Fact] - public void NoopStatsComponent_GetState() - { - Assert.Equal(StatsCollectionState.DISABLED, NoopStats.NewNoopStatsComponent().State); - } - - // [Fact] - // public void NoopStatsComponent_SetState_IgnoresInput() - // { - // IStatsComponent noopStatsComponent = NoopStats.NewNoopStatsComponent(); - // noopStatsComponent.State = StatsCollectionState.ENABLED; - // assertThat(noopStatsComponent.getState()).isEqualTo(StatsCollectionState.DISABLED); - // } - - // [Fact] - // public void NoopStatsComponent_SetState_DisallowsNull() - // { - // StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); - // thrown.expect(NullPointerException); - // noopStatsComponent.setState(null); - // } - - // [Fact] - // public void NoopStatsComponent_DisallowsSetStateAfterGetState() - // { - // StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); - // noopStatsComponent.setState(StatsCollectionState.DISABLED); - // noopStatsComponent.getState(); - // thrown.expect(IllegalStateException); - // thrown.expectMessage("State was already read, cannot set state."); - // noopStatsComponent.setState(StatsCollectionState.ENABLED); - // } - // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an // exception. [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs index 8deda0e66f4..f99dac70a44 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/QuickStartExampleTest.cs @@ -36,28 +36,28 @@ public QuickStartExampleTest(ITestOutputHelper output) [Fact] public void Main() { - var statsComponent = new StatsComponent(); - var viewManager = statsComponent.ViewManager; - var statsRecorder = statsComponent.StatsRecorder; - var tagsComponent = new TagsComponent(); - var tagger = tagsComponent.Tagger; + var viewManager = Stats.ViewManager; + var statsRecorder = Stats.StatsRecorder; - var FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); - var FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); - var FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); + var state = new CurrentTaggingState(); + var tagger = new Tagger(state); - var VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); + TagKey FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); + TagKey FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); + TagKey FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); - var VIDEO_SIZE_BY_FRONTEND_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend"); - var VIDEO_SIZE_BY_FRONTEND_VIEW = View.Create( + IMeasureLong VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); + + IViewName VIDEO_SIZE_BY_FRONTEND_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend/main1"); + IView VIDEO_SIZE_BY_FRONTEND_VIEW = View.Create( VIDEO_SIZE_BY_FRONTEND_VIEW_NAME, "processed video size over time", VIDEO_SIZE, Distribution.Create(BucketBoundaries.Create(new List() { 0.0, 256.0, 65536.0 })), new List() { FRONTEND_KEY}); - var VIDEO_SIZE_ALL_VIEW_NAME = ViewName.Create("my.org/views/video_size_all"); - var VIDEO_SIZE_VIEW_ALL = View.Create( + IViewName VIDEO_SIZE_ALL_VIEW_NAME = ViewName.Create("my.org/views/video_size_all"); + IView VIDEO_SIZE_VIEW_ALL = View.Create( VIDEO_SIZE_ALL_VIEW_NAME, "processed video size over time", VIDEO_SIZE, @@ -65,16 +65,16 @@ public void Main() new List() { }); - var VIDEO_SIZE_TOTAL_VIEW_NAME = ViewName.Create("my.org/views/video_size_total"); - var VIDEO_SIZE_TOTAL = View.Create( + IViewName VIDEO_SIZE_TOTAL_VIEW_NAME = ViewName.Create("my.org/views/video_size_total"); + IView VIDEO_SIZE_TOTAL = View.Create( VIDEO_SIZE_TOTAL_VIEW_NAME, "total video size over time", VIDEO_SIZE, Sum.Create(), new List() { FRONTEND_KEY}); - var VIDEOS_PROCESSED_VIEW_NAME = ViewName.Create("my.org/views/videos_processed"); - var VIDEOS_PROCESSED = View.Create( + IViewName VIDEOS_PROCESSED_VIEW_NAME = ViewName.Create("my.org/views/videos_processed"); + IView VIDEOS_PROCESSED = View.Create( VIDEOS_PROCESSED_VIEW_NAME, "total video processed", VIDEO_SIZE, @@ -86,17 +86,17 @@ public void Main() viewManager.RegisterView(VIDEO_SIZE_TOTAL); viewManager.RegisterView(VIDEOS_PROCESSED); - var context1 = tagger + ITagContext context1 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front1")) .Build(); - var context2 = tagger + ITagContext context2 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front2")) .Build(); long sum = 0; - for (var i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { sum = sum + (25648 * i); if (i % 2 == 0) @@ -108,19 +108,19 @@ public void Main() } } - var viewDataByFrontend = viewManager.GetView(VIDEO_SIZE_BY_FRONTEND_VIEW_NAME); + IViewData viewDataByFrontend = viewManager.GetView(VIDEO_SIZE_BY_FRONTEND_VIEW_NAME); var viewDataAggMap = viewDataByFrontend.AggregationMap.ToList(); output.WriteLine(viewDataByFrontend.ToString()); - var viewDataAll = viewManager.GetView(VIDEO_SIZE_ALL_VIEW_NAME); + IViewData viewDataAll = viewManager.GetView(VIDEO_SIZE_ALL_VIEW_NAME); var viewDataAggMapAll = viewDataAll.AggregationMap.ToList(); output.WriteLine(viewDataAll.ToString()); - var viewData1 = viewManager.GetView(VIDEO_SIZE_TOTAL_VIEW_NAME); + IViewData viewData1 = viewManager.GetView(VIDEO_SIZE_TOTAL_VIEW_NAME); var viewData1AggMap = viewData1.AggregationMap.ToList(); output.WriteLine(viewData1.ToString()); - var viewData2 = viewManager.GetView(VIDEOS_PROCESSED_VIEW_NAME); + IViewData viewData2 = viewManager.GetView(VIDEOS_PROCESSED_VIEW_NAME); var viewData2AggMap = viewData2.AggregationMap.ToList(); output.WriteLine(viewData2.ToString()); @@ -130,43 +130,41 @@ public void Main() [Fact] public void Main2() { - var statsComponent = new StatsComponent(); - var viewManager = statsComponent.ViewManager; - var statsRecorder = statsComponent.StatsRecorder; - var tagsComponent = new TagsComponent(); - var tagger = tagsComponent.Tagger; + var viewManager = Stats.ViewManager; + var statsRecorder = Stats.StatsRecorder; + + var state = new CurrentTaggingState(); + var tagger = new Tagger(state); - var FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); - var FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); - var FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); + TagKey FRONTEND_KEY = TagKey.Create("my.org/keys/frontend"); + TagKey FRONTEND_OS_KEY = TagKey.Create("my.org/keys/frontend/os"); + TagKey FRONTEND_OS_VERSION_KEY = TagKey.Create("my.org/keys/frontend/os/version"); - var VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); + IMeasureLong VIDEO_SIZE = MeasureLong.Create("my.org/measure/video_size", "size of processed videos", "MBy"); - var VIDEO_SIZE_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend"); - var VIDEO_SIZE_VIEW = View.Create( + IViewName VIDEO_SIZE_VIEW_NAME = ViewName.Create("my.org/views/video_size_byfrontend/main2"); + IView VIDEO_SIZE_VIEW = View.Create( VIDEO_SIZE_VIEW_NAME, "processed video size over time", VIDEO_SIZE, Distribution.Create(BucketBoundaries.Create(new List() { 0.0, 256.0, 65536.0 })), new List() { FRONTEND_KEY, FRONTEND_OS_KEY, FRONTEND_OS_VERSION_KEY }); - viewManager.RegisterView(VIDEO_SIZE_VIEW); - - var context1 = tagger + ITagContext context1 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front1")) .Put(FRONTEND_OS_KEY, TagValue.Create("windows")) .Build(); - var context2 = tagger + ITagContext context2 = tagger .EmptyBuilder .Put(FRONTEND_KEY, TagValue.Create("front2")) .Put(FRONTEND_OS_VERSION_KEY, TagValue.Create("1.1.1")) .Build(); long sum = 0; - for (var i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { sum = sum + (25648 * i); if (i % 2 == 0) @@ -179,10 +177,10 @@ public void Main2() } } - var videoSizeView = viewManager.GetView(VIDEO_SIZE_VIEW_NAME); + IViewData videoSizeView = viewManager.GetView(VIDEO_SIZE_VIEW_NAME); var viewDataAggMap = videoSizeView.AggregationMap.ToList(); var view = viewManager.AllExportedViews.ToList()[0]; - for (var i = 0; i < view.Columns.Count; i++) + for (int i = 0; i < view.Columns.Count; i++) { output.WriteLine(view.Columns[i] + "=" + GetTagValues(i, viewDataAggMap)); } @@ -208,7 +206,7 @@ public void Main2() private string GetTagValues(int i, List> viewDataAggMap) { - var result = string.Empty; + string result = string.Empty; foreach (var kvp in viewDataAggMap) { var val = kvp.Key.Values[i]; diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsComponentTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsComponentTest.cs deleted file mode 100644 index 521a6ac421b..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsComponentTest.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// 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.Stats.Test -{ - using OpenTelemetry.Internal; - using Xunit; - - public class StatsComponentTest - { - private readonly StatsComponent statsComponent = new StatsComponent(new SimpleEventQueue()); - - [Fact] - public void DefaultState() - { - Assert.Equal(StatsCollectionState.ENABLED, statsComponent.State); - } - - // [Fact] - // public void setState_Disabled() - // { - // statsComponent.setState(StatsCollectionState.DISABLED); - // assertThat(statsComponent.getState()).isEqualTo(StatsCollectionState.DISABLED); - // } - - // [Fact] - // public void setState_Enabled() - // { - // statsComponent.setState(StatsCollectionState.DISABLED); - // statsComponent.setState(StatsCollectionState.ENABLED); - // assertThat(statsComponent.getState()).isEqualTo(StatsCollectionState.ENABLED); - // } - - // [Fact] - // public void setState_DisallowsNull() - // { - // thrown.expect(NullPointerException); - // thrown.expectMessage("newState"); - // statsComponent.setState(null); - // } - - // [Fact] - // public void preventSettingStateAfterGettingState() - // { - // statsComponent.setState(StatsCollectionState.DISABLED); - // statsComponent.getState(); - // thrown.expect(IllegalStateException); - // thrown.expectMessage("State was already read, cannot set state."); - // statsComponent.setState(StatsCollectionState.ENABLED); - // } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs index 9eb776f3eaa..f7157f23b00 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/StatsRecorderTest.cs @@ -17,13 +17,14 @@ namespace OpenTelemetry.Stats.Test { using System; + using System.Linq; using System.Collections.Generic; - using OpenTelemetry.Internal; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; using OpenTelemetry.Tags.Unsafe; using Xunit; + using System.Collections; public class StatsRecorderTest { @@ -34,43 +35,50 @@ public class StatsRecorderTest private static readonly IMeasureDouble MEASURE_DOUBLE_NO_VIEW_1 = MeasureDouble.Create("my measurement no view 1", "description", "us"); private static readonly IMeasureDouble MEASURE_DOUBLE_NO_VIEW_2 = MeasureDouble.Create("my measurement no view 2", "description", "us"); private static readonly IViewName VIEW_NAME = ViewName.Create("my view"); + private static readonly int RANDOM_NAME_LEN = 8; - private readonly StatsComponent statsComponent; - private readonly IViewManager viewManager; - private readonly IStatsRecorder statsRecorder; + private static readonly IViewManager viewManager = Stats.ViewManager; + private static readonly IStatsRecorder statsRecorder = Stats.StatsRecorder; public StatsRecorderTest() { - statsComponent = new StatsComponent(new SimpleEventQueue()); - viewManager = statsComponent.ViewManager; - statsRecorder = statsComponent.StatsRecorder; } [Fact] public void Record_CurrentContextNotSet() { - var view = + Stats.State = StatsCollectionState.ENABLED; + + IViewName viewName = CreateRandomViewName(); + + IView view = View.Create( - VIEW_NAME, + viewName, "description", MEASURE_DOUBLE, Sum.Create(), new List() { KEY }); viewManager.RegisterView(view); statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 1.0).Record(); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(viewName); // record() should have used the default TagContext, so the tag value should be null. ICollection expected = new List() { TagValues.Create(new List() { null }) }; - Assert.Equal(expected, viewData.AggregationMap.Keys); + ICollection actual = viewData.AggregationMap.Keys.ToList(); + + Assert.Equal(expected, actual); } [Fact] public void Record_CurrentContextSet() { - var view = + Stats.State = StatsCollectionState.ENABLED; + + IViewName viewName = CreateRandomViewName(); + + IView view = View.Create( - VIEW_NAME, + viewName, "description", MEASURE_DOUBLE, Sum.Create(), @@ -87,19 +95,25 @@ public void Record_CurrentContextSet() { AsyncLocalContext.CurrentTagContext = orig; } - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(viewName); // record() should have used the given TagContext. ICollection expected = new List() { TagValues.Create(new List() { VALUE }) }; - Assert.Equal(expected, viewData.AggregationMap.Keys); + ICollection actual = viewData.AggregationMap.Keys.ToList(); + + Assert.Equal(expected, actual); } [Fact] public void Record_UnregisteredMeasure() { - var view = + Stats.State = StatsCollectionState.ENABLED; + + IViewName viewName = CreateRandomViewName(); + + IView view = View.Create( - VIEW_NAME, + viewName, "description", MEASURE_DOUBLE, Sum.Create(), @@ -112,7 +126,7 @@ public void Record_UnregisteredMeasure() .Put(MEASURE_DOUBLE_NO_VIEW_2, 3.0) .Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(viewName); // There should be one entry. var tv = TagValues.Create(new List() { VALUE }); @@ -125,19 +139,23 @@ public void Record_UnregisteredMeasure() [Fact] public void RecordTwice() { - var view = + Stats.State = StatsCollectionState.ENABLED; + + IViewName viewName = CreateRandomViewName(); + + IView view = View.Create( - VIEW_NAME, + viewName, "description", MEASURE_DOUBLE, Sum.Create(), new List() { KEY }); viewManager.RegisterView(view); - var statsRecord = statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 1.0); + IMeasureMap statsRecord = statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 1.0); statsRecord.Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); statsRecord.Record(new SimpleTagContext(Tag.Create(KEY, VALUE_2))); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(viewName); // There should be two entries. var tv = TagValues.Create(new List() { VALUE }); @@ -156,7 +174,7 @@ public void RecordTwice() [Fact] public void Record_StatsDisabled() { - var view = + IView view = View.Create( VIEW_NAME, "description", @@ -165,7 +183,7 @@ public void Record_StatsDisabled() new List() { KEY }); viewManager.RegisterView(view); - statsComponent.State = StatsCollectionState.DISABLED; + Stats.State = StatsCollectionState.DISABLED; statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.0) @@ -176,7 +194,7 @@ public void Record_StatsDisabled() [Fact] public void Record_StatsReenabled() { - var view = + IView view = View.Create( VIEW_NAME, "description", @@ -186,14 +204,14 @@ public void Record_StatsReenabled() viewManager.RegisterView(view); - statsComponent.State = StatsCollectionState.DISABLED; + Stats.State = StatsCollectionState.DISABLED; statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.0) .Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); Assert.Equal(CreateEmptyViewData(view), viewManager.GetView(VIEW_NAME)); - statsComponent.State = StatsCollectionState.ENABLED; + Stats.State = StatsCollectionState.ENABLED; Assert.Empty(viewManager.GetView(VIEW_NAME).AggregationMap); // assertThat(viewManager.getView(VIEW_NAME).getWindowData()) // .isNotEqualTo(CumulativeData.Create(ZERO_TIMESTAMP, ZERO_TIMESTAMP)); @@ -201,7 +219,7 @@ public void Record_StatsReenabled() .NewMeasureMap() .Put(MEASURE_DOUBLE, 4.0) .Record(new SimpleTagContext(Tag.Create(KEY, VALUE))); - var tv = TagValues.Create(new List() { VALUE }); + TagValues tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(VIEW_NAME).AggregationMap, new Dictionary() @@ -220,6 +238,19 @@ static IViewData CreateEmptyViewData(IView view) DateTimeOffset.MinValue, DateTimeOffset.MinValue); } + private static Random random = new Random(); + public static string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + + private static IViewName CreateRandomViewName() + { + return ViewName.Create(RandomString(RANDOM_NAME_LEN)); + } + class SimpleTagContext : TagContextBase { private readonly IEnumerable tags; @@ -235,4 +266,4 @@ public override IEnumerator GetEnumerator() } } } -} \ No newline at end of file +} diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs index fbdb3fff915..32e6ed0197e 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs @@ -52,12 +52,23 @@ internal static void AssertAggregationMapEquals( double tolerance) { Assert.Equal(expected.Count, actual.Count); - Assert.Equal(expected.Keys, actual.Keys); - foreach (var tagValues in actual.Keys) + // Check actual/expected tags match indpendent of order + foreach (var tagValue in actual.Keys) { - var act = actual[tagValues]; - var exp = expected[tagValues]; + Assert.True(expected.Keys.Contains(tagValue)); + } + + foreach (var tagValue in actual.Keys) + { + Assert.True(expected.Keys.Contains(tagValue)); + } + + // Confirm data for tagsValues matches + foreach (var tagValue in actual.Keys) + { + var act = actual[tagValue]; + var exp = expected[tagValue]; AssertAggregationDataEquals(exp, act, tolerance); } } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs index cb186efdcb1..34463ded65a 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs @@ -20,7 +20,6 @@ namespace OpenTelemetry.Stats.Test using System.Collections.Generic; using System.Linq; using OpenTelemetry.Common; - using OpenTelemetry.Internal; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; @@ -35,17 +34,18 @@ public class ViewManagerTest private static readonly String MEASURE_NAME_2 = "my measurement 2"; private static readonly String MEASURE_UNIT = "us"; private static readonly String MEASURE_DESCRIPTION = "measure description"; - private static readonly IMeasureDouble MEASURE_DOUBLE = MeasureDouble.Create(MEASURE_NAME, MEASURE_DESCRIPTION, MEASURE_UNIT); - private static readonly IMeasureLong MEASURE_LONG = MeasureLong.Create(MEASURE_NAME_2, MEASURE_DESCRIPTION, MEASURE_UNIT); + private static readonly IMeasureDouble MEASURE_DOUBLE = CreateRandomMeasureDouble(); + private static readonly IMeasureLong MEASURE_LONG = MeasureLong.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT); - private static readonly IViewName VIEW_NAME = ViewName.Create("my view"); - private static readonly IViewName VIEW_NAME_2 = ViewName.Create("my view 2"); + //private static readonly IViewName VIEW_NAME = ViewName.Create("my view"); + //private static readonly IViewName VIEW_NAME_2 = ViewName.Create("my view 2"); private static readonly String VIEW_DESCRIPTION = "view description"; // private static readonly Cumulative CUMULATIVE = Cumulative.Create(); private static readonly double EPSILON = 1e-7; + private static readonly int RANDOM_NAME_LEN = 8; private static readonly Duration TEN_SECONDS = Duration.Create(10, 0); // private static readonly Interval INTERVAL = Interval.Create(TEN_SECONDS); @@ -59,26 +59,19 @@ public class ViewManagerTest private static readonly IDistribution DISTRIBUTION = Distribution.Create(BUCKET_BOUNDARIES); private static readonly ILastValue LAST_VALUE = LastValue.Create(); - private readonly StatsComponent statsComponent; - private readonly TagsComponent tagsComponent; - + private static readonly IViewManager viewManager = Stats.ViewManager; + private static readonly IStatsRecorder statsRecorder = Stats.StatsRecorder; + private static readonly CurrentTaggingState state = new CurrentTaggingState(); private readonly ITagger tagger; - private readonly IViewManager viewManager; - private readonly IStatsRecorder statsRecorder; public ViewManagerTest() { - statsComponent = new StatsComponent(new SimpleEventQueue()); - tagsComponent = new TagsComponent(); - - tagger = tagsComponent.Tagger; - viewManager = statsComponent.ViewManager; - statsRecorder = statsComponent.StatsRecorder; + tagger = new Tagger(state); } private static IView CreateCumulativeView() { - return CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + return CreateCumulativeView(CreateRandomViewName(), CreateRandomMeasureDouble(), DISTRIBUTION, new List() { KEY }); } private static IView CreateCumulativeView( @@ -90,28 +83,33 @@ private static IView CreateCumulativeView( [Fact] public void TestRegisterAndGetCumulativeView() { - var view = CreateCumulativeView(); + IView view = CreateCumulativeView(); viewManager.RegisterView(view); - Assert.Equal(view, viewManager.GetView(VIEW_NAME).View); - Assert.Empty(viewManager.GetView(VIEW_NAME).AggregationMap); - // Assert.Equal(viewManager.GetView(VIEW_NAME).getWindowData()).isInstanceOf(CumulativeData); + Assert.Equal(view, viewManager.GetView(view.Name).View); + Assert.Empty(viewManager.GetView(view.Name).AggregationMap); + // Assert.Equal(viewManager.GetView(view.Name).getWindowData()).isInstanceOf(CumulativeData); } [Fact] public void TestGetAllExportedViews() { - Assert.Empty(viewManager.AllExportedViews); - var cumulativeView1 = + //Assert.Empty(viewManager.AllExportedViews); + + IViewName viewName1 = CreateRandomViewName(); + IViewName viewName2 = CreateRandomViewName(); + IMeasureDouble measure = CreateRandomMeasureDouble(); + + IView cumulativeView1 = CreateCumulativeView( - ViewName.Create("View 1"), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - var cumulativeView2 = + viewName1, measure, DISTRIBUTION, new List() { KEY }); + IView cumulativeView2 = CreateCumulativeView( - ViewName.Create("View 2"), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + viewName2, measure, DISTRIBUTION, new List() { KEY }); // View intervalView = // View.Create( // View.Name.Create("View 3"), // VIEW_DESCRIPTION, - // MEASURE_DOUBLE, + // measure, // DISTRIBUTION, // Arrays.asList(KEY), // INTERVAL); @@ -121,31 +119,34 @@ public void TestGetAllExportedViews() // Only cumulative views should be exported. Assert.Contains(cumulativeView1, viewManager.AllExportedViews); Assert.Contains(cumulativeView2, viewManager.AllExportedViews); - Assert.Equal(2, viewManager.AllExportedViews.Count); + //Assert.Equal(2, viewManager.AllExportedViews.Count); } [Fact] public void GetAllExportedViewsResultIsUnmodifiable() { - var view1 = + IViewName viewName1 = CreateRandomViewName(); + IViewName viewName2 = CreateRandomViewName(); + IMeasureDouble measure = CreateRandomMeasureDouble(); + + IView view1 = View.Create( - ViewName.Create("View 1"), + viewName1, VIEW_DESCRIPTION, - MEASURE_DOUBLE, + measure, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view1); - var exported = viewManager.AllExportedViews; + ISet exported = viewManager.AllExportedViews; - var view2 = + IView view2 = View.Create( - ViewName.Create("View 2"), + viewName2, VIEW_DESCRIPTION, - MEASURE_DOUBLE, + measure, DISTRIBUTION, new List() { KEY }); Assert.Throws(() => exported.Add(view2)); - } // [Fact] @@ -168,27 +169,30 @@ public void GetAllExportedViewsResultIsUnmodifiable() [Fact] public void AllowRegisteringSameViewTwice() { - var view = CreateCumulativeView(); + IView view = CreateCumulativeView(); viewManager.RegisterView(view); viewManager.RegisterView(view); - Assert.Equal(view, viewManager.GetView(VIEW_NAME).View); + Assert.Equal(view, viewManager.GetView(view.Name).View); } [Fact] public void PreventRegisteringDifferentViewWithSameName() { - var view1 = + IViewName viewName = CreateRandomViewName(); + IMeasureDouble measure = CreateRandomMeasureDouble(); + + IView view1 = View.Create( - VIEW_NAME, + viewName, "View description.", - MEASURE_DOUBLE, + measure, DISTRIBUTION, new List() { KEY }); - var view2 = + IView view2 = View.Create( - VIEW_NAME, + viewName, "This is a different description.", - MEASURE_DOUBLE, + measure, DISTRIBUTION, new List() { KEY }); TestFailedToRegisterView(view1, view2, "A different view with the same name is already registered"); @@ -197,14 +201,18 @@ public void PreventRegisteringDifferentViewWithSameName() [Fact] public void PreventRegisteringDifferentMeasureWithSameName() { - var measure1 = MeasureDouble.Create("measure", "description", "1"); - var measure2 = MeasureLong.Create("measure", "description", "1"); - var view1 = + IMeasureDouble measure1 = MeasureDouble.Create("measure", "description", "1"); + IMeasureLong measure2 = MeasureLong.Create("measure", "description", "1"); + + IViewName viewName1 = CreateRandomViewName(); + IViewName viewName2 = CreateRandomViewName(); + + IView view1 = + View.Create( + viewName1, VIEW_DESCRIPTION, measure1, DISTRIBUTION, new List() { KEY }); + IView view2 = View.Create( - VIEW_NAME, VIEW_DESCRIPTION, measure1, DISTRIBUTION, new List() { KEY }); - var view2 = - View.Create( - VIEW_NAME_2, VIEW_DESCRIPTION, measure2, DISTRIBUTION, new List() { KEY }); + viewName2, VIEW_DESCRIPTION, measure2, DISTRIBUTION, new List() { KEY }); TestFailedToRegisterView(view1, view2, "A different measure with the same name is already registered"); } @@ -215,62 +223,62 @@ private void TestFailedToRegisterView(IView view1, IView view2, String message) { Assert.Throws(() => viewManager.RegisterView(view2)); } finally { - Assert.Equal(view1, viewManager.GetView(VIEW_NAME).View); + Assert.Equal(view1, viewManager.GetView(view1.Name).View); } } [Fact] public void ReturnNullWhenGettingNonexistentViewData() { - Assert.Null(viewManager.GetView(VIEW_NAME)); + Assert.Null(viewManager.GetView(CreateRandomViewName())); } [Fact] public void TestRecordDouble_Distribution_Cumulative() { - TestRecordCumulative(MEASURE_DOUBLE, DISTRIBUTION, 10.0, 20.0, 30.0, 40.0); + TestRecordCumulative(CreateRandomMeasureDouble(), DISTRIBUTION, 10.0, 20.0, 30.0, 40.0); } [Fact] public void TestRecordLong_Distribution_Cumulative() { - TestRecordCumulative(MEASURE_LONG, DISTRIBUTION, 1000, 2000, 3000, 4000); + TestRecordCumulative(CreateRandomMeasureLong(), DISTRIBUTION, 1000, 2000, 3000, 4000); } [Fact] public void TestRecordDouble_Sum_Cumulative() { - TestRecordCumulative(MEASURE_DOUBLE, SUM, 11.1, 22.2, 33.3, 44.4); + TestRecordCumulative(CreateRandomMeasureDouble(), SUM, 11.1, 22.2, 33.3, 44.4); } [Fact] public void TestRecordLong_Sum_Cumulative() { - TestRecordCumulative(MEASURE_LONG, SUM, 1000, 2000, 3000, 4000); + TestRecordCumulative(CreateRandomMeasureLong(), SUM, 1000, 2000, 3000, 4000); } [Fact] public void TestRecordDouble_Lastvalue_Cumulative() { - TestRecordCumulative(MEASURE_DOUBLE, LAST_VALUE, 11.1, 22.2, 33.3, 44.4); + TestRecordCumulative(CreateRandomMeasureDouble(), LAST_VALUE, 11.1, 22.2, 33.3, 44.4); } [Fact] public void TestRecordLong_Lastvalue_Cumulative() { - TestRecordCumulative(MEASURE_LONG, LAST_VALUE, 1000, 2000, 3000, 4000); + TestRecordCumulative(CreateRandomMeasureLong(), LAST_VALUE, 1000, 2000, 3000, 4000); } private void TestRecordCumulative(IMeasure measure, IAggregation aggregation, params double[] values) { - var view = CreateCumulativeView(VIEW_NAME, measure, aggregation, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), measure, aggregation, new List() { KEY }); viewManager.RegisterView(view); - var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); - foreach (var val in values) + ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + foreach (double val in values) { PutToMeasureMap(statsRecorder.NewMeasureMap(), measure, val).Record(tags); } - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); Assert.Equal(view, viewData.View); var tv = TagValues.Create(new List() { VALUE }); @@ -287,11 +295,11 @@ private void TestRecordCumulative(IMeasure measure, IAggregation aggregation, pa [Fact] public void GetViewDoesNotClearStats() { - var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view); - var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 0.1).Record(tags); - var viewData1 = viewManager.GetView(VIEW_NAME); + IViewData viewData1 = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, @@ -302,7 +310,7 @@ public void GetViewDoesNotClearStats() EPSILON); statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 0.2).Record(tags); - var viewData2 = viewManager.GetView(VIEW_NAME); + IViewData viewData2 = viewManager.GetView(view.Name); // The second view should have the same start time as the first view, and it should include both // Recorded values: @@ -319,8 +327,8 @@ public void GetViewDoesNotClearStats() [Fact] public void TestRecordCumulativeMultipleTagValues() { - viewManager.RegisterView( - CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY })); + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 10.0) @@ -333,15 +341,15 @@ public void TestRecordCumulativeMultipleTagValues() .NewMeasureMap() .Put(MEASURE_DOUBLE, 50.0) .Record(tagger.EmptyBuilder.Put(KEY, VALUE_2).Build()); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { VALUE }); var tv2 = TagValues.Create(new List() { VALUE_2 }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, new Dictionary() { - { tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0)}, - { tv2, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 30.0, 50.0)}, + { tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0)}, + { tv2, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 30.0, 50.0)}, }, EPSILON); } @@ -361,11 +369,13 @@ public void AllowRecordingWithoutRegisteringMatchingViewData() [Fact] public void TestRecordWithEmptyStatsContext() { - viewManager.RegisterView( - CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY })); + Stats.State = StatsCollectionState.ENABLED; + + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + viewManager.RegisterView(view); // DEFAULT doesn't have tags, but the view has tag key "KEY". statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 10.0).Record(tagger.Empty); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { MutableViewData.UnknownTagValue }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -386,34 +396,38 @@ public void TestRecordWithEmptyStatsContext() public void TestRecord_MeasureNameNotMatch() { TestRecord_MeasureNotMatch( - MeasureDouble.Create(MEASURE_NAME, "measure", MEASURE_UNIT), - MeasureDouble.Create(MEASURE_NAME_2, "measure", MEASURE_UNIT), + MeasureDouble.Create(CreateRandomMeasureName(), "measure", MEASURE_UNIT), + MeasureDouble.Create(CreateRandomMeasureName(), "measure", MEASURE_UNIT), 10.0); } [Fact] public void TestRecord_MeasureTypeNotMatch() { + string name = CreateRandomMeasureName(); TestRecord_MeasureNotMatch( - MeasureLong.Create(MEASURE_NAME, "measure", MEASURE_UNIT), - MeasureDouble.Create(MEASURE_NAME, "measure", MEASURE_UNIT), + MeasureLong.Create(name, "measure", MEASURE_UNIT), + MeasureDouble.Create(name, "measure", MEASURE_UNIT), 10.0); } private void TestRecord_MeasureNotMatch(IMeasure measure1, IMeasure measure2, double value) { - viewManager.RegisterView(CreateCumulativeView(VIEW_NAME, measure1, MEAN, new List() { KEY })); - var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + IView view = CreateCumulativeView(CreateRandomViewName(), measure1, MEAN, new List() { KEY }); + viewManager.RegisterView(view); + ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); PutToMeasureMap(statsRecorder.NewMeasureMap(), measure2, value).Record(tags); - var view = viewManager.GetView(VIEW_NAME); - Assert.Empty(view.AggregationMap); + IViewData viewData = viewManager.GetView(view.Name); + Assert.Empty(viewData.AggregationMap); } [Fact] public void TestRecordWithTagsThatDoNotMatchViewData() { - viewManager.RegisterView( - CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY })); + Stats.State = StatsCollectionState.ENABLED; + + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 10.0) @@ -422,7 +436,7 @@ public void TestRecordWithTagsThatDoNotMatchViewData() .NewMeasureMap() .Put(MEASURE_DOUBLE, 50.0) .Record(tagger.EmptyBuilder.Put(TagKey.Create("another wrong key"), VALUE).Build()); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { MutableViewData.UnknownTagValue }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -430,10 +444,9 @@ public void TestRecordWithTagsThatDoNotMatchViewData() { // Won't Record the unregistered tag key, for missing registered keys will use default // tag value : "unknown/not set". - { - tv, - // Should Record stats with default tag value: "KEY" : "unknown/not set". - StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0, 50.0) + { tv, + // Should Record stats with default tag value: "KEY" : "unknown/not set". + StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0, 50.0) }, }, EPSILON); @@ -442,10 +455,10 @@ public void TestRecordWithTagsThatDoNotMatchViewData() [Fact] public void TestViewDataWithMultipleTagKeys() { - var key1 = TagKey.Create("Key-1"); - var key2 = TagKey.Create("Key-2"); - viewManager.RegisterView( - CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { key1, key2 })); + TagKey key1 = TagKey.Create("Key-1"); + TagKey key2 = TagKey.Create("Key-2"); + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { key1, key2 }); + viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) @@ -482,7 +495,7 @@ public void TestViewDataWithMultipleTagKeys() .Put(key1, TagValue.Create("v1")) .Put(key2, TagValue.Create("v10")) .Build()); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); var tv1 = TagValues.Create(new List() { TagValue.Create("v1"), TagValue.Create("v10") }); var tv2 = TagValues.Create(new List() { TagValue.Create("v1"), TagValue.Create("v20") }); var tv3 = TagValues.Create(new List() { TagValue.Create("v2"), TagValue.Create("v10") }); @@ -500,18 +513,18 @@ public void TestViewDataWithMultipleTagKeys() [Fact] public void TestMultipleViewSameMeasure() { - var view1 = - CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - var view2 = - CreateCumulativeView(VIEW_NAME_2, MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view1 = + CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view2 = + CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view1); viewManager.RegisterView(view2); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 5.0) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - var viewData1 = viewManager.GetView(VIEW_NAME); - var viewData2 = viewManager.GetView(VIEW_NAME_2); + IViewData viewData1 = viewManager.GetView(view1.Name); + IViewData viewData2 = viewManager.GetView(view2.Name); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, @@ -534,8 +547,8 @@ public void TestMultipleViewSameMeasure() public void TestMultipleViews_DifferentMeasureNames() { TestMultipleViews_DifferentMeasures( - MeasureDouble.Create(MEASURE_NAME, MEASURE_DESCRIPTION, MEASURE_UNIT), - MeasureDouble.Create(MEASURE_NAME_2, MEASURE_DESCRIPTION, MEASURE_UNIT), + MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), + MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), 1.1, 2.2); } @@ -544,26 +557,25 @@ public void TestMultipleViews_DifferentMeasureNames() public void TestMultipleViews_DifferentMeasureTypes() { TestMultipleViews_DifferentMeasures( - MeasureDouble.Create(MEASURE_NAME, MEASURE_DESCRIPTION, MEASURE_UNIT), - MeasureLong.Create(MEASURE_NAME_2, MEASURE_DESCRIPTION, MEASURE_UNIT), + MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), + MeasureLong.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), 1.1, 5000); } private void TestMultipleViews_DifferentMeasures(IMeasure measure1, IMeasure measure2, double value1, double value2) { - var view1 = CreateCumulativeView(VIEW_NAME, measure1, DISTRIBUTION, new List() { KEY }); - var view2 = - CreateCumulativeView(VIEW_NAME_2, measure2, DISTRIBUTION, new List() { KEY }); + IView view1 = CreateCumulativeView(CreateRandomViewName(), measure1, DISTRIBUTION, new List() { KEY }); + IView view2 = CreateCumulativeView(CreateRandomViewName(), measure2, DISTRIBUTION, new List() { KEY }); viewManager.RegisterView(view1); viewManager.RegisterView(view2); - var tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); - var measureMap = statsRecorder.NewMeasureMap(); + ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + IMeasureMap measureMap = statsRecorder.NewMeasureMap(); PutToMeasureMap(measureMap, measure1, value1); PutToMeasureMap(measureMap, measure2, value2); measureMap.Record(tags); - var viewData1 = viewManager.GetView(VIEW_NAME); - var viewData2 = viewManager.GetView(VIEW_NAME_2); + IViewData viewData1 = viewManager.GetView(view1.Name); + IViewData viewData2 = viewManager.GetView(view2.Name); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, @@ -587,13 +599,13 @@ public void TestGetCumulativeViewDataWithEmptyBucketBoundaries() { IAggregation noHistogram = Distribution.Create(BucketBoundaries.Create(Enumerable.Empty())); - var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, noHistogram, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, noHistogram, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -607,13 +619,13 @@ public void TestGetCumulativeViewDataWithEmptyBucketBoundaries() [Fact] public void TestGetCumulativeViewDataWithoutBucketBoundaries() { - var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - var viewData = viewManager.GetView(VIEW_NAME); + IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, @@ -627,30 +639,30 @@ public void TestGetCumulativeViewDataWithoutBucketBoundaries() [Fact] public void RegisterRecordAndGetView_StatsDisabled() { - statsComponent.State = StatsCollectionState.DISABLED; - var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + Stats.State = StatsCollectionState.DISABLED; + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - Assert.Equal(StatsTestUtil.CreateEmptyViewData(view), viewManager.GetView(VIEW_NAME)); + Assert.Equal(StatsTestUtil.CreateEmptyViewData(view), viewManager.GetView(view.Name)); } [Fact] public void RegisterRecordAndGetView_StatsReenabled() { - statsComponent.State = StatsCollectionState.DISABLED; - statsComponent.State = StatsCollectionState.ENABLED; - var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + Stats.State = StatsCollectionState.DISABLED; + Stats.State = StatsCollectionState.ENABLED; + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - var tv = TagValues.Create(new List() { VALUE }); + TagValues tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( - viewManager.GetView(VIEW_NAME).AggregationMap, + viewManager.GetView(view.Name).AggregationMap, new Dictionary() { { tv, StatsTestUtil.CreateAggregationData(MEAN, MEASURE_DOUBLE, 1.1) }, @@ -661,18 +673,18 @@ public void RegisterRecordAndGetView_StatsReenabled() [Fact] public void RegisterViewWithStatsDisabled_RecordAndGetViewWithStatsEnabled() { - statsComponent.State = StatsCollectionState.DISABLED; - var view = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + Stats.State = StatsCollectionState.DISABLED; + IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); viewManager.RegisterView(view); // view will still be registered. - statsComponent.State = StatsCollectionState.ENABLED; + Stats.State = StatsCollectionState.ENABLED; statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - var tv = TagValues.Create(new List() { VALUE }); + TagValues tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( - viewManager.GetView(VIEW_NAME).AggregationMap, + viewManager.GetView(view.Name).AggregationMap, new Dictionary() { { tv, StatsTestUtil.CreateAggregationData(MEAN, MEASURE_DOUBLE, 1.1) }, @@ -683,17 +695,18 @@ public void RegisterViewWithStatsDisabled_RecordAndGetViewWithStatsEnabled() [Fact] public void RegisterDifferentViewWithSameNameWithStatsDisabled() { - statsComponent.State = StatsCollectionState.DISABLED; - var view1 = + Stats.State = StatsCollectionState.DISABLED; + IViewName viewName = CreateRandomViewName(); + IView view1 = View.Create( - VIEW_NAME, + viewName, "View description.", MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); - var view2 = + IView view2 = View.Create( - VIEW_NAME, + viewName, "This is a different description.", MEASURE_DOUBLE, DISTRIBUTION, @@ -706,7 +719,7 @@ public void RegisterDifferentViewWithSameNameWithStatsDisabled() [Fact] public void SettingStateToDisabledWillClearStats_Cumulative() { - var cumulativeView = CreateCumulativeView(VIEW_NAME, MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView cumulativeView = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); SettingStateToDisabledWillClearStats(cumulativeView); } @@ -727,14 +740,14 @@ public void SettingStateToDisabledWillClearStats_Cumulative() private void SettingStateToDisabledWillClearStats(IView view) { // TODO: deal with timestamp validation - var timestamp1 = Timestamp.Create(1, 0); + Timestamp timestamp1 = Timestamp.Create(1, 0); //clock.Time = timestamp1; viewManager.RegisterView(view); statsRecorder .NewMeasureMap() .Put(MEASURE_DOUBLE, 1.1) .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - var tv = TagValues.Create(new List() { VALUE }); + TagValues tv = TagValues.Create(new List() { VALUE }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(view.Name).AggregationMap, new Dictionary() @@ -743,20 +756,20 @@ private void SettingStateToDisabledWillClearStats(IView view) }, EPSILON); - var timestamp2 = Timestamp.Create(2, 0); + Timestamp timestamp2 = Timestamp.Create(2, 0); //clock.Time = timestamp2; - statsComponent.State = StatsCollectionState.DISABLED; // This will clear stats. + Stats.State = StatsCollectionState.DISABLED; // This will clear stats. Assert.Equal(StatsTestUtil.CreateEmptyViewData(view), viewManager.GetView(view.Name)); - var timestamp3 = Timestamp.Create(3, 0); + Timestamp timestamp3 = Timestamp.Create(3, 0); //clock.Time = timestamp3; - statsComponent.State = StatsCollectionState.ENABLED; + Stats.State = StatsCollectionState.ENABLED; - var timestamp4 = Timestamp.Create(4, 0); + Timestamp timestamp4 = Timestamp.Create(4, 0); //clock.Time = timestamp4; // This ViewData does not have any stats, but it should not be an empty ViewData, since it has // non-zero TimeStamps. - var viewData = viewManager.GetView(view.Name); + IViewData viewData = viewManager.GetView(view.Name); Assert.Empty(viewData.AggregationMap); //Assert.Equal(timestamp3, viewData.Start); //Assert.Equal(timestamp4, viewData.End); @@ -778,6 +791,33 @@ private static IMeasureMap PutToMeasureMap(IMeasureMap measureMap, IMeasure meas throw new Exception(); } } - } + private static Random random = new Random(); + public static string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + + private static IViewName CreateRandomViewName() + { + return ViewName.Create(RandomString(RANDOM_NAME_LEN)); + } + + private static string CreateRandomMeasureName() + { + return RandomString(RANDOM_NAME_LEN); + } + + private static IMeasureDouble CreateRandomMeasureDouble() + { + return MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT); + } + + private static IMeasureLong CreateRandomMeasureLong() + { + return MeasureLong.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT); + } + } } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs index ccd3391fdd6..0883ae74111 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/NoopTagsTest.cs @@ -31,15 +31,6 @@ public class NoopTagsTest private static readonly TagValue VALUE = TagValue.Create("value"); private static readonly ITagContext TAG_CONTEXT = new TestTagContext(); - - - - [Fact] - public void NoopTagsComponent() - { - Assert.Same(NoopTags.NoopTagger, NoopTags.NewNoopTagsComponent().Tagger); - Assert.Equal(NoopTags.NoopTagPropagationComponent, NoopTags.NewNoopTagsComponent().TagPropagationComponent); - } [Fact] public void NoopTagger() @@ -103,12 +94,6 @@ public void NoopTagContext() Assert.Empty(NoopTags.NoopTagContext.ToList()); } - [Fact] - public void NoopTagPropagationComponent() - { - Assert.Same(NoopTags.NoopTagContextBinarySerializer, NoopTags.NoopTagPropagationComponent.BinarySerializer); - } - [Fact] public void NoopTagContextBinarySerializer() { diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextBinarySerializerTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextBinarySerializerTest.cs index 324c63e7ddf..b4e0a174459 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextBinarySerializerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextBinarySerializerTest.cs @@ -20,7 +20,7 @@ namespace OpenTelemetry.Tags.Propagation.Test public class TagContextBinarySerializerTest { - private readonly TagsComponent tagsComponent = new TagsComponent(); + private readonly CurrentTaggingState state; private readonly ITagContextBinarySerializer serializer; private readonly ITagContext tagContext = new TestTagContext(); @@ -36,7 +36,8 @@ public class TagContextBinarySerializerTest public TagContextBinarySerializerTest() { - serializer = tagsComponent.TagPropagationComponent.BinarySerializer; + state = new CurrentTaggingState(); + serializer = new TagContextBinarySerializer(state); } // [Fact] // public void ToByteArray_TaggingDisabled() diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs index 435325c6103..4a52bdbeec2 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextDeserializationTest.cs @@ -24,14 +24,15 @@ namespace OpenTelemetry.Tags.Propagation.Test public class TagContextDeserializationTest { - private readonly TagsComponent tagsComponent = new TagsComponent(); - private readonly ITagContextBinarySerializer serializer; + private readonly CurrentTaggingState state; private readonly ITagger tagger; + private readonly ITagContextBinarySerializer serializer; public TagContextDeserializationTest() { - serializer = tagsComponent.TagPropagationComponent.BinarySerializer; - tagger = tagsComponent.Tagger; + state = new CurrentTaggingState(); + tagger = new Tagger(state); + serializer = new TagContextBinarySerializer(state); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs index 3af3113e89f..49a4602e2ec 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextRoundtripTest.cs @@ -31,14 +31,15 @@ public class TagContextRoundtripTest private static readonly TagValue V2 = TagValue.Create("v2"); private static readonly TagValue V3 = TagValue.Create("v3"); - private readonly TagsComponent tagsComponent = new TagsComponent(); - private readonly ITagContextBinarySerializer serializer; + private readonly CurrentTaggingState state; private readonly ITagger tagger; + private readonly ITagContextBinarySerializer serializer; public TagContextRoundtripTest() { - serializer = tagsComponent.TagPropagationComponent.BinarySerializer; - tagger = tagsComponent.Tagger; + state = new CurrentTaggingState(); + tagger = new Tagger(state); + serializer = new TagContextBinarySerializer(state); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs index 3733d183cc6..c73893bf0d1 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/Propagation/TagContextSerializationTest.cs @@ -42,14 +42,15 @@ public class TagContextSerializationTest private static readonly Tag T3 = Tag.Create(K3, V3); private static readonly Tag T4 = Tag.Create(K4, V4); - private readonly TagsComponent tagsComponent = new TagsComponent(); - private readonly ITagContextBinarySerializer serializer; + private readonly CurrentTaggingState state; private readonly ITagger tagger; + private readonly ITagContextBinarySerializer serializer; public TagContextSerializationTest() { - serializer = tagsComponent.TagPropagationComponent.BinarySerializer; - tagger = tagsComponent.Tagger; + state = new CurrentTaggingState(); + tagger = new Tagger(state); + serializer = new TagContextBinarySerializer(state); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs index fdb4134e546..179f31aef63 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TaggerTest.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Tags.Test public class TaggerTest { - private readonly TagsComponent tagsComponent = new TagsComponent(); + private readonly CurrentTaggingState state; private readonly ITagger tagger; private static readonly TagKey K1 = TagKey.Create("k1"); @@ -39,7 +39,8 @@ public class TaggerTest public TaggerTest() { - tagger = tagsComponent.Tagger; + state = new CurrentTaggingState(); + tagger = new Tagger(state); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagsComponentBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagsComponentBaseTest.cs deleted file mode 100644 index 51fcc50c24b..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagsComponentBaseTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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.Tags.Test -{ - using Xunit; - - public class TagsComponentBaseTest - { - private readonly TagsComponent tagsComponent = new TagsComponent(); - - [Fact] - public void DefaultState() - { - Assert.Equal(TaggingState.ENABLED, tagsComponent.State); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagsDefaultTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagsDefaultTest.cs index 03c078342f7..61669e72f95 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagsDefaultTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TagsDefaultTest.cs @@ -38,12 +38,5 @@ public void DefaultTagger() { Assert.Equal(NoopTags.NoopTagger, Tags.Tagger); } - - [Fact(Skip = "Fix statics usage")] - public void DefaultTagContextSerializer() - { - Assert.Equal(NoopTags.NoopTagPropagationComponent, Tags.TagPropagationComponent); - } - } } diff --git a/test/OpenTelemetry.Tests/Impl/Tags/TagsTest.cs b/test/OpenTelemetry.Tests/Impl/Tags/TagsTest.cs index 459e89442ca..bd2e8ba12c4 100644 --- a/test/OpenTelemetry.Tests/Impl/Tags/TagsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Tags/TagsTest.cs @@ -23,7 +23,7 @@ public class TagsTest { public TagsTest() { - Tags.Initialize(true); + Tags.Initialize(); } [Fact] @@ -31,11 +31,5 @@ public void GetTagger() { Assert.Equal(typeof(Tagger), Tags.Tagger.GetType()); } - - [Fact] - public void GetTagContextSerializer() - { - Assert.Equal(typeof(TagPropagationComponent), Tags.TagPropagationComponent.GetType()); - } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index c50f7dc6c91..4f905d4b4ff 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -21,6 +21,7 @@ namespace OpenTelemetry.Trace.Test using Moq; using OpenTelemetry.Common; using OpenTelemetry.Trace.Config; + using OpenTelemetry.Trace.Internal; using OpenTelemetry.Trace.Sampler; using Xunit; @@ -39,7 +40,7 @@ public SpanBuilderTest() { // MockitoAnnotations.initMocks(this); spanBuilderOptions = - new SpanBuilderOptions(startEndHandler, traceConfig); + new SpanBuilderOptions(new RandomGenerator(), startEndHandler, traceConfig); var configMock = Mock.Get(traceConfig); configMock.Setup((c) => c.ActiveTraceParams).Returns(alwaysSampleTraceParams); // when(traceConfig.getActiveTraceParams()).thenReturn(alwaysSampleTraceParams); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs deleted file mode 100644 index b341e2e543b..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/TraceComponentTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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.Test -{ - using OpenTelemetry.Internal; - using OpenTelemetry.Trace.Export; - using OpenTelemetry.Trace.Internal; - using Xunit; - - public class TraceComponentTest - { - private readonly TraceComponent traceComponent = new TraceComponent(new SimpleEventQueue()); - - [Fact] - public void ImplementationOfTracer() - { - Assert.IsType(traceComponent.Tracer); - } - - [Fact] - public void ImplementationOfTraceExporter() - { - Assert.IsType(traceComponent.ExportComponent); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index ab5c19dfab1..be4e8ca6835 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -36,7 +36,7 @@ public TracerTest() { startEndHandler = Mock.Of(); traceConfig = Mock.Of(); - tracer = new Tracer(startEndHandler, traceConfig, null); + tracer = new Tracer(new RandomGenerator(), startEndHandler, traceConfig); } [Fact] diff --git a/test/TestApp.AspNetCore.2.0/Startup.cs b/test/TestApp.AspNetCore.2.0/Startup.cs index 97107641ae3..37060dc598c 100644 --- a/test/TestApp.AspNetCore.2.0/Startup.cs +++ b/test/TestApp.AspNetCore.2.0/Startup.cs @@ -22,10 +22,10 @@ using OpenTelemetry.Collector.AspNetCore; using OpenTelemetry.Collector.Dependencies; using OpenTelemetry.Trace; +using OpenTelemetry.Trace.Export; using OpenTelemetry.Trace.Sampler; using System.Net.Http; using OpenTelemetry.Exporter.Ocagent; -using OpenTelemetry.Trace.Export; namespace TestApp.AspNetCore._2._0 { From a14967f401ce259536b641f3b48de306c740819c Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 11 Jul 2019 23:41:27 -0700 Subject: [PATCH 13/41] Remove RandomGenerator again (#143) --- .../Trace/IRandomGenerator.cs | 23 -------- .../Trace/Internal/RandomGenerator.cs | 58 ------------------- src/OpenTelemetry/Trace/SpanBuilderOptions.cs | 5 +- src/OpenTelemetry/Trace/Tracer.cs | 10 ++-- src/OpenTelemetry/Trace/Tracing.cs | 3 +- .../BasicTests.cs | 4 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 2 +- .../BasicTests.cs | 2 +- .../HttpClientTests.cs | 2 +- .../StackExchangeRedisCallsCollectorTests.cs | 2 +- .../Impl/Trace/SpanBuilderTest.cs | 2 +- .../Impl/Trace/TracerTest.cs | 2 +- 12 files changed, 14 insertions(+), 101 deletions(-) delete mode 100644 src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs delete mode 100644 src/OpenTelemetry/Trace/Internal/RandomGenerator.cs diff --git a/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs b/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs deleted file mode 100644 index a7b79c2b755..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/IRandomGenerator.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// 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 -{ - public interface IRandomGenerator - { - void NextBytes(byte[] bytes); - } -} diff --git a/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs b/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs deleted file mode 100644 index 30a834ba164..00000000000 --- a/src/OpenTelemetry/Trace/Internal/RandomGenerator.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// 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.Internal -{ - using System; - - internal class RandomGenerator : IRandomGenerator - { - private static readonly Random Global = new Random(); - - [ThreadStatic] - private static Random local; - - private readonly int seed; - private readonly bool sameSeed; - - internal RandomGenerator() - { - this.sameSeed = false; - } - - /// - /// This constructur uses the same seed for all the thread static random objects. - /// You might get the same values if a random is accessed from different threads. - /// Use only for unit tests... - /// - /// Value to seed for . - internal RandomGenerator(int seed) - { - this.sameSeed = true; - this.seed = seed; - } - - public void NextBytes(byte[] bytes) - { - if (local == null) - { - local = new Random(this.sameSeed ? this.seed : Global.Next()); - } - - local.NextBytes(bytes); - } - } -} diff --git a/src/OpenTelemetry/Trace/SpanBuilderOptions.cs b/src/OpenTelemetry/Trace/SpanBuilderOptions.cs index b1acd82c022..f1ff88707d9 100644 --- a/src/OpenTelemetry/Trace/SpanBuilderOptions.cs +++ b/src/OpenTelemetry/Trace/SpanBuilderOptions.cs @@ -20,15 +20,12 @@ namespace OpenTelemetry.Trace internal class SpanBuilderOptions { - internal SpanBuilderOptions(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig) + internal SpanBuilderOptions(IStartEndHandler startEndHandler, ITraceConfig traceConfig) { - this.RandomHandler = randomGenerator; this.StartEndHandler = startEndHandler; this.TraceConfig = traceConfig; } - internal IRandomGenerator RandomHandler { get; } - internal IStartEndHandler StartEndHandler { get; } internal ITraceConfig TraceConfig { get; } diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 8f707be1819..52db9ed05d8 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -38,26 +38,24 @@ public sealed class Tracer : ITracer /// /// Creates an instance of . /// - /// Span id generator. /// Start/end event handler. /// Trace configuration. - public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig) - : this(randomGenerator, startEndHandler, traceConfig, null, null, null) + public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig) + : this(startEndHandler, traceConfig, null, null, null) { } /// /// Creates an instance of . /// - /// Span id generator. /// Start/end event handler. /// Trace configuration. /// Exporter for span. /// Binary format context propagator. /// Text format context propagator. - public Tracer(IRandomGenerator randomGenerator, IStartEndHandler startEndHandler, ITraceConfig traceConfig, SpanExporter spanExporter, IBinaryFormat binaryFormat, ITextFormat textFormat) + public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, SpanExporter spanExporter, IBinaryFormat binaryFormat, ITextFormat textFormat) { - this.spanBuilderOptions = new SpanBuilderOptions(randomGenerator, startEndHandler, traceConfig); + this.spanBuilderOptions = new SpanBuilderOptions(startEndHandler, traceConfig); this.spanExporter = spanExporter ?? (SpanExporter)SpanExporter.Create(ExporterBufferSize, ExporterScheduleDelay); this.BinaryFormat = binaryFormat ?? new BinaryFormat(); this.TextFormat = textFormat ?? new TraceContextFormat(); diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index ded0a9bbda2..2dc0d8b43d5 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -32,7 +32,6 @@ public sealed class Tracing internal Tracing() { - IRandomGenerator randomHandler = new RandomGenerator(); IEventQueue eventQueue = new SimpleEventQueue(); TraceConfig = new Config.TraceConfig(); @@ -54,7 +53,7 @@ internal Tracing() ((ExportComponent)ExportComponent).SampledSpanStore, eventQueue); - tracer = new Tracer(randomHandler, startEndHandler, TraceConfig); + tracer = new Tracer(startEndHandler, TraceConfig); } /// diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index 0fd6f28f430..cca495c9759 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -48,7 +48,7 @@ public BasicTests(WebApplicationFactory factory) public async Task SuccesfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig()); void ConfigureTestServices(IServiceCollection services) => services.AddSingleton(tracer); @@ -104,7 +104,7 @@ public async Task SuccesfulTemplateControllerCallUsesParentContext() Tracestate.Empty )); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null, null, tf.Object); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); // 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 ea6ed663c4f..6be51d3e1a6 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -55,7 +55,7 @@ public override async Task ProcessAsync(HttpContext context) public async Task SuccesfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig()); // 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 b4e7835f512..ebb496df0e7 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -60,7 +60,7 @@ public async Task HttpDepenenciesCollectorInjectsHeadersAsync() expectedSpanId = sc.SpanId; }); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig(), null, null, tf.Object); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); using (var dc = new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) { diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index ba62ce4b412..f964bb4ae96 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -99,7 +99,7 @@ public async Task HttpOutCallsAreCollectedSuccesfullyAsync(HttpOutTestCase tc) out var port); var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig()); tc.url = NormaizeValues(tc.url, host, port); using (serverLifeTime) diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs index e1454b67fdc..7f4c2cbdd66 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/StackExchangeRedisCallsCollectorTests.cs @@ -30,7 +30,7 @@ public class StackExchangeRedisCallsCollectorTests public async void ProfilerSessionUsesTheSameDefault() { var startEndHandler = new Mock(); - var tracer = new Tracer(new RandomGenerator(), startEndHandler.Object, new TraceConfig()); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig()); using (var collector = new StackExchangeRedisCallsCollector(tracer, null, null)) { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 4f905d4b4ff..3eff28b3b05 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -40,7 +40,7 @@ public SpanBuilderTest() { // MockitoAnnotations.initMocks(this); spanBuilderOptions = - new SpanBuilderOptions(new RandomGenerator(), startEndHandler, traceConfig); + new SpanBuilderOptions(startEndHandler, traceConfig); var configMock = Mock.Get(traceConfig); configMock.Setup((c) => c.ActiveTraceParams).Returns(alwaysSampleTraceParams); // when(traceConfig.getActiveTraceParams()).thenReturn(alwaysSampleTraceParams); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs index be4e8ca6835..6e56de675ba 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracerTest.cs @@ -36,7 +36,7 @@ public TracerTest() { startEndHandler = Mock.Of(); traceConfig = Mock.Of(); - tracer = new Tracer(new RandomGenerator(), startEndHandler, traceConfig); + tracer = new Tracer(startEndHandler, traceConfig); } [Fact] From 1ae543c57512d27529331e61b51a5df8c69e5a80 Mon Sep 17 00:00:00 2001 From: Austin Parker Date: Fri, 12 Jul 2019 09:09:37 -0400 Subject: [PATCH 14/41] Refactor AttributeValue Abstraction (#88) * refactor AttributeType to KeyValuePair --- samples/Exporters/TestRedis.cs | 4 +- samples/Exporters/TestZipkin.cs | 4 +- .../Internal/BlankSpan.cs | 13 +- .../Trace/AttributeValue.cs | 57 +++- src/OpenTelemetry.Abstractions/Trace/Event.cs | 12 +- .../Trace/Export/Attributes.cs | 10 +- .../Trace/Export/IAttributes.cs | 2 +- .../Trace/IEvent.cs | 2 +- src/OpenTelemetry.Abstractions/Trace/ILink.cs | 2 +- src/OpenTelemetry.Abstractions/Trace/ISpan.cs | 11 +- .../Trace/ISpanBuilder.cs | 2 +- .../Trace/Internal/AttributeValue{T}.cs | 5 + src/OpenTelemetry.Abstractions/Trace/Link.cs | 12 +- .../Trace/NoopSpanBuilder.cs | 2 +- .../Trace/SpanData.cs | 2 +- .../RedisProfilerEntryToSpanConverter.cs | 2 +- .../Implementation/TraceExporterHandler.cs | 98 +++---- .../Implementation/SpanDataExtensions.cs | 36 ++- .../Implementation/SpanExtensions.cs | 32 ++- .../Implementation/TraceExporterHandler.cs | 2 +- src/OpenTelemetry/Trace/Span.cs | 25 +- src/OpenTelemetry/Trace/SpanBuilder.cs | 2 +- .../Utils/AttributesWithCapacity.cs | 30 +-- .../BasicTests.cs | 4 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 4 +- .../HttpClientTests.cs | 2 +- .../TraceExporterHandlerTests.cs | 252 +++++++++--------- .../Impl/Trace/BlankSpanTest.cs | 24 +- .../Impl/Trace/EventTest.cs | 12 +- .../Impl/Trace/Export/SpanDataTest.cs | 6 +- .../Impl/Trace/LinkTest.cs | 2 +- .../Trace/Propagation/TraceContextTest.cs | 2 +- .../Impl/Trace/SpanTest.cs | 54 ++-- .../Impl/Trace/TestSpan.cs | 4 +- 34 files changed, 390 insertions(+), 343 deletions(-) diff --git a/samples/Exporters/TestRedis.cs b/samples/Exporters/TestRedis.cs index b0787ae317a..785fab1e08c 100644 --- a/samples/Exporters/TestRedis.cs +++ b/samples/Exporters/TestRedis.cs @@ -108,9 +108,9 @@ private static void DoWork(IDatabase db) } // 7. Annotate our span to capture metadata about our operation - var attributes = new Dictionary + var attributes = new Dictionary { - { "use", AttributeValue.StringAttributeValue("demo") }, + { "use", "demo" }, }; span.AddEvent("Invoking DoWork", attributes); } diff --git a/samples/Exporters/TestZipkin.cs b/samples/Exporters/TestZipkin.cs index 3e898b85354..ea75c4509ee 100644 --- a/samples/Exporters/TestZipkin.cs +++ b/samples/Exporters/TestZipkin.cs @@ -90,8 +90,8 @@ private static void DoWork(int i) } // 7. Annotate our span to capture metadata about our operation - var attributes = new Dictionary(); - attributes.Add("use", AttributeValue.StringAttributeValue("demo")); + var attributes = new Dictionary(); + attributes.Add("use", "demo"); span.AddEvent("Invoking DoWork", attributes); } } diff --git a/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs b/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs index 3d76ff39573..41812cb1213 100644 --- a/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs +++ b/src/OpenTelemetry.Abstractions/Internal/BlankSpan.cs @@ -66,16 +66,11 @@ public void UpdateName(string name) } /// - public void SetAttribute(string key, IAttributeValue value) + public void SetAttribute(KeyValuePair keyValuePair) { - if (key == null) + if (keyValuePair.Key == null || keyValuePair.Value == null) { - throw new ArgumentNullException(nameof(key)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); + throw new ArgumentNullException(nameof(keyValuePair)); } } @@ -130,7 +125,7 @@ public void AddEvent(string name) } /// - public void AddEvent(string name, IDictionary attributes) + public void AddEvent(string name, IDictionary attributes) { if (name == null) { diff --git a/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs b/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs index e2823c3f04a..c783ee16274 100644 --- a/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs +++ b/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs @@ -21,17 +21,35 @@ namespace OpenTelemetry.Trace /// /// Attribute value. /// - public abstract class AttributeValue : IAttributeValue + public abstract class AttributeValue { internal AttributeValue() { } - /// - /// Creates string attribute value from value provided. - /// - /// String value. - /// Attribute value encapsulating the provided string value. + public enum Type + { + /// + /// A String AttributeValue + /// + String, + + /// + /// A Boolean AttributeValue + /// + Boolean, + + /// + /// A Long AttributeValue + /// + Long, + + /// + /// A Double AttributeValue + /// + Double, + } + public static IAttributeValue StringAttributeValue(string stringValue) { if (stringValue == null) @@ -72,7 +90,32 @@ public static IAttributeValue DoubleAttributeValue(double doubleValue) return new AttributeValue(doubleValue); } - /// + public new abstract Type GetType(); + + /// + /// Creates string attribute value from value provided. + /// + /// String value of the AttributeValue. + public string GetStringValue() + { + throw new InvalidOperationException($"This type can only return {this.GetType()} data"); + } + + public bool GetBooleanValue() + { + throw new InvalidOperationException($"This type can only return {this.GetType()} data"); + } + + public long GetLongValue() + { + throw new InvalidOperationException($"This type can only return {this.GetType()} data"); + } + + public double GetDoubleValue() + { + throw new InvalidOperationException($"This type can only return {this.GetType()} data"); + } + public abstract T Match( Func stringFunction, Func booleanFunction, diff --git a/src/OpenTelemetry.Abstractions/Trace/Event.cs b/src/OpenTelemetry.Abstractions/Trace/Event.cs index 47e4b8d4246..f4cddb14977 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Event.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Event.cs @@ -25,10 +25,10 @@ namespace OpenTelemetry.Trace /// public sealed class Event : IEvent { - private static readonly ReadOnlyDictionary EmptyAttributes = - new ReadOnlyDictionary(new Dictionary()); + private static readonly ReadOnlyDictionary EmptyAttributes = + new ReadOnlyDictionary(new Dictionary()); - internal Event(string name, IDictionary attributes) + internal Event(string name, IDictionary attributes) { this.Name = name ?? throw new ArgumentNullException("Null event name"); this.Attributes = attributes ?? throw new ArgumentNullException("Null attributes"); @@ -38,7 +38,7 @@ internal Event(string name, IDictionary attributes) public string Name { get; } /// - public IDictionary Attributes { get; } + public IDictionary Attributes { get; } /// /// Returns a new with the provided name. @@ -58,14 +58,14 @@ public static IEvent Create(string name) /// The of attributes for the . /// A new with the provided name and set of attributes. /// If name or attributes is null. - public static IEvent Create(string name, IDictionary attributes) + public static IEvent Create(string name, IDictionary attributes) { if (attributes == null) { throw new ArgumentNullException(nameof(attributes)); } - IDictionary readOnly = new ReadOnlyDictionary(attributes); + IDictionary readOnly = new ReadOnlyDictionary(attributes); return new Event(name, readOnly); } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs index 5ac965c44a6..e195d7f714a 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs @@ -23,25 +23,25 @@ namespace OpenTelemetry.Trace.Export public sealed class Attributes : IAttributes { - internal Attributes(IDictionary attributeMap, int droppedAttributesCount) + internal Attributes(IDictionary attributeMap, int droppedAttributesCount) { this.AttributeMap = attributeMap ?? throw new ArgumentNullException("Null attributeMap"); this.DroppedAttributesCount = droppedAttributesCount; } - public IDictionary AttributeMap { get; } + public IDictionary AttributeMap { get; } public int DroppedAttributesCount { get; } - public static Attributes Create(IDictionary attributeMap, int droppedAttributesCount) + public static Attributes Create(IDictionary attributeMap, int droppedAttributesCount) { if (attributeMap == null) { throw new ArgumentNullException(nameof(attributeMap)); } - IDictionary copy = new Dictionary(attributeMap); - return new Attributes(new ReadOnlyDictionary(copy), droppedAttributesCount); + IDictionary copy = new Dictionary(attributeMap); + return new Attributes(new ReadOnlyDictionary(copy), droppedAttributesCount); } /// diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs index 9e1d00a6ebf..dd02449c252 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs @@ -26,7 +26,7 @@ public interface IAttributes /// /// Gets tha dictionaty of attributes by name. /// - IDictionary AttributeMap { get; } + IDictionary AttributeMap { get; } /// /// Gets the number of attributed dropped due to the limit. diff --git a/src/OpenTelemetry.Abstractions/Trace/IEvent.cs b/src/OpenTelemetry.Abstractions/Trace/IEvent.cs index 4d74a35f7a0..7ec3fb1d332 100644 --- a/src/OpenTelemetry.Abstractions/Trace/IEvent.cs +++ b/src/OpenTelemetry.Abstractions/Trace/IEvent.cs @@ -31,6 +31,6 @@ public interface IEvent /// /// Gets the collection of attributes associated with the event. /// - IDictionary Attributes { get; } + IDictionary Attributes { get; } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/ILink.cs b/src/OpenTelemetry.Abstractions/Trace/ILink.cs index f598ba053fc..4c87abd8d25 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ILink.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ILink.cs @@ -31,6 +31,6 @@ public interface ILink /// /// Gets the collection of attributes associated with the link. /// - IDictionary Attributes { get; } + IDictionary Attributes { get; } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/ISpan.cs b/src/OpenTelemetry.Abstractions/Trace/ISpan.cs index edad4cd84d3..2e6c5052759 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISpan.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISpan.cs @@ -58,13 +58,6 @@ public interface ISpan /// Name of the span. void UpdateName(string name); - /// - /// Puts a new attribute to the span. - /// - /// Key of the attribute. - /// Attribute value. - void SetAttribute(string key, IAttributeValue value); - /// /// Puts a new attribute to the span. /// @@ -93,6 +86,8 @@ public interface ISpan /// Attribute value. void SetAttribute(string key, bool value); + void SetAttribute(KeyValuePair keyValuePair); + /// /// Adds a single to the . /// @@ -104,7 +99,7 @@ public interface ISpan /// /// Event name. /// of attributes name/value pairs associated with the . - void AddEvent(string name, IDictionary attributes); + void AddEvent(string name, IDictionary attributes); /// /// Adds an object to the . diff --git a/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs index 9f89a5d88f3..75a77c108c5 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs @@ -80,7 +80,7 @@ public interface ISpanBuilder /// context. /// The attributes of the . /// This span builder for chaining. - ISpanBuilder AddLink(SpanContext context, IDictionary attributes); + ISpanBuilder AddLink(SpanContext context, IDictionary attributes); /// /// Set the record events value. diff --git a/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs b/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs index 52f271299f8..36fa95fcb87 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs @@ -116,6 +116,11 @@ public override string ToString() + "}"; } + public override Type GetType() + { + return this.GetType(); + } + /// public override TReturn Match( Func stringFunction, diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index dcd6d02e19f..d90bff1bb64 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -25,9 +25,9 @@ namespace OpenTelemetry.Trace /// public sealed class Link : ILink { - private static readonly IDictionary EmptyAttributes = new Dictionary(); + private static readonly IDictionary EmptyAttributes = new Dictionary(); - private Link(SpanContext context, IDictionary attributes) + private Link(SpanContext context, IDictionary attributes) { this.Context = context ?? throw new ArgumentNullException(nameof(context)); this.Attributes = attributes ?? throw new ArgumentNullException(nameof(attributes)); @@ -37,19 +37,19 @@ private Link(SpanContext context, IDictionary attribute public SpanContext Context { get; } /// - public IDictionary Attributes { get; } + public IDictionary Attributes { get; } public static ILink FromSpanContext(SpanContext context) { return new Link(context, EmptyAttributes); } - public static ILink FromSpanContext(SpanContext context, IDictionary attributes) + public static ILink FromSpanContext(SpanContext context, IDictionary attributes) { - IDictionary copy = new Dictionary(attributes); + IDictionary copy = new Dictionary(attributes); return new Link( context, - new ReadOnlyDictionary(copy)); + new ReadOnlyDictionary(copy)); } /// diff --git a/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs index 97b484c1300..370dac44f6c 100644 --- a/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs @@ -112,7 +112,7 @@ public ISpanBuilder AddLink(ILink link) } /// - public ISpanBuilder AddLink(SpanContext context, IDictionary attributes) + public ISpanBuilder AddLink(SpanContext context, IDictionary attributes) { if (context == null) { diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index c9f1aa42b28..b86f8ed5c8e 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -48,7 +48,7 @@ internal SpanData( this.Resource = resource ?? throw new ArgumentNullException(nameof(resource)); this.Name = name ?? throw new ArgumentNullException(nameof(name)); this.StartTimestamp = startTimestamp ?? throw new ArgumentNullException(nameof(startTimestamp)); - this.Attributes = attributes ?? Export.Attributes.Create(new Dictionary(), 0); + this.Attributes = attributes ?? Export.Attributes.Create(new Dictionary(), 0); this.Events = events ?? TimedEvents.Create(Enumerable.Empty>(), 0); this.Links = links ?? LinkList.Create(Enumerable.Empty(), 0); this.ChildSpanCount = childSpanCount; diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs index bf3d8135bab..27ac5522374 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs @@ -121,7 +121,7 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n // TODO: determine what to do with Resource in this context var resource = Resource.Empty; - var attributesMap = new Dictionary() + var attributesMap = new Dictionary() { // TODO: pre-allocate constant attribute and reuse { "db.type", AttributeValue.StringAttributeValue("redis") }, diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs index e273ffad11e..46f064f505d 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs @@ -59,16 +59,16 @@ public Task ExportAsync(IEnumerable spanDataList) string type = null; string userAgent = null; - IAttributeValue spanKindAttr = null; - IAttributeValue errorAttr = null; - IAttributeValue httpStatusCodeAttr = null; - IAttributeValue httpMethodAttr = null; - IAttributeValue httpPathAttr = null; - IAttributeValue httpHostAttr = null; - IAttributeValue httpUrlAttr = null; - IAttributeValue httpUserAgentAttr = null; - IAttributeValue httpRouteAttr = null; - IAttributeValue httpPortAttr = null; + string spanKindAttr = null; + string errorAttr = null; + string httpStatusCodeAttr = null; + string httpMethodAttr = null; + string httpPathAttr = null; + string httpHostAttr = null; + string httpUrlAttr = null; + string httpUserAgentAttr = null; + string httpRouteAttr = null; + string httpPortAttr = null; foreach (var attr in span.Attributes.AttributeMap) { @@ -76,42 +76,37 @@ public Task ExportAsync(IEnumerable spanDataList) switch (attr.Key) { case "span.kind": - spanKindAttr = attr.Value; + spanKindAttr = attr.Value.ToString(); break; case "error": - errorAttr = attr.Value; + errorAttr = attr.Value.ToString(); break; case "http.method": - httpMethodAttr = attr.Value; + httpMethodAttr = attr.Value.ToString(); break; case "http.path": - httpPathAttr = attr.Value; + httpPathAttr = attr.Value.ToString(); break; case "http.host": - httpHostAttr = attr.Value; + httpHostAttr = attr.Value.ToString(); break; case "http.url": - httpUrlAttr = attr.Value; + httpUrlAttr = attr.Value.ToString(); break; case "http.status_code": - httpStatusCodeAttr = attr.Value; + httpStatusCodeAttr = attr.Value.ToString(); break; case "http.user_agent": - httpUserAgentAttr = attr.Value; + httpUserAgentAttr = attr.Value.ToString(); break; case "http.route": - httpRouteAttr = attr.Value; + httpRouteAttr = attr.Value.ToString(); break; case "http.port": - httpPortAttr = attr.Value; + httpPortAttr = attr.Value.ToString(); break; default: - var value = attr.Value.Match( - (s) => { return s; }, - (b) => { return b.ToString(); }, - (l) => { return l.ToString(); }, - (d) => { return d.ToString(); }, - (obj) => { return obj.ToString(); }); + var value = attr.Value.ToString(); AddPropertyWithAdjustedName(props, attr.Key, value); @@ -127,7 +122,7 @@ public Task ExportAsync(IEnumerable spanDataList) foreach (var attr in link.Attributes) { - AddPropertyWithAdjustedName(props, "link" + linkId + "_" + attr.Key, attr.Value.Match((s) => s, (b) => b.ToString(), (l) => l.ToString(), (d) => d.ToString(), (obj) => obj.ToString())); + AddPropertyWithAdjustedName(props, "link" + linkId + "_" + attr.Key, attr.Value.ToString()); } ++linkId; @@ -146,12 +141,7 @@ public Task ExportAsync(IEnumerable spanDataList) foreach (var attr in t.Event.Attributes) { - var value = attr.Value.Match( - (s) => { return s; }, - (b) => { return b.ToString(); }, - (l) => { return l.ToString(); }, - (d) => { return d.ToString(); }, - (obj) => { return obj.ToString(); }); + var value = attr.Value.ToString(); AddPropertyWithAdjustedName(log.Properties, attr.Key, value); } @@ -298,12 +288,12 @@ private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, ou duration = TimeSpan.FromTicks((durationTs.Seconds * TimeSpan.TicksPerSecond) + (durationTs.Nanos / 100)); } - private void OverwriteSpanKindFromAttribute(IAttributeValue spanKindAttr, ref SpanKind resultKind) + private void OverwriteSpanKindFromAttribute(string spanKindAttr, ref SpanKind resultKind) { // override span kind with attribute named span.kind if (spanKindAttr != null) { - var kind = spanKindAttr.Match((s) => s, null, null, null, null); + var kind = spanKindAttr; switch (kind.ToLower(CultureInfo.InvariantCulture)) { @@ -326,23 +316,23 @@ private void OverwriteSpanKindFromAttribute(IAttributeValue spanKindAttr, ref Sp } } - private void OverwriteErrorAttribute(IAttributeValue errorAttr, ref bool? success) + private void OverwriteErrorAttribute(string errorAttr, ref bool? success) { if (errorAttr != null) { - success = errorAttr.Match((s) => !(s == "true"), (b) => !b, null, null, null); + success = errorAttr.ToLowerInvariant() != "true"; } } private void OverwriteFieldsForHttpSpans( - IAttributeValue httpMethodAttr, - IAttributeValue httpUrlAttr, - IAttributeValue httpHostAttr, - IAttributeValue httpPathAttr, - IAttributeValue httpStatusCodeAttr, - IAttributeValue httpUserAgentAttr, - IAttributeValue httpRouteAttr, - IAttributeValue httpPortAttr, + string httpMethodAttr, + string httpUrlAttr, + string httpHostAttr, + string httpPathAttr, + string httpStatusCodeAttr, + string httpUserAgentAttr, + string httpRouteAttr, + string httpPortAttr, ref string name, ref string resultCode, ref string data, @@ -352,7 +342,7 @@ private void OverwriteFieldsForHttpSpans( { if (httpStatusCodeAttr != null) { - resultCode = httpStatusCodeAttr.Match((s) => s, null, (l) => l.ToString(CultureInfo.InvariantCulture), null, null); + resultCode = httpStatusCodeAttr.ToString(CultureInfo.InvariantCulture); type = "Http"; } @@ -360,7 +350,7 @@ private void OverwriteFieldsForHttpSpans( if (httpUrlAttr != null) { - var urlString = httpUrlAttr.Match((s) => s, null, null, null, null); + var urlString = httpUrlAttr; Uri.TryCreate(urlString, UriKind.RelativeOrAbsolute, out url); } @@ -372,43 +362,43 @@ private void OverwriteFieldsForHttpSpans( if (httpMethodAttr != null) { - httpMethod = httpMethodAttr.Match((s) => s, null, null, null, null); + httpMethod = httpMethodAttr; type = "Http"; } if (httpPathAttr != null) { - httpPath = httpPathAttr.Match((s) => s, null, null, null, null); + httpPath = httpPathAttr; type = "Http"; } if (httpHostAttr != null) { - httpHost = httpHostAttr.Match((s) => s, null, null, null, null); + httpHost = httpHostAttr; type = "Http"; } if (httpUserAgentAttr != null) { - userAgent = httpUserAgentAttr.Match((s) => s, null, null, null, null); + userAgent = httpUserAgentAttr; type = "Http"; } if (httpRouteAttr != null) { - httpRoute = httpRouteAttr.Match((s) => s, null, null, null, null); + httpRoute = httpRouteAttr; type = "Http"; } if (httpRouteAttr != null) { - httpRoute = httpRouteAttr.Match((s) => s, null, null, null, null); + httpRoute = httpRouteAttr; type = "Http"; } if (httpPortAttr != null) { - httpPort = httpPortAttr.Match((s) => s, null, (l) => l.ToString(), null, null); + httpPort = httpPortAttr; type = "Http"; } diff --git a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs index 382583934e6..7a22303bd17 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs @@ -108,16 +108,31 @@ private static Span.Types.Attributes FromIAttributes(IAttributes source) attributes.AttributeMap.Add(source.AttributeMap.ToDictionary( kvp => kvp.Key, - kvp => kvp.Value.Match( - s => new OpenTelemetry.Proto.Trace.V1.AttributeValue { StringValue = new TruncatableString() { Value = s } }, - b => new OpenTelemetry.Proto.Trace.V1.AttributeValue { BoolValue = b }, - l => new OpenTelemetry.Proto.Trace.V1.AttributeValue { IntValue = l }, - d => new OpenTelemetry.Proto.Trace.V1.AttributeValue { DoubleValue = d }, - o => new OpenTelemetry.Proto.Trace.V1.AttributeValue { StringValue = new TruncatableString() { Value = o?.ToString() } }))); + kvp => FromAttribute(kvp.Value))); return attributes; } + private static OpenTelemetry.Proto.Trace.V1.AttributeValue FromAttribute(object value) + { + switch (value) + { + case string s: + return new OpenTelemetry.Proto.Trace.V1.AttributeValue { StringValue = new TruncatableString() { Value = s } }; + case bool b: + return new OpenTelemetry.Proto.Trace.V1.AttributeValue { BoolValue = b }; + case long l: + return new OpenTelemetry.Proto.Trace.V1.AttributeValue { IntValue = l }; + case double d: + return new OpenTelemetry.Proto.Trace.V1.AttributeValue { DoubleValue = d }; + default: + return new OpenTelemetry.Proto.Trace.V1.AttributeValue + { + StringValue = new TruncatableString() { Value = value?.ToString() }, + }; + } + } + private static Span.Types.TimeEvents FromITimeEvents(ITimedEvents events) { var timedEvents = new Span.Types.TimeEvents @@ -167,18 +182,13 @@ private static Span.Types.TimeEvent FromITimeEvent(ITimedEvent source) }; } - private static Span.Types.Attributes FromIAttributeMap(IDictionary source) + private static Span.Types.Attributes FromIAttributeMap(IDictionary source) { var attributes = new Span.Types.Attributes(); attributes.AttributeMap.Add(source.ToDictionary( kvp => kvp.Key, - kvp => kvp.Value.Match( - s => new OpenTelemetry.Proto.Trace.V1.AttributeValue { StringValue = new TruncatableString() { Value = s } }, - b => new OpenTelemetry.Proto.Trace.V1.AttributeValue { BoolValue = b }, - l => new OpenTelemetry.Proto.Trace.V1.AttributeValue { IntValue = l }, - d => new OpenTelemetry.Proto.Trace.V1.AttributeValue { DoubleValue = d }, - o => new OpenTelemetry.Proto.Trace.V1.AttributeValue { StringValue = new TruncatableString() { Value = o?.ToString() } }))); + kvp => FromAttribute(kvp.Value))); return attributes; } diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs index b0ceefcdecc..69d28fe3eff 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs @@ -106,16 +106,30 @@ public static Google.Cloud.Trace.V2.Span.Types.Link ToLink(this ILink link) return ret; } - public static Google.Cloud.Trace.V2.AttributeValue ToAttributeValue(this IAttributeValue av) + public static Google.Cloud.Trace.V2.AttributeValue ToAttributeValue(this object av) { - var ret = av.Match( - (s) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = s } }, - (b) => new Google.Cloud.Trace.V2.AttributeValue() { BoolValue = b }, - (l) => new Google.Cloud.Trace.V2.AttributeValue() { IntValue = l }, - (d) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = d.ToString() } }, - (obj) => new Google.Cloud.Trace.V2.AttributeValue() { StringValue = new TruncatableString() { Value = obj.ToString() } }); - - return ret; + switch (av) + { + case string s: + return new Google.Cloud.Trace.V2.AttributeValue() + { + StringValue = new TruncatableString() { Value = s }, + }; + case bool b: + return new Google.Cloud.Trace.V2.AttributeValue() { BoolValue = b }; + case long l: + return new Google.Cloud.Trace.V2.AttributeValue() { IntValue = l }; + case double d: + return new Google.Cloud.Trace.V2.AttributeValue() + { + StringValue = new TruncatableString() { Value = d.ToString() }, + }; + default: + return new Google.Cloud.Trace.V2.AttributeValue() + { + StringValue = new TruncatableString() { Value = av.ToString() }, + }; + } } } } diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index 3239292ab96..920900a6939 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -92,7 +92,7 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint foreach (var label in spanData.Attributes.AttributeMap) { - spanBuilder.PutTag(label.Key, this.AttributeValueToString(label.Value)); + spanBuilder.PutTag(label.Key, (string)label.Value); } var status = spanData.Status; diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index 0ea7dee2401..485387ba899 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -235,16 +235,11 @@ public void UpdateName(string name) } /// - public void SetAttribute(string key, IAttributeValue value) + public void SetAttribute(KeyValuePair keyValuePair) { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (value == null) + if (keyValuePair.Key == null || keyValuePair.Value == null) { - throw new ArgumentNullException(nameof(value)); + throw new ArgumentNullException(nameof(keyValuePair)); } if (!this.IsRecordingEvents) @@ -260,7 +255,7 @@ public void SetAttribute(string key, IAttributeValue value) return; } - this.InitializedAttributes.PutAttribute(key, value); + this.InitializedAttributes.PutAttribute(keyValuePair.Key, keyValuePair.Value); } } @@ -290,7 +285,7 @@ public void AddEvent(string name) } /// - public void AddEvent(string name, IDictionary eventAttributes) + public void AddEvent(string name, IDictionary eventAttributes) { if (name == null) { @@ -409,7 +404,7 @@ public SpanData ToSpanData() throw new InvalidOperationException("Getting SpanData for a Span without RECORD_EVENTS option."); } - var attributesSpanData = this.attributes == null ? Attributes.Create(new Dictionary(), 0) + var attributesSpanData = this.attributes == null ? Attributes.Create(new Dictionary(), 0) : Attributes.Create(this.attributes, this.attributes.NumberOfDroppedAttributes); var annotationsSpanData = CreateTimedEvents(this.InitializedEvents, this.TimestampConverter); @@ -448,7 +443,7 @@ public void SetAttribute(string key, string value) return; } - this.SetAttribute(key, AttributeValue.StringAttributeValue(value)); + this.SetAttribute(new KeyValuePair(key, value)); } /// @@ -464,7 +459,7 @@ public void SetAttribute(string key, long value) return; } - this.SetAttribute(key, AttributeValue.LongAttributeValue(value)); + this.SetAttribute(new KeyValuePair(key, value)); } /// @@ -480,7 +475,7 @@ public void SetAttribute(string key, double value) return; } - this.SetAttribute(key, AttributeValue.DoubleAttributeValue(value)); + this.SetAttribute(new KeyValuePair(key, value)); } /// @@ -496,7 +491,7 @@ public void SetAttribute(string key, bool value) return; } - this.SetAttribute(key, AttributeValue.BooleanAttributeValue(value)); + this.SetAttribute(new KeyValuePair(key, value)); } internal static ISpan StartSpan( diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index 397ae59d2e9..edc979541a6 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -105,7 +105,7 @@ public ISpanBuilder AddLink(SpanContext spanContext) } /// - public ISpanBuilder AddLink(SpanContext spanContext, IDictionary attributes) + public ISpanBuilder AddLink(SpanContext spanContext, IDictionary attributes) { if (spanContext == null) { diff --git a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs index 9e469567b5d..0ef2199fbdf 100644 --- a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs +++ b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Utils using System.Linq; using OpenTelemetry.Trace; - internal class AttributesWithCapacity : IDictionary + internal class AttributesWithCapacity : IDictionary { private readonly OrderedDictionary @delegate = new OrderedDictionary(); private readonly int capacity; @@ -49,11 +49,11 @@ public ICollection Keys } } - public ICollection Values + public ICollection Values { get { - return (ICollection)this.@delegate.Values; + return (ICollection)this.@delegate.Values; } } @@ -73,7 +73,7 @@ public bool IsReadOnly } } - public IAttributeValue this[string key] + public object this[string key] { get { @@ -86,7 +86,7 @@ public IAttributeValue this[string key] } } - public void PutAttribute(string key, IAttributeValue value) + public void PutAttribute(string key, object value) { this.totalRecordedAttributes += 1; this[key] = value; @@ -98,7 +98,7 @@ public void PutAttribute(string key, IAttributeValue value) // Users must call this method instead of putAll to keep count of the total number of entries // inserted. - public void PutAttributes(IDictionary attributes) + public void PutAttributes(IDictionary attributes) { foreach (var kvp in attributes) { @@ -106,7 +106,7 @@ public void PutAttributes(IDictionary attributes) } } - public void Add(string key, IAttributeValue value) + public void Add(string key, object value) { this.@delegate.Add(key, value); } @@ -129,7 +129,7 @@ public bool Remove(string key) } } - public bool TryGetValue(string key, out IAttributeValue value) + public bool TryGetValue(string key, out object value) { value = null; if (this.ContainsKey(key)) @@ -141,7 +141,7 @@ public bool TryGetValue(string key, out IAttributeValue value) return false; } - public void Add(KeyValuePair item) + public void Add(KeyValuePair item) { this.@delegate.Add(item.Key, item.Value); } @@ -151,7 +151,7 @@ public void Clear() this.@delegate.Clear(); } - public bool Contains(KeyValuePair item) + public bool Contains(KeyValuePair item) { var result = this.TryGetValue(item.Key, out var value); if (result) @@ -162,25 +162,25 @@ public bool Contains(KeyValuePair item) return false; } - public void CopyTo(KeyValuePair[] array, int arrayIndex) + public void CopyTo(KeyValuePair[] array, int arrayIndex) { var entries = new DictionaryEntry[this.@delegate.Count]; this.@delegate.CopyTo(entries, 0); for (var i = 0; i < entries.Length; i++) { - array[i + arrayIndex] = new KeyValuePair((string)entries[i].Key, (IAttributeValue)entries[i].Value); + array[i + arrayIndex] = new KeyValuePair((string)entries[i].Key, (object)entries[i].Value); } } - public bool Remove(KeyValuePair item) + public bool Remove(KeyValuePair item) { return this.Remove(item.Key); } - public IEnumerator> GetEnumerator() + public IEnumerator> GetEnumerator() { - var array = new KeyValuePair[this.@delegate.Count]; + var array = new KeyValuePair[this.@delegate.Count]; this.CopyTo(array, 0); return array.ToList().GetEnumerator(); } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index cca495c9759..c4a917c12ab 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -85,7 +85,7 @@ void ConfigureTestServices(IServiceCollection services) => var spanData = ((Span)startEndHandler.Invocations[1].Arguments[0]).ToSpanData(); Assert.Equal(SpanKind.Server, spanData.Kind); - Assert.Equal(AttributeValue.StringAttributeValue("/api/values"), spanData.Attributes.AttributeMap["http.path"]); + Assert.Equal("/api/values", spanData.Attributes.AttributeMap["http.path"]); } [Fact] @@ -143,7 +143,7 @@ public async Task SuccesfulTemplateControllerCallUsesParentContext() Assert.Equal(SpanKind.Server, spanData.Kind); Assert.Equal("api/Values/{id}", spanData.Name); - Assert.Equal(AttributeValue.StringAttributeValue("/api/values/2"), spanData.Attributes.AttributeMap["http.path"]); + Assert.Equal("/api/values/2", spanData.Attributes.AttributeMap["http.path"]); Assert.Equal(expectedTraceId, spanData.Context.TraceId); Assert.Equal(expectedSpanId, spanData.ParentSpanId); diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index 6be51d3e1a6..ab35d29ba2d 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -96,8 +96,8 @@ public async Task SuccesfulTemplateControllerCallGeneratesASpan() var spanData = ((Span)startEndHandler.Invocations[0].Arguments[0]).ToSpanData(); Assert.Equal(SpanKind.Server, spanData.Kind); - Assert.Equal(AttributeValue.StringAttributeValue("/api/values"), spanData.Attributes.AttributeMap["http.path"]); - Assert.Equal(AttributeValue.LongAttributeValue(503), spanData.Attributes.AttributeMap["http.status_code"]); + Assert.Equal("/api/values", spanData.Attributes.AttributeMap["http.path"]); + Assert.Equal(503L, spanData.Attributes.AttributeMap["http.status_code"]); } } } diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index f964bb4ae96..2e87ec8ade1 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -164,7 +164,7 @@ public async Task HttpOutCallsAreCollectedSuccesfullyAsync(HttpOutTestCase tc) Assert.Equal(tc.spanStatus, d[spanData.Status.CanonicalCode]); - var normilizedAttributes = spanData.Attributes.AttributeMap.ToDictionary(x => x.Key, x => AttributeToSimpleString(x.Value)); + var normilizedAttributes = spanData.Attributes.AttributeMap.ToDictionary(x => x.Key, x => x.Value.ToString()); tc.spanAttributes = tc.spanAttributes.ToDictionary(x => x.Key, x => NormaizeValues(x.Value, host, port)); Assert.Equal(tc.spanAttributes.ToHashSet(), normilizedAttributes.ToHashSet()); diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs index f5e2189d56f..cfea4df7e17 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs @@ -236,7 +236,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestErrorAttribute() { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - attributes = Attributes.Create(new Dictionary() { { "error", AttributeValue.BooleanAttributeValue(true) } }, 0); + attributes = Attributes.Create(new Dictionary() { { "error", true } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -510,7 +510,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyErrorAttribute( { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "error", AttributeValue.BooleanAttributeValue(true) } }, 0); + attributes = Attributes.Create(new Dictionary() { { "error", true } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); var sentItems = this.ConvertSpan(span); @@ -525,7 +525,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnServerSpanK { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", AttributeValue.StringAttributeValue("server") } }, 0); + attributes = Attributes.Create(new Dictionary() { { "span.kind", "server" } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -539,7 +539,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnClientSpanK { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", AttributeValue.StringAttributeValue("client") } }, 0); + attributes = Attributes.Create(new Dictionary() { { "span.kind", "client" } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -553,7 +553,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnProducerSpa { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", AttributeValue.StringAttributeValue("producer") } }, 0); + attributes = Attributes.Create(new Dictionary() { { "span.kind", "producer" } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -567,7 +567,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnConsumerSpa { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", AttributeValue.StringAttributeValue("consumer") } }, 0); + attributes = Attributes.Create(new Dictionary() { { "span.kind", "consumer" } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -581,7 +581,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnOtherSpanKi { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", AttributeValue.StringAttributeValue("other") } }, 0); + attributes = Attributes.Create(new Dictionary() { { "span.kind", "other" } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -620,7 +620,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyBasedOnSpanKind { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); kind = SpanKind.Internal; - attributes = Attributes.Create(new Dictionary() { { "span.kind", AttributeValue.StringAttributeValue("client") } }, 0); + attributes = Attributes.Create(new Dictionary() { { "span.kind", "client" } }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); var sentItems = this.ConvertSpan(span); @@ -698,11 +698,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestWithUrl() this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.status_code", AttributeValue.LongAttributeValue(409) }, + { "http.url", url.ToString() }, + { "http.method", "POST" }, + { "http.status_code", 409 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -720,11 +720,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestWithRelativeUr this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.LocalPath) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.status_code", AttributeValue.LongAttributeValue(409) }, + { "http.url", url.LocalPath }, + { "http.method", "POST" }, + { "http.status_code", 409 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -742,12 +742,12 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestWithUrlAndRout this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.route", AttributeValue.StringAttributeValue("route") }, - { "http.status_code", AttributeValue.LongAttributeValue(503) }, + { "http.url", url.ToString() }, + { "http.method", "POST" }, + { "http.route", "route" }, + { "http.status_code", 503 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -765,10 +765,10 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestWithUrlAndNoMe this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.url", url.ToString() }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -786,14 +786,14 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestWithUrlOtherAt this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("another path") }, - { "http.host", AttributeValue.StringAttributeValue("another host") }, - { "http.port", AttributeValue.LongAttributeValue(8080) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.url", url.ToString() }, + { "http.method", "POST" }, + { "http.path", "another path" }, + { "http.host", "another host" }, + { "http.port", 8080 }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -812,9 +812,9 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithStringStatusCo this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.status_code", AttributeValue.LongAttributeValue(201) }, + { "http.status_code", 201 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -833,13 +833,13 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestHostPortPathAt this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("path") }, - { "http.host", AttributeValue.StringAttributeValue("host") }, - { "http.port", AttributeValue.LongAttributeValue(123) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.path", "path" }, + { "http.host", "host" }, + { "http.port", 123 }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -856,13 +856,13 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestPortPathAndEmp { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("path") }, - { "http.host", AttributeValue.StringAttributeValue("") }, - { "http.port", AttributeValue.LongAttributeValue(123) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.path", "path" }, + { "http.host", "" }, + { "http.port", 123 }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -880,12 +880,12 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestHostPathAttrib this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("/path") }, - { "http.host", AttributeValue.StringAttributeValue("host") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.path", "/path" }, + { "http.host", "host" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -902,11 +902,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestHostAttributes { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.host", AttributeValue.StringAttributeValue("host") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.host", "host" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -924,10 +924,10 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestOnlyMethodAttr this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); var url = new Uri("https://host:123/path?query"); name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -947,9 +947,9 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyWithStringStatu var url = new Uri("https://host:123/path?query"); kind = SpanKind.Client; name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.status_code", AttributeValue.LongAttributeValue(201) }, + { "http.status_code", 201 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -969,10 +969,10 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpRequestUserAgent() var url = new Uri("https://host/path"); var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"; name = "HttpIn"; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.user_agent", AttributeValue.StringAttributeValue(userAgent) }, + { "http.url", url.ToString() }, + { "http.user_agent", userAgent }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -989,11 +989,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithUrl() var url = new Uri("https://host:123/path?query"); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.url", url.ToString() }, + { "http.method", "POST" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1014,11 +1014,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithRelativ var url = new Uri("https://host:123/path?query"); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.LocalPath) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.url", url.LocalPath }, + { "http.method", "POST" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1039,14 +1039,14 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithUrlIgno var url = new Uri("https://host:123/path?query"); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.url", AttributeValue.StringAttributeValue(url.ToString()) }, - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("another path") }, - { "http.host", AttributeValue.StringAttributeValue("another host") }, - { "http.port", AttributeValue.LongAttributeValue(8080) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.url", url.ToString() }, + { "http.method", "POST" }, + { "http.path", "another path" }, + { "http.host", "another host" }, + { "http.port", 8080 }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1066,13 +1066,13 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithHostPor this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("/path") }, - { "http.host", AttributeValue.StringAttributeValue("host") }, - { "http.port", AttributeValue.LongAttributeValue(123) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.path", "/path" }, + { "http.host", "host" }, + { "http.port", 123 }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1092,12 +1092,12 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithHostPor this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.host", AttributeValue.StringAttributeValue("host") }, - { "http.port", AttributeValue.LongAttributeValue(123) }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.host", "host" }, + { "http.port", 123 }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1117,12 +1117,12 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithPathAnd this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.path", AttributeValue.StringAttributeValue("/path") }, - { "http.host", AttributeValue.StringAttributeValue("") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.path", "/path" }, + { "http.host", "" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1143,11 +1143,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithHost() var url = new Uri("https://host:123/path?query"); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.host", AttributeValue.StringAttributeValue("host") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.host", "host" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1168,10 +1168,10 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithMethod( var url = new Uri("https://host:123/path?query"); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.method", AttributeValue.StringAttributeValue("POST") }, - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.method", "POST" }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1193,9 +1193,9 @@ public void OpenTelemetryTelemetryConverterTests_TracksHttpDependencyWithStatusC var url = new Uri("https://host:123/path?query"); name = "HttpOut"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "http.status_code", AttributeValue.LongAttributeValue(200) }, + { "http.status_code", 200 }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1216,11 +1216,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyWithCustomAttri var url = new Uri("https://host:123/path?query"); name = "spanName"; kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "custom.stringAttribute", AttributeValue.StringAttributeValue("string") }, - { "custom.longAttribute", AttributeValue.LongAttributeValue(long.MaxValue) }, - { "custom.boolAttribute", AttributeValue.BooleanAttributeValue(true) }, + { "custom.stringAttribute", "string" }, + { "custom.longAttribute", long.MaxValue }, + { "custom.boolAttribute", true }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1246,11 +1246,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestsWithCustomAttribu var url = new Uri("https://host:123/path?query"); name = "spanName"; kind = SpanKind.Server; - attributes = Attributes.Create(new Dictionary() + attributes = Attributes.Create(new Dictionary() { - { "custom.stringAttribute", AttributeValue.StringAttributeValue("string") }, - { "custom.longAttribute", AttributeValue.LongAttributeValue(long.MaxValue) }, - { "custom.boolAttribute", AttributeValue.BooleanAttributeValue(true) }, + { "custom.stringAttribute", "string" }, + { "custom.longAttribute", long.MaxValue }, + { "custom.boolAttribute", true }, }, 0); var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); @@ -1335,11 +1335,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyWithLinksAndAtt ActivitySpanId.CreateFromBytes(GenerateRandomId(8).Item2), ActivityTraceFlags.None, Tracestate.Empty), - new Dictionary() + new Dictionary() { - { "some.str.attribute", AttributeValue.StringAttributeValue("foo") }, - { "some.int.attribute", AttributeValue.LongAttributeValue(1) }, - { "some.bool.attribute", AttributeValue.BooleanAttributeValue(true) }, + { "some.str.attribute", "foo" }, + { "some.int.attribute", 1 }, + { "some.bool.attribute", true }, }), }, droppedLinksCount: 0); @@ -1426,11 +1426,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithLinksAndAttrib ActivitySpanId.CreateFromBytes(GenerateRandomId(8).Item2), ActivityTraceFlags.None, Tracestate.Empty), - new Dictionary() + new Dictionary() { - { "some.str.attribute", AttributeValue.StringAttributeValue("foo") }, - { "some.int.attribute", AttributeValue.LongAttributeValue(1) }, - { "some.bool.attribute", AttributeValue.BooleanAttributeValue(true) }, + { "some.str.attribute", "foo" }, + { "some.int.attribute", 1 }, + { "some.bool.attribute", true }, }), }, droppedLinksCount: 0); @@ -1464,11 +1464,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithEvents() new List>() { TimedEvent.Create(NowTimestamp, Event.Create("test message1")), - TimedEvent.Create(null, Event.Create("test message2", new Dictionary() + TimedEvent.Create(null, Event.Create("test message2", new Dictionary() { - { "custom.stringAttribute", AttributeValue.StringAttributeValue("string") }, - { "custom.longAttribute", AttributeValue.LongAttributeValue(long.MaxValue) }, - { "custom.boolAttribute", AttributeValue.BooleanAttributeValue(true) }, + { "custom.stringAttribute", "string" }, + { "custom.longAttribute", long.MaxValue }, + { "custom.boolAttribute", true }, })), }, droppedEventsCount: 0); @@ -1589,11 +1589,11 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependenciesWithEvents() new List>() { TimedEvent.Create(NowTimestamp, Event.Create("test message1")), - TimedEvent.Create(null, Event.Create("test message2", new Dictionary() + TimedEvent.Create(null, Event.Create("test message2", new Dictionary() { - { "custom.stringAttribute", AttributeValue.StringAttributeValue("string") }, - { "custom.longAttribute", AttributeValue.LongAttributeValue(long.MaxValue) }, - { "custom.boolAttribute", AttributeValue.BooleanAttributeValue(true) }, + { "custom.stringAttribute", "string" }, + { "custom.longAttribute", long.MaxValue }, + { "custom.boolAttribute", true }, })), }, droppedEventsCount: 0); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs index 8c55220bb99..c6ab348f991 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/BlankSpanTest.cs @@ -26,26 +26,26 @@ public class BlankSpanTest [Fact] public void DoNotCrash() { - IDictionary attributes = new Dictionary(); + IDictionary attributes = new Dictionary(); attributes.Add( - "MyStringAttributeKey", AttributeValue.Create("MyStringAttributeValue")); - IDictionary multipleAttributes = new Dictionary(); + "MyStringAttributeKey", "MyStringAttributeValue"); + IDictionary multipleAttributes = new Dictionary(); multipleAttributes.Add( - "MyStringAttributeKey", AttributeValue.Create("MyStringAttributeValue")); - multipleAttributes.Add("MyBooleanAttributeKey", AttributeValue.Create(true)); - multipleAttributes.Add("MyLongAttributeKey", AttributeValue.Create(123)); - multipleAttributes.Add("MyDoubleAttributeKey", AttributeValue.Create(0.005)); + "MyStringAttributeKey", "MyStringAttributeValue"); + multipleAttributes.Add("MyBooleanAttributeKey", true); + multipleAttributes.Add("MyLongAttributeKey", 123); + multipleAttributes.Add("MyDoubleAttributeKey", 0.005); // Tests only that all the methods are not crashing/throwing errors. BlankSpan.Instance.SetAttribute( - "MyStringAttributeKey2", AttributeValue.Create("MyStringAttributeValue2")); + "MyStringAttributeKey2", "MyStringAttributeValue2"); foreach (var a in attributes) { - BlankSpan.Instance.SetAttribute(a.Key, a.Value); + BlankSpan.Instance.SetAttribute(a); } foreach (var a in multipleAttributes) { - BlankSpan.Instance.SetAttribute(a.Key, a.Value); + BlankSpan.Instance.SetAttribute(a); } BlankSpan.Instance.AddEvent("MyEvent"); @@ -68,8 +68,8 @@ public void BadArguments() Assert.Throws(() => BlankSpan.Instance.Status = null); Assert.Throws(() => BlankSpan.Instance.UpdateName(null)); Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, string.Empty)); - Assert.Throws(() => BlankSpan.Instance.SetAttribute(string.Empty, (IAttributeValue)null)); - Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, AttributeValue.StringAttributeValue("foo"))); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(string.Empty, null)); + Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, "foo")); Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, 1L)); Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, 0.1d)); Assert.Throws(() => BlankSpan.Instance.SetAttribute(null, true)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs index 9d2b4dfe0eb..c3d82946f4d 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs @@ -40,7 +40,7 @@ public void FromDescription() [Fact] public void FromDescriptionAndAttributes_NullDescription() { - Assert.Throws(() => Event.Create(null, new Dictionary())); + Assert.Throws(() => Event.Create(null, new Dictionary())); } [Fact] @@ -52,9 +52,9 @@ public void FromDescriptionAndAttributes_NullAttributes() [Fact] public void FromDescriptionAndAttributes() { - var attributes = new Dictionary(); + var attributes = new Dictionary(); attributes.Add( - "MyStringAttributeKey", AttributeValue.Create("MyStringAttributeValue")); + "MyStringAttributeKey", "MyStringAttributeValue"); var @event = Event.Create("MyEventText", attributes); Assert.Equal("MyEventText", @event.Name); Assert.Equal(attributes, @event.Attributes); @@ -65,7 +65,7 @@ public void FromDescriptionAndAttributes_EmptyAttributes() { var @event = Event.Create( - "MyEventText", new Dictionary()); + "MyEventText", new Dictionary()); Assert.Equal("MyEventText", @event.Name); Assert.Equal(0, @event.Attributes.Count); } @@ -94,9 +94,9 @@ public void Event_ToString() { var @event = Event.Create("MyEventText"); Assert.Contains("MyEventText", @event.ToString()); - var attributes = new Dictionary(); + var attributes = new Dictionary(); attributes.Add( - "MyStringAttributeKey", AttributeValue.Create("MyStringAttributeValue")); + "MyStringAttributeKey", "MyStringAttributeValue"); @event = Event.Create("MyEventText2", attributes); Assert.Contains("MyEventText2", @event.ToString()); Assert.Contains(Collections.ToString(attributes), @event.ToString()); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index 7023dfacd19..c47eab4bf66 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -39,7 +39,7 @@ public class SpanDataTest private readonly SpanContext spanContext; private readonly ActivitySpanId parentSpanId; private readonly Resource resource = Resource.Empty; - private readonly IDictionary attributesMap = new Dictionary(); + private readonly IDictionary attributesMap = new Dictionary(); private readonly List> eventList = new List>(); private readonly List linksList = new List(); @@ -134,7 +134,7 @@ public void SpanData_AllDataEmpty() resource, SPAN_NAME, startTimestamp, - Attributes.Create(new Dictionary(), 0), + Attributes.Create(new Dictionary(), 0), TimedEvents.Create(new List>(), 0), LinkList.Create(new List(), 0), 0, @@ -193,7 +193,7 @@ public void SpanDataEquals() resource, SPAN_NAME, startTimestamp, - Attributes.Create(new Dictionary(), 0), + Attributes.Create(new Dictionary(), 0), TimedEvents.Create(new List>(), 0), LinkList.Create(new List(), 0), 0, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index a27dad9cf1e..303becfded1 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Trace.Test public class LinkTest { - private readonly IDictionary attributesMap = new Dictionary(); + private readonly IDictionary attributesMap = new Dictionary(); private readonly SpanContext spanContext; diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs index a10eb193def..25bc1ed09e5 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs @@ -75,7 +75,7 @@ public void TraceContextFormat_IsBlankIfInvalid() { var headers = new Dictionary { - {"traceparent", "00-xyz7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"} + { "traceparent", "00-xyz7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01" }, }; var f = new TraceContextFormat(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index fe2e3e4761a..91d4e0175b1 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -40,8 +40,8 @@ public class SpanTest private readonly Timer timestampConverter; private readonly SpanOptions noRecordSpanOptions = SpanOptions.None; private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; - private readonly IDictionary attributes = new Dictionary(); - private readonly IDictionary expectedAttributes; + private readonly IDictionary attributes = new Dictionary(); + private readonly IDictionary expectedAttributes; private readonly IStartEndHandler startEndHandler = Mock.Of(); public SpanTest() @@ -55,10 +55,10 @@ public SpanTest() "MyStringAttributeKey", AttributeValue.StringAttributeValue("MyStringAttributeValue")); attributes.Add("MyLongAttributeKey", AttributeValue.LongAttributeValue(123L)); attributes.Add("MyBooleanAttributeKey", AttributeValue.BooleanAttributeValue(false)); - expectedAttributes = new Dictionary(attributes); + expectedAttributes = new Dictionary(attributes); expectedAttributes.Add( "MySingleStringAttributeKey", - AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); + "MySingleStringAttributeValue"); } [Fact] @@ -77,7 +77,7 @@ public void ToSpanData_NoRecordEvents() // Check that adding trace events after Span#End() does not throw any exception. foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } span.AddEvent(Event.Create(EventDescription)); @@ -106,12 +106,12 @@ public void NoEventsRecordedAfterEnd() // recorded. foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } span.SetAttribute( "MySingleStringAttributeKey", - AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); + "MySingleStringAttributeValue"); span.AddEvent(Event.Create(EventDescription)); span.AddEvent(EventDescription, attributes); span.AddLink(Link.FromSpanContext(spanContext)); @@ -140,10 +140,10 @@ public void ToSpanData_ActiveSpan() span.SetAttribute( "MySingleStringAttributeKey", - AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); + "MySingleStringAttributeValue"); foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } interval = TimeSpan.FromMilliseconds(100); @@ -195,10 +195,10 @@ public void GoSpanData_EndedSpan() span.SetAttribute( "MySingleStringAttributeKey", - AttributeValue.StringAttributeValue("MySingleStringAttributeValue")); + "MySingleStringAttributeValue"); foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } interval = TimeSpan.FromMilliseconds(100); @@ -305,11 +305,11 @@ public void DroppingAttributes() timestampConverter); for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { - IDictionary attributes = new Dictionary(); - attributes.Add("MyStringAttributeKey" + i, AttributeValue.LongAttributeValue(i)); + IDictionary attributes = new Dictionary(); + attributes.Add("MyStringAttributeKey" + i, i); foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } } @@ -320,7 +320,7 @@ public void DroppingAttributes() for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( - AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), + i + maxNumberOfAttributes, spanData .Attributes .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); @@ -333,7 +333,7 @@ public void DroppingAttributes() for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( - AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), + i + maxNumberOfAttributes, spanData .Attributes .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); @@ -358,11 +358,11 @@ public void DroppingAndAddingAttributes() timestampConverter); for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { - IDictionary attributes = new Dictionary(); - attributes.Add("MyStringAttributeKey" + i, AttributeValue.LongAttributeValue(i)); + IDictionary attributes = new Dictionary(); + attributes.Add("MyStringAttributeKey" + i, i); foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } } @@ -373,7 +373,7 @@ public void DroppingAndAddingAttributes() for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( - AttributeValue.LongAttributeValue(i + maxNumberOfAttributes), + i + maxNumberOfAttributes, spanData .Attributes .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); @@ -381,11 +381,11 @@ public void DroppingAndAddingAttributes() for (var i = 0; i < maxNumberOfAttributes / 2; i++) { - IDictionary attributes = new Dictionary(); - attributes.Add("MyStringAttributeKey" + i, AttributeValue.LongAttributeValue(i)); + IDictionary attributes = new Dictionary(); + attributes.Add("MyStringAttributeKey" + i, i); foreach (var attribute in attributes) { - span.SetAttribute(attribute.Key, attribute.Value); + span.SetAttribute(attribute); } } @@ -397,7 +397,7 @@ public void DroppingAndAddingAttributes() for (var i = 0; i < maxNumberOfAttributes / 2; i++) { Assert.Equal( - AttributeValue.LongAttributeValue(i + maxNumberOfAttributes * 3 / 2), + i + maxNumberOfAttributes * 3 / 2, spanData .Attributes .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2)]); @@ -406,7 +406,7 @@ public void DroppingAndAddingAttributes() // Test that we have the newest re-added initial entries. for (var i = 0; i < maxNumberOfAttributes / 2; i++) { - Assert.Equal(AttributeValue.LongAttributeValue(i), + Assert.Equal(i, spanData.Attributes.AttributeMap["MyStringAttributeKey" + i]); } } @@ -574,9 +574,9 @@ public void BadArguments() Assert.Throws(() => span.Status = null); Assert.Throws(() => span.UpdateName(null)); Assert.Throws(() => span.SetAttribute(null, string.Empty)); - Assert.Throws(() => span.SetAttribute(string.Empty, (IAttributeValue)null)); + Assert.Throws(() => span.SetAttribute(string.Empty, null)); Assert.Throws(() => - span.SetAttribute(null, AttributeValue.StringAttributeValue("foo"))); + span.SetAttribute(null, "foo")); Assert.Throws(() => span.SetAttribute(null, 1L)); Assert.Throws(() => span.SetAttribute(null, 0.1d)); Assert.Throws(() => span.SetAttribute(null, true)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs b/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs index 9fbcd9ba9ad..54780325f5f 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TestSpan.cs @@ -34,7 +34,7 @@ public void UpdateName(string name) throw new NotImplementedException(); } - public void SetAttribute(string key, IAttributeValue value) + public void SetAttribute(KeyValuePair keyValuePair) { } @@ -58,7 +58,7 @@ public void AddEvent(string name) { } - public void AddEvent(string name, IDictionary attributes) + public void AddEvent(string name, IDictionary attributes) { } From c5f33e1742831c9f5b1dd048bfddc4314a46469d Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 12 Jul 2019 18:31:21 -0700 Subject: [PATCH 15/41] Support .NET Activities (#140) * StartSpanWithActivity * Sampler builder tests * cleanup start span * span tests * optimize tracestate * public tracestate parsing * more tracestate tests * Scopes and scope tests * minor merge issues * Do not make Span's Activity Current until WithSpan is called * CurrentSpanUtils to static * Tracestate parsing is not public API, reuse code without exposing it * more tests and fixes * rename * rename FromCurrentActivity to SetCreateChild * fix rebase issues * fix build warning * undo separate test project for Abstractions.Tests to fix build * up --- .../Context/Propagation/TraceContextFormat.cs | 155 ++----- .../Context/Propagation/TracestateUtils.cs | 115 +++++ .../OpenTelemetry.Abstractions.csproj | 1 + .../Trace/ISpanBuilder.cs | 29 +- src/OpenTelemetry.Abstractions/Trace/Link.cs | 21 + .../Trace/NoopSpanBuilder.cs | 56 ++- .../Trace/TraceState.cs | 37 +- src/OpenTelemetry/OpenTelemetry.csproj | 4 + src/OpenTelemetry/Trace/CurrentSpanUtils.cs | 80 +++- src/OpenTelemetry/Trace/Span.cs | 51 ++- src/OpenTelemetry/Trace/SpanBuilder.cs | 279 +++++++++--- src/OpenTelemetry/Trace/Tracer.cs | 4 +- ...elemetry.Collector.AspNetCore.Tests.csproj | 2 +- .../Impl/Trace/CurrentSpanUtilsTest.cs | 263 +++++++++++- .../Impl/Trace/EventTest.cs | 3 +- .../Export/InProcessRunningSpanStoreTest.cs | 19 +- .../Export/InProcessSampledSpanStoreTest.cs | 120 +++--- .../Impl/Trace/Export/SpanExporterTest.cs | 62 +-- .../Impl/Trace/LinkTest.cs | 50 +-- .../Impl/Trace/NoopSpanBuilderTests.cs | 17 +- .../Trace/Propagation/TraceContextTest.cs | 75 +++- .../Trace/Propagation/TracestateUtilsTests.cs | 90 ++++ .../Impl/Trace/SpanBuilderTest.cs | 401 +++++++++++++++++- .../Impl/Trace/SpanTest.cs | 282 +++++++++--- 24 files changed, 1812 insertions(+), 404 deletions(-) create mode 100644 src/OpenTelemetry.Abstractions/Context/Propagation/TracestateUtils.cs create mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Propagation/TracestateUtilsTests.cs diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs index bd56c1a817d..ee43407447e 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/TraceContextFormat.cs @@ -20,9 +20,8 @@ namespace OpenTelemetry.Context.Propagation using System.Collections.Generic; using System.Diagnostics; using System.Linq; - using System.Text; + using OpenTelemetry.Abstractions.Context.Propagation; using OpenTelemetry.Trace; - using OpenTelemetry.Utils; /// /// W3C trace context text wire protocol formatter. See https://github.com/w3c/distributed-tracing/. @@ -63,97 +62,13 @@ public SpanContext Extract(T carrier, Func> ge return SpanContext.Blank; } - var tracestateResult = Tracestate.Empty; - try + var tracestate = Tracestate.Empty; + if (tracestateCollection != null) { - var entries = new List>(); - var names = new HashSet(); - var discardTracestate = false; - if (tracestateCollection != null) - { - foreach (var tracestate in tracestateCollection) - { - if (string.IsNullOrWhiteSpace(tracestate)) - { - continue; - } - - // tracestate: rojo=00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01,congo=BleGNlZWRzIHRohbCBwbGVhc3VyZS4 - var keyStartIdx = 0; - var length = tracestate.Length; - while (keyStartIdx < length) - { - // first skip any prefix commas and OWS - var c = tracestate[keyStartIdx]; - while (c == ' ' || c == '\t' || c == ',') - { - keyStartIdx++; - if (keyStartIdx == length) - { - break; - } - - c = tracestate[keyStartIdx]; - } - - if (keyStartIdx == length) - { - break; - } - - var keyEndIdx = tracestate.IndexOf("=", keyStartIdx); - - if (keyEndIdx == -1) - { - discardTracestate = true; - break; - } - - var valueStartIdx = keyEndIdx + 1; - - var valueEndIdx = tracestate.IndexOf(",", valueStartIdx); - valueEndIdx = valueEndIdx == -1 ? length : valueEndIdx; - - // this will throw for duplicated keys - var key = tracestate.Substring(keyStartIdx, keyEndIdx - keyStartIdx).TrimStart(); - if (names.Add(key)) - { - entries.Add( - new KeyValuePair( - key, - tracestate.Substring(valueStartIdx, valueEndIdx - valueStartIdx).TrimEnd())); - } - else - { - discardTracestate = true; - break; - } - - keyStartIdx = valueEndIdx + 1; - } - } - } - - if (!discardTracestate) - { - var tracestateBuilder = Tracestate.Builder; - - entries.Reverse(); - foreach (var entry in entries) - { - tracestateBuilder.Set(entry.Key, entry.Value); - } - - tracestateResult = tracestateBuilder.Build(); - } - } - catch (Exception) - { - // failure to parse tracestate should not disregard traceparent - // TODO: logging + this.TryExtractTracestate(tracestateCollection.ToArray(), out tracestate); } - return SpanContext.Create(traceId, spanId, traceoptions, tracestateResult); + return SpanContext.Create(traceId, spanId, traceoptions, tracestate); } catch (Exception) { @@ -172,26 +87,10 @@ public void Inject(SpanContext spanContext, T carrier, Action(); + if (tracestateCollection != null) + { + // Iterate in reverse order because when call builder set the elements is added in the + // front of the list. + for (int i = tracestateCollection.Length - 1; i >= 0; i--) + { + if (!TracestateUtils.TryExtractTracestate(tracestateCollection[i], tracestateBuilder)) + { + return false; + } + } + } + + tracestateResult = tracestateBuilder.Build(); + return true; + } + catch (Exception) + { + // failure to parse tracestate should not disregard traceparent + // TODO: logging + } + + return false; + } } } diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/TracestateUtils.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/TracestateUtils.cs new file mode 100644 index 00000000000..9462e5e2c60 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/TracestateUtils.cs @@ -0,0 +1,115 @@ +// +// 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. +// + +#if ABSTRACTIONS +namespace OpenTelemetry.Abstractions.Context.Propagation +#else +namespace OpenTelemetry.Context.Propagation +#endif +{ + using System; + using System.Collections.Generic; + using OpenTelemetry.Trace; + + /// + /// Extension methods to extract Tracestate from string. + /// + internal static class TracestateUtils + { + /// + /// Extracts from the given string and sets it on provided . + /// + /// String with comma separated tracestate key value pairs. + /// to set tracestate pairs on. + /// True if string was parsed successfully and tracestate was recognized, false otherwise. + internal static bool TryExtractTracestate(string tracestateString, Tracestate.TracestateBuilder tracestateBuilder) + { + if (string.IsNullOrWhiteSpace(tracestateString)) + { + return true; + } + + try + { + var names = new HashSet(); + + var tracestate = tracestateString.AsSpan().Trim(' ').Trim(','); + do + { + // tracestate: rojo=00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01,congo=BleGNlZWRzIHRohbCBwbGVhc3VyZS4 + + // Iterate in reverse order because when call builder set the elements is added in the + // front of the list. + int pairStart = tracestate.LastIndexOf(',') + 1; + + if (!TryParseKeyValue(tracestate.Slice(pairStart, tracestate.Length - pairStart), out var key, out var value)) + { + return false; + } + + var keyStr = key.ToString(); + if (names.Add(keyStr)) + { + tracestateBuilder.Set(keyStr, value.ToString()); + } + else + { + return false; + } + + if (pairStart == 0) + { + break; + } + + tracestate = tracestate.Slice(0, pairStart - 1); + } + while (tracestate.Length > 0); + + return true; + } + catch (Exception) + { + // failure to parse tracestate + // TODO: logging + } + + return false; + } + + private static bool TryParseKeyValue(ReadOnlySpan pair, out ReadOnlySpan key, out ReadOnlySpan value) + { + key = default; + value = default; + + var keyEndIdx = pair.IndexOf('='); + if (keyEndIdx <= 0) + { + return false; + } + + var valueStartIdx = keyEndIdx + 1; + if (valueStartIdx >= pair.Length) + { + return false; + } + + key = pair.Slice(0, keyEndIdx).Trim(); + value = pair.Slice(valueStartIdx, pair.Length - valueStartIdx).Trim(); + return true; + } + } +} diff --git a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj index d8b5a12eacf..01a0b6200f1 100644 --- a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj +++ b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj @@ -4,6 +4,7 @@ netstandard2.0 OpenTelemetry .NET API abstractions OpenTelemetry + $(DefineConstants);ABSTRACTIONS diff --git a/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs index 75a77c108c5..337b0cc7a97 100644 --- a/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Trace/ISpanBuilder.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace { using System.Collections.Generic; + using System.Diagnostics; /// /// Span builder. @@ -38,6 +39,14 @@ public interface ISpanBuilder /// This span builder for chaining. ISpanBuilder SetParent(ISpan parent); + /// + /// Sets the to use as a parent for the new span. + /// Any parent that was set previously will be discarded. + /// + /// to set as parent. + /// This span builder for chaining. + ISpanBuilder SetParent(Activity parent); + /// /// Sets the remote to use as a parent for the new span. /// Any parent that was set previously will be discarded. @@ -53,6 +62,17 @@ public interface ISpanBuilder /// This span builder for chaining. ISpanBuilder SetNoParent(); + /// + /// Sets flag indicating that new span should become a child of implicit context (Activity.Current) + /// or continue run in this context and inherit it + /// Use this method with value 'false' in auto-collectors when library is instrumented with Activities. + /// Any parent that was set previously will be discarded. + /// + /// If true, a new span will become a child of the existing implicit context. + /// If false, new span will continue this context. + /// This span builder for chaining. + ISpanBuilder SetCreateChild(bool createChild); + /// /// Set on the span. /// @@ -63,10 +83,17 @@ public interface ISpanBuilder /// /// Set the on the span. /// - /// context to set on span. + /// context to set on span. /// This span builder for chaining. ISpanBuilder AddLink(SpanContext spanContext); + /// + /// Set the on the span. + /// + /// context to set on span. + /// This span builder for chaining. + ISpanBuilder AddLink(Activity activity); + /// /// Set the on the span. /// diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index d90bff1bb64..a9b0dd43a8a 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -19,7 +19,9 @@ namespace OpenTelemetry.Trace using System; using System.Collections.Generic; using System.Collections.ObjectModel; + using System.Diagnostics; using System.Linq; + using OpenTelemetry.Abstractions.Context.Propagation; using OpenTelemetry.Abstractions.Utils; /// @@ -39,6 +41,25 @@ private Link(SpanContext context, IDictionary attributes) /// public IDictionary Attributes { get; } + /// + /// Creates a from Activity. + /// + /// Activity to create link from. + /// New instance. + public static ILink FromActivity(Activity activity) + { + var tracestate = Tracestate.Empty; + var tracestateBuilder = Tracestate.Builder; + if (TracestateUtils.TryExtractTracestate(activity.TraceStateString, tracestateBuilder)) + { + tracestate = tracestateBuilder.Build(); + } + + return new Link( + SpanContext.Create(activity.TraceId, activity.SpanId, activity.ActivityTraceFlags, tracestate), + EmptyAttributes); + } + public static ILink FromSpanContext(SpanContext context) { return new Link(context, EmptyAttributes); diff --git a/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs b/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs index 370dac44f6c..95daee53d75 100644 --- a/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs +++ b/src/OpenTelemetry.Abstractions/Trace/NoopSpanBuilder.cs @@ -18,6 +18,7 @@ namespace OpenTelemetry.Trace { using System; using System.Collections.Generic; + using System.Diagnostics; /// /// No-op span builder. @@ -56,11 +57,22 @@ public ISpanBuilder SetSampler(ISampler sampler) } /// - public ISpanBuilder SetParent(ISpan parent) + public ISpanBuilder SetParent(ISpan parentSpan) { - if (parent == null) + if (parentSpan == null) { - throw new ArgumentNullException(nameof(parent)); + throw new ArgumentNullException(nameof(parentSpan)); + } + + return this; + } + + /// + public ISpanBuilder SetParent(Activity parentActivity) + { + if (parentActivity == null) + { + throw new ArgumentNullException(nameof(parentActivity)); } return this; @@ -83,6 +95,33 @@ public ISpanBuilder SetNoParent() return this; } + /// + public ISpanBuilder SetCreateChild(bool createChild) + { + if (!createChild) + { + var currentActivity = Activity.Current; + + if (currentActivity == null) + { + throw new ArgumentException("Current Activity cannot be null"); + } + + if (currentActivity.IdFormat != ActivityIdFormat.W3C) + { + throw new ArgumentException("Current Activity is not in W3C format"); + } + + if (currentActivity.StartTimeUtc == default || currentActivity.Duration != default) + { + throw new ArgumentException( + "Current Activity is not running: it has not been started or has been stopped"); + } + } + + return this; + } + /// public ISpanBuilder SetSpanKind(SpanKind spanKind) { @@ -100,6 +139,17 @@ public ISpanBuilder AddLink(SpanContext spanContext) return this; } + /// + public ISpanBuilder AddLink(Activity activity) + { + if (activity == null) + { + throw new ArgumentNullException(nameof(activity)); + } + + return this; + } + /// public ISpanBuilder AddLink(ILink link) { diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceState.cs b/src/OpenTelemetry.Abstractions/Trace/TraceState.cs index b49ad271097..80edfe792d5 100644 --- a/src/OpenTelemetry.Abstractions/Trace/TraceState.cs +++ b/src/OpenTelemetry.Abstractions/Trace/TraceState.cs @@ -19,6 +19,7 @@ namespace OpenTelemetry.Trace using System; using System.Collections.Generic; using System.Linq; + using System.Text; /// /// Tracestate entries allowing different vendors to participate in a trace. @@ -89,6 +90,35 @@ public TracestateBuilder ToBuilder() return new TracestateBuilder(this); } + /// + public override string ToString() + { + if (this.Entries.Any()) + { + var sb = new StringBuilder(); + + var isFirst = true; + + foreach (var entry in this.Entries) + { + if (isFirst) + { + isFirst = false; + } + else + { + sb.Append(","); + } + + sb.Append(entry.Key).Append("=").Append(entry.Value); + } + + return sb.ToString(); + } + + return string.Empty; + } + private static bool ValidateKey(string key) { // Key is opaque string up to 256 characters printable. It MUST begin with a lowercase letter, and @@ -189,7 +219,6 @@ private static bool ValidateValue(string value) private static Tracestate Create(ICollection entries) { // TODO: discard last entries instead of throwing - if (entries.Count > MaxKeyValuePairsCount) { throw new ArgumentException("Too many entries.", nameof(entries)); @@ -273,8 +302,12 @@ internal TracestateBuilder(Tracestate parent) /// Tracestate builder for chained calls. public TracestateBuilder Set(string key, string value) { - // Initially create the Entry to validate input. + if (this.entries != null && this.entries.Count > MaxKeyValuePairsCount) + { + throw new ArgumentException("Too many entries."); + } + // Initially create the Entry to validate input. var entry = Entry.Create(key, value); if (this.entries == null) diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index 85f9a5507b6..0545bfff9d6 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -9,6 +9,10 @@ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'OpenTelemetry.sln'))/build/OpenTelemetry.prod.loose.ruleset + + + + diff --git a/src/OpenTelemetry/Trace/CurrentSpanUtils.cs b/src/OpenTelemetry/Trace/CurrentSpanUtils.cs index 7bfcae89b0c..b3e1b212bde 100644 --- a/src/OpenTelemetry/Trace/CurrentSpanUtils.cs +++ b/src/OpenTelemetry/Trace/CurrentSpanUtils.cs @@ -16,24 +16,62 @@ namespace OpenTelemetry.Trace { - using System.Threading; + using System.Diagnostics; + using System.Runtime.CompilerServices; using OpenTelemetry.Context; - using OpenTelemetry.Trace.Internal; internal static class CurrentSpanUtils { - private static readonly AsyncLocal AsyncLocalContext = new AsyncLocal(); + private static readonly ConditionalWeakTable ActivitySpanTable = new ConditionalWeakTable(); - public static ISpan CurrentSpan => AsyncLocalContext.Value; + public static ISpan CurrentSpan + { + get + { + var currentActivity = Activity.Current; + if (currentActivity == null) + { + return BlankSpan.Instance; + } + + if (ActivitySpanTable.TryGetValue(currentActivity, out var currentSpan)) + { + return currentSpan; + } + + return BlankSpan.Instance; + } + } public static IScope WithSpan(ISpan span, bool endSpan) { return new ScopeInSpan(span, endSpan); } + private static void SetSpan(Span span) + { + if (span.Activity == null) + { + // log error + return; + } + + if (ActivitySpanTable.TryGetValue(span.Activity, out _)) + { + // log warning + return; + } + + ActivitySpanTable.Add(span.Activity, span); + } + + private static void DetachSpanFromActivity(Activity activity) + { + ActivitySpanTable.Remove(activity); + } + private sealed class ScopeInSpan : IScope { - private readonly ISpan origContext; private readonly ISpan span; private readonly bool endSpan; @@ -41,24 +79,42 @@ public ScopeInSpan(ISpan span, bool endSpan) { this.span = span; this.endSpan = endSpan; - this.origContext = AsyncLocalContext.Value; - AsyncLocalContext.Value = span; + + if (span is Span spanImpl) + { + if (spanImpl.OwnsActivity) + { + Activity.Current = spanImpl.Activity; + } + + SetSpan(spanImpl); + } } public void Dispose() { - var current = AsyncLocalContext.Value; - AsyncLocalContext.Value = this.origContext; - - if (current != this.origContext) + bool safeToStopActivity = false; + var current = (Span)this.span; + if (current != null && current.Activity == Activity.Current) { - // Log + if (!current.OwnsActivity) + { + DetachSpanFromActivity(current.Activity); + } + else + { + safeToStopActivity = true; + } } if (this.endSpan) { this.span.End(); } + else if (safeToStopActivity) + { + current.Activity.Stop(); + } } } } diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index 485387ba899..d689a000da0 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -31,7 +31,6 @@ namespace OpenTelemetry.Trace /// public sealed class Span : ISpan, IElement { - private readonly ActivitySpanId parentSpanId; private readonly ITraceParams traceParams; private readonly IStartEndHandler startEndHandler; private readonly DateTimeOffset startTime; @@ -43,20 +42,26 @@ public sealed class Span : ISpan, IElement private DateTimeOffset endTime; private bool hasBeenEnded; private bool sampleToLocalSpanStore; + private Lazy spanContext; private Span( - SpanContext context, + Activity activity, + Tracestate tracestate, SpanOptions options, string name, SpanKind spanKind, - ActivitySpanId parentSpanId, ITraceParams traceParams, IStartEndHandler startEndHandler, - Timer timestampConverter) + Timer timestampConverter, + bool stopActivity) { - this.Context = context; + this.Activity = activity; + this.spanContext = new Lazy(() => SpanContext.Create( + this.Activity.TraceId, + this.Activity.SpanId, + this.Activity.ActivityTraceFlags, + tracestate)); this.Options = options; - this.parentSpanId = parentSpanId; this.Name = name; this.traceParams = traceParams ?? throw new ArgumentNullException(nameof(traceParams)); this.startEndHandler = startEndHandler; @@ -81,9 +86,13 @@ private Span( this.startTime = DateTimeOffset.MinValue; this.TimestampConverter = timestampConverter; } + + this.OwnsActivity = stopActivity; } - public SpanContext Context { get; } + public Activity Activity { get; } + + public SpanContext Context => this.spanContext.Value; public SpanOptions Options { get; } @@ -172,7 +181,7 @@ public bool IsSampleToLocalSpanStore } } - public ActivitySpanId ParentSpanId => this.parentSpanId; + public ActivitySpanId ParentSpanId => this.Activity.ParentSpanId; public bool HasEnded => this.hasBeenEnded; @@ -184,6 +193,8 @@ public bool IsSampleToLocalSpanStore /// internal SpanKind? Kind { get; set; } + internal bool OwnsActivity { get; } + internal Timer TimestampConverter { get; private set; } private AttributesWithCapacity InitializedAttributes @@ -377,6 +388,12 @@ public void AddLink(ILink link) /// public void End() { + if (this.OwnsActivity && this.Activity == Activity.Current) + { + // TODO log if current is not span activity + this.Activity.Stop(); + } + if (!this.IsRecordingEvents) { return; @@ -411,8 +428,8 @@ public SpanData ToSpanData() var linksSpanData = this.links == null ? LinkList.Create(new List(), 0) : LinkList.Create(this.links.Events, this.links.NumberOfDroppedEvents); return SpanData.Create( - this.Context, - this.parentSpanId, + this.Context, // TODO avoid using context, use Activity instead + this.ParentSpanId, Resource.Empty, // TODO: determine what to do with Resource in this context this.Name, Timestamp.FromDateTimeOffset(this.startTime), @@ -495,24 +512,26 @@ public void SetAttribute(string key, bool value) } internal static ISpan StartSpan( - SpanContext context, + Activity activity, + Tracestate tracestate, SpanOptions options, string name, SpanKind spanKind, - ActivitySpanId parentSpanId, ITraceParams traceParams, IStartEndHandler startEndHandler, - Timer timestampConverter) + Timer timestampConverter, + bool ownsActivity = true) { var span = new Span( - context, + activity, + tracestate, options, name, spanKind, - parentSpanId, traceParams, startEndHandler, - timestampConverter); + timestampConverter, + ownsActivity); // Call onStart here instead of calling in the constructor to make sure the span is completely // initialized. diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index edc979541a6..9fe0fb8035c 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -19,6 +19,7 @@ namespace OpenTelemetry.Trace using System; using System.Collections.Generic; using System.Diagnostics; + using OpenTelemetry.Context.Propagation; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; @@ -29,9 +30,11 @@ public class SpanBuilder : ISpanBuilder private readonly string name; private SpanKind kind; - private ISpan parent; + private ISpan parentSpan; + private Activity parentActivity; + private Activity fromActivity; private SpanContext parentSpanContext; - private ParentType parentType = ParentType.CurrentSpan; + private ContextSource contextSource = ContextSource.CurrentActivityParent; private ISampler sampler; private List links; private bool recordEvents; @@ -39,14 +42,20 @@ public class SpanBuilder : ISpanBuilder internal SpanBuilder(string name, SpanBuilderOptions options) { + // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + Activity.ForceDefaultIdFormat = true; + this.name = name ?? throw new ArgumentNullException(nameof(name)); - this.options = options; + this.options = options ?? throw new ArgumentNullException(nameof(options)); } - private enum ParentType + private enum ContextSource { - CurrentSpan, - ExplicitParent, + CurrentActivityParent, + Activity, + ExplicitActivityParent, + ExplicitSpanParent, ExplicitRemoteParent, NoParent, } @@ -59,12 +68,27 @@ public ISpanBuilder SetSampler(ISampler sampler) } /// - public ISpanBuilder SetParent(ISpan parent) + public ISpanBuilder SetParent(ISpan parentSpan) + { + this.parentSpan = parentSpan ?? throw new ArgumentNullException(nameof(parentSpan)); + this.contextSource = ContextSource.ExplicitSpanParent; + if (parentSpan is Span parentSpanImpl) + { + this.timestampConverter = parentSpanImpl.TimestampConverter; + } + + this.parentSpanContext = null; + this.parentActivity = null; + return this; + } + + /// + public ISpanBuilder SetParent(Activity parentActivity) { - this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); - this.parentType = ParentType.ExplicitParent; - this.timestampConverter = ((Span)parent)?.TimestampConverter; + this.parentActivity = parentActivity ?? throw new ArgumentNullException(nameof(parentActivity)); + this.contextSource = ContextSource.ExplicitActivityParent; this.parentSpanContext = null; + this.parentSpan = null; return this; } @@ -72,17 +96,56 @@ public ISpanBuilder SetParent(ISpan parent) public ISpanBuilder SetParent(SpanContext remoteParent) { this.parentSpanContext = remoteParent ?? throw new ArgumentNullException(nameof(remoteParent)); - this.parent = null; - this.parentType = ParentType.ExplicitRemoteParent; + this.parentSpan = null; + this.parentActivity = null; + this.contextSource = ContextSource.ExplicitRemoteParent; return this; } /// public ISpanBuilder SetNoParent() { - this.parentType = ParentType.NoParent; + this.contextSource = ContextSource.NoParent; + this.parentSpanContext = null; + this.parentSpanContext = null; + this.parentActivity = null; + return this; + } + + /// + public ISpanBuilder SetCreateChild(bool createChild) + { + if (!createChild) + { + var currentActivity = Activity.Current; + + if (currentActivity == null) + { + throw new ArgumentException("Current Activity cannot be null"); + } + + if (currentActivity.IdFormat != ActivityIdFormat.W3C) + { + throw new ArgumentException("Current Activity is not in W3C format"); + } + + if (currentActivity.StartTimeUtc == default || currentActivity.Duration != default) + { + throw new ArgumentException( + "Current Activity is not running: it has not been started or has been stopped"); + } + + this.fromActivity = currentActivity; + this.contextSource = ContextSource.Activity; + } + else + { + this.contextSource = ContextSource.CurrentActivityParent; + } + this.parentSpanContext = null; this.parentSpanContext = null; + this.parentActivity = null; return this; } @@ -138,6 +201,17 @@ public ISpanBuilder AddLink(ILink link) return this; } + /// + public ISpanBuilder AddLink(Activity activity) + { + if (activity == null) + { + throw new ArgumentNullException(nameof(activity)); + } + + return this.AddLink(Link.FromActivity(activity)); + } + /// public ISpanBuilder SetRecordEvents(bool recordEvents) { @@ -148,56 +222,47 @@ public ISpanBuilder SetRecordEvents(bool recordEvents) /// public ISpan StartSpan() { - SpanContext parentContext = FindParent(this.parentType, this.parent, this.parentSpanContext); + var activityForSpan = this.CreateActivityForSpan(this.contextSource, this.parentSpan, + this.parentSpanContext, this.parentActivity, this.fromActivity); var activeTraceParams = this.options.TraceConfig.ActiveTraceParams; - ActivityTraceId traceId; - var spanId = ActivitySpanId.CreateRandom(); - - ActivitySpanId parentSpanId = default; - ActivityTraceFlags traceOptions = ActivityTraceFlags.None; - - if (parentContext == null || !parentContext.IsValid) - { - // New root span. - traceId = ActivityTraceId.CreateRandom(); - } - else - { - // New child span. - traceId = parentContext.TraceId; - parentSpanId = parentContext.SpanId; - traceOptions = parentContext.TraceOptions; - } bool sampledIn = MakeSamplingDecision( - parentContext, - this.name, - this.sampler, - this.links, - traceId, - spanId, - activeTraceParams); + this.parentSpanContext, // it is updated in CreateActivityForSpan + this.name, + this.sampler, + this.links, + activityForSpan.TraceId, + activityForSpan.SpanId, + activeTraceParams); var spanOptions = SpanOptions.None; if (sampledIn || this.recordEvents) { - traceOptions |= ActivityTraceFlags.Recorded; + activityForSpan.ActivityTraceFlags |= ActivityTraceFlags.Recorded; spanOptions = SpanOptions.RecordEvents; } else { - traceOptions &= ~ActivityTraceFlags.Recorded; + activityForSpan.ActivityTraceFlags &= ~ActivityTraceFlags.Recorded; + } + + var childTracestate = Tracestate.Empty; + + if (this.parentSpanContext?.Tracestate != null && this.parentSpanContext.Tracestate != Tracestate.Empty) + { + childTracestate = this.parentSpanContext.Tracestate.ToBuilder().Build(); } var span = Span.StartSpan( - SpanContext.Create(traceId, spanId, traceOptions, parentContext?.Tracestate ?? Tracestate.Empty), + activityForSpan, + childTracestate, // it is updated in CreateActivityForSpan, spanOptions, this.name, this.kind, - parentSpanId, activeTraceParams, this.options.StartEndHandler, - this.timestampConverter); + this.timestampConverter, + ownsActivity: this.contextSource != ContextSource.Activity); LinkSpans(span, this.links); return span; } @@ -257,22 +322,124 @@ private static bool MakeSamplingDecision( return (parent.TraceOptions & ActivityTraceFlags.Recorded) != 0 || IsAnyParentLinkSampled(parentLinks); } - private static SpanContext FindParent(ParentType parentType, ISpan explicitParent, SpanContext remoteParent) + private static SpanContext ParentContextFromActivity(Activity activity) + { + var tracestate = Tracestate.Empty; + var tracestateBuilder = Tracestate.Builder; + if (TracestateUtils.TryExtractTracestate(activity.TraceStateString, tracestateBuilder)) + { + tracestate = tracestateBuilder.Build(); + } + + return SpanContext.Create( + activity.TraceId, + activity.ParentSpanId, + ActivityTraceFlags.Recorded, + tracestate); + } + + private Activity CreateActivityForSpan(ContextSource contextSource, ISpan explicitParent, SpanContext remoteParent, Activity explicitParentActivity, Activity fromActivity) { - switch (parentType) + Activity spanActivity = null; + Activity originalActivity = Activity.Current; + bool needRestoreOriginal = true; + + switch (contextSource) { - case ParentType.NoParent: - return null; - case ParentType.CurrentSpan: - ISpan currentSpan = CurrentSpanUtils.CurrentSpan; - return currentSpan?.Context; - case ParentType.ExplicitParent: - return explicitParent?.Context; - case ParentType.ExplicitRemoteParent: - return remoteParent; + case ContextSource.CurrentActivityParent: + { + // Activity will figure out its parent + spanActivity = new Activity(this.name).Start(); + + // chances are, Activity.Current has span attached + if (CurrentSpanUtils.CurrentSpan is Span currentSpan) + { + this.parentSpanContext = currentSpan.Context; + } + else + { + this.parentSpanContext = ParentContextFromActivity(spanActivity); + } + + break; + } + + case ContextSource.ExplicitActivityParent: + { + spanActivity = new Activity(this.name) + .SetParentId(this.parentActivity.TraceId, + this.parentActivity.SpanId, + this.parentActivity.ActivityTraceFlags) + .Start(); + spanActivity.TraceStateString = this.parentActivity.TraceStateString; + this.parentSpanContext = ParentContextFromActivity(spanActivity); + break; + } + + case ContextSource.NoParent: + { + // TODO fix after next DiagnosticSource preview comes out - this is a hack to force activity to become orphan + spanActivity = new Activity(this.name).SetParentId(" ").Start(); + this.parentSpanContext = null; + break; + } + + case ContextSource.Activity: + { + this.parentSpanContext = ParentContextFromActivity(this.fromActivity); + spanActivity = this.fromActivity; + needRestoreOriginal = false; + break; + } + + case ContextSource.ExplicitRemoteParent: + { + spanActivity = new Activity(this.name); + if (this.parentSpanContext.IsValid) + { + spanActivity.SetParentId(this.parentSpanContext.TraceId, + this.parentSpanContext.SpanId, + this.parentSpanContext.TraceOptions); + } + + spanActivity.TraceStateString = this.parentSpanContext.Tracestate.ToString(); + spanActivity.Start(); + + break; + } + + case ContextSource.ExplicitSpanParent: + { + spanActivity = new Activity(this.name); + if (this.parentSpan.Context.IsValid) + { + spanActivity.SetParentId(this.parentSpan.Context.TraceId, + this.parentSpan.Context.SpanId, + this.parentSpan.Context.TraceOptions); + } + + spanActivity.TraceStateString = this.parentSpan.Context.Tracestate.ToString(); + spanActivity.Start(); + + this.parentSpanContext = this.parentSpan.Context; + break; + } + default: - throw new ArgumentException($"Unknown parentType {parentType}"); + throw new ArgumentException($"Unknown parentType {contextSource}"); } + + if (needRestoreOriginal) + { + // Activity Start always puts Activity on top of Current stack + // in OpenTelemetry we ask users to enable implicit propagation by calling WithSpan + // it will set Current Activity and attach span to it. + // we need to work with .NET team to allow starting Activities without updating Current + // As a workaround here we are undoing updating Current + Activity.Current = originalActivity; + } + + return spanActivity; } } } diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 52db9ed05d8..2ef89662934 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -62,7 +62,7 @@ public Tracer(IStartEndHandler startEndHandler, ITraceConfig traceConfig, SpanEx } /// - public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan ?? BlankSpan.Instance; + public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan; /// public IBinaryFormat BinaryFormat { get; } @@ -89,7 +89,7 @@ public IScope WithSpan(ISpan span) throw new ArgumentNullException(nameof(span)); } - return CurrentSpanUtils.WithSpan(span, false); + return CurrentSpanUtils.WithSpan(span, true); } } } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj b/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj index 742ddbe114a..ac64a261c1b 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/OpenTelemetry.Collector.AspNetCore.Tests.csproj @@ -29,7 +29,7 @@ - + diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index c1ecfbc134e..f641cd00d1f 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -16,51 +16,268 @@ namespace OpenTelemetry.Trace.Test { + using System; using System.Diagnostics; using Moq; - using OpenTelemetry.Trace.Internal; + using OpenTelemetry.Trace.Config; using Xunit; - public class CurrentSpanUtilsTest + public class CurrentSpanUtilsTest: IDisposable { - private ISpan span; - private SpanContext spanContext; - private SpanOptions spanOptions; + private readonly IStartEndHandler startEndHandler = Mock.Of(); public CurrentSpanUtilsTest() { - spanContext = - SpanContext.Create( - ActivityTraceId.CreateRandom(), - ActivitySpanId.CreateRandom(), - ActivityTraceFlags.Recorded, - Tracestate.Empty); - - spanOptions = SpanOptions.RecordEvents; - var mockSpan = new Mock() { CallBase = true }; - span = mockSpan.Object; + // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + Activity.ForceDefaultIdFormat = true; } [Fact] public void CurrentSpan_WhenNoContext() { - Assert.Null(CurrentSpanUtils.CurrentSpan); + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); } [Fact] - public void WithSpan_CloseDetaches() + public void CurrentSpan_WhenNoSpanOnActivity() { - Assert.Null(CurrentSpanUtils.CurrentSpan); - var ws = CurrentSpanUtils.WithSpan(span, false); - try + var a = new Activity("foo").Start(); + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void WithSpan_CloseDetaches(bool stopSpan, bool recordEvents) + { + var activity = new Activity("foo").Start(); + var span = Span.StartSpan( + activity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "foo", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + using (CurrentSpanUtils.WithSpan(span, stopSpan)) + { + Assert.Same(activity, Activity.Current); + Assert.Same(span, CurrentSpanUtils.CurrentSpan); + } + + Assert.Equal(stopSpan & recordEvents, span.HasEnded); + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + Assert.Null(Activity.Current); + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void WithSpan_NotOwningActivity(bool stopSpan, bool recordEvents) + { + var activity = new Activity("foo").Start(); + var span = Span.StartSpan( + activity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "foo", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null, + false); + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + using (CurrentSpanUtils.WithSpan(span, stopSpan)) + { + Assert.Same(activity, Activity.Current); + Assert.Same(span, CurrentSpanUtils.CurrentSpan); + } + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + Assert.Equal(activity, Activity.Current); + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void WithSpan_NoopOnBrokenScope(bool stopSpan, bool recordEvents) + { + var parentActivity = new Activity("parent").Start(); + var parentSpan = Span.StartSpan( + parentActivity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "parent", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + var parentScope = CurrentSpanUtils.WithSpan(parentSpan, stopSpan); + + var childActivity = new Activity("child").Start(); + var childSpan = Span.StartSpan( + childActivity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "child", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + + var childScope = CurrentSpanUtils.WithSpan(childSpan, stopSpan); + + parentScope.Dispose(); + + Assert.Equal(stopSpan & recordEvents, parentSpan.HasEnded); + Assert.False(childSpan.HasEnded); + Assert.Same(childSpan, CurrentSpanUtils.CurrentSpan); + Assert.Equal(childActivity, Activity.Current); + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void WithSpan_RestoresParentScope(bool stopSpan, bool recordEvents) + { + var parentActivity = new Activity("parent").Start(); + var parentSpan = Span.StartSpan( + parentActivity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "parent", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + var parentScope = CurrentSpanUtils.WithSpan(parentSpan, stopSpan); + + var childActivity = new Activity("child").Start(); + var childSpan = Span.StartSpan( + childActivity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "child", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + + var childScope = CurrentSpanUtils.WithSpan(childSpan, stopSpan); + + childScope.Dispose(); + + Assert.Equal(stopSpan & recordEvents, childSpan.HasEnded); + Assert.False(parentSpan.HasEnded); + + Assert.Same(parentSpan, CurrentSpanUtils.CurrentSpan); + Assert.Equal(parentActivity, Activity.Current); + } + + [Fact] + public void WithSpan_SameActivityCreateScopeTwice() + { + var activity = new Activity("foo").Start(); + var span = Span.StartSpan( + activity, + Tracestate.Empty, + SpanOptions.RecordEvents, + "foo", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + + using (CurrentSpanUtils.WithSpan(span, true)) + using(CurrentSpanUtils.WithSpan(span, true)) { + Assert.Same(activity, Activity.Current); Assert.Same(span, CurrentSpanUtils.CurrentSpan); } - finally + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + Assert.Null(Activity.Current); + } + + [Fact] + public void WithSpan_NullActivity() + { + var activity = new Activity("foo").Start(); + var span = Span.StartSpan( + activity, + Tracestate.Empty, + SpanOptions.RecordEvents, + "foo", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + + activity.Stop(); + + using (CurrentSpanUtils.WithSpan(span, true)) + { + Assert.Null(Activity.Current); + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + } + + Assert.Null(Activity.Current); + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void WithSpan_WrongActivity(bool stopSpan, bool recordEvents) + { + var activity = new Activity("foo").Start(); + var span = Span.StartSpan( + activity, + Tracestate.Empty, + recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, + "foo", + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + null); + + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + using (CurrentSpanUtils.WithSpan(span, stopSpan)) { - ws.Dispose(); + Assert.Same(activity, Activity.Current); + Assert.Same(span, CurrentSpanUtils.CurrentSpan); + + var anotherActivity = new Activity("foo").Start(); } - Assert.Null(CurrentSpanUtils.CurrentSpan); + + Assert.Equal(stopSpan & recordEvents, span.HasEnded); + Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); + Assert.NotSame(activity, Activity.Current); + Assert.NotNull(Activity.Current); + } + + public void Dispose() + { + Activity.Current = null; } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs index c3d82946f4d..75d3ede8cbd 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/EventTest.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace.Test { using System; + using System.Linq; using System.Collections.Generic; using OpenTelemetry.Utils; using Xunit; @@ -99,7 +100,7 @@ public void Event_ToString() "MyStringAttributeKey", "MyStringAttributeValue"); @event = Event.Create("MyEventText2", attributes); Assert.Contains("MyEventText2", @event.ToString()); - Assert.Contains(Collections.ToString(attributes), @event.ToString()); + Assert.Contains(string.Join(",", attributes.Select(kvp => $"{kvp.Key}={kvp.Value}")), @event.ToString()); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs index fef31b33af6..3adeb8b9114 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using System; + namespace OpenTelemetry.Trace.Export.Test { using System.Diagnostics; @@ -23,7 +25,7 @@ namespace OpenTelemetry.Trace.Export.Test using OpenTelemetry.Trace.Internal; using Xunit; - public class InProcessRunningSpanStoreTest + public class InProcessRunningSpanStoreTest : IDisposable { private const string SpanName1 = "MySpanName/1"; private const string SpanName2 = "MySpanName/2"; @@ -39,17 +41,13 @@ public InProcessRunningSpanStoreTest() private ISpan CreateSpan(string spanName) { - var spanContext = - SpanContext.Create( - ActivityTraceId.CreateRandom(), - ActivitySpanId.CreateRandom(), - ActivityTraceFlags.None, Tracestate.Empty); + var activity = new Activity(spanName).Start(); return Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, spanName, SpanKind.Internal, - ActivitySpanId.CreateRandom(), TraceParams.Default, startEndHandler, null); @@ -125,6 +123,11 @@ public void GetActiveSpans_SpansWithDifferentNames() span2.End(); } + public void Dispose() + { + Activity.Current = null; + } + // [Fact] // public void getActiveSpans_SpansWithSameName() // { diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs index 229fea3d6e9..081a79ae13e 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs @@ -26,13 +26,10 @@ namespace OpenTelemetry.Trace.Export.Test using OpenTelemetry.Utils; using Xunit; - public class InProcessSampledSpanStoreTest + public class InProcessSampledSpanStoreTest : IDisposable { - private static readonly string REGISTERED_SPAN_NAME = "MySpanName/1"; - private static readonly string NOT_REGISTERED_SPAN_NAME = "MySpanName/2"; - private readonly SpanContext sampledSpanContext; - - private readonly SpanContext notSampledSpanContext; + private const string RegisteredSpanName = "MySpanName/1"; + private const string NotRegisteredSpanName = "MySpanName/2"; private readonly ActivitySpanId parentSpanId; private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; @@ -50,20 +47,18 @@ public InProcessSampledSpanStoreTest() { timestamp = Timestamp.FromDateTimeOffset(startTime); timestampConverter = Timer.StartNew(startTime, () => interval); - sampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, Tracestate.Empty); - notSampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); parentSpanId = ActivitySpanId.CreateRandom(); startEndHandler = new TestStartEndHandler(sampleStore); - sampleStore.RegisterSpanNamesForCollection(new List() { REGISTERED_SPAN_NAME }); + sampleStore.RegisterSpanNamesForCollection(new List() { RegisteredSpanName }); } [Fact] public void AddSpansWithRegisteredNamesInAllLatencyBuckets() { - AddSpanNameToAllLatencyBuckets(REGISTERED_SPAN_NAME); + AddSpanNameToAllLatencyBuckets(RegisteredSpanName); var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); - var latencyBucketsSummaries = perSpanNameSummary[REGISTERED_SPAN_NAME].NumbersOfLatencySampledSpans; + var latencyBucketsSummaries = perSpanNameSummary[RegisteredSpanName].NumbersOfLatencySampledSpans; Assert.Equal(LatencyBucketBoundaries.Values.Count, latencyBucketsSummaries.Count); foreach (var it in latencyBucketsSummaries) { @@ -74,42 +69,42 @@ public void AddSpansWithRegisteredNamesInAllLatencyBuckets() [Fact] public void AddSpansWithoutRegisteredNamesInAllLatencyBuckets() { - AddSpanNameToAllLatencyBuckets(NOT_REGISTERED_SPAN_NAME); + AddSpanNameToAllLatencyBuckets(NotRegisteredSpanName); var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); - Assert.False(perSpanNameSummary.ContainsKey(NOT_REGISTERED_SPAN_NAME)); + Assert.False(perSpanNameSummary.ContainsKey(NotRegisteredSpanName)); } [Fact] public void RegisterUnregisterAndListSpanNames() { - Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); - sampleStore.RegisterSpanNamesForCollection(new List() { NOT_REGISTERED_SPAN_NAME }); + sampleStore.RegisterSpanNamesForCollection(new List() { NotRegisteredSpanName }); - Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); - Assert.Contains(NOT_REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(NotRegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); Assert.Equal(2, sampleStore.RegisteredSpanNamesForCollection.Count); - sampleStore.UnregisterSpanNamesForCollection(new List() { NOT_REGISTERED_SPAN_NAME }); + sampleStore.UnregisterSpanNamesForCollection(new List() { NotRegisteredSpanName }); - Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); } [Fact] public void RegisterSpanNamesViaSpanBuilderOption() { - Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); - var span = CreateSampledSpan(NOT_REGISTERED_SPAN_NAME); + var span = CreateSampledSpan(NotRegisteredSpanName); span.IsSampleToLocalSpanStore = true; span.End(); - Assert.Contains(REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); - Assert.Contains(NOT_REGISTERED_SPAN_NAME, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); + Assert.Contains(NotRegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); Assert.Equal(2, sampleStore.RegisteredSpanNamesForCollection.Count); } @@ -117,10 +112,10 @@ public void RegisterSpanNamesViaSpanBuilderOption() [Fact] public void AddSpansWithRegisteredNamesInAllErrorBuckets() { - AddSpanNameToAllErrorBuckets(REGISTERED_SPAN_NAME); + AddSpanNameToAllErrorBuckets(RegisteredSpanName); var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); - var errorBucketsSummaries = perSpanNameSummary[REGISTERED_SPAN_NAME].NumbersOfErrorSampledSpans; + var errorBucketsSummaries = perSpanNameSummary[RegisteredSpanName].NumbersOfErrorSampledSpans; var ccCount = Enum.GetValues(typeof(CanonicalCode)).Cast().Count(); Assert.Equal(ccCount - 1, errorBucketsSummaries.Count); foreach (var it in errorBucketsSummaries) @@ -132,23 +127,23 @@ public void AddSpansWithRegisteredNamesInAllErrorBuckets() [Fact] public void AddSpansWithoutRegisteredNamesInAllErrorBuckets() { - AddSpanNameToAllErrorBuckets(NOT_REGISTERED_SPAN_NAME); + AddSpanNameToAllErrorBuckets(NotRegisteredSpanName); var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; Assert.Equal(1, perSpanNameSummary.Count); - Assert.False(perSpanNameSummary.ContainsKey(NOT_REGISTERED_SPAN_NAME)); + Assert.False(perSpanNameSummary.ContainsKey(NotRegisteredSpanName)); } [Fact] public void GetErrorSampledSpans() { - var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span.Status = Status.Cancelled; span.End(); var samples = sampleStore.GetErrorSampledSpans( - SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, CanonicalCode.Cancelled, 0)); + SampledSpanStoreErrorFilter.Create(RegisteredSpanName, CanonicalCode.Cancelled, 0)); Assert.Single(samples); Assert.Contains(span.ToSpanData(), samples); } @@ -156,21 +151,21 @@ public void GetErrorSampledSpans() [Fact] public void GetErrorSampledSpans_MaxSpansToReturn() { - var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span1.Status = Status.Cancelled; span1.End(); // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); - var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span2.Status = Status.Cancelled; span2.End(); var samples = sampleStore.GetErrorSampledSpans( - SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, CanonicalCode.Cancelled, 1)); + SampledSpanStoreErrorFilter.Create(RegisteredSpanName, CanonicalCode.Cancelled, 1)); Assert.Single(samples); // No order guaranteed so one of the spans should be in the list. Assert.True(samples.Contains(span1.ToSpanData()) || samples.Contains(span2.ToSpanData())); @@ -179,19 +174,19 @@ public void GetErrorSampledSpans_MaxSpansToReturn() [Fact] public void GetErrorSampledSpans_NullCode() { - var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span1.Status = Status.Cancelled;; span1.End(); - var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span2.Status = Status.Unknown; span2.End(); var samples = - sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, null, 0)); + sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(RegisteredSpanName, null, 0)); Assert.Equal(2, samples.Count()); Assert.Contains(span1.ToSpanData(), samples); Assert.Contains(span2.ToSpanData(), samples); @@ -200,17 +195,17 @@ public void GetErrorSampledSpans_NullCode() [Fact] public void GetErrorSampledSpans_NullCode_MaxSpansToReturn() { - var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span1.Status = Status.Cancelled; span1.End(); - var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(10); span2.Status = Status.Unknown; span2.End(); var samples = - sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(REGISTERED_SPAN_NAME, null, 1)); + sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(RegisteredSpanName, null, 1)); Assert.Single(samples); Assert.True(samples.Contains(span1.ToSpanData()) || samples.Contains(span2.ToSpanData())); } @@ -218,13 +213,13 @@ public void GetErrorSampledSpans_NullCode_MaxSpansToReturn() [Fact] public void GetLatencySampledSpans() { - var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = sampleStore.GetLatencySampledSpans( SampledSpanStoreLatencyFilter.Create( - REGISTERED_SPAN_NAME, + RegisteredSpanName, TimeSpan.FromTicks(150), TimeSpan.FromTicks(250), 0)); @@ -235,13 +230,13 @@ public void GetLatencySampledSpans() [Fact] public void GetLatencySampledSpans_ExclusiveUpperBound() { - var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = sampleStore.GetLatencySampledSpans( SampledSpanStoreLatencyFilter.Create( - REGISTERED_SPAN_NAME, + RegisteredSpanName, TimeSpan.FromTicks(150), TimeSpan.FromTicks(200), 0)); @@ -251,13 +246,13 @@ public void GetLatencySampledSpans_ExclusiveUpperBound() [Fact] public void GetLatencySampledSpans_InclusiveLowerBound() { - var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = sampleStore.GetLatencySampledSpans( SampledSpanStoreLatencyFilter.Create( - REGISTERED_SPAN_NAME, + RegisteredSpanName, TimeSpan.FromTicks(150), TimeSpan.FromTicks(250), 0)); @@ -268,18 +263,18 @@ public void GetLatencySampledSpans_InclusiveLowerBound() [Fact] public void GetLatencySampledSpans_QueryBetweenMultipleBuckets() { - var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span1.End(); // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); - var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(2000); // 200 microseconds span2.End(); var samples = sampleStore.GetLatencySampledSpans( SampledSpanStoreLatencyFilter.Create( - REGISTERED_SPAN_NAME, + RegisteredSpanName, TimeSpan.FromTicks(150), TimeSpan.FromTicks(2500), 0)); @@ -291,18 +286,18 @@ public void GetLatencySampledSpans_QueryBetweenMultipleBuckets() [Fact] public void GetLatencySampledSpans_MaxSpansToReturn() { - var span1 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span1 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(200); // 20 microseconds span1.End(); // Advance time to allow other spans to be sampled. interval += TimeSpan.FromSeconds(5); - var span2 = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span2 = CreateSampledSpan(RegisteredSpanName) as Span; interval += TimeSpan.FromTicks(2000); // 200 microseconds span2.End(); var samples = sampleStore.GetLatencySampledSpans( SampledSpanStoreLatencyFilter.Create( - REGISTERED_SPAN_NAME, + RegisteredSpanName, TimeSpan.FromTicks(150), TimeSpan.FromTicks(2500), 1)); @@ -313,23 +308,26 @@ public void GetLatencySampledSpans_MaxSpansToReturn() [Fact] public void IgnoreNegativeSpanLatency() { - var span = CreateSampledSpan(REGISTERED_SPAN_NAME) as Span; + var span = CreateSampledSpan(RegisteredSpanName) as Span; interval -= TimeSpan.FromTicks(200); // 20 microseconds span.End(); var samples = sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create(REGISTERED_SPAN_NAME, TimeSpan.Zero, TimeSpan.MaxValue, 0)); + SampledSpanStoreLatencyFilter.Create(RegisteredSpanName, TimeSpan.Zero, TimeSpan.MaxValue, 0)); Assert.Empty(samples); } private Span CreateSampledSpan(string spanName) { + var activity = new Activity(spanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + return (Span)Span.StartSpan( - sampledSpanContext, + activity, + Tracestate.Empty, recordSpanOptions, spanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -337,12 +335,15 @@ private Span CreateSampledSpan(string spanName) private Span CreateNotSampledSpan(string spanName) { + var activity = new Activity(spanName).Start(); + activity.ActivityTraceFlags = ActivityTraceFlags.None; + return (Span)Span.StartSpan( - notSampledSpanContext, + activity, + Tracestate.Empty, recordSpanOptions, spanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -374,6 +375,8 @@ private void AddSpanNameToAllErrorBuckets(String spanName) notSampledSpan.Status = code.ToStatus(); sampledSpan.End(); notSampledSpan.End(); + sampledSpan.Activity.Stop(); + notSampledSpan.Activity.Stop(); } } } @@ -397,5 +400,10 @@ public void OnEnd(ISpan span) sampleStore.ConsiderForSampling(span); } } + + public void Dispose() + { + Activity.Current = null; + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index 37f7a5d98b6..3f640d2e3c5 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -30,12 +30,12 @@ namespace OpenTelemetry.Trace.Export.Test using OpenTelemetry.Trace.Internal; using Xunit; - public class SpanExporterTest + public class SpanExporterTest : IDisposable { - private const String SPAN_NAME_1 = "MySpanName/1"; - private const String SPAN_NAME_2 = "MySpanName/2"; - private readonly SpanContext sampledSpanContext; - private readonly SpanContext notSampledSpanContext; + private const string SpanName1 = "MySpanName/1"; + private const string SpanName2 = "MySpanName/2"; + private readonly Activity sampledActivity; + private readonly Activity notSampledActivity; private readonly ISpanExporter spanExporter = SpanExporter.Create(4, Duration.Create(1, 0)); private readonly IRunningSpanStore runningSpanStore = new InProcessRunningSpanStore(); private readonly IStartEndHandler startEndHandler; @@ -45,8 +45,10 @@ public class SpanExporterTest public SpanExporterTest() { - sampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, Tracestate.Empty); - notSampledSpanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); + sampledActivity = new Activity("foo"); + sampledActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + + notSampledActivity = new Activity("foo"); startEndHandler = new StartEndHandler(spanExporter, runningSpanStore, null, new SimpleEventQueue()); spanExporter.RegisterHandler("test.service", serviceHandler); @@ -54,13 +56,14 @@ public SpanExporterTest() private Span CreateSampledEndedSpan(string spanName) { + sampledActivity.Start(); var span = Span.StartSpan( - sampledSpanContext, + sampledActivity, + Tracestate.Empty, recordSpanOptions, spanName, SpanKind.Internal, - default, TraceParams.Default, startEndHandler, null); @@ -70,13 +73,14 @@ private Span CreateSampledEndedSpan(string spanName) private Span CreateNotSampledEndedSpan(string spanName) { + notSampledActivity.Start(); var span = Span.StartSpan( - notSampledSpanContext, + notSampledActivity, + Tracestate.Empty, recordSpanOptions, spanName, SpanKind.Internal, - default, TraceParams.Default, startEndHandler, null); @@ -87,8 +91,8 @@ private Span CreateNotSampledEndedSpan(string spanName) [Fact] public void ExportDifferentSampledSpans() { - var span1 = CreateSampledEndedSpan(SPAN_NAME_1); - var span2 = CreateSampledEndedSpan(SPAN_NAME_2); + var span1 = CreateSampledEndedSpan(SpanName1); + var span2 = CreateSampledEndedSpan(SpanName2); var exported = serviceHandler.WaitForExport(2); Assert.Equal(2, exported.Count()); Assert.Contains(span1.ToSpanData(), exported); @@ -98,12 +102,12 @@ public void ExportDifferentSampledSpans() [Fact] public void ExportMoreSpansThanTheBufferSize() { - var span1 = CreateSampledEndedSpan(SPAN_NAME_1); - var span2 = CreateSampledEndedSpan(SPAN_NAME_1); - var span3 = CreateSampledEndedSpan(SPAN_NAME_1); - var span4 = CreateSampledEndedSpan(SPAN_NAME_1); - var span5 = CreateSampledEndedSpan(SPAN_NAME_1); - var span6 = CreateSampledEndedSpan(SPAN_NAME_1); + var span1 = CreateSampledEndedSpan(SpanName1); + var span2 = CreateSampledEndedSpan(SpanName1); + var span3 = CreateSampledEndedSpan(SpanName1); + var span4 = CreateSampledEndedSpan(SpanName1); + var span5 = CreateSampledEndedSpan(SpanName1); + var span6 = CreateSampledEndedSpan(SpanName1); var exported = serviceHandler.WaitForExport(6); Assert.Equal(6, exported.Count()); Assert.Contains(span1.ToSpanData(), exported); @@ -135,13 +139,13 @@ public void ServiceHandlerThrowsException() // .when(mockServiceHandler) // .export(anyListOf(SpanData)); spanExporter.RegisterHandler("mock.service", mockServiceHandler); - var span1 = CreateSampledEndedSpan(SPAN_NAME_1); + var span1 = CreateSampledEndedSpan(SpanName1); var exported = serviceHandler.WaitForExport(1); Assert.Single(exported); Assert.Contains(span1.ToSpanData(), exported); // assertThat(exported).containsExactly(span1.toSpanData()); // Continue to export after the exception was received. - var span2 = CreateSampledEndedSpan(SPAN_NAME_1); + var span2 = CreateSampledEndedSpan(SpanName1); exported = serviceHandler.WaitForExport(1); Assert.Single(exported); Assert.Contains(span2.ToSpanData(), exported); @@ -153,8 +157,8 @@ public void ExportSpansToMultipleServices() { var serviceHandler2 = new TestHandler(); spanExporter.RegisterHandler("test.service2", serviceHandler2); - var span1 = CreateSampledEndedSpan(SPAN_NAME_1); - var span2 = CreateSampledEndedSpan(SPAN_NAME_2); + var span1 = CreateSampledEndedSpan(SpanName1); + var span2 = CreateSampledEndedSpan(SpanName2); var exported1 = serviceHandler.WaitForExport(2); var exported2 = serviceHandler2.WaitForExport(2); Assert.Equal(2, exported1.Count()); @@ -168,8 +172,8 @@ public void ExportSpansToMultipleServices() [Fact] public void ExportNotSampledSpans() { - var span1 = CreateNotSampledEndedSpan(SPAN_NAME_1); - var span2 = CreateSampledEndedSpan(SPAN_NAME_2); + var span1 = CreateNotSampledEndedSpan(SpanName1); + var span2 = CreateSampledEndedSpan(SpanName2); // Spans are recorded and exported in the same order as they are ended, we test that a non // sampled span is not exported by creating and ending a sampled span after a non sampled span // and checking that the first exported span is the sampled span (the non sampled did not get @@ -191,7 +195,7 @@ public async Task ExportAsyncCallsAllHandlers() exporter.RegisterHandler("first", handler1.Object); - var span1 = CreateNotSampledEndedSpan(SPAN_NAME_1).ToSpanData(); + var span1 = CreateNotSampledEndedSpan(SpanName1).ToSpanData(); await exporter.ExportAsync(span1, CancellationToken.None); @@ -202,6 +206,12 @@ public async Task ExportAsyncCallsAllHandlers() (x) => x.Where((s) => s == span1).Count() > 0 && x.Count() == 1))); } + + public void Dispose() + { + spanExporter?.Dispose(); + Activity.Current = null; + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index 303becfded1..95959235a9f 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -14,11 +14,12 @@ // limitations under the License. // +using System.Linq; + namespace OpenTelemetry.Trace.Test { using System.Collections.Generic; using System.Diagnostics; - using OpenTelemetry.Trace.Internal; using OpenTelemetry.Utils; using Xunit; @@ -30,6 +31,10 @@ public class LinkTest public LinkTest() { + // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + Activity.ForceDefaultIdFormat = true; + spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); ; attributesMap.Add("MyAttributeKey0", AttributeValue.Create("MyStringAttribute")); attributesMap.Add("MyAttributeKey1", AttributeValue.Create(10)); @@ -71,38 +76,35 @@ public void FromSpanContext_ParentLink_WithAttributes() Assert.Equal(attributesMap, link.Attributes); } - [Fact] - public void Link_EqualsAndHashCode() - { - // EqualsTester tester = new EqualsTester(); - // tester - // .addEqualityGroup( - // Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN), - // Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN)) - // .addEqualityGroup( - // Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN), - // Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)) - // .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD_LINKED_SPAN)) - // .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)) - // .addEqualityGroup( - // Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap), - // Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap)); - // tester.testEquals(); - - - } - [Fact] public void Link_ToString() { var link = Link.FromSpanContext(spanContext, attributesMap); Assert.Contains(spanContext.TraceId.ToString(), link.ToString()); Assert.Contains(spanContext.SpanId.ToString(), link.ToString()); - Assert.Contains(Collections.ToString(attributesMap), link.ToString()); + Assert.Contains(string.Join(" ", attributesMap.Select(kvp => $"{kvp.Key}={kvp.Value}")), link.ToString()); link = Link.FromSpanContext(spanContext, attributesMap); Assert.Contains(spanContext.TraceId.ToString(), link.ToString()); Assert.Contains(spanContext.SpanId.ToString(), spanContext.SpanId.ToString()); - Assert.Contains(Collections.ToString(attributesMap), link.ToString()); + Assert.Contains(string.Join(" ", attributesMap.Select(kvp => $"{kvp.Key}={kvp.Value}")), link.ToString()); + } + + [Fact] + public void FromSpanContext_FromActivity() + { + var activity = new Activity("foo").Start(); + activity.TraceStateString = "k1=v1, k2=v2"; + + var link = Link.FromActivity(activity); + Assert.Equal(activity.TraceId, link.Context.TraceId); + Assert.Equal(activity.SpanId, link.Context.SpanId); + + var entries = link.Context.Tracestate.Entries.ToArray(); + Assert.Equal(2, entries.Length); + Assert.Equal("k1", entries[0].Key); + Assert.Equal("v1", entries[0].Value); + Assert.Equal("k2", entries[1].Key); + Assert.Equal("v2", entries[1].Value); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs index e3d1b17349e..30ee42b591b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs @@ -14,10 +14,10 @@ // limitations under the License. // -using System; - namespace OpenTelemetry.Tests.Impl.Trace { + using System; + using System.Diagnostics; using OpenTelemetry.Trace; using Xunit; @@ -31,7 +31,20 @@ public void NoopSpanBuilder_BadArguments() var spanBuilder = new NoopSpanBuilder("foo"); Assert.Throws(() => spanBuilder.SetParent((ISpan)null)); Assert.Throws(() => spanBuilder.SetParent((SpanContext)null)); + Assert.Throws(() => spanBuilder.SetParent((Activity)null)); + + // no Activity.Current + Assert.Throws(() => spanBuilder.SetCreateChild(false)); + + // Activity.Current wrong format + Activity.DefaultIdFormat = ActivityIdFormat.Hierarchical; + Activity.ForceDefaultIdFormat = true; + var a = new Activity("foo").Start(); // TODO SetIdFormat + Assert.Throws(() => spanBuilder.SetCreateChild(false)); + a.Stop(); + Assert.Throws(() => spanBuilder.SetSampler(null)); + Assert.Throws(() => spanBuilder.AddLink((Activity)null)); Assert.Throws(() => spanBuilder.AddLink((ILink)null)); Assert.Throws(() => spanBuilder.AddLink((SpanContext)null)); Assert.Throws(() => spanBuilder.AddLink(null, null)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs index 25bc1ed09e5..19bf1ace22b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TraceContextTest.cs @@ -14,10 +14,9 @@ // limitations under the License. // -using System; - namespace OpenTelemetry.Impl.Trace.Propagation { + using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -27,6 +26,17 @@ namespace OpenTelemetry.Impl.Trace.Propagation public class TraceContextTest { + private static readonly string[] empty = new string[0]; + private static readonly Func, string, IEnumerable> getter = (headers, name) => + { + if (headers.TryGetValue(name, out var value)) + { + return new [] { value }; + } + + return empty; + }; + [Fact] public void TraceContextFormatCanParseExampleFromSpec() { @@ -40,7 +50,7 @@ public void TraceContextFormatCanParseExampleFromSpec() }; var f = new TraceContextFormat(); - var ctx = f.Extract(headers, (h, n) => new string[] {h[n]}); + var ctx = f.Extract(headers, getter); Assert.Equal(ActivityTraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c".AsSpan()), ctx.TraceId); Assert.Equal(ActivitySpanId.CreateFromString("b9c7c989f97918e1".AsSpan()), ctx.SpanId); @@ -59,13 +69,29 @@ public void TraceContextFormatCanParseExampleFromSpec() Assert.Equal("00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01", last.Value); } + [Fact] + public void TraceContextFormatNotSampled() + { + var headers = new Dictionary() + { + {"traceparent", "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-00"}, + }; + + var f = new TraceContextFormat(); + var ctx = f.Extract(headers, getter); + + Assert.Equal(ActivityTraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c".AsSpan()), ctx.TraceId); + Assert.Equal(ActivitySpanId.CreateFromString("b9c7c989f97918e1".AsSpan()), ctx.SpanId); + Assert.True((ctx.TraceOptions & ActivityTraceFlags.Recorded) == 0); + } + [Fact] public void TraceContextFormat_IsBlankIfNoHeader() { var headers = new Dictionary(); var f = new TraceContextFormat(); - var ctx = f.Extract(headers, (h, n) => new string[] { h[n] }); + var ctx = f.Extract(headers, getter); Assert.Same(SpanContext.Blank, ctx); } @@ -79,9 +105,48 @@ public void TraceContextFormat_IsBlankIfInvalid() }; var f = new TraceContextFormat(); - var ctx = f.Extract(headers, (h, n) => new string[] { h[n] }); + var ctx = f.Extract(headers, getter); Assert.Same(SpanContext.Blank, ctx); } + + [Fact] + public void TraceContextFormat_TracestateToStringEmpty() + { + var headers = new Dictionary + { + {"traceparent", "00-abc7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"}, + }; + + var f = new TraceContextFormat(); + var ctx = f.Extract(headers, getter); + + Assert.Empty(ctx.Tracestate.Entries); + Assert.Equal(string.Empty, ctx.Tracestate.ToString()); + } + + [Fact] + public void TraceContextFormat_TracestateToString() + { + var headers = new Dictionary + { + {"traceparent", "00-abc7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"}, + {"tracestate", "k1=v1,k2=v2,k3=v3" }, + }; + + var f = new TraceContextFormat(); + var ctx = f.Extract(headers, getter); + + var entries = ctx.Tracestate.Entries.ToArray(); + Assert.Equal(3, entries.Length); + Assert.Equal("k1", entries[0].Key); + Assert.Equal("v1", entries[0].Value); + Assert.Equal("k2", entries[1].Key); + Assert.Equal("v2", entries[1].Value); + Assert.Equal("k3", entries[2].Key); + Assert.Equal("v3", entries[2].Value); + + Assert.Equal("k1=v1,k2=v2,k3=v3", ctx.Tracestate.ToString()); + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TracestateUtilsTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TracestateUtilsTests.cs new file mode 100644 index 00000000000..2e12fb7952d --- /dev/null +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/TracestateUtilsTests.cs @@ -0,0 +1,90 @@ +// +// 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 System; +using System.Linq; +using OpenTelemetry.Context.Propagation; +using OpenTelemetry.Trace; +using Xunit; + +namespace OpenTelemetry.Tests.Impl.Trace.Propagation +{ + public class TracestateUtilsTests + { + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData(" ")] + [InlineData("\t")] + public void EmptyTracestate(string tracestate) + { + var builder = Tracestate.Builder; + Assert.True(TracestateUtils.TryExtractTracestate(tracestate, builder)); + Assert.Empty(builder.Build().Entries); + } + + [Theory] + [InlineData("k=", 0)] + [InlineData("=v", 0)] + [InlineData("kv", 0)] + [InlineData("k=v,k=v", 1)] + [InlineData("k1=v1,,,k2=v2", 1)] + [InlineData("k=morethan256......................................................................................................................................................................................................................................................", 0)] + [InlineData("v=morethan256......................................................................................................................................................................................................................................................", 0)] + public void InvalidTracestate(string tracestate, int validEntriesCount) + { + var builder = Tracestate.Builder; + Assert.False(TracestateUtils.TryExtractTracestate(tracestate, builder)); + Assert.Equal(validEntriesCount, builder.Build().Entries.Count()); + } + + [Fact] + public void TooManyEntries() + { + var builder = Tracestate.Builder; + var tracestate = + "k0=v,k1=v,k2=v,k3=v,k4=v,k5=v,k6=v,k7=v1,k8=v,k9=v,k10=v,k11=v,k12=v,k13=v,k14=v,k15=v,k16=v,k17=v,k18=v,k19=v,k20=v,k21=v,k22=v,k23=v,k24=v,k25=v,k26=v,k27=v1,k28=v,k29=v,k30=v,k31=v,k32=v,k33=v"; + Assert.False(TracestateUtils.TryExtractTracestate(tracestate, builder)); + Assert.Throws(() => builder.Build()); + } + + [Theory] + [InlineData("k=v")] + [InlineData(" k=v ")] + [InlineData(" k = v ")] + [InlineData("\tk\t=\tv\t")] + [InlineData(",k=v,")] + [InlineData(", k = v, ")] + public void ValidPair(string pair) + { + var builder = Tracestate.Builder; + Assert.True(TracestateUtils.TryExtractTracestate(pair, builder)); + Assert.Equal("k=v", builder.Build().ToString()); + } + + [Theory] + [InlineData("k1=v1,k2=v2")] + [InlineData(" k1=v1 , k2=v2")] + [InlineData(" ,k1=v1,k2=v2")] + [InlineData("k1=v1,k2=v2, ")] + public void ValidPairs(string tracestate) + { + var builder = Tracestate.Builder; + Assert.True(TracestateUtils.TryExtractTracestate(tracestate, builder)); + Assert.Equal("k1=v1,k2=v2", builder.Build().ToString()); + } + } +} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index 3eff28b3b05..dccf057ee96 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -18,6 +18,9 @@ namespace OpenTelemetry.Trace.Test { using System; using System.Diagnostics; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; using Moq; using OpenTelemetry.Common; using OpenTelemetry.Trace.Config; @@ -25,7 +28,7 @@ namespace OpenTelemetry.Trace.Test using OpenTelemetry.Trace.Sampler; using Xunit; - public class SpanBuilderTest + public class SpanBuilderTest : IDisposable { private static readonly string SpanName = "MySpanName"; private readonly SpanBuilderOptions spanBuilderOptions; @@ -36,14 +39,21 @@ public class SpanBuilderTest private readonly IStartEndHandler startEndHandler = Mock.Of(); private readonly ITraceConfig traceConfig = Mock.Of(); + private readonly ITracer tracer; public SpanBuilderTest() { + // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + Activity.ForceDefaultIdFormat = true; + // MockitoAnnotations.initMocks(this); spanBuilderOptions = new SpanBuilderOptions(startEndHandler, traceConfig); var configMock = Mock.Get(traceConfig); configMock.Setup((c) => c.ActiveTraceParams).Returns(alwaysSampleTraceParams); - // when(traceConfig.getActiveTraceParams()).thenReturn(alwaysSampleTraceParams); + + startEndHandler = Mock.Of(); + tracer = new Tracer(startEndHandler, traceConfig); } [Fact] @@ -62,6 +72,11 @@ public void StartSpanNullParent() Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(-1, 0)), Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(1, 0))); Assert.Equal(SpanName, spanData.Name); + + var activity = ((Span)span).Activity; + Assert.Null(Activity.Current); + Assert.Equal(activity.TraceId, span.Context.TraceId); + Assert.Equal(activity.SpanId, span.Context.SpanId); } [Fact] @@ -144,6 +159,66 @@ public void StartSpanLastParentWins4() Assert.Equal(spanContext.SpanId, childSpan.ParentSpanId); } + [Fact] + public void StartSpanLastParentWins5() + { + var spanContext = + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); + var activity = new Activity("foo").Start(); + + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetParent(spanContext) + .SetParent(activity) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(activity.TraceId, childSpan.Context.TraceId); + Assert.Equal(activity.SpanId, childSpan.ParentSpanId); + } + + [Fact] + public void StartSpanLastParentWins6() + { + var spanContext = + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); + var activity = new Activity("foo").Start(); + + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetParent(spanContext) + .SetCreateChild(false) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(activity.TraceId, childSpan.Context.TraceId); + Assert.Equal(activity.SpanId, childSpan.Context.SpanId); + } + + [Fact] + public void StartSpanLastParentWins7() + { + var spanContext = + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); + var activity = new Activity("foo").Start(); + + var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) + .SetCreateChild(false) + .SetParent(spanContext) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(spanContext.TraceId, childSpan.Context.TraceId); + Assert.Equal(spanContext.SpanId, childSpan.ParentSpanId); + } + [Fact] public void StartSpanNullParentWithRecordEvents() { @@ -180,6 +255,7 @@ public void StartChildSpan() .SetSpanKind(SpanKind.Internal) .SetNoParent() .StartSpan(); + Assert.True(rootSpan.Context.IsValid); Assert.True(rootSpan.IsRecordingEvents); Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); @@ -195,6 +271,150 @@ public void StartChildSpan() Assert.Equal(((Span)rootSpan).TimestampConverter, ((Span)childSpan).TimestampConverter); } + [Fact] + public void StartSpanInScopeOfCurrentActivity() + { + var parentActivity = new Activity(SpanName).Start(); + parentActivity.TraceStateString = "k1=v1,k2=v2"; + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(parentActivity.TraceId, childSpan.Context.TraceId); + Assert.Equal(parentActivity.SpanId, ((Span)childSpan).ParentSpanId); + + var activity = ((Span)childSpan).Activity; + Assert.Equal(parentActivity, Activity.Current); + Assert.Equal(activity.Parent, parentActivity); + + Assert.Equal("k1=v1,k2=v2", childSpan.Context.Tracestate.ToString()); + } + + [Fact] + public void StartSpanInScopeOfCurrentActivityRecorded() + { + var parentActivity = new Activity(SpanName).Start(); + parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(parentActivity.TraceId, childSpan.Context.TraceId); + Assert.Equal(parentActivity.SpanId, ((Span)childSpan).ParentSpanId); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); + parentActivity.Stop(); + } + + [Fact] + public void StartSpanInScopeOfCurrentActivityNoParent() + { + var parentActivity = new Activity(SpanName).Start(); + parentActivity.TraceStateString = "k1=v1,k2=v2"; + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetNoParent() + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.NotEqual(parentActivity.TraceId, childSpan.Context.TraceId); + Assert.True(((Span)childSpan).ToSpanData().ParentSpanId == default); + + var activity = ((Span)childSpan).Activity; + Assert.Equal(parentActivity, Activity.Current); + Assert.Null(activity.Parent); + Assert.Equal(activity.TraceId, childSpan.Context.TraceId); + Assert.Equal(activity.SpanId, childSpan.Context.SpanId); + Assert.Empty(childSpan.Context.Tracestate.Entries); + } + + [Fact] + public void StartSpanFromExplicitActivity() + { + var parentActivity = new Activity(SpanName).Start(); + parentActivity.TraceStateString = "k1=v1,k2=v2"; + parentActivity.Stop(); + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(parentActivity) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(parentActivity.TraceId, childSpan.Context.TraceId); + Assert.Equal(parentActivity.SpanId, ((Span)childSpan).ParentSpanId); + + var activity = ((Span)childSpan).Activity; + Assert.NotNull(activity); + Assert.Null(Activity.Current); + Assert.Equal(activity.TraceId, parentActivity.TraceId); + Assert.Equal(activity.ParentSpanId, parentActivity.SpanId); + Assert.Equal(activity.SpanId, childSpan.Context.SpanId); + Assert.Equal("k1=v1,k2=v2", childSpan.Context.Tracestate.ToString()); + } + + [Fact] + public void StartSpanFromExplicitRecordedActivity() + { + var parentActivity = new Activity(SpanName).Start(); + parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + parentActivity.Stop(); + + var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(parentActivity) + .StartSpan(); + + Assert.True(childSpan.Context.IsValid); + Assert.Equal(parentActivity.TraceId, childSpan.Context.TraceId); + Assert.Equal(parentActivity.SpanId, ((Span)childSpan).ParentSpanId); + Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); + } + + [Fact] + public void StartSpanFromCurrentActivity() + { + var activity = new Activity(SpanName).Start(); + activity.TraceStateString = "k1=v1,k2=v2"; + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetCreateChild(false) + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.Equal(activity.TraceId, span.Context.TraceId); + Assert.Equal(activity.SpanId, span.Context.SpanId); + Assert.True(((Span)span).ParentSpanId == default); + + Assert.NotNull(Activity.Current); + Assert.Equal(Activity.Current, activity); + Assert.Equal("k1=v1,k2=v2", span.Context.Tracestate.ToString()); + } + + [Fact] + public void StartSpanFromCurrentRecordedActivity() + { + var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetCreateChild(false) + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.Equal(activity.TraceId, span.Context.TraceId); + Assert.Equal(activity.SpanId, span.Context.SpanId); + Assert.True(((Span)span).ParentSpanId == default); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); + activity.Stop(); + } + [Fact] public void StartSpan_ExplicitNoParent() { @@ -208,6 +428,12 @@ public void StartSpan_ExplicitNoParent() Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); Assert.True(spanData.ParentSpanId == default); + + var activity = ((Span)span).Activity; + Assert.Null(Activity.Current); + Assert.Equal(activity.TraceId, span.Context.TraceId); + Assert.Equal(activity.SpanId, span.Context.SpanId); + Assert.Empty(span.Context.Tracestate.Entries); } [Fact] @@ -224,12 +450,50 @@ public void StartSpan_NoParent() Assert.True(spanData.ParentSpanId == default); } + + [Fact] + public void StartSpan_BlankSpanParent() + { + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(BlankSpan.Instance) + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.True(span.IsRecordingEvents); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); + var spanData = ((Span)span).ToSpanData(); + Assert.True(spanData.ParentSpanId == default); + } + + [Fact] + public void StartSpan_BlankSpanContextParent() + { + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .SetParent(SpanContext.Blank) + .StartSpan(); + + Assert.True(span.Context.IsValid); + Assert.True(span.IsRecordingEvents); + Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); + var spanData = ((Span)span).ToSpanData(); + Assert.True(spanData.ParentSpanId == default); + } + + [Fact] public void StartSpan_CurrentSpanParent() { var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) + .SetParent( + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, + Tracestate.Builder.Set("k1", "v1").Build())) .StartSpan(); - using (CurrentSpanUtils.WithSpan(rootSpan, true)) + using (tracer.WithSpan(rootSpan)) { var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .StartSpan(); @@ -237,6 +501,7 @@ public void StartSpan_CurrentSpanParent() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId); + Assert.Equal("k1=v1", childSpan.Context.Tracestate.ToString()); } } @@ -245,7 +510,7 @@ public void StartSpan_NoParentInScopeOfCurrentSpan() { var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) .StartSpan(); - using (CurrentSpanUtils.WithSpan(rootSpan, true)) + using (tracer.WithSpan(rootSpan)) { var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .SetNoParent() @@ -278,7 +543,8 @@ public void StartRemoteSpan() SpanContext.Create( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), - ActivityTraceFlags.None, Tracestate.Empty); + ActivityTraceFlags.None, + Tracestate.Builder.Set("k1", "v1").Build()); var span = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) @@ -291,6 +557,109 @@ public void StartRemoteSpan() Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); Assert.Equal(spanContext.SpanId, spanData.ParentSpanId); + Assert.Equal("k1=v1", span.Context.Tracestate.ToString()); + } + + [Fact] + public void StartSpan_WithLink() + { + var link = Link.FromSpanContext( + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty)); + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .AddLink(link) + .StartSpan(); + + var spanData = ((Span)span).ToSpanData(); + var links = spanData.Links.Links.ToArray(); + + Assert.Single(links); + + Assert.Equal(link.Context.TraceId, links[0].Context.TraceId); + Assert.Equal(link.Context.SpanId, links[0].Context.SpanId); + Assert.Equal(link.Context.TraceOptions, links[0].Context.TraceOptions); + Assert.Equal(link.Context.Tracestate, links[0].Context.Tracestate); + Assert.Equal(0, links[0].Attributes.Count); + } + + [Fact] + public void StartSpan_WithLinkFromActivity() + { + var activityLink = new Activity("foo").Start(); + activityLink.Stop(); + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .AddLink(activityLink) + .StartSpan(); + + var spanData = ((Span)span).ToSpanData(); + var links = spanData.Links.Links.ToArray(); + + Assert.Single(links); + + Assert.Equal(activityLink.TraceId, links[0].Context.TraceId); + Assert.Equal(activityLink.SpanId, links[0].Context.SpanId); + Assert.Equal(activityLink.ActivityTraceFlags, links[0].Context.TraceOptions); + Assert.Empty(links[0].Context.Tracestate.Entries); + Assert.Equal(0, links[0].Attributes.Count); + } + + [Fact] + public void StartSpan_WithLinkFromSpanContextAndAttributes() + { + var linkContext = + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .AddLink(linkContext, new Dictionary { ["k"] = "v", }) + .StartSpan(); + + var spanData = ((Span)span).ToSpanData(); + var links = spanData.Links.Links.ToArray(); + + Assert.Single(links); + + Assert.Equal(linkContext.TraceId, links[0].Context.TraceId); + Assert.Equal(linkContext.SpanId, links[0].Context.SpanId); + Assert.Equal(linkContext.TraceOptions, links[0].Context.TraceOptions); + Assert.Equal(linkContext.Tracestate, links[0].Context.Tracestate); + Assert.Equal(1, links[0].Attributes.Count); + Assert.True(links[0].Attributes.ContainsKey("k")); + Assert.Equal("v", links[0].Attributes["k"].ToString()); + } + + [Fact] + public void StartSpan_WithLinkFromSpanContext() + { + var linkContext = + SpanContext.Create( + ActivityTraceId.CreateRandom(), + ActivitySpanId.CreateRandom(), + ActivityTraceFlags.None, Tracestate.Empty); + + var span = new SpanBuilder(SpanName, spanBuilderOptions) + .SetSpanKind(SpanKind.Internal) + .AddLink(linkContext) + .StartSpan(); + + var spanData = ((Span)span).ToSpanData(); + var links = spanData.Links.Links.ToArray(); + + Assert.Single(links); + + Assert.Equal(linkContext.TraceId, links[0].Context.TraceId); + Assert.Equal(linkContext.SpanId, links[0].Context.SpanId); + Assert.Equal(linkContext.TraceOptions, links[0].Context.TraceOptions); + Assert.Equal(linkContext.Tracestate, links[0].Context.Tracestate); } [Fact] @@ -491,15 +860,35 @@ public void StartRemoteChildSpan_WithProbabilitySamplerDefaultSampler() [Fact] public void SpanBuilder_BadArguments() { - var spanBuilder = new SpanBuilder(SpanName, spanBuilderOptions); + Assert.Throws(() => new SpanBuilder(null, spanBuilderOptions)); + Assert.Throws(() => new SpanBuilder(SpanName, null)); + var spanBuilder = new SpanBuilder(SpanName, spanBuilderOptions); Assert.Throws(() => spanBuilder.SetParent((ISpan)null)); Assert.Throws(() => spanBuilder.SetParent((SpanContext)null)); + Assert.Throws(() => spanBuilder.SetParent((Activity)null)); + + // no Activity.Current + Assert.Throws(() => spanBuilder.SetCreateChild(false)); + + // Activity.Current wrong format + Activity.DefaultIdFormat = ActivityIdFormat.Hierarchical; + Activity.ForceDefaultIdFormat = true; + var a = new Activity("foo").Start(); // TODO SetIdFormat + Assert.Throws(() => spanBuilder.SetCreateChild(false)); + a.Stop(); + Assert.Throws(() => spanBuilder.SetSampler(null)); + Assert.Throws(() => spanBuilder.AddLink((Activity)null)); Assert.Throws(() => spanBuilder.AddLink((ILink)null)); Assert.Throws(() => spanBuilder.AddLink((SpanContext)null)); Assert.Throws(() => spanBuilder.AddLink(null, null)); Assert.Throws(() => spanBuilder.AddLink(SpanContext.Blank, null)); } + + public void Dispose() + { + Activity.Current = null; + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 91d4e0175b1..21447921f45 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -25,32 +25,28 @@ namespace OpenTelemetry.Trace.Test using OpenTelemetry.Internal; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Internal; using Xunit; - public class SpanTest + public class SpanTest : IDisposable { private const string SpanName = "MySpanName"; private const string EventDescription = "MyEvent"; - private readonly SpanContext spanContext; - private readonly ActivitySpanId parentSpanId; + private TimeSpan interval = TimeSpan.FromMilliseconds(0); private readonly DateTimeOffset startTime = DateTimeOffset.Now; private readonly Timestamp timestamp; private readonly Timer timestampConverter; private readonly SpanOptions noRecordSpanOptions = SpanOptions.None; private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; - private readonly IDictionary attributes = new Dictionary(); - private readonly IDictionary expectedAttributes; + private readonly IDictionary attributes = new Dictionary(); + private readonly IDictionary expectedAttributes; private readonly IStartEndHandler startEndHandler = Mock.Of(); public SpanTest() { timestamp = Timestamp.FromDateTimeOffset(startTime); timestampConverter = Timer.StartNew(startTime, () => interval); - spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), - ActivityTraceFlags.None, Tracestate.Empty); - parentSpanId = ActivitySpanId.CreateRandom(); + attributes.Add( "MyStringAttributeKey", AttributeValue.StringAttributeValue("MyStringAttributeValue")); attributes.Add("MyLongAttributeKey", AttributeValue.LongAttributeValue(123L)); @@ -64,13 +60,18 @@ public SpanTest() [Fact] public void ToSpanData_NoRecordEvents() { + var activityLink = new Activity(SpanName).Start(); + activityLink.Stop(); + + var activity = new Activity(SpanName).Start(); + var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, noRecordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -82,22 +83,78 @@ public void ToSpanData_NoRecordEvents() span.AddEvent(Event.Create(EventDescription)); span.AddEvent(EventDescription, attributes); - span.AddLink(Link.FromSpanContext(spanContext)); + span.AddLink(Link.FromActivity(activityLink)); span.End(); // exception.expect(IllegalStateException); Assert.Throws(() => ((Span)span).ToSpanData()); } + [Fact] + public void GetSpanContextFromActivity() + { + var tracestate = Tracestate.Builder.Set("k1", "v1").Build(); + var activity = new Activity(SpanName).Start(); + activity.TraceStateString = tracestate.ToString(); + + var span = + Span.StartSpan( + activity, + tracestate, + recordSpanOptions, + SpanName, + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + timestampConverter); + Assert.NotNull(span.Context); + Assert.Equal(activity.TraceId, span.Context.TraceId); + Assert.Equal(activity.SpanId, span.Context.SpanId); + Assert.Equal(activity.ParentSpanId, ((Span)span).ParentSpanId); + Assert.Equal(activity.ActivityTraceFlags, span.Context.TraceOptions); + Assert.Same(tracestate, span.Context.Tracestate); + } + + [Fact] + public void GetSpanContextFromActivityRecordedWithParent() + { + var tracestate = Tracestate.Builder.Set("k1", "v1").Build(); + var parent = new Activity(SpanName).Start(); + var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + + var span = + Span.StartSpan( + activity, + tracestate, + recordSpanOptions, + SpanName, + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + timestampConverter); + Assert.NotNull(span.Context); + Assert.Equal(activity.TraceId, span.Context.TraceId); + Assert.Equal(activity.SpanId, span.Context.SpanId); + Assert.Equal(activity.ParentSpanId, ((Span)span).ParentSpanId); + Assert.Equal(activity.ActivityTraceFlags, span.Context.TraceOptions); + Assert.Same(tracestate, span.Context.Tracestate); + } + [Fact] public void NoEventsRecordedAfterEnd() { + var activityLink = new Activity(SpanName).Start(); + activityLink.Stop(); + + var activity = new Activity(SpanName).Start(); + var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -114,7 +171,7 @@ public void NoEventsRecordedAfterEnd() "MySingleStringAttributeValue"); span.AddEvent(Event.Create(EventDescription)); span.AddEvent(EventDescription, attributes); - span.AddLink(Link.FromSpanContext(spanContext)); + span.AddLink(Link.FromActivity(activityLink)); var spanData = ((Span)span).ToSpanData(); Assert.Equal(timestamp, spanData.StartTimestamp); Assert.Empty(spanData.Attributes.AttributeMap); @@ -127,13 +184,21 @@ public void NoEventsRecordedAfterEnd() [Fact] public void ToSpanData_ActiveSpan() { + + var activityLink = new Activity(SpanName); + activityLink.Stop(); + + var activity = new Activity(SpanName) + .SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()) + .Start(); + var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -152,12 +217,17 @@ public void ToSpanData_ActiveSpan() span.AddEvent(EventDescription, attributes); interval = TimeSpan.FromMilliseconds(300); interval = TimeSpan.FromMilliseconds(400); - var link = Link.FromSpanContext(spanContext); + var link = Link.FromActivity(activityLink); span.AddLink(link); var spanData = ((Span)span).ToSpanData(); - Assert.Equal(spanContext, spanData.Context); + Assert.Equal(activity.TraceId, spanData.Context.TraceId); + Assert.Equal(activity.SpanId, spanData.Context.SpanId); + Assert.Equal(activity.ParentSpanId, spanData.ParentSpanId); + Assert.Equal(activity.ActivityTraceFlags, spanData.Context.TraceOptions); + Assert.Same(Tracestate.Empty, spanData.Context.Tracestate); + Assert.Equal(SpanName, spanData.Name); - Assert.Equal(parentSpanId, spanData.ParentSpanId); + Assert.Equal(activity.ParentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); Assert.Equal(0, spanData.Events.DroppedEventsCount); @@ -182,13 +252,20 @@ public void ToSpanData_ActiveSpan() [Fact] public void GoSpanData_EndedSpan() { + var activityLink = new Activity(SpanName).Start(); + activityLink.Stop(); + + var activity = new Activity(SpanName) + .SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()) + .Start(); + var span = (Span)Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -206,16 +283,20 @@ public void GoSpanData_EndedSpan() interval = TimeSpan.FromMilliseconds(200); span.AddEvent(EventDescription, attributes); interval = TimeSpan.FromMilliseconds(300); - var link = Link.FromSpanContext(spanContext); + var link = Link.FromActivity(activityLink); span.AddLink(link); interval = TimeSpan.FromMilliseconds(400); span.Status = Status.Cancelled; span.End(); var spanData = ((Span)span).ToSpanData(); - Assert.Equal(spanContext, spanData.Context); + Assert.Equal(activity.TraceId, spanData.Context.TraceId); + Assert.Equal(activity.SpanId, spanData.Context.SpanId); + Assert.Equal(activity.ParentSpanId, spanData.ParentSpanId); + Assert.Equal(activity.ActivityTraceFlags, spanData.Context.TraceOptions); + Assert.Equal(SpanName, spanData.Name); - Assert.Equal(parentSpanId, spanData.ParentSpanId); + Assert.Equal(activity.ParentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); Assert.Equal(0, spanData.Events.DroppedEventsCount); @@ -241,13 +322,15 @@ public void GoSpanData_EndedSpan() [Fact] public void Status_ViaSetStatus() { + var activity = new Activity(SpanName).Start(); + var span = (Span)Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -265,13 +348,15 @@ public void Status_ViaSetStatus() [Fact] public void status_ViaEndSpanOptions() { + var activity = new Activity(SpanName).Start(); + var span = (Span)Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -290,16 +375,18 @@ public void status_ViaEndSpanOptions() [Fact] public void DroppingAttributes() { + var activity = new Activity(SpanName).Start(); + var maxNumberOfAttributes = 8; var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfAttributes(maxNumberOfAttributes).Build(); var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, traceParams, startEndHandler, timestampConverter); @@ -343,16 +430,18 @@ public void DroppingAttributes() [Fact] public void DroppingAndAddingAttributes() { + var activity = new Activity(SpanName).Start(); + var maxNumberOfAttributes = 8; var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfAttributes(maxNumberOfAttributes).Build(); var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, traceParams, startEndHandler, timestampConverter); @@ -414,16 +503,18 @@ public void DroppingAndAddingAttributes() [Fact] public void DroppingEvents() { + var activity = new Activity(SpanName).Start(); + var maxNumberOfEvents = 8; var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfEvents(maxNumberOfEvents).Build(); var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, traceParams, startEndHandler, timestampConverter); @@ -466,20 +557,25 @@ public void DroppingEvents() [Fact] public void DroppingLinks() { + var activityLink = new Activity(SpanName).Start(); + activityLink.Stop(); + + var activity = new Activity(SpanName).Start(); + var maxNumberOfLinks = 8; var traceParams = TraceParams.Default.ToBuilder().SetMaxNumberOfLinks(maxNumberOfLinks).Build(); var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, traceParams, startEndHandler, timestampConverter); - var link = Link.FromSpanContext(spanContext); + var link = Link.FromActivity(activityLink); for (var i = 0; i < 2 * maxNumberOfLinks; i++) { span.AddLink(link); @@ -506,13 +602,15 @@ public void DroppingLinks() [Fact] public void SampleToLocalSpanStore() { + var activity1 = new Activity(SpanName).Start(); + var span = (Span)Span.StartSpan( - spanContext, + activity1, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -520,13 +618,15 @@ public void SampleToLocalSpanStore() span.End(); Assert.True(((Span)span).IsSampleToLocalSpanStore); + + var activity2 = new Activity(SpanName).Start(); var span2 = Span.StartSpan( - spanContext, + activity2, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -543,13 +643,15 @@ public void SampleToLocalSpanStore() [Fact] public void SampleToLocalSpanStore_RunningSpan() { + var activity = new Activity(SpanName).Start(); + var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -560,13 +662,15 @@ public void SampleToLocalSpanStore_RunningSpan() [Fact] public void BadArguments() { + var activity = new Activity(SpanName).Start(); + var span = Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -588,12 +692,14 @@ public void BadArguments() [Fact] public void SetSampleTo() { + var activity = new Activity(SpanName).Start(); + var span = (Span)Span.StartSpan( - spanContext, + activity, + Tracestate.Empty, recordSpanOptions, SpanName, SpanKind.Internal, - parentSpanId, TraceParams.Default, startEndHandler, timestampConverter); @@ -602,5 +708,85 @@ public void SetSampleTo() span.End(); Assert.True(span.IsSampleToLocalSpanStore); } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void EndSpanStopsActivity(bool recordEvents) + { + var parentActivity = new Activity(SpanName).Start(); + var activity = new Activity(SpanName).Start(); + + var span = + Span.StartSpan( + activity, + Tracestate.Empty, + recordEvents ? recordSpanOptions : noRecordSpanOptions, + SpanName, + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + timestampConverter, + ownsActivity: true); + + span.End(); + Assert.Same(parentActivity, Activity.Current); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void EndSpanDoesNotStopActivityWhenDoesNotOwnIt(bool recordEvents) + { + var activity = new Activity(SpanName).Start(); + + var span = + Span.StartSpan( + activity, + Tracestate.Empty, + recordEvents ? recordSpanOptions : noRecordSpanOptions, + SpanName, + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + timestampConverter, + ownsActivity: false); + + span.End(); + Assert.Equal(recordEvents, span.HasEnded); + Assert.Same(activity, Activity.Current); + } + + [Theory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void EndSpanStopActivity_NotCurrentActivity(bool recordEvents, bool ownsActivity) + { + var activity = new Activity(SpanName).Start(); + + var span = + Span.StartSpan( + activity, + Tracestate.Empty, + recordEvents ? recordSpanOptions : noRecordSpanOptions, + SpanName, + SpanKind.Internal, + TraceParams.Default, + startEndHandler, + timestampConverter, + ownsActivity: ownsActivity); + + var anotherActivity = new Activity(SpanName).Start(); + span.End(); + Assert.Equal(recordEvents, span.HasEnded); + Assert.Same(anotherActivity, Activity.Current); + } + + public void Dispose() + { + Activity.Current = null; + } } } From 4952219a8eb443582c0985021135c1121d92ff83 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Sat, 13 Jul 2019 18:56:24 -0700 Subject: [PATCH 16/41] Remove remains of AttributeValue (#148) * remove remains of AttributeVakue * fix tests * fix tests --- .../OpenTelemetry.Abstractions.csproj | 4 + .../Trace/AttributeValue.cs | 126 -------------- .../Trace/Export/Attributes.cs | 4 +- .../Trace/Export/IAttributes.cs | 2 +- .../Trace/Export/LinkList.cs | 4 +- .../Trace/Export/TimedEvents.cs | 4 +- .../Trace/IAttributeValue.cs | 63 ------- .../Trace/Internal/AttributeValue{T}.cs | 156 ------------------ .../RedisProfilerEntryToSpanConverter.cs | 8 +- .../Implementation/TraceExporterHandler.cs | 10 -- src/OpenTelemetry/Trace/Span.cs | 24 +-- .../Utils/AttributesWithCapacity.cs | 53 +----- .../HttpClientTests.cs | 11 -- .../RedisProfilerEntryToSpanConverterTests.cs | 6 +- .../Impl/Trace/AttributeValueTest.cs | 81 --------- .../Impl/Trace/Export/SpanDataTest.cs | 4 +- .../Impl/Trace/LinkTest.cs | 8 +- .../Impl/Trace/SpanTest.cs | 15 +- 18 files changed, 54 insertions(+), 529 deletions(-) delete mode 100644 src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/IAttributeValue.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs diff --git a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj index 01a0b6200f1..54d3ce88609 100644 --- a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj +++ b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj @@ -10,4 +10,8 @@ + + + + \ No newline at end of file diff --git a/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs b/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs deleted file mode 100644 index c783ee16274..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/AttributeValue.cs +++ /dev/null @@ -1,126 +0,0 @@ -// -// 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; - - /// - /// Attribute value. - /// - public abstract class AttributeValue - { - internal AttributeValue() - { - } - - public enum Type - { - /// - /// A String AttributeValue - /// - String, - - /// - /// A Boolean AttributeValue - /// - Boolean, - - /// - /// A Long AttributeValue - /// - Long, - - /// - /// A Double AttributeValue - /// - Double, - } - - public static IAttributeValue StringAttributeValue(string stringValue) - { - if (stringValue == null) - { - throw new ArgumentNullException(nameof(stringValue)); - } - - return new AttributeValue(stringValue); - } - - /// - /// Creates long attribute value from value provided. - /// - /// Long value. - /// Attribute value encapsulating the provided long value. - public static IAttributeValue LongAttributeValue(long longValue) - { - return new AttributeValue(longValue); - } - - /// - /// Creates boolean attribute value from value provided. - /// - /// Boolean value. - /// Attribute value encapsulating the provided boolean value. - public static IAttributeValue BooleanAttributeValue(bool booleanValue) - { - return new AttributeValue(booleanValue); - } - - /// - /// Creates double attribute value from value provided. - /// - /// Double value. - /// Attribute value encapsulating the provided double value. - public static IAttributeValue DoubleAttributeValue(double doubleValue) - { - return new AttributeValue(doubleValue); - } - - public new abstract Type GetType(); - - /// - /// Creates string attribute value from value provided. - /// - /// String value of the AttributeValue. - public string GetStringValue() - { - throw new InvalidOperationException($"This type can only return {this.GetType()} data"); - } - - public bool GetBooleanValue() - { - throw new InvalidOperationException($"This type can only return {this.GetType()} data"); - } - - public long GetLongValue() - { - throw new InvalidOperationException($"This type can only return {this.GetType()} data"); - } - - public double GetDoubleValue() - { - throw new InvalidOperationException($"This type can only return {this.GetType()} data"); - } - - public abstract T Match( - Func stringFunction, - Func booleanFunction, - Func longFunction, - Func doubleFunction, - Func defaultFunction); - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs index e195d7f714a..e0562276916 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs @@ -23,6 +23,8 @@ namespace OpenTelemetry.Trace.Export public sealed class Attributes : IAttributes { + private static readonly Attributes Empty = new Attributes(new Dictionary(), 0); + internal Attributes(IDictionary attributeMap, int droppedAttributesCount) { this.AttributeMap = attributeMap ?? throw new ArgumentNullException("Null attributeMap"); @@ -37,7 +39,7 @@ public static Attributes Create(IDictionary attributeMap, int dr { if (attributeMap == null) { - throw new ArgumentNullException(nameof(attributeMap)); + return Empty; } IDictionary copy = new Dictionary(attributeMap); diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs index dd02449c252..39d59d928df 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs @@ -24,7 +24,7 @@ namespace OpenTelemetry.Trace.Export public interface IAttributes { /// - /// Gets tha dictionaty of attributes by name. + /// Gets the dictionary of attributes by name. /// IDictionary AttributeMap { get; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs index d2871940b46..fc1baabd640 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs @@ -22,6 +22,8 @@ namespace OpenTelemetry.Trace.Export public sealed class LinkList : ILinks { + private static readonly LinkList Empty = new LinkList(new ILink[0], 0); + internal LinkList(IEnumerable links, int droppedLinksCount) { this.Links = links ?? throw new ArgumentNullException("Null links"); @@ -36,7 +38,7 @@ public static LinkList Create(IEnumerable links, int droppedLinksCount) { if (links == null) { - throw new ArgumentNullException(nameof(links)); + return Empty; } IEnumerable copy = new List(links); diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs index 881ed44f503..4e9afac1762 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs @@ -22,6 +22,8 @@ namespace OpenTelemetry.Trace.Export public sealed class TimedEvents : ITimedEvents { + private static readonly TimedEvents Empty = new TimedEvents(new ITimedEvent[0], 0); + internal TimedEvents(IEnumerable> events, int droppedEventsCount) { this.Events = events ?? throw new ArgumentNullException("Null events"); @@ -36,7 +38,7 @@ public static ITimedEvents Create(IEnumerable> events, int dro { if (events == null) { - throw new ArgumentNullException(nameof(events)); + return Empty; } return new TimedEvents(events, droppedEventsCount); diff --git a/src/OpenTelemetry.Abstractions/Trace/IAttributeValue.cs b/src/OpenTelemetry.Abstractions/Trace/IAttributeValue.cs deleted file mode 100644 index 0424ef11934..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/IAttributeValue.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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; - - /// - /// Attribute value. - /// - public interface IAttributeValue - { - /// - /// Executes type-specific callback without type casting. - /// - /// Callback return value. - /// Callback to call for string. - /// Callback to call for boolean. - /// Callback to call for long. - /// Callback to call for double. - /// Callback to call for any other type. - /// Callback execution result. - T Match( - Func stringFunction, - Func booleanFunction, - Func longFunction, - Func doubleFunction, - Func defaultFunction); - } - - /// - /// Generic attribute value interface. - /// - /// Type of the attribute. - public interface IAttributeValue : IAttributeValue - { - /// - /// Gets the attribute value. - /// - TAttr Value { get; } - - /// - /// Executes type specific callback. - /// - /// Callback result type. - /// Callback to execute. - /// Result of callback execution. - T Apply(Func function); - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs b/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs deleted file mode 100644 index 36fa95fcb87..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/Internal/AttributeValue{T}.cs +++ /dev/null @@ -1,156 +0,0 @@ -// -// 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; - - /// - /// Generic attribute value. - /// - /// Type of the value carried by this attribute value. - internal sealed class AttributeValue : AttributeValue, IAttributeValue - { - internal AttributeValue(T value) - { - this.Value = value; - } - - /// - public T Value { get; } - - /// - /// Creates an attribute value from string. - /// - /// Value to populate attribute value with. - /// Attribute value with the given value. - public static IAttributeValue Create(string stringValue) - { - if (stringValue == null) - { - throw new ArgumentNullException(nameof(stringValue)); - } - - return new AttributeValue(stringValue); - } - - /// - /// Creates an attribute value from long. - /// - /// Value to populate attribute value with. - /// Attribute value with the given value. - public static IAttributeValue Create(long longValue) - { - return new AttributeValue(longValue); - } - - /// - /// Creates an attribute value from bool. - /// - /// Value to populate attribute value with. - /// Attribute value with the given value. - public static IAttributeValue Create(bool booleanValue) - { - return new AttributeValue(booleanValue); - } - - /// - /// Creates an attribute value from double. - /// - /// Value to populate attribute value with. - /// Attribute value with the given value. - public static IAttributeValue Create(double doubleValue) - { - return new AttributeValue(doubleValue); - } - - /// - public TArg Apply(Func function) - { - return function(this.Value); - } - - /// - public override bool Equals(object obj) - { - if (obj == this) - { - return true; - } - - if (obj is AttributeValue attribute) - { - return attribute.Value.Equals(this.Value); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.Value.GetHashCode(); - return h; - } - - /// - public override string ToString() - { - return "AttributeValue{" - + "Value=" + this.Value.ToString() - + "}"; - } - - public override Type GetType() - { - return this.GetType(); - } - - /// - public override TReturn Match( - Func stringFunction, - Func booleanFunction, - Func longFunction, - Func doubleFunction, - Func defaultFunction) - { - if (typeof(T) == typeof(string)) - { - var value = this.Value as string; - return stringFunction(value); - } - else if (typeof(T) == typeof(long)) - { - var val = (long)(object)this.Value; - return longFunction(val); - } - else if (typeof(T) == typeof(bool)) - { - var val = (bool)(object)this.Value; - return booleanFunction(val); - } - else if (typeof(T) == typeof(double)) - { - var val = (double)(object)this.Value; - return doubleFunction(val); - } - - return defaultFunction(this.Value); - } - } -} diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs index 27ac5522374..4cf8acc6e0c 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs @@ -124,22 +124,22 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n var attributesMap = new Dictionary() { // TODO: pre-allocate constant attribute and reuse - { "db.type", AttributeValue.StringAttributeValue("redis") }, + { "db.type", "redis" }, // Example: "redis.flags": None, DemandMaster - { "redis.flags", AttributeValue.StringAttributeValue(command.Flags.ToString()) }, + { "redis.flags", command.Flags.ToString() }, }; if (command.Command != null) { // Example: "db.statement": SET; - attributesMap.Add("db.statement", AttributeValue.StringAttributeValue(command.Command)); + attributesMap.Add("db.statement", command.Command); } if (command.EndPoint != null) { // Example: "db.instance": Unspecified/localhost:6379[0] - attributesMap.Add("db.instance", AttributeValue.StringAttributeValue(command.EndPoint.ToString() + "[" + command.Db + "]")); + attributesMap.Add("db.instance", command.EndPoint.ToString() + "[" + command.Db + "]"); } var attributes = Attributes.Create(attributesMap, 0); diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index 920900a6939..ac721b5c43b 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -122,16 +122,6 @@ private long ToEpochMicroseconds(Timestamp timestamp) return micros; } - private string AttributeValueToString(IAttributeValue attributeValue) - { - return attributeValue.Match( - (arg) => { return arg; }, - (arg) => { return arg.ToString(); }, - (arg) => { return arg.ToString(); }, - (arg) => { return arg.ToString(); }, - (arg) => { return null; }); - } - private string EncodeTraceId(ActivityTraceId traceId) { var id = traceId.ToHexString(); diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index d689a000da0..6b107c629bd 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -421,11 +421,10 @@ public SpanData ToSpanData() throw new InvalidOperationException("Getting SpanData for a Span without RECORD_EVENTS option."); } - var attributesSpanData = this.attributes == null ? Attributes.Create(new Dictionary(), 0) - : Attributes.Create(this.attributes, this.attributes.NumberOfDroppedAttributes); + var attributesSpanData = Attributes.Create(this.attributes, this.attributes?.NumberOfDroppedAttributes ?? 0); var annotationsSpanData = CreateTimedEvents(this.InitializedEvents, this.TimestampConverter); - var linksSpanData = this.links == null ? LinkList.Create(new List(), 0) : LinkList.Create(this.links.Events, this.links.NumberOfDroppedEvents); + var linksSpanData = LinkList.Create(this.links?.Events, this.links?.NumberOfDroppedEvents ?? 0); return SpanData.Create( this.Context, // TODO avoid using context, use Activity instead @@ -545,19 +544,20 @@ internal static ISpan StartSpan( private static ITimedEvents CreateTimedEvents(TraceEvents> events, Timer timestampConverter) { - if (events == null) + List> eventsList = null; + int numberOfDroppedEvents = 0; + if (events != null) { - IEnumerable> empty = Array.Empty>(); - return TimedEvents.Create(empty, 0); - } + eventsList = new List>(events.Events.Count); + foreach (var networkEvent in events.Events) + { + eventsList.Add(networkEvent.ToSpanDataTimedEvent(timestampConverter)); + } - var eventsList = new List>(events.Events.Count); - foreach (var networkEvent in events.Events) - { - eventsList.Add(networkEvent.ToSpanDataTimedEvent(timestampConverter)); + numberOfDroppedEvents = events.NumberOfDroppedEvents; } - return TimedEvents.Create(eventsList, events.NumberOfDroppedEvents); + return TimedEvents.Create(eventsList, numberOfDroppedEvents); } } } diff --git a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs index 0ef2199fbdf..31b393544c3 100644 --- a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs +++ b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs @@ -20,7 +20,6 @@ namespace OpenTelemetry.Utils using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; - using OpenTelemetry.Trace; internal class AttributesWithCapacity : IDictionary { @@ -33,57 +32,21 @@ public AttributesWithCapacity(int capacity) this.capacity = capacity; } - public int NumberOfDroppedAttributes - { - get - { - return this.totalRecordedAttributes - this.Count; - } - } + public int NumberOfDroppedAttributes => this.totalRecordedAttributes - this.Count; - public ICollection Keys - { - get - { - return (ICollection)this.@delegate.Keys; - } - } + public ICollection Keys => (ICollection)this.@delegate.Keys; - public ICollection Values - { - get - { - return (ICollection)this.@delegate.Values; - } - } + public ICollection Values => (ICollection)this.@delegate.Values; - public int Count - { - get - { - return this.@delegate.Count; - } - } + public int Count => this.@delegate.Count; - public bool IsReadOnly - { - get - { - return this.@delegate.IsReadOnly; - } - } + public bool IsReadOnly => this.@delegate.IsReadOnly; public object this[string key] { - get - { - return (IAttributeValue)this.@delegate[key]; - } + get => this.@delegate[key]; - set - { - this.@delegate[key] = value; - } + set => this.@delegate[key] = value; } public void PutAttribute(string key, object value) @@ -134,7 +97,7 @@ public bool TryGetValue(string key, out object value) value = null; if (this.ContainsKey(key)) { - value = (IAttributeValue)this.@delegate[key]; + value = this.@delegate[key]; return true; } diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index 2e87ec8ade1..5d2ea48299f 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -198,17 +198,6 @@ public async Task DebugIndividualTestAsync() await t; } - private string AttributeToSimpleString(IAttributeValue value) - { - return value.Match( - x => x.ToString(), - x => x ? "true" : "false", - x => x.ToString(), - x => x.ToString(), - x => x.ToString() - ); - } - private string NormaizeValues(string value, string host, int port) { return value.Replace("{host}", host).Replace("{port}", port.ToString()); diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index b1ae129ffb0..82245add764 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -57,7 +57,7 @@ public void ProfiledCommandToSpanDataSetsDbTypeAttributeAsRedis() var profiledCommand = new Mock(); var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); Assert.Contains("db.type", result.Attributes.AttributeMap.Keys); - Assert.Equal(AttributeValue.StringAttributeValue("redis"), result.Attributes.AttributeMap["db.type"]); + Assert.Equal("redis", result.Attributes.AttributeMap["db.type"]); } [Fact] @@ -67,7 +67,7 @@ public void ProfiledCommandToSpanDataUsesCommandAsDbStatementAttribute() profiledCommand.Setup(m => m.Command).Returns("SET"); var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "another name", default, profiledCommand.Object); Assert.Contains("db.statement", result.Attributes.AttributeMap.Keys); - Assert.Equal(AttributeValue.StringAttributeValue("SET"), result.Attributes.AttributeMap["db.statement"]); + Assert.Equal("SET", result.Attributes.AttributeMap["db.statement"]); } [Fact] @@ -78,7 +78,7 @@ public void ProfiledCommandToSpanDataUsesFlagsForFlagsAttribute() profiledCommand.Setup(m => m.Flags).Returns(expectedFlags); var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); Assert.Contains("redis.flags", result.Attributes.AttributeMap.Keys); - Assert.Equal(AttributeValue.StringAttributeValue("None, FireAndForget, NoRedirect"), result.Attributes.AttributeMap["redis.flags"]); + Assert.Equal("None, FireAndForget, NoRedirect", result.Attributes.AttributeMap["redis.flags"]); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs deleted file mode 100644 index ab28fce1566..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/AttributeValueTest.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// 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.Test -{ - using Xunit; - - public class AttributeValueTest - { - - [Fact] - public void StringAttributeValue() - { - var attribute = AttributeValue.Create("MyStringAttributeValue"); - attribute.Apply((stringValue) => - { - Assert.Equal("MyStringAttributeValue", stringValue); - return null; - }); - } - - [Fact] - public void BooleanAttributeValue() - { - var attribute = AttributeValue.Create(true); - attribute.Apply((boolValue) => - { - Assert.True(boolValue); - return null; - }); - } - - [Fact] - public void LongAttributeValue() - { - var attribute = AttributeValue.Create(123456L); - attribute.Apply((longValue) => - { - Assert.Equal(123456L, longValue); - return null; - }); - } - - [Fact] - public void DoubleAttributeValue() - { - var attribute = AttributeValue.Create(0.005); - attribute.Apply((val) => - { - Assert.Equal(0.005, val); - return null; - }); - } - - [Fact] - public void AttributeValue_ToString() - { - var attribute = AttributeValue.Create("MyStringAttributeValue"); - Assert.Contains("MyStringAttributeValue", attribute.ToString()); - var attribute2 = AttributeValue.Create(true); - Assert.Contains("True", attribute2.ToString()); - var attribute3 = AttributeValue.Create(123456L); - Assert.Contains("123456", attribute3.ToString()); - } - } -} - - diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index c47eab4bf66..fd0d77d1e8c 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -52,8 +52,8 @@ public SpanDataTest() spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); parentSpanId = ActivitySpanId.CreateRandom(); - attributesMap.Add("MyAttributeKey1", AttributeValue.LongAttributeValue(10)); - attributesMap.Add("MyAttributeKey2", AttributeValue.BooleanAttributeValue(true)); + attributesMap.Add("MyAttributeKey1", 10L); + attributesMap.Add("MyAttributeKey2", true); attributes = Attributes.Create(attributesMap, 1); eventList.Add(TimedEvent.Create(eventTimestamp1, spanEvent)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index 95959235a9f..839fe2a4524 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -36,10 +36,10 @@ public LinkTest() Activity.ForceDefaultIdFormat = true; spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); ; - attributesMap.Add("MyAttributeKey0", AttributeValue.Create("MyStringAttribute")); - attributesMap.Add("MyAttributeKey1", AttributeValue.Create(10)); - attributesMap.Add("MyAttributeKey2", AttributeValue.Create(true)); - attributesMap.Add("MyAttributeKey3", AttributeValue.Create(0.005)); + attributesMap.Add("MyAttributeKey0", "MyStringAttribute"); + attributesMap.Add("MyAttributeKey1", 10L); + attributesMap.Add("MyAttributeKey2", true); + attributesMap.Add("MyAttributeKey3", 0.005); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 21447921f45..37032d58590 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -47,14 +47,13 @@ public SpanTest() timestamp = Timestamp.FromDateTimeOffset(startTime); timestampConverter = Timer.StartNew(startTime, () => interval); - attributes.Add( - "MyStringAttributeKey", AttributeValue.StringAttributeValue("MyStringAttributeValue")); - attributes.Add("MyLongAttributeKey", AttributeValue.LongAttributeValue(123L)); - attributes.Add("MyBooleanAttributeKey", AttributeValue.BooleanAttributeValue(false)); - expectedAttributes = new Dictionary(attributes); - expectedAttributes.Add( - "MySingleStringAttributeKey", - "MySingleStringAttributeValue"); + attributes.Add("MyStringAttributeKey", "MyStringAttributeValue"); + attributes.Add("MyLongAttributeKey", 123L); + attributes.Add("MyBooleanAttributeKey", false); + expectedAttributes = new Dictionary(attributes) + { + ["MySingleStringAttributeKey"] = "MySingleStringAttributeValue", + }; } [Fact] From 1eef24fcec5b2d20088ac2cf834f998e54584be1 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Sat, 13 Jul 2019 19:07:01 -0700 Subject: [PATCH 17/41] More Attributes improvements (#149) * Remove IAttributes and change Dictionary to list * Optimize AtributesWithcapacity to use linked list instead of ordered disct and reduce copying --- .../Trace/Export/Attributes.cs | 18 +-- .../Trace/SpanData.cs | 10 +- .../Implementation/SpanDataExtensions.cs | 4 +- src/OpenTelemetry/Trace/Span.cs | 2 +- .../Utils/AttributesWithCapacity.cs | 137 +++++------------- .../AttributesExtensions.cs | 25 ++-- .../BasicTests.cs | 4 +- ...stsCollectionsIsAccordingToTheSpecTests.cs | 4 +- .../AttributesExtensions.cs | 29 ++++ .../RedisProfilerEntryToSpanConverterTests.cs | 22 ++- .../TraceExporterHandlerTests.cs | 2 +- .../Impl/Trace/AttributesExtensions.cs | 44 ++++++ .../Impl/Trace/Export/SpanDataTest.cs | 6 +- .../Impl/Trace/SpanTest.cs | 31 ++-- .../OpenTelemetry.Tests.csproj | 5 + 15 files changed, 180 insertions(+), 163 deletions(-) rename src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs => test/OpenTelemetry.Collector.AspNetCore.Tests/AttributesExtensions.cs (52%) create mode 100644 test/OpenTelemetry.Collector.StackExchangeRedis.Tests/AttributesExtensions.cs create mode 100644 test/OpenTelemetry.Tests/Impl/Trace/AttributesExtensions.cs diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs index e0562276916..876d4b751e0 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs @@ -18,32 +18,30 @@ namespace OpenTelemetry.Trace.Export { using System; using System.Collections.Generic; - using System.Collections.ObjectModel; using System.Linq; - public sealed class Attributes : IAttributes + public sealed class Attributes { private static readonly Attributes Empty = new Attributes(new Dictionary(), 0); - internal Attributes(IDictionary attributeMap, int droppedAttributesCount) + private Attributes(IEnumerable> attributeMap, int droppedAttributesCount) { - this.AttributeMap = attributeMap ?? throw new ArgumentNullException("Null attributeMap"); + this.AttributeMap = attributeMap ?? throw new ArgumentNullException(nameof(attributeMap)); this.DroppedAttributesCount = droppedAttributesCount; } - public IDictionary AttributeMap { get; } + public IEnumerable> AttributeMap { get; } public int DroppedAttributesCount { get; } - public static Attributes Create(IDictionary attributeMap, int droppedAttributesCount) + public static Attributes Create(IReadOnlyCollection> attributeMap, int droppedAttributesCount) { if (attributeMap == null) { return Empty; } - IDictionary copy = new Dictionary(attributeMap); - return new Attributes(new ReadOnlyDictionary(copy), droppedAttributesCount); + return new Attributes(attributeMap, droppedAttributesCount); } /// @@ -55,7 +53,7 @@ public override string ToString() + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) @@ -72,7 +70,7 @@ public override bool Equals(object o) return false; } - /// + /// public override int GetHashCode() { var h = 1; diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index b86f8ed5c8e..91add17358f 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -35,7 +35,7 @@ internal SpanData( Resource resource, string name, Timestamp startTimestamp, - IAttributes attributes, + Attributes attributes, ITimedEvents events, ILinks links, int? childSpanCount, @@ -78,9 +78,9 @@ internal SpanData( public string Name { get; } /// - /// Gets the collection of objects. + /// Gets the collection of objects. /// - public IAttributes Attributes { get; } + public Attributes Attributes { get; } /// /// Gets the collection of objects. @@ -125,7 +125,7 @@ internal SpanData( /// The this span was executed on. /// The name of the . /// The start of the . - /// The associated with the . + /// The associated with the . /// The associated with the . /// The associated with the . /// The associated with the . @@ -139,7 +139,7 @@ public static SpanData Create( Resource resource, string name, Timestamp startTimestamp, - IAttributes attributes, + Attributes attributes, ITimedEvents events, ILinks links, int? childSpanCount, diff --git a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs index 7a22303bd17..5c04c3f3b30 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs @@ -78,7 +78,7 @@ internal static Span ToProtoSpan(this SpanData spanData) }, SameProcessAsParentSpan = spanData.ParentSpanId != null, ChildSpanCount = spanData.ChildSpanCount.HasValue ? (uint)spanData.ChildSpanCount.Value : 0, - Attributes = FromIAttributes(spanData.Attributes), + Attributes = FromAttributes(spanData.Attributes), TimeEvents = FromITimeEvents(spanData.Events), Links = new Span.Types.Links { @@ -99,7 +99,7 @@ internal static Span ToProtoSpan(this SpanData spanData) return null; } - private static Span.Types.Attributes FromIAttributes(IAttributes source) + private static Span.Types.Attributes FromAttributes(Attributes source) { var attributes = new Span.Types.Attributes { diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index 6b107c629bd..ac3c07b9a6d 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -421,7 +421,7 @@ public SpanData ToSpanData() throw new InvalidOperationException("Getting SpanData for a Span without RECORD_EVENTS option."); } - var attributesSpanData = Attributes.Create(this.attributes, this.attributes?.NumberOfDroppedAttributes ?? 0); + var attributesSpanData = Attributes.Create(this.attributes?.AsReadOnlyCollection(), this.attributes?.NumberOfDroppedAttributes ?? 0); var annotationsSpanData = CreateTimedEvents(this.InitializedEvents, this.TimestampConverter); var linksSpanData = LinkList.Create(this.links?.Events, this.links?.NumberOfDroppedEvents ?? 0); diff --git a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs index 31b393544c3..60d91a6daf9 100644 --- a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs +++ b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs @@ -16,141 +16,78 @@ namespace OpenTelemetry.Utils { - using System.Collections; using System.Collections.Generic; - using System.Collections.Specialized; - using System.Linq; - internal class AttributesWithCapacity : IDictionary + internal class AttributesWithCapacity { - private readonly OrderedDictionary @delegate = new OrderedDictionary(); private readonly int capacity; + + private KeyValueListNode attributesHead = null; + private KeyValueListNode attributesTail = null; + private int totalRecordedAttributes; + private int count = 0; public AttributesWithCapacity(int capacity) { this.capacity = capacity; } - public int NumberOfDroppedAttributes => this.totalRecordedAttributes - this.Count; - - public ICollection Keys => (ICollection)this.@delegate.Keys; - - public ICollection Values => (ICollection)this.@delegate.Values; - - public int Count => this.@delegate.Count; - - public bool IsReadOnly => this.@delegate.IsReadOnly; - - public object this[string key] - { - get => this.@delegate[key]; - - set => this.@delegate[key] = value; - } + public int NumberOfDroppedAttributes => this.totalRecordedAttributes - this.count; public void PutAttribute(string key, object value) { this.totalRecordedAttributes += 1; - this[key] = value; - if (this.Count > this.capacity) + if (this.capacity == 0) { - this.@delegate.RemoveAt(0); + return; } - } - // Users must call this method instead of putAll to keep count of the total number of entries - // inserted. - public void PutAttributes(IDictionary attributes) - { - foreach (var kvp in attributes) + this.count++; + var next = new KeyValueListNode { - this.PutAttribute(kvp.Key, kvp.Value); - } - } - - public void Add(string key, object value) - { - this.@delegate.Add(key, value); - } + KeyValue = new KeyValuePair(key, value), + Next = null, + }; - public bool ContainsKey(string key) - { - return this.@delegate.Contains(key); - } - - public bool Remove(string key) - { - if (this.@delegate.Contains(key)) + if (this.attributesHead == null) { - this.@delegate.Remove(key); - return true; + this.attributesHead = next; + this.attributesTail = next; } else { - return false; - } - } - - public bool TryGetValue(string key, out object value) - { - value = null; - if (this.ContainsKey(key)) - { - value = this.@delegate[key]; - return true; - } - - return false; - } - - public void Add(KeyValuePair item) - { - this.@delegate.Add(item.Key, item.Value); - } - - public void Clear() - { - this.@delegate.Clear(); - } - - public bool Contains(KeyValuePair item) - { - var result = this.TryGetValue(item.Key, out var value); - if (result) - { - return value.Equals(item.Value); + this.attributesTail.Next = next; + this.attributesTail = next; + if (this.count > this.capacity) + { + this.attributesHead = this.attributesHead.Next; + this.count--; + } } - - return false; } - public void CopyTo(KeyValuePair[] array, int arrayIndex) + public IReadOnlyCollection> AsReadOnlyCollection() { - var entries = new DictionaryEntry[this.@delegate.Count]; - this.@delegate.CopyTo(entries, 0); + var result = new List>(); + var next = this.attributesHead; - for (var i = 0; i < entries.Length; i++) + while (next != null) { - array[i + arrayIndex] = new KeyValuePair((string)entries[i].Key, (object)entries[i].Value); + result.Add(new KeyValuePair(next.KeyValue.Key, next.KeyValue.Value)); + next = next.Next; } - } - public bool Remove(KeyValuePair item) - { - return this.Remove(item.Key); - } - - public IEnumerator> GetEnumerator() - { - var array = new KeyValuePair[this.@delegate.Count]; - this.CopyTo(array, 0); - return array.ToList().GetEnumerator(); + return result; } - IEnumerator IEnumerable.GetEnumerator() + /// + /// Having our own key-value linked list allows us to be more efficient. + /// + private class KeyValueListNode { - return this.@delegate.GetEnumerator(); + public KeyValuePair KeyValue; + public KeyValueListNode Next; } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/AttributesExtensions.cs similarity index 52% rename from src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs rename to test/OpenTelemetry.Collector.AspNetCore.Tests/AttributesExtensions.cs index 39d59d928df..859be9e52c1 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/IAttributes.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/AttributesExtensions.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,23 +14,16 @@ // limitations under the License. // -namespace OpenTelemetry.Trace.Export +namespace OpenTelemetry.Collector.AspNetCore.Tests { - using System.Collections.Generic; + using System.Linq; + using OpenTelemetry.Trace.Export; - /// - /// Attributes collection. - /// - public interface IAttributes + internal static class AttributesExtensions { - /// - /// Gets the dictionary of attributes by name. - /// - IDictionary AttributeMap { get; } - - /// - /// Gets the number of attributed dropped due to the limit. - /// - int DroppedAttributesCount { get; } + public static object GetValue(this Attributes attributes, string key) + { + return attributes.AttributeMap.FirstOrDefault(kvp => kvp.Key == key).Value; + } } } diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index c4a917c12ab..5ea0517c6fd 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -85,7 +85,7 @@ void ConfigureTestServices(IServiceCollection services) => var spanData = ((Span)startEndHandler.Invocations[1].Arguments[0]).ToSpanData(); Assert.Equal(SpanKind.Server, spanData.Kind); - Assert.Equal("/api/values", spanData.Attributes.AttributeMap["http.path"]); + Assert.Equal("/api/values", spanData.Attributes.GetValue("http.path")); } [Fact] @@ -143,7 +143,7 @@ public async Task SuccesfulTemplateControllerCallUsesParentContext() Assert.Equal(SpanKind.Server, spanData.Kind); Assert.Equal("api/Values/{id}", spanData.Name); - Assert.Equal("/api/values/2", spanData.Attributes.AttributeMap["http.path"]); + Assert.Equal("/api/values/2", spanData.Attributes.GetValue("http.path")); Assert.Equal(expectedTraceId, spanData.Context.TraceId); Assert.Equal(expectedSpanId, spanData.ParentSpanId); diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs index ab35d29ba2d..dbf82998d14 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/IncomingRequestsCollectionsIsAccordingToTheSpecTests.cs @@ -96,8 +96,8 @@ public async Task SuccesfulTemplateControllerCallGeneratesASpan() var spanData = ((Span)startEndHandler.Invocations[0].Arguments[0]).ToSpanData(); Assert.Equal(SpanKind.Server, spanData.Kind); - Assert.Equal("/api/values", spanData.Attributes.AttributeMap["http.path"]); - Assert.Equal(503L, spanData.Attributes.AttributeMap["http.status_code"]); + Assert.Equal("/api/values", spanData.Attributes.GetValue("http.path")); + Assert.Equal(503L, spanData.Attributes.GetValue("http.status_code")); } } } diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/AttributesExtensions.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/AttributesExtensions.cs new file mode 100644 index 00000000000..019aca5aa02 --- /dev/null +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/AttributesExtensions.cs @@ -0,0 +1,29 @@ +// +// 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.Collector.StackExchangeRedis.Tests +{ + using System.Linq; + using OpenTelemetry.Trace.Export; + + internal static class AttributesExtensions + { + public static object GetValue(this Attributes attributes, string key) + { + return attributes.AttributeMap.FirstOrDefault(kvp => kvp.Key == key).Value; + } + } +} diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index 82245add764..218dfdb4103 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -14,6 +14,9 @@ // limitations under the License. // +using System.Linq; +using OpenTelemetry.Collector.StackExchangeRedis.Tests; + namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation { using OpenTelemetry.Trace; @@ -56,8 +59,8 @@ public void ProfiledCommandToSpanDataSetsDbTypeAttributeAsRedis() { var profiledCommand = new Mock(); var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); - Assert.Contains("db.type", result.Attributes.AttributeMap.Keys); - Assert.Equal("redis", result.Attributes.AttributeMap["db.type"]); + Assert.Contains(result.Attributes.AttributeMap, kvp => kvp.Key == "db.type"); + Assert.Equal("redis", result.Attributes.GetValue("db.type")); } [Fact] @@ -66,19 +69,22 @@ public void ProfiledCommandToSpanDataUsesCommandAsDbStatementAttribute() var profiledCommand = new Mock(); profiledCommand.Setup(m => m.Command).Returns("SET"); var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "another name", default, profiledCommand.Object); - Assert.Contains("db.statement", result.Attributes.AttributeMap.Keys); - Assert.Equal("SET", result.Attributes.AttributeMap["db.statement"]); + Assert.Contains(result.Attributes.AttributeMap, kvp => kvp.Key == "db.statement"); + Assert.Equal("SET", result.Attributes.GetValue("db.statement")); } [Fact] public void ProfiledCommandToSpanDataUsesFlagsForFlagsAttribute() { var profiledCommand = new Mock(); - var expectedFlags = StackExchange.Redis.CommandFlags.FireAndForget | StackExchange.Redis.CommandFlags.NoRedirect; + var expectedFlags = StackExchange.Redis.CommandFlags.FireAndForget | + StackExchange.Redis.CommandFlags.NoRedirect; profiledCommand.Setup(m => m.Flags).Returns(expectedFlags); - var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); - Assert.Contains("redis.flags", result.Attributes.AttributeMap.Keys); - Assert.Equal("None, FireAndForget, NoRedirect", result.Attributes.AttributeMap["redis.flags"]); + var result = + RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, + profiledCommand.Object); + Assert.Contains(result.Attributes.AttributeMap, kvp => kvp.Key == "redis.flags"); + Assert.Equal("None, FireAndForget, NoRedirect", result.Attributes.GetValue("redis.flags")); } } } diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs index cfea4df7e17..26b51b4d737 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs @@ -1863,7 +1863,7 @@ private void GetDefaults( out Resource resource, out string name, out Timestamp startTimestamp, - out IAttributes attributes, + out Attributes attributes, out ITimedEvents events, out ILinks links, out int? childSpanCount, diff --git a/test/OpenTelemetry.Tests/Impl/Trace/AttributesExtensions.cs b/test/OpenTelemetry.Tests/Impl/Trace/AttributesExtensions.cs new file mode 100644 index 00000000000..6c6389894d9 --- /dev/null +++ b/test/OpenTelemetry.Tests/Impl/Trace/AttributesExtensions.cs @@ -0,0 +1,44 @@ +// +// 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 System.Collections.Generic; +using Xunit; + +namespace OpenTelemetry.Tests +{ + using System.Linq; + using OpenTelemetry.Trace.Export; + + internal static class AttributesExtensions + { + public static object GetValue(this Attributes attributes, string key) + { + return attributes.AttributeMap.FirstOrDefault(kvp => kvp.Key == key).Value; + } + + public static void AssertAreSame(this Attributes attributes, + IEnumerable> expectedAttributes) + { + var keyValuePairs = expectedAttributes as KeyValuePair[] ?? expectedAttributes.ToArray(); + Assert.Equal(attributes.AttributeMap.Count(), keyValuePairs.Count()); + + foreach (var attr in attributes.AttributeMap) + { + Assert.Contains(attr, keyValuePairs); + } + } + } +} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index fd0d77d1e8c..1c7b1899981 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -14,6 +14,8 @@ // limitations under the License. // +using System.Collections.ObjectModel; + namespace OpenTelemetry.Trace.Export.Test { using System.Collections.Generic; @@ -43,7 +45,7 @@ public class SpanDataTest private readonly List> eventList = new List>(); private readonly List linksList = new List(); - private readonly IAttributes attributes; + private readonly Attributes attributes; private readonly ITimedEvents events; private readonly LinkList links; @@ -54,7 +56,7 @@ public SpanDataTest() attributesMap.Add("MyAttributeKey1", 10L); attributesMap.Add("MyAttributeKey2", true); - attributes = Attributes.Create(attributesMap, 1); + attributes = Attributes.Create(new ReadOnlyDictionary(attributesMap), 1); eventList.Add(TimedEvent.Create(eventTimestamp1, spanEvent)); eventList.Add(TimedEvent.Create(eventTimestamp3, spanEvent)); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 37032d58590..7c22a723083 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.Tests; + namespace OpenTelemetry.Trace.Test { using System; @@ -39,7 +41,7 @@ public class SpanTest : IDisposable private readonly SpanOptions noRecordSpanOptions = SpanOptions.None; private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; private readonly IDictionary attributes = new Dictionary(); - private readonly IDictionary expectedAttributes; + private readonly List> expectedAttributes; private readonly IStartEndHandler startEndHandler = Mock.Of(); public SpanTest() @@ -50,9 +52,9 @@ public SpanTest() attributes.Add("MyStringAttributeKey", "MyStringAttributeValue"); attributes.Add("MyLongAttributeKey", 123L); attributes.Add("MyBooleanAttributeKey", false); - expectedAttributes = new Dictionary(attributes) + expectedAttributes = new List>(attributes) { - ["MySingleStringAttributeKey"] = "MySingleStringAttributeValue", + new KeyValuePair("MySingleStringAttributeKey", "MySingleStringAttributeValue") }; } @@ -228,7 +230,7 @@ public void ToSpanData_ActiveSpan() Assert.Equal(SpanName, spanData.Name); Assert.Equal(activity.ParentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); + spanData.Attributes.AssertAreSame(expectedAttributes); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), @@ -297,7 +299,8 @@ public void GoSpanData_EndedSpan() Assert.Equal(SpanName, spanData.Name); Assert.Equal(activity.ParentSpanId, spanData.ParentSpanId); Assert.Equal(0, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(expectedAttributes, spanData.Attributes.AttributeMap); + + spanData.Attributes.AssertAreSame(expectedAttributes); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), @@ -402,27 +405,27 @@ public void DroppingAttributes() var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); + Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count()); for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( i + maxNumberOfAttributes, spanData .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); + .GetValue("MyStringAttributeKey" + (i + maxNumberOfAttributes))); } span.End(); spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); + Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count()); for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( i + maxNumberOfAttributes, spanData .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); + .GetValue("MyStringAttributeKey" + (i + maxNumberOfAttributes))); } } @@ -457,14 +460,14 @@ public void DroppingAndAddingAttributes() var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); + Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count()); for (var i = 0; i < maxNumberOfAttributes; i++) { Assert.Equal( i + maxNumberOfAttributes, spanData .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes)]); + .GetValue("MyStringAttributeKey" + (i + maxNumberOfAttributes))); } for (var i = 0; i < maxNumberOfAttributes / 2; i++) @@ -480,7 +483,7 @@ public void DroppingAndAddingAttributes() spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfAttributes * 3 / 2, spanData.Attributes.DroppedAttributesCount); - Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count); + Assert.Equal(maxNumberOfAttributes, spanData.Attributes.AttributeMap.Count()); // Test that we still have in the attributes map the latest maxNumberOfAttributes / 2 entries. for (var i = 0; i < maxNumberOfAttributes / 2; i++) { @@ -488,14 +491,14 @@ public void DroppingAndAddingAttributes() i + maxNumberOfAttributes * 3 / 2, spanData .Attributes - .AttributeMap["MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2)]); + .GetValue("MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2))); } // Test that we have the newest re-added initial entries. for (var i = 0; i < maxNumberOfAttributes / 2; i++) { Assert.Equal(i, - spanData.Attributes.AttributeMap["MyStringAttributeKey" + i]); + spanData.Attributes.GetValue("MyStringAttributeKey" + i)); } } diff --git a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj index 57c5ecc2bb7..533c15f685c 100644 --- a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj +++ b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj @@ -4,6 +4,11 @@ net46;netcoreapp2.1 netcoreapp2.1 + + + + + From 8aae2c02f1760668734d99e848ca780e7635b578 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 15 Jul 2019 10:21:44 -0700 Subject: [PATCH 18/41] Clean up (#147) * Remove timestamp * Remove timestamp, remove Timer, remove Duration. remove Span Stores, remove EndSpanOptions and EndSpanOptionsBuilder * remove collections * clean up more collections and span name * missing files * dups * rebase issues --- .../Common/Duration.cs | 138 ------ .../Common/Timestamp.cs | 228 --------- .../Tags/TagValues.cs | 5 +- src/OpenTelemetry.Abstractions/Trace/Event.cs | 3 +- .../Export/IRunningPerSpanNameSummary.cs | 29 -- .../Export/ISampledLatencyBucketBoundaries.cs | 36 -- .../Export/ISampledPerSpanNameSummary.cs | 36 -- .../Trace/Export/ITimedEvent.cs | 4 +- .../Trace/Export/TimedEvent.cs | 13 +- src/OpenTelemetry.Abstractions/Trace/Link.cs | 2 +- .../Trace/SpanData.cs | 23 +- .../Utils/Collections.cs | 63 --- .../Utils/DoubleUtil.cs | 56 --- .../Utils/PreciseTimestamp.cs | 116 +++++ .../RedisProfilerEntryToSpanConverter.cs | 15 +- .../Implementation/TraceExporterHandler.cs | 11 +- .../Implementation/SpanDataExtensions.cs | 20 +- .../Implementation/SpanExtensions.cs | 2 +- .../Utils/ProtoExtensions.cs | 37 -- .../Implementation/TraceExporterHandler.cs | 7 +- src/OpenTelemetry/Common/Timer.cs | 81 ---- src/OpenTelemetry/OpenTelemetry.csproj | 1 + .../Stats/Aggregations/DistributionData.cs | 2 +- src/OpenTelemetry/Stats/BucketBoundaries.cs | 2 +- src/OpenTelemetry/Stats/MutableViewData.cs | 9 - src/OpenTelemetry/Stats/NoopViewManager.cs | 3 - src/OpenTelemetry/Stats/ViewData.cs | 10 +- src/OpenTelemetry/Tags/TagContextBase.cs | 10 +- src/OpenTelemetry/Trace/EndSpanOptions.cs | 95 ---- .../Trace/EndSpanOptionsBuilder.cs | 77 --- src/OpenTelemetry/Trace/EventWithTime.cs | 9 +- .../Trace/Export/ExportComponent.cs | 22 +- .../Trace/Export/LatencyBucketBoundaries.cs | 49 -- .../Trace/Export/NoopExportComponent.cs | 10 - .../Trace/Export/RunningPerSpanNameSummary.cs | 73 --- .../Trace/Export/SampledPerSpanNameSummary.cs | 90 ---- .../Trace/Export/SpanExporter.cs | 4 +- .../Trace/Export/SpanExporterWorker.cs | 5 +- .../Export/SpanStore/IRunningSpanStore.cs | 50 -- .../SpanStore/IRunningSpanStoreFilter.cs | 34 -- .../SpanStore/IRunningSpanStoreSummary.cs | 31 -- .../Export/SpanStore/ISampledSpanStore.cs | 68 --- .../SpanStore/ISampledSpanStoreErrorFilter.cs | 39 -- .../ISampledSpanStoreLatencyFilter.cs | 46 -- .../SpanStore/ISampledSpanStoreSummary.cs | 31 -- .../SpanStore/InProcessRunningSpanStore.cs | 101 ---- .../SpanStore/InProcessSampledSpanStore.cs | 443 ------------------ .../Export/SpanStore/NoopRunningSpanStore.cs | 52 -- .../Export/SpanStore/NoopSampledSpanStore.cs | 104 ---- .../Export/SpanStore/RunningSpanStoreBase.cs | 45 -- .../SpanStore/RunningSpanStoreFilter.cs | 80 ---- .../SpanStore/RunningSpanStoreSummary.cs | 77 --- .../Export/SpanStore/SampledSpanStoreBase.cs | 59 --- .../SpanStore/SampledSpanStoreErrorFilter.cs | 92 ---- .../SampledSpanStoreLatencyFilter.cs | 104 ---- .../SpanStore/SampledSpanStoreSummary.cs | 77 --- .../Trace/Internal/StartEndHandler.cs | 61 +-- src/OpenTelemetry/Trace/Span.cs | 148 +----- src/OpenTelemetry/Trace/SpanBuilder.cs | 18 +- src/OpenTelemetry/Trace/SpanOptions.cs | 37 -- src/OpenTelemetry/Trace/Tracer.cs | 3 +- src/OpenTelemetry/Trace/Tracing.cs | 2 - src/OpenTelemetry/Utils/Collections.cs | 71 --- .../Utils/ConcurrentIntrusiveList.cs | 115 ----- src/OpenTelemetry/Utils/IElement.cs | 36 -- .../RedisProfilerEntryToSpanConverterTests.cs | 3 +- .../TraceExporterHandlerTests.cs | 39 +- .../Impl/Common/DurationTest.cs | 76 --- .../Impl/Common/TimestampTest.cs | 161 ------- .../Impl/Stats/MeasureMapBuilderTest.cs | 42 +- .../Impl/Stats/MutableViewDataTest.cs | 13 - .../Impl/Stats/NoopViewManagerTest.cs | 55 ++- .../Impl/Stats/StatsTestUtil.cs | 3 - .../Impl/Stats/ViewManagerTest.cs | 362 +++++++------- .../Impl/Stats/ViewTest.cs | 52 +- .../Impl/Trace/CurrentSpanUtilsTest.cs | 71 ++- .../Impl/Trace/EndSpanOptionsTest.cs | 80 ---- .../Trace/Export/ExportComponentBaseTest.cs | 12 - .../Impl/Trace/Export/ExportComponentTest.cs | 14 - .../Export/InProcessRunningSpanStoreTest.cs | 148 ------ .../Export/InProcessSampledSpanStoreTest.cs | 409 ---------------- .../Trace/Export/NoopRunningSpanStoreTest.cs | 46 -- .../Trace/Export/NoopSampledSpanStoreTest.cs | 93 ---- .../Impl/Trace/Export/SpanDataTest.cs | 18 +- .../Impl/Trace/Export/SpanExporterTest.cs | 39 +- .../Internal/ConcurrentIntrusiveListTest.cs | 112 ----- .../Impl/Trace/LinkTest.cs | 5 +- .../Impl/Trace/NoopTracerTests.cs | 3 +- .../Impl/Trace/SpanBuilderTest.cs | 7 +- .../Impl/Trace/SpanTest.cs | 312 +++++------- .../OpenTelemetry.Tests.csproj | 4 + 91 files changed, 670 insertions(+), 4929 deletions(-) delete mode 100644 src/OpenTelemetry.Abstractions/Common/Duration.cs delete mode 100644 src/OpenTelemetry.Abstractions/Common/Timestamp.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/Export/IRunningPerSpanNameSummary.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/Export/ISampledLatencyBucketBoundaries.cs delete mode 100644 src/OpenTelemetry.Abstractions/Trace/Export/ISampledPerSpanNameSummary.cs delete mode 100644 src/OpenTelemetry.Abstractions/Utils/Collections.cs delete mode 100644 src/OpenTelemetry.Abstractions/Utils/DoubleUtil.cs create mode 100644 src/OpenTelemetry.Abstractions/Utils/PreciseTimestamp.cs delete mode 100644 src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs delete mode 100644 src/OpenTelemetry/Common/Timer.cs delete mode 100644 src/OpenTelemetry/Trace/EndSpanOptions.cs delete mode 100644 src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs delete mode 100644 src/OpenTelemetry/Trace/Export/LatencyBucketBoundaries.cs delete mode 100644 src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStore.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreFilter.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreSummary.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStore.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreErrorFilter.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreLatencyFilter.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreSummary.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/NoopRunningSpanStore.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreBase.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreBase.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreLatencyFilter.cs delete mode 100644 src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs delete mode 100644 src/OpenTelemetry/Trace/SpanOptions.cs delete mode 100644 src/OpenTelemetry/Utils/Collections.cs delete mode 100644 src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs delete mode 100644 src/OpenTelemetry/Utils/IElement.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Common/DurationTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs diff --git a/src/OpenTelemetry.Abstractions/Common/Duration.cs b/src/OpenTelemetry.Abstractions/Common/Duration.cs deleted file mode 100644 index b3019457f05..00000000000 --- a/src/OpenTelemetry.Abstractions/Common/Duration.cs +++ /dev/null @@ -1,138 +0,0 @@ -// -// 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.Common -{ - using System; - using System.Diagnostics; - - /// - /// Represents duration with the nanoseconds precition. - /// - [DebuggerDisplay("{ToString(),nq}")] - public sealed class Duration : IComparable - { - private const long MaxSeconds = 315576000000L; - private const int MaxNanos = 999999999; - private static readonly Duration Zero = new Duration(0, 0); - private readonly string stringRepresentation; - - private Duration(long seconds, int nanos) - { - this.Seconds = seconds; - this.Nanos = nanos; - this.stringRepresentation = $"Duration{{seconds={this.Seconds}, nanos={this.Nanos}}}"; - } - - /// - /// Gets the number of second in duration. - /// - public long Seconds { get; } - - /// - /// Gets the number of nanoseconds in duration. - /// - public int Nanos { get; } - - /// - /// Creates a new instance of class. - /// - /// Total seconds. - /// Nanoseconds part of a duration up to 999999999. - /// New instance of class. - public static Duration Create(long seconds, int nanos) - { - if (seconds < -MaxSeconds || seconds > MaxSeconds) - { - return Zero; - } - - if (nanos < -MaxNanos || nanos > MaxNanos) - { - return Zero; - } - - if ((seconds < 0 && nanos > 0) || (seconds > 0 && nanos < 0)) - { - return Zero; - } - - return new Duration(seconds, nanos); - } - - /// - /// Creates a new instance of class. - /// - /// Duration as TimeStamp. - /// New instance of class. - public static Duration Create(TimeSpan duration) - { - var seconds = duration.Ticks / TimeSpan.TicksPerSecond; - var nanoseconds = (int)(duration.Ticks % TimeSpan.TicksPerSecond) * 100; - return Create(seconds, nanoseconds); - } - - /// - /// Compares durations. - /// - /// instasnce to compare to. - /// Zero if equal, -1 when lesser and +1 when greater than given value. - public int CompareTo(Duration other) - { - var cmp = (this.Seconds < other.Seconds) ? -1 : ((this.Seconds > other.Seconds) ? 1 : 0); - if (cmp != 0) - { - return cmp; - } - - return (this.Nanos < other.Nanos) ? -1 : ((this.Nanos > other.Nanos) ? 1 : 0); - } - - /// - public override string ToString() - { - return this.stringRepresentation; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is Duration that) - { - return (this.Seconds == that.Seconds) - && (this.Nanos == that.Nanos); - } - - return false; - } - - /// - public override int GetHashCode() - { - long h = 1; - h *= 1000003; - h ^= (this.Seconds >> 32) ^ this.Seconds; - h *= 1000003; - h ^= this.Nanos; - return (int)h; - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Common/Timestamp.cs b/src/OpenTelemetry.Abstractions/Common/Timestamp.cs deleted file mode 100644 index 517eb175b22..00000000000 --- a/src/OpenTelemetry.Abstractions/Common/Timestamp.cs +++ /dev/null @@ -1,228 +0,0 @@ -// -// 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.Common -{ - using System; - using System.Diagnostics; - - /// - /// Timestamp with the nanoseconds precision. - /// - [DebuggerDisplay("{ToString(),nq}")] - public sealed class Timestamp : IComparable, IComparable - { - /// - /// Represents zero timestamp. - /// - public static readonly Timestamp Zero = new Timestamp(0, 0); - - private const long MaxSeconds = 315576000000L; - private const int MaxNanos = 999999999; - private const long MillisPerSecond = 1000L; - private const long NanosPerMilli = 1000 * 1000; - private const long NanosPerSecond = NanosPerMilli * MillisPerSecond; - private readonly string stringRepresentation; - - internal Timestamp(long seconds, int nanos) - { - this.Seconds = seconds; - this.Nanos = nanos; - this.stringRepresentation = $"Timestamp{{seconds={this.Seconds}, nanos={this.Nanos}}}"; - } - - /// - /// Gets the number of seconds since the Unix Epoch represented by this timestamp. - /// - public long Seconds { get; } - - /// - /// Gets the the number of nanoseconds after the number of seconds since the Unix Epoch represented - /// by this timestamp. - /// - public int Nanos { get; } - - /// - /// Creates an instance of class with the given seconds and nanoseconds values. - /// - /// Total number of seconds since the Unix Epoch represented by this . - /// The number of nanoseconds after the number of seconds since the Unix Epoch represented by this . - /// New instance of . - public static Timestamp Create(long seconds, int nanos) - { - if (seconds < -MaxSeconds || seconds > MaxSeconds) - { - return Zero; - } - - if (nanos < 0 || nanos > MaxNanos) - { - return Zero; - } - - return new Timestamp(seconds, nanos); - } - - /// - /// Creates an instance of class with the given total milliseconds since Unix Epoch. - /// - /// Total number of milliseconds since the Unix Epoch represented by this . - /// New instance of . - public static Timestamp FromMillis(long millis) - { - var nanos = millis * NanosPerMilli; - return Zero.Plus(0, nanos); - } - - /// - /// Creates an instance of class with the given time as . - /// - /// Time to convert to . - /// New instance of . - public static Timestamp FromDateTimeOffset(DateTimeOffset time) - { - long seconds = 0; -#if NET45 - var unixZero = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - seconds = (int)Math.Floor(time.Subtract(unixZero).TotalSeconds); -#else - seconds = time.ToUnixTimeSeconds(); -#endif - - var nanos = (int)time.Subtract(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).Subtract(TimeSpan.FromSeconds(seconds)).Ticks * 100; - return Timestamp.Create(seconds, nanos); - } - - /// - /// Adds duration to the timestamp. - /// - /// Duration to add to the timestamp. - /// Returns the timestamp with added duration. - public Timestamp AddDuration(Duration duration) - { - return this.Plus(duration.Seconds, duration.Nanos); - } - - /// - /// Adds nanosToAdd nanosecond to the current timestamp. - /// - /// Number of nanoseconds to add. - /// Returns the timstemp with added nanoseconds. - public Timestamp AddNanos(long nanosToAdd) - { - return this.Plus(0, nanosToAdd); - } - - /// - /// Substructs timestamp from the current timestamp. Typically to calculate duration. - /// - /// Timestamp to substruct. - /// Returns the timestamp with the substructed duration. - public Duration SubtractTimestamp(Timestamp timestamp) - { - var durationSeconds = this.Seconds - timestamp.Seconds; - var durationNanos = this.Nanos - timestamp.Nanos; - if (durationSeconds < 0 && durationNanos > 0) - { - durationSeconds += 1; - durationNanos = (int)(durationNanos - NanosPerSecond); - } - else if (durationSeconds > 0 && durationNanos < 0) - { - durationSeconds -= 1; - durationNanos = (int)(durationNanos + NanosPerSecond); - } - - return Duration.Create(durationSeconds, durationNanos); - } - - /// - public int CompareTo(Timestamp other) - { - var cmp = (this.Seconds < other.Seconds) ? -1 : ((this.Seconds > other.Seconds) ? 1 : 0); - if (cmp != 0) - { - return cmp; - } - - return (this.Nanos < other.Nanos) ? -1 : ((this.Nanos > other.Nanos) ? 1 : 0); - } - - /// - public int CompareTo(object obj) - { - if (obj is Timestamp timestamp) - { - return this.CompareTo(timestamp); - } - else - { - throw new InvalidOperationException(); - } - } - - /// - public override string ToString() - { - return this.stringRepresentation; - } - - /// - public override bool Equals(object o) - { - if (o is Timestamp that) - { - return (this.Seconds == that.Seconds) - && (this.Nanos == that.Nanos); - } - - return false; - } - - /// - public override int GetHashCode() - { - long h = 1; - h *= 1000003; - h ^= (this.Seconds >> 32) ^ this.Seconds; - h *= 1000003; - h ^= this.Nanos; - return (int)h; - } - - private static Timestamp OfSecond(long seconds, long nanoAdjustment) - { - var floor = (long)Math.Floor((double)nanoAdjustment / NanosPerSecond); - var secs = seconds + floor; - var nos = nanoAdjustment - (floor * NanosPerSecond); - return Create(secs, (int)nos); - } - - private Timestamp Plus(long secondsToAdd, long nanosToAdd) - { - if ((secondsToAdd | nanosToAdd) == 0) - { - return this; - } - - var sec = this.Seconds + secondsToAdd; - var nanoSeconds = Math.DivRem(nanosToAdd, NanosPerSecond, out var nanosSpill); - sec += nanoSeconds; - var nanoAdjustment = this.Nanos + nanosSpill; - return OfSecond(sec, nanoAdjustment); - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Tags/TagValues.cs b/src/OpenTelemetry.Abstractions/Tags/TagValues.cs index 46d66cd9ff3..10b1ba49df7 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagValues.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagValues.cs @@ -17,7 +17,6 @@ namespace OpenTelemetry.Tags { using System.Collections.Generic; - using OpenTelemetry.Abstractions.Utils; /// /// Collection of tags. @@ -47,9 +46,7 @@ public static TagValues Create(IReadOnlyList values) /// public override string ToString() { - return "TagValues{" - + "values=" + Collections.ToString(this.Values) - + "}"; + return "TagValues{values=" + string.Join(", ", this.Values) + "}"; } /// diff --git a/src/OpenTelemetry.Abstractions/Trace/Event.cs b/src/OpenTelemetry.Abstractions/Trace/Event.cs index f4cddb14977..52cf868281b 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Event.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Event.cs @@ -20,7 +20,6 @@ namespace OpenTelemetry.Trace using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; - using OpenTelemetry.Abstractions.Utils; /// public sealed class Event : IEvent @@ -102,7 +101,7 @@ public override string ToString() { return "Annotation{" + "description=" + this.Name + ", " - + "attributes=" + Collections.ToString(this.Attributes) + + "attributes=" + string.Join(", ", this.Attributes.Select(kvp => $"{kvp.Key}={kvp.Value}")) + "}"; } } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/IRunningPerSpanNameSummary.cs b/src/OpenTelemetry.Abstractions/Trace/Export/IRunningPerSpanNameSummary.cs deleted file mode 100644 index c41e3a4f476..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/Export/IRunningPerSpanNameSummary.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// 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.Export -{ - /// - /// Running spans summary. - /// - public interface IRunningPerSpanNameSummary - { - /// - /// Gets the number of the running span. - /// - int NumRunningSpans { get; } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/ISampledLatencyBucketBoundaries.cs b/src/OpenTelemetry.Abstractions/Trace/Export/ISampledLatencyBucketBoundaries.cs deleted file mode 100644 index d8bc73cd87e..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/Export/ISampledLatencyBucketBoundaries.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// 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.Export -{ - using System; - - /// - /// Sampoled spans latency buckets for histograms calculations. - /// - public interface ISampledLatencyBucketBoundaries - { - /// - /// Gets the lower latency boundary. - /// - TimeSpan LatencyLower { get; } - - /// - /// Gets the upper latency boundary. - /// - TimeSpan LatencyUpper { get; } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/ISampledPerSpanNameSummary.cs b/src/OpenTelemetry.Abstractions/Trace/Export/ISampledPerSpanNameSummary.cs deleted file mode 100644 index 89cc908a42b..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/Export/ISampledPerSpanNameSummary.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - /// - /// Summary of sampled spans. - /// - public interface ISampledPerSpanNameSummary - { - /// - /// Gets the number of sampled spans by latency boundary. - /// - IDictionary NumbersOfLatencySampledSpans { get; } - - /// - /// Gets the number of error sampled spans by error code. - /// - IDictionary NumbersOfErrorSampledSpans { get; } - } -} diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/ITimedEvent.cs b/src/OpenTelemetry.Abstractions/Trace/Export/ITimedEvent.cs index 70b06a71307..5ed967156c7 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/ITimedEvent.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/ITimedEvent.cs @@ -16,7 +16,7 @@ namespace OpenTelemetry.Trace.Export { - using OpenTelemetry.Common; + using System; /// /// Timed event. @@ -27,7 +27,7 @@ public interface ITimedEvent /// /// Gets the timestamp associated with this timed event. /// - Timestamp Timestamp { get; } + DateTime Timestamp { get; } /// /// Gets the typed event content. diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs index 82628de9cf9..47bf79c4720 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs @@ -16,23 +16,26 @@ namespace OpenTelemetry.Trace.Export { - using OpenTelemetry.Common; + using System; + using OpenTelemetry.Abstractions.Utils; public sealed class TimedEvent : ITimedEvent { - internal TimedEvent(Timestamp timestamp, T @event) + internal TimedEvent(DateTime timestamp, T @event) { this.Timestamp = timestamp; this.Event = @event; } - public Timestamp Timestamp { get; } + public DateTime Timestamp { get; } public T Event { get; } - public static ITimedEvent Create(Timestamp timestamp, T @event) + public static ITimedEvent Create(DateTime timestamp, T @event) { - return new TimedEvent(timestamp, @event); + return timestamp == default + ? new TimedEvent(PreciseTimestamp.GetUtcNow(), @event) + : new TimedEvent(timestamp, @event); } /// diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index a9b0dd43a8a..db1bca0882b 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -80,7 +80,7 @@ public override string ToString() + "traceId=" + this.Context.TraceId.ToHexString() + ", " + "spanId=" + this.Context.SpanId.ToHexString() + ", " + "tracestate=" + this.Context.Tracestate.ToString() + ", " - + "attributes=" + Collections.ToString(this.Attributes) + + "attributes=" + string.Join(", ", this.Attributes.Select(kvp => $"{kvp.Key}={kvp.Value}")) + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index 91add17358f..9534af325a8 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -20,7 +20,6 @@ namespace OpenTelemetry.Trace using System.Collections.Generic; using System.Diagnostics; using System.Linq; - using OpenTelemetry.Common; using OpenTelemetry.Resources; using OpenTelemetry.Trace.Export; @@ -34,20 +33,20 @@ internal SpanData( ActivitySpanId parentSpanId, Resource resource, string name, - Timestamp startTimestamp, + DateTime startTimestamp, Attributes attributes, ITimedEvents events, ILinks links, int? childSpanCount, Status status, SpanKind kind, - Timestamp endTimestamp) + DateTime endTimestamp) { this.Context = context ?? throw new ArgumentNullException(nameof(context)); this.ParentSpanId = parentSpanId; this.Resource = resource ?? throw new ArgumentNullException(nameof(resource)); this.Name = name ?? throw new ArgumentNullException(nameof(name)); - this.StartTimestamp = startTimestamp ?? throw new ArgumentNullException(nameof(startTimestamp)); + this.StartTimestamp = startTimestamp; this.Attributes = attributes ?? Export.Attributes.Create(new Dictionary(), 0); this.Events = events ?? TimedEvents.Create(Enumerable.Empty>(), 0); this.Links = links ?? LinkList.Create(Enumerable.Empty(), 0); @@ -108,14 +107,14 @@ internal SpanData( public SpanKind Kind { get; } /// - /// Gets the start . + /// Gets the start . /// - public Timestamp StartTimestamp { get; } + public DateTime StartTimestamp { get; } /// - /// Gets the end . + /// Gets the end . /// - public Timestamp EndTimestamp { get; } + public DateTime EndTimestamp { get; } /// /// Returns a new immutable . @@ -124,28 +123,28 @@ internal SpanData( /// The parent of the . null if the is a root. /// The this span was executed on. /// The name of the . - /// The start of the . + /// The start of the . /// The associated with the . /// The associated with the . /// The associated with the . /// The associated with the . /// The of the . /// The of the . - /// The end of the . + /// The end of the . /// A new immutable . public static SpanData Create( SpanContext context, ActivitySpanId parentSpanId, Resource resource, string name, - Timestamp startTimestamp, + DateTime startTimestamp, Attributes attributes, ITimedEvents events, ILinks links, int? childSpanCount, Status status, SpanKind kind, - Timestamp endTimestamp) + DateTime endTimestamp) { if (events == null) { diff --git a/src/OpenTelemetry.Abstractions/Utils/Collections.cs b/src/OpenTelemetry.Abstractions/Utils/Collections.cs deleted file mode 100644 index 8b85a7b7dc4..00000000000 --- a/src/OpenTelemetry.Abstractions/Utils/Collections.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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.Abstractions.Utils -{ - using System.Collections.Generic; - using System.Text; - - internal static class Collections - { - public static string ToString(IDictionary dict) - { - if (dict == null) - { - return "null"; - } - - var sb = new StringBuilder(); - foreach (var kvp in dict) - { - sb.Append(kvp.Key.ToString()); - sb.Append("="); - sb.Append(kvp.Value.ToString()); - sb.Append(" "); - } - - return sb.ToString(); - } - - public static string ToString(IEnumerable list) - { - if (list == null) - { - return "null"; - } - - var sb = new StringBuilder(); - foreach (var val in list) - { - if (val != null) - { - sb.Append(val.ToString()); - sb.Append(" "); - } - } - - return sb.ToString(); - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Utils/DoubleUtil.cs b/src/OpenTelemetry.Abstractions/Utils/DoubleUtil.cs deleted file mode 100644 index a913bd7b8cd..00000000000 --- a/src/OpenTelemetry.Abstractions/Utils/DoubleUtil.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// 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.Utils -{ - using System; - - internal static class DoubleUtil - { - public static long ToInt64(double arg) - { - if (double.IsPositiveInfinity(arg)) - { - return 0x7ff0000000000000L; - } - - if (double.IsNegativeInfinity(arg)) - { - unchecked - { - return (long)0xfff0000000000000L; - } - } - - if (double.IsNaN(arg)) - { - return 0x7ff8000000000000L; - } - - if (arg == double.MaxValue) - { - return long.MaxValue; - } - - if (arg == double.MinValue) - { - return long.MinValue; - } - - return Convert.ToInt64(arg); - } - } -} diff --git a/src/OpenTelemetry.Abstractions/Utils/PreciseTimestamp.cs b/src/OpenTelemetry.Abstractions/Utils/PreciseTimestamp.cs new file mode 100644 index 00000000000..62ca108e519 --- /dev/null +++ b/src/OpenTelemetry.Abstractions/Utils/PreciseTimestamp.cs @@ -0,0 +1,116 @@ +// +// 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. +// + +#if ABSTRACTIONS +namespace OpenTelemetry.Abstractions.Utils +#else +namespace OpenTelemetry.Utils +#endif +{ + using System; + using System.Diagnostics; +#if NET45 || NET46 + using System.Diagnostics.CodeAnalysis; + using System.Threading; +#endif + + internal class PreciseTimestamp + { + /// + /// Multiplier to convert Stopwatch ticks to TimeSpan ticks. + /// + internal static readonly double StopwatchTicksToTimeSpanTicks = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency; + +#if NET45 || NET46 + private static readonly Timer SyncTimeUpdater; + private static TimeSync timeSync = new TimeSync(); + + [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "Enforcing static fields initialization.")] + static PreciseTimestamp() + { + SyncTimeUpdater = InitializeSyncTimer(); + } +#endif + + /// + /// Returns high resolution (1 DateTime tick) current UTC DateTime. + /// + /// DateTime UTC now with high resolution. + public static DateTime GetUtcNow() + { +#if NET45 || NET46 + // DateTime.UtcNow accuracy on .NET Framework is ~16ms, this method + // uses combination of Stopwatch and DateTime to calculate accurate UtcNow. + + var tmp = timeSync; + + // Timer ticks need to be converted to DateTime ticks + long dateTimeTicksDiff = (long)((Stopwatch.GetTimestamp() - tmp.SyncStopwatchTicks) * StopwatchTicksToTimeSpanTicks); + + // DateTime.AddSeconds (or Milliseconds) rounds value to 1 ms, use AddTicks to prevent it + return tmp.SyncUtcNow.AddTicks(dateTimeTicksDiff); +#else + return DateTime.UtcNow; +#endif + } + +#if NET45 || NET46 + private static void Sync() + { + // wait for DateTime.UtcNow update to the next granular value + Thread.Sleep(1); + timeSync = new TimeSync(); + } + + private static Timer InitializeSyncTimer() + { + Timer timer; + + // Don't capture the current ExecutionContext and its AsyncLocals onto the timer causing them to live forever + bool restoreFlow = false; + try + { + if (!ExecutionContext.IsFlowSuppressed()) + { + ExecutionContext.SuppressFlow(); + restoreFlow = true; + } + + // fire timer every 2 hours, Stopwatch is not very precise over long periods of time, + // so we need to correct it from time to time + // https://docs.microsoft.com/en-us/windows/desktop/SysInfo/acquiring-high-resolution-time-stamps + timer = new Timer(s => { Sync(); }, null, 0, 7200000); + } + finally + { + // Restore the current ExecutionContext + if (restoreFlow) + { + ExecutionContext.RestoreFlow(); + } + } + + return timer; + } + + private class TimeSync + { + public readonly DateTime SyncUtcNow = DateTime.UtcNow; + public readonly long SyncStopwatchTicks = Stopwatch.GetTimestamp(); + } +#endif + } +} diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs index 4cf8acc6e0c..cd2f763d0cc 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs @@ -19,7 +19,6 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation using System; using System.Collections.Generic; using System.Diagnostics; - using OpenTelemetry.Common; using OpenTelemetry.Resources; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Export; @@ -100,19 +99,21 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n // command.ElapsedTime; // 00:00:32.4988020 // TODO: make timestamp with the better precision - var startTimestamp = Timestamp.FromMillis(new DateTimeOffset(command.CommandCreated).ToUnixTimeMilliseconds()); + var startTimestamp = command.CommandCreated; - var timestamp = new DateTimeOffset(command.CommandCreated).Add(command.CreationToEnqueued); + var enqueued = command.CommandCreated.Add(command.CreationToEnqueued); + var send = enqueued.Add(command.EnqueuedToSending); + var response = send.Add(command.SentToResponse); var events = TimedEvents.Create( new List>() { - TimedEvent.Create(Timestamp.FromMillis(timestamp.ToUnixTimeMilliseconds()), Event.Create("Enqueued")), - TimedEvent.Create(Timestamp.FromMillis((timestamp = timestamp.Add(command.EnqueuedToSending)).ToUnixTimeMilliseconds()), Event.Create("Sent")), - TimedEvent.Create(Timestamp.FromMillis(timestamp.Add(command.SentToResponse).ToUnixTimeMilliseconds()), Event.Create("ResponseRecieved")), + TimedEvent.Create(enqueued, Event.Create("Enqueued")), + TimedEvent.Create(send, Event.Create("Sent")), + TimedEvent.Create(response, Event.Create("ResponseRecieved")), }, droppedEventsCount: 0); - var endTimestamp = Timestamp.FromMillis(new DateTimeOffset(command.CommandCreated.Add(command.ElapsedTime)).ToUnixTimeMilliseconds()); + var endTimestamp = command.CommandCreated.Add(command.ElapsedTime); // TODO: deal with the re-transmission // command.RetransmissionOf; diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs index 46f064f505d..004b32cf335 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs @@ -134,9 +134,7 @@ public Task ExportAsync(IEnumerable spanDataList) if (t.Timestamp != null) { - var logTimestamp = DateTimeOffset.FromUnixTimeSeconds(t.Timestamp.Seconds); - logTimestamp = logTimestamp.Add(TimeSpan.FromTicks(t.Timestamp.Nanos / 100)); - log.Timestamp = logTimestamp; + log.Timestamp = t.Timestamp; } foreach (var attr in t.Event.Attributes) @@ -255,8 +253,7 @@ private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, ou } // 1 tick is 100 ns - timestamp = DateTimeOffset.FromUnixTimeSeconds(span.StartTimestamp.Seconds); - timestamp = timestamp.Add(TimeSpan.FromTicks(span.StartTimestamp.Nanos / 100)); + timestamp = new DateTimeOffset(span.StartTimestamp); name = span.Name; @@ -283,9 +280,7 @@ private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, ou } tracestate = span.Context.Tracestate; - - var durationTs = span.EndTimestamp.SubtractTimestamp(span.StartTimestamp); - duration = TimeSpan.FromTicks((durationTs.Seconds * TimeSpan.TicksPerSecond) + (durationTs.Nanos / 100)); + duration = span.EndTimestamp - span.StartTimestamp; } private void OverwriteSpanKindFromAttribute(string spanKindAttr, ref SpanKind resultKind) diff --git a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs index 5c04c3f3b30..08aaf77cb8f 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/Implementation/SpanDataExtensions.cs @@ -59,16 +59,8 @@ internal static Span ToProtoSpan(this SpanData spanData) SpanId = ByteString.CopyFrom(spanIdBytes.ToArray()), ParentSpanId = parentSpanIdString, - StartTime = new Timestamp - { - Nanos = spanData.StartTimestamp.Nanos, - Seconds = spanData.StartTimestamp.Seconds, - }, - EndTime = new Timestamp - { - Nanos = spanData.EndTimestamp.Nanos, - Seconds = spanData.EndTimestamp.Seconds, - }, + StartTime = spanData.StartTimestamp.ToTimestamp(), + EndTime = spanData.EndTimestamp.ToTimestamp(), Status = spanData.Status == null ? null : new OpenTelemetry.Proto.Trace.V1.Status @@ -76,7 +68,7 @@ internal static Span ToProtoSpan(this SpanData spanData) Code = (int)spanData.Status.CanonicalCode, Message = spanData.Status.Description ?? string.Empty, }, - SameProcessAsParentSpan = spanData.ParentSpanId != null, + SameProcessAsParentSpan = spanData.ParentSpanId != default, ChildSpanCount = spanData.ChildSpanCount.HasValue ? (uint)spanData.ChildSpanCount.Value : 0, Attributes = FromAttributes(spanData.Attributes), TimeEvents = FromITimeEvents(spanData.Events), @@ -169,11 +161,7 @@ private static Span.Types.TimeEvent FromITimeEvent(ITimedEvent source) { return new Span.Types.TimeEvent { - Time = new Timestamp - { - Nanos = source.Timestamp.Nanos, - Seconds = source.Timestamp.Seconds, - }, + Time = source.Timestamp.ToTimestamp(), Annotation = new Span.Types.TimeEvent.Types.Annotation { Description = new TruncatableString { Value = source.Event.Name }, diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs index 69d28fe3eff..51241c069f0 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/SpanExtensions.cs @@ -18,7 +18,7 @@ namespace OpenTelemetry.Exporter.Stackdriver.Implementation { using System.Linq; using Google.Cloud.Trace.V2; - using OpenTelemetry.Exporter.Stackdriver.Utils; + using Google.Protobuf.WellKnownTypes; using OpenTelemetry.Trace; internal static class SpanExtensions diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs deleted file mode 100644 index 0dcc47ec88f..00000000000 --- a/src/OpenTelemetry.Exporter.Stackdriver/Utils/ProtoExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// 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.Exporter.Stackdriver.Utils -{ - using OpenTelemetry.Common; - - /// - /// Translation methods from OpenTelemetry structures to common - /// Protobuf structures. - /// - public static class ProtoExtensions - { - /// - /// Translates OpenTelemetry Timestamp to Protobuf's timestamp. - /// - /// OpenTelemetry timestamp. - /// Protobuf's timestamp. - public static Google.Protobuf.WellKnownTypes.Timestamp ToTimestamp(this Timestamp timestamp) - { - return new Google.Protobuf.WellKnownTypes.Timestamp { Seconds = timestamp.Seconds, Nanos = timestamp.Nanos }; - } - } -} diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index ac721b5c43b..b43a65e56e2 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -25,7 +25,6 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; - using OpenTelemetry.Common; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Export; @@ -115,11 +114,9 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint return spanBuilder.Build(); } - private long ToEpochMicroseconds(Timestamp timestamp) + private long ToEpochMicroseconds(DateTime timestamp) { - var nanos = (timestamp.Seconds * NanosPerSecond) + timestamp.Nanos; - var micros = nanos / 1000L; - return micros; + return new DateTimeOffset(timestamp).ToUnixTimeMilliseconds() * 1000; } private string EncodeTraceId(ActivityTraceId traceId) diff --git a/src/OpenTelemetry/Common/Timer.cs b/src/OpenTelemetry/Common/Timer.cs deleted file mode 100644 index cdde22116c3..00000000000 --- a/src/OpenTelemetry/Common/Timer.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// 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.Internal -{ - using System; - using System.Diagnostics; - - /// - /// Gets the current time based on start time and precise duration. - /// - internal sealed class Timer - { - private readonly DateTimeOffset timestamp; - private readonly Func stopwatch; - - private Timer(DateTimeOffset timestamp, Func watch) - { - this.timestamp = timestamp; - this.stopwatch = watch; - } - - /// - /// Gets the time of creation of this timer. - /// - /// Time of this timer creation. - public DateTimeOffset StartTime - { - get - { - return this.timestamp; - } - } - - /// - /// Gets the current timestamp based on start time and high precision elapsed time. - /// - /// Current timestamp based on start time and high precision elapsed time. - public DateTimeOffset Now - { - get - { - return this.timestamp.Add(this.stopwatch()); - } - } - - /// - /// Creates a new instance of a timer. - /// - /// New insance of a timer. - public static Timer StartNew() - { - var stopwatch = Stopwatch.StartNew(); - return new Timer(DateTimeOffset.Now, () => stopwatch.Elapsed); - } - - /// - /// Creates a new instance of a timer with the given start time. Used for test purposes. - /// - /// Start time to use in this timer. - /// Stopwatch to use. Should be started. - /// New instance of a timer. - public static Timer StartNew(DateTimeOffset time, Func watch) - { - return new Timer(time, watch); - } - } -} diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index 0545bfff9d6..0598216a268 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -11,6 +11,7 @@ + diff --git a/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs b/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs index 388f3c79d50..6e9d8af59ad 100644 --- a/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs +++ b/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs @@ -90,7 +90,7 @@ public override string ToString() + "min=" + this.Min + ", " + "max=" + this.Max + ", " + "sumOfSquaredDeviations=" + this.SumOfSquaredDeviations + ", " - + "bucketCounts=" + Collections.ToString(this.BucketCounts) + + "bucketCounts=" + string.Join(", ", this.BucketCounts) + "}"; } diff --git a/src/OpenTelemetry/Stats/BucketBoundaries.cs b/src/OpenTelemetry/Stats/BucketBoundaries.cs index e856815bb6b..4c8bf07fa53 100644 --- a/src/OpenTelemetry/Stats/BucketBoundaries.cs +++ b/src/OpenTelemetry/Stats/BucketBoundaries.cs @@ -61,7 +61,7 @@ public static IBucketBoundaries Create(IEnumerable bucketBoundaries) public override string ToString() { return "BucketBoundaries{" - + "boundaries=" + Collections.ToString(this.Boundaries) + + "boundaries=" + string.Join(", ", this.Boundaries) + "}"; } diff --git a/src/OpenTelemetry/Stats/MutableViewData.cs b/src/OpenTelemetry/Stats/MutableViewData.cs index 350e6b25c06..3ea7de72faf 100644 --- a/src/OpenTelemetry/Stats/MutableViewData.cs +++ b/src/OpenTelemetry/Stats/MutableViewData.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Stats { using System; using System.Collections.Generic; - using OpenTelemetry.Common; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Tags; @@ -26,8 +25,6 @@ internal abstract class MutableViewData { internal static readonly TagValue UnknownTagValue = null; - internal static readonly Timestamp ZeroTimestamp = Timestamp.Create(0, 0); - private const long MillisPerSecond = 1000L; private const long NanosPerMilli = 1000 * 1000; @@ -112,12 +109,6 @@ internal static IReadOnlyList GetTagValues(IDictionary registeredViews = new Dictionary(); // Cached set of exported views. It must be set to null whenever a view is registered or diff --git a/src/OpenTelemetry/Stats/ViewData.cs b/src/OpenTelemetry/Stats/ViewData.cs index a60db008df2..39223bfb2c7 100644 --- a/src/OpenTelemetry/Stats/ViewData.cs +++ b/src/OpenTelemetry/Stats/ViewData.cs @@ -62,11 +62,11 @@ public static IViewData Create(IView view, IDictionary $"{kvp.Key} = {kvp.Value}")) + ", " + + "start=" + this.Start + ", " + + "end=" + this.End + + "}"; } /// diff --git a/src/OpenTelemetry/Tags/TagContextBase.cs b/src/OpenTelemetry/Tags/TagContextBase.cs index e13046d54de..ad36f8566ae 100644 --- a/src/OpenTelemetry/Tags/TagContextBase.cs +++ b/src/OpenTelemetry/Tags/TagContextBase.cs @@ -63,7 +63,15 @@ public override bool Equals(object other) tags2 = otherTags.ToList(); } - return Collections.AreEquivalent(tags1, tags2); + if (tags1.Count != tags2.Count) + { + return false; + } + + // TODO: this sounds scary, we should rework it along with Tags API + var c1Dist = tags1.Distinct().ToArray(); + var c2Dist = tags2.Distinct().ToArray(); + return c1Dist.Count() == c2Dist.Count() && c1Dist.Intersect(c2Dist).Count() == c1Dist.Count(); } /// diff --git a/src/OpenTelemetry/Trace/EndSpanOptions.cs b/src/OpenTelemetry/Trace/EndSpanOptions.cs deleted file mode 100644 index c13c3016174..00000000000 --- a/src/OpenTelemetry/Trace/EndSpanOptions.cs +++ /dev/null @@ -1,95 +0,0 @@ -// -// 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 -{ - /// - /// End span options. - /// - public class EndSpanOptions - { - /// - /// Default span completion options. - /// - public static readonly EndSpanOptions Default = new EndSpanOptions(false); - - internal EndSpanOptions() - { - } - - internal EndSpanOptions(bool sampleToLocalSpanStore, Status status = null) - { - this.SampleToLocalSpanStore = sampleToLocalSpanStore; - this.Status = status; - } - - /// - /// Gets a value indicating whether span needs to be stored into local store. - /// - public bool SampleToLocalSpanStore { get; } - - /// - /// Gets the span status. - /// - public Status Status { get; } - - /// - /// Gets the span builder. - /// - /// Returns builder to build span options. - public static EndSpanOptionsBuilder Builder() - { - return new EndSpanOptionsBuilder().SetSampleToLocalSpanStore(false); - } - - /// - public override bool Equals(object obj) - { - if (obj == this) - { - return true; - } - - if (obj is EndSpanOptions that) - { - return (this.SampleToLocalSpanStore == that.SampleToLocalSpanStore) - && ((this.Status == null) ? (that.Status == null) : this.Status.Equals(that.Status)); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.SampleToLocalSpanStore ? 1231 : 1237; - h *= 1000003; - h ^= (this.Status == null) ? 0 : this.Status.GetHashCode(); - return h; - } - - /// - public override string ToString() - { - return "EndSpanOptions{" - + "sampleToLocalSpanStore=" + this.SampleToLocalSpanStore + ", " - + "status=" + this.Status - + "}"; - } - } -} diff --git a/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs b/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs deleted file mode 100644 index 11c295ab8c7..00000000000 --- a/src/OpenTelemetry/Trace/EndSpanOptionsBuilder.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// 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; - - /// - /// End span options builder. - /// - public class EndSpanOptionsBuilder - { - private bool? sampleToLocalSpanStore; - private Status status; - - internal EndSpanOptionsBuilder() - { - } - - /// - /// Indicate whether span is intended for local spans store. - /// - /// Value indicating whether span is intended for local span store. - /// Span options builder for operations chaining. - public EndSpanOptionsBuilder SetSampleToLocalSpanStore(bool sampleToLocalSpanStore) - { - this.sampleToLocalSpanStore = sampleToLocalSpanStore; - return this; - } - - /// - /// Sets the span status. - /// - /// Span status. - /// Span options builder for the operations chaining. - public EndSpanOptionsBuilder SetStatus(Status status) - { - this.status = status; - return this; - } - - /// - /// Builds the span options. - /// - /// Span options instance. - public EndSpanOptions Build() - { - var missing = string.Empty; - if (!this.sampleToLocalSpanStore.HasValue) - { - missing += " sampleToLocalSpanStore"; - } - - if (!string.IsNullOrEmpty(missing)) - { - throw new ArgumentOutOfRangeException("Missing required properties:" + missing); - } - - return new EndSpanOptions( - this.sampleToLocalSpanStore.Value, - this.status); - } - } -} diff --git a/src/OpenTelemetry/Trace/EventWithTime.cs b/src/OpenTelemetry/Trace/EventWithTime.cs index 5cf0c30616f..b441ff1a3a9 100644 --- a/src/OpenTelemetry/Trace/EventWithTime.cs +++ b/src/OpenTelemetry/Trace/EventWithTime.cs @@ -17,24 +17,23 @@ namespace OpenTelemetry.Trace { using System; - using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Export; internal class EventWithTime { - private readonly DateTimeOffset nanoTime; + private readonly DateTime nanoTime; private readonly T @event; - public EventWithTime(DateTimeOffset nanoTime, T @event) + public EventWithTime(DateTime nanoTime, T @event) { this.nanoTime = nanoTime; this.@event = @event; } - internal ITimedEvent ToSpanDataTimedEvent(Timer timestampConverter) + internal ITimedEvent ToSpanDataTimedEvent() { - return TimedEvent.Create(Timestamp.FromDateTimeOffset(this.nanoTime), this.@event); + return TimedEvent.Create(this.nanoTime, this.@event); } } } diff --git a/src/OpenTelemetry/Trace/Export/ExportComponent.cs b/src/OpenTelemetry/Trace/Export/ExportComponent.cs index 21cd19b2b01..e1afa58fb8f 100644 --- a/src/OpenTelemetry/Trace/Export/ExportComponent.cs +++ b/src/OpenTelemetry/Trace/Export/ExportComponent.cs @@ -16,7 +16,7 @@ namespace OpenTelemetry.Trace.Export { - using OpenTelemetry.Common; + using System; using OpenTelemetry.Internal; /// @@ -25,19 +25,11 @@ public sealed class ExportComponent : IExportComponent private const int ExporterBufferSize = 32; // Enforces that trace export exports data at least once every 5 seconds. - private static readonly Duration ExporterScheduleDelay = Duration.Create(5, 0); + private static readonly TimeSpan ExporterScheduleDelay = TimeSpan.FromSeconds(5); private ExportComponent(bool supportInProcessStores, IEventQueue eventQueue) { this.SpanExporter = Export.SpanExporter.Create(ExporterBufferSize, ExporterScheduleDelay); - this.RunningSpanStore = - supportInProcessStores - ? new InProcessRunningSpanStore() - : Export.RunningSpanStoreBase.NoopRunningSpanStore; - this.SampledSpanStore = - supportInProcessStores - ? new InProcessSampledSpanStore(eventQueue) - : Export.SampledSpanStoreBase.NoopSampledSpanStore; } /// @@ -48,16 +40,6 @@ private ExportComponent(bool supportInProcessStores, IEventQueue eventQueue) /// public ISpanExporter SpanExporter { get; } - /// - /// Gets the running span store. - /// - public IRunningSpanStore RunningSpanStore { get; } - - /// - /// Gets the sampled span store. - /// - public ISampledSpanStore SampledSpanStore { get; } - /// /// Constructs a new with noop span stores. /// diff --git a/src/OpenTelemetry/Trace/Export/LatencyBucketBoundaries.cs b/src/OpenTelemetry/Trace/Export/LatencyBucketBoundaries.cs deleted file mode 100644 index e9ba1347f08..00000000000 --- a/src/OpenTelemetry/Trace/Export/LatencyBucketBoundaries.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - - public class LatencyBucketBoundaries : ISampledLatencyBucketBoundaries - { - public static readonly ISampledLatencyBucketBoundaries ZeroMicrosx10 = new LatencyBucketBoundaries(TimeSpan.Zero, TimeSpan.FromTicks(100)); - public static readonly ISampledLatencyBucketBoundaries Microsx10Microsx100 = new LatencyBucketBoundaries(TimeSpan.FromTicks(100), TimeSpan.FromTicks(1000)); - public static readonly ISampledLatencyBucketBoundaries Microsx100Millix1 = new LatencyBucketBoundaries(TimeSpan.FromTicks(1000), TimeSpan.FromMilliseconds(1)); - public static readonly ISampledLatencyBucketBoundaries Millix1Millix10 = new LatencyBucketBoundaries(TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(10)); - public static readonly ISampledLatencyBucketBoundaries Millix10Millix100 = new LatencyBucketBoundaries(TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(100)); - public static readonly ISampledLatencyBucketBoundaries Millix100Secondx1 = new LatencyBucketBoundaries(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); - public static readonly ISampledLatencyBucketBoundaries Secondx1Secondx10 = new LatencyBucketBoundaries(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10)); - public static readonly ISampledLatencyBucketBoundaries Secondx10Secondx100 = new LatencyBucketBoundaries(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(100)); - public static readonly ISampledLatencyBucketBoundaries Secondx100Max = new LatencyBucketBoundaries(TimeSpan.FromSeconds(100), TimeSpan.MaxValue); - - public static IReadOnlyList Values = new List - { - ZeroMicrosx10, Microsx10Microsx100, Microsx100Millix1, Millix1Millix10, Millix10Millix100, Millix100Secondx1, Secondx1Secondx10, Secondx10Secondx100, Secondx100Max, - }; - - internal LatencyBucketBoundaries(TimeSpan latencyLowerNs, TimeSpan latencyUpperNs) - { - this.LatencyLower = latencyLowerNs; - this.LatencyUpper = latencyUpperNs; - } - - public TimeSpan LatencyLower { get; } - - public TimeSpan LatencyUpper { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs b/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs index 924c88234d2..b344d15c960 100644 --- a/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs +++ b/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs @@ -21,15 +21,5 @@ public sealed class NoopExportComponent : IExportComponent { /// public ISpanExporter SpanExporter => Export.SpanExporter.NoopSpanExporter; - - /// - /// Gets the running span store. - /// - public IRunningSpanStore RunningSpanStore => Export.RunningSpanStoreBase.NoopRunningSpanStore; - - /// - /// Gets the sampled span store. - /// - public ISampledSpanStore SampledSpanStore { get; } = Export.SampledSpanStoreBase.NewNoopSampledSpanStore; } } diff --git a/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs b/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs deleted file mode 100644 index 359973f67a6..00000000000 --- a/src/OpenTelemetry/Trace/Export/RunningPerSpanNameSummary.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// 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.Export -{ - using System; - - public sealed class RunningPerSpanNameSummary : IRunningPerSpanNameSummary - { - internal RunningPerSpanNameSummary(int numRunningSpans) - { - this.NumRunningSpans = numRunningSpans; - } - - public int NumRunningSpans { get; } - - public static IRunningPerSpanNameSummary Create(int numRunningSpans) - { - if (numRunningSpans < 0) - { - throw new ArgumentOutOfRangeException("Negative numRunningSpans."); - } - - return new RunningPerSpanNameSummary(numRunningSpans); - } - - /// - public override string ToString() - { - return "RunningPerSpanNameSummary{" - + "numRunningSpans=" + this.NumRunningSpans - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is RunningPerSpanNameSummary that) - { - return this.NumRunningSpans == that.NumRunningSpans; - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.NumRunningSpans; - return h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs b/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs deleted file mode 100644 index 24a8669cf93..00000000000 --- a/src/OpenTelemetry/Trace/Export/SampledPerSpanNameSummary.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; - - public sealed class SampledPerSpanNameSummary : ISampledPerSpanNameSummary - { - internal SampledPerSpanNameSummary(IDictionary numbersOfLatencySampledSpans, IDictionary numbersOfErrorSampledSpans) - { - this.NumbersOfLatencySampledSpans = numbersOfLatencySampledSpans ?? throw new ArgumentNullException(nameof(numbersOfLatencySampledSpans)); - this.NumbersOfErrorSampledSpans = numbersOfErrorSampledSpans ?? throw new ArgumentNullException(nameof(numbersOfErrorSampledSpans)); - } - - public IDictionary NumbersOfLatencySampledSpans { get; } - - public IDictionary NumbersOfErrorSampledSpans { get; } - - public static ISampledPerSpanNameSummary Create(IDictionary numbersOfLatencySampledSpans, IDictionary numbersOfErrorSampledSpans) - { - if (numbersOfLatencySampledSpans == null) - { - throw new ArgumentNullException(nameof(numbersOfLatencySampledSpans)); - } - - if (numbersOfErrorSampledSpans == null) - { - throw new ArgumentNullException(nameof(numbersOfErrorSampledSpans)); - } - - IDictionary copy1 = new Dictionary(numbersOfLatencySampledSpans); - IDictionary copy2 = new Dictionary(numbersOfErrorSampledSpans); - return new SampledPerSpanNameSummary(new ReadOnlyDictionary(copy1), new ReadOnlyDictionary(copy2)); - } - - /// - public override string ToString() - { - return "SampledPerSpanNameSummary{" - + "numbersOfLatencySampledSpans=" + this.NumbersOfLatencySampledSpans + ", " - + "numbersOfErrorSampledSpans=" + this.NumbersOfErrorSampledSpans - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is SampledPerSpanNameSummary that) - { - return this.NumbersOfLatencySampledSpans.SequenceEqual(that.NumbersOfLatencySampledSpans) - && this.NumbersOfErrorSampledSpans.SequenceEqual(that.NumbersOfErrorSampledSpans); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.NumbersOfLatencySampledSpans.GetHashCode(); - h *= 1000003; - h ^= this.NumbersOfErrorSampledSpans.GetHashCode(); - return h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanExporter.cs b/src/OpenTelemetry/Trace/Export/SpanExporter.cs index dc7081dd366..a6a5d90766d 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporter.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporter.cs @@ -16,9 +16,9 @@ namespace OpenTelemetry.Trace.Export { + using System; using System.Threading; using System.Threading.Tasks; - using OpenTelemetry.Common; public sealed class SpanExporter : SpanExporterBase { @@ -71,7 +71,7 @@ public override void Dispose() this.worker.Dispose(); } - internal static ISpanExporter Create(int bufferSize, Duration scheduleDelay) + internal static ISpanExporter Create(int bufferSize, TimeSpan scheduleDelay) { var worker = new SpanExporterWorker(bufferSize, scheduleDelay); return new SpanExporter(worker); diff --git a/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs b/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs index becf77c0aa1..fdc89456b58 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporterWorker.cs @@ -1,4 +1,4 @@ -// +// // Copyright 2018, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ namespace OpenTelemetry.Trace.Export using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; - using OpenTelemetry.Common; using OpenTelemetry.Implementation; internal class SpanExporterWorker : IDisposable @@ -32,7 +31,7 @@ internal class SpanExporterWorker : IDisposable private readonly TimeSpan scheduleDelay; private bool shutdown = false; - public SpanExporterWorker(int bufferSize, Duration scheduleDelay) + public SpanExporterWorker(int bufferSize, TimeSpan scheduleDelay) { this.bufferSize = bufferSize; this.scheduleDelay = TimeSpan.FromSeconds(scheduleDelay.Seconds); diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStore.cs deleted file mode 100644 index 78f0b300e3e..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStore.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - /// - /// Running spans store. - /// - public interface IRunningSpanStore - { - /// - /// Gets the summary of this store. - /// - IRunningSpanStoreSummary Summary { get; } - - /// - /// Gets the list of all running spans with the applied filter. - /// - /// Filter to apply to query running spans. - /// List of currently running spans. - IEnumerable GetRunningSpans(IRunningSpanStoreFilter filter); - - /// - /// Called when span got started. - /// - /// Span that was just started. - void OnStart(ISpan span); - - /// - /// Called when span just ended. - /// - /// Span that just ended. - void OnEnd(ISpan span); - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreFilter.cs deleted file mode 100644 index de8db381694..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreFilter.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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.Export -{ - /// - /// Filter to query spans from the running spans store. - /// - public interface IRunningSpanStoreFilter - { - /// - /// Gets the name of the span to query. - /// - string SpanName { get; } - - /// - /// Gets the maximum number of spans to return. - /// - int MaxSpansToReturn { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreSummary.cs b/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreSummary.cs deleted file mode 100644 index 6ab1b67c70f..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/IRunningSpanStoreSummary.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - /// - /// Summary of all running spans. - /// - public interface IRunningSpanStoreSummary - { - /// - /// Gets the summary of running spans per span name. - /// - IDictionary PerSpanNameSummary { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStore.cs deleted file mode 100644 index ce01a70b7f8..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStore.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - /// - /// Samples spans store. - /// - public interface ISampledSpanStore - { - /// - /// Gets the summary of sampled spans. - /// - ISampledSpanStoreSummary Summary { get; } - - /// - /// Gets all registered span names. - /// - ISet RegisteredSpanNamesForCollection { get; } - - /// - /// Gets the list of sampled spans using the provided filter. - /// - /// Filter to use to query sampled store. - /// List of spans satisfying filtering criteria. - IEnumerable GetLatencySampledSpans(ISampledSpanStoreLatencyFilter filter); - - /// - /// Gets the list of error spans using provided error filter. - /// - /// Filter to use to query store. - /// List of sampled spans satisfying filtering criteria. - IEnumerable GetErrorSampledSpans(ISampledSpanStoreErrorFilter filter); - - /// - /// Registers span names for collection. - /// - /// List of span names. - void RegisterSpanNamesForCollection(IEnumerable spanNames); - - /// - /// Unregister span names for the collection. - /// - /// Span names to unregister. - void UnregisterSpanNamesForCollection(IEnumerable spanNames); - - /// - /// Consider span for sampling. - /// - /// Span to consider. - void ConsiderForSampling(ISpan span); - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreErrorFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreErrorFilter.cs deleted file mode 100644 index a1f33774e1f..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreErrorFilter.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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.Export -{ - /// - /// Sampled spans store error filter. - /// - public interface ISampledSpanStoreErrorFilter - { - /// - /// Gets the span name to use to filter. - /// - string SpanName { get; } - - /// - /// Gets the cannonical code to use to filter. - /// - CanonicalCode? CanonicalCode { get; } - - /// - /// Gets the maximum number of spans to return. - /// - int MaxSpansToReturn { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreLatencyFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreLatencyFilter.cs deleted file mode 100644 index 3fe37575875..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreLatencyFilter.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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.Export -{ - using System; - - /// - /// Sampled span store latency filter. - /// - public interface ISampledSpanStoreLatencyFilter - { - /// - /// Gets the span name to filter by. - /// - string SpanName { get; } - - /// - /// Gets the latency lower boundery to filter by. - /// - TimeSpan LatencyLower { get; } - - /// - /// Gets the latency upper boundary to filter by. - /// - TimeSpan LatencyUpper { get; } - - /// - /// Gets the maximum number of spans to return. - /// - int MaxSpansToReturn { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreSummary.cs b/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreSummary.cs deleted file mode 100644 index 367db8d54ec..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/ISampledSpanStoreSummary.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - /// - /// Summary of sampled spans store. - /// - public interface ISampledSpanStoreSummary - { - /// - /// Gets the collection of summaries by span name. - /// - IDictionary PerSpanNameSummary { get; } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs deleted file mode 100644 index fa7be4f662c..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessRunningSpanStore.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - using OpenTelemetry.Utils; - - /// - public sealed class InProcessRunningSpanStore : RunningSpanStoreBase - { - private readonly ConcurrentIntrusiveList runningSpans; - - /// - /// Constructs a new . - /// - public InProcessRunningSpanStore() - { - this.runningSpans = new ConcurrentIntrusiveList(); - } - - /// - public override IRunningSpanStoreSummary Summary - { - get - { - IEnumerable allRunningSpans = this.runningSpans.Copy(); - var numSpansPerName = new Dictionary(); - foreach (var span in allRunningSpans) - { - numSpansPerName.TryGetValue(span.Name, out var prevValue); - numSpansPerName[span.Name] = prevValue + 1; - } - - var perSpanNameSummary = new Dictionary(); - foreach (var it in numSpansPerName) - { - var numRunningSpans = it.Value; - var runningPerSpanNameSummary = RunningPerSpanNameSummary.Create(numRunningSpans); - perSpanNameSummary[it.Key] = runningPerSpanNameSummary; - } - - var summary = RunningSpanStoreSummary.Create(perSpanNameSummary); - return summary; - } - } - - /// - public override IEnumerable GetRunningSpans(IRunningSpanStoreFilter filter) - { - IReadOnlyCollection allRunningSpans = this.runningSpans.Copy(); - var maxSpansToReturn = filter.MaxSpansToReturn == 0 ? allRunningSpans.Count : filter.MaxSpansToReturn; - var ret = new List(maxSpansToReturn); - foreach (var span in allRunningSpans) - { - if (ret.Count == maxSpansToReturn) - { - break; - } - - if (span.Name.Equals(filter.SpanName)) - { - ret.Add(span.ToSpanData()); - } - } - - return ret; - } - - /// - public override void OnEnd(ISpan span) - { - if (span is Span spanBase) - { - this.runningSpans.RemoveElement(spanBase); - } - } - - /// - public override void OnStart(ISpan span) - { - if (span is Span spanBase) - { - this.runningSpans.AddElement(spanBase); - } - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs deleted file mode 100644 index 2af6f5b0fe7..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/InProcessSampledSpanStore.cs +++ /dev/null @@ -1,443 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using OpenTelemetry.Internal; - using OpenTelemetry.Utils; - - /// - public sealed class InProcessSampledSpanStore : SampledSpanStoreBase - { - private const int NumSamplesPerLatencySamples = 10; - private const int NumSamplesPerErrorSamples = 5; - // The total number of canonical codes - 1 (the OK code). - private const int NumErrorBuckets = 17 - 1; // CanonicalCode.values().length - 1; - - private static readonly int NumLatencyBuckets = LatencyBucketBoundaries.Values.Count; - private static readonly int MaxPerSpanNameSamples = - (NumSamplesPerLatencySamples * NumLatencyBuckets) - + (NumSamplesPerErrorSamples * NumErrorBuckets); - - private static readonly TimeSpan TimeBetweenSamples = TimeSpan.FromSeconds(1); - - private readonly IEventQueue eventQueue; - private readonly Dictionary samples; - - internal InProcessSampledSpanStore(IEventQueue eventQueue) - { - this.samples = new Dictionary(); - this.eventQueue = eventQueue; - } - - /// - public override ISampledSpanStoreSummary Summary - { - get - { - var ret = new Dictionary(); - lock (this.samples) - { - foreach (var it in this.samples) - { - ret[it.Key] = SampledPerSpanNameSummary.Create(it.Value.GetNumbersOfLatencySampledSpans(), it.Value.GetNumbersOfErrorSampledSpans()); - } - } - - return SampledSpanStoreSummary.Create(ret); - } - } - - /// - public override ISet RegisteredSpanNamesForCollection - { - get - { - lock (this.samples) - { - return new HashSet(this.samples.Keys); - } - } - } - - /// - public override void ConsiderForSampling(ISpan ispan) - { - if (ispan is Span span) - { - lock (this.samples) - { - var spanName = span.Name; - if (span.IsSampleToLocalSpanStore && !this.samples.ContainsKey(spanName)) - { - this.samples[spanName] = new PerSpanNameSamples(); - } - - this.samples.TryGetValue(spanName, out var perSpanNameSamples); - if (perSpanNameSamples != null) - { - perSpanNameSamples.ConsiderForSampling(span); - } - } - } - } - - /// - public override IEnumerable GetErrorSampledSpans(ISampledSpanStoreErrorFilter filter) - { - var numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; - var spans = Enumerable.Empty(); - - // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. - lock (this.samples) - { - var perSpanNameSamples = this.samples[filter.SpanName]; - if (perSpanNameSamples != null) - { - spans = perSpanNameSamples.GetErrorSamples(filter.CanonicalCode, numSpansToReturn); - } - } - - var ret = new List(spans.Count()); - foreach (var span in spans) - { - ret.Add(span.ToSpanData()); - } - - return ret.AsReadOnly(); - } - - /// - public override IEnumerable GetLatencySampledSpans(ISampledSpanStoreLatencyFilter filter) - { - var numSpansToReturn = filter.MaxSpansToReturn == 0 ? MaxPerSpanNameSamples : filter.MaxSpansToReturn; - var spans = Enumerable.Empty(); - - // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. - lock (this.samples) - { - var perSpanNameSamples = this.samples[filter.SpanName]; - if (perSpanNameSamples != null) - { - spans = perSpanNameSamples.GetLatencySamples(filter.LatencyLower, filter.LatencyUpper, numSpansToReturn); - } - } - - var ret = new List(spans.Count()); - foreach (var span in spans) - { - ret.Add(span.ToSpanData()); - } - - return ret.AsReadOnly(); - } - - /// - public override void RegisterSpanNamesForCollection(IEnumerable spanNames) - { - this.eventQueue.Enqueue(new RegisterSpanNameEvent(this, spanNames)); - } - - /// - public override void UnregisterSpanNamesForCollection(IEnumerable spanNames) - { - this.eventQueue.Enqueue(new UnregisterSpanNameEvent(this, spanNames)); - } - - internal void InternalUnregisterSpanNamesForCollection(ICollection spanNames) - { - lock (this.samples) - { - foreach (var spanName in spanNames) - { - this.samples.Remove(spanName); - } - } - } - - internal void InternaltRegisterSpanNamesForCollection(ICollection spanNames) - { - lock (this.samples) - { - foreach (var spanName in spanNames) - { - if (!this.samples.ContainsKey(spanName)) - { - this.samples[spanName] = new PerSpanNameSamples(); - } - } - } - } - - private sealed class Bucket - { - private readonly EvictingQueue sampledSpansQueue; - private readonly EvictingQueue notSampledSpansQueue; - private DateTimeOffset lastSampledTime; - private DateTimeOffset lastNotSampledTime; - - public Bucket(int numSamples) - { - this.sampledSpansQueue = new EvictingQueue(numSamples); - this.notSampledSpansQueue = new EvictingQueue(numSamples); - } - - public static void GetSamples( - int maxSpansToReturn, ICollection output, EvictingQueue queue) - { - var copy = queue.ToArray(); - - foreach (var span in copy) - { - if (output.Count >= maxSpansToReturn) - { - break; - } - - output.Add(span); - } - } - - public static void GetSamplesFilteredByLatency( - TimeSpan latencyLower, - TimeSpan latencyUpper, - int maxSpansToReturn, - ICollection output, - EvictingQueue queue) - { - var copy = queue.ToArray(); - foreach (var span in copy) - { - if (output.Count >= maxSpansToReturn) - { - break; - } - - var spanLatency = span.Latency; - if (spanLatency >= latencyLower && spanLatency < latencyUpper) - { - output.Add(span); - } - } - } - - public void ConsiderForSampling(Span span) - { - var spanEndTime = span.EndTime; - if ((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) - { - // Need to compare by doing the subtraction all the time because in case of an overflow, - // this may never sample again (at least for the next ~200 years). No real chance to - // overflow two times because that means the process runs for ~200 years. - if (spanEndTime - this.lastSampledTime > TimeBetweenSamples) - { - this.sampledSpansQueue.Add(span); - this.lastSampledTime = spanEndTime; - } - } - else - { - // Need to compare by doing the subtraction all the time because in case of an overflow, - // this may never sample again (at least for the next ~200 years). No real chance to - // overflow two times because that means the process runs for ~200 years. - if (spanEndTime - this.lastNotSampledTime > TimeBetweenSamples) - { - this.notSampledSpansQueue.Add(span); - this.lastNotSampledTime = spanEndTime; - } - } - } - - public void GetSamples(int maxSpansToReturn, ICollection output) - { - GetSamples(maxSpansToReturn, output, this.sampledSpansQueue); - GetSamples(maxSpansToReturn, output, this.notSampledSpansQueue); - } - - public void GetSamplesFilteredByLatency( - TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn, ICollection output) - { - GetSamplesFilteredByLatency( - latencyLower, latencyUpper, maxSpansToReturn, output, this.sampledSpansQueue); - GetSamplesFilteredByLatency( - latencyLower, latencyUpper, maxSpansToReturn, output, this.notSampledSpansQueue); - } - - public int GetNumSamples() - { - return this.sampledSpansQueue.Count + this.notSampledSpansQueue.Count; - } - } - - private sealed class PerSpanNameSamples - { - private readonly Bucket[] latencyBuckets; - private readonly Bucket[] errorBuckets; - - public PerSpanNameSamples() - { - this.latencyBuckets = new Bucket[NumLatencyBuckets]; - for (var i = 0; i < NumLatencyBuckets; i++) - { - this.latencyBuckets[i] = new Bucket(NumSamplesPerLatencySamples); - } - - this.errorBuckets = new Bucket[NumErrorBuckets]; - for (var i = 0; i < NumErrorBuckets; i++) - { - this.errorBuckets[i] = new Bucket(NumSamplesPerErrorSamples); - } - } - - public Bucket GetLatencyBucket(TimeSpan latency) - { - for (var i = 0; i < NumLatencyBuckets; i++) - { - var boundaries = LatencyBucketBoundaries.Values[i]; - if (latency >= boundaries.LatencyLower - && latency < boundaries.LatencyUpper) - { - return this.latencyBuckets[i]; - } - } - - // latencyNs is negative or Long.MAX_VALUE, so this Span can be ignored. This cannot happen - // in real production because System#nanoTime is monotonic. - return null; - } - - public Bucket GetErrorBucket(CanonicalCode code) - { - return this.errorBuckets[(int)code - 1]; - } - - public void ConsiderForSampling(Span span) - { - var status = span.Status; - - // Null status means running Span, this should not happen in production, but the library - // should not crash because of this. - if (status != null) - { - var bucket = - status.IsOk - ? this.GetLatencyBucket(span.Latency) - : this.GetErrorBucket(status.CanonicalCode); - - // If unable to find the bucket, ignore this Span. - if (bucket != null) - { - bucket.ConsiderForSampling(span); - } - } - } - - public IDictionary GetNumbersOfLatencySampledSpans() - { - IDictionary latencyBucketSummaries = new Dictionary(); - for (var i = 0; i < NumLatencyBuckets; i++) - { - latencyBucketSummaries[LatencyBucketBoundaries.Values[i]] = this.latencyBuckets[i].GetNumSamples(); - } - - return latencyBucketSummaries; - } - - public IDictionary GetNumbersOfErrorSampledSpans() - { - IDictionary errorBucketSummaries = new Dictionary(); - for (var i = 0; i < NumErrorBuckets; i++) - { - errorBucketSummaries[(CanonicalCode)i + 1] = this.errorBuckets[i].GetNumSamples(); - } - - return errorBucketSummaries; - } - - public IEnumerable GetErrorSamples(CanonicalCode? code, int maxSpansToReturn) - { - var output = new List(maxSpansToReturn); - if (code.HasValue) - { - this.GetErrorBucket(code.Value).GetSamples(maxSpansToReturn, output); - } - else - { - for (var i = 0; i < NumErrorBuckets; i++) - { - this.errorBuckets[i].GetSamples(maxSpansToReturn, output); - } - } - - return output; - } - - public IEnumerable GetLatencySamples(TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn) - { - var output = new List(maxSpansToReturn); - for (var i = 0; i < NumLatencyBuckets; i++) - { - var boundaries = LatencyBucketBoundaries.Values[i]; - if (latencyUpper >= boundaries.LatencyLower - && latencyLower < boundaries.LatencyUpper) - { - this.latencyBuckets[i].GetSamplesFilteredByLatency(latencyLower, latencyUpper, maxSpansToReturn, output); - } - } - - return output; - } - } - - private sealed class RegisterSpanNameEvent : IEventQueueEntry - { - private readonly InProcessSampledSpanStore sampledSpanStore; - private readonly ICollection spanNames; - - public RegisterSpanNameEvent(InProcessSampledSpanStore sampledSpanStore, IEnumerable spanNames) - { - this.sampledSpanStore = sampledSpanStore; - this.spanNames = new List(spanNames); - } - - public void Process() - { - this.sampledSpanStore.InternaltRegisterSpanNamesForCollection(this.spanNames); - } - } - - private sealed class UnregisterSpanNameEvent : IEventQueueEntry - { - private readonly InProcessSampledSpanStore sampledSpanStore; - private readonly ICollection spanNames; - - public UnregisterSpanNameEvent(InProcessSampledSpanStore sampledSpanStore, IEnumerable spanNames) - { - this.sampledSpanStore = sampledSpanStore; - this.spanNames = new List(spanNames); - } - - public void Process() - { - this.sampledSpanStore.InternalUnregisterSpanNamesForCollection(this.spanNames); - } - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/NoopRunningSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/NoopRunningSpanStore.cs deleted file mode 100644 index 62abaa3cd37..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/NoopRunningSpanStore.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - - internal sealed class NoopRunningSpanStore : RunningSpanStoreBase - { - private static readonly IRunningSpanStoreSummary EmptySummary = RunningSpanStoreSummary.Create(new Dictionary()); - - public override IRunningSpanStoreSummary Summary - { - get - { - return EmptySummary; - } - } - - public override IEnumerable GetRunningSpans(IRunningSpanStoreFilter filter) - { - if (filter == null) - { - throw new ArgumentNullException(nameof(filter)); - } - - return new SpanData[0]; - } - - public override void OnEnd(ISpan span) - { - } - - public override void OnStart(ISpan span) - { - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs b/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs deleted file mode 100644 index 4a265fa1970..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/NoopSampledSpanStore.cs +++ /dev/null @@ -1,104 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - - internal sealed class NoopSampledSpanStore : SampledSpanStoreBase - { - private static readonly ISampledPerSpanNameSummary EmptyPerSpanNameSummary = SampledPerSpanNameSummary.Create( - new Dictionary(), new Dictionary()); - - private static readonly ISampledSpanStoreSummary EmptySummary = SampledSpanStoreSummary.Create(new Dictionary()); - - private static readonly IEnumerable EmptySpanData = new SpanData[0]; - - private readonly HashSet registeredSpanNames = new HashSet(); - - public override ISampledSpanStoreSummary Summary - { - get - { - IDictionary result = new Dictionary(); - lock (this.registeredSpanNames) - { - foreach (var registeredSpanName in this.registeredSpanNames) - { - result[registeredSpanName] = EmptyPerSpanNameSummary; - } - } - - return SampledSpanStoreSummary.Create(result); - } - } - - public override ISet RegisteredSpanNamesForCollection - { - get - { - return new HashSet(this.registeredSpanNames); - } - } - - public override void ConsiderForSampling(ISpan span) - { - } - - public override IEnumerable GetErrorSampledSpans(ISampledSpanStoreErrorFilter filter) - { - return EmptySpanData; - } - - public override IEnumerable GetLatencySampledSpans(ISampledSpanStoreLatencyFilter filter) - { - return EmptySpanData; - } - - public override void RegisterSpanNamesForCollection(IEnumerable spanNames) - { - if (spanNames == null) - { - throw new ArgumentNullException(nameof(spanNames)); - } - - lock (this.registeredSpanNames) - { - foreach (var name in spanNames) - { - this.registeredSpanNames.Add(name); - } - } - } - - public override void UnregisterSpanNamesForCollection(IEnumerable spanNames) - { - if (spanNames == null) - { - throw new ArgumentNullException(nameof(spanNames)); - } - - lock (this.registeredSpanNames) - { - foreach (var name in spanNames) - { - this.registeredSpanNames.Remove(name); - } - } - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreBase.cs b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreBase.cs deleted file mode 100644 index dbf6fe2571d..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreBase.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - public abstract class RunningSpanStoreBase : IRunningSpanStore - { - private static readonly IRunningSpanStore NoopRunningSpanStoreInstance = new NoopRunningSpanStore(); - - protected RunningSpanStoreBase() - { - } - - public abstract IRunningSpanStoreSummary Summary { get; } - - internal static IRunningSpanStore NoopRunningSpanStore - { - get - { - return NoopRunningSpanStoreInstance; - } - } - - public abstract IEnumerable GetRunningSpans(IRunningSpanStoreFilter filter); - - public abstract void OnEnd(ISpan span); - - public abstract void OnStart(ISpan span); - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs deleted file mode 100644 index 77a28b153e2..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreFilter.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// 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.Export -{ - using System; - - public sealed class RunningSpanStoreFilter : IRunningSpanStoreFilter - { - internal RunningSpanStoreFilter(string spanName, int maxSpansToReturn) - { - this.SpanName = spanName ?? throw new ArgumentNullException("Null spanName"); - this.MaxSpansToReturn = maxSpansToReturn; - } - - public string SpanName { get; } - - public int MaxSpansToReturn { get; } - - public static IRunningSpanStoreFilter Create(string spanName, int maxSpansToReturn) - { - if (maxSpansToReturn < 0) - { - throw new ArgumentOutOfRangeException("Negative maxSpansToReturn."); - } - - return new RunningSpanStoreFilter(spanName, maxSpansToReturn); - } - - /// - public override string ToString() - { - return "RunningFilter{" - + "spanName=" + this.SpanName + ", " - + "maxSpansToReturn=" + this.MaxSpansToReturn - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is RunningSpanStoreFilter that) - { - return this.SpanName.Equals(that.SpanName) - && (this.MaxSpansToReturn == that.MaxSpansToReturn); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.SpanName.GetHashCode(); - h *= 1000003; - h ^= this.MaxSpansToReturn; - return h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs b/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs deleted file mode 100644 index 2ddf980cf68..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/RunningSpanStoreSummary.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; - - public sealed class RunningSpanStoreSummary : IRunningSpanStoreSummary - { - internal RunningSpanStoreSummary(IDictionary perSpanNameSummary) - { - this.PerSpanNameSummary = perSpanNameSummary; - } - - public IDictionary PerSpanNameSummary { get; } - - public static IRunningSpanStoreSummary Create(IDictionary perSpanNameSummary) - { - if (perSpanNameSummary == null) - { - throw new ArgumentNullException(nameof(perSpanNameSummary)); - } - - IDictionary copy = new Dictionary(perSpanNameSummary); - return new RunningSpanStoreSummary(new ReadOnlyDictionary(copy)); - } - - /// - public override string ToString() - { - return "RunningSummary{" - + "perSpanNameSummary=" + this.PerSpanNameSummary - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is RunningSpanStoreSummary that) - { - return this.PerSpanNameSummary.SequenceEqual(that.PerSpanNameSummary); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.PerSpanNameSummary.GetHashCode(); - return h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreBase.cs b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreBase.cs deleted file mode 100644 index e5d0f808de9..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreBase.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// 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.Export -{ - using System.Collections.Generic; - - public abstract class SampledSpanStoreBase : ISampledSpanStore - { - private static readonly ISampledSpanStore NoopSampledSpanStoreInstance = new NoopSampledSpanStore(); - - protected SampledSpanStoreBase() - { - } - - public abstract ISampledSpanStoreSummary Summary { get; } - - public abstract ISet RegisteredSpanNamesForCollection { get; } - - internal static ISampledSpanStore NoopSampledSpanStore - { - get - { - return NoopSampledSpanStoreInstance; - } - } - - internal static ISampledSpanStore NewNoopSampledSpanStore - { - get - { - return new NoopSampledSpanStore(); - } - } - - public abstract void ConsiderForSampling(ISpan span); - - public abstract IEnumerable GetErrorSampledSpans(ISampledSpanStoreErrorFilter filter); - - public abstract IEnumerable GetLatencySampledSpans(ISampledSpanStoreLatencyFilter filter); - - public abstract void RegisterSpanNamesForCollection(IEnumerable spanNames); - - public abstract void UnregisterSpanNamesForCollection(IEnumerable spanNames); - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs deleted file mode 100644 index 7ee64dff88c..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreErrorFilter.cs +++ /dev/null @@ -1,92 +0,0 @@ -// -// 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.Export -{ - using System; - - public sealed class SampledSpanStoreErrorFilter : ISampledSpanStoreErrorFilter - { - internal SampledSpanStoreErrorFilter(string spanName, CanonicalCode? canonicalCode, int maxSpansToReturn) - { - this.SpanName = spanName ?? throw new ArgumentNullException(nameof(spanName)); - this.CanonicalCode = canonicalCode; - this.MaxSpansToReturn = maxSpansToReturn; - } - - public string SpanName { get; } - - public CanonicalCode? CanonicalCode { get; } - - public int MaxSpansToReturn { get; } - - public static ISampledSpanStoreErrorFilter Create(string spanName, CanonicalCode? canonicalCode, int maxSpansToReturn) - { - if (canonicalCode == Trace.CanonicalCode.Ok) - { - throw new ArgumentOutOfRangeException("Invalid canonical code."); - } - - if (maxSpansToReturn < 0) - { - throw new ArgumentOutOfRangeException(nameof(maxSpansToReturn)); - } - - return new SampledSpanStoreErrorFilter(spanName, canonicalCode, maxSpansToReturn); - } - - /// - public override string ToString() - { - return "ErrorFilter{" - + "spanName=" + this.SpanName + ", " - + "canonicalCode=" + this.CanonicalCode + ", " - + "maxSpansToReturn=" + this.MaxSpansToReturn - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is SampledSpanStoreErrorFilter that) - { - return this.SpanName.Equals(that.SpanName) - && (this.CanonicalCode == that.CanonicalCode) - && (this.MaxSpansToReturn == that.MaxSpansToReturn); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.SpanName.GetHashCode(); - h *= 1000003; - h ^= this.CanonicalCode.GetHashCode(); - h *= 1000003; - h ^= this.MaxSpansToReturn; - return h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreLatencyFilter.cs b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreLatencyFilter.cs deleted file mode 100644 index 58035b2e8a2..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreLatencyFilter.cs +++ /dev/null @@ -1,104 +0,0 @@ -// -// 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.Export -{ - using System; - - public sealed class SampledSpanStoreLatencyFilter : ISampledSpanStoreLatencyFilter - { - internal SampledSpanStoreLatencyFilter(string spanName, TimeSpan latencyLowerNs, TimeSpan latencyUpperNs, int maxSpansToReturn) - { - this.SpanName = spanName ?? throw new ArgumentNullException(nameof(spanName)); - this.LatencyLower = latencyLowerNs; - this.LatencyUpper = latencyUpperNs; - this.MaxSpansToReturn = maxSpansToReturn; - } - - public string SpanName { get; } - - public TimeSpan LatencyLower { get; } - - public TimeSpan LatencyUpper { get; } - - public int MaxSpansToReturn { get; } - - public static ISampledSpanStoreLatencyFilter Create(string spanName, TimeSpan latencyLower, TimeSpan latencyUpper, int maxSpansToReturn) - { - if (maxSpansToReturn < 0) - { - throw new ArgumentOutOfRangeException(nameof(maxSpansToReturn)); - } - - if (latencyLower < TimeSpan.Zero) - { - throw new ArgumentOutOfRangeException(nameof(latencyLower)); - } - - if (latencyUpper < TimeSpan.Zero) - { - throw new ArgumentOutOfRangeException(nameof(latencyUpper)); - } - - return new SampledSpanStoreLatencyFilter(spanName, latencyLower, latencyUpper, maxSpansToReturn); - } - - /// - public override string ToString() - { - return "LatencyFilter{" - + "spanName=" + this.SpanName + ", " - + "latencyLowerNs=" + this.LatencyLower + ", " - + "latencyUpperNs=" + this.LatencyUpper + ", " - + "maxSpansToReturn=" + this.MaxSpansToReturn - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is SampledSpanStoreLatencyFilter that) - { - return this.SpanName.Equals(that.SpanName) - && (this.LatencyLower == that.LatencyLower) - && (this.LatencyUpper == that.LatencyUpper) - && (this.MaxSpansToReturn == that.MaxSpansToReturn); - } - - return false; - } - - /// - public override int GetHashCode() - { - long h = 1; - h *= 1000003; - h ^= this.SpanName.GetHashCode(); - h *= 1000003; - h ^= (this.LatencyLower.Ticks >> 32) ^ this.LatencyLower.Ticks; - h *= 1000003; - h ^= (this.LatencyUpper.Ticks >> 32) ^ this.LatencyUpper.Ticks; - h *= 1000003; - h ^= this.MaxSpansToReturn; - return (int)h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs b/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs deleted file mode 100644 index 3abb574c385..00000000000 --- a/src/OpenTelemetry/Trace/Export/SpanStore/SampledSpanStoreSummary.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// 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.Export -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; - - public class SampledSpanStoreSummary : ISampledSpanStoreSummary - { - internal SampledSpanStoreSummary(IDictionary perSpanNameSummary) - { - this.PerSpanNameSummary = perSpanNameSummary ?? throw new ArgumentNullException(nameof(perSpanNameSummary)); - } - - public IDictionary PerSpanNameSummary { get; } - - public static ISampledSpanStoreSummary Create(IDictionary perSpanNameSummary) - { - if (perSpanNameSummary == null) - { - throw new ArgumentNullException(nameof(perSpanNameSummary)); - } - - IDictionary copy = new Dictionary(perSpanNameSummary); - return new SampledSpanStoreSummary(new ReadOnlyDictionary(copy)); - } - - /// - public override string ToString() - { - return "SampledSummary{" - + "perSpanNameSummary=" + this.PerSpanNameSummary - + "}"; - } - - /// - public override bool Equals(object o) - { - if (o == this) - { - return true; - } - - if (o is SampledSpanStoreSummary that) - { - return this.PerSpanNameSummary.SequenceEqual(that.PerSpanNameSummary); - } - - return false; - } - - /// - public override int GetHashCode() - { - var h = 1; - h *= 1000003; - h ^= this.PerSpanNameSummary.GetHashCode(); - return h; - } - } -} diff --git a/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs b/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs index 60f3e355ae5..84f68053359 100644 --- a/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs +++ b/src/OpenTelemetry/Trace/Internal/StartEndHandler.cs @@ -16,102 +16,51 @@ namespace OpenTelemetry.Trace.Internal { - using System.Diagnostics; using OpenTelemetry.Internal; using OpenTelemetry.Trace.Export; internal sealed class StartEndHandler : IStartEndHandler { private readonly ISpanExporter spanExporter; - private readonly IRunningSpanStore runningSpanStore; - private readonly ISampledSpanStore sampledSpanStore; private readonly IEventQueue eventQueue; - // true if any of (runningSpanStore OR sampledSpanStore) are different than null, which - // means the spans with RECORD_EVENTS should be enqueued in the queue. - private readonly bool enqueueEventForNonSampledSpans; - - public StartEndHandler(ISpanExporter spanExporter, IRunningSpanStore runningSpanStore, ISampledSpanStore sampledSpanStore, IEventQueue eventQueue) + public StartEndHandler(ISpanExporter spanExporter, IEventQueue eventQueue) { this.spanExporter = spanExporter; - this.runningSpanStore = runningSpanStore; - this.sampledSpanStore = sampledSpanStore; - this.enqueueEventForNonSampledSpans = runningSpanStore != null || sampledSpanStore != null; this.eventQueue = eventQueue; } public void OnEnd(ISpan span) { - if ((span.IsRecordingEvents && this.enqueueEventForNonSampledSpans) - || (span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) + if (span.IsRecordingEvents) { - this.eventQueue.Enqueue(new SpanEndEvent(span, this.spanExporter, this.runningSpanStore, this.sampledSpanStore)); + this.eventQueue.Enqueue(new SpanEndEvent(span, this.spanExporter)); } } public void OnStart(ISpan span) { - if (span.IsRecordingEvents && this.enqueueEventForNonSampledSpans) - { - this.eventQueue.Enqueue(new SpanStartEvent(span, this.runningSpanStore)); - } - } - - private sealed class SpanStartEvent : IEventQueueEntry - { - private readonly ISpan span; - private readonly IRunningSpanStore activeSpansExporter; - - public SpanStartEvent(ISpan span, IRunningSpanStore activeSpansExporter) - { - this.span = span; - this.activeSpansExporter = activeSpansExporter; - } - - public void Process() - { - if (this.activeSpansExporter != null) - { - this.activeSpansExporter.OnStart(this.span); - } - } } private sealed class SpanEndEvent : IEventQueueEntry { private readonly ISpan span; - private readonly IRunningSpanStore runningSpanStore; private readonly ISpanExporter spanExporter; - private readonly ISampledSpanStore sampledSpanStore; public SpanEndEvent( ISpan span, - ISpanExporter spanExporter, - IRunningSpanStore runningSpanStore, - ISampledSpanStore sampledSpanStore) + ISpanExporter spanExporter) { this.span = span; - this.runningSpanStore = runningSpanStore; this.spanExporter = spanExporter; - this.sampledSpanStore = sampledSpanStore; } public void Process() { - if ((this.span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0) + if (this.span.IsRecordingEvents) { this.spanExporter.AddSpan(this.span); } - - if (this.runningSpanStore != null) - { - this.runningSpanStore.OnEnd(this.span); - } - - if (this.sampledSpanStore != null) - { - this.sampledSpanStore.ConsiderForSampling(this.span); - } } } } diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index ac3c07b9a6d..c2db5bccda8 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -19,7 +19,6 @@ namespace OpenTelemetry.Trace using System; using System.Collections.Generic; using System.Diagnostics; - using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Resources; using OpenTelemetry.Trace.Config; @@ -29,31 +28,24 @@ namespace OpenTelemetry.Trace /// /// Span implementation. /// - public sealed class Span : ISpan, IElement + public sealed class Span : ISpan { private readonly ITraceParams traceParams; private readonly IStartEndHandler startEndHandler; - private readonly DateTimeOffset startTime; + private readonly Lazy spanContext; private readonly object @lock = new object(); private AttributesWithCapacity attributes; private TraceEvents> events; private TraceEvents links; private Status status; - private DateTimeOffset endTime; - private bool hasBeenEnded; - private bool sampleToLocalSpanStore; - private Lazy spanContext; private Span( Activity activity, Tracestate tracestate, - SpanOptions options, - string name, SpanKind spanKind, ITraceParams traceParams, IStartEndHandler startEndHandler, - Timer timestampConverter, - bool stopActivity) + bool ownsActivity) { this.Activity = activity; this.spanContext = new Lazy(() => SpanContext.Create( @@ -61,49 +53,20 @@ private Span( this.Activity.SpanId, this.Activity.ActivityTraceFlags, tracestate)); - this.Options = options; - this.Name = name; + this.Name = this.Activity.OperationName; this.traceParams = traceParams ?? throw new ArgumentNullException(nameof(traceParams)); this.startEndHandler = startEndHandler; - this.hasBeenEnded = false; - this.sampleToLocalSpanStore = false; this.Kind = spanKind; - if (this.IsRecordingEvents) - { - if (timestampConverter == null) - { - this.TimestampConverter = Timer.StartNew(); - this.startTime = this.TimestampConverter.StartTime; - } - else - { - this.TimestampConverter = timestampConverter; - this.startTime = this.TimestampConverter.Now; - } - } - else - { - this.startTime = DateTimeOffset.MinValue; - this.TimestampConverter = timestampConverter; - } - - this.OwnsActivity = stopActivity; + this.OwnsActivity = ownsActivity; + this.IsRecordingEvents = this.Activity.Recorded; } public Activity Activity { get; } public SpanContext Context => this.spanContext.Value; - public SpanOptions Options { get; } - public string Name { get; private set; } - /// - public Span Next { get; set; } - - /// - public Span Previous { get; set; } - /// public Status Status { @@ -124,7 +87,7 @@ public Status Status lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling setStatus() on an ended Span."); return; @@ -135,58 +98,12 @@ public Status Status } } - public DateTimeOffset EndTime - { - get - { - lock (this.@lock) - { - return this.hasBeenEnded ? this.endTime : this.TimestampConverter.Now; - } - } - } - - public TimeSpan Latency - { - get - { - lock (this.@lock) - { - return this.hasBeenEnded ? this.endTime - this.startTime : this.TimestampConverter.Now - this.startTime; - } - } - } - - public bool IsSampleToLocalSpanStore - { - get - { - lock (this.@lock) - { - if (!this.hasBeenEnded) - { - throw new InvalidOperationException("Running span does not have the SampleToLocalSpanStore set."); - } - - return this.sampleToLocalSpanStore; - } - } - - set - { - lock (this.@lock) - { - this.sampleToLocalSpanStore = value; - } - } - } - public ActivitySpanId ParentSpanId => this.Activity.ParentSpanId; - public bool HasEnded => this.hasBeenEnded; + public bool HasEnded { get; private set; } /// - public bool IsRecordingEvents => this.Options.HasFlag(SpanOptions.RecordEvents); + public bool IsRecordingEvents { get; } /// /// Gets or sets span kind. @@ -195,8 +112,6 @@ public bool IsSampleToLocalSpanStore internal bool OwnsActivity { get; } - internal Timer TimestampConverter { get; private set; } - private AttributesWithCapacity InitializedAttributes { get @@ -260,7 +175,7 @@ public void SetAttribute(KeyValuePair keyValuePair) lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling putAttributes() on an ended Span."); return; @@ -285,13 +200,13 @@ public void AddEvent(string name) lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling AddEvent() on an ended Span."); return; } - this.InitializedEvents.AddEvent(new EventWithTime(this.TimestampConverter.Now, Event.Create(name))); + this.InitializedEvents.AddEvent(new EventWithTime(PreciseTimestamp.GetUtcNow(), Event.Create(name))); } } @@ -315,13 +230,13 @@ public void AddEvent(string name, IDictionary eventAttributes) lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling AddEvent() on an ended Span."); return; } - this.InitializedEvents.AddEvent(new EventWithTime(this.TimestampConverter.Now, Event.Create(name, eventAttributes))); + this.InitializedEvents.AddEvent(new EventWithTime(PreciseTimestamp.GetUtcNow(), Event.Create(name, eventAttributes))); } } @@ -340,18 +255,13 @@ public void AddEvent(IEvent addEvent) lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling AddEvent() on an ended Span."); return; } - if (addEvent == null) - { - throw new ArgumentNullException(nameof(addEvent)); - } - - this.InitializedEvents.AddEvent(new EventWithTime(this.TimestampConverter.Now, addEvent)); + this.InitializedEvents.AddEvent(new EventWithTime(PreciseTimestamp.GetUtcNow(), addEvent)); } } @@ -370,7 +280,7 @@ public void AddLink(ILink link) lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling addLink() on an ended Span."); return; @@ -401,14 +311,13 @@ public void End() lock (this.@lock) { - if (this.hasBeenEnded) + if (this.HasEnded) { // logger.log(Level.FINE, "Calling end() on an ended Span."); return; } - this.endTime = this.TimestampConverter.Now; - this.hasBeenEnded = true; + this.HasEnded = true; } this.startEndHandler.OnEnd(this); @@ -422,8 +331,7 @@ public SpanData ToSpanData() } var attributesSpanData = Attributes.Create(this.attributes?.AsReadOnlyCollection(), this.attributes?.NumberOfDroppedAttributes ?? 0); - - var annotationsSpanData = CreateTimedEvents(this.InitializedEvents, this.TimestampConverter); + var annotationsSpanData = CreateTimedEvents(this.InitializedEvents); var linksSpanData = LinkList.Create(this.links?.Events, this.links?.NumberOfDroppedEvents ?? 0); return SpanData.Create( @@ -431,14 +339,14 @@ public SpanData ToSpanData() this.ParentSpanId, Resource.Empty, // TODO: determine what to do with Resource in this context this.Name, - Timestamp.FromDateTimeOffset(this.startTime), + this.Activity.StartTimeUtc, attributesSpanData, annotationsSpanData, linksSpanData, null, // Not supported yet. - this.hasBeenEnded ? this.StatusWithDefault : null, + this.HasEnded ? this.StatusWithDefault : null, this.Kind ?? SpanKind.Internal, - this.hasBeenEnded ? Timestamp.FromDateTimeOffset(this.endTime) : null); + this.HasEnded ? (this.Activity.StartTimeUtc + this.Activity.Duration) : default); } /// @@ -513,23 +421,17 @@ public void SetAttribute(string key, bool value) internal static ISpan StartSpan( Activity activity, Tracestate tracestate, - SpanOptions options, - string name, SpanKind spanKind, ITraceParams traceParams, IStartEndHandler startEndHandler, - Timer timestampConverter, bool ownsActivity = true) { var span = new Span( activity, tracestate, - options, - name, spanKind, traceParams, startEndHandler, - timestampConverter, ownsActivity); // Call onStart here instead of calling in the constructor to make sure the span is completely @@ -542,7 +444,7 @@ internal static ISpan StartSpan( return span; } - private static ITimedEvents CreateTimedEvents(TraceEvents> events, Timer timestampConverter) + private static ITimedEvents CreateTimedEvents(TraceEvents> events) { List> eventsList = null; int numberOfDroppedEvents = 0; @@ -551,7 +453,7 @@ private static ITimedEvents CreateTimedEvents(TraceEvents eventsList = new List>(events.Events.Count); foreach (var networkEvent in events.Events) { - eventsList.Add(networkEvent.ToSpanDataTimedEvent(timestampConverter)); + eventsList.Add(networkEvent.ToSpanDataTimedEvent()); } numberOfDroppedEvents = events.NumberOfDroppedEvents; diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index 9fe0fb8035c..e7f21da20af 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -38,7 +38,6 @@ public class SpanBuilder : ISpanBuilder private ISampler sampler; private List links; private bool recordEvents; - private Timer timestampConverter; internal SpanBuilder(string name, SpanBuilderOptions options) { @@ -72,11 +71,6 @@ public ISpanBuilder SetParent(ISpan parentSpan) { this.parentSpan = parentSpan ?? throw new ArgumentNullException(nameof(parentSpan)); this.contextSource = ContextSource.ExplicitSpanParent; - if (parentSpan is Span parentSpanImpl) - { - this.timestampConverter = parentSpanImpl.TimestampConverter; - } - this.parentSpanContext = null; this.parentActivity = null; return this; @@ -235,11 +229,9 @@ public ISpan StartSpan() activityForSpan.SpanId, activeTraceParams); - var spanOptions = SpanOptions.None; if (sampledIn || this.recordEvents) { activityForSpan.ActivityTraceFlags |= ActivityTraceFlags.Recorded; - spanOptions = SpanOptions.RecordEvents; } else { @@ -250,19 +242,21 @@ public ISpan StartSpan() if (this.parentSpanContext?.Tracestate != null && this.parentSpanContext.Tracestate != Tracestate.Empty) { - childTracestate = this.parentSpanContext.Tracestate.ToBuilder().Build(); + childTracestate = this.parentSpanContext.Tracestate; } var span = Span.StartSpan( activityForSpan, childTracestate, // it is updated in CreateActivityForSpan, - spanOptions, - this.name, this.kind, activeTraceParams, this.options.StartEndHandler, - this.timestampConverter, ownsActivity: this.contextSource != ContextSource.Activity); + if (activityForSpan.OperationName != this.name) + { + span.UpdateName(this.name); + } + LinkSpans(span, this.links); return span; } diff --git a/src/OpenTelemetry/Trace/SpanOptions.cs b/src/OpenTelemetry/Trace/SpanOptions.cs deleted file mode 100644 index ad0a667ec59..00000000000 --- a/src/OpenTelemetry/Trace/SpanOptions.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// 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; - - /// - /// Span recording options. - /// - [Flags] - public enum SpanOptions - { - /// - /// None - /// - None = 0x0, - - /// - /// Record events. - /// - RecordEvents = 0x1, - } -} diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 2ef89662934..9507410aff0 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Trace { using System; using System.Threading; - using OpenTelemetry.Common; using OpenTelemetry.Context; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Config; @@ -30,7 +29,7 @@ public sealed class Tracer : ITracer private const int ExporterBufferSize = 32; // Enforces that trace export exports data at least once every 5 seconds. - private static readonly Duration ExporterScheduleDelay = Duration.Create(5, 0); + private static readonly TimeSpan ExporterScheduleDelay = TimeSpan.FromSeconds(5); private readonly SpanBuilderOptions spanBuilderOptions; private readonly SpanExporter spanExporter; diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index 2dc0d8b43d5..dc1418ae357 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -49,8 +49,6 @@ internal Tracing() IStartEndHandler startEndHandler = new StartEndHandler( ExportComponent.SpanExporter, - ((ExportComponent)ExportComponent).RunningSpanStore, - ((ExportComponent)ExportComponent).SampledSpanStore, eventQueue); tracer = new Tracer(startEndHandler, TraceConfig); diff --git a/src/OpenTelemetry/Utils/Collections.cs b/src/OpenTelemetry/Utils/Collections.cs deleted file mode 100644 index a59e190c3bf..00000000000 --- a/src/OpenTelemetry/Utils/Collections.cs +++ /dev/null @@ -1,71 +0,0 @@ -// -// 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.Utils -{ - using System.Collections.Generic; - using System.Linq; - using System.Text; - - internal static class Collections - { - public static string ToString(IDictionary dict) - { - if (dict == null) - { - return "null"; - } - - var sb = new StringBuilder(); - foreach (var kvp in dict) - { - sb.Append(kvp.Key.ToString()); - sb.Append("="); - sb.Append(kvp.Value.ToString()); - sb.Append(" "); - } - - return sb.ToString(); - } - - public static string ToString(IEnumerable list) - { - if (list == null) - { - return "null"; - } - - var sb = new StringBuilder(); - foreach (var val in list) - { - if (val != null) - { - sb.Append(val.ToString()); - sb.Append(" "); - } - } - - return sb.ToString(); - } - - public static bool AreEquivalent(IEnumerable c1, IEnumerable c2) - { - var c1Dist = c1.Distinct(); - var c2Dist = c2.Distinct(); - return c1.Count() == c2.Count() && c1Dist.Count() == c2Dist.Count() && c1Dist.Intersect(c2Dist).Count() == c1Dist.Count(); - } - } -} diff --git a/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs b/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs deleted file mode 100644 index bbeddfcba69..00000000000 --- a/src/OpenTelemetry/Utils/ConcurrentIntrusiveList.cs +++ /dev/null @@ -1,115 +0,0 @@ -// -// 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.Utils -{ - using System; - using System.Collections.Generic; - - internal sealed class ConcurrentIntrusiveList where T : IElement - { - private readonly object lck = new object(); - private int size = 0; - private T head = default(T); - - public ConcurrentIntrusiveList() - { - } - - public int Count - { - get - { - return this.size; - } - } - - public void AddElement(T element) - { - lock (this.lck) - { - if (element.Next != null || element.Previous != null || element.Equals(this.head)) - { - throw new ArgumentOutOfRangeException("Element already in a list"); - } - - this.size++; - if (this.head == null) - { - this.head = element; - } - else - { - this.head.Previous = element; - element.Next = this.head; - this.head = element; - } - } - } - - public void RemoveElement(T element) - { - lock (this.lck) - { - if (element.Next == null && element.Previous == null && !element.Equals(this.head)) - { - throw new ArgumentOutOfRangeException("Element not in the list"); - } - - this.size--; - if (element.Previous == null) - { - // This is the first element - this.head = element.Next; - if (this.head != null) - { - // If more than one element in the list. - this.head.Previous = default(T); - element.Next = default(T); - } - } - else if (element.Next == null) - { - // This is the last element, and there is at least another element because - // element.getPrev() != null. - element.Previous.Next = default(T); - element.Previous = default(T); - } - else - { - element.Previous.Next = element.Next; - element.Next.Previous = element.Previous; - element.Next = default(T); - element.Previous = default(T); - } - } - } - - public IReadOnlyList Copy() - { - lock (this.lck) - { - var all = new List(this.size); - for (var e = this.head; e != null; e = e.Next) - { - all.Add(e); - } - - return all; - } - } - } -} diff --git a/src/OpenTelemetry/Utils/IElement.cs b/src/OpenTelemetry/Utils/IElement.cs deleted file mode 100644 index 61351646c96..00000000000 --- a/src/OpenTelemetry/Utils/IElement.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// 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.Utils -{ - /// - /// Element of double linked list. - /// - /// Type of a stored value. - public interface IElement - where T : IElement - { - /// - /// Gets or sets next element. - /// - T Next { get; set; } - - /// - /// Gets or sets previous element. - /// - T Previous { get; set; } - } -} diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs index 218dfdb4103..0eceef126ff 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/Implementation/RedisProfilerEntryToSpanConverterTests.cs @@ -25,7 +25,6 @@ namespace OpenTelemetry.Collector.StackExchangeRedis.Implementation using Xunit; using System; using System.Diagnostics; - using OpenTelemetry.Common; using System.Collections.Generic; public class RedisProfilerEntryToSpanConverterTests @@ -51,7 +50,7 @@ public void ProfiledCommandToSpanDataUsesTimestampAsStartTime() var now = DateTimeOffset.Now; profiledCommand.Setup(m => m.CommandCreated).Returns(now.DateTime); var result = RedisProfilerEntryToSpanConverter.ProfiledCommandToSpanData(SpanContext.Blank, "SET", default, profiledCommand.Object); - Assert.Equal(Timestamp.FromMillis(now.ToUnixTimeMilliseconds()), result.StartTimestamp); + Assert.Equal(now, result.StartTimestamp); } [Fact] diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs index 26b51b4d737..c845b6b8758 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs @@ -19,7 +19,6 @@ namespace OpenTelemetry.Exporter.ApplicationInsights.Tests using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.DataContracts; using Microsoft.ApplicationInsights.Extensibility; - using OpenTelemetry.Common; using OpenTelemetry.Exporter.ApplicationInsights.Implementation; using OpenTelemetry.Resources; using OpenTelemetry.Trace; @@ -42,13 +41,11 @@ public class OpenTelemetryTelemetryConverterTests private readonly byte[] testSpanIdBytes = { 0xd7, 0xdd, 0xeb, 0x4a, 0xa9, 0xa5, 0xe7, 0x8b }; private readonly byte[] testParentSpanIdBytes = { 0x9b, 0xa7, 0x9c, 0x9f, 0xbd, 0x2f, 0xb4, 0x95 }; - private DateTimeOffset nowDateTimeOffset; - - private Timestamp NowTimestamp => Timestamp.FromDateTimeOffset(nowDateTimeOffset); + private DateTime now; public OpenTelemetryTelemetryConverterTests() { - nowDateTimeOffset = DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(1)); + now = DateTime.UtcNow.AddSeconds(-1); } private ConcurrentQueue ConvertSpan(SpanData data) @@ -84,7 +81,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequest() var request = sentItems.OfType().Single(); Assert.Equal("spanName", request.Name); - Assert.Equal(nowDateTimeOffset.Subtract(TimeSpan.FromSeconds(1)), request.Timestamp); + Assert.Equal(now.AddSeconds(-1), request.Timestamp); Assert.Equal(1, request.Duration.TotalSeconds); Assert.Equal(TestTraceId, request.Context.Operation.Id); @@ -266,7 +263,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksClientDependency() var dependency = sentItems.OfType().Single(); Assert.Equal("spanName", dependency.Name); - Assert.Equal(nowDateTimeOffset.Subtract(TimeSpan.FromSeconds(1)), dependency.Timestamp); + Assert.Equal(now.AddSeconds(-1), dependency.Timestamp); Assert.Equal(1, dependency.Duration.TotalSeconds); Assert.Equal(TestTraceId, dependency.Context.Operation.Id); @@ -300,7 +297,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksProducerDependency() var dependency = sentItems.OfType().Single(); Assert.Equal("spanName", dependency.Name); - Assert.Equal(nowDateTimeOffset.Subtract(TimeSpan.FromSeconds(1)), dependency.Timestamp); + Assert.Equal(now.AddSeconds(-1), dependency.Timestamp); Assert.Equal(1, dependency.Duration.TotalSeconds); Assert.Equal(TestTraceId, dependency.Context.Operation.Id); @@ -1463,8 +1460,8 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithEvents() events = TimedEvents.Create( new List>() { - TimedEvent.Create(NowTimestamp, Event.Create("test message1")), - TimedEvent.Create(null, Event.Create("test message2", new Dictionary() + TimedEvent.Create(now, Event.Create("test message1")), + TimedEvent.Create(default, Event.Create("test message2", new Dictionary() { { "custom.stringAttribute", "string" }, { "custom.longAttribute", long.MaxValue }, @@ -1493,8 +1490,8 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithEvents() Assert.Equal("test message1", trace1.Message); Assert.Equal("test message2", trace2.Message); - Assert.Equal(nowDateTimeOffset, trace1.Timestamp); - Assert.NotEqual(nowDateTimeOffset, trace2.Timestamp); + Assert.Equal(now, trace1.Timestamp); + Assert.NotEqual(now, trace2.Timestamp); Assert.True(Math.Abs((DateTime.UtcNow - trace2.Timestamp).TotalSeconds) < 1); Assert.False(trace1.Properties.Any()); @@ -1581,15 +1578,15 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestWithEventsAndNode( public void OpenTelemetryTelemetryConverterTests_TracksDependenciesWithEvents() { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - nowDateTimeOffset = nowDateTimeOffset.Subtract(TimeSpan.FromSeconds(1)); + now = now.Subtract(TimeSpan.FromSeconds(1)); name = "spanName"; kind = SpanKind.Client; events = TimedEvents.Create( new List>() { - TimedEvent.Create(NowTimestamp, Event.Create("test message1")), - TimedEvent.Create(null, Event.Create("test message2", new Dictionary() + TimedEvent.Create(now, Event.Create("test message1")), + TimedEvent.Create(default, Event.Create("test message2", new Dictionary() { { "custom.stringAttribute", "string" }, { "custom.longAttribute", long.MaxValue }, @@ -1618,8 +1615,8 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependenciesWithEvents() Assert.Equal("test message1", trace1.Message); Assert.Equal("test message2", trace2.Message); - Assert.Equal(nowDateTimeOffset, trace1.Timestamp); - Assert.NotEqual(nowDateTimeOffset, trace2.Timestamp); + Assert.Equal(now, trace1.Timestamp); + Assert.NotEqual(now, trace2.Timestamp); Assert.True(Math.Abs((DateTime.UtcNow - trace2.Timestamp).TotalSeconds) < 1); Assert.False(trace1.Properties.Any()); @@ -1862,27 +1859,27 @@ private void GetDefaults( out ActivitySpanId parentSpanId, out Resource resource, out string name, - out Timestamp startTimestamp, + out DateTime startTimestamp, out Attributes attributes, out ITimedEvents events, out ILinks links, out int? childSpanCount, out Status status, out SpanKind kind, - out Timestamp endTimestamp) + out DateTime endTimestamp) { context = SpanContext.Create(ActivityTraceId.CreateFromBytes(this.testTraceIdBytes), ActivitySpanId.CreateFromBytes(this.testSpanIdBytes), ActivityTraceFlags.None, Tracestate.Empty); parentSpanId = default; resource = Resource.Empty; name = "spanName"; - startTimestamp = NowTimestamp.AddDuration(Duration.Create(TimeSpan.FromSeconds(-1))); + startTimestamp = now.AddSeconds(-1); attributes = null; events = null; links = null; childSpanCount = null; status = null; kind = SpanKind.Server; - endTimestamp = NowTimestamp; + endTimestamp = now; } } }; diff --git a/test/OpenTelemetry.Tests/Impl/Common/DurationTest.cs b/test/OpenTelemetry.Tests/Impl/Common/DurationTest.cs deleted file mode 100644 index a8e656a7334..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Common/DurationTest.cs +++ /dev/null @@ -1,76 +0,0 @@ -// -// 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.Common.Test -{ - using Xunit; - - public class DurationTest - { - [Fact] - public void TestDurationCreate() - { - Assert.Equal(24, Duration.Create(24, 42).Seconds); - Assert.Equal(42, Duration.Create(24, 42).Nanos); - Assert.Equal(-24, Duration.Create(-24, -42).Seconds); - Assert.Equal(-42, Duration.Create(-24, -42).Nanos); - Assert.Equal(315576000000L, Duration.Create(315576000000L, 999999999).Seconds); - Assert.Equal(999999999, Duration.Create(315576000000L, 999999999).Nanos); - Assert.Equal(-315576000000L, Duration.Create(-315576000000L, -999999999).Seconds); - Assert.Equal(-999999999, Duration.Create(-315576000000L, -999999999).Nanos); - } - - [Fact] - public void TestDurationCreateInvalidInput() - { - Assert.Equal(Duration.Create(0, 0), Duration.Create(-315576000001L, 0)); - Assert.Equal(Duration.Create(0, 0), Duration.Create(315576000001L, 0)); - Assert.Equal(Duration.Create(0, 0), Duration.Create(0, 1000000000)); - Assert.Equal(Duration.Create(0, 0), Duration.Create(0, -1000000000)); - Assert.Equal(Duration.Create(0, 0), Duration.Create(-1, 1)); - Assert.Equal(Duration.Create(0, 0), Duration.Create(1, -1)); - } - - [Fact] - public void Duration_CompareLength() - { - Assert.Equal(0, Duration.Create(0, 0).CompareTo(Duration.Create(0, 0))); - Assert.Equal(0, Duration.Create(24, 42).CompareTo(Duration.Create(24, 42))); - Assert.Equal(0, Duration.Create(-24, -42).CompareTo(Duration.Create(-24, -42))); - Assert.Equal(1, Duration.Create(25, 42).CompareTo(Duration.Create(24, 42))); - Assert.Equal(1, Duration.Create(24, 45).CompareTo(Duration.Create(24, 42))); - Assert.Equal(-1, Duration.Create(24, 42).CompareTo(Duration.Create(25, 42))); - Assert.Equal(-1, Duration.Create(24, 42).CompareTo(Duration.Create(24, 45))); - Assert.Equal(-1, Duration.Create(-24, -45).CompareTo(Duration.Create(-24, -42))); - Assert.Equal(1, Duration.Create(-24, -42).CompareTo(Duration.Create(-25, -42))); - Assert.Equal(1, Duration.Create(24, 42).CompareTo(Duration.Create(-24, -42))); - } - - [Fact] - public void TestDurationEqual() - { - // Positive tests. - Assert.Equal(Duration.Create(0, 0), Duration.Create(0, 0)); - Assert.Equal(Duration.Create(24, 42), Duration.Create(24, 42)); - Assert.Equal(Duration.Create(-24, -42), Duration.Create(-24, -42)); - // Negative tests. - Assert.NotEqual(Duration.Create(24, 42), Duration.Create(25, 42)); - Assert.NotEqual(Duration.Create(24, 42), Duration.Create(24, 43)); - Assert.NotEqual(Duration.Create(-24, -42), Duration.Create(-25, -42)); - Assert.NotEqual(Duration.Create(-24, -42), Duration.Create(-24, -43)); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs b/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs deleted file mode 100644 index e1a97f41ee9..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Common/TimestampTest.cs +++ /dev/null @@ -1,161 +0,0 @@ -// -// 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.Common.Test -{ - using System; - using Xunit; - - public class TimestampTest - { - [Fact] - public void TimestampCreate() - { - Assert.Equal(24, Timestamp.Create(24, 42).Seconds); - Assert.Equal(42, Timestamp.Create(24, 42).Nanos); - Assert.Equal(-24, Timestamp.Create(-24, 42).Seconds); - Assert.Equal(42, Timestamp.Create(-24, 42).Nanos); - Assert.Equal(315576000000L, Timestamp.Create(315576000000L, 999999999).Seconds); - Assert.Equal(999999999, Timestamp.Create(315576000000L, 999999999).Nanos); - Assert.Equal(-315576000000L, Timestamp.Create(-315576000000L, 999999999).Seconds); - Assert.Equal(999999999, Timestamp.Create(-315576000000L, 999999999).Nanos); - } - - [Fact] - public void TimestampCreate_InvalidInput() - { - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(-315576000001L, 0)); - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(315576000001L, 0)); - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(1, 1000000000)); - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(1, -1)); - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(-1, 1000000000)); - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(-1, -1)); - } - - [Fact] - public void TimestampFromMillis() - { - Assert.Equal(Timestamp.Create(0, 0), Timestamp.FromMillis(0)); - Assert.Equal(Timestamp.Create(0, 987000000), Timestamp.FromMillis(987)); - Assert.Equal(Timestamp.Create(3, 456000000), Timestamp.FromMillis(3456)); - } - - [Fact] - public void TimestampFromMillis_Negative() - { - Assert.Equal(Timestamp.Create(-1, 999000000), Timestamp.FromMillis(-1)); - Assert.Equal(Timestamp.Create(-1, 1000000), Timestamp.FromMillis(-999)); - Assert.Equal(Timestamp.Create(-4, 544000000), Timestamp.FromMillis(-3456)); - } - - [Fact] - public void TimestampAddNanos() - { - var timestamp = Timestamp.Create(1234, 223); - Assert.Equal(timestamp, timestamp.AddNanos(0)); - Assert.Equal(Timestamp.Create(1235, 0), timestamp.AddNanos(999999777)); - Assert.Equal(Timestamp.Create(1235, 300200723), timestamp.AddNanos(1300200500)); - Assert.Equal(Timestamp.Create(1236, 0), timestamp.AddNanos(1999999777)); - Assert.Equal(Timestamp.Create(1243, 876544012), timestamp.AddNanos(9876543789L)); - Assert.Equal(Timestamp.Create(1234L + 9223372036L, 223 + 854775807), timestamp.AddNanos(Int64.MaxValue)) - ; - } - - [Fact] - public void TimestampAddNanos_Negative() - { - var timestamp = Timestamp.Create(1234, 223); - Assert.Equal(Timestamp.Create(1234, 0), timestamp.AddNanos(-223)); - Assert.Equal(Timestamp.Create(1233, 0), timestamp.AddNanos(-1000000223)); - Assert.Equal(Timestamp.Create(1232, 699799723), timestamp.AddNanos(-1300200500)); - Assert.Equal(Timestamp.Create(1229, 876544010), timestamp.AddNanos(-4123456213L)); - Assert.Equal(Timestamp.Create(1234L - 9223372036L - 1, 223 + 145224192), timestamp.AddNanos(Int64.MinValue)) - ; - } - - [Fact] - public void TimestampAddDuration() - { - var timestamp = Timestamp.Create(1234, 223); - Assert.Equal(Timestamp.Create(1235, 223), timestamp.AddDuration(Duration.Create(1, 0))); - Assert.Equal(Timestamp.Create(1234, 224), timestamp.AddDuration(Duration.Create(0, 1))); - Assert.Equal(Timestamp.Create(1235, 224), timestamp.AddDuration(Duration.Create(1, 1))); - Assert.Equal(Timestamp.Create(1236, 123), timestamp.AddDuration(Duration.Create(1, 999999900))); - } - - [Fact] - public void TimestampAddDuration_Negative() - { - var timestamp = Timestamp.Create(1234, 223); - Assert.Equal(Timestamp.Create(0, 0), timestamp.AddDuration(Duration.Create(-1234, -223))); - Assert.Equal(Timestamp.Create(1233, 223), timestamp.AddDuration(Duration.Create(-1, 0))); - Assert.Equal(Timestamp.Create(1233, 222), timestamp.AddDuration(Duration.Create(-1, -1))); - Assert.Equal(Timestamp.Create(1232, 999999900), timestamp.AddDuration(Duration.Create(-1, -323))); - Assert.Equal(Timestamp.Create(1200, 224), timestamp.AddDuration(Duration.Create(-33, -999999999))); - } - - [Fact] - public void TimestampSubtractTimestamp() - { - var timestamp = Timestamp.Create(1234, 223); - Assert.Equal(Duration.Create(1234, 223), timestamp.SubtractTimestamp(Timestamp.Create(0, 0))); - Assert.Equal(Duration.Create(1, 0), timestamp.SubtractTimestamp(Timestamp.Create(1233, 223))); - Assert.Equal(Duration.Create(1, 1), timestamp.SubtractTimestamp(Timestamp.Create(1233, 222))); - Assert.Equal(Duration.Create(1, 323), timestamp.SubtractTimestamp(Timestamp.Create(1232, 999999900))); - Assert.Equal(Duration.Create(33, 999999999), timestamp.SubtractTimestamp(Timestamp.Create(1200, 224))); - } - - [Fact] - public void TimestampSubtractTimestamp_NegativeResult() - { - var timestamp = Timestamp.Create(1234, 223); - Assert.Equal(Duration.Create(-1, 0), timestamp.SubtractTimestamp(Timestamp.Create(1235, 223))); - Assert.Equal(Duration.Create(0, -1), timestamp.SubtractTimestamp(Timestamp.Create(1234, 224))); - Assert.Equal(Duration.Create(-1, -1), timestamp.SubtractTimestamp(Timestamp.Create(1235, 224))); - Assert.Equal(Duration.Create(-1, -999999900), timestamp.SubtractTimestamp(Timestamp.Create(1236, 123))); - } - - [Fact] - public void Timestamp_CompareTo() - { - Assert.Equal(0, Timestamp.Create(0, 0).CompareTo(Timestamp.Create(0, 0))); - Assert.Equal(0, Timestamp.Create(24, 42).CompareTo(Timestamp.Create(24, 42))); - Assert.Equal(0, Timestamp.Create(-24, 42).CompareTo(Timestamp.Create(-24, 42))); - Assert.Equal(1, Timestamp.Create(25, 42).CompareTo(Timestamp.Create(24, 42))); - Assert.Equal(1, Timestamp.Create(24, 45).CompareTo(Timestamp.Create(24, 42))); - Assert.Equal(-1, Timestamp.Create(24, 42).CompareTo(Timestamp.Create(25, 42))); - Assert.Equal(-1, Timestamp.Create(24, 42).CompareTo(Timestamp.Create(24, 45))); - Assert.Equal(-1, Timestamp.Create(-25, 42).CompareTo(Timestamp.Create(-24, 42))); - Assert.Equal(1, Timestamp.Create(-24, 45).CompareTo(Timestamp.Create(-24, 42))); - Assert.Equal(1, Timestamp.Create(-24, 42).CompareTo(Timestamp.Create(-25, 42))); - Assert.Equal(-1, Timestamp.Create(-24, 42).CompareTo(Timestamp.Create(-24, 45))); - } - - [Fact] - public void Timestamp_Equal() - { - // Positive tests. - Assert.Equal(Timestamp.Create(0, 0), Timestamp.Create(0, 0)); - Assert.Equal(Timestamp.Create(24, 42), Timestamp.Create(24, 42)); - Assert.Equal(Timestamp.Create(-24, 42), Timestamp.Create(-24, 42)); - // Negative tests. - Assert.NotEqual(Timestamp.Create(24, 42), Timestamp.Create(25, 42)); - Assert.NotEqual(Timestamp.Create(24, 42), Timestamp.Create(24, 43)); - Assert.NotEqual(Timestamp.Create(-24, 42), Timestamp.Create(-25, 42)); - Assert.NotEqual(Timestamp.Create(-24, 42), Timestamp.Create(-24, 43)); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs index dcbc8ef2bd2..16cb28e0b92 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MeasureMapBuilderTest.cs @@ -36,14 +36,14 @@ public class MeasureMapBuilderTest public void TestPutDouble() { var metrics = MeasureMapBuilder.Builder().Put(M1, 44.4).Build(); - AssertContains(metrics, MeasurementDouble.Create(M1, 44.4) ); + AssertCollectionsAreSame(metrics, MeasurementDouble.Create(M1, 44.4) ); } [Fact] public void TestPutLong() { var metrics = MeasureMapBuilder.Builder().Put(M3, 9999L).Put(M4, 8888L).Build(); - AssertContains(metrics, MeasurementLong.Create(M3, 9999L), MeasurementLong.Create(M4, 8888L)); + AssertCollectionsAreSame(metrics, MeasurementLong.Create(M3, 9999L), MeasurementLong.Create(M4, 8888L)); } [Fact] @@ -56,7 +56,7 @@ public void TestCombination() .Put(M3, 9999L) .Put(M4, 8888L) .Build(); - AssertContains( + AssertCollectionsAreSame( metrics, MeasurementDouble.Create(M1, 44.4), MeasurementDouble.Create(M2, 66.6), MeasurementLong.Create(M3, 9999L), MeasurementLong.Create(M4, 8888L)); @@ -66,7 +66,7 @@ public void TestCombination() public void TestBuilderEmpty() { var metrics = MeasureMapBuilder.Builder().Build(); - AssertContains(metrics); + AssertCollectionsAreSame(metrics); } [Fact] @@ -79,24 +79,24 @@ public void TestBuilder() expected.Add(MeasurementDouble.Create(MakeSimpleMeasureDouble("m" + i), i * 11.1)); builder.Put(MakeSimpleMeasureDouble("m" + i), i * 11.1); var expArray = expected.ToArray(); - AssertContains(builder.Build(), expArray); + AssertCollectionsAreSame(builder.Build(), expArray); } } [Fact] public void TestDuplicateMeasureDoubles() { - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M1, 1.0).Put(M1, 2.0).Build(), MeasurementDouble.Create(M1, 2.0)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M1, 1.0).Put(M1, 2.0).Put(M1, 3.0).Build(), MeasurementDouble.Create(M1, 3.0)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M1, 1.0).Put(M2, 2.0).Put(M1, 3.0).Build(), MeasurementDouble.Create(M1, 3.0), MeasurementDouble.Create(M2, 2.0)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M1, 1.0).Put(M1, 2.0).Put(M2, 2.0).Build(), MeasurementDouble.Create(M1, 2.0), MeasurementDouble.Create(M2, 2.0)); @@ -105,17 +105,17 @@ public void TestDuplicateMeasureDoubles() [Fact] public void TestDuplicateMeasureLongs() { - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M3, 100L).Put(M3, 100L).Build(), MeasurementLong.Create(M3, 100L)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M3, 100L).Put(M3, 200L).Put(M3, 300L).Build(), MeasurementLong.Create(M3, 300L)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M3, 100L).Put(M4, 200L).Put(M3, 300L).Build(), MeasurementLong.Create(M3, 300L), MeasurementLong.Create(M4, 200L)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M3, 100L).Put(M3, 200L).Put(M4, 200L).Build(), MeasurementLong.Create(M3, 200L), MeasurementLong.Create(M4, 200L)); @@ -124,11 +124,11 @@ public void TestDuplicateMeasureLongs() [Fact] public void TestDuplicateMeasures() { - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M3, 100L).Put(M1, 1.0).Put(M3, 300L).Build(), MeasurementLong.Create(M3, 300L), MeasurementDouble.Create(M1, 1.0)); - AssertContains( + AssertCollectionsAreSame( MeasureMapBuilder.Builder().Put(M2, 2.0).Put(M3, 100L).Put(M2, 3.0).Build(), MeasurementDouble.Create(M2, 3.0), MeasurementLong.Create(M3, 100L)); @@ -144,10 +144,16 @@ private static IMeasureLong MakeSimpleMeasureLong(String measure) return MeasureLong.Create(measure, measure + " description", "1"); } - private static void AssertContains(IEnumerable metrics, params IMeasurement[] measurements) + private static void AssertCollectionsAreSame(IEnumerable metrics, params IMeasurement[] measurements) { - var expected = measurements.ToList(); - Assert.True(Collections.AreEquivalent(metrics, expected)); + var metricsList = metrics.ToList(); + var measurementsList = measurements.ToList(); + Assert.Equal(metricsList.Count, measurementsList.Count); + + foreach (var measurement in measurements) + { + Assert.Contains(measurement, metricsList); + } } } } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs index 101b9747c4f..7ec52f1a54b 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/MutableViewDataTest.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Stats.Test { using System; using System.Collections.Generic; - using OpenTelemetry.Common; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; @@ -41,7 +40,6 @@ public class MutableViewDataTest public void TestConstants() { Assert.Null(MutableViewData.UnknownTagValue); - Assert.Equal(Timestamp.Create(0, 0), MutableViewData.ZeroTimestamp); } [Fact] @@ -112,16 +110,5 @@ public void CreateAggregationData() Assert.Equal(expected, aggregates); } - - [Fact] - public void TestDurationToMillis() - { - Assert.Equal(0, MutableViewData.ToMillis(Duration.Create(0, 0))); - Assert.Equal(987, MutableViewData.ToMillis(Duration.Create(0, 987000000))); - Assert.Equal(3456, MutableViewData.ToMillis(Duration.Create(3, 456000000))); - Assert.Equal(-1, MutableViewData.ToMillis(Duration.Create(0, -1000000))); - Assert.Equal(-1000, MutableViewData.ToMillis(Duration.Create(-1, 0))); - Assert.Equal(-3456, MutableViewData.ToMillis(Duration.Create(-3, -456000000))); - } } } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs index fcf20da8283..78c8861ab74 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/NoopViewManagerTest.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Stats.Test { using System; using System.Collections.Generic; - using OpenTelemetry.Common; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; @@ -26,13 +25,13 @@ namespace OpenTelemetry.Stats.Test public class NoopViewManagerTest { - private static readonly IMeasureDouble MEASURE = MeasureDouble.Create("my measure", "description", "s"); - private static readonly TagKey KEY = TagKey.Create("KEY"); - private static readonly IViewName VIEW_NAME = ViewName.Create("my view"); - private static readonly String VIEW_DESCRIPTION = "view description"; - private static readonly ISum AGGREGATION = Sum.Create(); + private static readonly IMeasureDouble Measure = MeasureDouble.Create("my measure", "description", "s"); + private static readonly TagKey Key = TagKey.Create("KEY"); + private static readonly IViewName ViewName = OpenTelemetry.Stats.ViewName.Create("my view"); + private static readonly String ViewDescription = "view description"; + private static readonly ISum Aggregation = Sum.Create(); // private static readonly Cumulative CUMULATIVE = Cumulative.create(); - private static readonly Duration TEN_SECONDS = Duration.Create(10, 0); + private static readonly TimeSpan TenSeconds = TimeSpan.FromSeconds(10); // private static readonly Interval INTERVAL = Interval.create(TEN_SECONDS); // @Rule public readonly ExpectedException thrown = ExpectedException.none(); @@ -42,10 +41,10 @@ public void NoopViewManager_RegisterView_DisallowRegisteringDifferentViewWithSam { var view1 = View.Create( - VIEW_NAME, "description 1", MEASURE, AGGREGATION, new List { KEY }); + ViewName, "description 1", Measure, Aggregation, new List { Key }); var view2 = View.Create( - VIEW_NAME, "description 2", MEASURE, AGGREGATION, new List { KEY }); + ViewName, "description 2", Measure, Aggregation, new List { Key }); var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view1); @@ -55,7 +54,7 @@ public void NoopViewManager_RegisterView_DisallowRegisteringDifferentViewWithSam } finally { - Assert.Equal(view1, viewManager.GetView(VIEW_NAME).View); + Assert.Equal(view1, viewManager.GetView(ViewName).View); } } @@ -64,7 +63,7 @@ public void NoopViewManager_RegisterView_AllowRegisteringSameViewTwice() { var view = View.Create( - VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); + ViewName, ViewDescription, Measure, Aggregation, new List { Key }); var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view); viewManager.RegisterView(view); @@ -81,7 +80,7 @@ public void NoopViewManager_RegisterView_DisallowNull() public void NoopViewManager_GetView_GettingNonExistentViewReturnsNull() { var viewManager = NoopStats.NewNoopViewManager(); - Assert.Null(viewManager.GetView(VIEW_NAME)); + Assert.Null(viewManager.GetView(ViewName)); } [Fact] @@ -89,11 +88,11 @@ public void NoopViewManager_GetView_Cumulative() { var view = View.Create( - VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); + ViewName, ViewDescription, Measure, Aggregation, new List { Key }); var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view); - var viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(ViewName); Assert.Equal(view, viewData.View); Assert.Empty(viewData.AggregationMap); Assert.Equal(DateTimeOffset.MinValue, viewData.Start); @@ -106,11 +105,11 @@ public void noopViewManager_GetView_Interval() { var view = View.Create( - VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); + ViewName, ViewDescription, Measure, Aggregation, new List { Key }); var viewManager = NoopStats.NewNoopViewManager(); viewManager.RegisterView(view); - var viewData = viewManager.GetView(VIEW_NAME); + var viewData = viewManager.GetView(ViewName); Assert.Equal(view, viewData.View); Assert.Empty(viewData.AggregationMap); Assert.Equal(DateTimeOffset.MinValue, viewData.Start); @@ -132,18 +131,18 @@ public void GetAllExportedViews() Assert.Empty(viewManager.AllExportedViews); var cumulativeView1 = View.Create( - ViewName.Create("View 1"), - VIEW_DESCRIPTION, - MEASURE, - AGGREGATION, - new List { KEY }); + OpenTelemetry.Stats.ViewName.Create("View 1"), + ViewDescription, + Measure, + Aggregation, + new List { Key }); var cumulativeView2 = View.Create( - ViewName.Create("View 2"), - VIEW_DESCRIPTION, - MEASURE, - AGGREGATION, - new List { KEY }); + OpenTelemetry.Stats.ViewName.Create("View 2"), + ViewDescription, + Measure, + Aggregation, + new List { Key }); viewManager.RegisterView(cumulativeView1); @@ -161,13 +160,13 @@ public void GetAllExportedViews_ResultIsUnmodifiable() var viewManager = NoopStats.NewNoopViewManager(); var view1 = View.Create( - ViewName.Create("View 1"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); + OpenTelemetry.Stats.ViewName.Create("View 1"), ViewDescription, Measure, Aggregation, new List { Key }); viewManager.RegisterView(view1); var exported = viewManager.AllExportedViews; var view2 = View.Create( - ViewName.Create("View 2"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, new List { KEY }); + OpenTelemetry.Stats.ViewName.Create("View 2"), ViewDescription, Measure, Aggregation, new List { Key }); Assert.Throws(() => exported.Add(view2)); } } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs b/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs index 32e6ed0197e..c334c4b35b2 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/StatsTestUtil.cs @@ -19,15 +19,12 @@ namespace OpenTelemetry.Stats.Test using System; using System.Collections.Generic; using System.Linq; - using OpenTelemetry.Common; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Tags; using Xunit; internal static class StatsTestUtil { - static readonly Timestamp ZERO_TIMESTAMP = Timestamp.Create(0, 0); - internal static IAggregationData CreateAggregationData(IAggregation aggregation, IMeasure measure, params double[] values) { var mutableAggregation = MutableViewData.CreateMutableAggregation(aggregation); diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs index 34463ded65a..9ae6648d945 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewManagerTest.cs @@ -19,7 +19,7 @@ namespace OpenTelemetry.Stats.Test using System; using System.Collections.Generic; using System.Linq; - using OpenTelemetry.Common; + using OpenTelemetry.Abstractions.Utils; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; @@ -27,37 +27,32 @@ namespace OpenTelemetry.Stats.Test public class ViewManagerTest { - private static readonly TagKey KEY = TagKey.Create("KEY"); - private static readonly TagValue VALUE = TagValue.Create("VALUE"); - private static readonly TagValue VALUE_2 = TagValue.Create("VALUE_2"); - private static readonly String MEASURE_NAME = "my measurement"; - private static readonly String MEASURE_NAME_2 = "my measurement 2"; - private static readonly String MEASURE_UNIT = "us"; - private static readonly String MEASURE_DESCRIPTION = "measure description"; - private static readonly IMeasureDouble MEASURE_DOUBLE = CreateRandomMeasureDouble(); - private static readonly IMeasureLong MEASURE_LONG = MeasureLong.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT); - - //private static readonly IViewName VIEW_NAME = ViewName.Create("my view"); - //private static readonly IViewName VIEW_NAME_2 = ViewName.Create("my view 2"); - - private static readonly String VIEW_DESCRIPTION = "view description"; - - // private static readonly Cumulative CUMULATIVE = Cumulative.Create(); - - private static readonly double EPSILON = 1e-7; - private static readonly int RANDOM_NAME_LEN = 8; - private static readonly Duration TEN_SECONDS = Duration.Create(10, 0); - // private static readonly Interval INTERVAL = Interval.Create(TEN_SECONDS); - - private static readonly IBucketBoundaries BUCKET_BOUNDARIES = - BucketBoundaries.Create( + private static readonly TagKey Key = TagKey.Create("Key"); + private static readonly TagValue Value = TagValue.Create("Value"); + private static readonly TagValue Value2 = TagValue.Create("Value2"); + private static readonly String MeasureUnit = "us"; + private static readonly String MeasureDescription = "measure description"; + private static readonly IMeasureDouble MeasureDouble = CreateRandomMeasureDouble(); + private static readonly IMeasureLong MeasureLong = Measures.MeasureLong.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit); + + private static readonly IViewName ViewName = OpenTelemetry.Stats.ViewName.Create("my view"); + private static readonly IViewName ViewName2 = OpenTelemetry.Stats.ViewName.Create("my view 2"); + + private static readonly string VIEW_DESCRIPTION = "view description"; + + private static readonly double Epsilon = 1e-7; + private static readonly int RandomNameLen = 8; + private static readonly TimeSpan TenSeconds = TimeSpan.FromSeconds(10); + + private static readonly IBucketBoundaries BucketBoundaries = + OpenTelemetry.Stats.BucketBoundaries.Create( new List() { 0.0, 0.2, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0,}); - private static readonly ISum SUM = Sum.Create(); - private static readonly IMean MEAN = Mean.Create(); - private static readonly IDistribution DISTRIBUTION = Distribution.Create(BUCKET_BOUNDARIES); - private static readonly ILastValue LAST_VALUE = LastValue.Create(); + private static readonly ISum Sum = Aggregations.Sum.Create(); + private static readonly IMean Mean = Aggregations.Mean.Create(); + private static readonly IDistribution Distribution = Aggregations.Distribution.Create(BucketBoundaries); + private static readonly ILastValue LastValue = Aggregations.LastValue.Create(); private static readonly IViewManager viewManager = Stats.ViewManager; private static readonly IStatsRecorder statsRecorder = Stats.StatsRecorder; @@ -71,7 +66,7 @@ public ViewManagerTest() private static IView CreateCumulativeView() { - return CreateCumulativeView(CreateRandomViewName(), CreateRandomMeasureDouble(), DISTRIBUTION, new List() { KEY }); + return CreateCumulativeView(CreateRandomViewName(), CreateRandomMeasureDouble(), Distribution, new List() { Key }); } private static IView CreateCumulativeView( @@ -101,17 +96,17 @@ public void TestGetAllExportedViews() IView cumulativeView1 = CreateCumulativeView( - viewName1, measure, DISTRIBUTION, new List() { KEY }); + viewName1, measure, Distribution, new List() { Key }); IView cumulativeView2 = CreateCumulativeView( - viewName2, measure, DISTRIBUTION, new List() { KEY }); + viewName2, measure, Distribution, new List() { Key }); // View intervalView = // View.Create( // View.Name.Create("View 3"), // VIEW_DESCRIPTION, // measure, - // DISTRIBUTION, - // Arrays.asList(KEY), + // Distribution, + // Arrays.asList(Key), // INTERVAL); viewManager.RegisterView(cumulativeView1); viewManager.RegisterView(cumulativeView2); @@ -134,8 +129,8 @@ public void GetAllExportedViewsResultIsUnmodifiable() viewName1, VIEW_DESCRIPTION, measure, - DISTRIBUTION, - new List() { KEY }); + Distribution, + new List() { Key }); viewManager.RegisterView(view1); ISet exported = viewManager.AllExportedViews; @@ -144,8 +139,8 @@ public void GetAllExportedViewsResultIsUnmodifiable() viewName2, VIEW_DESCRIPTION, measure, - DISTRIBUTION, - new List() { KEY }); + Distribution, + new List() { Key }); Assert.Throws(() => exported.Add(view2)); } @@ -156,9 +151,9 @@ public void GetAllExportedViewsResultIsUnmodifiable() // View.Create( // VIEW_NAME, // VIEW_DESCRIPTION, - // MEASURE_DOUBLE, - // DISTRIBUTION, - // Arrays.asList(KEY), + // MeasureDouble, + // Distribution, + // Arrays.asList(Key), // INTERVAL); // viewManager.RegisterView(intervalView); // Assert.Equal(viewManager.GetView(VIEW_NAME).GetView()).isEqualTo(intervalView); @@ -186,33 +181,33 @@ public void PreventRegisteringDifferentViewWithSameName() viewName, "View description.", measure, - DISTRIBUTION, - new List() { KEY }); + Distribution, + new List() { Key }); IView view2 = View.Create( viewName, "This is a different description.", measure, - DISTRIBUTION, - new List() { KEY }); + Distribution, + new List() { Key }); TestFailedToRegisterView(view1, view2, "A different view with the same name is already registered"); } [Fact] public void PreventRegisteringDifferentMeasureWithSameName() { - IMeasureDouble measure1 = MeasureDouble.Create("measure", "description", "1"); - IMeasureLong measure2 = MeasureLong.Create("measure", "description", "1"); + IMeasureDouble measure1 = Measures.MeasureDouble.Create("measure", "description", "1"); + IMeasureLong measure2 = Measures.MeasureLong.Create("measure", "description", "1"); IViewName viewName1 = CreateRandomViewName(); IViewName viewName2 = CreateRandomViewName(); IView view1 = View.Create( - viewName1, VIEW_DESCRIPTION, measure1, DISTRIBUTION, new List() { KEY }); + viewName1, VIEW_DESCRIPTION, measure1, Distribution, new List() { Key }); IView view2 = View.Create( - viewName2, VIEW_DESCRIPTION, measure2, DISTRIBUTION, new List() { KEY }); + viewName2, VIEW_DESCRIPTION, measure2, Distribution, new List() { Key }); TestFailedToRegisterView(view1, view2, "A different measure with the same name is already registered"); } @@ -236,80 +231,82 @@ public void ReturnNullWhenGettingNonexistentViewData() [Fact] public void TestRecordDouble_Distribution_Cumulative() { - TestRecordCumulative(CreateRandomMeasureDouble(), DISTRIBUTION, 10.0, 20.0, 30.0, 40.0); + TestRecordCumulative(CreateRandomMeasureDouble(), Distribution, 10.0, 20.0, 30.0, 40.0); } [Fact] public void TestRecordLong_Distribution_Cumulative() { - TestRecordCumulative(CreateRandomMeasureLong(), DISTRIBUTION, 1000, 2000, 3000, 4000); + TestRecordCumulative(CreateRandomMeasureLong(), Distribution, 1000, 2000, 3000, 4000); } [Fact] public void TestRecordDouble_Sum_Cumulative() { - TestRecordCumulative(CreateRandomMeasureDouble(), SUM, 11.1, 22.2, 33.3, 44.4); + TestRecordCumulative(CreateRandomMeasureDouble(), Sum, 11.1, 22.2, 33.3, 44.4); } [Fact] public void TestRecordLong_Sum_Cumulative() { - TestRecordCumulative(CreateRandomMeasureLong(), SUM, 1000, 2000, 3000, 4000); + TestRecordCumulative(CreateRandomMeasureLong(), Sum, 1000, 2000, 3000, 4000); } [Fact] public void TestRecordDouble_Lastvalue_Cumulative() { - TestRecordCumulative(CreateRandomMeasureDouble(), LAST_VALUE, 11.1, 22.2, 33.3, 44.4); + TestRecordCumulative(CreateRandomMeasureDouble(), LastValue, 11.1, 22.2, 33.3, 44.4); } [Fact] public void TestRecordLong_Lastvalue_Cumulative() { - TestRecordCumulative(CreateRandomMeasureLong(), LAST_VALUE, 1000, 2000, 3000, 4000); + TestRecordCumulative(CreateRandomMeasureLong(), LastValue, 1000, 2000, 3000, 4000); } private void TestRecordCumulative(IMeasure measure, IAggregation aggregation, params double[] values) { - IView view = CreateCumulativeView(CreateRandomViewName(), measure, aggregation, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), measure, aggregation, new List() { Key }); viewManager.RegisterView(view); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + ITagContext tags = tagger.EmptyBuilder.Put(Key, Value).Build(); foreach (double val in values) { PutToMeasureMap(statsRecorder.NewMeasureMap(), measure, val).Record(tags); } IViewData viewData = viewManager.GetView(view.Name); + Assert.Equal(view, viewData.View); - var tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, new Dictionary() { {tv, StatsTestUtil.CreateAggregationData(aggregation, measure, values) }, }, - EPSILON); + Epsilon); } [Fact] public void GetViewDoesNotClearStats() { - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { Key }); viewManager.RegisterView(view); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); - statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 0.1).Record(tags); + ITagContext tags = tagger.EmptyBuilder.Put(Key, Value).Build(); + statsRecorder.NewMeasureMap().Put(MeasureDouble, 0.1).Record(tags); IViewData viewData1 = viewManager.GetView(view.Name); - var tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { Value }); + StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 0.1) }, + {tv, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 0.1) }, }, - EPSILON); + Epsilon); - statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 0.2).Record(tags); + statsRecorder.NewMeasureMap().Put(MeasureDouble, 0.2).Record(tags); IViewData viewData2 = viewManager.GetView(view.Name); // The second view should have the same start time as the first view, and it should include both @@ -319,39 +316,40 @@ public void GetViewDoesNotClearStats() viewData2.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 0.1, 0.2) }, + {tv, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 0.1, 0.2) }, }, - EPSILON); + Epsilon); } [Fact] public void TestRecordCumulativeMultipleTagValues() { - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { Key }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 10.0) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); + .Put(MeasureDouble, 10.0) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 30.0) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE_2).Build()); + .Put(MeasureDouble, 30.0) + .Record(tagger.EmptyBuilder.Put(Key, Value2).Build()); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 50.0) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE_2).Build()); + .Put(MeasureDouble, 50.0) + .Record(tagger.EmptyBuilder.Put(Key, Value2).Build()); IViewData viewData = viewManager.GetView(view.Name); - var tv = TagValues.Create(new List() { VALUE }); - var tv2 = TagValues.Create(new List() { VALUE_2 }); + var tv = TagValues.Create(new List() { Value }); + var tv2 = TagValues.Create(new List() { Value2 }); + StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, new Dictionary() { - { tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0)}, - { tv2, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 30.0, 50.0)}, + { tv, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 10.0)}, + { tv2, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 30.0, 50.0)}, }, - EPSILON); + Epsilon); } @@ -362,8 +360,8 @@ public void AllowRecordingWithoutRegisteringMatchingViewData() { statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 10) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); + .Put(MeasureDouble, 10) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); } [Fact] @@ -371,10 +369,10 @@ public void TestRecordWithEmptyStatsContext() { Stats.State = StatsCollectionState.ENABLED; - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { Key }); viewManager.RegisterView(view); - // DEFAULT doesn't have tags, but the view has tag key "KEY". - statsRecorder.NewMeasureMap().Put(MEASURE_DOUBLE, 10.0).Record(tagger.Empty); + // DEFAULT doesn't have tags, but the view has tag key "Key". + statsRecorder.NewMeasureMap().Put(MeasureDouble, 10.0).Record(tagger.Empty); IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { MutableViewData.UnknownTagValue }); StatsTestUtil.AssertAggregationMapEquals( @@ -384,11 +382,11 @@ public void TestRecordWithEmptyStatsContext() // Tag is missing for associated measureValues, should use default tag value // "unknown/not set". { tv, - // Should Record stats with default tag value: "KEY" : "unknown/not set". - StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0) + // Should Record stats with default tag value: "Key" : "unknown/not set". + StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 10.0) }, }, - EPSILON); + Epsilon); } @@ -396,8 +394,8 @@ public void TestRecordWithEmptyStatsContext() public void TestRecord_MeasureNameNotMatch() { TestRecord_MeasureNotMatch( - MeasureDouble.Create(CreateRandomMeasureName(), "measure", MEASURE_UNIT), - MeasureDouble.Create(CreateRandomMeasureName(), "measure", MEASURE_UNIT), + Measures.MeasureDouble.Create(CreateRandomMeasureName(), "measure", MeasureUnit), + Measures.MeasureDouble.Create(CreateRandomMeasureName(), "measure", MeasureUnit), 10.0); } @@ -406,16 +404,16 @@ public void TestRecord_MeasureTypeNotMatch() { string name = CreateRandomMeasureName(); TestRecord_MeasureNotMatch( - MeasureLong.Create(name, "measure", MEASURE_UNIT), - MeasureDouble.Create(name, "measure", MEASURE_UNIT), + Measures.MeasureLong.Create(name, "measure", MeasureUnit), + Measures.MeasureDouble.Create(name, "measure", MeasureUnit), 10.0); } private void TestRecord_MeasureNotMatch(IMeasure measure1, IMeasure measure2, double value) { - IView view = CreateCumulativeView(CreateRandomViewName(), measure1, MEAN, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), measure1, Mean, new List() { Key }); viewManager.RegisterView(view); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + ITagContext tags = tagger.EmptyBuilder.Put(Key, Value).Build(); PutToMeasureMap(statsRecorder.NewMeasureMap(), measure2, value).Record(tags); IViewData viewData = viewManager.GetView(view.Name); Assert.Empty(viewData.AggregationMap); @@ -426,16 +424,16 @@ public void TestRecordWithTagsThatDoNotMatchViewData() { Stats.State = StatsCollectionState.ENABLED; - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { Key }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 10.0) - .Record(tagger.EmptyBuilder.Put(TagKey.Create("wrong key"), VALUE).Build()); + .Put(MeasureDouble, 10.0) + .Record(tagger.EmptyBuilder.Put(TagKey.Create("wrong key"), Value).Build()); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 50.0) - .Record(tagger.EmptyBuilder.Put(TagKey.Create("another wrong key"), VALUE).Build()); + .Put(MeasureDouble, 50.0) + .Record(tagger.EmptyBuilder.Put(TagKey.Create("another wrong key"), Value).Build()); IViewData viewData = viewManager.GetView(view.Name); var tv = TagValues.Create(new List() { MutableViewData.UnknownTagValue }); StatsTestUtil.AssertAggregationMapEquals( @@ -445,11 +443,11 @@ public void TestRecordWithTagsThatDoNotMatchViewData() // Won't Record the unregistered tag key, for missing registered keys will use default // tag value : "unknown/not set". { tv, - // Should Record stats with default tag value: "KEY" : "unknown/not set". - StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 10.0, 50.0) + // Should Record stats with default tag value: "Key" : "unknown/not set". + StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 10.0, 50.0) }, }, - EPSILON); + Epsilon); } [Fact] @@ -457,11 +455,11 @@ public void TestViewDataWithMultipleTagKeys() { TagKey key1 = TagKey.Create("Key-1"); TagKey key2 = TagKey.Create("Key-2"); - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { key1, key2 }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { key1, key2 }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) + .Put(MeasureDouble, 1.1) .Record( tagger .EmptyBuilder @@ -470,7 +468,7 @@ public void TestViewDataWithMultipleTagKeys() .Build()); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 2.2) + .Put(MeasureDouble, 2.2) .Record( tagger .EmptyBuilder @@ -479,7 +477,7 @@ public void TestViewDataWithMultipleTagKeys() .Build()); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 3.3) + .Put(MeasureDouble, 3.3) .Record( tagger .EmptyBuilder @@ -488,7 +486,7 @@ public void TestViewDataWithMultipleTagKeys() .Build()); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 4.4) + .Put(MeasureDouble, 4.4) .Record( tagger .EmptyBuilder @@ -503,52 +501,52 @@ public void TestViewDataWithMultipleTagKeys() viewData.AggregationMap, new Dictionary() { - { tv1, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 1.1, 4.4) }, - { tv2, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 2.2) }, - { tv3, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 3.3)}, + { tv1, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 1.1, 4.4) }, + { tv2, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 2.2) }, + { tv3, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 3.3)}, }, - EPSILON); + Epsilon); } [Fact] public void TestMultipleViewSameMeasure() { IView view1 = - CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { Key }); IView view2 = - CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, DISTRIBUTION, new List() { KEY }); + CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Distribution, new List() { Key }); viewManager.RegisterView(view1); viewManager.RegisterView(view2); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 5.0) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); + .Put(MeasureDouble, 5.0) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); IViewData viewData1 = viewManager.GetView(view1.Name); IViewData viewData2 = viewManager.GetView(view2.Name); - var tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 5.0) }, + {tv, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 5.0) }, }, - EPSILON); + Epsilon); StatsTestUtil.AssertAggregationMapEquals( viewData2.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, MEASURE_DOUBLE, 5.0) }, + {tv, StatsTestUtil.CreateAggregationData(Distribution, MeasureDouble, 5.0) }, }, - EPSILON); + Epsilon); } [Fact] public void TestMultipleViews_DifferentMeasureNames() { TestMultipleViews_DifferentMeasures( - MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), - MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), + Measures.MeasureDouble.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit), + Measures.MeasureDouble.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit), 1.1, 2.2); } @@ -557,95 +555,95 @@ public void TestMultipleViews_DifferentMeasureNames() public void TestMultipleViews_DifferentMeasureTypes() { TestMultipleViews_DifferentMeasures( - MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), - MeasureLong.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT), + Measures.MeasureDouble.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit), + Measures.MeasureLong.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit), 1.1, 5000); } private void TestMultipleViews_DifferentMeasures(IMeasure measure1, IMeasure measure2, double value1, double value2) { - IView view1 = CreateCumulativeView(CreateRandomViewName(), measure1, DISTRIBUTION, new List() { KEY }); - IView view2 = CreateCumulativeView(CreateRandomViewName(), measure2, DISTRIBUTION, new List() { KEY }); + IView view1 = CreateCumulativeView(CreateRandomViewName(), measure1, Distribution, new List() { Key }); + IView view2 = CreateCumulativeView(CreateRandomViewName(), measure2, Distribution, new List() { Key }); viewManager.RegisterView(view1); viewManager.RegisterView(view2); - ITagContext tags = tagger.EmptyBuilder.Put(KEY, VALUE).Build(); + ITagContext tags = tagger.EmptyBuilder.Put(Key, Value).Build(); IMeasureMap measureMap = statsRecorder.NewMeasureMap(); PutToMeasureMap(measureMap, measure1, value1); PutToMeasureMap(measureMap, measure2, value2); measureMap.Record(tags); IViewData viewData1 = viewManager.GetView(view1.Name); IViewData viewData2 = viewManager.GetView(view2.Name); - var tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewData1.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, measure1, value1) }, + {tv, StatsTestUtil.CreateAggregationData(Distribution, measure1, value1) }, }, - EPSILON); + Epsilon); StatsTestUtil.AssertAggregationMapEquals( viewData2.AggregationMap, new Dictionary() { - { tv, StatsTestUtil.CreateAggregationData(DISTRIBUTION, measure2, value2) }, + { tv, StatsTestUtil.CreateAggregationData(Distribution, measure2, value2) }, }, - EPSILON); + Epsilon); } [Fact] public void TestGetCumulativeViewDataWithEmptyBucketBoundaries() { IAggregation noHistogram = - Distribution.Create(BucketBoundaries.Create(Enumerable.Empty())); - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, noHistogram, new List() { KEY }); + Aggregations.Distribution.Create(OpenTelemetry.Stats.BucketBoundaries.Create(Enumerable.Empty())); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, noHistogram, new List() { Key }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); + .Put(MeasureDouble, 1.1) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); IViewData viewData = viewManager.GetView(view.Name); - var tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(noHistogram, MEASURE_DOUBLE, 1.1) }, + {tv, StatsTestUtil.CreateAggregationData(noHistogram, MeasureDouble, 1.1) }, }, - EPSILON); + Epsilon); } [Fact] public void TestGetCumulativeViewDataWithoutBucketBoundaries() { - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Mean, new List() { Key }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); + .Put(MeasureDouble, 1.1) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); IViewData viewData = viewManager.GetView(view.Name); - var tv = TagValues.Create(new List() { VALUE }); + var tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewData.AggregationMap, new Dictionary() { - {tv, StatsTestUtil.CreateAggregationData(MEAN, MEASURE_DOUBLE, 1.1) }, + {tv, StatsTestUtil.CreateAggregationData(Mean, MeasureDouble, 1.1) }, }, - EPSILON); + Epsilon); } [Fact] public void RegisterRecordAndGetView_StatsDisabled() { Stats.State = StatsCollectionState.DISABLED; - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Mean, new List() { Key }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); + .Put(MeasureDouble, 1.1) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); Assert.Equal(StatsTestUtil.CreateEmptyViewData(view), viewManager.GetView(view.Name)); } @@ -654,42 +652,42 @@ public void RegisterRecordAndGetView_StatsReenabled() { Stats.State = StatsCollectionState.DISABLED; Stats.State = StatsCollectionState.ENABLED; - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Mean, new List() { Key }); viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - TagValues tv = TagValues.Create(new List() { VALUE }); + .Put(MeasureDouble, 1.1) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); + TagValues tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(view.Name).AggregationMap, new Dictionary() { - { tv, StatsTestUtil.CreateAggregationData(MEAN, MEASURE_DOUBLE, 1.1) }, + { tv, StatsTestUtil.CreateAggregationData(Mean, MeasureDouble, 1.1) }, }, - EPSILON); + Epsilon); } [Fact] public void RegisterViewWithStatsDisabled_RecordAndGetViewWithStatsEnabled() { Stats.State = StatsCollectionState.DISABLED; - IView view = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView view = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Mean, new List() { Key }); viewManager.RegisterView(view); // view will still be registered. Stats.State = StatsCollectionState.ENABLED; statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - TagValues tv = TagValues.Create(new List() { VALUE }); + .Put(MeasureDouble, 1.1) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); + TagValues tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(view.Name).AggregationMap, new Dictionary() { - { tv, StatsTestUtil.CreateAggregationData(MEAN, MEASURE_DOUBLE, 1.1) }, + { tv, StatsTestUtil.CreateAggregationData(Mean, MeasureDouble, 1.1) }, }, - EPSILON); + Epsilon); } [Fact] @@ -701,16 +699,16 @@ public void RegisterDifferentViewWithSameNameWithStatsDisabled() View.Create( viewName, "View description.", - MEASURE_DOUBLE, - DISTRIBUTION, - new List() { KEY }); + MeasureDouble, + Distribution, + new List() { Key }); IView view2 = View.Create( viewName, "This is a different description.", - MEASURE_DOUBLE, - DISTRIBUTION, - new List() { KEY }); + MeasureDouble, + Distribution, + new List() { Key }); TestFailedToRegisterView( view1, view2, "A different view with the same name is already registered"); @@ -719,7 +717,7 @@ public void RegisterDifferentViewWithSameNameWithStatsDisabled() [Fact] public void SettingStateToDisabledWillClearStats_Cumulative() { - IView cumulativeView = CreateCumulativeView(CreateRandomViewName(), MEASURE_DOUBLE, MEAN, new List() { KEY }); + IView cumulativeView = CreateCumulativeView(CreateRandomViewName(), MeasureDouble, Mean, new List() { Key }); SettingStateToDisabledWillClearStats(cumulativeView); } @@ -730,9 +728,9 @@ public void SettingStateToDisabledWillClearStats_Cumulative() // View.Create( // VIEW_NAME_2, // VIEW_DESCRIPTION, - // MEASURE_DOUBLE, - // MEAN, - // Arrays.asList(KEY), + // MeasureDouble, + // Mean, + // Arrays.asList(Key), // Interval.Create(Duration.Create(60, 0))); // settingStateToDisabledWillClearStats(intervalView); // } @@ -740,32 +738,32 @@ public void SettingStateToDisabledWillClearStats_Cumulative() private void SettingStateToDisabledWillClearStats(IView view) { // TODO: deal with timestamp validation - Timestamp timestamp1 = Timestamp.Create(1, 0); + var timestamp1 = PreciseTimestamp.GetUtcNow().AddSeconds(-10); //clock.Time = timestamp1; viewManager.RegisterView(view); statsRecorder .NewMeasureMap() - .Put(MEASURE_DOUBLE, 1.1) - .Record(tagger.EmptyBuilder.Put(KEY, VALUE).Build()); - TagValues tv = TagValues.Create(new List() { VALUE }); + .Put(MeasureDouble, 1.1) + .Record(tagger.EmptyBuilder.Put(Key, Value).Build()); + TagValues tv = TagValues.Create(new List() { Value }); StatsTestUtil.AssertAggregationMapEquals( viewManager.GetView(view.Name).AggregationMap, new Dictionary() { { tv, StatsTestUtil.CreateAggregationData(view.Aggregation, view.Measure, 1.1) }, }, - EPSILON); + Epsilon); - Timestamp timestamp2 = Timestamp.Create(2, 0); + var timestamp2 = timestamp1.AddSeconds(2); //clock.Time = timestamp2; Stats.State = StatsCollectionState.DISABLED; // This will clear stats. Assert.Equal(StatsTestUtil.CreateEmptyViewData(view), viewManager.GetView(view.Name)); - Timestamp timestamp3 = Timestamp.Create(3, 0); + var timestamp3 = timestamp1.AddSeconds(3); //clock.Time = timestamp3; Stats.State = StatsCollectionState.ENABLED; - Timestamp timestamp4 = Timestamp.Create(4, 0); + var timestamp4 = timestamp1.AddSeconds(4); //clock.Time = timestamp4; // This ViewData does not have any stats, but it should not be an empty ViewData, since it has // non-zero TimeStamps. @@ -802,22 +800,22 @@ public static string RandomString(int length) private static IViewName CreateRandomViewName() { - return ViewName.Create(RandomString(RANDOM_NAME_LEN)); + return OpenTelemetry.Stats.ViewName.Create(RandomString(RandomNameLen)); } private static string CreateRandomMeasureName() { - return RandomString(RANDOM_NAME_LEN); + return RandomString(RandomNameLen); } private static IMeasureDouble CreateRandomMeasureDouble() { - return MeasureDouble.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT); + return Measures.MeasureDouble.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit); } private static IMeasureLong CreateRandomMeasureLong() { - return MeasureLong.Create(CreateRandomMeasureName(), MEASURE_DESCRIPTION, MEASURE_UNIT); + return Measures.MeasureLong.Create(CreateRandomMeasureName(), MeasureDescription, MeasureUnit); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs b/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs index 9a713de0840..ad47bf90538 100644 --- a/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Stats/ViewTest.cs @@ -18,7 +18,6 @@ namespace OpenTelemetry.Stats.Test { using System; using System.Collections.Generic; - using OpenTelemetry.Common; using OpenTelemetry.Stats.Aggregations; using OpenTelemetry.Stats.Measures; using OpenTelemetry.Tags; @@ -26,18 +25,18 @@ namespace OpenTelemetry.Stats.Test public class ViewTest { - private static readonly IViewName NAME = ViewName.Create("test-view-name"); - private static readonly String DESCRIPTION = "test-view-name description"; - private static readonly IMeasure MEASURE = + private static readonly IViewName Name = ViewName.Create("test-view-name"); + private static readonly string Description = "test-view-name description"; + private static readonly IMeasure Measure = MeasureDouble.Create("measure", "measure description", "1"); - private static readonly TagKey FOO = TagKey.Create("foo"); - private static readonly TagKey BAR = TagKey.Create("bar"); - private static readonly List keys = new List() { FOO, BAR }; - private static readonly IMean MEAN = Mean.Create(); - private static readonly Duration MINUTE = Duration.Create(60, 0); - private static readonly Duration TWO_MINUTES = Duration.Create(120, 0); - private static readonly Duration NEG_TEN_SECONDS = Duration.Create(-10, 0); + private static readonly TagKey Foo = TagKey.Create("foo"); + private static readonly TagKey Bar = TagKey.Create("bar"); + private static readonly List keys = new List() { Foo, Bar }; + private static readonly IMean Mean = Aggregations.Mean.Create(); + private static readonly TimeSpan Minute = TimeSpan.FromMinutes(1); + private static readonly TimeSpan TwoMinutes = TimeSpan.FromMinutes(2); + private static readonly TimeSpan NegTenSeconds = TimeSpan.FromSeconds(-10); [Fact] public void TestConstants() @@ -48,25 +47,24 @@ public void TestConstants() [Fact] public void TestDistributionView() { - var view = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); - Assert.Equal(NAME, view.Name); - Assert.Equal(DESCRIPTION, view.Description); - Assert.Equal(MEASURE.Name, view.Measure.Name); - Assert.Equal(MEAN, view.Aggregation); + var view = View.Create(Name, Description, Measure, Mean, keys); + Assert.Equal(Name, view.Name); + Assert.Equal(Description, view.Description); + Assert.Equal(Measure.Name, view.Measure.Name); + Assert.Equal(Mean, view.Aggregation); Assert.Equal(2, view.Columns.Count); - Assert.Equal(FOO, view.Columns[0]); - Assert.Equal(BAR, view.Columns[1]); - + Assert.Equal(Foo, view.Columns[0]); + Assert.Equal(Bar, view.Columns[1]); } [Fact] public void testViewEquals() { - var view1 = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); - var view2 = View.Create(NAME, DESCRIPTION, MEASURE, MEAN, keys); + var view1 = View.Create(Name, Description, Measure, Mean, keys); + var view2 = View.Create(Name, Description, Measure, Mean, keys); Assert.Equal(view1, view2); - var view3 = View.Create(NAME, DESCRIPTION + 2, MEASURE, MEAN, keys); + var view3 = View.Create(Name, Description + 2, Measure, Mean, keys); Assert.NotEqual(view1, view3); Assert.NotEqual(view2, view3); @@ -76,17 +74,17 @@ public void testViewEquals() public void PreventDuplicateColumns() { Assert.Throws(() => View.Create( - NAME, - DESCRIPTION, - MEASURE, - MEAN, + Name, + Description, + Measure, + Mean, new List() { TagKey.Create("duplicate"), TagKey.Create("duplicate") })); } [Fact] public void PreventNullViewName() { - Assert.Throws(() => View.Create(null, DESCRIPTION, MEASURE, MEAN, keys)); + Assert.Throws(() => View.Create(null, Description, Measure, Mean, keys)); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index f641cd00d1f..1116422afac 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -54,15 +54,17 @@ public void CurrentSpan_WhenNoSpanOnActivity() public void WithSpan_CloseDetaches(bool stopSpan, bool recordEvents) { var activity = new Activity("foo").Start(); + if (recordEvents) + { + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } + var span = Span.StartSpan( activity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "foo", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); using (CurrentSpanUtils.WithSpan(span, stopSpan)) @@ -84,15 +86,17 @@ public void WithSpan_CloseDetaches(bool stopSpan, bool recordEvents) public void WithSpan_NotOwningActivity(bool stopSpan, bool recordEvents) { var activity = new Activity("foo").Start(); + if (recordEvents) + { + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } + var span = Span.StartSpan( activity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "foo", SpanKind.Internal, TraceParams.Default, startEndHandler, - null, false); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); @@ -114,27 +118,26 @@ public void WithSpan_NotOwningActivity(bool stopSpan, bool recordEvents) public void WithSpan_NoopOnBrokenScope(bool stopSpan, bool recordEvents) { var parentActivity = new Activity("parent").Start(); + if (recordEvents) + { + parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } + var parentSpan = Span.StartSpan( parentActivity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "parent", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); var parentScope = CurrentSpanUtils.WithSpan(parentSpan, stopSpan); var childActivity = new Activity("child").Start(); var childSpan = Span.StartSpan( childActivity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "child", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); @@ -156,27 +159,27 @@ public void WithSpan_NoopOnBrokenScope(bool stopSpan, bool recordEvents) public void WithSpan_RestoresParentScope(bool stopSpan, bool recordEvents) { var parentActivity = new Activity("parent").Start(); + if (recordEvents) + { + parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } + var parentSpan = Span.StartSpan( parentActivity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "parent", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); + var parentScope = CurrentSpanUtils.WithSpan(parentSpan, stopSpan); var childActivity = new Activity("child").Start(); var childSpan = Span.StartSpan( childActivity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "child", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); @@ -198,14 +201,11 @@ public void WithSpan_SameActivityCreateScopeTwice() var span = Span.StartSpan( activity, Tracestate.Empty, - SpanOptions.RecordEvents, - "foo", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); - using (CurrentSpanUtils.WithSpan(span, true)) + using(CurrentSpanUtils.WithSpan(span, true)) using(CurrentSpanUtils.WithSpan(span, true)) { Assert.Same(activity, Activity.Current); @@ -223,12 +223,9 @@ public void WithSpan_NullActivity() var span = Span.StartSpan( activity, Tracestate.Empty, - SpanOptions.RecordEvents, - "foo", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); activity.Stop(); @@ -250,15 +247,17 @@ public void WithSpan_NullActivity() public void WithSpan_WrongActivity(bool stopSpan, bool recordEvents) { var activity = new Activity("foo").Start(); + if (recordEvents) + { + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } + var span = Span.StartSpan( activity, Tracestate.Empty, - recordEvents ? SpanOptions.RecordEvents : SpanOptions.None, - "foo", SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); Assert.Same(BlankSpan.Instance, CurrentSpanUtils.CurrentSpan); using (CurrentSpanUtils.WithSpan(span, stopSpan)) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs deleted file mode 100644 index 065f9bd1b6f..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/EndSpanOptionsTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// 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.Test -{ - using Xunit; - - public class EndSpanOptionsTest - { - [Fact] - public void EndSpanOptions_DefaultOptions() - { - Assert.Null(EndSpanOptions.Default.Status); - Assert.False(EndSpanOptions.Default.SampleToLocalSpanStore); - } - - [Fact] - public void SetStatus_Ok() - { - var endSpanOptions = EndSpanOptions.Builder().SetStatus(Status.Ok).Build(); - Assert.Equal(Status.Ok, endSpanOptions.Status); - } - - [Fact] - public void SetStatus_Error() - { - var endSpanOptions = - EndSpanOptions.Builder() - .SetStatus(Status.Cancelled.WithDescription("ThisIsAnError")) - .Build(); - Assert.Equal(Status.Cancelled.WithDescription("ThisIsAnError"), endSpanOptions.Status); - } - - [Fact] - public void SetSampleToLocalSpanStore() - { - var endSpanOptions = - EndSpanOptions.Builder().SetSampleToLocalSpanStore(true).Build(); - Assert.True(endSpanOptions.SampleToLocalSpanStore); - } - - [Fact] - public void EndSpanOptions_EqualsAndHashCode() - { - // EqualsTester tester = new EqualsTester(); - // tester.addEqualityGroup( - // EndSpanOptions.builder() - // .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - // .build(), - // EndSpanOptions.builder() - // .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - // .build()); - // tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); - // tester.testEquals(); - } - - [Fact] - public void EndSpanOptions_ToString() - { - var endSpanOptions = - EndSpanOptions.Builder() - .SetStatus(Status.Cancelled.WithDescription("ThisIsAnError")) - .Build(); - Assert.Contains("ThisIsAnError", endSpanOptions.ToString()); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs index 5663b84ba5d..bec26f03711 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs @@ -27,17 +27,5 @@ public void ImplementationOfSpanExporter() { Assert.Equal(SpanExporter.NoopSpanExporter, exportComponent.SpanExporter); } - - [Fact] - public void ImplementationOfActiveSpans() - { - Assert.Equal(RunningSpanStoreBase.NoopRunningSpanStore, exportComponent.RunningSpanStore); - } - - [Fact] - public void ImplementationOfSampledSpanStore() - { - Assert.Equal(SampledSpanStoreBase.NewNoopSampledSpanStore.GetType(), exportComponent.SampledSpanStore.GetType()); - } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs index b8d78b44004..63c524baed4 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs @@ -29,19 +29,5 @@ public void ImplementationOfSpanExporter() { Assert.IsType(exportComponentWithInProcess.SpanExporter); } - - [Fact] - public void ImplementationOfActiveSpans() - { - Assert.IsType(exportComponentWithInProcess.RunningSpanStore); - Assert.IsType(exportComponentWithoutInProcess.RunningSpanStore); - } - - [Fact] - public void ImplementationOfSampledSpanStore() - { - Assert.IsType(exportComponentWithInProcess.SampledSpanStore); - Assert.IsType(exportComponentWithoutInProcess.SampledSpanStore); - } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs deleted file mode 100644 index 3adeb8b9114..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessRunningSpanStoreTest.cs +++ /dev/null @@ -1,148 +0,0 @@ -// -// 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 System; - -namespace OpenTelemetry.Trace.Export.Test -{ - using System.Diagnostics; - using OpenTelemetry.Common; - using OpenTelemetry.Internal; - using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Internal; - using Xunit; - - public class InProcessRunningSpanStoreTest : IDisposable - { - private const string SpanName1 = "MySpanName/1"; - private const string SpanName2 = "MySpanName/2"; - private readonly ISpanExporter sampledSpansServiceExporter = SpanExporter.Create(4, Duration.Create(1, 0)); - private readonly InProcessRunningSpanStore activeSpansExporter = new InProcessRunningSpanStore(); - private readonly StartEndHandler startEndHandler; - private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; - - public InProcessRunningSpanStoreTest() - { - startEndHandler = new StartEndHandler(sampledSpansServiceExporter, activeSpansExporter, null, new SimpleEventQueue()); - } - - private ISpan CreateSpan(string spanName) - { - var activity = new Activity(spanName).Start(); - return Span.StartSpan( - activity, - Tracestate.Empty, - recordSpanOptions, - spanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - null); - } - - [Fact] - public void GetSummary_SpansWithDifferentNames() - { - var span1 = CreateSpan(SpanName1); - var span2 = CreateSpan(SpanName2); - Assert.Equal(2, activeSpansExporter.Summary.PerSpanNameSummary.Count); - Assert.Equal(1, - activeSpansExporter - .Summary - .PerSpanNameSummary[SpanName1] - .NumRunningSpans); - Assert.Equal(1, - activeSpansExporter - .Summary - .PerSpanNameSummary[SpanName2] - .NumRunningSpans); - span1.End(); - Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); - Assert.False(activeSpansExporter.Summary.PerSpanNameSummary.ContainsKey(SpanName1)); - Assert.Equal(1, - activeSpansExporter - .Summary - .PerSpanNameSummary[SpanName2] - .NumRunningSpans); - span2.End(); - Assert.Equal(0, activeSpansExporter.Summary.PerSpanNameSummary.Count); - } - - [Fact] - public void GetSummary_SpansWithSameName() - { - var span1 = CreateSpan(SpanName1); - var span2 = CreateSpan(SpanName1); - var span3 = CreateSpan(SpanName1); - Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); - Assert.Equal(3, - activeSpansExporter - .Summary - .PerSpanNameSummary[SpanName1] - .NumRunningSpans); - span1.End(); - Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); - Assert.Equal(2, - activeSpansExporter - .Summary - .PerSpanNameSummary[SpanName1] - .NumRunningSpans); - span2.End(); - Assert.Equal(1, activeSpansExporter.Summary.PerSpanNameSummary.Count); - Assert.Equal(1, - activeSpansExporter - .Summary - .PerSpanNameSummary[SpanName1] - .NumRunningSpans); - span3.End(); - Assert.Equal(0, activeSpansExporter.Summary.PerSpanNameSummary.Count); - } - - [Fact] - public void GetActiveSpans_SpansWithDifferentNames() - { - var span1 = CreateSpan(SpanName1) as Span; - var span2 = CreateSpan(SpanName2) as Span; - Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SpanName1, 0))); - Assert.Contains(span1.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SpanName1, 2))); - Assert.Contains(span2.ToSpanData(), activeSpansExporter.GetRunningSpans(RunningSpanStoreFilter.Create(SpanName2, 0))); - span1.End(); - span2.End(); - } - - public void Dispose() - { - Activity.Current = null; - } - - // [Fact] - // public void getActiveSpans_SpansWithSameName() - // { - // SpanImpl span1 = createSpan(SPAN_NAME_1); - // SpanImpl span2 = createSpan(SPAN_NAME_1); - // SpanImpl span3 = createSpan(SPAN_NAME_1); - // Assert.Equal(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 0))) - // .containsExactly(span1.toSpanData(), span2.toSpanData(), span3.toSpanData()); - // Assert.Equal(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 2)).size()) - // .isEqualTo(2); - // Assert.Equal(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 2))) - // .containsAnyOf(span1.toSpanData(), span2.toSpanData(), span3.toSpanData()); - // span1.end(); - // span2.end(); - // span3.end(); - // } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs deleted file mode 100644 index 081a79ae13e..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/InProcessSampledSpanStoreTest.cs +++ /dev/null @@ -1,409 +0,0 @@ -// -// 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.Export.Test -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using OpenTelemetry.Common; - using OpenTelemetry.Internal; - using OpenTelemetry.Trace.Config; - using OpenTelemetry.Utils; - using Xunit; - - public class InProcessSampledSpanStoreTest : IDisposable - { - private const string RegisteredSpanName = "MySpanName/1"; - private const string NotRegisteredSpanName = "MySpanName/2"; - - private readonly ActivitySpanId parentSpanId; - private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; - private TimeSpan interval = TimeSpan.FromMilliseconds(0); - private readonly DateTimeOffset startTime = DateTimeOffset.Now; - private readonly Timestamp timestamp; - private readonly Timer timestampConverter; - - private readonly InProcessSampledSpanStore sampleStore = new InProcessSampledSpanStore(new SimpleEventQueue()); - - private readonly IStartEndHandler startEndHandler; - - - public InProcessSampledSpanStoreTest() - { - timestamp = Timestamp.FromDateTimeOffset(startTime); - timestampConverter = Timer.StartNew(startTime, () => interval); - parentSpanId = ActivitySpanId.CreateRandom(); - startEndHandler = new TestStartEndHandler(sampleStore); - sampleStore.RegisterSpanNamesForCollection(new List() { RegisteredSpanName }); - } - - [Fact] - public void AddSpansWithRegisteredNamesInAllLatencyBuckets() - { - AddSpanNameToAllLatencyBuckets(RegisteredSpanName); - var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; - Assert.Equal(1, perSpanNameSummary.Count); - var latencyBucketsSummaries = perSpanNameSummary[RegisteredSpanName].NumbersOfLatencySampledSpans; - Assert.Equal(LatencyBucketBoundaries.Values.Count, latencyBucketsSummaries.Count); - foreach (var it in latencyBucketsSummaries) - { - Assert.Equal(2, it.Value); - } - } - - [Fact] - public void AddSpansWithoutRegisteredNamesInAllLatencyBuckets() - { - AddSpanNameToAllLatencyBuckets(NotRegisteredSpanName); - var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; - Assert.Equal(1, perSpanNameSummary.Count); - Assert.False(perSpanNameSummary.ContainsKey(NotRegisteredSpanName)); - } - - [Fact] - public void RegisterUnregisterAndListSpanNames() - { - Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); - - sampleStore.RegisterSpanNamesForCollection(new List() { NotRegisteredSpanName }); - - Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Contains(NotRegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Equal(2, sampleStore.RegisteredSpanNamesForCollection.Count); - - sampleStore.UnregisterSpanNamesForCollection(new List() { NotRegisteredSpanName }); - - Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); - } - - [Fact] - public void RegisterSpanNamesViaSpanBuilderOption() - { - Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Equal(1, sampleStore.RegisteredSpanNamesForCollection.Count); - - var span = CreateSampledSpan(NotRegisteredSpanName); - span.IsSampleToLocalSpanStore = true; - span.End(); - - Assert.Contains(RegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Contains(NotRegisteredSpanName, sampleStore.RegisteredSpanNamesForCollection); - Assert.Equal(2, sampleStore.RegisteredSpanNamesForCollection.Count); - - } - - [Fact] - public void AddSpansWithRegisteredNamesInAllErrorBuckets() - { - AddSpanNameToAllErrorBuckets(RegisteredSpanName); - var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; - Assert.Equal(1, perSpanNameSummary.Count); - var errorBucketsSummaries = perSpanNameSummary[RegisteredSpanName].NumbersOfErrorSampledSpans; - var ccCount = Enum.GetValues(typeof(CanonicalCode)).Cast().Count(); - Assert.Equal(ccCount - 1, errorBucketsSummaries.Count); - foreach (var it in errorBucketsSummaries) - { - Assert.Equal(2, it.Value); - } - } - - [Fact] - public void AddSpansWithoutRegisteredNamesInAllErrorBuckets() - { - AddSpanNameToAllErrorBuckets(NotRegisteredSpanName); - var perSpanNameSummary = sampleStore.Summary.PerSpanNameSummary; - Assert.Equal(1, perSpanNameSummary.Count); - Assert.False(perSpanNameSummary.ContainsKey(NotRegisteredSpanName)); - } - - [Fact] - public void GetErrorSampledSpans() - { - var span = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - span.Status = Status.Cancelled; - span.End(); - - var samples = - sampleStore.GetErrorSampledSpans( - SampledSpanStoreErrorFilter.Create(RegisteredSpanName, CanonicalCode.Cancelled, 0)); - Assert.Single(samples); - Assert.Contains(span.ToSpanData(), samples); - } - - [Fact] - public void GetErrorSampledSpans_MaxSpansToReturn() - { - var span1 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - span1.Status = Status.Cancelled; - span1.End(); - - // Advance time to allow other spans to be sampled. - interval += TimeSpan.FromSeconds(5); - var span2 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - span2.Status = Status.Cancelled; - span2.End(); - - var samples = - sampleStore.GetErrorSampledSpans( - SampledSpanStoreErrorFilter.Create(RegisteredSpanName, CanonicalCode.Cancelled, 1)); - Assert.Single(samples); - // No order guaranteed so one of the spans should be in the list. - Assert.True(samples.Contains(span1.ToSpanData()) || samples.Contains(span2.ToSpanData())); - } - - [Fact] - public void GetErrorSampledSpans_NullCode() - { - var span1 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - - span1.Status = Status.Cancelled;; - span1.End(); - - var span2 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - span2.Status = Status.Unknown; - span2.End(); - - var samples = - sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(RegisteredSpanName, null, 0)); - Assert.Equal(2, samples.Count()); - Assert.Contains(span1.ToSpanData(), samples); - Assert.Contains(span2.ToSpanData(), samples); - } - - [Fact] - public void GetErrorSampledSpans_NullCode_MaxSpansToReturn() - { - var span1 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - span1.Status = Status.Cancelled; - span1.End(); - var span2 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(10); - span2.Status = Status.Unknown; - span2.End(); - - var samples = - sampleStore.GetErrorSampledSpans(SampledSpanStoreErrorFilter.Create(RegisteredSpanName, null, 1)); - Assert.Single(samples); - Assert.True(samples.Contains(span1.ToSpanData()) || samples.Contains(span2.ToSpanData())); - } - - [Fact] - public void GetLatencySampledSpans() - { - var span = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(200); // 20 microseconds - span.End(); - var samples = - sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create( - RegisteredSpanName, - TimeSpan.FromTicks(150), - TimeSpan.FromTicks(250), - 0)); - Assert.Single(samples); - Assert.Contains(span.ToSpanData(), samples); - } - - [Fact] - public void GetLatencySampledSpans_ExclusiveUpperBound() - { - var span = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(200); // 20 microseconds - span.End(); - var samples = - sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create( - RegisteredSpanName, - TimeSpan.FromTicks(150), - TimeSpan.FromTicks(200), - 0)); - Assert.Empty(samples); - } - - [Fact] - public void GetLatencySampledSpans_InclusiveLowerBound() - { - var span = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(200); // 20 microseconds - span.End(); - var samples = - sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create( - RegisteredSpanName, - TimeSpan.FromTicks(150), - TimeSpan.FromTicks(250), - 0)); - Assert.Single(samples); - Assert.Contains(span.ToSpanData(), samples); - } - - [Fact] - public void GetLatencySampledSpans_QueryBetweenMultipleBuckets() - { - var span1 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(200); // 20 microseconds - span1.End(); - // Advance time to allow other spans to be sampled. - interval += TimeSpan.FromSeconds(5); - var span2 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(2000); // 200 microseconds - span2.End(); - var samples = - sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create( - RegisteredSpanName, - TimeSpan.FromTicks(150), - TimeSpan.FromTicks(2500), - 0)); - Assert.Equal(2, samples.Count()); - Assert.Contains(span1.ToSpanData(), samples); - Assert.Contains(span2.ToSpanData(), samples); - } - - [Fact] - public void GetLatencySampledSpans_MaxSpansToReturn() - { - var span1 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(200); // 20 microseconds - span1.End(); - // Advance time to allow other spans to be sampled. - interval += TimeSpan.FromSeconds(5); - var span2 = CreateSampledSpan(RegisteredSpanName) as Span; - interval += TimeSpan.FromTicks(2000); // 200 microseconds - span2.End(); - var samples = - sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create( - RegisteredSpanName, - TimeSpan.FromTicks(150), - TimeSpan.FromTicks(2500), - 1)); - Assert.Single(samples); - Assert.Contains(span1.ToSpanData(), samples); - } - - [Fact] - public void IgnoreNegativeSpanLatency() - { - var span = CreateSampledSpan(RegisteredSpanName) as Span; - interval -= TimeSpan.FromTicks(200); // 20 microseconds - span.End(); - var samples = - sampleStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create(RegisteredSpanName, TimeSpan.Zero, TimeSpan.MaxValue, 0)); - Assert.Empty(samples); - } - - private Span CreateSampledSpan(string spanName) - { - var activity = new Activity(spanName).Start(); - activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; - - return (Span)Span.StartSpan( - activity, - Tracestate.Empty, - recordSpanOptions, - spanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - timestampConverter); - } - - private Span CreateNotSampledSpan(string spanName) - { - var activity = new Activity(spanName).Start(); - activity.ActivityTraceFlags = ActivityTraceFlags.None; - - return (Span)Span.StartSpan( - activity, - Tracestate.Empty, - recordSpanOptions, - spanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - timestampConverter); - } - - private void AddSpanNameToAllLatencyBuckets(string spanName) - { - foreach (LatencyBucketBoundaries boundaries in LatencyBucketBoundaries.Values) - { - ISpan sampledSpan = CreateSampledSpan(spanName); - ISpan notSampledSpan = CreateNotSampledSpan(spanName); - interval += boundaries.LatencyLower; - sampledSpan.End(); - notSampledSpan.End(); - } - } - - private void AddSpanNameToAllErrorBuckets(String spanName) - { - foreach (var code in Enum.GetValues(typeof(CanonicalCode)).Cast()) - { - if (code != CanonicalCode.Ok) - { - var sampledSpan = CreateSampledSpan(spanName); - var notSampledSpan = CreateNotSampledSpan(spanName); - interval += TimeSpan.FromTicks(10); - - sampledSpan.Status = code.ToStatus(); - notSampledSpan.Status = code.ToStatus(); - sampledSpan.End(); - notSampledSpan.End(); - sampledSpan.Activity.Stop(); - notSampledSpan.Activity.Stop(); - } - } - } - - class TestStartEndHandler : IStartEndHandler - { - readonly InProcessSampledSpanStore sampleStore; - - public TestStartEndHandler(InProcessSampledSpanStore store) - { - sampleStore = store; - } - - public void OnStart(ISpan span) - { - // Do nothing. - } - - public void OnEnd(ISpan span) - { - sampleStore.ConsiderForSampling(span); - } - } - - public void Dispose() - { - Activity.Current = null; - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs deleted file mode 100644 index 4ea728827ec..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopRunningSpanStoreTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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.Export.Test -{ - using System; - using Xunit; - - public class NoopRunningSpanStoreTest - { - private readonly IRunningSpanStore runningSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).RunningSpanStore; - - [Fact] - public void NoopRunningSpanStore_GetSummary() - { - var summary = runningSpanStore.Summary; - Assert.Empty(summary.PerSpanNameSummary); - } - - [Fact] - public void NoopRunningSpanStore_GetRunningSpans_DisallowsNull() - { - Assert.Throws(() => runningSpanStore.GetRunningSpans(null)); - } - - [Fact] - public void NoopRunningSpanStore_GetRunningSpans() - { - var runningSpans = runningSpanStore.GetRunningSpans(RunningSpanStoreFilter.Create("TestSpan", 0)); - Assert.Empty(runningSpans); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs deleted file mode 100644 index f09b089503c..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/NoopSampledSpanStoreTest.cs +++ /dev/null @@ -1,93 +0,0 @@ -// -// 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.Export.Test -{ - using System; - using System.Collections.Generic; - using Xunit; - - public class NoopSampledSpanStoreTest - { - // @Rule public final ExpectedException thrown = ExpectedException.none(); - private static readonly ISampledPerSpanNameSummary EMPTY_PER_SPAN_NAME_SUMMARY = - SampledPerSpanNameSummary.Create(new Dictionary(), new Dictionary()); - - [Fact] - public void NoopSampledSpanStore_RegisterUnregisterAndGetSummary() - { - // should return empty before register - var sampledSpanStore = - ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; - var summary = sampledSpanStore.Summary; - Assert.Empty(summary.PerSpanNameSummary); - - // should return non-empty summaries with zero latency/error sampled spans after register - sampledSpanStore.RegisterSpanNamesForCollection( - new List() { "TestSpan1", "TestSpan2", "TestSpan3" }); - summary = sampledSpanStore.Summary; - Assert.Equal(3, summary.PerSpanNameSummary.Count); - Assert.Contains(summary.PerSpanNameSummary, (item) => - { - return (item.Key == "TestSpan1" || item.Key == "TestSpan2" || item.Key == "TestSpan3") && - item.Value.Equals(EMPTY_PER_SPAN_NAME_SUMMARY); - }); - - // should unregister specific spanNames - sampledSpanStore.UnregisterSpanNamesForCollection(new List() { "TestSpan1", "TestSpan3" }); - summary = sampledSpanStore.Summary; - Assert.Equal(1, summary.PerSpanNameSummary.Count); - Assert.Contains(summary.PerSpanNameSummary, (item) => - { - return (item.Key == "TestSpan2") && item.Value.Equals(EMPTY_PER_SPAN_NAME_SUMMARY); - }); - - } - - [Fact] - public void NoopSampledSpanStore_GetLatencySampledSpans() - { - var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; - var latencySampledSpans = - sampledSpanStore.GetLatencySampledSpans( - SampledSpanStoreLatencyFilter.Create("TestLatencyFilter", TimeSpan.Zero, TimeSpan.Zero, 0)); - Assert.Empty(latencySampledSpans); - } - - [Fact] - public void NoopSampledSpanStore_GetErrorSampledSpans() - { - var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; - var errorSampledSpans = - sampledSpanStore.GetErrorSampledSpans( - SampledSpanStoreErrorFilter.Create("TestErrorFilter", null, 0)); - Assert.Empty(errorSampledSpans); - } - - [Fact] - public void NoopSampledSpanStore_GetRegisteredSpanNamesForCollection() - { - var sampledSpanStore = ((NoopExportComponent)ExportComponent.NewNoopExportComponent).SampledSpanStore; - sampledSpanStore.RegisterSpanNamesForCollection(new List() { "TestSpan3", "TestSpan4" }); - var registeredSpanNames = sampledSpanStore.RegisteredSpanNamesForCollection; - Assert.Equal(2, registeredSpanNames.Count); - Assert.Contains(registeredSpanNames, (item) => - { - return (item == "TestSpan3" || item == "TestSpan4"); - }); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs index 1c7b1899981..ef4a65ede37 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanDataTest.cs @@ -18,11 +18,11 @@ namespace OpenTelemetry.Trace.Export.Test { + using System; using System.Collections.Generic; using System.Diagnostics; - using OpenTelemetry.Common; + using OpenTelemetry.Abstractions.Utils; using OpenTelemetry.Resources; - using OpenTelemetry.Trace.Internal; using Xunit; public class SpanDataTest @@ -31,11 +31,11 @@ public class SpanDataTest private const string EVENT_TEXT = "MyEventText"; private const SpanKind SPAN_KIND = SpanKind.Client; private const int CHILD_SPAN_COUNT = 13; - private static readonly Timestamp startTimestamp = Timestamp.Create(123, 456); - private static readonly Timestamp eventTimestamp1 = Timestamp.Create(123, 457); - private static readonly Timestamp eventTimestamp2 = Timestamp.Create(123, 458); - private static readonly Timestamp eventTimestamp3 = Timestamp.Create(123, 459); - private static readonly Timestamp endTimestamp = Timestamp.Create(123, 460); + private static readonly DateTime startTimestamp = PreciseTimestamp.GetUtcNow().AddSeconds(-1); + private static readonly DateTime eventTimestamp1 = startTimestamp.AddMilliseconds(1); + private static readonly DateTime eventTimestamp2 = startTimestamp.AddMilliseconds(2); + private static readonly DateTime eventTimestamp3 = startTimestamp.AddMilliseconds(3); + private static readonly DateTime endTimestamp = startTimestamp.AddMilliseconds(4); private static readonly IEvent spanEvent = Event.Create(EVENT_TEXT); private static readonly Status status = Status.DeadlineExceeded.WithDescription("TooSlow"); private readonly SpanContext spanContext; @@ -112,7 +112,7 @@ public void SpanData_RootActiveSpan() null, null, SPAN_KIND, - null); + default); Assert.Equal(spanContext, spanData.Context); Assert.True(spanData.ParentSpanId == default); Assert.Equal(resource, spanData.Resource); @@ -123,7 +123,7 @@ public void SpanData_RootActiveSpan() Assert.Equal(links, spanData.Links); Assert.Null(spanData.ChildSpanCount); Assert.Null(spanData.Status); - Assert.Null(spanData.EndTimestamp); + Assert.Equal(default, spanData.EndTimestamp); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index 3f640d2e3c5..86549fb5c1a 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -23,7 +23,6 @@ namespace OpenTelemetry.Trace.Export.Test using System.Threading; using System.Threading.Tasks; using Moq; - using OpenTelemetry.Common; using OpenTelemetry.Internal; using OpenTelemetry.Testing.Export; using OpenTelemetry.Trace.Config; @@ -34,56 +33,48 @@ public class SpanExporterTest : IDisposable { private const string SpanName1 = "MySpanName/1"; private const string SpanName2 = "MySpanName/2"; - private readonly Activity sampledActivity; - private readonly Activity notSampledActivity; - private readonly ISpanExporter spanExporter = SpanExporter.Create(4, Duration.Create(1, 0)); - private readonly IRunningSpanStore runningSpanStore = new InProcessRunningSpanStore(); + private readonly ISpanExporter spanExporter = SpanExporter.Create(4, TimeSpan.FromSeconds(1)); private readonly IStartEndHandler startEndHandler; - private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; private readonly TestHandler serviceHandler = new TestHandler(); private readonly IHandler mockServiceHandler = Mock.Of(); public SpanExporterTest() { - sampledActivity = new Activity("foo"); - sampledActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; - - notSampledActivity = new Activity("foo"); - startEndHandler = new StartEndHandler(spanExporter, runningSpanStore, null, new SimpleEventQueue()); + // TODO + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + Activity.ForceDefaultIdFormat = true; + startEndHandler = new StartEndHandler(spanExporter, new SimpleEventQueue()); spanExporter.RegisterHandler("test.service", serviceHandler); } private Span CreateSampledEndedSpan(string spanName) { + var sampledActivity = new Activity(spanName); + sampledActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; sampledActivity.Start(); var span = Span.StartSpan( sampledActivity, Tracestate.Empty, - recordSpanOptions, - spanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); span.End(); return span as Span; } private Span CreateNotSampledEndedSpan(string spanName) { + var notSampledActivity = new Activity(spanName); notSampledActivity.Start(); var span = Span.StartSpan( notSampledActivity, Tracestate.Empty, - recordSpanOptions, - spanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - null); + startEndHandler); span.End(); return span as Span; } @@ -178,24 +169,23 @@ public void ExportNotSampledSpans() // sampled span is not exported by creating and ending a sampled span after a non sampled span // and checking that the first exported span is the sampled span (the non sampled did not get // exported). - var exported = serviceHandler.WaitForExport(1); + var exported = serviceHandler.WaitForExport(1).ToArray(); // Need to check this because otherwise the variable span1 is unused, other option is to not // have a span1 variable. Assert.Single(exported); - Assert.DoesNotContain(span1.ToSpanData(), exported); Assert.Contains(span2.ToSpanData(), exported); } [Fact] public async Task ExportAsyncCallsAllHandlers() { - var exporter = SpanExporter.Create(4, Duration.Create(1, 0)); + var exporter = SpanExporter.Create(4, TimeSpan.FromSeconds(1)); var handler1 = new Mock(); exporter.RegisterHandler("first", handler1.Object); - var span1 = CreateNotSampledEndedSpan(SpanName1).ToSpanData(); + var span1 = CreateSampledEndedSpan(SpanName1).ToSpanData(); await exporter.ExportAsync(span1, CancellationToken.None); @@ -203,8 +193,7 @@ public async Task ExportAsyncCallsAllHandlers() var args = (IEnumerable)handler1.Invocations.First().Arguments.First(); handler1.Verify(c => c.ExportAsync(It.Is>( - (x) => x.Where((s) => s == span1).Count() > 0 && - x.Count() == 1))); + (x) => x.Any(s => s == span1) && x.Count() == 1))); } public void Dispose() diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs deleted file mode 100644 index 2a401705bd5..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Internal/ConcurrentIntrusiveListTest.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// 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.Internal.Test -{ - using System; - using OpenTelemetry.Utils; - using Xunit; - - public class ConcurrentIntrusiveListTest - { - private readonly ConcurrentIntrusiveList intrusiveList = new ConcurrentIntrusiveList(); - - [Fact] - public void EmptyList() - { - Assert.Equal(0, intrusiveList.Count); - Assert.Empty(intrusiveList.Copy()); - } - - [Fact] - public void AddRemoveAdd_SameElement() - { - var element = new FakeElement(); - intrusiveList.AddElement(element); - Assert.Equal(1, intrusiveList.Count); - intrusiveList.RemoveElement(element); - Assert.Equal(0, intrusiveList.Count); - intrusiveList.AddElement(element); - Assert.Equal(1, intrusiveList.Count); - } - - [Fact] - public void addAndRemoveElements() - { - var element1 = new FakeElement(); - var element2 = new FakeElement(); - var element3 = new FakeElement(); - intrusiveList.AddElement(element1); - intrusiveList.AddElement(element2); - intrusiveList.AddElement(element3); - Assert.Equal(3, intrusiveList.Count); - var copy = intrusiveList.Copy(); - Assert.Equal(element3, copy[0]); - Assert.Equal(element2, copy[1]); - Assert.Equal(element1, copy[2]); - // Remove element from the middle of the list. - intrusiveList.RemoveElement(element2); - Assert.Equal(2, intrusiveList.Count); - copy = intrusiveList.Copy(); - Assert.Equal(element3, copy[0]); - Assert.Equal(element1, copy[1]); - // Remove element from the tail of the list. - intrusiveList.RemoveElement(element1); - Assert.Equal(1, intrusiveList.Count); - copy = intrusiveList.Copy(); - Assert.Equal(element3, copy[0]); - - intrusiveList.AddElement(element1); - Assert.Equal(2, intrusiveList.Count); - copy = intrusiveList.Copy(); - Assert.Equal(element1, copy[0]); - Assert.Equal(element3, copy[1]); - // Remove element from the head of the list when there are other elements after. - intrusiveList.RemoveElement(element1); - Assert.Equal(1, intrusiveList.Count); - copy = intrusiveList.Copy(); - Assert.Equal(element3, copy[0]); - // Remove element from the head of the list when no more other elements in the list. - intrusiveList.RemoveElement(element3); - Assert.Equal(0, intrusiveList.Count); - Assert.Empty(intrusiveList.Copy()); - } - - [Fact] - public void AddAlreadyAddedElement() - { - var element = new FakeElement(); - intrusiveList.AddElement(element); - - Assert.Throws(() => intrusiveList.AddElement(element)); - } - - [Fact] - public void removeNotAddedElement() - { - var element = new FakeElement(); - Assert.Throws(() => intrusiveList.RemoveElement(element)); - } - - - private sealed class FakeElement : IElement - { - public FakeElement Next { get; set; } - - public FakeElement Previous { get; set; } - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index 839fe2a4524..f157c7ed31f 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -36,6 +36,7 @@ public LinkTest() Activity.ForceDefaultIdFormat = true; spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); ; + attributesMap.Add("MyAttributeKey0", "MyStringAttribute"); attributesMap.Add("MyAttributeKey1", 10L); attributesMap.Add("MyAttributeKey2", true); @@ -82,11 +83,11 @@ public void Link_ToString() var link = Link.FromSpanContext(spanContext, attributesMap); Assert.Contains(spanContext.TraceId.ToString(), link.ToString()); Assert.Contains(spanContext.SpanId.ToString(), link.ToString()); - Assert.Contains(string.Join(" ", attributesMap.Select(kvp => $"{kvp.Key}={kvp.Value}")), link.ToString()); + Assert.Contains(string.Join(", ", attributesMap.Select(kvp => $"{kvp.Key}={kvp.Value}")), link.ToString()); link = Link.FromSpanContext(spanContext, attributesMap); Assert.Contains(spanContext.TraceId.ToString(), link.ToString()); Assert.Contains(spanContext.SpanId.ToString(), spanContext.SpanId.ToString()); - Assert.Contains(string.Join(" ", attributesMap.Select(kvp => $"{kvp.Key}={kvp.Value}")), link.ToString()); + Assert.Contains(string.Join(", ", attributesMap.Select(kvp => $"{kvp.Key}={kvp.Value}")), link.ToString()); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs index 57f1e69fbb7..6494fbc6164 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/NoopTracerTests.cs @@ -19,7 +19,6 @@ namespace OpenTelemetry.Tests.Impl.Trace { using System; - using OpenTelemetry.Common; using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace; using Xunit; @@ -59,7 +58,7 @@ public void NoopTracer_RecordData() Assert.Throws(() => NoopTracer.Instance.RecordSpanData(null)); // does not throw - NoopTracer.Instance.RecordSpanData(SpanData.Create(SpanContext.Blank, default, Resource.Empty, "foo", Timestamp.Zero, null, null, null, null, Status.Ok, SpanKind.Internal, Timestamp.Zero)); + NoopTracer.Instance.RecordSpanData(SpanData.Create(SpanContext.Blank, default, Resource.Empty, "foo", default, null, null, null, null, Status.Ok, SpanKind.Internal, default)); } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index dccf057ee96..f34ea73894b 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Trace.Test using System.Globalization; using System.Linq; using Moq; - using OpenTelemetry.Common; + using OpenTelemetry.Abstractions.Utils; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Internal; using OpenTelemetry.Trace.Sampler; @@ -68,9 +68,7 @@ public void StartSpanNullParent() Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); var spanData = ((Span)span).ToSpanData(); Assert.True(spanData.ParentSpanId == default); - Assert.InRange(spanData.StartTimestamp, - Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(-1, 0)), - Timestamp.FromDateTimeOffset(DateTimeOffset.Now).AddDuration(Duration.Create(1, 0))); + Assert.InRange(spanData.StartTimestamp, PreciseTimestamp.GetUtcNow().AddSeconds(-1), PreciseTimestamp.GetUtcNow().AddSeconds(1)); Assert.Equal(SpanName, spanData.Name); var activity = ((Span)span).Activity; @@ -268,7 +266,6 @@ public void StartChildSpan() Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.Equal(rootSpan.Context.SpanId, ((Span)childSpan).ToSpanData().ParentSpanId); - Assert.Equal(((Span)rootSpan).TimestampConverter, ((Span)childSpan).TimestampConverter); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index 7c22a723083..fc3a1a93254 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -22,9 +22,9 @@ namespace OpenTelemetry.Trace.Test using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using System.Threading.Tasks; using Moq; - using OpenTelemetry.Common; - using OpenTelemetry.Internal; + using OpenTelemetry.Abstractions.Utils; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; using Xunit; @@ -33,29 +33,20 @@ public class SpanTest : IDisposable { private const string SpanName = "MySpanName"; private const string EventDescription = "MyEvent"; - - private TimeSpan interval = TimeSpan.FromMilliseconds(0); - private readonly DateTimeOffset startTime = DateTimeOffset.Now; - private readonly Timestamp timestamp; - private readonly Timer timestampConverter; - private readonly SpanOptions noRecordSpanOptions = SpanOptions.None; - private readonly SpanOptions recordSpanOptions = SpanOptions.RecordEvents; + private readonly IDictionary attributes = new Dictionary(); private readonly List> expectedAttributes; private readonly IStartEndHandler startEndHandler = Mock.Of(); public SpanTest() { - timestamp = Timestamp.FromDateTimeOffset(startTime); - timestampConverter = Timer.StartNew(startTime, () => interval); - attributes.Add("MyStringAttributeKey", "MyStringAttributeValue"); attributes.Add("MyLongAttributeKey", 123L); attributes.Add("MyBooleanAttributeKey", false); expectedAttributes = new List>(attributes) - { - new KeyValuePair("MySingleStringAttributeKey", "MySingleStringAttributeValue") - }; + { + new KeyValuePair("MySingleStringAttributeKey", "MySingleStringAttributeValue") + }; } [Fact] @@ -65,17 +56,15 @@ public void ToSpanData_NoRecordEvents() activityLink.Stop(); var activity = new Activity(SpanName).Start(); + Assert.False(activity.Recorded); var span = Span.StartSpan( activity, Tracestate.Empty, - noRecordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); // Check that adding trace events after Span#End() does not throw any exception. foreach (var attribute in attributes) { @@ -96,17 +85,15 @@ public void GetSpanContextFromActivity() var tracestate = Tracestate.Builder.Set("k1", "v1").Build(); var activity = new Activity(SpanName).Start(); activity.TraceStateString = tracestate.ToString(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var span = Span.StartSpan( activity, tracestate, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); Assert.NotNull(span.Context); Assert.Equal(activity.TraceId, span.Context.TraceId); Assert.Equal(activity.SpanId, span.Context.SpanId); @@ -127,12 +114,9 @@ public void GetSpanContextFromActivityRecordedWithParent() Span.StartSpan( activity, tracestate, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); Assert.NotNull(span.Context); Assert.Equal(activity.TraceId, span.Context.TraceId); Assert.Equal(activity.SpanId, span.Context.SpanId); @@ -148,17 +132,17 @@ public void NoEventsRecordedAfterEnd() activityLink.Stop(); var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + var spanStartTime = PreciseTimestamp.GetUtcNow(); var span = Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); + var spaEndTime = PreciseTimestamp.GetUtcNow(); span.End(); // Check that adding trace events after Span#End() does not throw any exception and are not // recorded. @@ -170,39 +154,39 @@ public void NoEventsRecordedAfterEnd() span.SetAttribute( "MySingleStringAttributeKey", "MySingleStringAttributeValue"); + span.AddEvent(Event.Create(EventDescription)); span.AddEvent(EventDescription, attributes); span.AddLink(Link.FromActivity(activityLink)); var spanData = ((Span)span).ToSpanData(); - Assert.Equal(timestamp, spanData.StartTimestamp); + + AssertApproxSameTimestamp(spanData.StartTimestamp, spanStartTime); Assert.Empty(spanData.Attributes.AttributeMap); Assert.Empty(spanData.Events.Events); Assert.Empty(spanData.Links.Links); Assert.Equal(Status.Ok, spanData.Status); - Assert.Equal(timestamp, spanData.EndTimestamp); + AssertApproxSameTimestamp(spaEndTime, spanData.EndTimestamp); } [Fact] - public void ToSpanData_ActiveSpan() + public async Task ToSpanData_ActiveSpan() { - var activityLink = new Activity(SpanName); activityLink.Stop(); var activity = new Activity(SpanName) .SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()) .Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + var spanStartTime = PreciseTimestamp.GetUtcNow(); var span = Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); span.SetAttribute( "MySingleStringAttributeKey", @@ -212,12 +196,13 @@ public void ToSpanData_ActiveSpan() span.SetAttribute(attribute); } - interval = TimeSpan.FromMilliseconds(100); + var firstEventTime = PreciseTimestamp.GetUtcNow(); span.AddEvent(Event.Create(EventDescription)); - interval = TimeSpan.FromMilliseconds(200); + await Task.Delay(TimeSpan.FromMilliseconds(100)); + + var secondEventTime = PreciseTimestamp.GetUtcNow(); span.AddEvent(EventDescription, attributes); - interval = TimeSpan.FromMilliseconds(300); - interval = TimeSpan.FromMilliseconds(400); + var link = Link.FromActivity(activityLink); span.AddLink(link); var spanData = ((Span)span).ToSpanData(); @@ -233,25 +218,28 @@ public void ToSpanData_ActiveSpan() spanData.Attributes.AssertAreSame(expectedAttributes); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), - spanData.Events.Events.ToList()[0].Timestamp); + + AssertApproxSameTimestamp(spanData.Events.Events.ToList()[0].Timestamp, firstEventTime); + AssertApproxSameTimestamp(spanData.Events.Events.ToList()[1].Timestamp, secondEventTime); + Assert.Equal(Event.Create(EventDescription), spanData.Events.Events.ToList()[0].Event); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), - spanData.Events.Events.ToList()[1].Timestamp); + Assert.Equal(Event.Create(EventDescription, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); Assert.Equal(link, spanData.Links.Links.First()); - Assert.Equal(timestamp, spanData.StartTimestamp); + + AssertApproxSameTimestamp(spanStartTime, spanData.StartTimestamp); + Assert.Null(spanData.Status); - Assert.Null(spanData.EndTimestamp); + Assert.Equal(default, spanData.EndTimestamp); var startEndMock = Mock.Get(startEndHandler); startEndMock.Verify(s => s.OnStart(span), Times.Once); } [Fact] - public void GoSpanData_EndedSpan() + public async Task GoSpanData_EndedSpan() { var activityLink = new Activity(SpanName).Start(); activityLink.Stop(); @@ -260,16 +248,15 @@ public void GoSpanData_EndedSpan() .SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()) .Start(); + var spanStartTime = PreciseTimestamp.GetUtcNow(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var span = (Span)Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); span.SetAttribute( "MySingleStringAttributeKey", @@ -279,15 +266,19 @@ public void GoSpanData_EndedSpan() span.SetAttribute(attribute); } - interval = TimeSpan.FromMilliseconds(100); + await Task.Delay(TimeSpan.FromMilliseconds(100)); + var firstEventTime = PreciseTimestamp.GetUtcNow(); span.AddEvent(Event.Create(EventDescription)); - interval = TimeSpan.FromMilliseconds(200); + + await Task.Delay(TimeSpan.FromMilliseconds(100)); + var secondEventTime = PreciseTimestamp.GetUtcNow(); span.AddEvent(EventDescription, attributes); - interval = TimeSpan.FromMilliseconds(300); + var link = Link.FromActivity(activityLink); span.AddLink(link); - interval = TimeSpan.FromMilliseconds(400); span.Status = Status.Cancelled; + + var spanEndTime = PreciseTimestamp.GetUtcNow(); span.End(); var spanData = ((Span)span).ToSpanData(); @@ -303,18 +294,17 @@ public void GoSpanData_EndedSpan() spanData.Attributes.AssertAreSame(expectedAttributes); Assert.Equal(0, spanData.Events.DroppedEventsCount); Assert.Equal(2, spanData.Events.Events.Count()); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100))), - spanData.Events.Events.ToList()[0].Timestamp); + + AssertApproxSameTimestamp(spanData.Events.Events.ToList()[0].Timestamp, firstEventTime); + AssertApproxSameTimestamp(spanData.Events.Events.ToList()[1].Timestamp, secondEventTime); + Assert.Equal(Event.Create(EventDescription), spanData.Events.Events.ToList()[0].Event); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(200))), - spanData.Events.Events.ToList()[1].Timestamp); - Assert.Equal(Event.Create(EventDescription, attributes), spanData.Events.Events.ToList()[1].Event); Assert.Equal(0, spanData.Links.DroppedLinksCount); Assert.Single(spanData.Links.Links); Assert.Equal(link, spanData.Links.Links.First()); - Assert.Equal(timestamp, spanData.StartTimestamp); + AssertApproxSameTimestamp(spanData.StartTimestamp, spanStartTime); Assert.Equal(Status.Cancelled, spanData.Status); - Assert.Equal(timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(400))), spanData.EndTimestamp); + AssertApproxSameTimestamp(spanEndTime, spanData.EndTimestamp); var startEndMock = Mock.Get(startEndHandler); startEndMock.Verify(s => s.OnStart(span), Times.Once); @@ -325,18 +315,16 @@ public void GoSpanData_EndedSpan() public void Status_ViaSetStatus() { var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var span = (Span)Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); - interval = TimeSpan.FromMilliseconds(100); + startEndHandler); + Assert.Equal(Status.Ok, span.Status); ((Span)span).Status = Status.Cancelled; Assert.Equal(Status.Cancelled, span.Status); @@ -351,18 +339,16 @@ public void Status_ViaSetStatus() public void status_ViaEndSpanOptions() { var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var span = (Span)Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); - interval = TimeSpan.FromMilliseconds(100); + startEndHandler); + Assert.Equal(Status.Ok, span.Status); ((Span)span).Status = Status.Cancelled; Assert.Equal(Status.Cancelled, span.Status); @@ -378,6 +364,7 @@ public void status_ViaEndSpanOptions() public void DroppingAttributes() { var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var maxNumberOfAttributes = 8; var traceParams = @@ -386,15 +373,12 @@ public void DroppingAttributes() Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, traceParams, - startEndHandler, - timestampConverter); + startEndHandler); for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { - IDictionary attributes = new Dictionary(); + IDictionary attributes = new Dictionary(); attributes.Add("MyStringAttributeKey" + i, i); foreach (var attribute in attributes) { @@ -433,6 +417,7 @@ public void DroppingAttributes() public void DroppingAndAddingAttributes() { var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var maxNumberOfAttributes = 8; var traceParams = @@ -441,12 +426,9 @@ public void DroppingAndAddingAttributes() Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, traceParams, - startEndHandler, - timestampConverter); + startEndHandler); for (var i = 0; i < 2 * maxNumberOfAttributes; i++) { IDictionary attributes = new Dictionary(); @@ -503,9 +485,10 @@ public void DroppingAndAddingAttributes() } [Fact] - public void DroppingEvents() + public async Task DroppingEvents() { var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var maxNumberOfEvents = 8; var traceParams = @@ -514,46 +497,35 @@ public void DroppingEvents() Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, traceParams, - startEndHandler, - timestampConverter); + startEndHandler); var testEvent = Event.Create(EventDescription); - var i = 0; - for (i = 0; i < 2 * maxNumberOfEvents; i++) + + var eventTimestamps = new DateTime[2 * maxNumberOfEvents]; + + for (int i = 0; i < 2 * maxNumberOfEvents; i++) { + eventTimestamps[i] = PreciseTimestamp.GetUtcNow(); span.AddEvent(testEvent); - interval += TimeSpan.FromMilliseconds(100); + await Task.Delay(10); } var spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); Assert.Equal(maxNumberOfEvents, spanData.Events.Events.Count()); - i = 0; - foreach (var te in spanData.Events.Events) + + var events = spanData.Events.Events.ToArray(); + + for (int i = 0; i < maxNumberOfEvents; i++) { - Assert.Equal( - timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), - te.Timestamp); - Assert.Equal(testEvent, te.Event); - i++; + AssertApproxSameTimestamp(events[i].Timestamp, eventTimestamps[i + maxNumberOfEvents]); } span.End(); spanData = ((Span)span).ToSpanData(); Assert.Equal(maxNumberOfEvents, spanData.Events.DroppedEventsCount); Assert.Equal(maxNumberOfEvents, spanData.Events.Events.Count()); - i = 0; - foreach (var te in spanData.Events.Events) - { - Assert.Equal( - timestamp.AddDuration(Duration.Create(TimeSpan.FromMilliseconds(100 * (maxNumberOfEvents + i)))), - te.Timestamp); - Assert.Equal(testEvent, te.Event); - i++; - } } [Fact] @@ -563,6 +535,7 @@ public void DroppingLinks() activityLink.Stop(); var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var maxNumberOfLinks = 8; var traceParams = @@ -570,13 +543,10 @@ public void DroppingLinks() var span = Span.StartSpan( activity, - Tracestate.Empty, - recordSpanOptions, - SpanName, + Tracestate.Empty, SpanKind.Internal, traceParams, - startEndHandler, - timestampConverter); + startEndHandler); var link = Link.FromActivity(activityLink); for (var i = 0; i < 2 * maxNumberOfLinks; i++) { @@ -601,81 +571,19 @@ public void DroppingLinks() } } - [Fact] - public void SampleToLocalSpanStore() - { - var activity1 = new Activity(SpanName).Start(); - - var span = - (Span)Span.StartSpan( - activity1, - Tracestate.Empty, - recordSpanOptions, - SpanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - timestampConverter); - span.IsSampleToLocalSpanStore = true; - span.End(); - - Assert.True(((Span)span).IsSampleToLocalSpanStore); - - var activity2 = new Activity(SpanName).Start(); - var span2 = - Span.StartSpan( - activity2, - Tracestate.Empty, - recordSpanOptions, - SpanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - timestampConverter); - span2.End(); - - Assert.False(((Span)span2).IsSampleToLocalSpanStore); - - var startEndMock = Mock.Get(startEndHandler); - - startEndMock.Verify(s => s.OnEnd(span), Times.Exactly(1)); - startEndMock.Verify(s => s.OnEnd(span2), Times.Exactly(1)); - } - - [Fact] - public void SampleToLocalSpanStore_RunningSpan() - { - var activity = new Activity(SpanName).Start(); - - var span = - Span.StartSpan( - activity, - Tracestate.Empty, - recordSpanOptions, - SpanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - timestampConverter); - - Assert.Throws(() => ((Span)span).IsSampleToLocalSpanStore); - } - [Fact] public void BadArguments() { var activity = new Activity(SpanName).Start(); + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var span = Span.StartSpan( activity, Tracestate.Empty, - recordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, - startEndHandler, - timestampConverter); + startEndHandler); Assert.Throws(() => span.Status = null); Assert.Throws(() => span.UpdateName(null)); @@ -691,26 +599,6 @@ public void BadArguments() Assert.Throws(() => span.AddLink(null)); } - [Fact] - public void SetSampleTo() - { - var activity = new Activity(SpanName).Start(); - - var span = (Span)Span.StartSpan( - activity, - Tracestate.Empty, - recordSpanOptions, - SpanName, - SpanKind.Internal, - TraceParams.Default, - startEndHandler, - timestampConverter); - - span.IsSampleToLocalSpanStore = true; - span.End(); - Assert.True(span.IsSampleToLocalSpanStore); - } - [Theory] [InlineData(true)] [InlineData(false)] @@ -718,17 +606,18 @@ public void EndSpanStopsActivity(bool recordEvents) { var parentActivity = new Activity(SpanName).Start(); var activity = new Activity(SpanName).Start(); + if (recordEvents) + { + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } var span = Span.StartSpan( activity, - Tracestate.Empty, - recordEvents ? recordSpanOptions : noRecordSpanOptions, - SpanName, + Tracestate.Empty, SpanKind.Internal, TraceParams.Default, startEndHandler, - timestampConverter, ownsActivity: true); span.End(); @@ -741,17 +630,18 @@ public void EndSpanStopsActivity(bool recordEvents) public void EndSpanDoesNotStopActivityWhenDoesNotOwnIt(bool recordEvents) { var activity = new Activity(SpanName).Start(); + if (recordEvents) + { + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } var span = Span.StartSpan( activity, Tracestate.Empty, - recordEvents ? recordSpanOptions : noRecordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, startEndHandler, - timestampConverter, ownsActivity: false); span.End(); @@ -767,17 +657,18 @@ public void EndSpanDoesNotStopActivityWhenDoesNotOwnIt(bool recordEvents) public void EndSpanStopActivity_NotCurrentActivity(bool recordEvents, bool ownsActivity) { var activity = new Activity(SpanName).Start(); + if (recordEvents) + { + activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + } var span = Span.StartSpan( activity, Tracestate.Empty, - recordEvents ? recordSpanOptions : noRecordSpanOptions, - SpanName, SpanKind.Internal, TraceParams.Default, startEndHandler, - timestampConverter, ownsActivity: ownsActivity); var anotherActivity = new Activity(SpanName).Start(); @@ -790,5 +681,12 @@ public void Dispose() { Activity.Current = null; } + + private void AssertApproxSameTimestamp(DateTime one, DateTime two) + { + var timeShift = Math.Abs((one - two).TotalMilliseconds); + Assert.True(timeShift > 0); + Assert.True(timeShift < 10); + } } } diff --git a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj index 533c15f685c..ec477c3b1c1 100644 --- a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj +++ b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj @@ -30,4 +30,8 @@ + + + + \ No newline at end of file From 156c40022a9aae1419a2c8179cfc59d42fd61a12 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Tue, 16 Jul 2019 00:39:51 +0200 Subject: [PATCH 19/41] nit: Event name mispelled: ResponseReceived (#150) --- .../Implementation/RedisProfilerEntryToSpanConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs index cd2f763d0cc..ef9b61a2867 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/Implementation/RedisProfilerEntryToSpanConverter.cs @@ -109,7 +109,7 @@ internal static SpanData ProfiledCommandToSpanData(SpanContext context, string n { TimedEvent.Create(enqueued, Event.Create("Enqueued")), TimedEvent.Create(send, Event.Create("Sent")), - TimedEvent.Create(response, Event.Create("ResponseRecieved")), + TimedEvent.Create(response, Event.Create("ResponseReceived")), }, droppedEventsCount: 0); From 2183c425e80abcebd77cb2db6e1f1763d498c554 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 16 Jul 2019 16:25:52 -0700 Subject: [PATCH 20/41] TimedEvents clean up (#152) --- .../Trace/Export/Attributes.cs | 2 +- .../Trace/Export/LinkList.cs | 8 +- .../Trace/Export/TimedEvent.cs | 2 +- .../Trace/Export/TimedEvents.cs | 4 +- .../Trace/SpanData.cs | 6 +- src/OpenTelemetry/Trace/EventWithTime.cs | 39 ------ .../Trace/Internal/EvictingQueue.cs | 69 +++++++++++ src/OpenTelemetry/Trace/Span.cs | 54 +++------ src/OpenTelemetry/Trace/TraceEvents.cs | 50 -------- .../Utils/AttributesWithCapacity.cs | 93 -------------- src/OpenTelemetry/Utils/EvictingQueue.cs | 113 ------------------ .../Impl/Trace/Export/SpanExporterTest.cs | 1 + 12 files changed, 98 insertions(+), 343 deletions(-) delete mode 100644 src/OpenTelemetry/Trace/EventWithTime.cs create mode 100644 src/OpenTelemetry/Trace/Internal/EvictingQueue.cs delete mode 100644 src/OpenTelemetry/Trace/TraceEvents.cs delete mode 100644 src/OpenTelemetry/Utils/AttributesWithCapacity.cs delete mode 100644 src/OpenTelemetry/Utils/EvictingQueue.cs diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs index 876d4b751e0..141a7b66d57 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Trace.Export public sealed class Attributes { - private static readonly Attributes Empty = new Attributes(new Dictionary(), 0); + public static readonly Attributes Empty = new Attributes(new Dictionary(), 0); private Attributes(IEnumerable> attributeMap, int droppedAttributesCount) { diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs index fc1baabd640..35aa621c663 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Trace.Export public sealed class LinkList : ILinks { - private static readonly LinkList Empty = new LinkList(new ILink[0], 0); + public static readonly LinkList Empty = new LinkList(new ILink[0], 0); internal LinkList(IEnumerable links, int droppedLinksCount) { @@ -34,16 +34,14 @@ internal LinkList(IEnumerable links, int droppedLinksCount) public IEnumerable Links { get; } - public static LinkList Create(IEnumerable links, int droppedLinksCount) + public static LinkList Create(IReadOnlyCollection links, int droppedLinksCount) { if (links == null) { return Empty; } - IEnumerable copy = new List(links); - - return new LinkList(copy, droppedLinksCount); + return new LinkList(links, droppedLinksCount); } /// diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs index 47bf79c4720..1a195613065 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs @@ -64,7 +64,7 @@ public override bool Equals(object o) return false; } - /// + /// public override int GetHashCode() { var h = 1; diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs index 4e9afac1762..0af1c4ae530 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Trace.Export public sealed class TimedEvents : ITimedEvents { - private static readonly TimedEvents Empty = new TimedEvents(new ITimedEvent[0], 0); + public static readonly ITimedEvents Empty = new TimedEvents(new ITimedEvent[0], 0); internal TimedEvents(IEnumerable> events, int droppedEventsCount) { @@ -34,7 +34,7 @@ internal TimedEvents(IEnumerable> events, int droppedEventsCount) public int DroppedEventsCount { get; } - public static ITimedEvents Create(IEnumerable> events, int droppedEventsCount) + public static ITimedEvents Create(IReadOnlyCollection> events, int droppedEventsCount) { if (events == null) { diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index 9534af325a8..82f0471ce4d 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -47,9 +47,9 @@ internal SpanData( this.Resource = resource ?? throw new ArgumentNullException(nameof(resource)); this.Name = name ?? throw new ArgumentNullException(nameof(name)); this.StartTimestamp = startTimestamp; - this.Attributes = attributes ?? Export.Attributes.Create(new Dictionary(), 0); - this.Events = events ?? TimedEvents.Create(Enumerable.Empty>(), 0); - this.Links = links ?? LinkList.Create(Enumerable.Empty(), 0); + this.Attributes = attributes ?? Attributes.Empty; + this.Events = events ?? TimedEvents.Empty; + this.Links = links ?? LinkList.Empty; this.ChildSpanCount = childSpanCount; this.Status = status; this.Kind = kind; diff --git a/src/OpenTelemetry/Trace/EventWithTime.cs b/src/OpenTelemetry/Trace/EventWithTime.cs deleted file mode 100644 index b441ff1a3a9..00000000000 --- a/src/OpenTelemetry/Trace/EventWithTime.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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; - using OpenTelemetry.Internal; - using OpenTelemetry.Trace.Export; - - internal class EventWithTime - { - private readonly DateTime nanoTime; - private readonly T @event; - - public EventWithTime(DateTime nanoTime, T @event) - { - this.nanoTime = nanoTime; - this.@event = @event; - } - - internal ITimedEvent ToSpanDataTimedEvent() - { - return TimedEvent.Create(this.nanoTime, this.@event); - } - } -} diff --git a/src/OpenTelemetry/Trace/Internal/EvictingQueue.cs b/src/OpenTelemetry/Trace/Internal/EvictingQueue.cs new file mode 100644 index 00000000000..40713757ee9 --- /dev/null +++ b/src/OpenTelemetry/Trace/Internal/EvictingQueue.cs @@ -0,0 +1,69 @@ +// +// 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.Internal +{ + using System; + using System.Collections.Generic; + + internal class EvictingQueue + { + private readonly int maxNumEvents; + private readonly Queue events; + private int totalRecorded; + + public EvictingQueue(int maxNumEvents) + { + if (maxNumEvents < 0) + { + throw new ArgumentOutOfRangeException($"{nameof(maxNumEvents)} must be >= 0"); + } + + this.maxNumEvents = maxNumEvents; + this.events = new Queue(maxNumEvents); + } + + public int Count => this.events.Count; + + public int DroppedItems => this.totalRecorded - this.events.Count; + + public IReadOnlyCollection ToReadOnlyCollection() + { + return this.events.ToArray(); + } + + internal void AddEvent(T evnt) + { + if (evnt == null) + { + throw new ArgumentNullException(); + } + + this.totalRecorded++; + if (this.maxNumEvents == 0) + { + return; + } + + if (this.events.Count == this.maxNumEvents) + { + this.events.Dequeue(); + } + + this.events.Enqueue(evnt); + } + } +} diff --git a/src/OpenTelemetry/Trace/Span.cs b/src/OpenTelemetry/Trace/Span.cs index c2db5bccda8..2efebcdcb9b 100644 --- a/src/OpenTelemetry/Trace/Span.cs +++ b/src/OpenTelemetry/Trace/Span.cs @@ -19,10 +19,10 @@ namespace OpenTelemetry.Trace using System; using System.Collections.Generic; using System.Diagnostics; - using OpenTelemetry.Internal; using OpenTelemetry.Resources; using OpenTelemetry.Trace.Config; using OpenTelemetry.Trace.Export; + using OpenTelemetry.Trace.Internal; using OpenTelemetry.Utils; /// @@ -34,9 +34,9 @@ public sealed class Span : ISpan private readonly IStartEndHandler startEndHandler; private readonly Lazy spanContext; private readonly object @lock = new object(); - private AttributesWithCapacity attributes; - private TraceEvents> events; - private TraceEvents links; + private EvictingQueue> attributes; + private EvictingQueue> events; + private EvictingQueue links; private Status status; private Span( @@ -112,40 +112,40 @@ public Status Status internal bool OwnsActivity { get; } - private AttributesWithCapacity InitializedAttributes + private EvictingQueue> InitializedAttributes { get { if (this.attributes == null) { - this.attributes = new AttributesWithCapacity(this.traceParams.MaxNumberOfAttributes); + this.attributes = new EvictingQueue>(this.traceParams.MaxNumberOfAttributes); } return this.attributes; } } - private TraceEvents> InitializedEvents + private EvictingQueue> InitializedEvents { get { if (this.events == null) { this.events = - new TraceEvents>(this.traceParams.MaxNumberOfEvents); + new EvictingQueue>(this.traceParams.MaxNumberOfEvents); } return this.events; } } - private TraceEvents InitializedLinks + private EvictingQueue InitializedLinks { get { if (this.links == null) { - this.links = new TraceEvents(this.traceParams.MaxNumberOfLinks); + this.links = new EvictingQueue(this.traceParams.MaxNumberOfLinks); } return this.links; @@ -181,7 +181,7 @@ public void SetAttribute(KeyValuePair keyValuePair) return; } - this.InitializedAttributes.PutAttribute(keyValuePair.Key, keyValuePair.Value); + this.InitializedAttributes.AddEvent(new KeyValuePair(keyValuePair.Key, keyValuePair.Value)); } } @@ -206,7 +206,7 @@ public void AddEvent(string name) return; } - this.InitializedEvents.AddEvent(new EventWithTime(PreciseTimestamp.GetUtcNow(), Event.Create(name))); + this.InitializedEvents.AddEvent(TimedEvent.Create(PreciseTimestamp.GetUtcNow(), Event.Create(name))); } } @@ -236,7 +236,7 @@ public void AddEvent(string name, IDictionary eventAttributes) return; } - this.InitializedEvents.AddEvent(new EventWithTime(PreciseTimestamp.GetUtcNow(), Event.Create(name, eventAttributes))); + this.InitializedEvents.AddEvent(TimedEvent.Create(PreciseTimestamp.GetUtcNow(), Event.Create(name, eventAttributes))); } } @@ -261,7 +261,7 @@ public void AddEvent(IEvent addEvent) return; } - this.InitializedEvents.AddEvent(new EventWithTime(PreciseTimestamp.GetUtcNow(), addEvent)); + this.InitializedEvents.AddEvent(TimedEvent.Create(PreciseTimestamp.GetUtcNow(), addEvent)); } } @@ -330,9 +330,9 @@ public SpanData ToSpanData() throw new InvalidOperationException("Getting SpanData for a Span without RECORD_EVENTS option."); } - var attributesSpanData = Attributes.Create(this.attributes?.AsReadOnlyCollection(), this.attributes?.NumberOfDroppedAttributes ?? 0); - var annotationsSpanData = CreateTimedEvents(this.InitializedEvents); - var linksSpanData = LinkList.Create(this.links?.Events, this.links?.NumberOfDroppedEvents ?? 0); + var attributesSpanData = Attributes.Create(this.attributes?.ToReadOnlyCollection(), this.attributes?.DroppedItems ?? 0); + var eventsSpanData = TimedEvents.Create(this.events?.ToReadOnlyCollection(), this.events?.DroppedItems ?? 0); + var linksSpanData = LinkList.Create(this.links?.ToReadOnlyCollection(), this.links?.DroppedItems ?? 0); return SpanData.Create( this.Context, // TODO avoid using context, use Activity instead @@ -341,7 +341,7 @@ public SpanData ToSpanData() this.Name, this.Activity.StartTimeUtc, attributesSpanData, - annotationsSpanData, + eventsSpanData, linksSpanData, null, // Not supported yet. this.HasEnded ? this.StatusWithDefault : null, @@ -443,23 +443,5 @@ internal static ISpan StartSpan( return span; } - - private static ITimedEvents CreateTimedEvents(TraceEvents> events) - { - List> eventsList = null; - int numberOfDroppedEvents = 0; - if (events != null) - { - eventsList = new List>(events.Events.Count); - foreach (var networkEvent in events.Events) - { - eventsList.Add(networkEvent.ToSpanDataTimedEvent()); - } - - numberOfDroppedEvents = events.NumberOfDroppedEvents; - } - - return TimedEvents.Create(eventsList, numberOfDroppedEvents); - } } } diff --git a/src/OpenTelemetry/Trace/TraceEvents.cs b/src/OpenTelemetry/Trace/TraceEvents.cs deleted file mode 100644 index 07edeab7369..00000000000 --- a/src/OpenTelemetry/Trace/TraceEvents.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// 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.Utils; - - internal class TraceEvents - { - private readonly EvictingQueue events; - private int totalRecordedEvents = 0; - - public TraceEvents(int maxNumEvents) - { - this.events = new EvictingQueue(maxNumEvents); - } - - public EvictingQueue Events - { - get - { - return this.events; - } - } - - public int NumberOfDroppedEvents - { - get { return this.totalRecordedEvents - this.events.Count; } - } - - internal void AddEvent(T @event) - { - this.totalRecordedEvents++; - this.events.Add(@event); - } - } -} diff --git a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs b/src/OpenTelemetry/Utils/AttributesWithCapacity.cs deleted file mode 100644 index 60d91a6daf9..00000000000 --- a/src/OpenTelemetry/Utils/AttributesWithCapacity.cs +++ /dev/null @@ -1,93 +0,0 @@ -// -// 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.Utils -{ - using System.Collections.Generic; - - internal class AttributesWithCapacity - { - private readonly int capacity; - - private KeyValueListNode attributesHead = null; - private KeyValueListNode attributesTail = null; - - private int totalRecordedAttributes; - private int count = 0; - - public AttributesWithCapacity(int capacity) - { - this.capacity = capacity; - } - - public int NumberOfDroppedAttributes => this.totalRecordedAttributes - this.count; - - public void PutAttribute(string key, object value) - { - this.totalRecordedAttributes += 1; - if (this.capacity == 0) - { - return; - } - - this.count++; - var next = new KeyValueListNode - { - KeyValue = new KeyValuePair(key, value), - Next = null, - }; - - if (this.attributesHead == null) - { - this.attributesHead = next; - this.attributesTail = next; - } - else - { - this.attributesTail.Next = next; - this.attributesTail = next; - if (this.count > this.capacity) - { - this.attributesHead = this.attributesHead.Next; - this.count--; - } - } - } - - public IReadOnlyCollection> AsReadOnlyCollection() - { - var result = new List>(); - var next = this.attributesHead; - - while (next != null) - { - result.Add(new KeyValuePair(next.KeyValue.Key, next.KeyValue.Value)); - next = next.Next; - } - - return result; - } - - /// - /// Having our own key-value linked list allows us to be more efficient. - /// - private class KeyValueListNode - { - public KeyValuePair KeyValue; - public KeyValueListNode Next; - } - } -} diff --git a/src/OpenTelemetry/Utils/EvictingQueue.cs b/src/OpenTelemetry/Utils/EvictingQueue.cs deleted file mode 100644 index fb8560df883..00000000000 --- a/src/OpenTelemetry/Utils/EvictingQueue.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// 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.Utils -{ - using System; - using System.Collections; - using System.Collections.Generic; - - internal class EvictingQueue : IEnumerable, IEnumerable - { - private readonly Queue @delegate; - private readonly int maxSize; - - public EvictingQueue(int maxSize) - { - if (maxSize < 0) - { - throw new ArgumentOutOfRangeException("maxSize must be >= 0"); - } - - this.maxSize = maxSize; - this.@delegate = new Queue(maxSize); - } - - public int Count - { - get - { - return this.@delegate.Count; - } - } - - public int RemainingCapacity() - { - return this.maxSize - this.@delegate.Count; - } - - public bool Offer(T e) - { - return this.Add(e); - } - - public bool Add(T e) - { - if (e == null) - { - throw new ArgumentNullException(); - } - - if (this.maxSize == 0) - { - return true; - } - - if (this.@delegate.Count == this.maxSize) - { - this.@delegate.Dequeue(); - } - - this.@delegate.Enqueue(e); - return true; - } - - public bool AddAll(ICollection collection) - { - foreach (var e in collection) - { - this.Add(e); - } - - return true; - } - - public bool Contains(T e) - { - if (e == null) - { - throw new ArgumentNullException(); - } - - return this.@delegate.Contains(e); - } - - public T[] ToArray() - { - return this.@delegate.ToArray(); - } - - public IEnumerator GetEnumerator() - { - return this.@delegate.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this.@delegate.GetEnumerator(); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index 86549fb5c1a..12b894c5422 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -33,6 +33,7 @@ public class SpanExporterTest : IDisposable { private const string SpanName1 = "MySpanName/1"; private const string SpanName2 = "MySpanName/2"; + private readonly ISpanExporter spanExporter = SpanExporter.Create(4, TimeSpan.FromSeconds(1)); private readonly IStartEndHandler startEndHandler; private readonly TestHandler serviceHandler = new TestHandler(); From 799da6de755edcf3ae81e0b804b63a89df9ec7e7 Mon Sep 17 00:00:00 2001 From: Tim Wegner Date: Mon, 22 Jul 2019 11:17:06 -0700 Subject: [PATCH 21/41] Addressing perf concern raised in issue #83 and replacing string literals with nameof(). (#157) --- src/OpenTelemetry.Abstractions/Tags/Tag.cs | 7 +++--- src/OpenTelemetry.Abstractions/Tags/TagKey.cs | 5 ++-- .../Tags/TagValue.cs | 5 ++-- .../Tags/TagValues.cs | 5 +++- .../Trace/Config/TraceParams.cs | 13 +++++----- src/OpenTelemetry.Abstractions/Trace/Event.cs | 7 +++--- .../Trace/Export/Attributes.cs | 7 +++--- .../Trace/Export/LinkList.cs | 7 +++--- .../Trace/Export/TimedEvent.cs | 9 ++++--- .../Trace/Export/TimedEvents.cs | 3 ++- src/OpenTelemetry.Abstractions/Trace/Link.cs | 11 ++++---- .../Sampler/Internal/AlwaysSampleSampler.cs | 2 +- .../Sampler/Internal/NeverSampleSampler.cs | 2 +- .../Trace/SpanContext.cs | 11 ++++---- .../Trace/SpanData.cs | 25 ++++++++++--------- .../Trace/Status.cs | 9 ++++--- .../Trace/TraceState.cs | 17 +++---------- .../Stats/Aggregations/CountData.cs | 5 ++-- .../Stats/Aggregations/Distribution.cs | 5 ++-- .../Stats/Aggregations/DistributionData.cs | 15 +++++------ .../Stats/Aggregations/LastValue.cs | 3 +-- .../Stats/Aggregations/LastValueDataDouble.cs | 5 ++-- .../Stats/Aggregations/LastValueDataLong.cs | 5 ++-- src/OpenTelemetry/Stats/Aggregations/Mean.cs | 3 +-- .../Stats/Aggregations/MeanData.cs | 13 +++++----- src/OpenTelemetry/Stats/Aggregations/Sum.cs | 3 +-- .../Stats/Aggregations/SumDataDouble.cs | 5 ++-- .../Stats/Aggregations/SumDataLong.cs | 5 ++-- src/OpenTelemetry/Stats/BucketBoundaries.cs | 5 ++-- .../Stats/Measurements/MeasurementDouble.cs | 7 +++--- .../Stats/Measurements/MeasurementLong.cs | 7 +++--- .../Stats/Measures/MeasureDouble.cs | 11 ++++---- .../Stats/Measures/MeasureLong.cs | 11 ++++---- src/OpenTelemetry/Stats/View.cs | 15 +++++------ src/OpenTelemetry/Stats/ViewData.cs | 13 +++++----- src/OpenTelemetry/Stats/ViewName.cs | 5 ++-- .../Trace/Sampler/ProbabilitySampler.cs | 7 +++--- 37 files changed, 156 insertions(+), 137 deletions(-) diff --git a/src/OpenTelemetry.Abstractions/Tags/Tag.cs b/src/OpenTelemetry.Abstractions/Tags/Tag.cs index 2a585de5e3f..3787554e6d0 100644 --- a/src/OpenTelemetry.Abstractions/Tags/Tag.cs +++ b/src/OpenTelemetry.Abstractions/Tags/Tag.cs @@ -58,9 +58,10 @@ public static Tag Create(TagKey key, TagValue value) /// public override string ToString() { - return "Tag{" - + "key=" + this.Key + ", " - + "value=" + this.Value + return nameof(Tag) + + "{" + + nameof(this.Key) + "=" + this.Key + ", " + + nameof(this.Value) + "=" + this.Value + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Tags/TagKey.cs b/src/OpenTelemetry.Abstractions/Tags/TagKey.cs index bf90e094410..84820860684 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagKey.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagKey.cs @@ -57,8 +57,9 @@ public static TagKey Create(string name) /// public override string ToString() { - return "TagKey{" - + "name=" + this.Name + return nameof(TagKey) + + "{" + + this.Name + "=" + this.Name + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Tags/TagValue.cs b/src/OpenTelemetry.Abstractions/Tags/TagValue.cs index a12d5162809..8178d3f648d 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagValue.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagValue.cs @@ -57,8 +57,9 @@ public static TagValue Create(string value) /// public override string ToString() { - return "TagValue{" - + "asString=" + this.AsString + return nameof(TagValue) + + "{" + + nameof(this.AsString) + "=" + this.AsString + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Tags/TagValues.cs b/src/OpenTelemetry.Abstractions/Tags/TagValues.cs index 10b1ba49df7..28d539ffe05 100644 --- a/src/OpenTelemetry.Abstractions/Tags/TagValues.cs +++ b/src/OpenTelemetry.Abstractions/Tags/TagValues.cs @@ -46,7 +46,10 @@ public static TagValues Create(IReadOnlyList values) /// public override string ToString() { - return "TagValues{values=" + string.Join(", ", this.Values) + "}"; + return nameof(TagValues) + + "{" + + nameof(this.Values) + "=" + string.Join(", ", this.Values) + + "}"; } /// diff --git a/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs b/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs index 46b05fb694d..de67ffe48a9 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Config/TraceParams.cs @@ -86,12 +86,13 @@ public TraceParamsBuilder ToBuilder() /// public override string ToString() { - return "TraceParams{" - + "sampler=" + this.Sampler + ", " - + "maxNumberOfAttributes=" + this.MaxNumberOfAttributes + ", " - + "maxNumberOfAnnotations=" + this.MaxNumberOfEvents + ", " - + "maxNumberOfMessageEvents=" + this.MaxNumberOfMessageEvents + ", " - + "maxNumberOfLinks=" + this.MaxNumberOfLinks + return nameof(TraceParams) + + "{" + + nameof(this.Sampler) + "=" + this.Sampler + ", " + + nameof(this.MaxNumberOfAttributes) + "=" + this.MaxNumberOfAttributes + ", " + + nameof(this.MaxNumberOfEvents) + "=" + this.MaxNumberOfEvents + ", " + + nameof(this.MaxNumberOfMessageEvents) + "=" + this.MaxNumberOfMessageEvents + ", " + + nameof(this.MaxNumberOfLinks) + "=" + this.MaxNumberOfLinks + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Event.cs b/src/OpenTelemetry.Abstractions/Trace/Event.cs index 52cf868281b..da6810586a0 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Event.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Event.cs @@ -99,9 +99,10 @@ public override int GetHashCode() /// public override string ToString() { - return "Annotation{" - + "description=" + this.Name + ", " - + "attributes=" + string.Join(", ", this.Attributes.Select(kvp => $"{kvp.Key}={kvp.Value}")) + return nameof(Event) + + "{" + + nameof(this.Name) + "=" + this.Name + ", " + + nameof(this.Attributes) + "=" + string.Join(", ", this.Attributes.Select(kvp => (kvp.Key + "=" + kvp.Value))) + "}"; } } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs index 141a7b66d57..04eaa7070fa 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/Attributes.cs @@ -47,9 +47,10 @@ public static Attributes Create(IReadOnlyCollection /// public override string ToString() { - return "Attributes{" - + "attributeMap=" + this.AttributeMap + ", " - + "droppedAttributesCount=" + this.DroppedAttributesCount + return nameof(Attributes) + + "{" + + nameof(this.AttributeMap) + "=" + this.AttributeMap + ", " + + nameof(this.DroppedAttributesCount) + "=" + this.DroppedAttributesCount + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs index 35aa621c663..e5c8e26a688 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs @@ -47,9 +47,10 @@ public static LinkList Create(IReadOnlyCollection links, int droppedLinks /// public override string ToString() { - return "Links{" - + "links=" + this.Links + ", " - + "droppedLinksCount=" + this.DroppedLinksCount + return nameof(LinkList) + + "{" + + nameof(this.Links) + "=" + this.Links + ", " + + nameof(this.DroppedLinksCount) + "=" + this.DroppedLinksCount + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs index 1a195613065..27b22d0615f 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvent.cs @@ -41,13 +41,14 @@ public static ITimedEvent Create(DateTime timestamp, T @event) /// public override string ToString() { - return "TimedEvent{" - + "timestamp=" + this.Timestamp + ", " - + "event=" + this.Event + return "TimedEvent" + + "{" + + nameof(this.Timestamp) + "=" + this.Timestamp + ", " + + nameof(this.Event) + "=" + this.Event + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs index 0af1c4ae530..6d7a20e7656 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs @@ -47,7 +47,8 @@ public static ITimedEvents Create(IReadOnlyCollection> events, /// public override string ToString() { - return "TimedEvents{" + return "TimedEvents" + + "{" + "events=" + this.Events + ", " + "droppedEventsCount=" + this.DroppedEventsCount + "}"; diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index db1bca0882b..3b7045a5e26 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -76,11 +76,12 @@ public static ILink FromSpanContext(SpanContext context, IDictionary public override string ToString() { - return "Link{" - + "traceId=" + this.Context.TraceId.ToHexString() + ", " - + "spanId=" + this.Context.SpanId.ToHexString() + ", " - + "tracestate=" + this.Context.Tracestate.ToString() + ", " - + "attributes=" + string.Join(", ", this.Attributes.Select(kvp => $"{kvp.Key}={kvp.Value}")) + return nameof(Link) + + "{" + + nameof(this.Context) + "=" + this.Context.TraceId.ToHexString() + ", " + + nameof(this.Context) + "=" + this.Context.SpanId.ToHexString() + ", " + + nameof(this.Context) + "=" + this.Context.Tracestate.ToString() + ", " + + nameof(this.Attributes) + "=" + string.Join(", ", this.Attributes.Select(kvp => (kvp.Key + "=" + kvp.Value))) + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs index 48ca5446223..eaf42de42b6 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/AlwaysSampleSampler.cs @@ -36,7 +36,7 @@ public bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, Act /// public override string ToString() { - return "AlwaysSampleSampler"; + return nameof(AlwaysSampleSampler); } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs index d34c8a7e785..cac1f4a9d6b 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Sampler/Internal/NeverSampleSampler.cs @@ -37,7 +37,7 @@ public bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, Act /// public override string ToString() { - return "NeverSampleSampler"; + return nameof(NeverSampleSampler); } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs b/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs index fc61f93202a..18d77f7d91d 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanContext.cs @@ -108,11 +108,12 @@ public override bool Equals(object obj) /// public override string ToString() { - return "SpanContext{" - + "traceId=" + this.TraceId + ", " - + "spanId=" + this.SpanId + ", " - + "traceOptions=" + this.TraceOptions - + "}"; + return nameof(SpanContext) + + "{" + + nameof(this.TraceId) + "=" + this.TraceId + ", " + + nameof(this.SpanId) + "=" + this.SpanId + ", " + + nameof(this.TraceOptions) + "=" + this.TraceOptions + + "}"; } private bool IsTraceIdValid(ActivityTraceId traceId) diff --git a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs index 82f0471ce4d..b8c0f71f20a 100644 --- a/src/OpenTelemetry.Abstractions/Trace/SpanData.cs +++ b/src/OpenTelemetry.Abstractions/Trace/SpanData.cs @@ -169,18 +169,19 @@ public static SpanData Create( /// public override string ToString() { - return "SpanData{" - + "context=" + this.Context + ", " - + "parentSpanId=" + this.ParentSpanId + ", " - + "resource=" + this.Resource + ", " - + "name=" + this.Name + ", " - + "startTimestamp=" + this.StartTimestamp + ", " - + "attributes=" + this.Attributes + ", " - + "events=" + this.Events + ", " - + "links=" + this.Links + ", " - + "childSpanCount=" + this.ChildSpanCount + ", " - + "status=" + this.Status + ", " - + "endTimestamp=" + this.EndTimestamp + return nameof(SpanData) + + "{" + + nameof(this.Context) + "=" + this.Context + ", " + + nameof(this.ParentSpanId) + "=" + this.ParentSpanId + ", " + + nameof(this.Resource) + "=" + this.Resource + ", " + + nameof(this.Name) + "=" + this.Name + ", " + + nameof(this.StartTimestamp) + "=" + this.StartTimestamp + ", " + + nameof(this.Attributes) + "=" + this.Attributes + ", " + + nameof(this.Events) + "=" + this.Events + ", " + + nameof(this.Links) + "=" + this.Links + ", " + + nameof(this.ChildSpanCount) + "=" + this.ChildSpanCount + ", " + + nameof(this.Status) + "=" + this.Status + ", " + + nameof(this.EndTimestamp) + "=" + this.EndTimestamp + "}"; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Status.cs b/src/OpenTelemetry.Abstractions/Trace/Status.cs index 4b587208065..0f5309da4a7 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Status.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Status.cs @@ -213,10 +213,11 @@ public override int GetHashCode() /// public override string ToString() { - return "Status{" - + "canonicalCode=" + this.CanonicalCode + ", " - + "description=" + this.Description - + "}"; + return nameof(Status) + + "{" + + nameof(this.CanonicalCode) + "=" + this.CanonicalCode + ", " + + nameof(this.Description) + "=" + this.Description + + "}"; } } } diff --git a/src/OpenTelemetry.Abstractions/Trace/TraceState.cs b/src/OpenTelemetry.Abstractions/Trace/TraceState.cs index 80edfe792d5..e2905bb788c 100644 --- a/src/OpenTelemetry.Abstractions/Trace/TraceState.cs +++ b/src/OpenTelemetry.Abstractions/Trace/TraceState.cs @@ -55,7 +55,7 @@ public static TracestateBuilder Builder } /// - /// Gets the list of entris in tracestate. + /// Gets the list of entries in tracestate. /// public IEnumerable Entries { get => this.entries; } @@ -97,23 +97,12 @@ public override string ToString() { var sb = new StringBuilder(); - var isFirst = true; - foreach (var entry in this.Entries) { - if (isFirst) - { - isFirst = false; - } - else - { - sb.Append(","); - } - - sb.Append(entry.Key).Append("=").Append(entry.Value); + sb.Append(entry.Key + "=" + entry.Value + ","); } - return sb.ToString(); + return sb.Remove(sb.Length - 1, 1).ToString(); } return string.Empty; diff --git a/src/OpenTelemetry/Stats/Aggregations/CountData.cs b/src/OpenTelemetry/Stats/Aggregations/CountData.cs index 8430ee1e6f7..2685174fa20 100644 --- a/src/OpenTelemetry/Stats/Aggregations/CountData.cs +++ b/src/OpenTelemetry/Stats/Aggregations/CountData.cs @@ -50,8 +50,9 @@ public override T Match( /// public override string ToString() { - return "CountData{" - + "count=" + this.Count + return nameof(CountData) + + "{" + + nameof(this.Count) + "=" + this.Count + "}"; } diff --git a/src/OpenTelemetry/Stats/Aggregations/Distribution.cs b/src/OpenTelemetry/Stats/Aggregations/Distribution.cs index 51723b805d5..d5c96eacb60 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Distribution.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Distribution.cs @@ -51,8 +51,9 @@ public override T Match(Func p0, Func p1, Func /// public override string ToString() { - return "Distribution{" - + "bucketBoundaries=" + this.BucketBoundaries + return nameof(Distribution) + + "{" + + nameof(this.BucketBoundaries) + "=" + this.BucketBoundaries + "}"; } diff --git a/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs b/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs index 6e9d8af59ad..f6eb6957f36 100644 --- a/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs +++ b/src/OpenTelemetry/Stats/Aggregations/DistributionData.cs @@ -84,13 +84,14 @@ public override T Match( /// public override string ToString() { - return "DistributionData{" - + "mean=" + this.Mean + ", " - + "count=" + this.Count + ", " - + "min=" + this.Min + ", " - + "max=" + this.Max + ", " - + "sumOfSquaredDeviations=" + this.SumOfSquaredDeviations + ", " - + "bucketCounts=" + string.Join(", ", this.BucketCounts) + return nameof(DistributionData) + + "{" + + nameof(this.Mean) + "=" + this.Mean + ", " + + nameof(this.Count) + "=" + this.Count + ", " + + nameof(this.Min) + "=" + this.Min + ", " + + nameof(this.Max) + "=" + this.Max + ", " + + nameof(this.SumOfSquaredDeviations) + "=" + this.SumOfSquaredDeviations + ", " + + nameof(this.BucketCounts) + "=" + string.Join(", ", this.BucketCounts) + "}"; } diff --git a/src/OpenTelemetry/Stats/Aggregations/LastValue.cs b/src/OpenTelemetry/Stats/Aggregations/LastValue.cs index 2efe4a141b0..c221bf9cca1 100644 --- a/src/OpenTelemetry/Stats/Aggregations/LastValue.cs +++ b/src/OpenTelemetry/Stats/Aggregations/LastValue.cs @@ -41,8 +41,7 @@ public override T Match(Func p0, Func p1, Func /// public override string ToString() { - return "LastValue{" - + "}"; + return nameof(LastValue) + "{}"; } /// diff --git a/src/OpenTelemetry/Stats/Aggregations/LastValueDataDouble.cs b/src/OpenTelemetry/Stats/Aggregations/LastValueDataDouble.cs index 2a7f73eccb0..eba85501060 100644 --- a/src/OpenTelemetry/Stats/Aggregations/LastValueDataDouble.cs +++ b/src/OpenTelemetry/Stats/Aggregations/LastValueDataDouble.cs @@ -42,8 +42,9 @@ public static ILastValueDataDouble Create(double lastValue) /// public override string ToString() { - return "LastValueDataDouble{" - + "lastValue=" + this.LastValue + return nameof(LastValueDataDouble) + + "{" + + nameof(this.LastValue) + "=" + this.LastValue + "}"; } diff --git a/src/OpenTelemetry/Stats/Aggregations/LastValueDataLong.cs b/src/OpenTelemetry/Stats/Aggregations/LastValueDataLong.cs index fad80cfe788..d1206abd6fd 100644 --- a/src/OpenTelemetry/Stats/Aggregations/LastValueDataLong.cs +++ b/src/OpenTelemetry/Stats/Aggregations/LastValueDataLong.cs @@ -41,8 +41,9 @@ public static ILastValueDataLong Create(long lastValue) /// public override string ToString() { - return "LastValueDataLong{" - + "lastValue=" + this.LastValue + return nameof(LastValueDataLong) + + "{" + + nameof(this.LastValue) + "=" + this.LastValue + "}"; } diff --git a/src/OpenTelemetry/Stats/Aggregations/Mean.cs b/src/OpenTelemetry/Stats/Aggregations/Mean.cs index 4d64f06d655..e0a64ec483a 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Mean.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Mean.cs @@ -41,8 +41,7 @@ public override T Match(Func p0, Func p1, Func /// public override string ToString() { - return "Mean{" - + "}"; + return nameof(Mean) + "{}"; } /// diff --git a/src/OpenTelemetry/Stats/Aggregations/MeanData.cs b/src/OpenTelemetry/Stats/Aggregations/MeanData.cs index 78957db8750..c5adf2949c4 100644 --- a/src/OpenTelemetry/Stats/Aggregations/MeanData.cs +++ b/src/OpenTelemetry/Stats/Aggregations/MeanData.cs @@ -60,15 +60,16 @@ public override T Match( /// public override string ToString() { - return "MeanData{" - + "mean=" + this.Mean + ", " - + "min=" + this.Min + ", " - + "max=" + this.Max + ", " - + "count=" + this.Count + return nameof(MeanData) + + "{" + + nameof(this.Mean) + "=" + this.Mean + ", " + + nameof(this.Min) + "=" + this.Min + ", " + + nameof(this.Max) + "=" + this.Max + ", " + + nameof(this.Count) + "=" + this.Count + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) diff --git a/src/OpenTelemetry/Stats/Aggregations/Sum.cs b/src/OpenTelemetry/Stats/Aggregations/Sum.cs index 65bb1834a68..613cb91a58a 100644 --- a/src/OpenTelemetry/Stats/Aggregations/Sum.cs +++ b/src/OpenTelemetry/Stats/Aggregations/Sum.cs @@ -41,8 +41,7 @@ public override T Match(Func p0, Func p1, Func /// public override string ToString() { - return "Sum{" - + "}"; + return nameof(Sum) + "{}"; } /// diff --git a/src/OpenTelemetry/Stats/Aggregations/SumDataDouble.cs b/src/OpenTelemetry/Stats/Aggregations/SumDataDouble.cs index 91ff62847c2..9c6263cf9b4 100644 --- a/src/OpenTelemetry/Stats/Aggregations/SumDataDouble.cs +++ b/src/OpenTelemetry/Stats/Aggregations/SumDataDouble.cs @@ -51,8 +51,9 @@ public override T Match( /// public override string ToString() { - return "SumDataDouble{" - + "sum=" + this.Sum + return nameof(SumDataDouble) + + "{" + + nameof(this.Sum) + "=" + this.Sum + "}"; } diff --git a/src/OpenTelemetry/Stats/Aggregations/SumDataLong.cs b/src/OpenTelemetry/Stats/Aggregations/SumDataLong.cs index faa5d5e2aaf..00b73ac6ecc 100644 --- a/src/OpenTelemetry/Stats/Aggregations/SumDataLong.cs +++ b/src/OpenTelemetry/Stats/Aggregations/SumDataLong.cs @@ -50,8 +50,9 @@ public override T Match( /// public override string ToString() { - return "SumDataLong{" - + "sum=" + this.Sum + return nameof(SumDataLong) + + "{" + + nameof(this.Sum) + "=" + this.Sum + "}"; } diff --git a/src/OpenTelemetry/Stats/BucketBoundaries.cs b/src/OpenTelemetry/Stats/BucketBoundaries.cs index 4c8bf07fa53..0fcc241cfff 100644 --- a/src/OpenTelemetry/Stats/BucketBoundaries.cs +++ b/src/OpenTelemetry/Stats/BucketBoundaries.cs @@ -60,8 +60,9 @@ public static IBucketBoundaries Create(IEnumerable bucketBoundaries) /// public override string ToString() { - return "BucketBoundaries{" - + "boundaries=" + string.Join(", ", this.Boundaries) + return nameof(BucketBoundaries) + + "{" + + nameof(this.Boundaries) + "=" + string.Join(", ", this.Boundaries) + "}"; } diff --git a/src/OpenTelemetry/Stats/Measurements/MeasurementDouble.cs b/src/OpenTelemetry/Stats/Measurements/MeasurementDouble.cs index cdb0234a809..03ca1cba0b3 100644 --- a/src/OpenTelemetry/Stats/Measurements/MeasurementDouble.cs +++ b/src/OpenTelemetry/Stats/Measurements/MeasurementDouble.cs @@ -47,9 +47,10 @@ public override T Match(Func p0, Func public override string ToString() { - return "MeasurementDouble{" - + "measure=" + this.Measure + ", " - + "value=" + this.Value + return nameof(MeasurementDouble) + + "{" + + nameof(this.Measure) + "=" + this.Measure + ", " + + nameof(this.Value) + "=" + this.Value + "}"; } diff --git a/src/OpenTelemetry/Stats/Measurements/MeasurementLong.cs b/src/OpenTelemetry/Stats/Measurements/MeasurementLong.cs index f77ead2b068..22908dc53f6 100644 --- a/src/OpenTelemetry/Stats/Measurements/MeasurementLong.cs +++ b/src/OpenTelemetry/Stats/Measurements/MeasurementLong.cs @@ -46,9 +46,10 @@ public override T Match(Func p0, Func public override string ToString() { - return "MeasurementLong{" - + "measure=" + this.Measure + ", " - + "value=" + this.Value + return nameof(MeasurementLong) + + "{" + + nameof(this.Measure) + "=" + this.Measure + ", " + + nameof(this.Value) + "=" + this.Value + "}"; } diff --git a/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs b/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs index 171d1df8baf..2ef5d905072 100644 --- a/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs +++ b/src/OpenTelemetry/Stats/Measures/MeasureDouble.cs @@ -57,14 +57,15 @@ public override T Match(Func p0, Func p1, /// public override string ToString() { - return "MeasureDouble{" - + "name=" + this.Name + ", " - + "description=" + this.Description + ", " - + "unit=" + this.Unit + return nameof(MeasureDouble) + + "{" + + nameof(this.Name) + "=" + this.Name + ", " + + nameof(this.Description) + "=" + this.Description + ", " + + nameof(this.Unit) + "=" + this.Unit + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) diff --git a/src/OpenTelemetry/Stats/Measures/MeasureLong.cs b/src/OpenTelemetry/Stats/Measures/MeasureLong.cs index cdcac40ed59..0e6ad6a69d3 100644 --- a/src/OpenTelemetry/Stats/Measures/MeasureLong.cs +++ b/src/OpenTelemetry/Stats/Measures/MeasureLong.cs @@ -57,14 +57,15 @@ public override T Match(Func p0, Func p1, /// public override string ToString() { - return "MeasureLong{" - + "name=" + this.Name + ", " - + "description=" + this.Description + ", " - + "unit=" + this.Unit + return nameof(MeasureLong) + + "{" + + nameof(this.Name) + "=" + this.Name + ", " + + nameof(this.Description) + "=" + this.Description + ", " + + nameof(this.Unit) + "=" + this.Unit + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) diff --git a/src/OpenTelemetry/Stats/View.cs b/src/OpenTelemetry/Stats/View.cs index a06a7862f53..8bcf753d987 100644 --- a/src/OpenTelemetry/Stats/View.cs +++ b/src/OpenTelemetry/Stats/View.cs @@ -61,16 +61,17 @@ public static IView Create(IViewName name, string description, IMeasure measure, /// public override string ToString() { - return "View{" - + "name=" + this.Name + ", " - + "description=" + this.Description + ", " - + "measure=" + this.Measure + ", " - + "aggregation=" + this.Aggregation + ", " - + "columns=" + this.Columns + ", " + return nameof(View) + + "{" + + nameof(this.Name) + "=" + this.Name + ", " + + nameof(this.Description) + "=" + this.Description + ", " + + nameof(this.Measure) + "=" + this.Measure + ", " + + nameof(this.Aggregation) + "=" + this.Aggregation + ", " + + nameof(this.Columns) + "=" + this.Columns + ", " + "}"; } - /// + /// public override bool Equals(object o) { if (o == this) diff --git a/src/OpenTelemetry/Stats/ViewData.cs b/src/OpenTelemetry/Stats/ViewData.cs index 39223bfb2c7..031bfc9ba17 100644 --- a/src/OpenTelemetry/Stats/ViewData.cs +++ b/src/OpenTelemetry/Stats/ViewData.cs @@ -61,12 +61,13 @@ public static IViewData Create(IView view, IDictionary public override string ToString() { - return "ViewData{" - + "view=" + this.View + ", " - + "aggregationMap=" + string.Join(", ", this.AggregationMap.Select(kvp => $"{kvp.Key} = {kvp.Value}")) + ", " - + "start=" + this.Start + ", " - + "end=" + this.End - + "}"; + return nameof(ViewData) + + "{" + + nameof(this.View) + "=" + this.View + ", " + + nameof(this.AggregationMap) + "=" + string.Join(", ", this.AggregationMap.Select(kvp => (kvp.Key + " = " + kvp.Value))) + ", " + + nameof(this.Start) + "=" + this.Start + ", " + + nameof(this.End) + "=" + this.End + + "}"; } /// diff --git a/src/OpenTelemetry/Stats/ViewName.cs b/src/OpenTelemetry/Stats/ViewName.cs index 0dcff6e15a2..9f0e72918ee 100644 --- a/src/OpenTelemetry/Stats/ViewName.cs +++ b/src/OpenTelemetry/Stats/ViewName.cs @@ -51,8 +51,9 @@ public static IViewName Create(string name) /// public override string ToString() { - return "Name{" - + "asString=" + this.AsString + return nameof(ViewName) + + "{" + + nameof(this.AsString) + "=" + this.AsString + "}"; } diff --git a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs index 06a13a0322f..11ffbd1ce52 100644 --- a/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs +++ b/src/OpenTelemetry/Trace/Sampler/ProbabilitySampler.cs @@ -102,9 +102,10 @@ public bool ShouldSample(SpanContext parentContext, ActivityTraceId traceId, Act /// public override string ToString() { - return "ProbabilitySampler{" - + "probability=" + this.Probability + ", " - + "idUpperBound=" + this.IdUpperBound + return nameof(ProbabilitySampler) + + "{" + + nameof(this.Probability) + "=" + this.Probability + ", " + + nameof(this.IdUpperBound) + "=" + this.IdUpperBound + "}"; } From d053e7506e7fa6e3ca4a9e90f6672d7f3929d08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Neum=C3=BCller?= Date: Tue, 23 Jul 2019 18:42:55 +0200 Subject: [PATCH 22/41] Add LoggingTracer sample (#92) * move and rename "Samples" project to "samples\Exporters" * add "LoggingTracer" as an example of an API implementation * add readme to solution file * remove Samples project from solution * fix scoping * add "LoggingTracer" as an example of an API implementation * add readme to solution file * fix scoping * changed back to 2.1. was an accidental change. * added "Demo" to project names * adapted LoggingTracer to API changes. stripped down asp.net core example to bare minimum. * cleaned up LoggingTracer sample. not more NotImplementedExceptions, adhere to code style better (usings), don't log getters * consistency fixes * made console sample async, code style * adapt to API changes --- OpenTelemetry.sln | 27 ++++ .../LoggingTracer.Demo.AspNetCore.csproj | 20 +++ .../LoggingTracerExtensions.cs | 29 ++++ .../LoggingTracer.Demo.AspNetCore/Program.cs | 17 +++ .../LoggingTracer.Demo.AspNetCore/Startup.cs | 30 ++++ .../appsettings.Development.json | 9 ++ .../appsettings.json | 10 ++ .../LoggingTracer.Demo.ConsoleApp.csproj | 12 ++ .../LoggingTracer.Demo.ConsoleApp/Program.cs | 31 ++++ samples/LoggingTracer/LoggingTracer/Logger.cs | 30 ++++ .../LoggingTracer/LoggingBinaryFormat.cs | 35 +++++ .../LoggingTracer/LoggingScope.cs | 45 ++++++ .../LoggingTracer/LoggingSpan.cs | 89 ++++++++++++ .../LoggingTracer/LoggingSpanBuilder.cs | 133 ++++++++++++++++++ .../LoggingTracer/LoggingTextFormat.cs | 23 +++ .../LoggingTracer/LoggingTracer.cs | 44 ++++++ .../LoggingTracer/LoggingTracer.csproj | 11 ++ samples/LoggingTracer/readme.md | 6 + 18 files changed, 601 insertions(+) create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Program.cs create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Startup.cs create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.Development.json create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.json create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj create mode 100644 samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs create mode 100644 samples/LoggingTracer/LoggingTracer/Logger.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingBinaryFormat.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingScope.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingSpan.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingSpanBuilder.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingTextFormat.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingTracer.cs create mode 100644 samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj create mode 100644 samples/LoggingTracer/readme.md diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 0c5e72f5ea6..b76e95f5904 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -69,6 +69,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E359 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exporters", "samples\Exporters\Exporters.csproj", "{6EC9DEC9-086F-4F29-BF3F-5FC7253829D5}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LoggingTracer", "LoggingTracer", "{D9C14CDA-5182-4DEA-8606-98FF1A388BD3}" + ProjectSection(SolutionItems) = preProject + samples\LoggingTracer\readme.md = samples\LoggingTracer\readme.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer", "samples\LoggingTracer\LoggingTracer\LoggingTracer.csproj", "{1EEF77DF-7552-4265-B64C-FA13BC40C256}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer.Demo.ConsoleApp", "samples\LoggingTracer\LoggingTracer.Demo.ConsoleApp\LoggingTracer.Demo.ConsoleApp.csproj", "{607B3861-4D69-43EF-84CE-19F18CD5339A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer.Demo.AspNetCore", "samples\LoggingTracer\LoggingTracer.Demo.AspNetCore\LoggingTracer.Demo.AspNetCore.csproj", "{1EB74FCE-55C5-476A-8BB0-C46B77FE1070}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -147,6 +158,18 @@ Global {6EC9DEC9-086F-4F29-BF3F-5FC7253829D5}.Debug|Any CPU.Build.0 = Debug|Any CPU {6EC9DEC9-086F-4F29-BF3F-5FC7253829D5}.Release|Any CPU.ActiveCfg = Release|Any CPU {6EC9DEC9-086F-4F29-BF3F-5FC7253829D5}.Release|Any CPU.Build.0 = Release|Any CPU + {1EEF77DF-7552-4265-B64C-FA13BC40C256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EEF77DF-7552-4265-B64C-FA13BC40C256}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EEF77DF-7552-4265-B64C-FA13BC40C256}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EEF77DF-7552-4265-B64C-FA13BC40C256}.Release|Any CPU.Build.0 = Release|Any CPU + {607B3861-4D69-43EF-84CE-19F18CD5339A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {607B3861-4D69-43EF-84CE-19F18CD5339A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {607B3861-4D69-43EF-84CE-19F18CD5339A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {607B3861-4D69-43EF-84CE-19F18CD5339A}.Release|Any CPU.Build.0 = Release|Any CPU + {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -155,6 +178,10 @@ Global {7CB2F02E-03FA-4FFF-89A5-C51F107623FD} = {61188153-47FB-4567-AC9B-79B2435853EB} {F2F81E76-6A0E-466B-B673-EBBF1A9ED075} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F} {6EC9DEC9-086F-4F29-BF3F-5FC7253829D5} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} + {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} + {1EEF77DF-7552-4265-B64C-FA13BC40C256} = {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} + {607B3861-4D69-43EF-84CE-19F18CD5339A} = {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} + {1EB74FCE-55C5-476A-8BB0-C46B77FE1070} = {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj new file mode 100644 index 00000000000..0196370d0e9 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.2 + InProcess + + + + + + + + + + + + + + + diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs new file mode 100644 index 00000000000..27e129078fd --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracerExtensions.cs @@ -0,0 +1,29 @@ +namespace LoggingTracer.Demo.AspNetCore +{ + using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.DependencyInjection; + using OpenTelemetry.Collector.AspNetCore; + using OpenTelemetry.Collector.Dependencies; + using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Sampler; + + static class LoggingTracerExtensions { + internal static void AddLoggingTracer(this IServiceCollection services) + { + services.AddSingleton(new global::LoggingTracer.LoggingTracer()); + + services.AddSingleton(Samplers.AlwaysSample); + services.AddSingleton(new RequestsCollectorOptions()); + services.AddSingleton(); + + services.AddSingleton(new DependenciesCollectorOptions()); + services.AddSingleton(); + } + + internal static void UseLoggingTracer(this IApplicationBuilder app) + { + app.ApplicationServices.GetService(); // get it instantiated + app.ApplicationServices.GetService(); // get it instantiated + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Program.cs b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Program.cs new file mode 100644 index 00000000000..a190e76536b --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Program.cs @@ -0,0 +1,17 @@ +namespace LoggingTracer.Demo.AspNetCore +{ + using Microsoft.AspNetCore; + using Microsoft.AspNetCore.Hosting; + + public class Program + { + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Startup.cs b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Startup.cs new file mode 100644 index 00000000000..d2e52cb7f7c --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/Startup.cs @@ -0,0 +1,30 @@ +namespace LoggingTracer.Demo.AspNetCore +{ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.DependencyInjection; + + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddLoggingTracer(); + } + + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseLoggingTracer(); + + app.Run(async (context) => + { + await context.Response.WriteAsync("Hello World!"); + }); + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.Development.json b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.Development.json new file mode 100644 index 00000000000..e203e9407e7 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.json b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.json new file mode 100644 index 00000000000..d9d9a9bff6f --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj new file mode 100644 index 00000000000..0071f95514d --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp2.2 + + + + + + + diff --git a/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs new file mode 100644 index 00000000000..c546dfdfa94 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/Program.cs @@ -0,0 +1,31 @@ +namespace LoggingTracer.ConsoleApp +{ + using System.Threading; + using System.Threading.Tasks; + using OpenTelemetry.Trace; + + public class Program + { + private static ITracer tracer = new LoggingTracer(); + + public static async Task Main(string[] args) + { + var builder = tracer.SpanBuilder("Main (span1)"); + using (tracer.WithSpan(builder.StartSpan())) + { + await Task.Delay(100); + await Foo(); + } + } + + private static async Task Foo() + { + var builder = tracer.SpanBuilder("Foo (span2)"); + using (tracer.WithSpan(builder.StartSpan())) + { + tracer.CurrentSpan.SetAttribute("myattribute", "mvalue"); + await Task.Delay(100); + } + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/Logger.cs b/samples/LoggingTracer/LoggingTracer/Logger.cs new file mode 100644 index 00000000000..d1fdfe573be --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/Logger.cs @@ -0,0 +1,30 @@ +namespace LoggingTracer +{ + using System; + using System.Threading; + + public static class Logger + { + private static DateTime startTime = DateTime.UtcNow; + + static Logger() + { + PrintHeader(); + } + + public static void PrintHeader() + { + Console.WriteLine("MsSinceStart | ThreadId | API"); + } + + public static void Log(string s) + { + Console.WriteLine($"{MillisSinceStart(),12} | {Thread.CurrentThread.ManagedThreadId,8} | {s}"); + } + + private static int MillisSinceStart() + { + return (int)DateTime.UtcNow.Subtract(startTime).TotalMilliseconds; + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingBinaryFormat.cs b/samples/LoggingTracer/LoggingTracer/LoggingBinaryFormat.cs new file mode 100644 index 00000000000..ccc5bd70db4 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingBinaryFormat.cs @@ -0,0 +1,35 @@ +namespace LoggingTracer +{ + using System; + using System.Collections.Generic; + using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Trace; + + public sealed class LoggingBinaryFormat : IBinaryFormat + { + public ISet Fields => null; + + public SpanContext Extract(T carrier, Func> getter) + { + Logger.Log($"LoggingBinaryFormat.Extract(...)"); + return SpanContext.Blank; + } + + public SpanContext FromByteArray(byte[] bytes) + { + Logger.Log($"LoggingBinaryFormat.FromByteArray(...)"); + return SpanContext.Blank; + } + + public void Inject(SpanContext spanContext, T carrier, Action setter) + { + Logger.Log($"LoggingBinaryFormat.Inject({spanContext}, ...)"); + } + + public byte[] ToByteArray(SpanContext spanContext) + { + Logger.Log($"LoggingBinaryFormat.ToByteArray({spanContext})"); + return new byte[0]; + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingScope.cs b/samples/LoggingTracer/LoggingTracer/LoggingScope.cs new file mode 100644 index 00000000000..835e265900d --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingScope.cs @@ -0,0 +1,45 @@ +namespace LoggingTracer +{ + using System.Threading; + using OpenTelemetry.Context; + using OpenTelemetry.Trace; + + public static class CurrentSpanUtils + { + private static AsyncLocal asyncLocalContext = new AsyncLocal(); + + public static ISpan CurrentSpan => asyncLocalContext.Value; + + public class LoggingScope : IScope + { + private readonly ISpan origContext; + private readonly ISpan span; + private readonly bool endSpan; + + public LoggingScope(ISpan span, bool endSpan = true) + { + this.span = span; + this.endSpan = endSpan; + this.origContext = CurrentSpanUtils.asyncLocalContext.Value; + CurrentSpanUtils.asyncLocalContext.Value = span; + } + + public void Dispose() + { + Logger.Log($"Scope.Dispose"); + var current = asyncLocalContext.Value; + asyncLocalContext.Value = this.origContext; + + if (current != this.origContext) + { + Logger.Log($"Scope.Dispose: current != this.origContext"); + } + + if (this.endSpan) + { + this.span.End(); + } + } + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingSpan.cs b/samples/LoggingTracer/LoggingTracer/LoggingSpan.cs new file mode 100644 index 00000000000..5a2aae4e384 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingSpan.cs @@ -0,0 +1,89 @@ +namespace LoggingTracer +{ + using System.Collections.Generic; + using OpenTelemetry.Trace; + + public class LoggingSpan : ISpan + { + public string Name { get; set; } + + public SpanContext Context { get; set; } + + public Status Status { get; set; } + + public SpanKind? Kind { get; set; } + + public bool HasEnded { get; set; } + + public bool IsRecordingEvents => true; + + public LoggingSpan(string name, SpanKind kind) + { + Logger.Log($"Span.ctor({name}, {kind})"); + this.Name = name; + this.Kind = kind; + } + + public void AddEvent(string name) + { + Logger.Log($"Span.AddEvent({name})"); + } + + public void AddEvent(string name, IDictionary attributes) + { + Logger.Log($"Span.AddEvent({name}, attributes: {attributes.Count})"); + } + + public void AddEvent(IEvent newEvent) + { + Logger.Log($"Span.AddEvent({newEvent})"); + } + + public void AddLink(ILink link) + { + Logger.Log($"Span.AddLink({link})"); + } + + public void End() + { + Logger.Log($"Span.End, Name: {this.Name}"); + } + + public void SetAttribute(string key, object value) + { + Logger.Log($"Span.SetAttribute({key}, {value})"); + } + + public void SetAttribute(string key, string value) + { + Logger.Log($"Span.SetAttribute({key}, {value})"); + } + + public void SetAttribute(string key, long value) + { + Logger.Log($"Span.SetAttribute({key}, {value})"); + } + + public void SetAttribute(string key, double value) + { + Logger.Log($"Span.SetAttribute({key}, {value})"); + } + + public void SetAttribute(string key, bool value) + { + Logger.Log($"Span.SetAttribute({key}, {value})"); + } + + public void SetAttribute(KeyValuePair keyValuePair) + { + Logger.Log($"Span.SetAttributes(attributes: {keyValuePair})"); + this.SetAttribute(keyValuePair.Key, keyValuePair.Value); + } + + public void UpdateName(string name) + { + Logger.Log($"Span.UpdateName({name})"); + this.Name = name; + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingSpanBuilder.cs b/samples/LoggingTracer/LoggingTracer/LoggingSpanBuilder.cs new file mode 100644 index 00000000000..40aae40f94e --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingSpanBuilder.cs @@ -0,0 +1,133 @@ +namespace LoggingTracer +{ + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using OpenTelemetry.Context; + using OpenTelemetry.Trace; + + public class LoggingSpanBuilder : ISpanBuilder + { + private string spanName; + private SpanKind spanKind; + private ISpan parent; + private SpanContext remoteParentSpanContext; + private ISpan span; + + public LoggingSpanBuilder(string spanName, SpanKind spanKind) + { + Logger.Log($"SpanBuilder.ctor({spanName})"); + this.spanName = spanName; + this.spanKind = spanKind; + this.span = new LoggingSpan(spanName, spanKind); + } + + public LoggingSpanBuilder(string spanName, SpanKind spanKind, ISpan parent) : this(spanName, spanKind) + { + Logger.Log($"SpanBuilder.ctor({spanName}, {spanKind}, {parent})"); + this.parent = parent; + } + + public LoggingSpanBuilder(string spanName, SpanKind spanKind, SpanContext remoteParentSpanContext) : this(spanName, spanKind) + { + Logger.Log($"SpanBuilder.ctor({spanName}, {spanKind}, {remoteParentSpanContext})"); + this.remoteParentSpanContext = remoteParentSpanContext; + } + + public ISpanBuilder AddLink(SpanContext spanContext) + { + Logger.Log($"SpanBuilder.AddLink({spanContext})"); + return this; + } + + public ISpanBuilder AddLink(Activity activity) + { + Logger.Log($"SpanBuilder.AddLink({activity})"); + return this; + } + + public ISpanBuilder AddLink(ILink link) + { + Logger.Log($"SpanBuilder.AddLink({link})"); + return this; + } + + public ISpanBuilder AddLink(SpanContext context, IDictionary attributes) + { + Logger.Log($"SpanBuilder.AddLink({context}, {attributes.Count})"); + return this; + } + + public ISpanBuilder SetCreateChild(bool createChild) + { + Logger.Log($"SpanBuilder.SetCreateChild({createChild})"); + return this; + } + + public ISpanBuilder SetNoParent() + { + Logger.Log($"SpanBuilder.SetNoParent()"); + return this; + } + + public ISpanBuilder SetParent(ISpan parent) + { + Logger.Log($"SpanBuilder.SetParent({parent})"); + return this; + } + + public ISpanBuilder SetParent(Activity parent) + { + Logger.Log($"SpanBuilder.SetParent({parent})"); + return this; + } + + public ISpanBuilder SetParent(SpanContext remoteParent) + { + Logger.Log($"SpanBuilder.SetParent({remoteParent})"); + return this; + } + + public ISpanBuilder SetParentLinks(IEnumerable parentLinks) + { + Logger.Log($"SpanBuilder.SetParentLinks(parentLinks: {parentLinks.Count()})"); + return this; + } + + public ISpanBuilder SetRecordEvents(bool recordEvents) + { + Logger.Log($"SpanBuilder.SetRecordEvents({recordEvents})"); + return this; + } + + public ISpanBuilder SetSampler(ISampler sampler) + { + Logger.Log($"SpanBuilder.SetSampler({sampler})"); + return this; + } + + public ISpanBuilder SetSpanKind(SpanKind spanKind) + { + Logger.Log($"SpanBuilder.SetSpanKind({spanKind})"); + return this; + } + + public IScope StartScopedSpan() + { + Logger.Log($"SpanBuilder.StartScopedSpan()"); + return new CurrentSpanUtils.LoggingScope(this.span); + } + + public IScope StartScopedSpan(out ISpan currentSpan) + { + Logger.Log($"SpanBuilder.StartScopedSpan()"); + return new CurrentSpanUtils.LoggingScope(currentSpan = this.span); + } + + public ISpan StartSpan() + { + Logger.Log($"SpanBuilder.StartSpan()"); + return this.span; + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTextFormat.cs b/samples/LoggingTracer/LoggingTracer/LoggingTextFormat.cs new file mode 100644 index 00000000000..66a0a77ccdc --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingTextFormat.cs @@ -0,0 +1,23 @@ +namespace LoggingTracer +{ + using System; + using System.Collections.Generic; + using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Trace; + + public sealed class LoggingTextFormat : ITextFormat + { + public ISet Fields => null; + + public SpanContext Extract(T carrier, Func> getter) + { + Logger.Log($"LoggingTextFormat.Extract(...)"); + return SpanContext.Blank; + } + + public void Inject(SpanContext spanContext, T carrier, Action setter) + { + Logger.Log($"LoggingTextFormat.Inject({spanContext}, ...)"); + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs b/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs new file mode 100644 index 00000000000..5ba6ea108d6 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracer.cs @@ -0,0 +1,44 @@ +namespace LoggingTracer +{ + using OpenTelemetry.Context; + using OpenTelemetry.Context.Propagation; + using OpenTelemetry.Trace; + + public class LoggingTracer : ITracer + { + public ISpan CurrentSpan => CurrentSpanUtils.CurrentSpan; + + public IBinaryFormat BinaryFormat => new LoggingBinaryFormat(); + + public ITextFormat TextFormat => new LoggingTextFormat(); + + public void RecordSpanData(SpanData span) + { + Logger.Log($"Tracer.RecordSpanData({span})"); + } + + public ISpanBuilder SpanBuilder(string spanName) + { + Logger.Log($"Tracer.SpanBuilder({spanName})"); + return new LoggingSpanBuilder(spanName, SpanKind.Internal); + } + + public ISpanBuilder SpanBuilderWithParent(string spanName, SpanKind spanKind = SpanKind.Internal, ISpan parent = null) + { + Logger.Log($"Tracer.SpanBuilderWithExplicitParent({spanName}, {spanKind}, {parent})"); + return new LoggingSpanBuilder(spanName, spanKind, parent); + } + + public ISpanBuilder SpanBuilderWithParentContext(string spanName, SpanKind spanKind = SpanKind.Internal, SpanContext remoteParentSpanContext = null) + { + Logger.Log($"Tracer.SpanBuilderWithRemoteParent"); + return new LoggingSpanBuilder(spanName, spanKind, remoteParentSpanContext); + } + + public IScope WithSpan(ISpan span) + { + Logger.Log($"Tracer.WithSpan"); + return new CurrentSpanUtils.LoggingScope(span); + } + } +} diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj b/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj new file mode 100644 index 00000000000..587c124f279 --- /dev/null +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/samples/LoggingTracer/readme.md b/samples/LoggingTracer/readme.md new file mode 100644 index 00000000000..53207416ff1 --- /dev/null +++ b/samples/LoggingTracer/readme.md @@ -0,0 +1,6 @@ +# LoggingTracer + +This is supposed to be a super-simple API implementation that helps to understand OpenTelemetry API layer. It is not a functional tracer in the sense that it creates meaningful spans. It just logs API calls. + +It basically just logs every single API call, with thread-id and a time-offset since start. + From 4b0b2c29e7d4d65e116b45faa7bb6b30d8c8c4b8 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 23 Jul 2019 19:13:26 -0700 Subject: [PATCH 23/41] Disable code coverage in CI: reportgenerator does not work (#159) --- build/Common.test.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Common.test.props b/build/Common.test.props index 7e003529ee2..182a5a4f7f9 100644 --- a/build/Common.test.props +++ b/build/Common.test.props @@ -26,7 +26,7 @@ true - true + From 8e1d8fa47e750b75a5437a5b7519661cfc4b2b48 Mon Sep 17 00:00:00 2001 From: PS-EGHornbostel Date: Tue, 23 Jul 2019 19:47:52 -0700 Subject: [PATCH 24/41] Jaeger exporter implementation (#132) * Fix visual studio dotnet core build task * Added CNCF Jaeger exporter support https://github.com/open-telemetry/opentelemetry-dotnet/issues/77 * possible fix for win32 build issue. * Fix windows build by adding Thrift source * Fix yet more windows build issues. * fix another style issue. * fix reference to System.Net.Http * remove unnecessary conditional framework reference. * Update lib/Thrift/Transports/Client/TStreamClientTransport.cs Co-Authored-By: Bruno Garcia * Update lib/Thrift/Transports/Client/TStreamClientTransport.cs Co-Authored-By: Bruno Garcia * Added the conditional for netstandard2.0 * remove IDisposable TODO comments. * Update src/OpenTelemetry.Exporter.Jaeger/Implimentation/EmitBatchArgs.cs Co-Authored-By: Bruno Garcia * Add readme with thrift fork info. * cleanup after merge. * WIP remove thrift code * Use prepackaged Apache Thrift assembly * wrap EmitBatch * Revert "wrap EmitBatch " This reverts commit 9aaa1388ba423c5c564434fc88d26409c598419b. * Revert "Use prepackaged Apache Thrift assembly" This reverts commit fa5fbd8e6c2b197641503b978bcc5f51421805f2. * Revert "Use prepackaged Apache Thrift assembly" This reverts commit fa5fbd8e6c2b197641503b978bcc5f51421805f2. * Revert "WIP remove thrift code" This reverts commit bbbcf470e8cbdc4d81b6350455db81da4d72cbd3. * Add missing ConfigureAwait(false) to Thrift async calls. * Added Thrift fork differences to README.md * WIP Jaeger Unit tests * Fix build after merge. * WIP Jaeger Unit tests - Span conversion to Jaeger Thrift format * WIP Jaeger Unit tests - Span conversion to Jaeger Thrift format - cleanup * Clean up merge issues * WIP * WIP cleanup * more testing WIP * use pattern matching for attribute conversion * WIP cleanup after timestamp removal. * WIP * WIP UDP integration test * Update src/OpenTelemetry.Exporter.Jaeger/Implimentation/Batch.cs Co-Authored-By: Bruno Garcia * remove solution-explorer * add to gitignore * refactored List to IEnumerable * Fix unit test bug * Add integration test * cleanup * fix unix epoch conversion * Update Thrift expected payload in unit test. * fix build issues * fix typo * fix solution --- .gitignore | 1 + .vscode/launch.json | 14 + .vscode/tasks.json | 6 +- CHANGELOG.md | 1 + Directory.Build.targets | 2 +- OpenTelemetry.sln | 13 +- README.md | 38 + lib/Directory.Build.props | 8 + lib/Directory.Build.targets | 10 + lib/Thrift/Collections/TCollections.cs | 101 ++ lib/Thrift/Collections/THashSet.cs | 67 ++ lib/Thrift/ITAsyncProcessor.cs | 29 + lib/Thrift/ITProcessorFactory.cs | 28 + lib/Thrift/Protocols/Entities/TField.cs | 37 + lib/Thrift/Protocols/Entities/TList.cs | 33 + lib/Thrift/Protocols/Entities/TMap.cs | 36 + lib/Thrift/Protocols/Entities/TMessage.cs | 37 + lib/Thrift/Protocols/Entities/TMessageType.cs | 28 + lib/Thrift/Protocols/Entities/TSet.cs | 38 + lib/Thrift/Protocols/Entities/TStruct.cs | 30 + lib/Thrift/Protocols/Entities/TType.cs | 37 + lib/Thrift/Protocols/ITProtocolFactory.cs | 27 + lib/Thrift/Protocols/TAbstractBase.cs | 28 + lib/Thrift/Protocols/TBase.cs | 28 + lib/Thrift/Protocols/TBinaryProtocol.cs | 613 +++++++++++ lib/Thrift/Protocols/TCompactProtocol.cs | 922 ++++++++++++++++ lib/Thrift/Protocols/TJSONProtocol.cs | 981 ++++++++++++++++++ lib/Thrift/Protocols/TMultiplexedProtocol.cs | 91 ++ lib/Thrift/Protocols/TProtocol.cs | 376 +++++++ lib/Thrift/Protocols/TProtocolDecorator.cs | 247 +++++ lib/Thrift/Protocols/TProtocolException.cs | 59 ++ .../Protocols/Utilities/TBase64Helper.cs | 101 ++ .../Protocols/Utilities/TBase64Utils.cs | 101 ++ .../Utilities/TJsonProtocolConstants.cs | 61 ++ .../Utilities/TJsonProtocolHelper.cs | 176 ++++ .../Protocols/Utilities/TProtocolUtil.cs | 110 ++ lib/Thrift/README.md | 12 + lib/Thrift/Server/TBaseServer.cs | 75 ++ lib/Thrift/Server/TServerEventHandler.cs | 54 + lib/Thrift/Settings.Stylecop | 5 + lib/Thrift/SingletonTProcessorFactory.cs | 38 + lib/Thrift/TApplicationException.cs | 150 +++ lib/Thrift/TBaseClient.cs | 91 ++ lib/Thrift/TException.cs | 34 + lib/Thrift/TMultiplexedProcessor.cs | 143 +++ lib/Thrift/Thrift.csproj | 17 + .../Client/TBufferedClientTransport.cs | 206 ++++ .../Client/TFramedClientTransport.cs | 201 ++++ .../Transports/Client/THttpClientTransport.cs | 235 +++++ .../Client/TMemoryBufferClientTransport.cs | 97 ++ .../Client/TNamedPipeClientTransport.cs | 95 ++ .../Client/TSocketClientTransport.cs | 139 +++ .../Client/TStreamClientTransport.cs | 110 ++ .../Client/TTlsSocketClientTransport.cs | 237 +++++ .../Server/TNamedPipeServerTransport.cs | 191 ++++ .../Server/TServerFramedTransport.cs | 150 +++ .../Server/TServerSocketTransport.cs | 174 ++++ .../Server/TTlsServerSocketTransport.cs | 177 ++++ lib/Thrift/Transports/TClientTransport.cs | 179 ++++ lib/Thrift/Transports/TServerTransport.cs | 54 + lib/Thrift/Transports/TTransportException.cs | 58 ++ lib/Thrift/Transports/TTransportFactory.cs | 35 + samples/Exporters/Exporters.csproj | 1 + samples/Exporters/Program.cs | 13 +- samples/Exporters/TestJaeger.cs | 103 ++ .../Implementation/Batch.cs | 103 ++ .../Implementation/EmitBatchArgs.cs | 78 ++ .../Implementation/IJaegerUdpBatcher.cs | 31 + .../Implementation/IJaegerUdpClient.cs | 35 + .../Implementation/InMemoryTransport.cs | 90 ++ .../Implementation/Int128.cs | 53 + .../JaegerConversionExtensions.cs | 145 +++ .../Implementation/JaegerExporterException.cs | 28 + .../Implementation/JaegerLog.cs | 101 ++ .../Implementation/JaegerSpan.cs | 255 +++++ .../Implementation/JaegerSpanRef.cs | 119 +++ .../Implementation/JaegerSpanRefType.cs | 36 + .../Implementation/JaegerTag.cs | 180 ++++ .../Implementation/JaegerTagType.cs | 51 + .../Implementation/JaegerThriftClient.cs | 50 + .../JaegerThriftClientTransport.cs | 113 ++ .../JaegerTraceExporterHandler.cs | 75 ++ .../Implementation/JaegerUdpBatcher.cs | 156 +++ .../Implementation/JaegerUdpClient.cs | 45 + .../Implementation/Process.cs | 116 +++ .../JaegerExporter.cs | 128 +++ .../JaegerExporterOptions.cs | 34 + .../OpenTelemetry.Exporter.Jaeger.csproj | 16 + .../Implementation/JaegerSpanConverterTest.cs | 539 ++++++++++ .../JaegerThriftIntegrationTest.cs | 132 +++ .../ThriftUdpClientTransportTests.cs | 167 +++ ...OpenTelemetry.Exporter.Jaeger.Tests.csproj | 31 + .../xunit.runner.json | 4 + 93 files changed, 10496 insertions(+), 4 deletions(-) create mode 100644 lib/Directory.Build.props create mode 100644 lib/Directory.Build.targets create mode 100644 lib/Thrift/Collections/TCollections.cs create mode 100644 lib/Thrift/Collections/THashSet.cs create mode 100644 lib/Thrift/ITAsyncProcessor.cs create mode 100644 lib/Thrift/ITProcessorFactory.cs create mode 100644 lib/Thrift/Protocols/Entities/TField.cs create mode 100644 lib/Thrift/Protocols/Entities/TList.cs create mode 100644 lib/Thrift/Protocols/Entities/TMap.cs create mode 100644 lib/Thrift/Protocols/Entities/TMessage.cs create mode 100644 lib/Thrift/Protocols/Entities/TMessageType.cs create mode 100644 lib/Thrift/Protocols/Entities/TSet.cs create mode 100644 lib/Thrift/Protocols/Entities/TStruct.cs create mode 100644 lib/Thrift/Protocols/Entities/TType.cs create mode 100644 lib/Thrift/Protocols/ITProtocolFactory.cs create mode 100644 lib/Thrift/Protocols/TAbstractBase.cs create mode 100644 lib/Thrift/Protocols/TBase.cs create mode 100644 lib/Thrift/Protocols/TBinaryProtocol.cs create mode 100644 lib/Thrift/Protocols/TCompactProtocol.cs create mode 100644 lib/Thrift/Protocols/TJSONProtocol.cs create mode 100644 lib/Thrift/Protocols/TMultiplexedProtocol.cs create mode 100644 lib/Thrift/Protocols/TProtocol.cs create mode 100644 lib/Thrift/Protocols/TProtocolDecorator.cs create mode 100644 lib/Thrift/Protocols/TProtocolException.cs create mode 100644 lib/Thrift/Protocols/Utilities/TBase64Helper.cs create mode 100644 lib/Thrift/Protocols/Utilities/TBase64Utils.cs create mode 100644 lib/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs create mode 100644 lib/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs create mode 100644 lib/Thrift/Protocols/Utilities/TProtocolUtil.cs create mode 100644 lib/Thrift/README.md create mode 100644 lib/Thrift/Server/TBaseServer.cs create mode 100644 lib/Thrift/Server/TServerEventHandler.cs create mode 100644 lib/Thrift/Settings.Stylecop create mode 100644 lib/Thrift/SingletonTProcessorFactory.cs create mode 100644 lib/Thrift/TApplicationException.cs create mode 100644 lib/Thrift/TBaseClient.cs create mode 100644 lib/Thrift/TException.cs create mode 100644 lib/Thrift/TMultiplexedProcessor.cs create mode 100644 lib/Thrift/Thrift.csproj create mode 100644 lib/Thrift/Transports/Client/TBufferedClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/TFramedClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/THttpClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/TMemoryBufferClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/TNamedPipeClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/TSocketClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/TStreamClientTransport.cs create mode 100644 lib/Thrift/Transports/Client/TTlsSocketClientTransport.cs create mode 100644 lib/Thrift/Transports/Server/TNamedPipeServerTransport.cs create mode 100644 lib/Thrift/Transports/Server/TServerFramedTransport.cs create mode 100644 lib/Thrift/Transports/Server/TServerSocketTransport.cs create mode 100644 lib/Thrift/Transports/Server/TTlsServerSocketTransport.cs create mode 100644 lib/Thrift/Transports/TClientTransport.cs create mode 100644 lib/Thrift/Transports/TServerTransport.cs create mode 100644 lib/Thrift/Transports/TTransportException.cs create mode 100644 lib/Thrift/Transports/TTransportFactory.cs create mode 100644 samples/Exporters/TestJaeger.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/Batch.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/EmitBatchArgs.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpBatcher.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpClient.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/InMemoryTransport.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/Int128.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerConversionExtensions.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterException.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerLog.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpan.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRef.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRefType.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTag.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagType.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClient.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClientTransport.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTraceExporterHandler.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpBatcher.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpClient.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs create mode 100644 src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj create mode 100644 test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs create mode 100644 test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs create mode 100644 test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/ThriftUdpClientTransportTests.cs create mode 100644 test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj create mode 100644 test/OpenTelemetry.Exporter.Jaeger.Tests/xunit.runner.json diff --git a/.gitignore b/.gitignore index 3e759b75bf4..4d0f3d5af45 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.user *.userosscache *.sln.docstates +.vscode/solution-explorer # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/.vscode/launch.json b/.vscode/launch.json index ddbfc5fa664..571c85e3511 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,20 @@ "stopAtEntry": false, "internalConsoleOptions": "openOnSessionStart" }, + { + "name": "Jaeger Exporter Tests (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/test/OpenTelemetry.Exporter.Jaeger.Tests/bin/Debug/netcoreapp2.2/OpenTelemetry.Exporter.Jaeger.Tests.dll", + "args": [], + "cwd": "${workspaceFolder}/test/OpenTelemetry.Exporter.Jaeger.Tests", + // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window + "console": "internalConsole", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart" + }, { "name": ".NET Core Attach", "type": "coreclr", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a914fef1305..2d4663d57e2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,12 +5,16 @@ "tasks": [ { "label": "build", - "command": "dotnet build", + "command": "dotnet", "type": "shell", "group": "build", "presentation": { "reveal": "silent" }, + "args": [ + "build", + "/property:GenerateFullPaths=true" + ], "problemMatcher": "$msCompile" } ] diff --git a/CHANGELOG.md b/CHANGELOG.md index fdcdd85aa11..89157c48a2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ the release. 1. Modified the content of PrometheusExporterOptions from `Uri()` to `string`. 2. `HttpListener()` can support "+" as: hostname which listens on all ports. 3. Modified samples/TestPrometheus.cs to safely use the new implementation. + 4. Jaeger exporter implemented - Copy from [OpenCensus](http://github.com/census-instrumentation/opencensus-csharp) at diff --git a/Directory.Build.targets b/Directory.Build.targets index cff5023aa19..96d0176b091 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,6 +1,6 @@ - + All diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index b76e95f5904..ab2ac06e63f 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -80,6 +80,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer.Demo.ConsoleA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer.Demo.AspNetCore", "samples\LoggingTracer\LoggingTracer.Demo.AspNetCore\LoggingTracer.Demo.AspNetCore.csproj", "{1EB74FCE-55C5-476A-8BB0-C46B77FE1070}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Jaeger", "src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj", "{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Jaeger.Tests", "test\OpenTelemetry.Exporter.Jaeger.Tests\OpenTelemetry.Exporter.Jaeger.Tests.csproj", "{21E69213-72D5-453F-BD00-75EF36AC4965}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -170,12 +174,19 @@ Global {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Debug|Any CPU.Build.0 = Debug|Any CPU {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Release|Any CPU.ActiveCfg = Release|Any CPU {1EB74FCE-55C5-476A-8BB0-C46B77FE1070}.Release|Any CPU.Build.0 = Release|Any CPU + {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}.Release|Any CPU.Build.0 = Release|Any CPU + {21E69213-72D5-453F-BD00-75EF36AC4965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21E69213-72D5-453F-BD00-75EF36AC4965}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21E69213-72D5-453F-BD00-75EF36AC4965}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21E69213-72D5-453F-BD00-75EF36AC4965}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {7CB2F02E-03FA-4FFF-89A5-C51F107623FD} = {61188153-47FB-4567-AC9B-79B2435853EB} {F2F81E76-6A0E-466B-B673-EBBF1A9ED075} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F} {6EC9DEC9-086F-4F29-BF3F-5FC7253829D5} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E} diff --git a/README.md b/README.md index bdf4fc21b85..13f3ad55a26 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,42 @@ Outgoing http calls to Redis made usign StackExchange.Redis library can be autom ## OpenTelemetry QuickStart: exporting data +### Using the Jaeger exporter + +The Jaeger exporter communicates to a Jaeger Agent through the compact thrift protocol on +the Compact Thrift API port. You can configure the Jaeger exporter by following the directions below: + +1. [Get Jaeger][jaeger-get-started]. +2. Configure the `JaegerExporter` + - `ServiceName`: The name of your application or service. + - `AgengHost`: Usually `localhost` since an agent should + usually be running on the same machine as your application or service. + - `AgentPort`: The compact thrift protocol port of the Jaeger Agent (default `6831`) + - `MaxPacketSize`: The maximum size of each UDP packet that gets sent to the agent. (default `65000`) +3. See the [sample][jaeger-sample] for an example of how to use the exporter. + +``` csharp +var exporter = new JaegerExporter( + new JaegerExporterOptions + { + ServiceName = "tracing-to-jaeger-service", + AgentHost = host, + AgentPort = port, + }, + Tracing.ExportComponent); + +exporter.Start(); + +var span = tracer + .SpanBuilder("incoming request") + .SetSampler(Samplers.AlwaysSample) + .StartSpan(); + +Thread.Sleep(TimeSpan.FromSeconds(1)); +span.End(); +``` + + ### Using Zipkin exporter Configure Zipkin exporter to see traces in Zipkin UI. @@ -316,6 +352,7 @@ deprecate it for 18 months before removing it, if possible. [up-for-grabs-issues]: https://github.com/open-telemetry/OpenTelemetry-dotnet/issues?q=is%3Aissue+is%3Aopen+label%3Aup-for-grabs [good-first-issues]: https://github.com/open-telemetry/OpenTelemetry-dotnet/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22 [zipkin-get-started]: https://zipkin.io/pages/quickstart.html +[jaeger-get-started]: https://www.jaegertracing.io/docs/1.13/getting-started/ [ai-get-started]: https://docs.microsoft.com/azure/application-insights [stackdriver-trace-setup]: https://cloud.google.com/trace/docs/setup/ [stackdriver-monitoring-setup]: https://cloud.google.com/monitoring/api/enable-api @@ -326,6 +363,7 @@ deprecate it for 18 months before removing it, if possible. [ai-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestApplicationInsights.cs [stackdriver-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestStackdriver.cs [zipkin-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestZipkin.cs +[jaeger-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestJaeger.cs [prometheus-get-started]: https://prometheus.io/docs/introduction/first_steps/ [prometheus-sample]: https://github.com/open-telemetry/opentelemetry-dotnet/blob/master/samples/Exporters/TestPrometheus.cs diff --git a/lib/Directory.Build.props b/lib/Directory.Build.props new file mode 100644 index 00000000000..e3fa4661306 --- /dev/null +++ b/lib/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + True + + \ No newline at end of file diff --git a/lib/Directory.Build.targets b/lib/Directory.Build.targets new file mode 100644 index 00000000000..347a97078b1 --- /dev/null +++ b/lib/Directory.Build.targets @@ -0,0 +1,10 @@ + + + + + + all + runtime; build; native; contentfiles; analyzers + + + \ No newline at end of file diff --git a/lib/Thrift/Collections/TCollections.cs b/lib/Thrift/Collections/TCollections.cs new file mode 100644 index 00000000000..147bfc7d31c --- /dev/null +++ b/lib/Thrift/Collections/TCollections.cs @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Collections; + +namespace Thrift.Collections +{ + // ReSharper disable once InconsistentNaming + public class TCollections + { + /// + /// This will return true if the two collections are value-wise the same. + /// If the collection contains a collection, the collections will be compared using this method. + /// + public static bool Equals(IEnumerable first, IEnumerable second) + { + if (first == null && second == null) + { + return true; + } + + if (first == null || second == null) + { + return false; + } + + var fiter = first.GetEnumerator(); + var siter = second.GetEnumerator(); + + var fnext = fiter.MoveNext(); + var snext = siter.MoveNext(); + + while (fnext && snext) + { + var fenum = fiter.Current as IEnumerable; + var senum = siter.Current as IEnumerable; + + if (fenum != null && senum != null) + { + if (!Equals(fenum, senum)) + { + return false; + } + } + else if (fenum == null ^ senum == null) + { + return false; + } + else if (!Equals(fiter.Current, siter.Current)) + { + return false; + } + + fnext = fiter.MoveNext(); + snext = siter.MoveNext(); + } + + return fnext == snext; + } + + /// + /// This returns a hashcode based on the value of the enumerable. + /// + public static int GetHashCode(IEnumerable enumerable) + { + if (enumerable == null) + { + return 0; + } + + var hashcode = 0; + + foreach (var obj in enumerable) + { + var enum2 = obj as IEnumerable; + var objHash = enum2 == null ? obj.GetHashCode() : GetHashCode(enum2); + + unchecked + { + hashcode = (hashcode*397) ^ (objHash); + } + } + + return hashcode; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Collections/THashSet.cs b/lib/Thrift/Collections/THashSet.cs new file mode 100644 index 00000000000..011f0a0d629 --- /dev/null +++ b/lib/Thrift/Collections/THashSet.cs @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Collections; +using System.Collections.Generic; + +namespace Thrift.Collections +{ + // ReSharper disable once InconsistentNaming + public class THashSet : ICollection + { + private readonly HashSet _set = new HashSet(); + + public int Count => _set.Count; + + public bool IsReadOnly => false; + + public void Add(T item) + { + _set.Add(item); + } + + public void Clear() + { + _set.Clear(); + } + + public bool Contains(T item) + { + return _set.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + _set.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return _set.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable) _set).GetEnumerator(); + } + + public bool Remove(T item) + { + return _set.Remove(item); + } + } +} \ No newline at end of file diff --git a/lib/Thrift/ITAsyncProcessor.cs b/lib/Thrift/ITAsyncProcessor.cs new file mode 100644 index 00000000000..db8e40aefe8 --- /dev/null +++ b/lib/Thrift/ITAsyncProcessor.cs @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols; + +namespace Thrift +{ + public interface ITAsyncProcessor + { + Task ProcessAsync(TProtocol iprot, TProtocol oprot); + Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/Thrift/ITProcessorFactory.cs b/lib/Thrift/ITProcessorFactory.cs new file mode 100644 index 00000000000..5133e5c4801 --- /dev/null +++ b/lib/Thrift/ITProcessorFactory.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Server; +using Thrift.Transports; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public interface ITProcessorFactory + { + ITAsyncProcessor GetAsyncProcessor(TClientTransport trans, TBaseServer baseServer = null); + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TField.cs b/lib/Thrift/Protocols/Entities/TField.cs new file mode 100644 index 00000000000..d311535e73c --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TField.cs @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TField + { + public TField(string name, TType type, short id) + { + Name = name; + Type = type; + ID = id; + } + + public string Name { get; set; } + + public TType Type { get; set; } + + // ReSharper disable once InconsistentNaming - do not rename - it used for generation + public short ID { get; set; } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TList.cs b/lib/Thrift/Protocols/Entities/TList.cs new file mode 100644 index 00000000000..ce232207cba --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TList.cs @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TList + { + public TList(TType elementType, int count) + { + ElementType = elementType; + Count = count; + } + + public TType ElementType { get; set; } + + public int Count { get; set; } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TMap.cs b/lib/Thrift/Protocols/Entities/TMap.cs new file mode 100644 index 00000000000..9195593db27 --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TMap.cs @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TMap + { + public TMap(TType keyType, TType valueType, int count) + { + KeyType = keyType; + ValueType = valueType; + Count = count; + } + + public TType KeyType { get; set; } + + public TType ValueType { get; set; } + + public int Count { get; set; } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TMessage.cs b/lib/Thrift/Protocols/Entities/TMessage.cs new file mode 100644 index 00000000000..17f49298f77 --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TMessage.cs @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TMessage + { + public TMessage(string name, TMessageType type, int seqid) + { + Name = name; + Type = type; + SeqID = seqid; + } + + public string Name { get; set; } + + public TMessageType Type { get; set; } + + // ReSharper disable once InconsistentNaming - do not rename - it used for generation + public int SeqID { get; set; } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TMessageType.cs b/lib/Thrift/Protocols/Entities/TMessageType.cs new file mode 100644 index 00000000000..d7b9a227595 --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TMessageType.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public enum TMessageType + { + Call = 1, + Reply = 2, + Exception = 3, + Oneway = 4 + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TSet.cs b/lib/Thrift/Protocols/Entities/TSet.cs new file mode 100644 index 00000000000..a583b54a681 --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TSet.cs @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TSet + { + public TSet(TType elementType, int count) + { + ElementType = elementType; + Count = count; + } + + public TSet(TList list) + : this(list.ElementType, list.Count) + { + } + + public TType ElementType { get; set; } + + public int Count { get; set; } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TStruct.cs b/lib/Thrift/Protocols/Entities/TStruct.cs new file mode 100644 index 00000000000..a28dcc3d001 --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TStruct.cs @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TStruct + { + public TStruct(string name) + { + Name = name; + } + + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Entities/TType.cs b/lib/Thrift/Protocols/Entities/TType.cs new file mode 100644 index 00000000000..ebe781c9547 --- /dev/null +++ b/lib/Thrift/Protocols/Entities/TType.cs @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities +{ + // ReSharper disable once InconsistentNaming + public enum TType : byte + { + Stop = 0, + Void = 1, + Bool = 2, + Byte = 3, + Double = 4, + I16 = 6, + I32 = 8, + I64 = 10, + String = 11, + Struct = 12, + Map = 13, + Set = 14, + List = 15 + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/ITProtocolFactory.cs b/lib/Thrift/Protocols/ITProtocolFactory.cs new file mode 100644 index 00000000000..ecc5cc494d4 --- /dev/null +++ b/lib/Thrift/Protocols/ITProtocolFactory.cs @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Transports; + +namespace Thrift.Protocols +{ + // ReSharper disable once InconsistentNaming + public interface ITProtocolFactory + { + TProtocol GetProtocol(TClientTransport trans); + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/TAbstractBase.cs b/lib/Thrift/Protocols/TAbstractBase.cs new file mode 100644 index 00000000000..4e18681bfb9 --- /dev/null +++ b/lib/Thrift/Protocols/TAbstractBase.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Protocols +{ + // ReSharper disable once InconsistentNaming + public interface TAbstractBase + { + Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/TBase.cs b/lib/Thrift/Protocols/TBase.cs new file mode 100644 index 00000000000..014e1aee856 --- /dev/null +++ b/lib/Thrift/Protocols/TBase.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Protocols +{ + // ReSharper disable once InconsistentNaming + public interface TBase : TAbstractBase + { + Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/TBinaryProtocol.cs b/lib/Thrift/Protocols/TBinaryProtocol.cs new file mode 100644 index 00000000000..72bc3d2cdca --- /dev/null +++ b/lib/Thrift/Protocols/TBinaryProtocol.cs @@ -0,0 +1,613 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; +using Thrift.Transports; + +namespace Thrift.Protocols +{ + // ReSharper disable once InconsistentNaming + public class TBinaryProtocol : TProtocol + { + //TODO: Unit tests + //TODO: Localization + //TODO: pragma + + protected const uint VersionMask = 0xffff0000; + protected const uint Version1 = 0x80010000; + + protected bool StrictRead; + protected bool StrictWrite; + + public TBinaryProtocol(TClientTransport trans) + : this(trans, false, true) + { + } + + public TBinaryProtocol(TClientTransport trans, bool strictRead, bool strictWrite) + : base(trans) + { + StrictRead = strictRead; + StrictWrite = strictWrite; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + if (StrictWrite) + { + var version = Version1 | (uint) message.Type; + await WriteI32Async((int) version, cancellationToken).ConfigureAwait(false); + await WriteStringAsync(message.Name, cancellationToken).ConfigureAwait(false); + await WriteI32Async(message.SeqID, cancellationToken).ConfigureAwait(false); + } + else + { + await WriteStringAsync(message.Name, cancellationToken).ConfigureAwait(false); + await WriteByteAsync((sbyte) message.Type, cancellationToken).ConfigureAwait(false); + await WriteI32Async(message.SeqID, cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) field.Type, cancellationToken).ConfigureAwait(false); + await WriteI16Async(field.ID, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) TType.Stop, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) map.KeyType, cancellationToken).ConfigureAwait(false); + await WriteByteAsync((sbyte) map.ValueType, cancellationToken).ConfigureAwait(false); + await WriteI32Async(map.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) list.ElementType, cancellationToken).ConfigureAwait(false); + await WriteI32Async(list.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) set.ElementType, cancellationToken).ConfigureAwait(false); + await WriteI32Async(set.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken).ConfigureAwait(false); + } + + protected internal static byte[] CreateWriteByte(sbyte b) + { + var bout = new byte[1]; + + bout[0] = (byte) b; + + return bout; + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bout = CreateWriteByte(b); + await Trans.WriteAsync(bout, 0, 1, cancellationToken).ConfigureAwait(false); + } + + protected internal static byte[] CreateWriteI16(short s) + { + var i16Out = new byte[2]; + + i16Out[0] = (byte) (0xff & (s >> 8)); + i16Out[1] = (byte) (0xff & s); + + return i16Out; + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var i16Out = CreateWriteI16(i16); + await Trans.WriteAsync(i16Out, 0, 2, cancellationToken).ConfigureAwait(false); + } + + protected internal static byte[] CreateWriteI32(int i32) + { + var i32Out = new byte[4]; + + i32Out[0] = (byte) (0xff & (i32 >> 24)); + i32Out[1] = (byte) (0xff & (i32 >> 16)); + i32Out[2] = (byte) (0xff & (i32 >> 8)); + i32Out[3] = (byte) (0xff & i32); + + return i32Out; + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var i32Out = CreateWriteI32(i32); + await Trans.WriteAsync(i32Out, 0, 4, cancellationToken).ConfigureAwait(false); + } + + protected internal static byte[] CreateWriteI64(long i64) + { + var i64Out = new byte[8]; + + i64Out[0] = (byte) (0xff & (i64 >> 56)); + i64Out[1] = (byte) (0xff & (i64 >> 48)); + i64Out[2] = (byte) (0xff & (i64 >> 40)); + i64Out[3] = (byte) (0xff & (i64 >> 32)); + i64Out[4] = (byte) (0xff & (i64 >> 24)); + i64Out[5] = (byte) (0xff & (i64 >> 16)); + i64Out[6] = (byte) (0xff & (i64 >> 8)); + i64Out[7] = (byte) (0xff & i64); + + return i64Out; + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var i64Out = CreateWriteI64(i64); + await Trans.WriteAsync(i64Out, 0, 8, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteI32Async(bytes.Length, cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var message = new TMessage(); + var size = await ReadI32Async(cancellationToken).ConfigureAwait(false); + if (size < 0) + { + var version = (uint) size & VersionMask; + if (version != Version1) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + $"Bad version in ReadMessageBegin: {version}"); + } + message.Type = (TMessageType) (size & 0x000000ff); + message.Name = await ReadStringAsync(cancellationToken).ConfigureAwait(false); + message.SeqID = await ReadI32Async(cancellationToken).ConfigureAwait(false); + } + else + { + if (StrictRead) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + "Missing version in ReadMessageBegin, old client?"); + } + message.Name = await ReadStringBodyAsync(size, cancellationToken).ConfigureAwait(false); + message.Type = (TMessageType) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + message.SeqID = await ReadI32Async(cancellationToken).ConfigureAwait(false); + } + return message; + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + //TODO: no read from internal transport? + return new TStruct(); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var field = new TField + { + Type = (TType) await ReadByteAsync(cancellationToken) + }; + + if (field.Type != TType.Stop) + { + field.ID = await ReadI16Async(cancellationToken).ConfigureAwait(false); + } + + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var map = new TMap + { + KeyType = (TType) await ReadByteAsync(cancellationToken), + ValueType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + + return map; + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var list = new TList + { + ElementType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + + return list; + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var set = new TSet + { + ElementType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + + return set; + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + return (await ReadByteAsync(cancellationToken).ConfigureAwait(false)) == 1; + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var bin = new byte[1]; + await Trans.ReadAllAsync(bin, 0, 1, cancellationToken).ConfigureAwait(false); //TODO: why readall ? + return (sbyte) bin[0]; + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var i16In = new byte[2]; + await Trans.ReadAllAsync(i16In, 0, 2, cancellationToken).ConfigureAwait(false); + var result = (short) (((i16In[0] & 0xff) << 8) | i16In[1] & 0xff); + return result; + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var i32In = new byte[4]; + await Trans.ReadAllAsync(i32In, 0, 4, cancellationToken).ConfigureAwait(false); + + var result = + ((i32In[0] & 0xff) << 24) | + ((i32In[1] & 0xff) << 16) | + ((i32In[2] & 0xff) << 8) | + i32In[3] & 0xff; + + return result; + } + +#pragma warning disable 675 + + protected internal long CreateReadI64(byte[] buf) + { + var result = + ((long) (buf[0] & 0xff) << 56) | + ((long) (buf[1] & 0xff) << 48) | + ((long) (buf[2] & 0xff) << 40) | + ((long) (buf[3] & 0xff) << 32) | + ((long) (buf[4] & 0xff) << 24) | + ((long) (buf[5] & 0xff) << 16) | + ((long) (buf[6] & 0xff) << 8) | + buf[7] & 0xff; + + return result; + } + +#pragma warning restore 675 + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var i64In = new byte[8]; + await Trans.ReadAllAsync(i64In, 0, 8, cancellationToken).ConfigureAwait(false); + return CreateReadI64(i64In); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var d = await ReadI64Async(cancellationToken).ConfigureAwait(false); + return BitConverter.Int64BitsToDouble(d); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var size = await ReadI32Async(cancellationToken).ConfigureAwait(false); + var buf = new byte[size]; + await Trans.ReadAllAsync(buf, 0, size, cancellationToken).ConfigureAwait(false); + return buf; + } + + private async Task ReadStringBodyAsync(int size, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var buf = new byte[size]; + await Trans.ReadAllAsync(buf, 0, size, cancellationToken).ConfigureAwait(false); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + public class Factory : ITProtocolFactory + { + protected bool StrictRead; + protected bool StrictWrite; + + public Factory() + : this(false, true) + { + } + + public Factory(bool strictRead, bool strictWrite) + { + StrictRead = strictRead; + StrictWrite = strictWrite; + } + + public TProtocol GetProtocol(TClientTransport trans) + { + return new TBinaryProtocol(trans, StrictRead, StrictWrite); + } + } + } +} diff --git a/lib/Thrift/Protocols/TCompactProtocol.cs b/lib/Thrift/Protocols/TCompactProtocol.cs new file mode 100644 index 00000000000..a9101075403 --- /dev/null +++ b/lib/Thrift/Protocols/TCompactProtocol.cs @@ -0,0 +1,922 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; +using Thrift.Transports; + +namespace Thrift.Protocols +{ + //TODO: implementation of TProtocol + + // ReSharper disable once InconsistentNaming + public class TCompactProtocol : TProtocol + { + private const byte ProtocolId = 0x82; + private const byte Version = 1; + private const byte VersionMask = 0x1f; // 0001 1111 + private const byte TypeMask = 0xE0; // 1110 0000 + private const byte TypeBits = 0x07; // 0000 0111 + private const int TypeShiftAmount = 5; + private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); + private static readonly TField Tstop = new TField(string.Empty, TType.Stop, 0); + + // ReSharper disable once InconsistentNaming + private static readonly byte[] TTypeToCompactType = new byte[16]; + + /// + /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff. + /// + private readonly Stack _lastField = new Stack(15); + + /// + /// If we encounter a boolean field begin, save the TField here so it can have the value incorporated. + /// + private TField? _booleanField; + + /// + /// If we Read a field header, and it's a boolean field, save the boolean value here so that ReadBool can use it. + /// + private bool? _boolValue; + + private short _lastFieldId; + + public TCompactProtocol(TClientTransport trans) + : base(trans) + { + TTypeToCompactType[(int) TType.Stop] = Types.Stop; + TTypeToCompactType[(int) TType.Bool] = Types.BooleanTrue; + TTypeToCompactType[(int) TType.Byte] = Types.Byte; + TTypeToCompactType[(int) TType.I16] = Types.I16; + TTypeToCompactType[(int) TType.I32] = Types.I32; + TTypeToCompactType[(int) TType.I64] = Types.I64; + TTypeToCompactType[(int) TType.Double] = Types.Double; + TTypeToCompactType[(int) TType.String] = Types.Binary; + TTypeToCompactType[(int) TType.List] = Types.List; + TTypeToCompactType[(int) TType.Set] = Types.Set; + TTypeToCompactType[(int) TType.Map] = Types.Map; + TTypeToCompactType[(int) TType.Struct] = Types.Struct; + } + + public void Reset() + { + _lastField.Clear(); + _lastFieldId = 0; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Trans.WriteAsync(new[] {ProtocolId}, cancellationToken).ConfigureAwait(false); + await + Trans.WriteAsync( + new[] {(byte) ((Version & VersionMask) | (((uint) message.Type << TypeShiftAmount) & TypeMask))}, + cancellationToken); + + var bufferTuple = CreateWriteVarInt32((uint) message.SeqID); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + + await WriteStringAsync(message.Name, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + /// + /// Write a struct begin. This doesn't actually put anything on the wire. We + /// use it as an opportunity to put special placeholder markers on the field + /// stack so we can get the field id deltas correct. + /// + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + _lastField.Push(_lastFieldId); + _lastFieldId = 0; + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + _lastFieldId = _lastField.Pop(); + } + + private async Task WriteFieldBeginInternalAsync(TField field, byte typeOverride, + CancellationToken cancellationToken) + { + // if there's a exType override, use that. + var typeToWrite = typeOverride == 0xFF ? GetCompactType(field.Type) : typeOverride; + + // check if we can use delta encoding for the field id + if ((field.ID > _lastFieldId) && (field.ID - _lastFieldId <= 15)) + { + var b = (byte) (((field.ID - _lastFieldId) << 4) | typeToWrite); + // Write them together + await Trans.WriteAsync(new[] {b}, cancellationToken).ConfigureAwait(false); + } + else + { + // Write them separate + await Trans.WriteAsync(new[] {typeToWrite}, cancellationToken).ConfigureAwait(false); + await WriteI16Async(field.ID, cancellationToken).ConfigureAwait(false); + } + + _lastFieldId = field.ID; + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + if (field.Type == TType.Bool) + { + _booleanField = field; + } + else + { + await WriteFieldBeginInternalAsync(field, 0xFF, cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Trans.WriteAsync(new[] {Types.Stop}, cancellationToken).ConfigureAwait(false); + } + + protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + /* + Abstract method for writing the start of lists and sets. List and sets on + the wire differ only by the exType indicator. + */ + + if (size <= 14) + { + await Trans.WriteAsync(new[] {(byte) ((size << 4) | GetCompactType(elemType))}, cancellationToken).ConfigureAwait(false); + } + else + { + await Trans.WriteAsync(new[] {(byte) (0xf0 | GetCompactType(elemType))}, cancellationToken).ConfigureAwait(false); + + var bufferTuple = CreateWriteVarInt32((uint) size); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + /* + Write a boolean value. Potentially, this could be a boolean field, in + which case the field header info isn't written yet. If so, decide what the + right exType header is for the value and then Write the field header. + Otherwise, Write a single byte. + */ + + if (_booleanField != null) + { + // we haven't written the field header yet + await + WriteFieldBeginInternalAsync(_booleanField.Value, b ? Types.BooleanTrue : Types.BooleanFalse, + cancellationToken); + _booleanField = null; + } + else + { + // we're not part of a field, so just Write the value. + await Trans.WriteAsync(new[] {b ? Types.BooleanTrue : Types.BooleanFalse}, cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Trans.WriteAsync(new[] {(byte) b}, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt32(IntToZigzag(i16)); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + } + + protected internal Tuple CreateWriteVarInt32(uint n) + { + // Write an i32 as a varint.Results in 1 - 5 bytes on the wire. + var i32Buf = new byte[5]; + var idx = 0; + + while (true) + { + if ((n & ~0x7F) == 0) + { + i32Buf[idx++] = (byte) n; + break; + } + + i32Buf[idx++] = (byte) ((n & 0x7F) | 0x80); + n >>= 7; + } + + return new Tuple(i32Buf, idx); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt32(IntToZigzag(i32)); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + } + + protected internal Tuple CreateWriteVarInt64(ulong n) + { + // Write an i64 as a varint. Results in 1-10 bytes on the wire. + var buf = new byte[10]; + var idx = 0; + + while (true) + { + if ((n & ~(ulong) 0x7FL) == 0) + { + buf[idx++] = (byte) n; + break; + } + buf[idx++] = (byte) ((n & 0x7F) | 0x80); + n >>= 7; + } + + return new Tuple(buf, idx); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt64(LongToZigzag(i64)); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var data = new byte[8]; + FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), data, 0); + await Trans.WriteAsync(data, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bytes = Encoding.UTF8.GetBytes(str); + + var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + if (map.Count == 0) + { + await Trans.WriteAsync(new[] {(byte) 0}, cancellationToken).ConfigureAwait(false); + } + else + { + var bufferTuple = CreateWriteVarInt32((uint) map.Count); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken).ConfigureAwait(false); + await + Trans.WriteAsync( + new[] {(byte) ((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType))}, + cancellationToken); + } + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var protocolId = (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + if (protocolId != ProtocolId) + { + throw new TProtocolException($"Expected protocol id {ProtocolId:X} but got {protocolId:X}"); + } + + var versionAndType = (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + var version = (byte) (versionAndType & VersionMask); + + if (version != Version) + { + throw new TProtocolException($"Expected version {Version} but got {version}"); + } + + var type = (byte) ((versionAndType >> TypeShiftAmount) & TypeBits); + var seqid = (int) await ReadVarInt32Async(cancellationToken).ConfigureAwait(false); + var messageName = await ReadStringAsync(cancellationToken).ConfigureAwait(false); + + return new TMessage(messageName, (TMessageType) type, seqid); + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + // some magic is here ) + + _lastField.Push(_lastFieldId); + _lastFieldId = 0; + + return AnonymousStruct; + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + /* + Doesn't actually consume any wire data, just removes the last field for + this struct from the field stack. + */ + + // consume the last field we Read off the wire. + _lastFieldId = _lastField.Pop(); + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + // Read a field header off the wire. + var type = (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + // if it's a stop, then we can return immediately, as the struct is over. + if (type == Types.Stop) + { + return Tstop; + } + + short fieldId; + // mask off the 4 MSB of the exType header. it could contain a field id delta. + var modifier = (short) ((type & 0xf0) >> 4); + if (modifier == 0) + { + fieldId = await ReadI16Async(cancellationToken).ConfigureAwait(false); + } + else + { + fieldId = (short) (_lastFieldId + modifier); + } + + var field = new TField(string.Empty, GetTType((byte) (type & 0x0f)), fieldId); + // if this happens to be a boolean field, the value is encoded in the exType + if (IsBoolType(type)) + { + _boolValue = (byte) (type & 0x0f) == Types.BooleanTrue; + } + + // push the new field onto the field stack so we can keep the deltas going. + _lastFieldId = field.ID; + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + /* + Read a map header off the wire. If the size is zero, skip Reading the key + and value exType. This means that 0-length maps will yield TMaps without the + "correct" types. + */ + + var size = (int) await ReadVarInt32Async(cancellationToken).ConfigureAwait(false); + var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + return new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + /* + Read a set header off the wire. If the set size is 0-14, the size will + be packed into the element exType header. If it's a longer set, the 4 MSB + of the element exType header will be 0xF, and a varint will follow with the + true size. + */ + + return new TSet(await ReadListBeginAsync(cancellationToken).ConfigureAwait(false)); + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + /* + Read a boolean off the wire. If this is a boolean field, the value should + already have been Read during ReadFieldBegin, so we'll just consume the + pre-stored value. Otherwise, Read a byte. + */ + + if (_boolValue != null) + { + var result = _boolValue.Value; + _boolValue = null; + return result; + } + + return (await ReadByteAsync(cancellationToken).ConfigureAwait(false)) == Types.BooleanTrue; + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + // Read a single byte off the wire. Nothing interesting here. + var buf = new byte[1]; + await Trans.ReadAllAsync(buf, 0, 1, cancellationToken).ConfigureAwait(false); + return (sbyte) buf[0]; + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken).ConfigureAwait(false)); + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + return ZigzagToInt(await ReadVarInt32Async(cancellationToken).ConfigureAwait(false)); + } + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + return ZigzagToLong(await ReadVarInt64Async(cancellationToken).ConfigureAwait(false)); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var longBits = new byte[8]; + await Trans.ReadAllAsync(longBits, 0, 8, cancellationToken).ConfigureAwait(false); + + return BitConverter.Int64BitsToDouble(BytesToLong(longBits)); + } + + public override async Task ReadStringAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + // Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. + var length = (int) await ReadVarInt32Async(cancellationToken).ConfigureAwait(false); + + if (length == 0) + { + return string.Empty; + } + + var buf = new byte[length]; + await Trans.ReadAllAsync(buf, 0, length, cancellationToken).ConfigureAwait(false); + + return Encoding.UTF8.GetString(buf); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + // Read a byte[] from the wire. + var length = (int) await ReadVarInt32Async(cancellationToken).ConfigureAwait(false); + if (length == 0) + { + return new byte[0]; + } + + var buf = new byte[length]; + await Trans.ReadAllAsync(buf, 0, length, cancellationToken).ConfigureAwait(false); + return buf; + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + /* + Read a list header off the wire. If the list size is 0-14, the size will + be packed into the element exType header. If it's a longer list, the 4 MSB + of the element exType header will be 0xF, and a varint will follow with the + true size. + */ + + var sizeAndType = (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + var size = (sizeAndType >> 4) & 0x0f; + if (size == 15) + { + size = (int) await ReadVarInt32Async(cancellationToken).ConfigureAwait(false); + } + + var type = GetTType(sizeAndType); + return new TList(type, size); + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + private static byte GetCompactType(TType ttype) + { + // Given a TType value, find the appropriate TCompactProtocol.Types constant. + return TTypeToCompactType[(int) ttype]; + } + + + private async Task ReadVarInt32Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + /* + Read an i32 from the wire as a varint. The MSB of each byte is set + if there is another byte to follow. This can Read up to 5 bytes. + */ + + uint result = 0; + var shift = 0; + + while (true) + { + var b = (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + result |= (uint) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) + { + break; + } + shift += 7; + } + + return result; + } + + private async Task ReadVarInt64Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + /* + Read an i64 from the wire as a proper varint. The MSB of each byte is set + if there is another byte to follow. This can Read up to 10 bytes. + */ + + var shift = 0; + ulong result = 0; + while (true) + { + var b = (byte) await ReadByteAsync(cancellationToken).ConfigureAwait(false); + result |= (ulong) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) + { + break; + } + shift += 7; + } + + return result; + } + + private static int ZigzagToInt(uint n) + { + return (int) (n >> 1) ^ -(int) (n & 1); + } + + private static long ZigzagToLong(ulong n) + { + return (long) (n >> 1) ^ -(long) (n & 1); + } + + private static long BytesToLong(byte[] bytes) + { + /* + Note that it's important that the mask bytes are long literals, + otherwise they'll default to ints, and when you shift an int left 56 bits, + you just get a messed up int. + */ + + return + ((bytes[7] & 0xffL) << 56) | + ((bytes[6] & 0xffL) << 48) | + ((bytes[5] & 0xffL) << 40) | + ((bytes[4] & 0xffL) << 32) | + ((bytes[3] & 0xffL) << 24) | + ((bytes[2] & 0xffL) << 16) | + ((bytes[1] & 0xffL) << 8) | + (bytes[0] & 0xffL); + } + + private static bool IsBoolType(byte b) + { + var lowerNibble = b & 0x0f; + return (lowerNibble == Types.BooleanTrue) || (lowerNibble == Types.BooleanFalse); + } + + private static TType GetTType(byte type) + { + // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. + switch ((byte) (type & 0x0f)) + { + case Types.Stop: + return TType.Stop; + case Types.BooleanFalse: + case Types.BooleanTrue: + return TType.Bool; + case Types.Byte: + return TType.Byte; + case Types.I16: + return TType.I16; + case Types.I32: + return TType.I32; + case Types.I64: + return TType.I64; + case Types.Double: + return TType.Double; + case Types.Binary: + return TType.String; + case Types.List: + return TType.List; + case Types.Set: + return TType.Set; + case Types.Map: + return TType.Map; + case Types.Struct: + return TType.Struct; + default: + throw new TProtocolException($"Don't know what exType: {(byte) (type & 0x0f)}"); + } + } + + private static ulong LongToZigzag(long n) + { + // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint + return (ulong) (n << 1) ^ (ulong) (n >> 63); + } + + private static uint IntToZigzag(int n) + { + // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint + return (uint) (n << 1) ^ (uint) (n >> 31); + } + + private static void FixedLongToBytes(long n, byte[] buf, int off) + { + // Convert a long into little-endian bytes in buf starting at off and going until off+7. + buf[off + 0] = (byte) (n & 0xff); + buf[off + 1] = (byte) ((n >> 8) & 0xff); + buf[off + 2] = (byte) ((n >> 16) & 0xff); + buf[off + 3] = (byte) ((n >> 24) & 0xff); + buf[off + 4] = (byte) ((n >> 32) & 0xff); + buf[off + 5] = (byte) ((n >> 40) & 0xff); + buf[off + 6] = (byte) ((n >> 48) & 0xff); + buf[off + 7] = (byte) ((n >> 56) & 0xff); + } + + public class Factory : ITProtocolFactory + { + public TProtocol GetProtocol(TClientTransport trans) + { + return new TCompactProtocol(trans); + } + } + + /// + /// All of the on-wire exType codes. + /// + private static class Types + { + public const byte Stop = 0x00; + public const byte BooleanTrue = 0x01; + public const byte BooleanFalse = 0x02; + public const byte Byte = 0x03; + public const byte I16 = 0x04; + public const byte I32 = 0x05; + public const byte I64 = 0x06; + public const byte Double = 0x07; + public const byte Binary = 0x08; + public const byte List = 0x09; + public const byte Set = 0x0A; + public const byte Map = 0x0B; + public const byte Struct = 0x0C; + } + } +} diff --git a/lib/Thrift/Protocols/TJSONProtocol.cs b/lib/Thrift/Protocols/TJSONProtocol.cs new file mode 100644 index 00000000000..b2b5df2d9f2 --- /dev/null +++ b/lib/Thrift/Protocols/TJSONProtocol.cs @@ -0,0 +1,981 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; +using Thrift.Protocols.Utilities; +using Thrift.Transports; + +namespace Thrift.Protocols +{ + /// + /// JSON protocol implementation for thrift. + /// This is a full-featured protocol supporting Write and Read. + /// Please see the C++ class header for a detailed description of the + /// protocol's wire format. + /// Adapted from the Java version. + /// + // ReSharper disable once InconsistentNaming + public class TJsonProtocol : TProtocol + { + private const long Version = 1; + + // Temporary buffer used by several methods + private readonly byte[] _tempBuffer = new byte[4]; + + // Current context that we are in + protected JSONBaseContext Context; + + // Stack of nested contexts that we may be in + protected Stack ContextStack = new Stack(); + + // Reader that manages a 1-byte buffer + protected LookaheadReader Reader; + + // Default encoding + protected Encoding Utf8Encoding = Encoding.UTF8; + + /// + /// TJsonProtocol Constructor + /// + public TJsonProtocol(TClientTransport trans) + : base(trans) + { + Context = new JSONBaseContext(this); + Reader = new LookaheadReader(this); + } + + /// + /// Push a new JSON context onto the stack. + /// + protected void PushContext(JSONBaseContext c) + { + ContextStack.Push(Context); + Context = c; + } + + /// + /// Pop the last JSON context off the stack + /// + protected void PopContext() + { + Context = ContextStack.Pop(); + } + + /// + /// Read a byte that must match b[0]; otherwise an exception is thrown. + /// Marked protected to avoid synthetic accessor in JSONListContext.Read + /// and JSONPairContext.Read + /// + protected async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken) + { + var ch = await Reader.ReadAsync(cancellationToken).ConfigureAwait(false); + if (ch != bytes[0]) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, $"Unexpected character: {(char) ch}"); + } + } + + /// + /// Write the bytes in array buf as a JSON characters, escaping as needed + /// + private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + + var len = bytes.Length; + for (var i = 0; i < len; i++) + { + if ((bytes[i] & 0x00FF) >= 0x30) + { + if (bytes[i] == TJSONProtocolConstants.Backslash[0]) + { + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken).ConfigureAwait(false); + } + else + { + await Trans.WriteAsync(bytes.ToArray(), i, 1, cancellationToken).ConfigureAwait(false); + } + } + else + { + _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]]; + if (_tempBuffer[0] == 1) + { + await Trans.WriteAsync(bytes, i, 1, cancellationToken).ConfigureAwait(false); + } + else if (_tempBuffer[0] > 1) + { + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken).ConfigureAwait(false); + } + else + { + await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken).ConfigureAwait(false); + _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4)); + _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]); + await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken).ConfigureAwait(false); + } + } + } + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + /// + /// Write out number as a JSON value. If the context dictates so, it will be + /// wrapped in quotes to output as a JSON string. + /// + private async Task WriteJsonIntegerAsync(long num, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken).ConfigureAwait(false); + var str = num.ToString(); + + var escapeNum = Context.EscapeNumbers(); + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + var bytes = Utf8Encoding.GetBytes(str); + await Trans.WriteAsync(bytes, cancellationToken).ConfigureAwait(false); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + } + + /// + /// Write out a double as a JSON value. If it is NaN or infinity or if the + /// context dictates escaping, Write out as JSON string. + /// + private async Task WriteJsonDoubleAsync(double num, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken).ConfigureAwait(false); + var str = num.ToString("G17", CultureInfo.InvariantCulture); + var special = false; + + switch (str[0]) + { + case 'N': // NaN + case 'I': // Infinity + special = true; + break; + case '-': + if (str[1] == 'I') + { + // -Infinity + special = true; + } + break; + } + + var escapeNum = special || Context.EscapeNumbers(); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken).ConfigureAwait(false); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + } + + /// + /// Write out contents of byte array b as a JSON string with base-64 encoded + /// data + /// + private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + + var len = bytes.Length; + var off = 0; + + while (len >= 3) + { + // Encode 3 bytes at a time + TBase64Helper.Encode(bytes, off, 3, _tempBuffer, 0); + await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken).ConfigureAwait(false); + off += 3; + len -= 3; + } + + if (len > 0) + { + // Encode remainder + TBase64Helper.Encode(bytes, off, len, _tempBuffer, 0); + await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken).ConfigureAwait(false); + } + + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken).ConfigureAwait(false); + PushContext(new JSONPairContext(this)); + } + + private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken) + { + PopContext(); + await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken).ConfigureAwait(false); + } + + private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken).ConfigureAwait(false); + await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken).ConfigureAwait(false); + PushContext(new JSONListContext(this)); + } + + private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken) + { + PopContext(); + await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + await WriteJsonIntegerAsync(Version, cancellationToken).ConfigureAwait(false); + + var b = Utf8Encoding.GetBytes(message.Name); + await WriteJsonStringAsync(b, cancellationToken).ConfigureAwait(false); + + await WriteJsonIntegerAsync((long) message.Type, cancellationToken).ConfigureAwait(false); + await WriteJsonIntegerAsync(message.SeqID, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + await WriteJsonObjectStartAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(field.ID, cancellationToken).ConfigureAwait(false); + await WriteJsonObjectStartAsync(cancellationToken).ConfigureAwait(false); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken).ConfigureAwait(false); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken).ConfigureAwait(false); + await WriteJsonIntegerAsync(map.Count, cancellationToken).ConfigureAwait(false); + await WriteJsonObjectStartAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken).ConfigureAwait(false); + await WriteJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken).ConfigureAwait(false); + await WriteJsonIntegerAsync(list.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken).ConfigureAwait(false); + await WriteJsonIntegerAsync(set.Count, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(b ? 1 : 0, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(b, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i16, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i32, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i64, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + await WriteJsonDoubleAsync(d, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + var b = Utf8Encoding.GetBytes(s); + await WriteJsonStringAsync(b, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + await WriteJsonBase64Async(bytes, cancellationToken).ConfigureAwait(false); + } + + /// + /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the + /// context if skipContext is true. + /// + private async Task ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) + { + using (var buffer = new MemoryStream()) + { + var codeunits = new List(); + + + if (!skipContext) + { + await Context.ReadAsync(cancellationToken).ConfigureAwait(false); + } + + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + + while (true) + { + var ch = await Reader.ReadAsync(cancellationToken).ConfigureAwait(false); + if (ch == TJSONProtocolConstants.Quote[0]) + { + break; + } + + // escaped? + if (ch != TJSONProtocolConstants.EscSequences[0]) + { + await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken).ConfigureAwait(false); + continue; + } + + // distinguish between \uXXXX and \? + ch = await Reader.ReadAsync(cancellationToken).ConfigureAwait(false); + if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n + { + var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch); + if (off == -1) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); + } + ch = TJSONProtocolConstants.EscapeCharValues[off]; + await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken).ConfigureAwait(false); + continue; + } + + // it's \uXXXX + await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken).ConfigureAwait(false); + + var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) + + (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) + + (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) + + TJSONProtocolHelper.ToHexVal(_tempBuffer[3])); + + if (char.IsHighSurrogate((char) wch)) + { + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); + } + codeunits.Add((char) wch); + } + else if (char.IsLowSurrogate((char) wch)) + { + if (codeunits.Count == 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected high surrogate char"); + } + + codeunits.Add((char) wch); + var tmp = Utf8Encoding.GetBytes(codeunits.ToArray()); + await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken).ConfigureAwait(false); + codeunits.Clear(); + } + else + { + var tmp = Utf8Encoding.GetBytes(new[] {(char) wch}); + await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken).ConfigureAwait(false); + } + } + + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); + } + + return buffer.ToArray(); + } + } + + /// + /// Read in a sequence of characters that are all valid in JSON numbers. Does + /// not do a complete regex check to validate that this is actually a number. + /// + private async Task ReadJsonNumericCharsAsync(CancellationToken cancellationToken) + { + var strbld = new StringBuilder(); + while (true) + { + //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions + try + { + var ch = await Reader.PeekAsync(cancellationToken).ConfigureAwait(false); + if (!TJSONProtocolHelper.IsJsonNumeric(ch)) + { + break; + } + var c = (char)await Reader.ReadAsync(cancellationToken).ConfigureAwait(false); + strbld.Append(c); + } + catch (TTransportException) + { + break; + } + } + return strbld.ToString(); + } + + /// + /// Read in a JSON number. If the context dictates, Read in enclosing quotes. + /// + private async Task ReadJsonIntegerAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken).ConfigureAwait(false); + if (Context.EscapeNumbers()) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + var str = await ReadJsonNumericCharsAsync(cancellationToken).ConfigureAwait(false); + if (Context.EscapeNumbers()) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + try + { + return long.Parse(str); + } + catch (FormatException) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); + } + } + + /// + /// Read in a JSON double value. Throw if the value is not wrapped in quotes + /// when expected or if wrapped in quotes when not expected. + /// + private async Task ReadJsonDoubleAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken).ConfigureAwait(false); + if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) + { + var arr = await ReadJsonStringAsync(true, cancellationToken).ConfigureAwait(false); + var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); + + if (!Context.EscapeNumbers() && !double.IsNaN(dub) && !double.IsInfinity(dub)) + { + // Throw exception -- we should not be in a string in this case + throw new TProtocolException(TProtocolException.INVALID_DATA, "Numeric data unexpectedly quoted"); + } + + return dub; + } + + if (Context.EscapeNumbers()) + { + // This will throw - we should have had a quote if escapeNum == true + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken).ConfigureAwait(false); + } + + try + { + return double.Parse(await ReadJsonNumericCharsAsync(cancellationToken).ConfigureAwait(false), CultureInfo.InvariantCulture); + } + catch (FormatException) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); + } + } + + /// + /// Read in a JSON string containing base-64 encoded data and decode it. + /// + private async Task ReadJsonBase64Async(CancellationToken cancellationToken) + { + var b = await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false); + var len = b.Length; + var off = 0; + var size = 0; + + // reduce len to ignore fill bytes + while ((len > 0) && (b[len - 1] == '=')) + { + --len; + } + + // read & decode full byte triplets = 4 source bytes + while (len > 4) + { + // Decode 4 bytes at a time + TBase64Helper.Decode(b, off, 4, b, size); // NB: decoded in place + off += 4; + len -= 4; + size += 3; + } + + // Don't decode if we hit the end or got a single leftover byte (invalid + // base64 but legal for skip of regular string exType) + if (len > 1) + { + // Decode remainder + TBase64Helper.Decode(b, off, len, b, size); // NB: decoded in place + size += len - 1; + } + + // Sadly we must copy the byte[] (any way around this?) + var result = new byte[size]; + Array.Copy(b, 0, result, 0, size); + return result; + } + + private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken).ConfigureAwait(false); + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken).ConfigureAwait(false); + PushContext(new JSONPairContext(this)); + } + + private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken).ConfigureAwait(false); + PopContext(); + } + + private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken).ConfigureAwait(false); + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken).ConfigureAwait(false); + PushContext(new JSONListContext(this)); + } + + private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken).ConfigureAwait(false); + PopContext(); + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + var message = new TMessage(); + await ReadJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + if (await ReadJsonIntegerAsync(cancellationToken) != Version) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Message contained bad version."); + } + + var buf = await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false); + message.Name = Utf8Encoding.GetString(buf, 0, buf.Length); + message.Type = (TMessageType) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + message.SeqID = (int) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + return message; + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectStartAsync(cancellationToken).ConfigureAwait(false); + return new TStruct(); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + var field = new TField(); + var ch = await Reader.PeekAsync(cancellationToken).ConfigureAwait(false); + if (ch == TJSONProtocolConstants.RightBrace[0]) + { + field.Type = TType.Stop; + } + else + { + field.ID = (short) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + await ReadJsonObjectStartAsync(cancellationToken).ConfigureAwait(false); + field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false)); + } + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + var map = new TMap(); + await ReadJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false)); + map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false)); + map.Count = (int) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + await ReadJsonObjectStartAsync(cancellationToken).ConfigureAwait(false); + return map; + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken).ConfigureAwait(false); + await ReadJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + var list = new TList(); + await ReadJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false)); + list.Count = (int) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + return list; + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + var set = new TSet(); + await ReadJsonArrayStartAsync(cancellationToken).ConfigureAwait(false); + set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false)); + set.Count = (int) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + return set; + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + return (await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false)) != 0; + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + return (sbyte) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + return (short) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + return (int) await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + return await ReadJsonIntegerAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + return await ReadJsonDoubleAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadStringAsync(CancellationToken cancellationToken) + { + var buf = await ReadJsonStringAsync(false, cancellationToken).ConfigureAwait(false); + return Utf8Encoding.GetString(buf, 0, buf.Length); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + return await ReadJsonBase64Async(cancellationToken).ConfigureAwait(false); + } + + /// + /// Factory for JSON protocol objects + /// + public class Factory : ITProtocolFactory + { + public TProtocol GetProtocol(TClientTransport trans) + { + return new TJsonProtocol(trans); + } + } + + /// + /// Base class for tracking JSON contexts that may require + /// inserting/Reading additional JSON syntax characters + /// This base context does nothing. + /// + protected class JSONBaseContext + { + protected TJsonProtocol Proto; + + public JSONBaseContext(TJsonProtocol proto) + { + Proto = proto; + } + + public virtual async Task WriteAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public virtual async Task ReadAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public virtual bool EscapeNumbers() + { + return false; + } + } + + /// + /// Context for JSON lists. Will insert/Read commas before each item except + /// for the first one + /// + protected class JSONListContext : JSONBaseContext + { + private bool _first = true; + + public JSONListContext(TJsonProtocol protocol) + : base(protocol) + { + } + + public override async Task WriteAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + } + else + { + await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken).ConfigureAwait(false); + } + } + + public override async Task ReadAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + } + else + { + await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken).ConfigureAwait(false); + } + } + } + + /// + /// Context for JSON records. Will insert/Read colons before the value portion + /// of each record pair, and commas before each key except the first. In + /// addition, will indicate that numbers in the key position need to be + /// escaped in quotes (since JSON keys must be strings). + /// + // ReSharper disable once InconsistentNaming + protected class JSONPairContext : JSONBaseContext + { + private bool _colon = true; + + private bool _first = true; + + public JSONPairContext(TJsonProtocol proto) + : base(proto) + { + } + + public override async Task WriteAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + _colon = true; + } + else + { + await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken).ConfigureAwait(false); + _colon = !_colon; + } + } + + public override async Task ReadAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + _colon = true; + } + else + { + await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken).ConfigureAwait(false); + _colon = !_colon; + } + } + + public override bool EscapeNumbers() + { + return _colon; + } + } + + /// + /// Holds up to one byte from the transport + /// + protected class LookaheadReader + { + private readonly byte[] _data = new byte[1]; + + private bool _hasData; + protected TJsonProtocol Proto; + + public LookaheadReader(TJsonProtocol proto) + { + Proto = proto; + } + + /// + /// Return and consume the next byte to be Read, either taking it from the + /// data buffer if present or getting it from the transport otherwise. + /// + public async Task ReadAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (_hasData) + { + _hasData = false; + } + else + { + // find more easy way to avoid exception on reading primitive types + await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken).ConfigureAwait(false); + } + return _data[0]; + } + + /// + /// Return the next byte to be Read without consuming, filling the data + /// buffer if it has not been filled alReady. + /// + public async Task PeekAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (!_hasData) + { + // find more easy way to avoid exception on reading primitive types + await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken).ConfigureAwait(false); + } + _hasData = true; + return _data[0]; + } + } + } +} diff --git a/lib/Thrift/Protocols/TMultiplexedProtocol.cs b/lib/Thrift/Protocols/TMultiplexedProtocol.cs new file mode 100644 index 00000000000..38f1c6ca0d8 --- /dev/null +++ b/lib/Thrift/Protocols/TMultiplexedProtocol.cs @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; + +namespace Thrift.Protocols +{ + /** + * TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift + * client to communicate with a multiplexing Thrift server, by prepending the service name + * to the function name during function calls. + * + * NOTE: THIS IS NOT TO BE USED BY SERVERS. + * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. + * + * This example uses a single socket transport to invoke two services: + * + * TSocketClientTransport transport = new TSocketClientTransport("localhost", 9090); + * transport.open(); + * + * TBinaryProtocol protocol = new TBinaryProtocol(transport); + * + * TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator"); + * Calculator.Client service = new Calculator.Client(mp); + * + * TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport"); + * WeatherReport.Client service2 = new WeatherReport.Client(mp2); + * + * System.out.println(service.add(2,2)); + * System.out.println(service2.getTemperature()); + * + */ + + //TODO: implementation of TProtocol + + // ReSharper disable once InconsistentNaming + public class TMultiplexedProtocol : TProtocolDecorator + { + /** Used to delimit the service name from the function name */ + public const string Separator = ":"; + + private readonly string _serviceName; + + /** + * Wrap the specified protocol, allowing it to be used to communicate with a + * multiplexing server. The serviceName is required as it is + * prepended to the message header so that the multiplexing server can broker + * the function call to the proper service. + * + * Args: + * protocol Your communication protocol of choice, e.g. TBinaryProtocol + * serviceName The service name of the service communicating via this protocol. + */ + + public TMultiplexedProtocol(TProtocol protocol, string serviceName) + : base(protocol) + { + _serviceName = serviceName; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + switch (message.Type) + { + case TMessageType.Call: + case TMessageType.Oneway: + await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken).ConfigureAwait(false); + break; + default: + await base.WriteMessageBeginAsync(message, cancellationToken).ConfigureAwait(false); + break; + } + } + } +} diff --git a/lib/Thrift/Protocols/TProtocol.cs b/lib/Thrift/Protocols/TProtocol.cs new file mode 100644 index 00000000000..5bda512f9a3 --- /dev/null +++ b/lib/Thrift/Protocols/TProtocol.cs @@ -0,0 +1,376 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; +using Thrift.Transports; + +namespace Thrift.Protocols +{ + // ReSharper disable once InconsistentNaming + public abstract class TProtocol : IDisposable + { + public const int DefaultRecursionDepth = 64; + private bool _isDisposed; + protected int RecursionDepth; + + protected TClientTransport Trans; + + protected TProtocol(TClientTransport trans) + { + Trans = trans; + RecursionLimit = DefaultRecursionDepth; + RecursionDepth = 0; + } + + public TClientTransport Transport => Trans; + + protected int RecursionLimit { get; set; } + + public void Dispose() + { + Dispose(true); + } + + public void IncrementRecursionDepth() + { + if (RecursionDepth < RecursionLimit) + { + ++RecursionDepth; + } + else + { + throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); + } + } + + public void DecrementRecursionDepth() + { + --RecursionDepth; + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + (Trans as IDisposable)?.Dispose(); + } + } + _isDisposed = true; + } + + public virtual async Task WriteMessageBeginAsync(TMessage message) + { + await WriteMessageBeginAsync(message, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken); + + public virtual async Task WriteMessageEndAsync() + { + await WriteMessageEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteStructBeginAsync(TStruct @struct) + { + await WriteStructBeginAsync(@struct, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken); + + public virtual async Task WriteStructEndAsync() + { + await WriteStructEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteStructEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteFieldBeginAsync(TField field) + { + await WriteFieldBeginAsync(field, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken); + + public virtual async Task WriteFieldEndAsync() + { + await WriteFieldEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteFieldStopAsync() + { + await WriteFieldStopAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken); + + public virtual async Task WriteMapBeginAsync(TMap map) + { + await WriteMapBeginAsync(map, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken); + + public virtual async Task WriteMapEndAsync() + { + await WriteMapEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteMapEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteListBeginAsync(TList list) + { + await WriteListBeginAsync(list, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken); + + public virtual async Task WriteListEndAsync() + { + await WriteListEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteListEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteSetBeginAsync(TSet set) + { + await WriteSetBeginAsync(set, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken); + + public virtual async Task WriteSetEndAsync() + { + await WriteSetEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteSetEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteBoolAsync(bool b) + { + await WriteBoolAsync(b, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken); + + public virtual async Task WriteByteAsync(sbyte b) + { + await WriteByteAsync(b, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken); + + public virtual async Task WriteI16Async(short i16) + { + await WriteI16Async(i16, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken); + + public virtual async Task WriteI32Async(int i32) + { + await WriteI32Async(i32, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken); + + public virtual async Task WriteI64Async(long i64) + { + await WriteI64Async(i64, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken); + + public virtual async Task WriteDoubleAsync(double d) + { + await WriteDoubleAsync(d, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken); + + public virtual async Task WriteStringAsync(string s) + { + await WriteStringAsync(s, CancellationToken.None).ConfigureAwait(false); + } + + public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + var bytes = Encoding.UTF8.GetBytes(s); + await WriteBinaryAsync(bytes, cancellationToken).ConfigureAwait(false); + } + + public virtual async Task WriteBinaryAsync(byte[] bytes) + { + await WriteBinaryAsync(bytes, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken); + + public virtual async Task ReadMessageBeginAsync() + { + return await ReadMessageBeginAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadMessageBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadMessageEndAsync() + { + await ReadMessageEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadStructBeginAsync() + { + return await ReadStructBeginAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadStructBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadStructEndAsync() + { + await ReadStructEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadStructEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadFieldBeginAsync() + { + return await ReadFieldBeginAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadFieldBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadFieldEndAsync() + { + await ReadFieldEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadMapBeginAsync() + { + return await ReadMapBeginAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadMapBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadMapEndAsync() + { + await ReadMapEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadMapEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadListBeginAsync() + { + return await ReadListBeginAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadListBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadListEndAsync() + { + await ReadListEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadListEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadSetBeginAsync() + { + return await ReadSetBeginAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadSetBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadSetEndAsync() + { + await ReadSetEndAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadSetEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadBoolAsync() + { + return await ReadBoolAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadBoolAsync(CancellationToken cancellationToken); + + public virtual async Task ReadByteAsync() + { + return await ReadByteAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadByteAsync(CancellationToken cancellationToken); + + public virtual async Task ReadI16Async() + { + return await ReadI16Async(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadI16Async(CancellationToken cancellationToken); + + public virtual async Task ReadI32Async() + { + return await ReadI32Async(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadI32Async(CancellationToken cancellationToken); + + public virtual async Task ReadI64Async() + { + return await ReadI64Async(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadI64Async(CancellationToken cancellationToken); + + public virtual async Task ReadDoubleAsync() + { + return await ReadDoubleAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadDoubleAsync(CancellationToken cancellationToken); + + public virtual async Task ReadStringAsync() + { + return await ReadStringAsync(CancellationToken.None).ConfigureAwait(false); + } + + public virtual async Task ReadStringAsync(CancellationToken cancellationToken) + { + var buf = await ReadBinaryAsync(cancellationToken).ConfigureAwait(false); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + public virtual async Task ReadBinaryAsync() + { + return await ReadBinaryAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadBinaryAsync(CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/TProtocolDecorator.cs b/lib/Thrift/Protocols/TProtocolDecorator.cs new file mode 100644 index 00000000000..b1c47a9200e --- /dev/null +++ b/lib/Thrift/Protocols/TProtocolDecorator.cs @@ -0,0 +1,247 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; + +namespace Thrift.Protocols +{ + // ReSharper disable once InconsistentNaming + /// + /// TProtocolDecorator forwards all requests to an enclosed TProtocol instance, + /// providing a way to author concise concrete decorator subclasses.While it has + /// no abstract methods, it is marked abstract as a reminder that by itself, + /// it does not modify the behaviour of the enclosed TProtocol. + /// + public abstract class TProtocolDecorator : TProtocol + { + private readonly TProtocol _wrappedProtocol; + + protected TProtocolDecorator(TProtocol protocol) + : base(protocol.Transport) + { + _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol)); + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMessageBeginAsync(message, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMessageEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStructEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldBeginAsync(field, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldStopAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMapBeginAsync(map, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMapEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteListBeginAsync(list, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteListEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteSetBeginAsync(set, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteSetEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteBoolAsync(b, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteByteAsync(b, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI16Async(i16, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI32Async(i32, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI64Async(i64, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteDoubleAsync(d, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStringAsync(s, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadMessageBeginAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadMessageEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadStructBeginAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadStructEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadFieldBeginAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadFieldEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadMapBeginAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadMapEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadListBeginAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadListEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadSetBeginAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadSetEndAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadBoolAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadByteAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI16Async(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI32Async(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI64Async(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadDoubleAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadStringAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadStringAsync(cancellationToken).ConfigureAwait(false); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadBinaryAsync(cancellationToken).ConfigureAwait(false); + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/TProtocolException.cs b/lib/Thrift/Protocols/TProtocolException.cs new file mode 100644 index 00000000000..8c67c3bfdf9 --- /dev/null +++ b/lib/Thrift/Protocols/TProtocolException.cs @@ -0,0 +1,59 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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. + +// ReSharper disable InconsistentNaming +namespace Thrift.Protocols +{ + public class TProtocolException : TException + { + // do not rename public constants - they used in generated files + public const int UNKNOWN = 0; + public const int INVALID_DATA = 1; + public const int NEGATIVE_SIZE = 2; + public const int SIZE_LIMIT = 3; + public const int BAD_VERSION = 4; + public const int NOT_IMPLEMENTED = 5; + public const int DEPTH_LIMIT = 6; + + protected int Type = UNKNOWN; + + public TProtocolException() + { + } + + public TProtocolException(int type) + { + Type = type; + } + + public TProtocolException(int type, string message) + : base(message) + { + Type = type; + } + + public TProtocolException(string message) + : base(message) + { + } + + public int GetExceptionType() + { + return Type; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Utilities/TBase64Helper.cs b/lib/Thrift/Protocols/Utilities/TBase64Helper.cs new file mode 100644 index 00000000000..7eff5e181d1 --- /dev/null +++ b/lib/Thrift/Protocols/Utilities/TBase64Helper.cs @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; + +namespace Thrift.Protocols.Utilities +{ + // ReSharper disable once InconsistentNaming + internal static class TBase64Helper + { + //TODO: Constants + //TODO: Check for args + //TODO: Unitests + + internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + private static readonly int[] DecodeTable = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; + + if (len == 3) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; + dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; + } + else if (len == 2) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; + } + else + { + // len == 1 + dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; + } + } + + internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); + + if (len > 2) + { + dst[dstOff + 1] = + (byte) + (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); + if (len > 3) + { + dst[dstOff + 2] = + (byte) + (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); + } + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Utilities/TBase64Utils.cs b/lib/Thrift/Protocols/Utilities/TBase64Utils.cs new file mode 100644 index 00000000000..15fd45cbef9 --- /dev/null +++ b/lib/Thrift/Protocols/Utilities/TBase64Utils.cs @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; + +namespace Thrift.Protocols.Utilities +{ + // ReSharper disable once InconsistentNaming + internal static class TBase64Utils + { + //TODO: Constants + //TODO: Check for args + //TODO: Unitests + + internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + private static readonly int[] DecodeTable = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; + + if (len == 3) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; + dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; + } + else if (len == 2) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; + } + else + { + // len == 1 + dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; + } + } + + internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); + + if (len > 2) + { + dst[dstOff + 1] = + (byte) + (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); + if (len > 3) + { + dst[dstOff + 2] = + (byte) + (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); + } + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs b/lib/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs new file mode 100644 index 00000000000..93eff785555 --- /dev/null +++ b/lib/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TJSONProtocolConstants + { + //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/) + // can be possible to get better performance and also better GC + + public static readonly byte[] Comma = {(byte) ','}; + public static readonly byte[] Colon = {(byte) ':'}; + public static readonly byte[] LeftBrace = {(byte) '{'}; + public static readonly byte[] RightBrace = {(byte) '}'}; + public static readonly byte[] LeftBracket = {(byte) '['}; + public static readonly byte[] RightBracket = {(byte) ']'}; + public static readonly byte[] Quote = {(byte) '"'}; + public static readonly byte[] Backslash = {(byte) '\\'}; + + public static readonly byte[] JsonCharTable = + { + 0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray(); + public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'}; + public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'}; + + public static class TypeNames + { + public static readonly byte[] NameBool = { (byte)'t', (byte)'f' }; + public static readonly byte[] NameByte = { (byte)'i', (byte)'8' }; + public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' }; + public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' }; + public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' }; + public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' }; + public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' }; + public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' }; + public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' }; + public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' }; + public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' }; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs b/lib/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs new file mode 100644 index 00000000000..adc26a9af01 --- /dev/null +++ b/lib/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs @@ -0,0 +1,176 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Protocols.Entities; + +namespace Thrift.Protocols.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TJSONProtocolHelper + { + public static byte[] GetTypeNameForTypeId(TType typeId) + { + switch (typeId) + { + case TType.Bool: + return TJSONProtocolConstants.TypeNames.NameBool; + case TType.Byte: + return TJSONProtocolConstants.TypeNames.NameByte; + case TType.I16: + return TJSONProtocolConstants.TypeNames.NameI16; + case TType.I32: + return TJSONProtocolConstants.TypeNames.NameI32; + case TType.I64: + return TJSONProtocolConstants.TypeNames.NameI64; + case TType.Double: + return TJSONProtocolConstants.TypeNames.NameDouble; + case TType.String: + return TJSONProtocolConstants.TypeNames.NameString; + case TType.Struct: + return TJSONProtocolConstants.TypeNames.NameStruct; + case TType.Map: + return TJSONProtocolConstants.TypeNames.NameMap; + case TType.Set: + return TJSONProtocolConstants.TypeNames.NameSet; + case TType.List: + return TJSONProtocolConstants.TypeNames.NameList; + default: + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); + } + } + + public static TType GetTypeIdForTypeName(byte[] name) + { + var result = TType.Stop; + if (name.Length > 1) + { + switch (name[0]) + { + case (byte) 'd': + result = TType.Double; + break; + case (byte) 'i': + switch (name[1]) + { + case (byte) '8': + result = TType.Byte; + break; + case (byte) '1': + result = TType.I16; + break; + case (byte) '3': + result = TType.I32; + break; + case (byte) '6': + result = TType.I64; + break; + } + break; + case (byte) 'l': + result = TType.List; + break; + case (byte) 'm': + result = TType.Map; + break; + case (byte) 'r': + result = TType.Struct; + break; + case (byte) 's': + if (name[1] == (byte) 't') + { + result = TType.String; + } + else if (name[1] == (byte) 'e') + { + result = TType.Set; + } + break; + case (byte) 't': + result = TType.Bool; + break; + } + } + if (result == TType.Stop) + { + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); + } + return result; + } + + /// + /// Return true if the given byte could be a valid part of a JSON number. + /// + public static bool IsJsonNumeric(byte b) + { + switch (b) + { + case (byte)'+': + case (byte)'-': + case (byte)'.': + case (byte)'0': + case (byte)'1': + case (byte)'2': + case (byte)'3': + case (byte)'4': + case (byte)'5': + case (byte)'6': + case (byte)'7': + case (byte)'8': + case (byte)'9': + case (byte)'E': + case (byte)'e': + return true; + default: + return false; + } + } + + /// + /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its + /// corresponding hex value + /// + public static byte ToHexVal(byte ch) + { + if (ch >= '0' && ch <= '9') + { + return (byte)((char)ch - '0'); + } + + if (ch >= 'a' && ch <= 'f') + { + ch += 10; + return (byte)((char)ch - 'a'); + } + + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); + } + + /// + /// Convert a byte containing a hex value to its corresponding hex character + /// + public static byte ToHexChar(byte val) + { + val &= 0x0F; + if (val < 10) + { + return (byte)((char)val + '0'); + } + val -= 10; + return (byte)((char)val + 'a'); + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Protocols/Utilities/TProtocolUtil.cs b/lib/Thrift/Protocols/Utilities/TProtocolUtil.cs new file mode 100644 index 00000000000..ffc466c8825 --- /dev/null +++ b/lib/Thrift/Protocols/Utilities/TProtocolUtil.cs @@ -0,0 +1,110 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols.Entities; + +namespace Thrift.Protocols.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TProtocolUtil + { + public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + protocol.IncrementRecursionDepth(); + try + { + switch (type) + { + case TType.Bool: + await protocol.ReadBoolAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.Byte: + await protocol.ReadByteAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.I16: + await protocol.ReadI16Async(cancellationToken).ConfigureAwait(false); + break; + case TType.I32: + await protocol.ReadI32Async(cancellationToken).ConfigureAwait(false); + break; + case TType.I64: + await protocol.ReadI64Async(cancellationToken).ConfigureAwait(false); + break; + case TType.Double: + await protocol.ReadDoubleAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.String: + // Don't try to decode the string, just skip it. + await protocol.ReadBinaryAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.Struct: + await protocol.ReadStructBeginAsync(cancellationToken).ConfigureAwait(false); + while (true) + { + var field = await protocol.ReadFieldBeginAsync(cancellationToken).ConfigureAwait(false); + if (field.Type == TType.Stop) + { + break; + } + await SkipAsync(protocol, field.Type, cancellationToken).ConfigureAwait(false); + await protocol.ReadFieldEndAsync(cancellationToken).ConfigureAwait(false); + } + await protocol.ReadStructEndAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.Map: + var map = await protocol.ReadMapBeginAsync(cancellationToken).ConfigureAwait(false); + for (var i = 0; i < map.Count; i++) + { + await SkipAsync(protocol, map.KeyType, cancellationToken).ConfigureAwait(false); + await SkipAsync(protocol, map.ValueType, cancellationToken).ConfigureAwait(false); + } + await protocol.ReadMapEndAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.Set: + var set = await protocol.ReadSetBeginAsync(cancellationToken).ConfigureAwait(false); + for (var i = 0; i < set.Count; i++) + { + await SkipAsync(protocol, set.ElementType, cancellationToken).ConfigureAwait(false); + } + await protocol.ReadSetEndAsync(cancellationToken).ConfigureAwait(false); + break; + case TType.List: + var list = await protocol.ReadListBeginAsync(cancellationToken).ConfigureAwait(false); + for (var i = 0; i < list.Count; i++) + { + await SkipAsync(protocol, list.ElementType, cancellationToken).ConfigureAwait(false); + } + await protocol.ReadListEndAsync(cancellationToken).ConfigureAwait(false); + break; + default: + throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); + } + } + finally + { + protocol.DecrementRecursionDepth(); + } + } + } +} diff --git a/lib/Thrift/README.md b/lib/Thrift/README.md new file mode 100644 index 00000000000..acd7ed2ceb9 --- /dev/null +++ b/lib/Thrift/README.md @@ -0,0 +1,12 @@ +# Thrift Protocol .Net Implementation + +This is the .net implementation of the Apache Thrift protocol. This code was forked from the [Jaeger Tracing C# Client Repository](https://github.com/jaegertracing/jaeger-client-csharp). + +Path: src/Thrift + +commitID: 0794ea71cb6e58f7bf0f0ef2c0c8ceceb1d8b6d9 + +The following changes were made to this fork: + +* ConfigureAwait(false) added to async calls to prevent deadlocks. +* THttpClientTransport uses WebRequestHandler() in .NET Framework 4.6 builds. \ No newline at end of file diff --git a/lib/Thrift/Server/TBaseServer.cs b/lib/Thrift/Server/TBaseServer.cs new file mode 100644 index 00000000000..f7af8174850 --- /dev/null +++ b/lib/Thrift/Server/TBaseServer.cs @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols; +using Thrift.Transports; + +namespace Thrift.Server +{ + // ReSharper disable once InconsistentNaming + public abstract class TBaseServer + { + protected ITProtocolFactory InputProtocolFactory; + protected TTransportFactory InputTransportFactory; + protected ITProcessorFactory ItProcessorFactory; + protected ITProtocolFactory OutputProtocolFactory; + protected TTransportFactory OutputTransportFactory; + + protected TServerEventHandler ServerEventHandler; + protected TServerTransport ServerTransport; + + protected TBaseServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, + TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, + ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory) + { + ItProcessorFactory = itProcessorFactory ?? throw new ArgumentNullException(nameof(itProcessorFactory)); + ServerTransport = serverTransport; + InputTransportFactory = inputTransportFactory ?? throw new ArgumentNullException(nameof(inputTransportFactory)); + OutputTransportFactory = outputTransportFactory ?? throw new ArgumentNullException(nameof(outputTransportFactory)); + InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); + OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); + } + + public void SetEventHandler(TServerEventHandler seh) + { + ServerEventHandler = seh; + } + + public TServerEventHandler GetEventHandler() + { + return ServerEventHandler; + } + + public abstract void Stop(); + + public virtual void Start() + { + // do nothing + } + + public virtual async Task ServeAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Server/TServerEventHandler.cs b/lib/Thrift/Server/TServerEventHandler.cs new file mode 100644 index 00000000000..733bb4bef7c --- /dev/null +++ b/lib/Thrift/Server/TServerEventHandler.cs @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols; +using Thrift.Transports; + +namespace Thrift.Server +{ + //TODO: replacement by event? + + /// + /// Interface implemented by server users to handle events from the server + /// + // ReSharper disable once InconsistentNaming + public interface TServerEventHandler + { + /// + /// Called before the server begins */ + /// + Task PreServeAsync(CancellationToken cancellationToken); + + /// + /// Called when a new client has connected and is about to being processing */ + /// + Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken); + + /// + /// Called when a client has finished request-handling to delete server context */ + /// + Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, + CancellationToken cancellationToken); + + /// + /// Called when a client is about to call the processor */ + /// + Task ProcessContextAsync(object serverContext, TClientTransport transport, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/Thrift/Settings.Stylecop b/lib/Thrift/Settings.Stylecop new file mode 100644 index 00000000000..e74fe5aed50 --- /dev/null +++ b/lib/Thrift/Settings.Stylecop @@ -0,0 +1,5 @@ + + + False + + \ No newline at end of file diff --git a/lib/Thrift/SingletonTProcessorFactory.cs b/lib/Thrift/SingletonTProcessorFactory.cs new file mode 100644 index 00000000000..c35123348ba --- /dev/null +++ b/lib/Thrift/SingletonTProcessorFactory.cs @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Server; +using Thrift.Transports; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class SingletonTProcessorFactory : ITProcessorFactory + { + private readonly ITAsyncProcessor _tAsyncProcessor; + + public SingletonTProcessorFactory(ITAsyncProcessor tAsyncProcessor) + { + _tAsyncProcessor = tAsyncProcessor; + } + + public ITAsyncProcessor GetAsyncProcessor(TClientTransport trans, TBaseServer baseServer = null) + { + return _tAsyncProcessor; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/TApplicationException.cs b/lib/Thrift/TApplicationException.cs new file mode 100644 index 00000000000..7e96272239a --- /dev/null +++ b/lib/Thrift/TApplicationException.cs @@ -0,0 +1,150 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols; +using Thrift.Protocols.Entities; +using Thrift.Protocols.Utilities; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TApplicationException : TException + { + public enum ExceptionType + { + Unknown, + UnknownMethod, + InvalidMessageType, + WrongMethodName, + BadSequenceId, + MissingResult, + InternalError, + ProtocolError, + InvalidTransform, + InvalidProtocol, + UnsupportedClientType + } + + private const int MessageTypeFieldId = 1; + private const int ExTypeFieldId = 2; + + protected ExceptionType Type; + + public TApplicationException() + { + } + + public TApplicationException(ExceptionType type) + { + Type = type; + } + + public TApplicationException(ExceptionType type, string message) + : base(message) + { + Type = type; + } + + public static async Task ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) + { + string message = null; + var type = ExceptionType.Unknown; + + await inputProtocol.ReadStructBeginAsync(cancellationToken).ConfigureAwait(false); + while (true) + { + var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken).ConfigureAwait(false); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case MessageTypeFieldId: + if (field.Type == TType.String) + { + message = await inputProtocol.ReadStringAsync(cancellationToken).ConfigureAwait(false); + } + else + { + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken).ConfigureAwait(false); + } + break; + case ExTypeFieldId: + if (field.Type == TType.I32) + { + type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken).ConfigureAwait(false); + } + else + { + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken).ConfigureAwait(false); + } + break; + default: + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken).ConfigureAwait(false); + break; + } + + await inputProtocol.ReadFieldEndAsync(cancellationToken).ConfigureAwait(false); + } + + await inputProtocol.ReadStructEndAsync(cancellationToken).ConfigureAwait(false); + + return new TApplicationException(type, message); + } + + public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + const string messageTypeFieldName = "message"; + const string exTypeFieldName = "exType"; + const string structApplicationExceptionName = "TApplicationException"; + + var struc = new TStruct(structApplicationExceptionName); + var field = new TField(); + + await outputProtocol.WriteStructBeginAsync(struc, cancellationToken).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(Message)) + { + field.Name = messageTypeFieldName; + field.Type = TType.String; + field.ID = MessageTypeFieldId; + await outputProtocol.WriteFieldBeginAsync(field, cancellationToken).ConfigureAwait(false); + await outputProtocol.WriteStringAsync(Message, cancellationToken).ConfigureAwait(false); + await outputProtocol.WriteFieldEndAsync(cancellationToken).ConfigureAwait(false); + } + + field.Name = exTypeFieldName; + field.Type = TType.I32; + field.ID = ExTypeFieldId; + + await outputProtocol.WriteFieldBeginAsync(field, cancellationToken).ConfigureAwait(false); + await outputProtocol.WriteI32Async((int) Type, cancellationToken).ConfigureAwait(false); + await outputProtocol.WriteFieldEndAsync(cancellationToken).ConfigureAwait(false); + await outputProtocol.WriteFieldStopAsync(cancellationToken).ConfigureAwait(false); + await outputProtocol.WriteStructEndAsync(cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/lib/Thrift/TBaseClient.cs b/lib/Thrift/TBaseClient.cs new file mode 100644 index 00000000000..5284a124ffe --- /dev/null +++ b/lib/Thrift/TBaseClient.cs @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + /// + /// TBaseClient. + /// Base client for generated clients. + /// Do not change this class without checking generated code (namings, etc.) + /// + public abstract class TBaseClient + { + private readonly TProtocol _inputProtocol; + private readonly TProtocol _outputProtocol; + private bool _isDisposed; + private int _seqId; + public readonly Guid ClientId = Guid.NewGuid(); + + protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol) + { + _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol)); + _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol)); + } + + public TProtocol InputProtocol => _inputProtocol; + + public TProtocol OutputProtocol => _outputProtocol; + + public int SeqId + { + get { return ++_seqId; } + } + + public virtual async Task OpenTransportAsync() + { + await OpenTransportAsync(CancellationToken.None).ConfigureAwait(false); + } + + public virtual async Task OpenTransportAsync(CancellationToken cancellationToken) + { + if (!_inputProtocol.Transport.IsOpen) + { + await _inputProtocol.Transport.OpenAsync(cancellationToken).ConfigureAwait(false); + } + + if (!_inputProtocol.Transport.IsOpen) + { + await _outputProtocol.Transport.OpenAsync(cancellationToken).ConfigureAwait(false); + } + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputProtocol?.Dispose(); + _outputProtocol?.Dispose(); + } + } + + _isDisposed = true; + } + } +} diff --git a/lib/Thrift/TException.cs b/lib/Thrift/TException.cs new file mode 100644 index 00000000000..6aa588d7f34 --- /dev/null +++ b/lib/Thrift/TException.cs @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TException : Exception + { + public TException() + { + } + + public TException(string message) + : base(message) + { + } + } +} \ No newline at end of file diff --git a/lib/Thrift/TMultiplexedProcessor.cs b/lib/Thrift/TMultiplexedProcessor.cs new file mode 100644 index 00000000000..d58d697929e --- /dev/null +++ b/lib/Thrift/TMultiplexedProcessor.cs @@ -0,0 +1,143 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocols; +using Thrift.Protocols.Entities; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TMultiplexedProcessor : ITAsyncProcessor + { + //TODO: Localization + + private readonly Dictionary _serviceProcessorMap = + new Dictionary(); + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) + { + return await ProcessAsync(iprot, oprot, CancellationToken.None).ConfigureAwait(false); + } + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + try + { + var message = await iprot.ReadMessageBeginAsync(cancellationToken).ConfigureAwait(false); + + if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) + { + await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidMessageType, + "Message exType CALL or ONEWAY expected", cancellationToken); + return false; + } + + // Extract the service name + var index = message.Name.IndexOf(TMultiplexedProtocol.Separator, StringComparison.Ordinal); + if (index < 0) + { + await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidProtocol, + $"Service name not found in message name: {message.Name}. Did you forget to use a TMultiplexProtocol in your client?", + cancellationToken); + return false; + } + + // Create a new TMessage, something that can be consumed by any TProtocol + var serviceName = message.Name.Substring(0, index); + ITAsyncProcessor actualProcessor; + if (!_serviceProcessorMap.TryGetValue(serviceName, out actualProcessor)) + { + await FailAsync(oprot, message, TApplicationException.ExceptionType.InternalError, + $"Service name not found: {serviceName}. Did you forget to call RegisterProcessor()?", + cancellationToken); + return false; + } + + // Create a new TMessage, removing the service name + var newMessage = new TMessage( + message.Name.Substring(serviceName.Length + TMultiplexedProtocol.Separator.Length), + message.Type, + message.SeqID); + + // Dispatch processing to the stored processor + return + await + actualProcessor.ProcessAsync(new StoredMessageProtocol(iprot, newMessage), oprot, + cancellationToken); + } + catch (IOException) + { + return false; // similar to all other processors + } + } + + public void RegisterProcessor(string serviceName, ITAsyncProcessor processor) + { + if (_serviceProcessorMap.ContainsKey(serviceName)) + { + throw new InvalidOperationException( + $"Processor map already contains processor with name: '{serviceName}'"); + } + + _serviceProcessorMap.Add(serviceName, processor); + } + + private async Task FailAsync(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, + string etxt, CancellationToken cancellationToken) + { + var appex = new TApplicationException(extype, etxt); + + var newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); + + await oprot.WriteMessageBeginAsync(newMessage, cancellationToken).ConfigureAwait(false); + await appex.WriteAsync(oprot, cancellationToken).ConfigureAwait(false); + await oprot.WriteMessageEndAsync(cancellationToken).ConfigureAwait(false); + await oprot.Transport.FlushAsync(cancellationToken).ConfigureAwait(false); + } + + private class StoredMessageProtocol : TProtocolDecorator + { + readonly TMessage _msgBegin; + + public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) + : base(protocol) + { + _msgBegin = messageBegin; + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + return _msgBegin; + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Thrift.csproj b/lib/Thrift/Thrift.csproj new file mode 100644 index 00000000000..3dbd8203b50 --- /dev/null +++ b/lib/Thrift/Thrift.csproj @@ -0,0 +1,17 @@ + + + + net46;netstandard2.0 + netstandard2.0 + OpenTelemetry authors + https://opentelemetry.io/img/logos/opentelemetry-icon-color.png + https://OpenTelemetry.io + Tracing;OpenTelemetry;Management;Monitoring;Jaeger;distributed-tracing + + + + + + + + diff --git a/lib/Thrift/Transports/Client/TBufferedClientTransport.cs b/lib/Thrift/Transports/Client/TBufferedClientTransport.cs new file mode 100644 index 00000000000..58f08899c3a --- /dev/null +++ b/lib/Thrift/Transports/Client/TBufferedClientTransport.cs @@ -0,0 +1,206 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + // ReSharper disable once InconsistentNaming + public class TBufferedClientTransport : TClientTransport + { + private readonly int _bufSize; + private readonly MemoryStream _inputBuffer = new MemoryStream(0); + private readonly MemoryStream _outputBuffer = new MemoryStream(0); + private readonly TClientTransport _transport; + private bool _isDisposed; + + //TODO: should support only specified input transport? + public TBufferedClientTransport(TClientTransport transport, int bufSize = 1024) + { + if (bufSize <= 0) + { + throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); + } + + _transport = transport ?? throw new ArgumentNullException(nameof(transport)); + _bufSize = bufSize; + } + + public TClientTransport UnderlyingTransport + { + get + { + CheckNotDisposed(); + + return _transport; + } + } + + public override bool IsOpen => !_isDisposed && _transport.IsOpen; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + await _transport.OpenAsync(cancellationToken).ConfigureAwait(false); + } + + public override void Close() + { + CheckNotDisposed(); + + _transport.Close(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + //TODO: investigate how it should work correctly + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (_inputBuffer.Capacity < _bufSize) + { + _inputBuffer.Capacity = _bufSize; + } + + var got = await _inputBuffer.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + if (got > 0) + { + return got; + } + + _inputBuffer.Seek(0, SeekOrigin.Begin); + _inputBuffer.SetLength(_inputBuffer.Capacity); + + ArraySegment bufSegment; + _inputBuffer.TryGetBuffer(out bufSegment); + + // investigate + var filled = await _transport.ReadAsync(bufSegment.Array, 0, (int) _inputBuffer.Length, cancellationToken).ConfigureAwait(false); + _inputBuffer.SetLength(filled); + + if (filled == 0) + { + return 0; + } + + return await ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // Relative offset from "off" argument + var writtenCount = 0; + if (_outputBuffer.Length > 0) + { + var capa = (int) (_outputBuffer.Capacity - _outputBuffer.Length); + var writeSize = capa <= length ? capa : length; + await _outputBuffer.WriteAsync(buffer, offset, writeSize, cancellationToken).ConfigureAwait(false); + + writtenCount += writeSize; + if (writeSize == capa) + { + //ArraySegment bufSegment; + //_outputBuffer.TryGetBuffer(out bufSegment); + var data = _outputBuffer.ToArray(); + //await _transport.WriteAsync(bufSegment.Array, cancellationToken).ConfigureAwait(false); + await _transport.WriteAsync(data, cancellationToken).ConfigureAwait(false); + _outputBuffer.SetLength(0); + } + } + + while (length - writtenCount >= _bufSize) + { + await _transport.WriteAsync(buffer, offset + writtenCount, _bufSize, cancellationToken).ConfigureAwait(false); + writtenCount += _bufSize; + } + + var remain = length - writtenCount; + if (remain > 0) + { + if (_outputBuffer.Capacity < _bufSize) + { + _outputBuffer.Capacity = _bufSize; + } + await _outputBuffer.WriteAsync(buffer, offset + writtenCount, remain, cancellationToken).ConfigureAwait(false); + } + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (_outputBuffer.Length > 0) + { + //ArraySegment bufSegment; + var data = _outputBuffer.ToArray(); // TryGetBuffer(out bufSegment); + + await _transport.WriteAsync(data /*bufSegment.Array*/, cancellationToken).ConfigureAwait(false); + _outputBuffer.SetLength(0); + } + + await _transport.FlushAsync(cancellationToken).ConfigureAwait(false); + } + + private void CheckNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(_transport)); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputBuffer?.Dispose(); + _outputBuffer?.Dispose(); + _transport?.Dispose(); + } + } + _isDisposed = true; + } + } +} diff --git a/lib/Thrift/Transports/Client/TFramedClientTransport.cs b/lib/Thrift/Transports/Client/TFramedClientTransport.cs new file mode 100644 index 00000000000..85c43db06f8 --- /dev/null +++ b/lib/Thrift/Transports/Client/TFramedClientTransport.cs @@ -0,0 +1,201 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + //TODO: check for correct implementation + + // ReSharper disable once InconsistentNaming + public class TFramedClientTransport : TClientTransport + { + private const int HeaderSize = 4; + private readonly byte[] _headerBuf = new byte[HeaderSize]; + private readonly MemoryStream _readBuffer = new MemoryStream(1024); + private readonly TClientTransport _transport; + private readonly MemoryStream _writeBuffer = new MemoryStream(1024); + + private bool _isDisposed; + + public TFramedClientTransport(TClientTransport transport) + { + _transport = transport ?? throw new ArgumentNullException(nameof(transport)); + + InitWriteBuffer(); + } + + public override bool IsOpen => !_isDisposed && _transport.IsOpen; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + await _transport.OpenAsync(cancellationToken).ConfigureAwait(false); + } + + public override void Close() + { + CheckNotDisposed(); + + _transport.Close(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + var got = await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + if (got > 0) + { + return got; + } + + // Read another frame of data + await ReadFrameAsync(cancellationToken).ConfigureAwait(false); + + return await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + private async Task ReadFrameAsync(CancellationToken cancellationToken) + { + await _transport.ReadAllAsync(_headerBuf, 0, HeaderSize, cancellationToken).ConfigureAwait(false); + + var size = DecodeFrameSize(_headerBuf); + + _readBuffer.SetLength(size); + _readBuffer.Seek(0, SeekOrigin.Begin); + + ArraySegment bufSegment; + _readBuffer.TryGetBuffer(out bufSegment); + + var buff = bufSegment.Array; + + await _transport.ReadAllAsync(buff, 0, size, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (_writeBuffer.Length + length > int.MaxValue) + { + await FlushAsync(cancellationToken).ConfigureAwait(false); + } + + await _writeBuffer.WriteAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + //ArraySegment bufSegment; + //_writeBuffer.TryGetBuffer(out bufSegment); + //var buf = bufSegment.Array; + var buf = _writeBuffer.ToArray(); + + //var len = (int)_writeBuffer.Length; + var dataLen = (int) _writeBuffer.Length - HeaderSize; + if (dataLen < 0) + { + throw new InvalidOperationException(); // logic error actually + } + + // Inject message header into the reserved buffer space + EncodeFrameSize(dataLen, buf); + + // Send the entire message at once + await _transport.WriteAsync(buf, cancellationToken).ConfigureAwait(false); + + InitWriteBuffer(); + + await _transport.FlushAsync(cancellationToken).ConfigureAwait(false); + } + + private void InitWriteBuffer() + { + // Reserve space for message header to be put right before sending it out + _writeBuffer.SetLength(HeaderSize); + _writeBuffer.Seek(0, SeekOrigin.End); + } + + private static void EncodeFrameSize(int frameSize, byte[] buf) + { + buf[0] = (byte) (0xff & (frameSize >> 24)); + buf[1] = (byte) (0xff & (frameSize >> 16)); + buf[2] = (byte) (0xff & (frameSize >> 8)); + buf[3] = (byte) (0xff & (frameSize)); + } + + private static int DecodeFrameSize(byte[] buf) + { + return + ((buf[0] & 0xff) << 24) | + ((buf[1] & 0xff) << 16) | + ((buf[2] & 0xff) << 8) | + (buf[3] & 0xff); + } + + + private void CheckNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("TFramedClientTransport"); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _readBuffer?.Dispose(); + _writeBuffer?.Dispose(); + _transport?.Dispose(); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Client/THttpClientTransport.cs b/lib/Thrift/Transports/Client/THttpClientTransport.cs new file mode 100644 index 00000000000..6ea3061c9e7 --- /dev/null +++ b/lib/Thrift/Transports/Client/THttpClientTransport.cs @@ -0,0 +1,235 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + // ReSharper disable once InconsistentNaming + public class THttpClientTransport : TClientTransport + { + private readonly X509Certificate[] _certificates; + private readonly Uri _uri; + + // Timeouts in milliseconds + private int _connectTimeout = 30000; + private HttpClient _httpClient; + private Stream _inputStream; + + private bool _isDisposed; + private MemoryStream _outputStream = new MemoryStream(); + private static readonly MediaTypeWithQualityHeaderValue ApacheThriftMediaType = new MediaTypeWithQualityHeaderValue("application/vnd.apache.thrift.binary"); + + public THttpClientTransport(Uri u, IDictionary customHeaders) + : this(u, Enumerable.Empty(), customHeaders) + { + } + + public THttpClientTransport(Uri u, IEnumerable certificates, + IDictionary customHeaders) + { + _uri = u; + _certificates = (certificates ?? Enumerable.Empty()).ToArray(); + CustomHeaders = customHeaders; + + // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 + // this can be switched to default way (create client->use->dispose per flush) later + _httpClient = CreateClient(); + } + + public IDictionary CustomHeaders { get; } + + public int ConnectTimeout + { + set { _connectTimeout = value; } + } + + public override bool IsOpen => true; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override void Close() + { + if (_inputStream != null) + { + _inputStream.Dispose(); + _inputStream = null; + } + + if (_outputStream != null) + { + _outputStream.Dispose(); + _outputStream = null; + } + + if (_httpClient != null) + { + _httpClient.Dispose(); + _httpClient = null; + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (_inputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); + } + + try + { + var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + + if (ret == -1) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); + } + + return ret; + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); + } + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + await _outputStream.WriteAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + private HttpClient CreateClient() + { +#if NET46 + var handler = new WebRequestHandler(); +#else + var handler = new HttpClientHandler(); +#endif + if (_certificates.Length > 0) + { + handler.ClientCertificates.AddRange(_certificates); + } + + var httpClient = new HttpClient(handler); + + if (_connectTimeout > 0) + { + httpClient.Timeout = TimeSpan.FromSeconds(_connectTimeout); + } + + httpClient.DefaultRequestHeaders.Accept.Add(ApacheThriftMediaType); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "1.0.0")); + + if (CustomHeaders != null) + { + foreach (var item in CustomHeaders) + { + httpClient.DefaultRequestHeaders.Add(item.Key, item.Value); + } + } + + return httpClient; + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + try + { + try + { + if (_outputStream.CanSeek) + { + _outputStream.Seek(0, SeekOrigin.Begin); + } + + using (var outStream = new StreamContent(_outputStream)) + { + outStream.Headers.ContentType = ApacheThriftMediaType; + var msg = await _httpClient.PostAsync(_uri, outStream, cancellationToken).ConfigureAwait(false); + + msg.EnsureSuccessStatusCode(); + + if (_inputStream != null) + { + _inputStream.Dispose(); + _inputStream = null; + } + + _inputStream = await msg.Content.ReadAsStreamAsync().ConfigureAwait(false); + if (_inputStream.CanSeek) + { + _inputStream.Seek(0, SeekOrigin.Begin); + } + } + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); + } + catch (HttpRequestException wx) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Couldn't connect to server: " + wx); + } + } + finally + { + _outputStream = new MemoryStream(); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputStream?.Dispose(); + _outputStream?.Dispose(); + _httpClient?.Dispose(); + } + } + _isDisposed = true; + } + } +} diff --git a/lib/Thrift/Transports/Client/TMemoryBufferClientTransport.cs b/lib/Thrift/Transports/Client/TMemoryBufferClientTransport.cs new file mode 100644 index 00000000000..92c6bc3ae68 --- /dev/null +++ b/lib/Thrift/Transports/Client/TMemoryBufferClientTransport.cs @@ -0,0 +1,97 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + // ReSharper disable once InconsistentNaming + public class TMemoryBufferClientTransport : TClientTransport + { + private readonly MemoryStream _byteStream; + private bool _isDisposed; + + public TMemoryBufferClientTransport() + { + _byteStream = new MemoryStream(); + } + + public TMemoryBufferClientTransport(byte[] buf) + { + _byteStream = new MemoryStream(buf); + } + + public override bool IsOpen => true; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override void Close() + { + // do nothing + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + return await _byteStream.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + await _byteStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + await _byteStream.WriteAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public byte[] GetBuffer() + { + return _byteStream.ToArray(); + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _byteStream?.Dispose(); + } + } + _isDisposed = true; + } + } +} diff --git a/lib/Thrift/Transports/Client/TNamedPipeClientTransport.cs b/lib/Thrift/Transports/Client/TNamedPipeClientTransport.cs new file mode 100644 index 00000000000..b137ae3687c --- /dev/null +++ b/lib/Thrift/Transports/Client/TNamedPipeClientTransport.cs @@ -0,0 +1,95 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.IO.Pipes; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + // ReSharper disable once InconsistentNaming + public class TNamedPipeClientTransport : TClientTransport + { + private NamedPipeClientStream _client; + + public TNamedPipeClientTransport(string pipe) : this(".", pipe) + { + } + + public TNamedPipeClientTransport(string server, string pipe) + { + var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; + + _client = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None); + } + + public override bool IsOpen => _client != null && _client.IsConnected; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); + } + + await _client.ConnectAsync(cancellationToken).ConfigureAwait(false); + } + + public override void Close() + { + if (_client != null) + { + _client.Dispose(); + _client = null; + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (_client == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + return await _client.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (_client == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + await _client.WriteAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + protected override void Dispose(bool disposing) + { + _client.Dispose(); + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Client/TSocketClientTransport.cs b/lib/Thrift/Transports/Client/TSocketClientTransport.cs new file mode 100644 index 00000000000..806c9b61cc8 --- /dev/null +++ b/lib/Thrift/Transports/Client/TSocketClientTransport.cs @@ -0,0 +1,139 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + // ReSharper disable once InconsistentNaming + public class TSocketClientTransport : TStreamClientTransport + { + private bool _isDisposed; + + public TSocketClientTransport(TcpClient client) + { + TcpClient = client ?? throw new ArgumentNullException(nameof(client)); + + if (IsOpen) + { + InputStream = client.GetStream(); + OutputStream = client.GetStream(); + } + } + + public TSocketClientTransport(IPAddress host, int port) + : this(host, port, 0) + { + } + + public TSocketClientTransport(IPAddress host, int port, int timeout) + { + Host = host; + Port = port; + + TcpClient = new TcpClient(); + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; + TcpClient.Client.NoDelay = true; + } + + public TcpClient TcpClient { get; private set; } + public IPAddress Host { get; } + public int Port { get; } + + public int Timeout + { + set + { + if (TcpClient != null) + { + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = value; + } + } + } + + public override bool IsOpen + { + get + { + if (TcpClient == null) + { + return false; + } + + return TcpClient.Connected; + } + } + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (Port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (TcpClient == null) + { + throw new InvalidOperationException("Invalid or not initialized tcp client"); + } + + await TcpClient.ConnectAsync(Host, Port).ConfigureAwait(false); + + InputStream = TcpClient.GetStream(); + OutputStream = TcpClient.GetStream(); + } + + public override void Close() + { + base.Close(); + + if (TcpClient != null) + { + TcpClient.Dispose(); + TcpClient = null; + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + TcpClient?.Dispose(); + + base.Dispose(disposing); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Client/TStreamClientTransport.cs b/lib/Thrift/Transports/Client/TStreamClientTransport.cs new file mode 100644 index 00000000000..e1a6d2b6e5f --- /dev/null +++ b/lib/Thrift/Transports/Client/TStreamClientTransport.cs @@ -0,0 +1,110 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + // ReSharper disable once InconsistentNaming + public class TStreamClientTransport : TClientTransport + { + private bool _isDisposed; + + protected TStreamClientTransport() + { + } + + public TStreamClientTransport(Stream inputStream, Stream outputStream) + { + InputStream = inputStream; + OutputStream = outputStream; + } + + protected Stream OutputStream { get; set; } + + protected Stream InputStream { get; set; } + + public override bool IsOpen => true; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override void Close() + { + if (InputStream != null) + { + InputStream.Dispose(); + InputStream = null; + } + + if (OutputStream != null) + { + OutputStream.Dispose(); + OutputStream = null; + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (InputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, + "Cannot read from null inputstream"); + } + + return await InputStream.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (OutputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, + "Cannot read from null inputstream"); + } + + await OutputStream.WriteAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + return OutputStream.FlushAsync(cancellationToken); + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + InputStream?.Dispose(); + OutputStream?.Dispose(); + } + } + _isDisposed = true; + } + } +} diff --git a/lib/Thrift/Transports/Client/TTlsSocketClientTransport.cs b/lib/Thrift/Transports/Client/TTlsSocketClientTransport.cs new file mode 100644 index 00000000000..f60ea588af0 --- /dev/null +++ b/lib/Thrift/Transports/Client/TTlsSocketClientTransport.cs @@ -0,0 +1,237 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Client +{ + //TODO: check for correct work + + // ReSharper disable once InconsistentNaming + public class TTlsSocketClientTransport : TStreamClientTransport + { + private readonly X509Certificate2 _certificate; + private readonly RemoteCertificateValidationCallback _certValidator; + private readonly IPAddress _host; + private readonly bool _isServer; + private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; + private readonly int _port; + private readonly SslProtocols _sslProtocols; + private TcpClient _client; + private SslStream _secureStream; + private int _timeout; + + public TTlsSocketClientTransport(TcpClient client, X509Certificate2 certificate, bool isServer = false, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + _client = client; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + _isServer = isServer; + + if (isServer && certificate == null) + { + throw new ArgumentException("TTlsSocketClientTransport needs certificate to be used for server", + nameof(certificate)); + } + + if (IsOpen) + { + InputStream = client.GetStream(); + OutputStream = client.GetStream(); + } + } + + public TTlsSocketClientTransport(IPAddress host, int port, string certificatePath, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + : this(host, port, 0, + new X509Certificate2(certificatePath), + certValidator, + localCertificateSelectionCallback, + sslProtocols) + { + } + + public TTlsSocketClientTransport(IPAddress host, int port, + X509Certificate2 certificate = null, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + : this(host, port, 0, + certificate, + certValidator, + localCertificateSelectionCallback, + sslProtocols) + { + } + + public TTlsSocketClientTransport(IPAddress host, int port, int timeout, + X509Certificate2 certificate, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + _host = host; + _port = port; + _timeout = timeout; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + InitSocket(); + } + + public int Timeout + { + set { _client.ReceiveTimeout = _client.SendTimeout = _timeout = value; } + } + + public TcpClient TcpClient => _client; + + public IPAddress Host => _host; + + public int Port => _port; + + public override bool IsOpen + { + get + { + if (_client == null) + { + return false; + } + + return _client.Connected; + } + } + + private void InitSocket() + { + _client = new TcpClient(); + _client.ReceiveTimeout = _client.SendTimeout = _timeout; + _client.Client.NoDelay = true; + } + + private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, + SslPolicyErrors sslValidationErrors) + { + return sslValidationErrors == SslPolicyErrors.None; + } + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (_host == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); + } + + if (_port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (_client == null) + { + InitSocket(); + } + + if (_client != null) + { + await _client.ConnectAsync(_host, _port).ConfigureAwait(false); + await SetupTlsAsync().ConfigureAwait(false); + } + } + + public async Task SetupTlsAsync() + { + var validator = _certValidator ?? DefaultCertificateValidator; + + if (_localCertificateSelectionCallback != null) + { + _secureStream = new SslStream(_client.GetStream(), false, validator, _localCertificateSelectionCallback); + } + else + { + _secureStream = new SslStream(_client.GetStream(), false, validator); + } + + try + { + if (_isServer) + { + // Server authentication + await + _secureStream.AuthenticateAsServerAsync(_certificate, _certValidator != null, _sslProtocols, + true); + } + else + { + // Client authentication + var certs = _certificate != null + ? new X509CertificateCollection {_certificate} + : new X509CertificateCollection(); + + var targetHost = _host.ToString(); + await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true).ConfigureAwait(false); + } + } + catch (Exception) + { + Close(); + throw; + } + + InputStream = _secureStream; + OutputStream = _secureStream; + } + + public override void Close() + { + base.Close(); + if (_client != null) + { + _client.Dispose(); + _client = null; + } + + if (_secureStream != null) + { + _secureStream.Dispose(); + _secureStream = null; + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Server/TNamedPipeServerTransport.cs b/lib/Thrift/Transports/Server/TNamedPipeServerTransport.cs new file mode 100644 index 00000000000..9d3b9341af1 --- /dev/null +++ b/lib/Thrift/Transports/Server/TNamedPipeServerTransport.cs @@ -0,0 +1,191 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.IO.Pipes; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports.Server +{ + // ReSharper disable once InconsistentNaming + public class TNamedPipeServerTransport : TServerTransport + { + /// + /// This is the address of the Pipe on the localhost. + /// + private readonly string _pipeAddress; + + private bool _asyncMode = true; + private volatile bool _isPending = true; + + private NamedPipeServerStream _stream = null; + + public TNamedPipeServerTransport(string pipeAddress) + { + _pipeAddress = pipeAddress; + } + + public override void Listen() + { + // nothing to do here + } + + public override void Close() + { + if (_stream != null) + { + try + { + //TODO: check for disconection + _stream.Disconnect(); + _stream.Dispose(); + } + finally + { + _stream = null; + _isPending = false; + } + } + } + + public override bool IsClientPending() + { + return _isPending; + } + + private void EnsurePipeInstance() + { + if (_stream == null) + { + var direction = PipeDirection.InOut; + var maxconn = 254; + var mode = PipeTransmissionMode.Byte; + var options = _asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; + var inbuf = 4096; + var outbuf = 4096; + // TODO: security + + try + { + _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf); + } + catch (NotImplementedException) // Mono still does not support async, fallback to sync + { + if (_asyncMode) + { + options &= (~PipeOptions.Asynchronous); + _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, + outbuf); + _asyncMode = false; + } + else + { + throw; + } + } + } + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + try + { + EnsurePipeInstance(); + + await _stream.WaitForConnectionAsync(cancellationToken).ConfigureAwait(false); + + var trans = new ServerTransport(_stream); + _stream = null; // pass ownership to ServerTransport + + //_isPending = false; + + return trans; + } + catch (TTransportException) + { + Close(); + throw; + } + catch (Exception e) + { + Close(); + throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message); + } + } + + private class ServerTransport : TClientTransport + { + private readonly NamedPipeServerStream _stream; + + public ServerTransport(NamedPipeServerStream stream) + { + _stream = stream; + } + + public override bool IsOpen => _stream != null && _stream.IsConnected; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + public override void Close() + { + _stream?.Dispose(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (_stream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + return await _stream.ReadAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (_stream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + await _stream.WriteAsync(buffer, offset, length, cancellationToken).ConfigureAwait(false); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + } + + protected override void Dispose(bool disposing) + { + _stream?.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Server/TServerFramedTransport.cs b/lib/Thrift/Transports/Server/TServerFramedTransport.cs new file mode 100644 index 00000000000..293a0e36582 --- /dev/null +++ b/lib/Thrift/Transports/Server/TServerFramedTransport.cs @@ -0,0 +1,150 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Transports.Client; + +namespace Thrift.Transports.Server +{ + // ReSharper disable once InconsistentNaming + public class TServerFramedTransport : TServerTransport + { + private readonly int _clientTimeout; + private readonly int _port; + private TcpListener _server; + + public TServerFramedTransport(TcpListener listener) + : this(listener, 0) + { + } + + public TServerFramedTransport(TcpListener listener, int clientTimeout) + { + _server = listener; + _clientTimeout = clientTimeout; + } + + public TServerFramedTransport(int port) + : this(port, 0) + { + } + + public TServerFramedTransport(int port, int clientTimeout) + { + _port = port; + _clientTimeout = clientTimeout; + try + { + // Make server socket + _server = new TcpListener(IPAddress.Any, _port); + _server.Server.NoDelay = true; + } + catch (Exception) + { + _server = null; + throw new TTransportException("Could not create ServerSocket on port " + port + "."); + } + } + + public override void Listen() + { + // Make sure not to block on accept + if (_server != null) + { + try + { + _server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException("Could not accept on listening socket: " + sx.Message); + } + } + } + + public override bool IsClientPending() + { + return _server.Pending(); + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (_server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + TFramedClientTransport tSocketTransport = null; + var tcpClient = await _server.AcceptTcpClientAsync().ConfigureAwait(false); + + try + { + tSocketTransport = new TFramedClientTransport(new TSocketClientTransport(tcpClient) + { + Timeout = _clientTimeout + }); + + return tSocketTransport; + } + catch (Exception) + { + if (tSocketTransport != null) + { + tSocketTransport.Dispose(); + } + else // Otherwise, clean it up ourselves. + { + ((IDisposable) tcpClient).Dispose(); + } + + throw; + } + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString()); + } + } + + public override void Close() + { + if (_server != null) + { + try + { + _server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException("WARNING: Could not close server socket: " + ex); + } + _server = null; + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Server/TServerSocketTransport.cs b/lib/Thrift/Transports/Server/TServerSocketTransport.cs new file mode 100644 index 00000000000..b9d7b9eca71 --- /dev/null +++ b/lib/Thrift/Transports/Server/TServerSocketTransport.cs @@ -0,0 +1,174 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Transports.Client; + +namespace Thrift.Transports.Server +{ + // ReSharper disable once InconsistentNaming + public class TServerSocketTransport : TServerTransport + { + private readonly int _clientTimeout; + private readonly int _port; + private readonly bool _useBufferedSockets; + private readonly bool _useFramedTransport; + private TcpListener _server; + + public TServerSocketTransport(TcpListener listener) + : this(listener, 0) + { + } + + public TServerSocketTransport(TcpListener listener, int clientTimeout) + { + _server = listener; + _clientTimeout = clientTimeout; + } + + public TServerSocketTransport(int port) + : this(port, 0) + { + } + + public TServerSocketTransport(int port, int clientTimeout) + : this(port, clientTimeout, false) + { + } + + public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets): + this(port, clientTimeout, useBufferedSockets, false) + { + } + + public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets, bool useFramedTransport) + { + _port = port; + _clientTimeout = clientTimeout; + _useBufferedSockets = useBufferedSockets; + _useFramedTransport = useFramedTransport; + try + { + // Make server socket + _server = new TcpListener(IPAddress.Any, _port); + _server.Server.NoDelay = true; + } + catch (Exception) + { + _server = null; + throw new TTransportException("Could not create ServerSocket on port " + port + "."); + } + } + + public override void Listen() + { + // Make sure not to block on accept + if (_server != null) + { + try + { + _server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException("Could not accept on listening socket: " + sx.Message); + } + } + } + + public override bool IsClientPending() + { + return _server.Pending(); + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (_server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + TClientTransport tSocketTransport = null; + var tcpClient = await _server.AcceptTcpClientAsync().ConfigureAwait(false); + + try + { + tSocketTransport = new TSocketClientTransport(tcpClient) + { + Timeout = _clientTimeout + }; + + if (_useBufferedSockets) + { + tSocketTransport = new TBufferedClientTransport(tSocketTransport); + } + + if (_useFramedTransport) + { + tSocketTransport = new TFramedClientTransport(tSocketTransport); + } + + return tSocketTransport; + } + catch (Exception) + { + if (tSocketTransport != null) + { + tSocketTransport.Dispose(); + } + else // Otherwise, clean it up ourselves. + { + ((IDisposable) tcpClient).Dispose(); + } + + throw; + } + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString()); + } + } + + public override void Close() + { + if (_server != null) + { + try + { + _server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException("WARNING: Could not close server socket: " + ex); + } + _server = null; + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/Server/TTlsServerSocketTransport.cs b/lib/Thrift/Transports/Server/TTlsServerSocketTransport.cs new file mode 100644 index 00000000000..87528a792d1 --- /dev/null +++ b/lib/Thrift/Transports/Server/TTlsServerSocketTransport.cs @@ -0,0 +1,177 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Transports.Client; + +namespace Thrift.Transports.Server +{ + // ReSharper disable once InconsistentNaming + public class TTlsServerSocketTransport : TServerTransport + { + private readonly RemoteCertificateValidationCallback _clientCertValidator; + private readonly int _clientTimeout = 0; + private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; + private readonly int _port; + private readonly X509Certificate2 _serverCertificate; + private readonly SslProtocols _sslProtocols; + private readonly bool _useBufferedSockets; + private readonly bool _useFramedTransport; + private TcpListener _server; + + public TTlsServerSocketTransport(int port, X509Certificate2 certificate) + : this(port, false, certificate) + { + } + + public TTlsServerSocketTransport( + int port, + bool useBufferedSockets, + X509Certificate2 certificate, + RemoteCertificateValidationCallback clientCertValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + : this(port, useBufferedSockets, false, certificate, + clientCertValidator, localCertificateSelectionCallback, sslProtocols) + { + } + + public TTlsServerSocketTransport( + int port, + bool useBufferedSockets, + bool useFramedTransport, + X509Certificate2 certificate, + RemoteCertificateValidationCallback clientCertValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + if (!certificate.HasPrivateKey) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Your server-certificate needs to have a private key"); + } + + _port = port; + _serverCertificate = certificate; + _useBufferedSockets = useBufferedSockets; + _useFramedTransport = useFramedTransport; + _clientCertValidator = clientCertValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + try + { + // Create server socket + _server = new TcpListener(IPAddress.Any, _port); + _server.Server.NoDelay = true; + } + catch (Exception) + { + _server = null; + throw new TTransportException($"Could not create ServerSocket on port {port}."); + } + } + + public override void Listen() + { + // Make sure accept is not blocking + if (_server != null) + { + try + { + _server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException($"Could not accept on listening socket: {sx.Message}"); + } + } + } + + public override bool IsClientPending() + { + return _server.Pending(); + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + if (_server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + var client = await _server.AcceptTcpClientAsync().ConfigureAwait(false); + client.SendTimeout = client.ReceiveTimeout = _clientTimeout; + + //wrap the client in an SSL Socket passing in the SSL cert + var tTlsSocket = new TTlsSocketClientTransport(client, _serverCertificate, true, _clientCertValidator, + _localCertificateSelectionCallback, _sslProtocols); + + await tTlsSocket.SetupTlsAsync().ConfigureAwait(false); + + TClientTransport trans = tTlsSocket; + + if (_useBufferedSockets) + { + trans = new TBufferedClientTransport(trans); + } + + if (_useFramedTransport) + { + trans = new TFramedClientTransport(trans); + } + + return trans; + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString()); + } + } + + public override void Close() + { + if (_server != null) + { + try + { + _server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException($"WARNING: Could not close server socket: {ex}"); + } + + _server = null; + } + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/TClientTransport.cs b/lib/Thrift/Transports/TClientTransport.cs new file mode 100644 index 00000000000..4eebbcf8cdd --- /dev/null +++ b/lib/Thrift/Transports/TClientTransport.cs @@ -0,0 +1,179 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports +{ + //TODO: think about client info + // ReSharper disable once InconsistentNaming + public abstract class TClientTransport : IDisposable + { + //TODO: think how to avoid peek byte + private readonly byte[] _peekBuffer = new byte[1]; + private bool _hasPeekByte; + public abstract bool IsOpen { get; } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public async Task PeekAsync(CancellationToken cancellationToken) + { + //If we already have a byte read but not consumed, do nothing. + if (_hasPeekByte) + { + return true; + } + + //If transport closed we can't peek. + if (!IsOpen) + { + return false; + } + + //Try to read one byte. If succeeds we will need to store it for the next read. + try + { + var bytes = await ReadAsync(_peekBuffer, 0, 1, cancellationToken).ConfigureAwait(false); + if (bytes == 0) + { + return false; + } + } + catch (IOException) + { + return false; + } + + _hasPeekByte = true; + return true; + } + + public virtual async Task OpenAsync() + { + await OpenAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task OpenAsync(CancellationToken cancellationToken); + + public abstract void Close(); + + protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + if (offset < 0) + { + throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset is smaller than zero."); + } + + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length), "Buffer length is smaller than zero."); + } + + if (offset + length > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data."); + } + } + + public virtual async Task ReadAsync(byte[] buffer, int offset, int length) + { + return await ReadAsync(buffer, offset, length, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + + public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length) + { + return await ReadAllAsync(buffer, offset, length, CancellationToken.None).ConfigureAwait(false); + } + + public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + ValidateBufferArgs(buffer, offset, length); + + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var retrieved = 0; + + //If we previously peeked a byte, we need to use that first. + if (_hasPeekByte) + { + buffer[offset + retrieved++] = _peekBuffer[0]; + _hasPeekByte = false; + } + + while (retrieved < length) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken).ConfigureAwait(false); + } + + var returnedCount = await ReadAsync(buffer, offset + retrieved, length - retrieved, cancellationToken).ConfigureAwait(false); + if (returnedCount <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, + "Cannot read, Remote side has closed"); + } + retrieved += returnedCount; + } + return retrieved; + } + + public virtual async Task WriteAsync(byte[] buffer) + { + await WriteAsync(buffer, CancellationToken.None).ConfigureAwait(false); + } + + public virtual async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + await WriteAsync(buffer, 0, buffer.Length, CancellationToken.None).ConfigureAwait(false); + } + + public virtual async Task WriteAsync(byte[] buffer, int offset, int length) + { + await WriteAsync(buffer, offset, length, CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + + public virtual async Task FlushAsync() + { + await FlushAsync(CancellationToken.None).ConfigureAwait(false); + } + + public abstract Task FlushAsync(CancellationToken cancellationToken); + + protected abstract void Dispose(bool disposing); + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/TServerTransport.cs b/lib/Thrift/Transports/TServerTransport.cs new file mode 100644 index 00000000000..21516c33a5e --- /dev/null +++ b/lib/Thrift/Transports/TServerTransport.cs @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transports +{ + // ReSharper disable once InconsistentNaming + public abstract class TServerTransport + { + public abstract void Listen(); + public abstract void Close(); + public abstract bool IsClientPending(); + + protected virtual async Task AcceptImplementationAsync() + { + return await AcceptImplementationAsync(CancellationToken.None).ConfigureAwait(false); + } + + protected abstract Task AcceptImplementationAsync(CancellationToken cancellationToken); + + public async Task AcceptAsync() + { + return await AcceptAsync(CancellationToken.None).ConfigureAwait(false); + } + + public async Task AcceptAsync(CancellationToken cancellationToken) + { + var transport = await AcceptImplementationAsync(cancellationToken).ConfigureAwait(false); + + if (transport == null) + { + throw new TTransportException($"{nameof(AcceptImplementationAsync)} should not return null"); + } + + return transport; + } + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/TTransportException.cs b/lib/Thrift/Transports/TTransportException.cs new file mode 100644 index 00000000000..b7c42e33a87 --- /dev/null +++ b/lib/Thrift/Transports/TTransportException.cs @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Transports +{ + // ReSharper disable once InconsistentNaming + public class TTransportException : TException + { + public enum ExceptionType + { + Unknown, + NotOpen, + AlreadyOpen, + TimedOut, + EndOfFile, + Interrupted + } + + protected ExceptionType ExType; + + public TTransportException() + { + } + + public TTransportException(ExceptionType exType) + : this() + { + ExType = exType; + } + + public TTransportException(ExceptionType exType, string message) + : base(message) + { + ExType = exType; + } + + public TTransportException(string message) + : base(message) + { + } + + public ExceptionType Type => ExType; + } +} \ No newline at end of file diff --git a/lib/Thrift/Transports/TTransportFactory.cs b/lib/Thrift/Transports/TTransportFactory.cs new file mode 100644 index 00000000000..d505f45d4ab --- /dev/null +++ b/lib/Thrift/Transports/TTransportFactory.cs @@ -0,0 +1,35 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you 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 Thrift.Transports +{ + /// + /// From Mark Slee & Aditya Agarwal of Facebook: + /// Factory class used to create wrapped instance of Transports. + /// This is used primarily in servers, which get Transports from + /// a ServerTransport and then may want to mutate them (i.e. create + /// a BufferedTransport from the underlying base transport). + /// + // ReSharper disable once InconsistentNaming + public class TTransportFactory + { + public virtual TClientTransport GetTransport(TClientTransport trans) + { + return trans; + } + } +} diff --git a/samples/Exporters/Exporters.csproj b/samples/Exporters/Exporters.csproj index 32b518a9608..7013bb5e792 100644 --- a/samples/Exporters/Exporters.csproj +++ b/samples/Exporters/Exporters.csproj @@ -23,6 +23,7 @@ + diff --git a/samples/Exporters/Program.cs b/samples/Exporters/Program.cs index b03c75bcbf9..1b7fb7b7d9d 100644 --- a/samples/Exporters/Program.cs +++ b/samples/Exporters/Program.cs @@ -35,8 +35,9 @@ public class Program /// Arguments from command line. public static void Main(string[] args) { - Parser.Default.ParseArguments(args) + Parser.Default.ParseArguments(args) .MapResult( + (JaegerOptions options) => TestJaeger.Run(options.Host, options.Port), (ZipkinOptions options) => TestZipkin.Run(options.Uri), (ApplicationInsightsOptions options) => TestApplicationInsights.Run(), (PrometheusOptions options) => TestPrometheus.Run(), @@ -57,6 +58,16 @@ internal class StackdriverOptions public string ProjectId { get; set; } } + [Verb("jaeger", HelpText = "Specify the options required to test Jaeger exporter")] + internal class JaegerOptions + { + [Option('h', "host", HelpText = "Please specify the host of the Jaeger Agent", Required = true)] + public string Host { get; set; } + + [Option('p', "port", HelpText = "Please specify the port of the Jaeger Agent", Required = true)] + public int Port { get; set; } + } + [Verb("zipkin", HelpText = "Specify the options required to test Zipkin exporter")] internal class ZipkinOptions { diff --git a/samples/Exporters/TestJaeger.cs b/samples/Exporters/TestJaeger.cs new file mode 100644 index 00000000000..941bd5b12e8 --- /dev/null +++ b/samples/Exporters/TestJaeger.cs @@ -0,0 +1,103 @@ +// +// 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 Samples +{ + using System; + using System.Collections.Generic; + using System.Threading; + using OpenTelemetry.Exporter.Jaeger; + using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Config; + using OpenTelemetry.Trace.Sampler; + + internal class TestJaeger + { + internal static object Run(string host, int port) + { + // 1. Configure exporter to export traces to Jaeger + var exporter = new JaegerExporter( + new JaegerExporterOptions + { + ServiceName = "tracing-to-jaeger-service", + AgentHost = host, + AgentPort = port, + }, + Tracing.ExportComponent); + + exporter.Start(); + + // 2. Configure 100% sample rate for the purposes of the demo + ITraceConfig traceConfig = Tracing.TraceConfig; + ITraceParams currentConfig = traceConfig.ActiveTraceParams; + var newConfig = currentConfig.ToBuilder() + .SetSampler(Samplers.AlwaysSample) + .Build(); + traceConfig.UpdateActiveTraceParams(newConfig); + + // 3. Tracer is global singleton. You can register it via dependency injection if it exists + // but if not - you can use it as follows: + var tracer = Tracing.Tracer; + + // 4. Create a scoped span. It will end automatically when using statement ends + using (tracer.WithSpan(tracer.SpanBuilder("Main").StartSpan())) + { + tracer.CurrentSpan.SetAttribute("custom-attribute", 55); + Console.WriteLine("About to do a busy work"); + for (int i = 0; i < 10; i++) + { + DoWork(i); + } + } + + // 5. Gracefully shutdown the exporter so it'll flush queued traces to Zipkin. + Tracing.ExportComponent.SpanExporter.Dispose(); + + return null; + } + + private static void DoWork(int i) + { + // 6. Get the global singleton Tracer object + var tracer = Tracing.Tracer; + + // 7. 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 + // a child span. + using (tracer.WithSpan(tracer.SpanBuilder("DoWork").StartSpan())) + { + // Simulate some work. + var span = tracer.CurrentSpan; + + try + { + Console.WriteLine("Doing busy work"); + Thread.Sleep(1000); + } + catch (ArgumentOutOfRangeException e) + { + // 6. Set status upon error + span.Status = Status.Internal.WithDescription(e.ToString()); + } + + // 7. Annotate our span to capture metadata about our operation + var attributes = new Dictionary(); + attributes.Add("use", "demo"); + span.AddEvent("Invoking DoWork", attributes); + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Batch.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Batch.cs new file mode 100644 index 00000000000..83d7b3b47dc --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Batch.cs @@ -0,0 +1,103 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + using Thrift.Protocols.Utilities; + + public class Batch : TAbstractBase + { + public Batch() + { + } + + public Batch(Process process, IEnumerable spans) + : this() + { + this.Process = process; + this.Spans = spans ?? Enumerable.Empty(); + } + + public Process Process { get; set; } + + public IEnumerable Spans { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var struc = new TStruct("Batch"); + + await oprot.WriteStructBeginAsync(struc, cancellationToken); + + var field = new TField + { + Name = "process", + Type = TType.Struct, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await this.Process.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "spans"; + field.Type = TType.List; + field.ID = 2; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + { + await oprot.WriteListBeginAsync(new TList(TType.Struct, this.Spans.Count()), cancellationToken); + foreach (JaegerSpan s in this.Spans) + { + await s.WriteAsync(oprot, cancellationToken); + } + + await oprot.WriteListEndAsync(cancellationToken); + } + + await oprot.WriteFieldEndAsync(cancellationToken); + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override string ToString() + { + var sb = new StringBuilder("Batch("); + sb.Append(", Process: "); + sb.Append(this.Process?.ToString() ?? ""); + sb.Append(", Spans: "); + sb.Append(this.Spans); + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/EmitBatchArgs.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/EmitBatchArgs.cs new file mode 100644 index 00000000000..aa794caca3b --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/EmitBatchArgs.cs @@ -0,0 +1,78 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class EmitBatchArgs : TAbstractBase + { + public EmitBatchArgs() + { + } + + public Batch Batch { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var struc = new TStruct("emitBatch_args"); + await oprot.WriteStructBeginAsync(struc, cancellationToken); + if (this.Batch is Batch batch) + { + var field = new TField + { + Name = "batch", + Type = TType.Struct, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await batch.WriteAsync(oprot, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override string ToString() + { + var sb = new StringBuilder("emitBatch_args("); + + if (this.Batch is Batch batch) + { + sb.Append("Batch: "); + sb.Append(batch?.ToString() ?? ""); + } + + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpBatcher.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpBatcher.cs new file mode 100644 index 00000000000..fea9cbdcace --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpBatcher.cs @@ -0,0 +1,31 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + public interface IJaegerUdpBatcher : IDisposable + { + Task AppendAsync(JaegerSpan span, CancellationToken cancellationToken); + + Task CloseAsync(CancellationToken cancellationToken); + + Task FlushAsync(CancellationToken cancellationToken); + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpClient.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpClient.cs new file mode 100644 index 00000000000..b1a28617d8e --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/IJaegerUdpClient.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.Exporter.Jaeger.Implementation +{ + using System; + using System.Net; + using System.Threading.Tasks; + + public interface IJaegerUdpClient : IDisposable + { + bool Connected { get; } + + EndPoint RemoteEndPoint { get; } + + void Connect(string host, int port); + + void Close(); + + Task SendAsync(byte[] datagram, int bytes); + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/InMemoryTransport.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/InMemoryTransport.cs new file mode 100644 index 00000000000..330dae04df5 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/InMemoryTransport.cs @@ -0,0 +1,90 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Transports; + + public class InMemoryTransport : TClientTransport + { + private readonly MemoryStream byteStream; + private bool isDisposed; + + public InMemoryTransport() + { + this.byteStream = new MemoryStream(); + } + + public override bool IsOpen => true; + + public override Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + + return Task.CompletedTask; + } + + public override void Close() + { + // do nothing + } + + public override Task ReadAsync( + byte[] buffer, + int offset, + int length, + CancellationToken cancellationToken) => this.byteStream.ReadAsync(buffer, offset, length, cancellationToken); + + public override Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) => this.byteStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken); + + public override Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) => this.byteStream.WriteAsync(buffer, offset, length, cancellationToken); + + public override Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled(cancellationToken); + } + + return Task.CompletedTask; + } + + public byte[] GetBuffer() => this.byteStream.ToArray(); + + public void Reset() => this.byteStream.SetLength(0); + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!this.isDisposed) + { + if (disposing) + { + this.byteStream?.Dispose(); + } + } + + this.isDisposed = true; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Int128.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Int128.cs new file mode 100644 index 00000000000..99b5b827f42 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Int128.cs @@ -0,0 +1,53 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Diagnostics; + + public struct Int128 + { + public static Int128 Empty = default; + + private const int SpanIdBytes = 8; + private const int TraceIdBytes = 16; + + public Int128(ActivitySpanId spanId) + { + var bytes = new byte[SpanIdBytes]; + + spanId.CopyTo(bytes); + + this.High = 0; + this.Low = BitConverter.ToInt64(bytes, 0); + } + + public Int128(ActivityTraceId traceId) + { + var bytes = new byte[TraceIdBytes]; + + traceId.CopyTo(bytes); + + this.High = BitConverter.ToInt64(bytes, 0); + this.Low = BitConverter.ToInt64(bytes, 8); + } + + public long High { get; set; } + + public long Low { get; set; } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerConversionExtensions.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerConversionExtensions.cs new file mode 100644 index 00000000000..854244e4f90 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerConversionExtensions.cs @@ -0,0 +1,145 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Export; + + public static class JaegerConversionExtensions + { + private const int DaysPerYear = 365; + + // Number of days in 4 years + private const int DaysPer4Years = (DaysPerYear * 4) + 1; // 1461 + + // Number of days in 100 years + private const int DaysPer100Years = (DaysPer4Years * 25) - 1; // 36524 + + // Number of days in 400 years + private const int DaysPer400Years = (DaysPer100Years * 4) + 1; // 146097 + + // Number of days from 1/1/0001 to 12/31/1969 + private const int DaysTo1970 = (DaysPer400Years * 4) + (DaysPer100Years * 3) + (DaysPer4Years * 17) + DaysPerYear; // 719,162 + + private const long UnixEpochTicks = DaysTo1970 * TimeSpan.TicksPerDay; + private const long TicksPerMicrosecond = TimeSpan.TicksPerMillisecond / 1000; + private const long UnixEpochMicroseconds = UnixEpochTicks / TicksPerMicrosecond; // 62,135,596,800,000,000 + + public static JaegerSpan ToJaegerSpan(this SpanData span) + { + IEnumerable jaegerTags = null; + + if (span?.Attributes?.AttributeMap is IEnumerable> attributeMap) + { + jaegerTags = attributeMap.Select(a => a.ToJaegerTag()).AsEnumerable(); + } + + IEnumerable jaegerLogs = null; + + if (span?.Events?.Events != null) + { + jaegerLogs = span.Events.Events.Select(e => e.ToJaegerLog()).AsEnumerable(); + } + + IEnumerable refs = null; + + if (span?.Links?.Links != null) + { + refs = span.Links.Links.Select(l => l.ToJaegerSpanRef()).Where(l => l != null).AsEnumerable(); + } + + var parentSpanId = new Int128(span.ParentSpanId); + + var traceId = span?.Context?.TraceId == null ? Int128.Empty : new Int128(span.Context.TraceId); + var spanId = span?.Context?.SpanId == null ? Int128.Empty : new Int128(span.Context.SpanId); + + return new JaegerSpan + { + TraceIdHigh = traceId.High, + TraceIdLow = traceId.Low, + SpanId = spanId.Low, + ParentSpanId = parentSpanId.Low, + OperationName = span.Name, + References = refs, + Flags = (span.Context.TraceOptions & ActivityTraceFlags.Recorded) > 0 ? 0x1 : 0, + StartTime = ToEpochMicroseconds(span.StartTimestamp), + Duration = ToEpochMicroseconds(span.EndTimestamp) - ToEpochMicroseconds(span.StartTimestamp), + JaegerTags = jaegerTags, + Logs = jaegerLogs, + }; + } + + public static JaegerTag ToJaegerTag(this KeyValuePair attribute) + { + switch (attribute.Value) + { + case string s: + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.STRING, VStr = s }; + case int i: + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.LONG, VLong = Convert.ToInt64(i) }; + case long l: + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.LONG, VLong = l }; + case float f: + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.DOUBLE, VDouble = Convert.ToDouble(f) }; + case double d: + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.DOUBLE, VDouble = d }; + case bool b: + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.BOOL, VBool = b }; + } + + return new JaegerTag { Key = attribute.Key, VType = JaegerTagType.STRING, VStr = attribute.Value.ToString() }; + } + + public static JaegerLog ToJaegerLog(this ITimedEvent timedEvent) + { + var tags = timedEvent.Event.Attributes.Select(a => a.ToJaegerTag()).ToList(); + tags.Add(new JaegerTag { Key = "description", VType = JaegerTagType.STRING, VStr = timedEvent.Event.Name }); + + return new JaegerLog + { + Timestamp = timedEvent.Timestamp.ToEpochMicroseconds(), + Fields = tags, + }; + } + + public static JaegerSpanRef ToJaegerSpanRef(this ILink link) + { + var traceId = link?.Context?.TraceId == null ? Int128.Empty : new Int128(link.Context.TraceId); + var spanId = link?.Context?.SpanId == null ? Int128.Empty : new Int128(link.Context.SpanId); + + return new JaegerSpanRef + { + TraceIdHigh = traceId.High, + TraceIdLow = traceId.Low, + SpanId = spanId.Low, + RefType = JaegerSpanRefType.CHILD_OF, + }; + } + + public static long ToEpochMicroseconds(this DateTime timestamp) + { + // Truncate sub-microsecond precision before offsetting by the Unix Epoch to avoid + // the last digit being off by one for dates that result in negative Unix times + long microseconds = timestamp.Ticks / TicksPerMicrosecond; + return microseconds - UnixEpochMicroseconds; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterException.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterException.cs new file mode 100644 index 00000000000..c31906dbc27 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerExporterException.cs @@ -0,0 +1,28 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + + public class JaegerExporterException : Exception + { + public JaegerExporterException(string message, Exception originalException) + : base(message, originalException) + { + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerLog.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerLog.cs new file mode 100644 index 00000000000..0ddef52eac2 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerLog.cs @@ -0,0 +1,101 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class JaegerLog : TAbstractBase + { + public JaegerLog() + { + } + + public JaegerLog(long timestamp, IEnumerable fields) + : this() + { + this.Timestamp = timestamp; + this.Fields = fields ?? Enumerable.Empty(); + } + + public long Timestamp { get; set; } + + public IEnumerable Fields { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var struc = new TStruct("Log"); + await oprot.WriteStructBeginAsync(struc, cancellationToken); + + var field = new TField + { + Name = "timestamp", + Type = TType.I64, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.Timestamp, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "fields"; + field.Type = TType.List; + field.ID = 2; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + { + await oprot.WriteListBeginAsync(new TList(TType.Struct, this.Fields.Count()), cancellationToken); + + foreach (JaegerTag jt in this.Fields) + { + await jt.WriteAsync(oprot, cancellationToken); + } + + await oprot.WriteListEndAsync(cancellationToken); + } + + await oprot.WriteFieldEndAsync(cancellationToken); + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override string ToString() + { + var sb = new StringBuilder("Log("); + sb.Append(", Timestamp: "); + sb.Append(this.Timestamp); + sb.Append(", Fields: "); + sb.Append(this.Fields); + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpan.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpan.cs new file mode 100644 index 00000000000..c11f1443f4d --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpan.cs @@ -0,0 +1,255 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class JaegerSpan : TAbstractBase + { + public JaegerSpan() + { + } + + public JaegerSpan(long traceIdLow, long traceIdHigh, long spanId, long parentSpanId, string operationName, int flags, long startTime, long duration) + : this() + { + this.TraceIdLow = traceIdLow; + this.TraceIdHigh = traceIdHigh; + this.SpanId = spanId; + this.ParentSpanId = parentSpanId; + this.OperationName = operationName; + this.Flags = flags; + this.StartTime = startTime; + this.Duration = duration; + } + + public long TraceIdLow { get; set; } + + public long TraceIdHigh { get; set; } + + public long SpanId { get; set; } + + public long ParentSpanId { get; set; } + + public string OperationName { get; set; } + + public IEnumerable References { get; set; } + + public int Flags { get; set; } + + public long StartTime { get; set; } + + public long Duration { get; set; } + + public IEnumerable JaegerTags { get; set; } + + public IEnumerable Logs { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var struc = new TStruct("Span"); + await oprot.WriteStructBeginAsync(struc, cancellationToken); + + var field = new TField + { + Name = "traceIdLow", + Type = TType.I64, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.TraceIdLow, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "traceIdHigh"; + field.Type = TType.I64; + field.ID = 2; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.TraceIdHigh, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "spanId"; + field.Type = TType.I64; + field.ID = 3; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.SpanId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "parentSpanId"; + field.Type = TType.I64; + field.ID = 4; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.ParentSpanId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "operationName"; + field.Type = TType.String; + field.ID = 5; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteStringAsync(this.OperationName, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + if (this.References is IEnumerable references) + { + field.Name = "references"; + field.Type = TType.List; + field.ID = 6; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + { + await oprot.WriteListBeginAsync(new TList(TType.Struct, references.Count()), cancellationToken); + + foreach (JaegerSpanRef sr in references) + { + await sr.WriteAsync(oprot, cancellationToken); + } + + await oprot.WriteListEndAsync(cancellationToken); + } + + await oprot.WriteFieldEndAsync(cancellationToken); + } + + field.Name = "flags"; + field.Type = TType.I32; + field.ID = 7; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI32Async(this.Flags, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "startTime"; + field.Type = TType.I64; + field.ID = 8; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.StartTime, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "duration"; + field.Type = TType.I64; + field.ID = 9; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.Duration, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + if (this.JaegerTags is IEnumerable jaegerTags) + { + field.Name = "JaegerTags"; + field.Type = TType.List; + field.ID = 10; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + { + await oprot.WriteListBeginAsync(new TList(TType.Struct, jaegerTags.Count()), cancellationToken); + + foreach (JaegerTag jt in jaegerTags) + { + await jt.WriteAsync(oprot, cancellationToken); + } + + await oprot.WriteListEndAsync(cancellationToken); + } + + await oprot.WriteFieldEndAsync(cancellationToken); + } + + if (this.Logs is IEnumerable logs) + { + field.Name = "logs"; + field.Type = TType.List; + field.ID = 11; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + { + await oprot.WriteListBeginAsync(new TList(TType.Struct, logs.Count()), cancellationToken); + + foreach (JaegerLog jl in logs) + { + await jl.WriteAsync(oprot, cancellationToken); + } + + await oprot.WriteListEndAsync(cancellationToken); + } + + await oprot.WriteFieldEndAsync(cancellationToken); + } + + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override string ToString() + { + var sb = new StringBuilder("Span("); + sb.Append(", TraceIdLow: "); + sb.Append(this.TraceIdLow); + sb.Append(", TraceIdHigh: "); + sb.Append(this.TraceIdHigh); + sb.Append(", SpanId: "); + sb.Append(this.SpanId); + sb.Append(", ParentSpanId: "); + sb.Append(this.ParentSpanId); + sb.Append(", OperationName: "); + sb.Append(this.OperationName); + if (this.References is IEnumerable jaegerSpanRef) + { + sb.Append(", References: "); + sb.Append(jaegerSpanRef); + } + + sb.Append(", Flags: "); + sb.Append(this.Flags); + sb.Append(", StartTime: "); + sb.Append(this.StartTime); + sb.Append(", Duration: "); + sb.Append(this.Duration); + if (this.JaegerTags is IEnumerable tags) + { + sb.Append(", JaegerTags: "); + sb.Append(tags); + } + + if (this.Logs is IEnumerable logs) + { + sb.Append(", Logs: "); + sb.Append(logs); + } + + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRef.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRef.cs new file mode 100644 index 00000000000..d9824380630 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRef.cs @@ -0,0 +1,119 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class JaegerSpanRef : TAbstractBase + { + public JaegerSpanRef() + { + } + + public JaegerSpanRef(JaegerSpanRefType refType, long traceIdLow, long traceIdHigh, long spanId) + : this() + { + this.RefType = refType; + this.TraceIdLow = traceIdLow; + this.TraceIdHigh = traceIdHigh; + this.SpanId = spanId; + } + + public JaegerSpanRefType RefType { get; set; } + + public long TraceIdLow { get; set; } + + public long TraceIdHigh { get; set; } + + public long SpanId { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var struc = new TStruct("SpanRef"); + await oprot.WriteStructBeginAsync(struc, cancellationToken); + + var field = new TField + { + Name = "refType", + Type = TType.I32, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI32Async((int)this.RefType, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "traceIdLow"; + field.Type = TType.I64; + field.ID = 2; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.TraceIdLow, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "traceIdHigh"; + field.Type = TType.I64; + field.ID = 3; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.TraceIdHigh, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "spanId"; + field.Type = TType.I64; + field.ID = 4; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.SpanId, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + /// + /// + /// + /// A string representation of the object. + public override string ToString() + { + var sb = new StringBuilder("SpanRef("); + sb.Append(", RefType: "); + sb.Append(this.RefType); + sb.Append(", TraceIdLow: "); + sb.Append(this.TraceIdLow); + sb.Append(", TraceIdHigh: "); + sb.Append(this.TraceIdHigh); + sb.Append(", SpanId: "); + sb.Append(this.SpanId); + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRefType.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRefType.cs new file mode 100644 index 00000000000..4b49dfef5de --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerSpanRefType.cs @@ -0,0 +1,36 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + + /// + /// Represents the different types of Jaeger Spans. + /// + public enum JaegerSpanRefType + { + /// + /// A child span + /// + CHILD_OF = 0, + + /// + /// A sibling span + /// + FOLLOWS_FROM = 1, + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTag.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTag.cs new file mode 100644 index 00000000000..71853ebe3ef --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTag.cs @@ -0,0 +1,180 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class JaegerTag : TAbstractBase + { + public JaegerTag() + { + } + + public JaegerTag(string key, JaegerTagType vType) + : this() + { + this.Key = key; + this.VType = vType; + } + + public string Key { get; set; } + + public JaegerTagType VType { get; set; } + + public string VStr { get; set; } + + public double? VDouble { get; set; } + + public bool? VBool { get; set; } + + public long? VLong { get; set; } + + public byte[] VBinary { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + try + { + var struc = new TStruct("Tag"); + await oprot.WriteStructBeginAsync(struc, cancellationToken); + + var field = new TField + { + Name = "key", + Type = TType.String, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteStringAsync(this.Key, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + field.Name = "vType"; + field.Type = TType.I32; + field.ID = 2; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI32Async((int)this.VType, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + if (this.VStr != null) + { + field.Name = "vStr"; + field.Type = TType.String; + field.ID = 3; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteStringAsync(this.VStr, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + + if (this.VDouble.HasValue) + { + field.Name = "vDouble"; + field.Type = TType.Double; + field.ID = 4; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteDoubleAsync(this.VDouble.Value, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + + if (this.VBool.HasValue) + { + field.Name = "vBool"; + field.Type = TType.Bool; + field.ID = 5; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteBoolAsync(this.VBool.Value, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + + if (this.VLong.HasValue) + { + field.Name = "vLong"; + field.Type = TType.I64; + field.ID = 6; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteI64Async(this.VLong.Value, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + + if (this.VBinary != null) + { + field.Name = "vBinary"; + field.Type = TType.String; + field.ID = 7; + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteBinaryAsync(this.VBinary, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + } + + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override string ToString() + { + var sb = new StringBuilder("Tag("); + sb.Append(", Key: "); + sb.Append(this.Key); + sb.Append(", VType: "); + sb.Append(this.VType); + if (this.VStr != null) + { + sb.Append(", VStr: "); + sb.Append(this.VStr); + } + + if (this.VDouble.HasValue) + { + sb.Append(", VDouble: "); + sb.Append(this.VDouble); + } + + if (this.VBool.HasValue) + { + sb.Append(", VBool: "); + sb.Append(this.VBool); + } + + if (this.VLong.HasValue) + { + sb.Append(", VLong: "); + sb.Append(this.VLong); + } + + if (this.VBinary != null) + { + sb.Append(", VBinary: "); + sb.Append(this.VBinary); + } + + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagType.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagType.cs new file mode 100644 index 00000000000..868a41cc461 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTagType.cs @@ -0,0 +1,51 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + + /// + /// Indicates the data type of a Jaeger tag. + /// + public enum JaegerTagType + { + /// + /// Tag contains a string + /// + STRING = 0, + + /// + /// Tag contains a double + /// + DOUBLE = 1, + + /// + /// Tag contains a boolean + /// + BOOL = 2, + + /// + /// Tag contains a long + /// + LONG = 3, + + /// + /// Tag contains binary data + /// + BINARY = 4, + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClient.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClient.cs new file mode 100644 index 00000000000..061b5368232 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClient.cs @@ -0,0 +1,50 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using Thrift; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class JaegerThriftClient : TBaseClient, IDisposable + { + public JaegerThriftClient(TProtocol protocol) + : this(protocol, protocol) + { + } + + public JaegerThriftClient(TProtocol inputProtocol, TProtocol outputProtocol) + : base(inputProtocol, outputProtocol) + { + } + + public async Task EmitBatchAsync(Batch batch, CancellationToken cancellationToken) + { + await this.OutputProtocol.WriteMessageBeginAsync(new TMessage("emitBatch", TMessageType.Oneway, this.SeqId), cancellationToken); + + var args = new EmitBatchArgs(); + args.Batch = batch; + + await args.WriteAsync(this.OutputProtocol, cancellationToken); + await this.OutputProtocol.WriteMessageEndAsync(cancellationToken); + await this.OutputProtocol.Transport.FlushAsync(cancellationToken); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClientTransport.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClientTransport.cs new file mode 100644 index 00000000000..4e97b346021 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerThriftClientTransport.cs @@ -0,0 +1,113 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.IO; + using System.Net.Sockets; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Transports; + + public class JaegerThriftClientTransport : TClientTransport + { + private readonly IJaegerUdpClient udpClient; + private readonly MemoryStream byteStream; + private bool isDisposed = false; + + public JaegerThriftClientTransport(string host, int port) + : this(host, port, new MemoryStream(), new JaegerUdpClient()) + { + } + + public JaegerThriftClientTransport(string host, int port, MemoryStream stream, IJaegerUdpClient client) + { + this.byteStream = stream; + this.udpClient = client; + this.udpClient.Connect(host, port); + } + + public override bool IsOpen => this.udpClient.Connected; + + public override void Close() + { + this.udpClient.Close(); + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + var bytes = this.byteStream.ToArray(); + + if (bytes.Length == 0) + { + return Task.CompletedTask; + } + + this.byteStream.SetLength(0); + + try + { + return this.udpClient.SendAsync(bytes, bytes.Length); + } + catch (SocketException se) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, $"Cannot flush because of socket exception. UDP Packet size was {bytes.Length}. Exception message: {se.Message}"); + } + catch (Exception e) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, $"Cannot flush closed transport. {e.Message}"); + } + } + + public override Task OpenAsync(CancellationToken cancellationToken) + { + // Do nothing + return Task.CompletedTask; + } + + public override Task ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public override Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + return this.WriteAsync(buffer, 0, buffer.Length, cancellationToken); + } + + public override Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + return this.byteStream.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override string ToString() + { + return $"{nameof(JaegerThriftClientTransport)}(Client={this.udpClient.RemoteEndPoint})"; + } + + protected override void Dispose(bool disposing) + { + if (!this.isDisposed && disposing) + { + this.byteStream?.Dispose(); + this.udpClient?.Dispose(); + } + + this.isDisposed = true; + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTraceExporterHandler.cs new file mode 100644 index 00000000000..5f1e64739c0 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerTraceExporterHandler.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. +// + +namespace OpenTelemetry.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net.Sockets; + using System.Threading; + using System.Threading.Tasks; + using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Export; + using Thrift.Protocols; + + public class JaegerTraceExporterHandler : IHandler, IDisposable + { + private readonly IJaegerUdpBatcher jaegerAgentUdpBatcher; + private bool disposedValue = false; // To detect redundant dispose calls + + public JaegerTraceExporterHandler(JaegerExporterOptions options) + : this(new JaegerUdpBatcher(options)) + { + } + + public JaegerTraceExporterHandler(IJaegerUdpBatcher jaegerAgentUdpBatcher) + { + this.jaegerAgentUdpBatcher = jaegerAgentUdpBatcher; + } + + public async Task ExportAsync(IEnumerable spanDataList) + { + var jaegerspans = spanDataList.Select(sdl => sdl.ToJaegerSpan()); + + foreach (var s in jaegerspans) + { + await this.jaegerAgentUdpBatcher.AppendAsync(s, CancellationToken.None); + } + + await this.jaegerAgentUdpBatcher.FlushAsync(CancellationToken.None); + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing). + this.Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposedValue) + { + if (disposing) + { + this.jaegerAgentUdpBatcher.Dispose(); + } + + this.disposedValue = true; + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpBatcher.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpBatcher.cs new file mode 100644 index 00000000000..8827909fb10 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpBatcher.cs @@ -0,0 +1,156 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + + public class JaegerUdpBatcher : IJaegerUdpBatcher + { + private const int DefaultMaxPacketSize = 65000; + private readonly int? maxPacketSize; + private readonly ITProtocolFactory protocolFactory; + private readonly JaegerThriftClientTransport clientTransport; + private readonly JaegerThriftClient thriftClient; + private readonly Process process; + private readonly int processByteSize; + private readonly List currentBatch = new List(); + + private int batchByteSize; + + private bool disposedValue = false; // To detect redundant calls + + public JaegerUdpBatcher(JaegerExporterOptions options) + { + this.maxPacketSize = options.MaxPacketSize == 0 ? DefaultMaxPacketSize : options.MaxPacketSize; + this.protocolFactory = new TCompactProtocol.Factory(); + this.clientTransport = new JaegerThriftClientTransport(options.AgentHost, options.AgentPort.Value); + this.thriftClient = new JaegerThriftClient(this.protocolFactory.GetProtocol(this.clientTransport)); + this.process = new Process(options.ServiceName, options.ProcessTags); + this.processByteSize = this.GetSize(this.process); + this.batchByteSize = this.processByteSize; + } + + public async Task AppendAsync(JaegerSpan span, CancellationToken cancellationToken) + { + int spanSize = this.GetSize(span); + + if (spanSize > this.maxPacketSize) + { + throw new JaegerExporterException($"ThriftSender received a span that was too large, size = {spanSize}, max = {this.maxPacketSize}", null); + } + + this.batchByteSize += spanSize; + if (this.batchByteSize <= this.maxPacketSize) + { + this.currentBatch.Add(span); + + if (this.batchByteSize < this.maxPacketSize) + { + return 0; + } + + return await this.FlushAsync(cancellationToken).ConfigureAwait(false); + } + + int n; + + try + { + n = await this.FlushAsync(cancellationToken).ConfigureAwait(false); + } + catch (JaegerExporterException ex) + { + // +1 for the span not submitted in the buffer above + throw new JaegerExporterException(ex.Message, ex); + } + + this.currentBatch.Add(span); + this.batchByteSize = this.processByteSize + spanSize; + return n; + } + + public async Task FlushAsync(CancellationToken cancellationToken) + { + int n = this.currentBatch.Count; + + if (n == 0) + { + return 0; + } + + try + { + await this.SendAsync(this.process, this.currentBatch, cancellationToken).ConfigureAwait(false); + } + finally + { + this.currentBatch.Clear(); + this.batchByteSize = this.processByteSize; + } + + return n; + } + + public virtual Task CloseAsync(CancellationToken cancellationToken) => this.FlushAsync(cancellationToken); + + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing). + this.Dispose(true); + } + + protected async Task SendAsync(Process process, List spans, CancellationToken cancellationToken) + { + try + { + var batch = new Batch(process, spans); + await this.thriftClient.EmitBatchAsync(batch, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + throw new JaegerExporterException($"Could not send {spans.Count} spans", ex); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposedValue) + { + if (disposing) + { + this.thriftClient.Dispose(); + this.clientTransport.Dispose(); + } + + this.disposedValue = true; + } + } + + private int GetSize(TAbstractBase thriftBase) + { + using (var memoryTransport = new InMemoryTransport()) + { + thriftBase.WriteAsync(this.protocolFactory.GetProtocol(memoryTransport), CancellationToken.None).GetAwaiter().GetResult(); + return memoryTransport.GetBuffer().Length; + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpClient.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpClient.cs new file mode 100644 index 00000000000..146d7f32a98 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerUdpClient.cs @@ -0,0 +1,45 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Net; + using System.Net.Sockets; + using System.Threading.Tasks; + + public class JaegerUdpClient : IJaegerUdpClient + { + private readonly UdpClient client; + + public JaegerUdpClient() + { + this.client = new UdpClient(); + } + + public bool Connected => this.client.Client.Connected; + + public EndPoint RemoteEndPoint => this.client.Client.RemoteEndPoint; + + public void Close() => this.client.Close(); + + public void Connect(string host, int port) => this.client.Connect(host, port); + + public Task SendAsync(byte[] datagram, int bytes) => this.client.SendAsync(datagram, bytes); + + public void Dispose() => this.client.Dispose(); + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs new file mode 100644 index 00000000000..b08c84d83ca --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/Implementation/Process.cs @@ -0,0 +1,116 @@ +// +// 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.Exporter.Jaeger.Implementation +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Thrift.Protocols; + using Thrift.Protocols.Entities; + + public class Process : TAbstractBase + { + public Process() + { + } + + public Process(string serviceName, IDictionary processTags) + : this() + { + this.ServiceName = serviceName; + + if (processTags != null) + { + this.Tags = new List(); + this.Tags.AddRange(processTags.Select(pt => pt.ToJaegerTag())); + } + } + + public string ServiceName { get; set; } + + public List Tags { get; set; } + + public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) + { + oprot.IncrementRecursionDepth(); + + try + { + var struc = new TStruct("Process"); + await oprot.WriteStructBeginAsync(struc, cancellationToken); + + var field = new TField + { + Name = "serviceName", + Type = TType.String, + ID = 1, + }; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + await oprot.WriteStringAsync(this.ServiceName, cancellationToken); + await oprot.WriteFieldEndAsync(cancellationToken); + + if (this.Tags != null) + { + field.Name = "tags"; + field.Type = TType.List; + field.ID = 2; + + await oprot.WriteFieldBeginAsync(field, cancellationToken); + { + await oprot.WriteListBeginAsync(new TList(TType.Struct, this.Tags.Count), cancellationToken); + + foreach (JaegerTag jt in this.Tags) + { + await jt.WriteAsync(oprot, cancellationToken); + } + + await oprot.WriteListEndAsync(cancellationToken); + } + + await oprot.WriteFieldEndAsync(cancellationToken); + } + + await oprot.WriteFieldStopAsync(cancellationToken); + await oprot.WriteStructEndAsync(cancellationToken); + } + finally + { + oprot.DecrementRecursionDepth(); + } + } + + public override string ToString() + { + var sb = new StringBuilder("Process("); + sb.Append(", ServiceName: "); + sb.Append(this.ServiceName); + + if (this.Tags != null) + { + sb.Append(", Tags: "); + sb.Append(this.Tags); + } + + sb.Append(")"); + return sb.ToString(); + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs new file mode 100644 index 00000000000..60f200f26a4 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs @@ -0,0 +1,128 @@ +// +// 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.Exporter.Jaeger +{ + using System; + using OpenTelemetry.Exporter.Jaeger.Implementation; + using OpenTelemetry.Trace.Export; + + public class JaegerExporter : IDisposable + { + public const string DefaultAgentUdpHost = "localhost"; + public const int DefaultAgentUdpCompactPort = 6831; + public const int DefaultMaxPacketSize = 65000; + + private const string ExporterName = "JaegerTraceExporter"; + + private readonly object @lock = new object(); + private readonly JaegerExporterOptions options; + private readonly IExportComponent exportComponent; + + private volatile bool isInitialized = false; + private JaegerTraceExporterHandler handler; + private bool disposedValue = false; // To detect redundant dispose calls + + public JaegerExporter(JaegerExporterOptions options, IExportComponent exportComponent) + { + this.ValidateOptions(options); + this.InitializeOptions(options); + + this.options = options; + this.exportComponent = exportComponent; + } + + public void Start() + { + lock (this.@lock) + { + if (this.isInitialized) + { + return; + } + + if (this.exportComponent != null) + { + this.handler = new JaegerTraceExporterHandler(this.options); + this.exportComponent.SpanExporter.RegisterHandler(ExporterName, this.handler); + } + } + } + + public void Stop() + { + if (!this.isInitialized) + { + return; + } + + lock (this.@lock) + { + if (this.exportComponent != null) + { + this.exportComponent.SpanExporter.UnregisterHandler(ExporterName); + } + } + + this.isInitialized = false; + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing). + this.Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposedValue) + { + if (disposing) + { + this.handler.Dispose(); + } + + this.disposedValue = true; + } + } + + private void ValidateOptions(JaegerExporterOptions options) + { + if (string.IsNullOrWhiteSpace(options.ServiceName)) + { + throw new ArgumentException("ServiceName", "Service Name is required."); + } + } + + private void InitializeOptions(JaegerExporterOptions options) + { + if (string.IsNullOrWhiteSpace(options.AgentHost)) + { + options.AgentHost = DefaultAgentUdpHost; + } + + if (!options.AgentPort.HasValue) + { + options.AgentPort = DefaultAgentUdpCompactPort; + } + + if (!options.MaxPacketSize.HasValue) + { + options.MaxPacketSize = DefaultMaxPacketSize; + } + } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs new file mode 100644 index 00000000000..fef770a198f --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporterOptions.cs @@ -0,0 +1,34 @@ +// +// 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.Exporter.Jaeger +{ + using System; + using System.Collections.Generic; + + public class JaegerExporterOptions + { + public string ServiceName { get; set; } + + public string AgentHost { get; set; } + + public int? AgentPort { get; set; } + + public int? MaxPacketSize { get; set; } + + public Dictionary ProcessTags { get; set; } + } +} diff --git a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj new file mode 100644 index 00000000000..879d3410513 --- /dev/null +++ b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj @@ -0,0 +1,16 @@ + + + + net46;netstandard2.0 + netstandard2.0 + OpenTelemetry authors + https://opentelemetry.io/img/logos/opentelemetry-icon-color.png + https://OpenTelemetry.io + Tracing;OpenTelemetry;Management;Monitoring;Jaeger;distributed-tracing + + + + + + + diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs new file mode 100644 index 00000000000..7c1ecb959b5 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerSpanConverterTest.cs @@ -0,0 +1,539 @@ +// +// 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.Exporter.Jaeger.Tests.Implementation +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using OpenTelemetry.Exporter.Jaeger.Implementation; + using OpenTelemetry.Resources; + using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Export; + using Xunit; + + public class JaegerSpanConverterTest + { + private const long MillisPerSecond = 1000L; + private const long NanosPerMillisecond = 1000 * 1000; + private const long NanosPerSecond = NanosPerMillisecond * MillisPerSecond; + + public JaegerSpanConverterTest() + { + } + + [Fact] + public void JaegerSpanConverterTest_ConvertSpanToJaegerSpan_AllPropertiesSet() + { + var startTimestamp = DateTime.Now; + var endTimestamp = startTimestamp.AddSeconds(60); + var eventTimestamp = DateTime.Now; + + var traceId = ActivityTraceId.CreateRandom(); + var traceIdAsInt = new Int128(traceId); + var spanId = ActivitySpanId.CreateRandom(); + var spanIdAsInt = new Int128(spanId); + var parentSpanId = ActivitySpanId.CreateRandom(); + var attributes = Attributes.Create(new Dictionary{ + { "stringKey", "value"}, + { "longKey", 1L}, + { "longKey2", 1 }, + { "doubleKey", 1D}, + { "doubleKey2", 1F}, + { "boolKey", true}, + }, 0); + var events = TimedEvents.Create(new List> + { + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event1", + new Dictionary + { + { "key", "value" }, + } + ) + ), + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event2", + new Dictionary + { + { "key", "value" }, + } + ) + ), + }, 0); + + var linkedSpanId = ActivitySpanId.CreateRandom(); + + var link = Link.FromSpanContext(SpanContext.Create( + traceId, + linkedSpanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty)); + + var linkTraceIdAsInt = new Int128(link.Context.TraceId); + var linkSpanIdAsInt = new Int128(link.Context.SpanId); + + var links = LinkList.Create(new List { link }, 0); + + var spanData = SpanData.Create( + SpanContext.Create( + traceId, + spanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty + ), + parentSpanId, + Resource.Empty, + "Name", + startTimestamp, + attributes, + events, + links, + null, + Status.Ok, + SpanKind.Client, + endTimestamp + ); + + var jaegerSpan = spanData.ToJaegerSpan(); + + Assert.Equal("Name", jaegerSpan.OperationName); + Assert.Equal(2, jaegerSpan.Logs.Count()); + + Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh); + Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow); + Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId); + Assert.Equal(new Int128(parentSpanId).Low, jaegerSpan.ParentSpanId); + + Assert.Equal(links.Links.Count(), jaegerSpan.References.Count()); + var references = jaegerSpan.References.ToArray(); + var jaegerRef = references[0]; + Assert.Equal(linkTraceIdAsInt.High, jaegerRef.TraceIdHigh); + Assert.Equal(linkTraceIdAsInt.Low, jaegerRef.TraceIdLow); + Assert.Equal(linkSpanIdAsInt.Low, jaegerRef.SpanId); + + Assert.Equal(0x1, jaegerSpan.Flags); + + Assert.Equal(startTimestamp.ToEpochMicroseconds(), jaegerSpan.StartTime); + Assert.Equal(endTimestamp.ToEpochMicroseconds() - startTimestamp.ToEpochMicroseconds(), jaegerSpan.Duration); + + var tags = jaegerSpan.JaegerTags.ToArray(); + var tag = tags[0]; + Assert.Equal(JaegerTagType.STRING, tag.VType); + Assert.Equal("stringKey", tag.Key); + Assert.Equal("value", tag.VStr); + tag = tags[1]; + Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal("longKey", tag.Key); + Assert.Equal(1, tag.VLong); + tag = tags[2]; + Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal("longKey2", tag.Key); + Assert.Equal(1, tag.VLong); + tag = tags[3]; + Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + Assert.Equal("doubleKey", tag.Key); + Assert.Equal(1, tag.VDouble); + tag = tags[4]; + Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + Assert.Equal("doubleKey2", tag.Key); + Assert.Equal(1, tag.VDouble); + tag = tags[5]; + Assert.Equal(JaegerTagType.BOOL, tag.VType); + Assert.Equal("boolKey", tag.Key); + Assert.Equal(true, tag.VBool); + + var logs = jaegerSpan.Logs.ToArray(); + var jaegerLog = logs[0]; + Assert.Equal(events.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); + Assert.Equal(jaegerLog.Fields.Count(), 2); + var eventFields = jaegerLog.Fields.ToArray(); + var eventField = eventFields[0]; + Assert.Equal("key", eventField.Key); + Assert.Equal("value", eventField.VStr); + eventField = eventFields[1]; + Assert.Equal("description", eventField.Key); + Assert.Equal("Event1", eventField.VStr); + + jaegerLog = logs[1]; + Assert.Equal(events.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); + Assert.Equal(jaegerLog.Fields.Count(), 2); + eventFields = jaegerLog.Fields.ToArray(); + eventField = eventFields[0]; + Assert.Equal("key", eventField.Key); + Assert.Equal("value", eventField.VStr); + eventField = eventFields[1]; + Assert.Equal("description", eventField.Key); + Assert.Equal("Event2", eventField.VStr); + } + + [Fact] + public void JaegerSpanConverterTest_ConvertSpanToJaegerSpan_NoAttributes() + { + var startTimestamp = DateTime.Now; + var endTimestamp = startTimestamp.AddSeconds(60); + var eventTimestamp = DateTime.Now; + + var traceId = ActivityTraceId.CreateRandom(); + var traceIdAsInt = new Int128(traceId); + var spanId = ActivitySpanId.CreateRandom(); + var spanIdAsInt = new Int128(spanId); + var parentSpanId = ActivitySpanId.CreateRandom(); + var events = TimedEvents.Create(new List> + { + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event1", + new Dictionary + { + { "key", "value" }, + } + ) + ), + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event2", + new Dictionary + { + { "key", "value" }, + } + ) + ), + }, 0); + + var linkedSpanId = ActivitySpanId.CreateRandom(); + + var link = Link.FromSpanContext(SpanContext.Create( + traceId, + linkedSpanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty)); + + var linkTraceIdAsInt = new Int128(link.Context.TraceId); + var linkSpanIdAsInt = new Int128(link.Context.SpanId); + + var links = LinkList.Create(new List { link }, 0); + + var spanData = SpanData.Create( + SpanContext.Create( + traceId, + spanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty + ), + parentSpanId, + Resource.Empty, + "Name", + startTimestamp, + null, + events, + links, + null, + Status.Ok, + SpanKind.Client, + endTimestamp + ); + + var jaegerSpan = spanData.ToJaegerSpan(); + + Assert.Equal("Name", jaegerSpan.OperationName); + Assert.Equal(2, jaegerSpan.Logs.Count()); + + Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh); + Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow); + Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId); + Assert.Equal(new Int128(parentSpanId).Low, jaegerSpan.ParentSpanId); + + Assert.Equal(links.Links.Count(), jaegerSpan.References.Count()); + var references = jaegerSpan.References.ToArray(); + var jaegerRef = references[0]; + Assert.Equal(linkTraceIdAsInt.High, jaegerRef.TraceIdHigh); + Assert.Equal(linkTraceIdAsInt.Low, jaegerRef.TraceIdLow); + Assert.Equal(linkSpanIdAsInt.Low, jaegerRef.SpanId); + + Assert.Equal(0x1, jaegerSpan.Flags); + + Assert.Equal(startTimestamp.ToEpochMicroseconds(), jaegerSpan.StartTime); + Assert.Equal(endTimestamp.ToEpochMicroseconds() - startTimestamp.ToEpochMicroseconds(), jaegerSpan.Duration); + + Assert.Empty(jaegerSpan.JaegerTags); + + var logs = jaegerSpan.Logs.ToArray(); + var jaegerLog = logs[0]; + Assert.Equal(events.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); + Assert.Equal(jaegerLog.Fields.Count(), 2); + var eventFields = jaegerLog.Fields.ToArray(); + var eventField = eventFields[0]; + Assert.Equal("key", eventField.Key); + Assert.Equal("value", eventField.VStr); + eventField = eventFields[1]; + Assert.Equal("description", eventField.Key); + Assert.Equal("Event1", eventField.VStr); + + jaegerLog = logs[1]; + Assert.Equal(events.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); + Assert.Equal(jaegerLog.Fields.Count(), 2); + eventFields = jaegerLog.Fields.ToArray(); + eventField = eventFields[0]; + Assert.Equal("key", eventField.Key); + Assert.Equal("value", eventField.VStr); + eventField = eventFields[1]; + Assert.Equal("description", eventField.Key); + Assert.Equal("Event2", eventField.VStr); + } + + [Fact] + public void JaegerSpanConverterTest_ConvertSpanToJaegerSpan_NoEvents() + { + var startTimestamp = DateTime.Now; + var endTimestamp = startTimestamp.AddSeconds(60); + var eventTimestamp = DateTime.Now; + + var traceId = ActivityTraceId.CreateRandom(); + var traceIdAsInt = new Int128(traceId); + var spanId = ActivitySpanId.CreateRandom(); + var spanIdAsInt = new Int128(spanId); + var parentSpanId = ActivitySpanId.CreateRandom(); + var attributes = Attributes.Create(new Dictionary{ + { "stringKey", "value"}, + { "longKey", 1L}, + { "longKey2", 1 }, + { "doubleKey", 1D}, + { "doubleKey2", 1F}, + { "boolKey", true}, + }, 0); + + var linkedSpanId = ActivitySpanId.CreateRandom(); + + var link = Link.FromSpanContext(SpanContext.Create( + traceId, + linkedSpanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty)); + + var linkTraceIdAsInt = new Int128(link.Context.TraceId); + var linkSpanIdAsInt = new Int128(link.Context.SpanId); + + var links = LinkList.Create(new List { link }, 0); + + var spanData = SpanData.Create( + SpanContext.Create( + traceId, + spanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty + ), + parentSpanId, + Resource.Empty, + "Name", + startTimestamp, + attributes, + null, + links, + null, + Status.Ok, + SpanKind.Client, + endTimestamp + ); + + var jaegerSpan = spanData.ToJaegerSpan(); + + Assert.Equal("Name", jaegerSpan.OperationName); + Assert.Empty(jaegerSpan.Logs); + + Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh); + Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow); + Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId); + Assert.Equal(new Int128(parentSpanId).Low, jaegerSpan.ParentSpanId); + + Assert.Equal(links.Links.Count(), jaegerSpan.References.Count()); + var references = jaegerSpan.References.ToArray(); + var jaegerRef = references[0]; + Assert.Equal(linkTraceIdAsInt.High, jaegerRef.TraceIdHigh); + Assert.Equal(linkTraceIdAsInt.Low, jaegerRef.TraceIdLow); + Assert.Equal(linkSpanIdAsInt.Low, jaegerRef.SpanId); + + Assert.Equal(0x1, jaegerSpan.Flags); + + Assert.Equal(startTimestamp.ToEpochMicroseconds(), jaegerSpan.StartTime); + Assert.Equal(endTimestamp.ToEpochMicroseconds() - startTimestamp.ToEpochMicroseconds(), jaegerSpan.Duration); + + var tags = jaegerSpan.JaegerTags.ToArray(); + var tag = tags[0]; + Assert.Equal(JaegerTagType.STRING, tag.VType); + Assert.Equal("stringKey", tag.Key); + Assert.Equal("value", tag.VStr); + tag = tags[1]; + Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal("longKey", tag.Key); + Assert.Equal(1, tag.VLong); + tag = tags[2]; + Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal("longKey2", tag.Key); + Assert.Equal(1, tag.VLong); + tag = tags[3]; + Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + Assert.Equal("doubleKey", tag.Key); + Assert.Equal(1, tag.VDouble); + tag = tags[4]; + Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + Assert.Equal("doubleKey2", tag.Key); + Assert.Equal(1, tag.VDouble); + tag = tags[5]; + Assert.Equal(JaegerTagType.BOOL, tag.VType); + Assert.Equal("boolKey", tag.Key); + Assert.Equal(true, tag.VBool); + } + + [Fact] + public void JaegerSpanConverterTest_ConvertSpanToJaegerSpan_NoLinks() + { + var startTimestamp = DateTime.Now; + var endTimestamp = startTimestamp.AddSeconds(60); + var eventTimestamp = DateTime.Now; + + var traceId = ActivityTraceId.CreateRandom(); + var traceIdAsInt = new Int128(traceId); + var spanId = ActivitySpanId.CreateRandom(); + var spanIdAsInt = new Int128(spanId); + var parentSpanId = ActivitySpanId.CreateRandom(); + var attributes = Attributes.Create(new Dictionary{ + { "stringKey", "value"}, + { "longKey", 1L}, + { "longKey2", 1 }, + { "doubleKey", 1D}, + { "doubleKey2", 1F}, + { "boolKey", true}, + }, 0); + var events = TimedEvents.Create(new List> + { + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event1", + new Dictionary + { + { "key", "value" }, + } + ) + ), + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event2", + new Dictionary + { + { "key", "value" }, + } + ) + ), + }, 0); + + var spanData = SpanData.Create( + SpanContext.Create( + traceId, + spanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty + ), + parentSpanId, + Resource.Empty, + "Name", + startTimestamp, + attributes, + events, + null, + null, + Status.Ok, + SpanKind.Client, + endTimestamp + ); + + var jaegerSpan = spanData.ToJaegerSpan(); + + Assert.Equal("Name", jaegerSpan.OperationName); + Assert.Equal(2, jaegerSpan.Logs.Count()); + + Assert.Equal(traceIdAsInt.High, jaegerSpan.TraceIdHigh); + Assert.Equal(traceIdAsInt.Low, jaegerSpan.TraceIdLow); + Assert.Equal(spanIdAsInt.Low, jaegerSpan.SpanId); + Assert.Equal(new Int128(parentSpanId).Low, jaegerSpan.ParentSpanId); + + Assert.Empty(jaegerSpan.References); + + Assert.Equal(0x1, jaegerSpan.Flags); + + Assert.Equal(startTimestamp.ToEpochMicroseconds(), jaegerSpan.StartTime); + Assert.Equal(endTimestamp.ToEpochMicroseconds() - startTimestamp.ToEpochMicroseconds(), jaegerSpan.Duration); + + var tags = jaegerSpan.JaegerTags.ToArray(); + var tag = tags[0]; + Assert.Equal(JaegerTagType.STRING, tag.VType); + Assert.Equal("stringKey", tag.Key); + Assert.Equal("value", tag.VStr); + tag = tags[1]; + Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal("longKey", tag.Key); + Assert.Equal(1, tag.VLong); + tag = tags[2]; + Assert.Equal(JaegerTagType.LONG, tag.VType); + Assert.Equal("longKey2", tag.Key); + Assert.Equal(1, tag.VLong); + tag = tags[3]; + Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + Assert.Equal("doubleKey", tag.Key); + Assert.Equal(1, tag.VDouble); + tag = tags[4]; + Assert.Equal(JaegerTagType.DOUBLE, tag.VType); + Assert.Equal("doubleKey2", tag.Key); + Assert.Equal(1, tag.VDouble); + tag = tags[5]; + Assert.Equal(JaegerTagType.BOOL, tag.VType); + Assert.Equal("boolKey", tag.Key); + Assert.Equal(true, tag.VBool); + + var logs = jaegerSpan.Logs.ToArray(); + var jaegerLog = logs[0]; + Assert.Equal(events.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); + Assert.Equal(2, jaegerLog.Fields.Count()); + var eventFields = jaegerLog.Fields.ToArray(); + var eventField = eventFields[0]; + Assert.Equal("key", eventField.Key); + Assert.Equal("value", eventField.VStr); + eventField = eventFields[1]; + Assert.Equal("description", eventField.Key); + Assert.Equal("Event1", eventField.VStr); + + jaegerLog = logs[1]; + Assert.Equal(events.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp); + Assert.Equal(jaegerLog.Fields.Count(), 2); + eventFields = jaegerLog.Fields.ToArray(); + eventField = eventFields[0]; + Assert.Equal("key", eventField.Key); + Assert.Equal("value", eventField.VStr); + eventField = eventFields[1]; + Assert.Equal("description", eventField.Key); + Assert.Equal("Event2", eventField.VStr); + } + } +} diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs new file mode 100644 index 00000000000..947affc9c64 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/JaegerThriftIntegrationTest.cs @@ -0,0 +1,132 @@ +// +// 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.Exporter.Jaeger.Tests.Implementation +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Threading; + using OpenTelemetry.Exporter.Jaeger.Implementation; + using OpenTelemetry.Resources; + using OpenTelemetry.Trace; + using OpenTelemetry.Trace.Export; + using Thrift.Protocols; + using Xunit; + using Process = Jaeger.Implementation.Process; + + public class JaegerThriftIntegrationTest + { + [Fact] + public async void JaegerThriftIntegrationTest_TAbstractBaseGeneratesConsistentThriftPayload() + { + var validJaegerThriftPayload = Convert.FromBase64String("goEBCWVtaXRCYXRjaBwcGAx0ZXN0IHByb2Nlc3MZHBgQdGVzdF9wcm9jZXNzX3RhZxUAGAp0ZXN0X3ZhbHVlAAAZHBbdlZjkk/C0+ZoBFtCr96fz8ZbpnQEW1KXb/ciQz6OBARaY3JDShc6hzrIBGAROYW1lGRwVABbdlZjkk/C0+ZoBFtCr96fz8ZbpnQEWkKas4ZbKtZyDAQAVAhaAgLPexpa/BRaAnJw5GWwYCXN0cmluZ0tleRUAGAV2YWx1ZQAYB2xvbmdLZXkVBkYCABgIbG9uZ0tleTIVBkYCABgJZG91YmxlS2V5FQInAAAAAAAA8D8AGApkb3VibGVLZXkyFQInAAAAAAAA8D8AGAdib29sS2V5FQQxABksFoCAs97Glr8FGSwYA2tleRUAGAV2YWx1ZQAYC2Rlc2NyaXB0aW9uFQAYBkV2ZW50MQAAFoCAs97Glr8FGSwYA2tleRUAGAV2YWx1ZQAYC2Rlc2NyaXB0aW9uFQAYBkV2ZW50MgAAAAAA"); + using (var memoryTransport = new InMemoryTransport()) + { + var protocolFactory = new TCompactProtocol.Factory(); + var thriftClient = new JaegerThriftClient(protocolFactory.GetProtocol(memoryTransport)); + var spanData = CreateTestSpan(); + var span = spanData.ToJaegerSpan(); + var process = new Process("test process", new Dictionary { { "test_process_tag", "test_value" } }); + var batch = new Batch(process, new List { span }); + + await thriftClient.EmitBatchAsync(batch, CancellationToken.None); + + var buff = memoryTransport.GetBuffer(); + + Assert.Equal(validJaegerThriftPayload, buff); + } + } + + + private SpanData CreateTestSpan() + { + var startTimestamp = new DateTime(2019, 1, 1); + var endTimestamp = startTimestamp.AddSeconds(60); + var eventTimestamp = new DateTime(2019, 1, 1); + + var traceId = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan()); + var traceIdAsInt = new Int128(traceId); + var spanId = ActivitySpanId.CreateFromString("6a69db47429ea340".AsSpan()); + var spanIdAsInt = new Int128(spanId); + var parentSpanId = ActivitySpanId.CreateFromBytes(new byte []{ 12, 23, 34, 45, 56, 67, 78, 89 }); + var attributes = Attributes.Create(new Dictionary{ + { "stringKey", "value"}, + { "longKey", 1L}, + { "longKey2", 1 }, + { "doubleKey", 1D}, + { "doubleKey2", 1F}, + { "boolKey", true}, + }, 0); + var events = TimedEvents.Create(new List> + { + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event1", + new Dictionary + { + { "key", "value" }, + } + ) + ), + TimedEvent.Create( + eventTimestamp, + Event.Create( + "Event2", + new Dictionary + { + { "key", "value" }, + } + ) + ), + }, 0); + + var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan()); + + var link = Link.FromSpanContext(SpanContext.Create( + traceId, + linkedSpanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty)); + + var linkTraceIdAsInt = new Int128(link.Context.TraceId); + var linkSpanIdAsInt = new Int128(link.Context.SpanId); + + var links = LinkList.Create(new List { link }, 0); + + return SpanData.Create( + SpanContext.Create( + traceId, + spanId, + ActivityTraceFlags.Recorded, + Tracestate.Empty + ), + parentSpanId, + Resource.Empty, + "Name", + startTimestamp, + attributes, + events, + links, + null, + Status.Ok, + SpanKind.Client, + endTimestamp + ); + } + } +} diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/ThriftUdpClientTransportTests.cs b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/ThriftUdpClientTransportTests.cs new file mode 100644 index 00000000000..8c84f808f6a --- /dev/null +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/Implementation/ThriftUdpClientTransportTests.cs @@ -0,0 +1,167 @@ +// +// 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.Exporter.Jaeger.Tests.Implementation +{ + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Moq; + using OpenTelemetry.Exporter.Jaeger.Implementation; + using Thrift.Transports; + using Xunit; + + public class ThriftUdpClientTransportTests: IDisposable + { + private MemoryStream testingMemoryStream = new MemoryStream(); + private readonly Mock mockClient = new Mock(); + + public void Dispose() + { + this.testingMemoryStream?.Dispose(); + } + + [Fact] + public void Constructor_ShouldConnectClient() + { + var host = "host, yo"; + var port = 4528; + + new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + + this.mockClient.Verify(t => t.Connect(host, port), Times.Once); + } + + [Fact] + public void Close_ShouldCloseClient() + { + var host = "host, yo"; + var port = 4528; + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + transport.Close(); + + this.mockClient.Verify(t => t.Close(), Times.Once); + } + + [Fact] + public async Task ReadAsync_ShouldResultInNotImplementedException() + { + var host = "host, yo"; + var port = 4528; + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + var newBuffer = new byte[8]; + + await Assert.ThrowsAsync(async () => await transport.ReadAsync(newBuffer, 0, 7, CancellationToken.None)); + } + + [Fact] + public async Task WriteAsync_ShouldWriteToMemoryStream() + { + var host = "host, yo"; + var port = 4528; + var writeBuffer = new byte[] { 0x20, 0x10, 0x40, 0x30, 0x18, 0x14, 0x10, 0x28 }; + var readBuffer = new byte[8]; + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + + await transport.WriteAsync(writeBuffer, CancellationToken.None); + this.testingMemoryStream.Seek(0, SeekOrigin.Begin); + var size = await this.testingMemoryStream.ReadAsync(readBuffer, 0, 8, CancellationToken.None); + + Assert.Equal(8, size); + Assert.Equal(writeBuffer, readBuffer); + } + + [Fact] + public void FlushAsync_ShouldReturnWhenNothingIsInTheStream() + { + var host = "host, yo"; + var port = 4528; + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + var tInfo = transport.FlushAsync(); + + Assert.True(tInfo.IsCompleted); + this.mockClient.Verify(t => t.SendAsync(It.IsAny(), It.IsAny()), Times.Never); + } + + [Fact] + public void FlushAsync_ShouldSendStreamBytes() + { + var host = "host, yo"; + var port = 4528; + var streamBytes = new byte[] { 0x20, 0x10, 0x40, 0x30, 0x18, 0x14, 0x10, 0x28 }; + this.testingMemoryStream = new MemoryStream(streamBytes); + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + var tInfo = transport.FlushAsync(); + + Assert.True(tInfo.IsCompleted); + this.mockClient.Verify(t => t.SendAsync(It.IsAny(), 8), Times.Once); + } + + [Fact] + public async Task FlushAsync_ShouldThrowWhenClientDoes() + { + var host = "host, yo"; + var port = 4528; + var streamBytes = new byte[] { 0x20, 0x10, 0x40, 0x30, 0x18, 0x14, 0x10, 0x28 }; + this.testingMemoryStream = new MemoryStream(streamBytes); + + //this.mockClient.Setup(t => t.SendAsync(It.IsAny(), It.IsAny())).Throws("message, yo"); + this.mockClient.Setup(t => t.SendAsync(It.IsAny(), It.IsAny())).Throws(new Exception("message, yo")); + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + var ex = await Assert.ThrowsAsync(() => transport.FlushAsync()); + + Assert.Equal("Cannot flush closed transport. message, yo", ex.Message); + } + + [Fact] + public void Dispose_ShouldCloseClientAndDisposeMemoryStream() + { + var host = "host, yo"; + var port = 4528; + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + transport.Dispose(); + + this.mockClient.Verify(t => t.Dispose(), Times.Once); + Assert.False(this.testingMemoryStream.CanRead); + Assert.False(this.testingMemoryStream.CanSeek); + Assert.False(this.testingMemoryStream.CanWrite); + } + + [Fact] + public void Dispose_ShouldNotTryToDisposeResourcesMoreThanOnce() + { + var host = "host, yo"; + var port = 4528; + + var transport = new JaegerThriftClientTransport(host, port, this.testingMemoryStream, this.mockClient.Object); + transport.Dispose(); + transport.Dispose(); + + this.mockClient.Verify(t => t.Dispose(), Times.Once); + Assert.False(this.testingMemoryStream.CanRead); + Assert.False(this.testingMemoryStream.CanSeek); + Assert.False(this.testingMemoryStream.CanWrite); + } + } +} diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj b/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj new file mode 100644 index 00000000000..0f995164e4b --- /dev/null +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj @@ -0,0 +1,31 @@ + + + Unit test project for Stackdriver Exporter for OpenTelemetry + net46;netcoreapp2.1 + netcoreapp2.1 + false + + + + + PreserveNewest + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + + diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/xunit.runner.json b/test/OpenTelemetry.Exporter.Jaeger.Tests/xunit.runner.json new file mode 100644 index 00000000000..9fbc9011580 --- /dev/null +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "maxParallelThreads": 1, + "parallelizeTestCollections": false +} \ No newline at end of file From b02f3121076c9d2071cde0bb8d3ebf10fe416a5f Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Wed, 24 Jul 2019 05:02:11 +0200 Subject: [PATCH 25/41] review use of lists (#151) * review use of lists * Use Enumerable.Empty * Remove alloc of empty array --- src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs | 2 +- src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs | 4 ++-- .../Implementation/MetricsConversions.cs | 3 +-- .../Implementation/ZipkinSpan.cs | 2 +- src/OpenTelemetry/Stats/MutableViewData.cs | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs index e5c8e26a688..cee0da7f608 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/LinkList.cs @@ -22,7 +22,7 @@ namespace OpenTelemetry.Trace.Export public sealed class LinkList : ILinks { - public static readonly LinkList Empty = new LinkList(new ILink[0], 0); + public static readonly LinkList Empty = new LinkList(Enumerable.Empty(), 0); internal LinkList(IEnumerable links, int droppedLinksCount) { diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs index 6d7a20e7656..aa0f3b3865c 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Export/TimedEvents.cs @@ -22,11 +22,11 @@ namespace OpenTelemetry.Trace.Export public sealed class TimedEvents : ITimedEvents { - public static readonly ITimedEvents Empty = new TimedEvents(new ITimedEvent[0], 0); + public static readonly ITimedEvents Empty = new TimedEvents(Enumerable.Empty>(), 0); internal TimedEvents(IEnumerable> events, int droppedEventsCount) { - this.Events = events ?? throw new ArgumentNullException("Null events"); + this.Events = events ?? throw new ArgumentNullException(nameof(events), "Null events"); this.DroppedEventsCount = droppedEventsCount; } diff --git a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs index 7bed6c09936..be08f394a26 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/Implementation/MetricsConversions.cs @@ -248,8 +248,7 @@ public static List CreateTimeSeriesList( timeSeries.Metric = GetMetric(view, labels, metricDescriptor, domain); var point = ExtractPointInInterval(viewData.Start, viewData.End, view.Aggregation, points); - var timeSeriesPoints = new List { point }; - timeSeries.Points.AddRange(timeSeriesPoints); + timeSeries.Points.Add(point); timeSeriesList.Add(timeSeries); } diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs index 07691a5c077..5872bd165b0 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinSpan.cs @@ -52,7 +52,7 @@ internal class ZipkinSpan public ZipkinEndpoint RemoteEndpoint { get; set; } [JsonProperty("annotations")] - public List Annotations { get; set; } + public IList Annotations { get; set; } [JsonProperty("tags")] public Dictionary Tags { get; set; } diff --git a/src/OpenTelemetry/Stats/MutableViewData.cs b/src/OpenTelemetry/Stats/MutableViewData.cs index 3ea7de72faf..9666228bee8 100644 --- a/src/OpenTelemetry/Stats/MutableViewData.cs +++ b/src/OpenTelemetry/Stats/MutableViewData.cs @@ -53,7 +53,7 @@ protected MutableViewData(IView view) private static Func CreateDistributionData { get; } = (s) => { - var boxedBucketCounts = new List(); + var boxedBucketCounts = new List(s.BucketCounts.Length); foreach (var bucketCount in s.BucketCounts) { boxedBucketCounts.Add(bucketCount); From d1e66e1e0b721feba856a6162cb8a262c6e7989c Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Wed, 24 Jul 2019 19:46:09 +0200 Subject: [PATCH 26/41] Build all targets in all platforms. (#155) * build all targets in all platforms Resolves #154 * Tests for netfx run only on Windows * AppInsights can build x-plat * fix: TFMs for Jaeger --- Directory.Build.props | 5 +++++ lib/Thrift/Thrift.csproj | 1 - .../OpenTelemetry.Abstractions.csproj | 1 - .../OpenTelemetry.Collector.AspNetCore.csproj | 1 - .../OpenTelemetry.Collector.Dependencies.csproj | 1 - .../OpenTelemetry.Collector.StackExchangeRedis.csproj | 1 - .../OpenTelemetry.Exporter.ApplicationInsights.csproj | 1 - .../OpenTelemetry.Exporter.Jaeger.csproj | 1 - .../OpenTelemetry.Exporter.Ocagent.csproj | 1 - .../OpenTelemetry.Exporter.Prometheus.csproj | 1 - .../OpenTelemetry.Exporter.Stackdriver.csproj | 1 - .../OpenTelemetry.Exporter.Zipkin.csproj | 1 - src/OpenTelemetry/OpenTelemetry.csproj | 1 - .../OpenTelemetry.Collector.StackExchangeRedis.Tests.csproj | 5 ++--- .../OpenTelemetry.Exporter.ApplicationInsights.Tests.csproj | 5 ++--- .../OpenTelemetry.Exporter.Jaeger.Tests.csproj | 4 ++-- .../OpenTelemetry.Exporter.Stackdriver.Tests.csproj | 5 ++--- test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj | 4 ++-- 18 files changed, 15 insertions(+), 25 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index abd99817026..e9c59969936 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,4 +4,9 @@ https://github.com/open-telemetry/opentelemetry-dotnet 7.3 + + + + + \ No newline at end of file diff --git a/lib/Thrift/Thrift.csproj b/lib/Thrift/Thrift.csproj index 3dbd8203b50..89cbb63b6f1 100644 --- a/lib/Thrift/Thrift.csproj +++ b/lib/Thrift/Thrift.csproj @@ -2,7 +2,6 @@ net46;netstandard2.0 - netstandard2.0 OpenTelemetry authors https://opentelemetry.io/img/logos/opentelemetry-icon-color.png https://OpenTelemetry.io diff --git a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj index 54d3ce88609..d21e1c3be4b 100644 --- a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj +++ b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj @@ -1,7 +1,6 @@  net45;netstandard2.0 - netstandard2.0 OpenTelemetry .NET API abstractions OpenTelemetry $(DefineConstants);ABSTRACTIONS diff --git a/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj b/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj index 9fbdadc7244..a4adbaa47b5 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj +++ b/src/OpenTelemetry.Collector.AspNetCore/OpenTelemetry.Collector.AspNetCore.csproj @@ -1,7 +1,6 @@  netstandard2.0 - netstandard2.0 OpenTelemetry collector for ASP.NET Core requests $(PackageTags);distributed-tracing;AspNetCore diff --git a/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj b/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj index 9ffc850c8b1..5efb78f3871 100644 --- a/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj +++ b/src/OpenTelemetry.Collector.Dependencies/OpenTelemetry.Collector.Dependencies.csproj @@ -1,7 +1,6 @@  netstandard2.0 - netstandard2.0 OpenTelemetry collector for calls to dependencies $(PackageTags);distributed-tracing;HttpClient diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/OpenTelemetry.Collector.StackExchangeRedis.csproj b/src/OpenTelemetry.Collector.StackExchangeRedis/OpenTelemetry.Collector.StackExchangeRedis.csproj index 12cf37e57e2..631135fbd50 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/OpenTelemetry.Collector.StackExchangeRedis.csproj +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/OpenTelemetry.Collector.StackExchangeRedis.csproj @@ -1,7 +1,6 @@  netstandard2.0;net461 - netstandard2.0 OpenTelemetry collector for Redis calls made by StackExchange.Redis library. $(PackageTags);distributed-tracing;Redis;StackExchange.Redis diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj b/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj index f56d57ee129..475d59b92e8 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/OpenTelemetry.Exporter.ApplicationInsights.csproj @@ -1,7 +1,6 @@  net46;netstandard2.0 - netstandard2.0 Application Insights exporter for Open Census. $(PackageTags);application-insights;azure;distributed-tracing diff --git a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj index 879d3410513..298d1b9dc61 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj +++ b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj @@ -2,7 +2,6 @@ net46;netstandard2.0 - netstandard2.0 OpenTelemetry authors https://opentelemetry.io/img/logos/opentelemetry-icon-color.png https://OpenTelemetry.io diff --git a/src/OpenTelemetry.Exporter.Ocagent/OpenTelemetry.Exporter.Ocagent.csproj b/src/OpenTelemetry.Exporter.Ocagent/OpenTelemetry.Exporter.Ocagent.csproj index c1105f52eaa..f9d0d15bec4 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/OpenTelemetry.Exporter.Ocagent.csproj +++ b/src/OpenTelemetry.Exporter.Ocagent/OpenTelemetry.Exporter.Ocagent.csproj @@ -1,7 +1,6 @@  net46;netstandard2.0 - netstandard2.0 OcAgent exporter for OpenTelemetry $(PackageTags);ocagent;distributed-tracing diff --git a/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj b/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj index 5a86702073c..46c1e64fb86 100644 --- a/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj +++ b/src/OpenTelemetry.Exporter.Prometheus/OpenTelemetry.Exporter.Prometheus.csproj @@ -1,7 +1,6 @@  net46;netstandard2.0 - netstandard2.0 OpenTelemetry to Prometheus exporter. $(PackageTags);Prometheus diff --git a/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj b/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj index eb58484c84d..c9d7cf978ca 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj +++ b/src/OpenTelemetry.Exporter.Stackdriver/OpenTelemetry.Exporter.Stackdriver.csproj @@ -1,7 +1,6 @@  net46;netstandard2.0 - netstandard2.0 Stackdriver .NET Exporter for OpenTelemetry. True $(PackageTags);Stackdriver;Google;GCP;distributed-tracing diff --git a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj index 2d1f920d7c8..aefd16daa65 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj +++ b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj @@ -1,7 +1,6 @@  net46;netstandard2.0 - netstandard2.0 Zipkin exporter for OpenTelemetry $(PackageTags);Zipkin;distributed-tracing diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index 0598216a268..86d4a90d0de 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -1,7 +1,6 @@  net46;netstandard2.0 - netstandard2.0 OpenTelemetry .NET API diff --git a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/OpenTelemetry.Collector.StackExchangeRedis.Tests.csproj b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/OpenTelemetry.Collector.StackExchangeRedis.Tests.csproj index 10cc445ef7a..3ac713a51f7 100644 --- a/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/OpenTelemetry.Collector.StackExchangeRedis.Tests.csproj +++ b/test/OpenTelemetry.Collector.StackExchangeRedis.Tests/OpenTelemetry.Collector.StackExchangeRedis.Tests.csproj @@ -1,10 +1,9 @@  Unit test project for ApplicationInsights Exporter for OpenTelemetry - net461;netcoreapp2.1 - netcoreapp2.1 + netcoreapp2.1 + $(TargetFrameworks);net461 - diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/OpenTelemetry.Exporter.ApplicationInsights.Tests.csproj b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/OpenTelemetry.Exporter.ApplicationInsights.Tests.csproj index 4a52b2fe068..1d85b03a9ff 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/OpenTelemetry.Exporter.ApplicationInsights.Tests.csproj +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/OpenTelemetry.Exporter.ApplicationInsights.Tests.csproj @@ -1,10 +1,9 @@  Unit test project for ApplicationInsights Exporter for OpenTelemetry - net46;netcoreapp2.1 - netcoreapp2.1 + netcoreapp2.1 + $(TargetFrameworks);net46 - PreserveNewest diff --git a/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj b/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj index 0f995164e4b..85b1fceb42c 100644 --- a/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj +++ b/test/OpenTelemetry.Exporter.Jaeger.Tests/OpenTelemetry.Exporter.Jaeger.Tests.csproj @@ -1,8 +1,8 @@ Unit test project for Stackdriver Exporter for OpenTelemetry - net46;netcoreapp2.1 - netcoreapp2.1 + netcoreapp2.1 + $(TargetFrameworks);net46 false diff --git a/test/OpenTelemetry.Exporter.Stackdriver.Tests/OpenTelemetry.Exporter.Stackdriver.Tests.csproj b/test/OpenTelemetry.Exporter.Stackdriver.Tests/OpenTelemetry.Exporter.Stackdriver.Tests.csproj index 266506afbe2..619ceb3fe98 100644 --- a/test/OpenTelemetry.Exporter.Stackdriver.Tests/OpenTelemetry.Exporter.Stackdriver.Tests.csproj +++ b/test/OpenTelemetry.Exporter.Stackdriver.Tests/OpenTelemetry.Exporter.Stackdriver.Tests.csproj @@ -1,10 +1,9 @@  Unit test project for Stackdriver Exporter for OpenTelemetry - net46;netcoreapp2.1 - netcoreapp2.1 + netcoreapp2.1 + $(TargetFrameworks);net46 - PreserveNewest diff --git a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj index ec477c3b1c1..79aad31d772 100644 --- a/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj +++ b/test/OpenTelemetry.Tests/OpenTelemetry.Tests.csproj @@ -1,8 +1,8 @@  Unit test project for OpenTelemetry - net46;netcoreapp2.1 - netcoreapp2.1 + netcoreapp2.1 + $(TargetFrameworks);net46 From 175ae3bf0d37f418b49c8c5ad480d1017314f7d6 Mon Sep 17 00:00:00 2001 From: Tim Wegner Date: Wed, 24 Jul 2019 17:45:25 -0700 Subject: [PATCH 27/41] Dev/twegner/issue 139 (#153) * Removing ExportComponent * Updating IExportComponent references * Updating references to ExportComponent --- samples/Exporters/TestApplicationInsights.cs | 8 +-- samples/Exporters/TestHttpClient.cs | 2 +- samples/Exporters/TestJaeger.cs | 4 +- samples/Exporters/TestRedis.cs | 6 +- samples/Exporters/TestStackdriver.cs | 2 +- samples/Exporters/TestZipkin.cs | 4 +- .../Trace/Export/IExportComponent.cs | 29 --------- .../StackExchangeRedisCallsCollector.cs | 10 +-- .../ApplicationInsightsExporter.cs | 12 ++-- .../JaegerExporter.cs | 14 ++--- .../OcagentExporter.cs | 12 ++-- .../StackdriverExporter.cs | 22 +++---- .../ZipkinTraceExporter.cs | 12 ++-- .../Trace/Export/ExportComponent.cs | 63 ------------------- .../Trace/Export/NoopExportComponent.cs | 25 -------- .../Trace/Export/SpanExporter.cs | 12 ++-- src/OpenTelemetry/Trace/Tracing.cs | 14 +---- .../Trace/Export/ExportComponentBaseTest.cs | 31 --------- .../Impl/Trace/Export/ExportComponentTest.cs | 33 ---------- .../Impl/Trace/TracingTest.cs | 2 +- test/TestApp.AspNetCore.2.0/Startup.cs | 4 +- 21 files changed, 66 insertions(+), 255 deletions(-) delete mode 100644 src/OpenTelemetry.Abstractions/Trace/Export/IExportComponent.cs delete mode 100644 src/OpenTelemetry/Trace/Export/ExportComponent.cs delete mode 100644 src/OpenTelemetry/Trace/Export/NoopExportComponent.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs delete mode 100644 test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs diff --git a/samples/Exporters/TestApplicationInsights.cs b/samples/Exporters/TestApplicationInsights.cs index 4ef62531c65..5df8d96bfa8 100644 --- a/samples/Exporters/TestApplicationInsights.cs +++ b/samples/Exporters/TestApplicationInsights.cs @@ -53,11 +53,11 @@ internal class TestApplicationInsights internal static object Run() { SimpleEventQueue eventQueue = new SimpleEventQueue(); - ExportComponent exportComponent = ExportComponent.CreateWithInProcessStores(eventQueue); + ISpanExporter exporter = OpenTelemetry.Trace.Export.SpanExporter.Create(); TelemetryConfiguration.Active.InstrumentationKey = "instrumentation-key"; - var exporter = new ApplicationInsightsExporter(exportComponent, Stats.ViewManager, TelemetryConfiguration.Active); - exporter.Start(); + var appInsightsExporter = new ApplicationInsightsExporter(exporter, Stats.ViewManager, TelemetryConfiguration.Active); + appInsightsExporter.Start(); var tagContextBuilder = Tagger.CurrentBuilder.Put(FrontendKey, TagValue.Create("mobile-ios9.3.5")); @@ -88,7 +88,7 @@ internal static object Run() Console.WriteLine("Done... wait for events to arrive to backend!"); Console.ReadLine(); - exportComponent.SpanExporter.Dispose(); + exporter.Dispose(); return null; } diff --git a/samples/Exporters/TestHttpClient.cs b/samples/Exporters/TestHttpClient.cs index 4e2ed713abb..ada6d0a2c97 100644 --- a/samples/Exporters/TestHttpClient.cs +++ b/samples/Exporters/TestHttpClient.cs @@ -39,7 +39,7 @@ internal static object Run() Endpoint = new Uri("https://zipkin.azurewebsites.net/api/v2/spans"), ServiceName = typeof(Program).Assembly.GetName().Name, }, - Tracing.ExportComponent); + Tracing.SpanExporter); exporter.Start(); using (Tracer.WithSpan(Tracer.SpanBuilder("incoming request").SetSampler(Samplers.AlwaysSample).StartSpan())) diff --git a/samples/Exporters/TestJaeger.cs b/samples/Exporters/TestJaeger.cs index 941bd5b12e8..60e4c7ca962 100644 --- a/samples/Exporters/TestJaeger.cs +++ b/samples/Exporters/TestJaeger.cs @@ -36,7 +36,7 @@ internal static object Run(string host, int port) AgentHost = host, AgentPort = port, }, - Tracing.ExportComponent); + Tracing.SpanExporter); exporter.Start(); @@ -64,7 +64,7 @@ internal static object Run(string host, int port) } // 5. Gracefully shutdown the exporter so it'll flush queued traces to Zipkin. - Tracing.ExportComponent.SpanExporter.Dispose(); + Tracing.SpanExporter.Dispose(); return null; } diff --git a/samples/Exporters/TestRedis.cs b/samples/Exporters/TestRedis.cs index 785fab1e08c..96fe68c9750 100644 --- a/samples/Exporters/TestRedis.cs +++ b/samples/Exporters/TestRedis.cs @@ -36,7 +36,7 @@ internal static object Run(string zipkinUri) Endpoint = new Uri(zipkinUri), ServiceName = "tracing-to-zipkin-service", }, - Tracing.ExportComponent); + Tracing.SpanExporter); exporter.Start(); // 2. Configure 100% sample rate for the purposes of the demo @@ -51,7 +51,7 @@ internal static object Run(string zipkinUri) // but if not - you can use it as follows: var tracer = Tracing.Tracer; - var collector = new StackExchangeRedisCallsCollector(tracer, null, Tracing.ExportComponent); + var collector = new StackExchangeRedisCallsCollector(tracer, null, Tracing.SpanExporter); // connect to the server var connection = ConnectionMultiplexer.Connect("localhost:6379"); @@ -71,7 +71,7 @@ internal static object Run(string zipkinUri) } // 5. Gracefully shutdown the exporter so it'll flush queued traces to Zipkin. - Tracing.ExportComponent.SpanExporter.Dispose(); + Tracing.SpanExporter.Dispose(); return null; } diff --git a/samples/Exporters/TestStackdriver.cs b/samples/Exporters/TestStackdriver.cs index 97bff278763..ccb52747a07 100644 --- a/samples/Exporters/TestStackdriver.cs +++ b/samples/Exporters/TestStackdriver.cs @@ -51,7 +51,7 @@ internal static object Run(string projectId) { var exporter = new StackdriverExporter( projectId, - Tracing.ExportComponent, + Tracing.SpanExporter, Stats.ViewManager); exporter.Start(); diff --git a/samples/Exporters/TestZipkin.cs b/samples/Exporters/TestZipkin.cs index ea75c4509ee..ff672c36de9 100644 --- a/samples/Exporters/TestZipkin.cs +++ b/samples/Exporters/TestZipkin.cs @@ -34,7 +34,7 @@ internal static object Run(string zipkinUri) Endpoint = new Uri(zipkinUri), ServiceName = "tracing-to-zipkin-service", }, - Tracing.ExportComponent); + Tracing.SpanExporter); exporter.Start(); // 2. Configure 100% sample rate for the purposes of the demo @@ -60,7 +60,7 @@ internal static object Run(string zipkinUri) } // 5. Gracefully shutdown the exporter so it'll flush queued traces to Zipkin. - Tracing.ExportComponent.SpanExporter.Dispose(); + Tracing.SpanExporter.Dispose(); return null; } diff --git a/src/OpenTelemetry.Abstractions/Trace/Export/IExportComponent.cs b/src/OpenTelemetry.Abstractions/Trace/Export/IExportComponent.cs deleted file mode 100644 index a860554d3fa..00000000000 --- a/src/OpenTelemetry.Abstractions/Trace/Export/IExportComponent.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// 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.Export -{ - /// - /// Component that exports spans. - /// - public interface IExportComponent - { - /// - /// Gets the span exporter. - /// - ISpanExporter SpanExporter { get; } - } -} \ No newline at end of file diff --git a/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs b/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs index c9d752905a6..d325d8cbd99 100644 --- a/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs +++ b/src/OpenTelemetry.Collector.StackExchangeRedis/StackExchangeRedisCallsCollector.cs @@ -32,7 +32,7 @@ namespace OpenTelemetry.Collector.StackExchangeRedis public class StackExchangeRedisCallsCollector : IDisposable { private readonly ITracer tracer; - private readonly IExportComponent exporter; + private readonly ISpanExporter exporter; private readonly ISampler sampler; private readonly CancellationTokenSource cancellationTokenSource; @@ -46,11 +46,11 @@ public class StackExchangeRedisCallsCollector : IDisposable /// /// Tracer to record traced with. /// Sampler to use to sample dependnecy calls. - /// TEMPORARY: handler to send data to. - public StackExchangeRedisCallsCollector(ITracer tracer, ISampler sampler, IExportComponent exportComponent) + /// TEMPORARY: handler to send data to. + public StackExchangeRedisCallsCollector(ITracer tracer, ISampler sampler, ISpanExporter exporter) { this.tracer = tracer; - this.exporter = exportComponent; + this.exporter = exporter; this.sampler = sampler; this.cancellationTokenSource = new CancellationTokenSource(); @@ -125,7 +125,7 @@ private void DumpEntries(object state) foreach (var s in spans) { - this.exporter.SpanExporter.ExportAsync(s, CancellationToken.None).Wait(); + this.exporter.ExportAsync(s, CancellationToken.None).Wait(); } Thread.Sleep(TimeSpan.FromSeconds(1)); diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs index 561d5681915..22fe5a96446 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs @@ -35,7 +35,7 @@ public class ApplicationInsightsExporter private readonly IViewManager viewManager; - private readonly IExportComponent exportComponent; + private readonly ISpanExporter exporter; private readonly object lck = new object(); @@ -49,12 +49,12 @@ public class ApplicationInsightsExporter /// Initializes a new instance of the class. /// This exporter allows to send Open Census data to Azure Application Insights. /// - /// Exporter to get traces and metrics from. + /// Exporter to get traces and metrics from. /// View manager to get stats from. /// Telemetry configuration to use to report telemetry. - public ApplicationInsightsExporter(IExportComponent exportComponent, IViewManager viewManager, TelemetryConfiguration telemetryConfiguration) + public ApplicationInsightsExporter(ISpanExporter exporter, IViewManager viewManager, TelemetryConfiguration telemetryConfiguration) { - this.exportComponent = exportComponent; + this.exporter = exporter; this.viewManager = viewManager; this.telemetryConfiguration = telemetryConfiguration; } @@ -73,7 +73,7 @@ public void Start() this.handler = new TraceExporterHandler(this.telemetryConfiguration); - this.exportComponent.SpanExporter.RegisterHandler(TraceExporterName, this.handler); + this.exporter.RegisterHandler(TraceExporterName, this.handler); this.tokenSource = new CancellationTokenSource(); @@ -96,7 +96,7 @@ public void Stop() return; } - this.exportComponent.SpanExporter.UnregisterHandler(TraceExporterName); + this.exporter.UnregisterHandler(TraceExporterName); this.tokenSource.Cancel(); this.workerThread.Wait(); this.tokenSource = null; diff --git a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs index 60f200f26a4..c1735e6f46d 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs +++ b/src/OpenTelemetry.Exporter.Jaeger/JaegerExporter.cs @@ -30,19 +30,19 @@ public class JaegerExporter : IDisposable private readonly object @lock = new object(); private readonly JaegerExporterOptions options; - private readonly IExportComponent exportComponent; + private readonly ISpanExporter spanExporter; private volatile bool isInitialized = false; private JaegerTraceExporterHandler handler; private bool disposedValue = false; // To detect redundant dispose calls - public JaegerExporter(JaegerExporterOptions options, IExportComponent exportComponent) + public JaegerExporter(JaegerExporterOptions options, ISpanExporter spanExporter) { this.ValidateOptions(options); this.InitializeOptions(options); this.options = options; - this.exportComponent = exportComponent; + this.spanExporter = spanExporter; } public void Start() @@ -54,10 +54,10 @@ public void Start() return; } - if (this.exportComponent != null) + if (this.spanExporter != null) { this.handler = new JaegerTraceExporterHandler(this.options); - this.exportComponent.SpanExporter.RegisterHandler(ExporterName, this.handler); + this.spanExporter.RegisterHandler(ExporterName, this.handler); } } } @@ -71,9 +71,9 @@ public void Stop() lock (this.@lock) { - if (this.exportComponent != null) + if (this.spanExporter != null) { - this.exportComponent.SpanExporter.UnregisterHandler(ExporterName); + this.spanExporter.UnregisterHandler(ExporterName); } } diff --git a/src/OpenTelemetry.Exporter.Ocagent/OcagentExporter.cs b/src/OpenTelemetry.Exporter.Ocagent/OcagentExporter.cs index 59569b1a52e..c897fb74c6a 100644 --- a/src/OpenTelemetry.Exporter.Ocagent/OcagentExporter.cs +++ b/src/OpenTelemetry.Exporter.Ocagent/OcagentExporter.cs @@ -28,7 +28,7 @@ public class OcagentExporter { private const string TraceExporterName = "OcagentTraceExporter"; - private readonly IExportComponent exportComponent; + private readonly ISpanExporter exporter; private readonly object lck = new object(); @@ -41,17 +41,17 @@ public class OcagentExporter /// Initializes a new instance of the class. /// This exporter allows to send Open Census data to OpenTelemetry service or LocalForwarder. /// - /// Exporter to get traces from. + /// Exporter to get traces from. /// Agent endpoint in the host:port format. /// Name of the host. /// Name of the application. public OcagentExporter( - IExportComponent exportComponent, + ISpanExporter exporter, string agentEndpoint, string hostName, string serviceName) { - this.exportComponent = exportComponent; + this.exporter = exporter; this.agentEndpoint = agentEndpoint; this.hostName = hostName; this.serviceName = serviceName; @@ -75,7 +75,7 @@ public void Start() this.serviceName, ChannelCredentials.Insecure); - this.exportComponent.SpanExporter.RegisterHandler(TraceExporterName, this.handler); + this.exporter.RegisterHandler(TraceExporterName, this.handler); } } @@ -91,7 +91,7 @@ public void Stop() return; } - this.exportComponent.SpanExporter.UnregisterHandler(TraceExporterName); + this.exporter.UnregisterHandler(TraceExporterName); this.handler.Dispose(); this.handler = null; } diff --git a/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs b/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs index 9e220f2d2c7..cdee78e789e 100644 --- a/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs +++ b/src/OpenTelemetry.Exporter.Stackdriver/StackdriverExporter.cs @@ -30,7 +30,7 @@ public class StackdriverExporter { private const string ExporterName = "StackdriverTraceExporter"; - private readonly IExportComponent exportComponent; + private readonly ISpanExporter exporter; private readonly IViewManager viewManager; private readonly string projectId; private readonly string jsonPath; @@ -42,12 +42,12 @@ public class StackdriverExporter /// Initializes a new instance of the class. /// /// Google Cloud ProjectId that is used to send data to Stackdriver. - /// Exporter to get traces from. + /// Exporter to get traces from. /// View manager to get the stats from. public StackdriverExporter( string projectId, - IExportComponent exportComponent, - IViewManager viewManager) : this(projectId, null, exportComponent, viewManager) + ISpanExporter exporter, + IViewManager viewManager) : this(projectId, null, exporter, viewManager) { } @@ -56,19 +56,19 @@ public StackdriverExporter( /// /// Google Cloud ProjectId that is used to send data to Stackdriver. /// File path to the json file containing the service credential used to authenticate against Stackdriver APIs. - /// Exporter to get traces from. + /// Exporter to get traces from. /// View manager to get the stats from. public StackdriverExporter( string projectId, string jsonPath, - IExportComponent exportComponent, + ISpanExporter exporter, IViewManager viewManager) { GaxPreconditions.CheckNotNullOrEmpty(projectId, "projectId"); this.projectId = projectId; this.jsonPath = jsonPath; - this.exportComponent = exportComponent; + this.exporter = exporter; this.viewManager = viewManager; } @@ -85,10 +85,10 @@ public void Start() } // Register trace exporter - if (this.exportComponent != null) + if (this.exporter != null) { var traceExporter = new StackdriverTraceExporter(this.projectId); - this.exportComponent.SpanExporter.RegisterHandler(ExporterName, traceExporter); + this.exporter.RegisterHandler(ExporterName, traceExporter); } // Register stats(metrics) exporter @@ -125,9 +125,9 @@ public void Stop() } // Stop tracing exporter - if (this.exportComponent != null) + if (this.exporter != null) { - this.exportComponent.SpanExporter.UnregisterHandler(ExporterName); + this.exporter.UnregisterHandler(ExporterName); } // Stop metrics exporter diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs index 2eac6d3fdca..53eca9c88ff 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs @@ -29,7 +29,7 @@ public class ZipkinTraceExporter private readonly ZipkinTraceExporterOptions options; - private readonly IExportComponent exportComponent; + private readonly ISpanExporter exporter; private readonly object lck = new object(); @@ -42,16 +42,16 @@ public class ZipkinTraceExporter /// This exporter sends Open Census traces to Zipkin. /// /// Zipkin exporter configuration options. - /// Exporter to get traces from. + /// Exporter to get traces from. /// Http client to use to upload telemetry. /// For local development with invalid certificates use code like this: /// new HttpClient(new HttpClientHandler() { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }). /// - public ZipkinTraceExporter(ZipkinTraceExporterOptions options, IExportComponent exportComponent, HttpClient client = null) + public ZipkinTraceExporter(ZipkinTraceExporterOptions options, ISpanExporter exporter, HttpClient client = null) { this.options = options; - this.exportComponent = exportComponent; + this.exporter = exporter; this.httpClient = client; } @@ -70,7 +70,7 @@ public void Start() this.handler = new TraceExporterHandler(this.options, this.httpClient); - this.exportComponent.SpanExporter.RegisterHandler(ExporterName, this.handler); + this.exporter.RegisterHandler(ExporterName, this.handler); } } @@ -86,7 +86,7 @@ public void Stop() return; } - this.exportComponent.SpanExporter.UnregisterHandler(ExporterName); + this.exporter.UnregisterHandler(ExporterName); this.handler = null; } diff --git a/src/OpenTelemetry/Trace/Export/ExportComponent.cs b/src/OpenTelemetry/Trace/Export/ExportComponent.cs deleted file mode 100644 index e1afa58fb8f..00000000000 --- a/src/OpenTelemetry/Trace/Export/ExportComponent.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// 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.Export -{ - using System; - using OpenTelemetry.Internal; - - /// - public sealed class ExportComponent : IExportComponent - { - private const int ExporterBufferSize = 32; - - // Enforces that trace export exports data at least once every 5 seconds. - private static readonly TimeSpan ExporterScheduleDelay = TimeSpan.FromSeconds(5); - - private ExportComponent(bool supportInProcessStores, IEventQueue eventQueue) - { - this.SpanExporter = Export.SpanExporter.Create(ExporterBufferSize, ExporterScheduleDelay); - } - - /// - /// Gets a new no-op . - /// - public static IExportComponent NewNoopExportComponent => new NoopExportComponent(); - - /// - public ISpanExporter SpanExporter { get; } - - /// - /// Constructs a new with noop span stores. - /// - /// for sampled span store. - /// A new . - public static ExportComponent CreateWithoutInProcessStores(IEventQueue eventQueue) - { - return new ExportComponent(false, eventQueue); - } - - /// - /// Constructs a new with in process span stores. - /// - /// for sampled span store. - /// A new . - public static ExportComponent CreateWithInProcessStores(IEventQueue eventQueue) - { - return new ExportComponent(true, eventQueue); - } - } -} diff --git a/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs b/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs deleted file mode 100644 index b344d15c960..00000000000 --- a/src/OpenTelemetry/Trace/Export/NoopExportComponent.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// 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.Export -{ - /// - public sealed class NoopExportComponent : IExportComponent - { - /// - public ISpanExporter SpanExporter => Export.SpanExporter.NoopSpanExporter; - } -} diff --git a/src/OpenTelemetry/Trace/Export/SpanExporter.cs b/src/OpenTelemetry/Trace/Export/SpanExporter.cs index a6a5d90766d..68347f89c46 100644 --- a/src/OpenTelemetry/Trace/Export/SpanExporter.cs +++ b/src/OpenTelemetry/Trace/Export/SpanExporter.cs @@ -45,6 +45,12 @@ internal Thread ServiceExporterThread } } + public static ISpanExporter Create(int bufferSize = 32, TimeSpan? scheduleDelay = null) + { + var worker = new SpanExporterWorker(bufferSize, scheduleDelay ?? TimeSpan.FromSeconds(5)); + return new SpanExporter(worker); + } + public override void AddSpan(ISpan span) { this.worker.AddSpan(span); @@ -70,11 +76,5 @@ public override void Dispose() { this.worker.Dispose(); } - - internal static ISpanExporter Create(int bufferSize, TimeSpan scheduleDelay) - { - var worker = new SpanExporterWorker(bufferSize, scheduleDelay); - return new SpanExporter(worker); - } } } diff --git a/src/OpenTelemetry/Trace/Tracing.cs b/src/OpenTelemetry/Trace/Tracing.cs index dc1418ae357..cbe309a1914 100644 --- a/src/OpenTelemetry/Trace/Tracing.cs +++ b/src/OpenTelemetry/Trace/Tracing.cs @@ -36,19 +36,11 @@ internal Tracing() TraceConfig = new Config.TraceConfig(); - // TODO(bdrutu): Add a config/argument for supportInProcessStores. - if (eventQueue is SimpleEventQueue) - { - ExportComponent = Export.ExportComponent.CreateWithoutInProcessStores(eventQueue); - } - else - { - ExportComponent = Export.ExportComponent.CreateWithInProcessStores(eventQueue); - } + SpanExporter = Export.SpanExporter.Create(); IStartEndHandler startEndHandler = new StartEndHandler( - ExportComponent.SpanExporter, + SpanExporter, eventQueue); tracer = new Tracer(startEndHandler, TraceConfig); @@ -62,7 +54,7 @@ internal Tracing() /// /// Gets the exporter to use to upload spans. /// - public static IExportComponent ExportComponent { get; private set; } + public static ISpanExporter SpanExporter { get; private set; } /// /// Gets the trace config. diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs deleted file mode 100644 index bec26f03711..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentBaseTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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.Export.Test -{ - using Xunit; - - public class ExportComponentBaseTest - { - private readonly NoopExportComponent exportComponent = (NoopExportComponent)ExportComponent.NewNoopExportComponent; - - [Fact] - public void ImplementationOfSpanExporter() - { - Assert.Equal(SpanExporter.NoopSpanExporter, exportComponent.SpanExporter); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs deleted file mode 100644 index 63c524baed4..00000000000 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/ExportComponentTest.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// 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.Export.Test -{ - using OpenTelemetry.Internal; - using Xunit; - - public class ExportComponentTest - { - private readonly ExportComponent exportComponentWithInProcess = ExportComponent.CreateWithInProcessStores(new SimpleEventQueue()); - private readonly ExportComponent exportComponentWithoutInProcess = ExportComponent.CreateWithoutInProcessStores(new SimpleEventQueue()); - - [Fact] - public void ImplementationOfSpanExporter() - { - Assert.IsType(exportComponentWithInProcess.SpanExporter); - } - } -} diff --git a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs index 6b997344b22..38c8abb493e 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/TracingTest.cs @@ -64,7 +64,7 @@ public void DefaultTracer() [Fact(Skip = "need to fix the way tracer being instantiated")] public void DefaultTraceExporter() { - Assert.Equal(ExportComponent.NewNoopExportComponent.GetType(), Tracing.ExportComponent.GetType()); + Assert.Equal(Export.SpanExporter.NoopSpanExporter.GetType(), Tracing.SpanExporter.GetType()); } [Fact(Skip = "need to fix the way tracer being instantiated")] diff --git a/test/TestApp.AspNetCore.2.0/Startup.cs b/test/TestApp.AspNetCore.2.0/Startup.cs index 37060dc598c..e15cb48de92 100644 --- a/test/TestApp.AspNetCore.2.0/Startup.cs +++ b/test/TestApp.AspNetCore.2.0/Startup.cs @@ -50,11 +50,11 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(new DependenciesCollectorOptions()); services.AddSingleton(); - services.AddSingleton(Tracing.ExportComponent); + services.AddSingleton(Tracing.SpanExporter); services.AddSingleton(new CallbackMiddleware.CallbackMiddlewareImpl()); services.AddSingleton((p) => { - var exportComponent = p.GetService(); + var exportComponent = p.GetService(); return new OcagentExporter( exportComponent, "localhost:55678", From 487f358cafa7ae37df436165b7434b652278a60a Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 24 Jul 2019 18:15:41 -0700 Subject: [PATCH 28/41] Update to DiagnosticSource preview 7 and leverage Activity.SetIdFormat() (#160) --- .../Context/Propagation/BinaryFormat.cs | 10 ++-- .../OpenTelemetry.Abstractions.csproj | 2 +- src/OpenTelemetry.Abstractions/Trace/Link.cs | 10 ++++ src/OpenTelemetry/Trace/SpanBuilder.cs | 19 +++---- .../Impl/Trace/CurrentSpanUtilsTest.cs | 1 - .../Impl/Trace/Export/SpanExporterTest.cs | 6 +-- .../Impl/Trace/LinkTest.cs | 35 ++++++++---- .../Impl/Trace/NoopSpanBuilderTests.cs | 6 +-- .../Trace/Propagation/BinaryFormatTest.cs | 3 +- .../Impl/Trace/SpanBuilderTest.cs | 53 ++++++++++++------- .../Impl/Trace/SpanTest.cs | 26 ++++++--- 11 files changed, 113 insertions(+), 58 deletions(-) diff --git a/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs b/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs index f4a661e793b..c2645cd6e71 100644 --- a/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs +++ b/src/OpenTelemetry.Abstractions/Context/Propagation/BinaryFormat.cs @@ -34,8 +34,8 @@ public class BinaryFormat : IBinaryFormat private const int TraceIdFieldIdOffset = VersionIdOffset + IdSize; private const int TraceIdOffset = TraceIdFieldIdOffset + IdSize; private const byte SpanIdFieldId = 1; - private const int SpaneIdFieldIdOffset = TraceIdOffset + TraceIdSize; - private const int SpanIdOffset = SpaneIdFieldIdOffset + IdSize; + private const int SpanIdFieldIdOffset = TraceIdOffset + TraceIdSize; + private const int SpanIdOffset = SpanIdFieldIdOffset + IdSize; private const byte TraceOptionsFieldId = 2; private const int TraceOptionFieldIdOffset = SpanIdOffset + SpanIdSize; private const int TraceOptionOffset = TraceOptionFieldIdOffset + IdSize; @@ -96,11 +96,11 @@ public byte[] ToByteArray(SpanContext spanContext) Span spanBytes = stackalloc byte[FormatLength]; spanBytes[VersionIdOffset] = VersionId; spanBytes[TraceIdFieldIdOffset] = TraceIdFieldId; - spanBytes[SpaneIdFieldIdOffset] = SpanIdFieldId; + spanBytes[SpanIdFieldIdOffset] = SpanIdFieldId; spanBytes[TraceOptionFieldIdOffset] = TraceOptionsFieldId; spanBytes[TraceOptionOffset] = (byte)spanContext.TraceOptions; - spanContext.TraceId.CopyTo(spanBytes.Slice(TraceIdOffset)); - spanContext.SpanId.CopyTo(spanBytes.Slice(SpanIdOffset)); + spanContext.TraceId.CopyTo(spanBytes.Slice(TraceIdOffset, TraceIdSize)); + spanContext.SpanId.CopyTo(spanBytes.Slice(SpanIdOffset, SpanIdSize)); return spanBytes.ToArray(); } diff --git a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj index d21e1c3be4b..756585edaab 100644 --- a/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj +++ b/src/OpenTelemetry.Abstractions/OpenTelemetry.Abstractions.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/OpenTelemetry.Abstractions/Trace/Link.cs b/src/OpenTelemetry.Abstractions/Trace/Link.cs index 3b7045a5e26..3398869477f 100644 --- a/src/OpenTelemetry.Abstractions/Trace/Link.cs +++ b/src/OpenTelemetry.Abstractions/Trace/Link.cs @@ -48,6 +48,16 @@ private Link(SpanContext context, IDictionary attributes) /// New instance. public static ILink FromActivity(Activity activity) { + if (activity == null) + { + throw new ArgumentNullException(nameof(activity)); + } + + if (activity.IdFormat != ActivityIdFormat.W3C) + { + throw new ArgumentException("Current Activity is not in W3C format"); + } + var tracestate = Tracestate.Empty; var tracestateBuilder = Tracestate.Builder; if (TracestateUtils.TryExtractTracestate(activity.TraceStateString, tracestateBuilder)) diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index e7f21da20af..c8ebd6ea49a 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -20,7 +20,6 @@ namespace OpenTelemetry.Trace using System.Collections.Generic; using System.Diagnostics; using OpenTelemetry.Context.Propagation; - using OpenTelemetry.Internal; using OpenTelemetry.Trace.Config; /// @@ -41,10 +40,6 @@ public class SpanBuilder : ISpanBuilder internal SpanBuilder(string name, SpanBuilderOptions options) { - // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat - Activity.DefaultIdFormat = ActivityIdFormat.W3C; - Activity.ForceDefaultIdFormat = true; - this.name = name ?? throw new ArgumentNullException(nameof(name)); this.options = options ?? throw new ArgumentNullException(nameof(options)); } @@ -343,8 +338,10 @@ private Activity CreateActivityForSpan(ContextSource contextSource, ISpan explic case ContextSource.CurrentActivityParent: { // Activity will figure out its parent - spanActivity = new Activity(this.name).Start(); - + spanActivity = new Activity(this.name) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); + // chances are, Activity.Current has span attached if (CurrentSpanUtils.CurrentSpan is Span currentSpan) { @@ -372,8 +369,10 @@ private Activity CreateActivityForSpan(ContextSource contextSource, ISpan explic case ContextSource.NoParent: { - // TODO fix after next DiagnosticSource preview comes out - this is a hack to force activity to become orphan - spanActivity = new Activity(this.name).SetParentId(" ").Start(); + spanActivity = new Activity(this.name) + .SetIdFormat(ActivityIdFormat.W3C) + .SetParentId(" ") + .Start(); this.parentSpanContext = null; break; } @@ -396,6 +395,7 @@ private Activity CreateActivityForSpan(ContextSource contextSource, ISpan explic this.parentSpanContext.TraceOptions); } + spanActivity.SetIdFormat(ActivityIdFormat.W3C); spanActivity.TraceStateString = this.parentSpanContext.Tracestate.ToString(); spanActivity.Start(); @@ -412,6 +412,7 @@ private Activity CreateActivityForSpan(ContextSource contextSource, ISpan explic this.parentSpan.Context.TraceOptions); } + spanActivity.SetIdFormat(ActivityIdFormat.W3C); spanActivity.TraceStateString = this.parentSpan.Context.Tracestate.ToString(); spanActivity.Start(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs index 1116422afac..0ea5b3a4f03 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/CurrentSpanUtilsTest.cs @@ -28,7 +28,6 @@ public class CurrentSpanUtilsTest: IDisposable public CurrentSpanUtilsTest() { - // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat Activity.DefaultIdFormat = ActivityIdFormat.W3C; Activity.ForceDefaultIdFormat = true; } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs index 12b894c5422..5c4e12c25a6 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Export/SpanExporterTest.cs @@ -41,10 +41,6 @@ public class SpanExporterTest : IDisposable public SpanExporterTest() { - // TODO - Activity.DefaultIdFormat = ActivityIdFormat.W3C; - Activity.ForceDefaultIdFormat = true; - startEndHandler = new StartEndHandler(spanExporter, new SimpleEventQueue()); spanExporter.RegisterHandler("test.service", serviceHandler); } @@ -53,6 +49,7 @@ private Span CreateSampledEndedSpan(string spanName) { var sampledActivity = new Activity(spanName); sampledActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; + sampledActivity.SetIdFormat(ActivityIdFormat.W3C); sampledActivity.Start(); var span = Span.StartSpan( @@ -68,6 +65,7 @@ private Span CreateSampledEndedSpan(string spanName) private Span CreateNotSampledEndedSpan(string spanName) { var notSampledActivity = new Activity(spanName); + notSampledActivity.SetIdFormat(ActivityIdFormat.W3C); notSampledActivity.Start(); var span = Span.StartSpan( diff --git a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs index f157c7ed31f..41ec3e92e36 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/LinkTest.cs @@ -14,16 +14,15 @@ // limitations under the License. // -using System.Linq; - namespace OpenTelemetry.Trace.Test { + using System; + using System.Linq; using System.Collections.Generic; using System.Diagnostics; - using OpenTelemetry.Utils; using Xunit; - public class LinkTest + public class LinkTest : IDisposable { private readonly IDictionary attributesMap = new Dictionary(); private readonly SpanContext spanContext; @@ -31,10 +30,6 @@ public class LinkTest public LinkTest() { - // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat - Activity.DefaultIdFormat = ActivityIdFormat.W3C; - Activity.ForceDefaultIdFormat = true; - spanContext = SpanContext.Create(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); ; attributesMap.Add("MyAttributeKey0", "MyStringAttribute"); @@ -93,7 +88,9 @@ public void Link_ToString() [Fact] public void FromSpanContext_FromActivity() { - var activity = new Activity("foo").Start(); + var activity = new Activity("foo") + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activity.TraceStateString = "k1=v1, k2=v2"; var link = Link.FromActivity(activity); @@ -107,5 +104,25 @@ public void FromSpanContext_FromActivity() Assert.Equal("k2", entries[1].Key); Assert.Equal("v2", entries[1].Value); } + + [Fact] + public void FromSpanContext_FromNullActivity() + { + Assert.Throws( () => Link.FromActivity(null)); + } + + [Fact] + public void FromSpanContext_FromHierarchicalActivity() + { + var activity = new Activity("foo") + .SetIdFormat(ActivityIdFormat.Hierarchical) + .Start(); + Assert.Throws(() => Link.FromActivity(activity)); + } + + public void Dispose() + { + Activity.Current = null; + } } } diff --git a/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs b/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs index 30ee42b591b..24ed4523910 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/NoopSpanBuilderTests.cs @@ -37,9 +37,9 @@ public void NoopSpanBuilder_BadArguments() Assert.Throws(() => spanBuilder.SetCreateChild(false)); // Activity.Current wrong format - Activity.DefaultIdFormat = ActivityIdFormat.Hierarchical; - Activity.ForceDefaultIdFormat = true; - var a = new Activity("foo").Start(); // TODO SetIdFormat + var a = new Activity("foo") + .SetIdFormat(ActivityIdFormat.Hierarchical) + .Start(); Assert.Throws(() => spanBuilder.SetCreateChild(false)); a.Stop(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs index dd85bb1d9ab..e28476d35a0 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/Propagation/BinaryFormatTest.cs @@ -46,8 +46,7 @@ private void TestSpanContextConversion(SpanContext spanContext) [Fact] public void Propagate_SpanContextTracingEnabled() { - TestSpanContextConversion( - SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.Recorded, Tracestate.Empty)); + TestSpanContextConversion(SpanContext.Create(TraceId, SpanId, ActivityTraceFlags.Recorded, Tracestate.Empty)); } [Fact] diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs index f34ea73894b..63d88b47b57 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanBuilderTest.cs @@ -19,7 +19,6 @@ namespace OpenTelemetry.Trace.Test using System; using System.Diagnostics; using System.Collections.Generic; - using System.Globalization; using System.Linq; using Moq; using OpenTelemetry.Abstractions.Utils; @@ -42,10 +41,6 @@ public class SpanBuilderTest : IDisposable private readonly ITracer tracer; public SpanBuilderTest() { - // TODO: remove with next DiagnosticSource preview, switch to Activity setidformat - Activity.DefaultIdFormat = ActivityIdFormat.W3C; - Activity.ForceDefaultIdFormat = true; - // MockitoAnnotations.initMocks(this); spanBuilderOptions = new SpanBuilderOptions(startEndHandler, traceConfig); @@ -165,7 +160,9 @@ public void StartSpanLastParentWins5() ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var activity = new Activity("foo").Start(); + var activity = new Activity("foo") + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .SetParent(spanContext) @@ -185,7 +182,9 @@ public void StartSpanLastParentWins6() ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var activity = new Activity("foo").Start(); + var activity = new Activity("foo") + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .SetParent(spanContext) @@ -205,7 +204,9 @@ public void StartSpanLastParentWins7() ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); - var activity = new Activity("foo").Start(); + var activity = new Activity("foo") + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); var childSpan = (Span)new SpanBuilder(SpanName, spanBuilderOptions) .SetCreateChild(false) @@ -271,7 +272,9 @@ public void StartChildSpan() [Fact] public void StartSpanInScopeOfCurrentActivity() { - var parentActivity = new Activity(SpanName).Start(); + var parentActivity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); parentActivity.TraceStateString = "k1=v1,k2=v2"; var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) @@ -292,7 +295,9 @@ public void StartSpanInScopeOfCurrentActivity() [Fact] public void StartSpanInScopeOfCurrentActivityRecorded() { - var parentActivity = new Activity(SpanName).Start(); + var parentActivity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var childSpan = new SpanBuilder(SpanName, spanBuilderOptions) @@ -332,7 +337,9 @@ public void StartSpanInScopeOfCurrentActivityNoParent() [Fact] public void StartSpanFromExplicitActivity() { - var parentActivity = new Activity(SpanName).Start(); + var parentActivity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); parentActivity.TraceStateString = "k1=v1,k2=v2"; parentActivity.Stop(); @@ -357,7 +364,9 @@ public void StartSpanFromExplicitActivity() [Fact] public void StartSpanFromExplicitRecordedActivity() { - var parentActivity = new Activity(SpanName).Start(); + var parentActivity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); parentActivity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; parentActivity.Stop(); @@ -375,7 +384,9 @@ public void StartSpanFromExplicitRecordedActivity() [Fact] public void StartSpanFromCurrentActivity() { - var activity = new Activity(SpanName).Start(); + var activity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activity.TraceStateString = "k1=v1,k2=v2"; var span = new SpanBuilder(SpanName, spanBuilderOptions) @@ -396,7 +407,9 @@ public void StartSpanFromCurrentActivity() [Fact] public void StartSpanFromCurrentRecordedActivity() { - var activity = new Activity(SpanName).Start(); + var activity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; var span = new SpanBuilder(SpanName, spanBuilderOptions) @@ -586,7 +599,9 @@ public void StartSpan_WithLink() [Fact] public void StartSpan_WithLinkFromActivity() { - var activityLink = new Activity("foo").Start(); + var activityLink = new Activity("foo") + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activityLink.Stop(); var span = new SpanBuilder(SpanName, spanBuilderOptions) @@ -599,6 +614,8 @@ public void StartSpan_WithLinkFromActivity() Assert.Single(links); + Assert.NotEqual(default, activityLink.TraceId); + Assert.NotEqual(default, activityLink.SpanId); Assert.Equal(activityLink.TraceId, links[0].Context.TraceId); Assert.Equal(activityLink.SpanId, links[0].Context.SpanId); Assert.Equal(activityLink.ActivityTraceFlags, links[0].Context.TraceOptions); @@ -869,9 +886,9 @@ public void SpanBuilder_BadArguments() Assert.Throws(() => spanBuilder.SetCreateChild(false)); // Activity.Current wrong format - Activity.DefaultIdFormat = ActivityIdFormat.Hierarchical; - Activity.ForceDefaultIdFormat = true; - var a = new Activity("foo").Start(); // TODO SetIdFormat + var a = new Activity("foo") + .SetIdFormat(ActivityIdFormat.Hierarchical) + .Start(); Assert.Throws(() => spanBuilder.SetCreateChild(false)); a.Stop(); diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index fc3a1a93254..e3fabb9caaf 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -52,10 +52,15 @@ public SpanTest() [Fact] public void ToSpanData_NoRecordEvents() { - var activityLink = new Activity(SpanName).Start(); + var activityLink = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activityLink.Stop(); - var activity = new Activity(SpanName).Start(); + var activity = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); + Assert.False(activity.Recorded); var span = @@ -128,7 +133,10 @@ public void GetSpanContextFromActivityRecordedWithParent() [Fact] public void NoEventsRecordedAfterEnd() { - var activityLink = new Activity(SpanName).Start(); + var activityLink = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); + activityLink.Stop(); var activity = new Activity(SpanName).Start(); @@ -171,7 +179,9 @@ public void NoEventsRecordedAfterEnd() [Fact] public async Task ToSpanData_ActiveSpan() { - var activityLink = new Activity(SpanName); + var activityLink = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activityLink.Stop(); var activity = new Activity(SpanName) @@ -241,7 +251,9 @@ public async Task ToSpanData_ActiveSpan() [Fact] public async Task GoSpanData_EndedSpan() { - var activityLink = new Activity(SpanName).Start(); + var activityLink = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activityLink.Stop(); var activity = new Activity(SpanName) @@ -531,7 +543,9 @@ public async Task DroppingEvents() [Fact] public void DroppingLinks() { - var activityLink = new Activity(SpanName).Start(); + var activityLink = new Activity(SpanName) + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); activityLink.Stop(); var activity = new Activity(SpanName).Start(); From 64d9fbf5e080049621fbabd055101042de7e5050 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 26 Jul 2019 11:53:42 -0700 Subject: [PATCH 29/41] Improvements in http in and out auto-collectors (#162) --- OpenTelemetry.sln | 17 ++- .../AspNetCoreCollectorEventSource.cs | 12 +- .../Implementation/HttpInListener.cs | 106 +++++++++++------- .../RequestsCollector.cs | 2 +- .../DependenciesCollector.cs | 2 +- .../DependenciesCollectorEventSource.cs | 18 ++- .../HttpHandlerDiagnosticListener.cs | 75 ++++++++++--- .../DiagnosticSourceListener.cs | 11 +- .../DiagnosticSourceSubscriber.cs | 2 +- .../ListenerHandler.cs | 4 +- src/OpenTelemetry/Trace/SpanBuilder.cs | 2 +- src/OpenTelemetry/Trace/Tracer.cs | 7 ++ .../BasicTests.cs | 6 +- .../BasicTests.cs | 106 +++++++++++------- .../HttpClientTests.cs | 4 +- 15 files changed, 247 insertions(+), 127 deletions(-) diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index ab2ac06e63f..4c9dd7e6c10 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28407.52 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.705 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry", "src\OpenTelemetry\OpenTelemetry.csproj", "{AE3E3DF5-4083-4C6E-A840-8271B0ACDE7E}" EndProject @@ -80,9 +80,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer.Demo.ConsoleA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggingTracer.Demo.AspNetCore", "samples\LoggingTracer\LoggingTracer.Demo.AspNetCore\LoggingTracer.Demo.AspNetCore.csproj", "{1EB74FCE-55C5-476A-8BB0-C46B77FE1070}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Jaeger", "src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj", "{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Jaeger", "src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj", "{8D47E3CF-9AE3-42FE-9084-FEB72D9AD769}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Jaeger.Tests", "test\OpenTelemetry.Exporter.Jaeger.Tests\OpenTelemetry.Exporter.Jaeger.Tests.csproj", "{21E69213-72D5-453F-BD00-75EF36AC4965}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Jaeger.Tests", "test\OpenTelemetry.Exporter.Jaeger.Tests\OpenTelemetry.Exporter.Jaeger.Tests.csproj", "{21E69213-72D5-453F-BD00-75EF36AC4965}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "lib\Thrift\Thrift.csproj", "{ED179037-DDB3-4780-A24F-F56278623EBB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{9D2D6933-C28C-4541-9A25-FDAE0DA5A5D4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -182,6 +186,10 @@ Global {21E69213-72D5-453F-BD00-75EF36AC4965}.Debug|Any CPU.Build.0 = Debug|Any CPU {21E69213-72D5-453F-BD00-75EF36AC4965}.Release|Any CPU.ActiveCfg = Release|Any CPU {21E69213-72D5-453F-BD00-75EF36AC4965}.Release|Any CPU.Build.0 = Release|Any CPU + {ED179037-DDB3-4780-A24F-F56278623EBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED179037-DDB3-4780-A24F-F56278623EBB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED179037-DDB3-4780-A24F-F56278623EBB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED179037-DDB3-4780-A24F-F56278623EBB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -193,6 +201,7 @@ Global {1EEF77DF-7552-4265-B64C-FA13BC40C256} = {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} {607B3861-4D69-43EF-84CE-19F18CD5339A} = {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} {1EB74FCE-55C5-476A-8BB0-C46B77FE1070} = {D9C14CDA-5182-4DEA-8606-98FF1A388BD3} + {ED179037-DDB3-4780-A24F-F56278623EBB} = {9D2D6933-C28C-4541-9A25-FDAE0DA5A5D4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521} diff --git a/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs b/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs index 4f4fa6d07a9..b87cd91a9f9 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/AspNetCoreCollectorEventSource.cs @@ -38,10 +38,10 @@ public void ExceptionInCustomSampler(Exception ex) } } - [Event(1, Message = "Context is NULL in end callback. Span will not be recorded.", Level = EventLevel.Warning)] - public void NullContext() + [Event(1, Message = "Http Context is NULL in '{0}' callback. Span will not be recorded.", Level = EventLevel.Warning)] + public void NullHttpContext(string eventName) { - this.WriteEvent(1); + this.WriteEvent(1, eventName); } [Event(2, Message = "Error getting custom sampler, the default sampler will be used. Exception : {0}", Level = EventLevel.Warning)] @@ -50,6 +50,12 @@ public void ExceptionInCustomSampler(string ex) this.WriteEvent(2, ex); } + [Event(3, Message = "Current Span is null or blank in '{0}' callback. Span will not be recorded.", Level = EventLevel.Warning)] + public void NullOrBlankSpan(string callbackName) + { + this.WriteEvent(3, callbackName); + } + /// /// Returns a culture-independent string representation of the given object, /// appropriate for diagnostics tracing. diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs index 0e7c3f0c0b5..96108837729 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs @@ -33,10 +33,12 @@ internal class HttpInListener : ListenerHandler private readonly PropertyFetcher beforeActionActionDescriptorFetcher = new PropertyFetcher("actionDescriptor"); private readonly PropertyFetcher beforeActionAttributeRouteInfoFetcher = new PropertyFetcher("AttributeRouteInfo"); private readonly PropertyFetcher beforeActionTemplateFetcher = new PropertyFetcher("Template"); + private readonly bool hostingSupportsW3C = false; public HttpInListener(ITracer tracer, Func samplerFactory) : base("Microsoft.AspNetCore", tracer, samplerFactory) { + this.hostingSupportsW3C = typeof(HttpRequest).Assembly.GetName().Version.Major >= 3; } public override void OnStartActivity(Activity activity, object payload) @@ -51,48 +53,65 @@ public override void OnStartActivity(Activity activity, object payload) var request = context.Request; - var ctx = this.Tracer.TextFormat.Extract( - request, - (r, name) => r.Headers[name]); + SpanContext ctx = null; + if (!this.hostingSupportsW3C) + { + ctx = this.Tracer.TextFormat.Extract( + request, + (r, name) => r.Headers[name]); + } // see the spec https://github.com/open-telemetry/OpenTelemetry-specs/blob/master/trace/HTTP.md - var path = (request.PathBase.HasValue || request.Path.HasValue) ? (request.PathBase + request.Path).ToString() : "/"; - ISpan span = this.Tracer.SpanBuilder(path) + var spanBuilder = this.Tracer.SpanBuilder(path) .SetSpanKind(SpanKind.Server) - .SetParent(ctx) - .SetSampler(this.SamplerFactory(request)) - .StartSpan(); + .SetSampler(this.SamplerFactory(request)); - this.Tracer.WithSpan(span); - - // Note, route is missing at this stage. It will be available later + if (this.hostingSupportsW3C) + { + spanBuilder.SetCreateChild(false); + } + else + { + spanBuilder.SetParent(ctx); + } - span.PutHttpHostAttribute(request.Host.Host, request.Host.Port ?? 80); - span.PutHttpMethodAttribute(request.Method); - span.PutHttpPathAttribute(path); + var span = spanBuilder.StartSpan(); + this.Tracer.WithSpan(span); - var userAgent = request.Headers["User-Agent"].FirstOrDefault(); - span.PutHttpUserAgentAttribute(userAgent); - span.PutHttpRawUrlAttribute(GetUri(request)); + if (span.IsRecordingEvents) + { + // Note, route is missing at this stage. It will be available later + span.PutHttpHostAttribute(request.Host.Host, request.Host.Port ?? 80); + span.PutHttpMethodAttribute(request.Method); + span.PutHttpPathAttribute(path); + + var userAgent = request.Headers["User-Agent"].FirstOrDefault(); + span.PutHttpUserAgentAttribute(userAgent); + span.PutHttpRawUrlAttribute(GetUri(request)); + } } public override void OnStopActivity(Activity activity, object payload) { - var context = this.stopContextFetcher.Fetch(payload) as HttpContext; + var span = this.Tracer.CurrentSpan; - if (context == null) + if (span == null || span == BlankSpan.Instance) { - AspNetCoreCollectorEventSource.Log.NullContext(); + AspNetCoreCollectorEventSource.Log.NullOrBlankSpan("HttpInListener.OnStopActivity"); return; } - var span = this.Tracer.CurrentSpan; + if (!span.IsRecordingEvents) + { + span.End(); + return; + } - if (span == null) + if (!(this.stopContextFetcher.Fetch(payload) is HttpContext context)) { - // TODO: report lost span + AspNetCoreCollectorEventSource.Log.NullHttpContext("HttpInListener.OnStopActivity"); return; } @@ -110,30 +129,33 @@ public override void OnCustom(string name, Activity activity, object payload) if (span == null) { - // TODO: report lost span + AspNetCoreCollectorEventSource.Log.NullOrBlankSpan(name); return; } - // See https://github.com/aspnet/Mvc/blob/2414db256f32a047770326d14d8b0e2afd49ba49/src/Microsoft.AspNetCore.Mvc.Core/MvcCoreDiagnosticSourceExtensions.cs#L36-L44 - // Reflection accessing: ActionDescriptor.AttributeRouteInfo.Template - // The reason to use reflection is to avoid a reference on MVC package. - // This package can be used with non-MVC apps and this logic simply wouldn't run. - // Taking reference on MVC will increase size of deployment for non-MVC apps. - var actionDescriptor = this.beforeActionActionDescriptorFetcher.Fetch(payload); - var attributeRouteInfo = this.beforeActionAttributeRouteInfoFetcher.Fetch(actionDescriptor); - var template = this.beforeActionTemplateFetcher.Fetch(attributeRouteInfo) as string; - - if (!string.IsNullOrEmpty(template)) + if (span.IsRecordingEvents) { - // override the span name that was previously set to the path part of URL. - span.UpdateName(template); - - span.PutHttpRouteAttribute(template); + // See https://github.com/aspnet/Mvc/blob/2414db256f32a047770326d14d8b0e2afd49ba49/src/Microsoft.AspNetCore.Mvc.Core/MvcCoreDiagnosticSourceExtensions.cs#L36-L44 + // Reflection accessing: ActionDescriptor.AttributeRouteInfo.Template + // The reason to use reflection is to avoid a reference on MVC package. + // This package can be used with non-MVC apps and this logic simply wouldn't run. + // Taking reference on MVC will increase size of deployment for non-MVC apps. + var actionDescriptor = this.beforeActionActionDescriptorFetcher.Fetch(payload); + var attributeRouteInfo = this.beforeActionAttributeRouteInfoFetcher.Fetch(actionDescriptor); + var template = this.beforeActionTemplateFetcher.Fetch(attributeRouteInfo) as string; + + if (!string.IsNullOrEmpty(template)) + { + // override the span name that was previously set to the path part of URL. + span.UpdateName(template); + + span.PutHttpRouteAttribute(template); + } + + // TODO: Should we get values from RouteData? + // private readonly PropertyFetcher beforActionRouteDataFetcher = new PropertyFetcher("routeData"); + // var routeData = this.beforActionRouteDataFetcher.Fetch(payload) as RouteData; } - - // TODO: Should we get values from RouteData? - // private readonly PropertyFetcher beforActionRouteDataFetcher = new PropertyFetcher("routeData"); - // var routeData = this.beforActionRouteDataFetcher.Fetch(payload) as RouteData; } } diff --git a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs index c80122c4f17..cd4b35bbfd3 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/RequestsCollector.cs @@ -57,7 +57,7 @@ public RequestsCollector(RequestsCollectorOptions options, ITracer tracer, ISamp AspNetCoreCollectorEventSource.Log.ExceptionInCustomSampler(e); } - return s == null ? sampler : s; + return s ?? sampler; }); this.diagnosticSourceSubscriber.Subscribe(); } diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs index e241b1b83fc..2ed0259ab94 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs @@ -55,7 +55,7 @@ public DependenciesCollector(DependenciesCollectorOptions options, ITracer trace DependenciesCollectorEventSource.Log.ExceptionInCustomSampler(e); } - return s == null ? sampler : s; + return s ?? sampler; }); this.diagnosticSourceSubscriber.Subscribe(); } diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs index 8d5fc997183..b088d812c62 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs @@ -38,10 +38,10 @@ public void ExceptionInCustomSampler(Exception ex) } } - [Event(1, Message = "Context is NULL in end callback. Span will not be recorded.", Level = EventLevel.Warning)] - public void NullContext() + [Event(1, Message = "Span is NULL or blank in the '{0}' callback. Span will not be recorded.", Level = EventLevel.Warning)] + public void NullOrBlankSpan(string eventName) { - this.WriteEvent(1); + this.WriteEvent(1, eventName); } [Event(2, Message = "Error getting custom sampler, the default sampler will be used. Exception : {0}", Level = EventLevel.Warning)] @@ -50,6 +50,18 @@ public void ExceptionInCustomSampler(string ex) this.WriteEvent(2, ex); } + [Event(3, Message = "Current Activity is NULL the '{0}' callback. Span will not be recorded.", Level = EventLevel.Warning)] + public void NullActivity(string eventName) + { + this.WriteEvent(3, eventName); + } + + [Event(4, Message = "Unknown error processing event '{0}' from handler '{1}', Exception: {2}", Level = EventLevel.Error)] + public void UnknownErrorProcessingEvent(string handlerName, string eventName, Exception ex) + { + this.WriteEvent(4, handlerName, eventName, ToInvariantString(ex)); + } + /// /// Returns a culture-independent string representation of the given object, /// appropriate for diagnostics tracing. diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs index aef890c8bcd..1860cee00cc 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs @@ -21,6 +21,8 @@ namespace OpenTelemetry.Collector.Dependencies.Implementation using System.Linq; using System.Net; using System.Net.Http; + using System.Reflection; + using System.Runtime.Versioning; using System.Threading.Tasks; using OpenTelemetry.Collector.Dependencies.Common; using OpenTelemetry.Trace; @@ -31,10 +33,23 @@ internal class HttpHandlerDiagnosticListener : ListenerHandler private readonly PropertyFetcher stopResponseFetcher = new PropertyFetcher("Response"); private readonly PropertyFetcher stopExceptionFetcher = new PropertyFetcher("Exception"); private readonly PropertyFetcher stopRequestStatusFetcher = new PropertyFetcher("RequestTaskStatus"); + private readonly bool httpClientSupportsW3C = false; public HttpHandlerDiagnosticListener(ITracer tracer, Func samplerFactory) : base("HttpHandlerDiagnosticListener", tracer, samplerFactory) { + var framework = Assembly + .GetEntryAssembly()? + .GetCustomAttribute()? + .FrameworkName; + + // Depending on the .NET version/flavor this will look like + // '.NETCoreApp,Version=v3.0', '.NETCoreApp,Version = v2.2' or '.NETFramework,Version = v4.7.1' + + if (framework != null && framework.Contains("Version=v3")) + { + this.httpClientSupportsW3C = true; + } } public override void OnStartActivity(Activity activity, object payload) @@ -45,29 +60,49 @@ public override void OnStartActivity(Activity activity, object payload) return; } + if (request.Headers.Contains("traceparent")) + { + // this request is already instrumented, we should back off + return; + } + var span = this.Tracer.SpanBuilder(request.RequestUri.AbsolutePath) .SetSpanKind(SpanKind.Client) .SetSampler(this.SamplerFactory(request)) + .SetCreateChild(false) .StartSpan(); + this.Tracer.WithSpan(span); - span.PutHttpMethodAttribute(request.Method.ToString()); - span.PutHttpHostAttribute(request.RequestUri.Host, request.RequestUri.Port); - span.PutHttpPathAttribute(request.RequestUri.AbsolutePath); - request.Headers.TryGetValues("User-Agent", out var userAgents); - span.PutHttpUserAgentAttribute(userAgents?.FirstOrDefault()); - span.PutHttpRawUrlAttribute(request.RequestUri.OriginalString); + if (span.IsRecordingEvents) + { + span.PutHttpMethodAttribute(request.Method.ToString()); + span.PutHttpHostAttribute(request.RequestUri.Host, request.RequestUri.Port); + span.PutHttpPathAttribute(request.RequestUri.AbsolutePath); + request.Headers.TryGetValues("User-Agent", out var userAgents); + span.PutHttpUserAgentAttribute(userAgents?.FirstOrDefault()); + span.PutHttpRawUrlAttribute(request.RequestUri.OriginalString); + } - this.Tracer.TextFormat.Inject(span.Context, request, (r, k, v) => r.Headers.Add(k, v)); + if (!this.httpClientSupportsW3C) + { + this.Tracer.TextFormat.Inject(span.Context, request, (r, k, v) => r.Headers.Add(k, v)); + } } public override void OnStopActivity(Activity activity, object payload) { var span = this.Tracer.CurrentSpan; - if (span == null) + if (span == null || span == BlankSpan.Instance) + { + DependenciesCollectorEventSource.Log.NullOrBlankSpan("HttpHandlerDiagnosticListener.OnStopActivity"); + return; + } + + if (!span.IsRecordingEvents) { - DependenciesCollectorEventSource.Log.NullContext(); + span.End(); return; } @@ -89,8 +124,6 @@ public override void OnStopActivity(Activity activity, object payload) if (!(this.stopResponseFetcher.Fetch(payload) is HttpResponseMessage response)) { // response could be null for DNS issues, timeouts, etc... - // TODO: how do we make sure we will not close a scope that wasn't opened? - span.End(); return; } @@ -102,25 +135,31 @@ public override void OnStopActivity(Activity activity, object payload) public override void OnException(Activity activity, object payload) { - if (!(this.stopExceptionFetcher.Fetch(payload) is Exception exc)) + var span = this.Tracer.CurrentSpan; + + if (span == null || span == BlankSpan.Instance) { - // Debug.WriteLine("response is null"); + DependenciesCollectorEventSource.Log.NullOrBlankSpan("HttpHandlerDiagnosticListener.OnException"); return; } - var span = this.Tracer.CurrentSpan; + if (!span.IsRecordingEvents) + { + span.End(); + return; + } - if (span == null) + if (!(this.stopExceptionFetcher.Fetch(payload) is Exception exc)) { - // TODO: Notify that span got lost + // Debug.WriteLine("response is null"); return; } if (exc is HttpRequestException) { // TODO: on netstandard this will be System.Net.Http.WinHttpException: The server name or address could not be resolved - if (exc.InnerException is WebException && - ((WebException)exc.InnerException).Status == WebExceptionStatus.NameResolutionFailure) + if (exc.InnerException is WebException exception && + exception.Status == WebExceptionStatus.NameResolutionFailure) { span.Status = Status.InvalidArgument; } diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs index 0c651192bc6..d62929c5923 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceListener.cs @@ -22,12 +22,10 @@ namespace OpenTelemetry.Collector.Dependencies.Common internal class DiagnosticSourceListener : IObserver>, IDisposable { - private readonly string sourceName; private readonly ListenerHandler handler; - public DiagnosticSourceListener(string sourceName, ListenerHandler handler) + public DiagnosticSourceListener(ListenerHandler handler) { - this.sourceName = sourceName; this.handler = handler; } @@ -45,7 +43,7 @@ public void OnNext(KeyValuePair value) { if (Activity.Current == null) { - Debug.WriteLine("Activity is null " + value.Key); + DependenciesCollectorEventSource.Log.NullActivity(value.Key); return; } @@ -68,10 +66,9 @@ public void OnNext(KeyValuePair value) this.handler.OnCustom(value.Key, Activity.Current, value.Value); } } - catch (Exception) + catch (Exception ex) { - // Debug.WriteLine(e); - // TODO: make sure to output the handler name as part of error message + DependenciesCollectorEventSource.Log.UnknownErrorProcessingEvent(this.handler?.SourceName, value.Key, ex); } } diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs index 0f410f73cd3..6892b6b50ad 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs @@ -57,7 +57,7 @@ public void OnNext(DiagnosticListener value) { this.subscriptions.GetOrAdd(value.Name, name => { - var dl = new DiagnosticSourceListener(value.Name, this.handlers[value.Name](this.tracer, this.sampler)); + var dl = new DiagnosticSourceListener(this.handlers[value.Name](this.tracer, this.sampler)); dl.Subscription = value.Subscribe(dl); return dl; }); diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/ListenerHandler.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/ListenerHandler.cs index d05ec8a681a..daf04308533 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/ListenerHandler.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/ListenerHandler.cs @@ -42,9 +42,9 @@ public virtual void OnStopActivity(Activity activity, object payload) { var span = this.Tracer.CurrentSpan; - if (span == null) + if (span == null || span == BlankSpan.Instance) { - // TODO: Notify that span got lost + DependenciesCollectorEventSource.Log.NullOrBlankSpan("ListenerHandler.OnStopActivity"); return; } diff --git a/src/OpenTelemetry/Trace/SpanBuilder.cs b/src/OpenTelemetry/Trace/SpanBuilder.cs index c8ebd6ea49a..078e4f1877e 100644 --- a/src/OpenTelemetry/Trace/SpanBuilder.cs +++ b/src/OpenTelemetry/Trace/SpanBuilder.cs @@ -242,7 +242,7 @@ public ISpan StartSpan() var span = Span.StartSpan( activityForSpan, - childTracestate, // it is updated in CreateActivityForSpan, + childTracestate, this.kind, activeTraceParams, this.options.StartEndHandler, diff --git a/src/OpenTelemetry/Trace/Tracer.cs b/src/OpenTelemetry/Trace/Tracer.cs index 9507410aff0..2541b19abf6 100644 --- a/src/OpenTelemetry/Trace/Tracer.cs +++ b/src/OpenTelemetry/Trace/Tracer.cs @@ -17,6 +17,7 @@ namespace OpenTelemetry.Trace { using System; + using System.Diagnostics; using System.Threading; using OpenTelemetry.Context; using OpenTelemetry.Context.Propagation; @@ -34,6 +35,12 @@ public sealed class Tracer : ITracer private readonly SpanBuilderOptions spanBuilderOptions; private readonly SpanExporter spanExporter; + static Tracer() + { + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + Activity.ForceDefaultIdFormat = true; + } + /// /// Creates an instance of . /// diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs index 5ea0517c6fd..240cb192c09 100644 --- a/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/BasicTests.cs @@ -23,7 +23,6 @@ namespace OpenTelemetry.Collector.AspNetCore.Tests using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Internal; using Moq; using Microsoft.AspNetCore.TestHost; using System; @@ -41,11 +40,10 @@ public class BasicTests public BasicTests(WebApplicationFactory factory) { this.factory = factory; - } [Fact] - public async Task SuccesfulTemplateControllerCallGeneratesASpan() + public async Task SuccessfulTemplateControllerCallGeneratesASpan() { var startEndHandler = new Mock(); var tracer = new Tracer(startEndHandler.Object, new TraceConfig()); @@ -89,7 +87,7 @@ void ConfigureTestServices(IServiceCollection services) => } [Fact] - public async Task SuccesfulTemplateControllerCallUsesParentContext() + public async Task SuccessfulTemplateControllerCallUsesParentContext() { var startEndHandler = new Mock(); diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs index ebb496df0e7..245dde74845 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/BasicTests.cs @@ -14,13 +14,13 @@ // limitations under the License. // +using System.Linq; + namespace OpenTelemetry.Collector.Dependencies.Tests { using Moq; using OpenTelemetry.Trace; using OpenTelemetry.Trace.Config; - using OpenTelemetry.Trace.Internal; - using OpenTelemetry.Context.Propagation; using OpenTelemetry.Trace.Sampler; using System; using System.Diagnostics; @@ -28,14 +28,13 @@ namespace OpenTelemetry.Collector.Dependencies.Tests using System.Threading.Tasks; using Xunit; - public partial class HttpClientTests + public partial class HttpClientTests : IDisposable { - [Fact] - public async Task HttpDepenenciesCollectorInjectsHeadersAsync() + private readonly IDisposable serverLifeTime; + private readonly string url; + public HttpClientTests() { - var startEndHandler = new Mock(); - - var serverLifeTime = TestServer.RunServer( + this.serverLifeTime = TestServer.RunServer( (ctx) => { ctx.Response.StatusCode = 200; @@ -44,45 +43,76 @@ public async Task HttpDepenenciesCollectorInjectsHeadersAsync() out var host, out var port); - var url = $"http://{host}:{port}/"; + this.url = $"http://{host}:{port}/"; + } - ActivityTraceId expectedTraceId = default; - ActivitySpanId expectedSpanId = default; + [Fact] + public async Task HttpDependenciesCollectorInjectsHeadersAsync() + { + var startEndHandler = new Mock(); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, null); - using (serverLifeTime) + var request = new HttpRequestMessage { - var tf = new Mock(); - tf - .Setup(m => m.Inject(It.IsAny(), It.IsAny(), It.IsAny>())) - .Callback((SpanContext sc, HttpRequestMessage obj, Action setter) => - { - expectedTraceId = sc.TraceId; - expectedSpanId = sc.SpanId; - }); - - var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, tf.Object); - - using (var dc = new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) - { + RequestUri = new Uri(url), + Method = new HttpMethod("GET"), + }; - using (var c = new HttpClient()) - { - var request = new HttpRequestMessage - { - RequestUri = new Uri(url), - Method = new HttpMethod("GET"), - }; - - await c.SendAsync(request); - } - } + var parent = new Activity("parent") + .SetIdFormat(ActivityIdFormat.W3C) + .Start(); + parent.TraceStateString = "k1=v1,k2=v2"; + + using (new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) + using (var c = new HttpClient()) + { + await c.SendAsync(request); } Assert.Equal(2, startEndHandler.Invocations.Count); // begin and end was called var spanData = ((Span)startEndHandler.Invocations[1].Arguments[0]).ToSpanData(); - Assert.Equal(expectedTraceId, spanData.Context.TraceId); - Assert.Equal(expectedSpanId, spanData.Context.SpanId); + Assert.Equal(parent.TraceId, spanData.Context.TraceId); + Assert.Equal(parent.SpanId, spanData.ParentSpanId); + Assert.NotEqual(parent.SpanId, spanData.Context.SpanId); + Assert.NotEqual(default, spanData.Context.SpanId); + + Assert.True(request.Headers.TryGetValues("traceparent", out var traceparents)); + Assert.True(request.Headers.TryGetValues("tracestate", out var tracestates)); + Assert.Single(traceparents); + Assert.Single(tracestates); + + Assert.Equal($"00-{spanData.Context.TraceId}-{spanData.Context.SpanId}-01", traceparents.Single()); + Assert.Equal("k1=v1,k2=v2", tracestates.Single()); + } + + [Fact] + public async Task HttpDependenciesCollectorBacksOffIfAlreadyInstrumented() + { + var startEndHandler = new Mock(); + var tracer = new Tracer(startEndHandler.Object, new TraceConfig(), null, null, null); + + var request = new HttpRequestMessage + { + RequestUri = new Uri(url), + Method = new HttpMethod("GET"), + }; + + request.Headers.Add("traceparent", "00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"); + + using (new DependenciesCollector(new DependenciesCollectorOptions(), tracer, Samplers.AlwaysSample)) + using (var c = new HttpClient()) + { + await c.SendAsync(request); + } + + Assert.Equal(0, startEndHandler.Invocations.Count); + } + + public void Dispose() + { + serverLifeTime?.Dispose(); + Activity.Current = null; } } } diff --git a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs index 5d2ea48299f..d22c28380d2 100644 --- a/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs +++ b/test/OpenTelemetry.Collector.Dependencies.Tests/HttpClientTests.cs @@ -87,7 +87,7 @@ public static IEnumerable TestData [Theory] [MemberData(nameof(TestData))] - public async Task HttpOutCallsAreCollectedSuccesfullyAsync(HttpOutTestCase tc) + public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpOutTestCase tc) { var serverLifeTime = TestServer.RunServer( (ctx) => @@ -194,7 +194,7 @@ public async Task DebugIndividualTestAsync() ] "))); - var t = (Task)this.GetType().InvokeMember(nameof(HttpOutCallsAreCollectedSuccesfullyAsync), BindingFlags.InvokeMethod, null, this, getArgumentsFromTestCaseObject(input).First()); + var t = (Task)this.GetType().InvokeMember(nameof(HttpOutCallsAreCollectedSuccessfullyAsync), BindingFlags.InvokeMethod, null, this, getArgumentsFromTestCaseObject(input).First()); await t; } From e00bccb15fc2a2b8dee1dde620487b5a879d9bca Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 29 Jul 2019 22:03:55 -0700 Subject: [PATCH 30/41] Make samples projects not packable (#165) --- samples/Exporters/Exporters.csproj | 1 + .../LoggingTracer.Demo.AspNetCore.csproj | 1 + .../LoggingTracer.Demo.ConsoleApp.csproj | 1 + samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj | 1 + 4 files changed, 4 insertions(+) diff --git a/samples/Exporters/Exporters.csproj b/samples/Exporters/Exporters.csproj index 7013bb5e792..f9f2f9be2d7 100644 --- a/samples/Exporters/Exporters.csproj +++ b/samples/Exporters/Exporters.csproj @@ -4,6 +4,7 @@ Exe netcoreapp2.1 + false diff --git a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj index 0196370d0e9..7cb1fa5a73d 100644 --- a/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj +++ b/samples/LoggingTracer/LoggingTracer.Demo.AspNetCore/LoggingTracer.Demo.AspNetCore.csproj @@ -3,6 +3,7 @@ netcoreapp2.2 InProcess + false diff --git a/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj index 0071f95514d..26fc681b216 100644 --- a/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj +++ b/samples/LoggingTracer/LoggingTracer.Demo.ConsoleApp/LoggingTracer.Demo.ConsoleApp.csproj @@ -3,6 +3,7 @@ Exe netcoreapp2.2 + false diff --git a/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj b/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj index 587c124f279..c9538670b88 100644 --- a/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj +++ b/samples/LoggingTracer/LoggingTracer/LoggingTracer.csproj @@ -2,6 +2,7 @@ netstandard2.0 + false From b94fc10dd363cd0fa674a82bbfbf0fcb4ca5817c Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 30 Jul 2019 10:55:51 -0700 Subject: [PATCH 31/41] Do not export zipkin exporter calls to zipkin endpoint (#167) * Do not export calls to Zipkin * up --- .../Implementation/TraceExporterHandler.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index b43a65e56e2..b9254e4198b 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -40,12 +40,14 @@ internal class TraceExporterHandler : IHandler private readonly ZipkinTraceExporterOptions options; private readonly ZipkinEndpoint localEndpoint; private readonly HttpClient httpClient; + private readonly string serviceEndpoint; public TraceExporterHandler(ZipkinTraceExporterOptions options, HttpClient client) { this.options = options; this.localEndpoint = this.GetLocalZipkinEndpoint(); this.httpClient = client ?? new HttpClient(); + this.serviceEndpoint = options.Endpoint?.ToString(); } public async Task ExportAsync(IEnumerable spanDataList) @@ -54,8 +56,26 @@ public async Task ExportAsync(IEnumerable spanDataList) foreach (var data in spanDataList) { - var zipkinSpan = this.GenerateSpan(data, this.localEndpoint); - zipkinSpans.Add(zipkinSpan); + bool shouldExport = true; + foreach (var label in data.Attributes.AttributeMap) + { + if (label.Key == "http.url") + { + if (label.Value is string urlStr && urlStr == this.serviceEndpoint) + { + // do not track calls to Zipkin + shouldExport = false; + } + + break; + } + } + + if (shouldExport) + { + var zipkinSpan = this.GenerateSpan(data, this.localEndpoint); + zipkinSpans.Add(zipkinSpan); + } } try @@ -91,7 +111,7 @@ internal ZipkinSpan GenerateSpan(SpanData spanData, ZipkinEndpoint localEndpoint foreach (var label in spanData.Attributes.AttributeMap) { - spanBuilder.PutTag(label.Key, (string)label.Value); + spanBuilder.PutTag(label.Key, label.Value.ToString()); } var status = spanData.Status; From a4447ad6053fee7068084b2f3be60da624288842 Mon Sep 17 00:00:00 2001 From: John Du Hart Date: Tue, 30 Jul 2019 17:25:26 -0400 Subject: [PATCH 32/41] Don't POST to zipkin if there are no spans to send (#171) --- .../Implementation/TraceExporterHandler.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index b9254e4198b..4901f0259a4 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -78,6 +78,11 @@ public async Task ExportAsync(IEnumerable spanDataList) } } + if (zipkinSpans.Count == 0) + { + return; + } + try { await this.SendSpansAsync(zipkinSpans); From f6fc8d7a83c658981d1c23f3dbdf474dbfde518b Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 2 Aug 2019 10:49:38 -0700 Subject: [PATCH 33/41] ApplicationInsights exporter improvements (#172) --- .../Implementation/TraceExporterHandler.cs | 198 ++++++++---------- .../TraceExporterHandlerTests.cs | 89 +++++--- 2 files changed, 152 insertions(+), 135 deletions(-) diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs index 004b32cf335..86f96d2b344 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/TraceExporterHandler.cs @@ -30,23 +30,44 @@ namespace OpenTelemetry.Exporter.ApplicationInsights.Implementation internal class TraceExporterHandler : IHandler { private readonly TelemetryClient telemetryClient; + private readonly string serviceEndpoint; public TraceExporterHandler(TelemetryConfiguration telemetryConfiguration) { this.telemetryClient = new TelemetryClient(telemetryConfiguration); + this.serviceEndpoint = telemetryConfiguration.TelemetryChannel.EndpointAddress; } public Task ExportAsync(IEnumerable spanDataList) { foreach (var span in spanDataList) { + bool shouldExport = true; + string httpUrlAttr = null; + + foreach (var attr in span.Attributes.AttributeMap) + { + if (attr.Key == "http.url") + { + httpUrlAttr = attr.Value.ToString(); + if (httpUrlAttr == this.serviceEndpoint) + { + shouldExport = false; + break; + } + } + } + + if (!shouldExport) + { + continue; + } + this.ExtractGenericProperties( span, - out var resultKind, - out var timestamp, out var name, out var resultCode, - out var props, + out var statusDescription, out var traceId, out var spanId, out var parentId, @@ -54,30 +75,42 @@ public Task ExportAsync(IEnumerable spanDataList) out var success, out var duration); + // BUILDING resulting telemetry + OperationTelemetry result; + if (span.Kind == SpanKind.Client || span.Kind == SpanKind.Internal || span.Kind == SpanKind.Producer) + { + var resultD = new DependencyTelemetry(); + if (span.Kind == SpanKind.Internal) + { + resultD.Type = "InProc"; + } + + result = resultD; + } + else + { + result = new RequestTelemetry(); + } + string data = null; string target = null; string type = null; string userAgent = null; - string spanKindAttr = null; string errorAttr = null; string httpStatusCodeAttr = null; string httpMethodAttr = null; string httpPathAttr = null; string httpHostAttr = null; - string httpUrlAttr = null; + string httpUserAgentAttr = null; string httpRouteAttr = null; string httpPortAttr = null; foreach (var attr in span.Attributes.AttributeMap) { - var key = attr.Key; switch (attr.Key) { - case "span.kind": - spanKindAttr = attr.Value.ToString(); - break; case "error": errorAttr = attr.Value.ToString(); break; @@ -90,9 +123,6 @@ public Task ExportAsync(IEnumerable spanDataList) case "http.host": httpHostAttr = attr.Value.ToString(); break; - case "http.url": - httpUrlAttr = attr.Value.ToString(); - break; case "http.status_code": httpStatusCodeAttr = attr.Value.ToString(); break; @@ -108,21 +138,59 @@ public Task ExportAsync(IEnumerable spanDataList) default: var value = attr.Value.ToString(); - AddPropertyWithAdjustedName(props, attr.Key, value); + AddPropertyWithAdjustedName(result.Properties, attr.Key, value); break; } } + this.OverwriteFieldsForHttpSpans( + httpMethodAttr, + httpUrlAttr, + httpHostAttr, + httpPathAttr, + httpStatusCodeAttr, + httpUserAgentAttr, + httpRouteAttr, + httpPortAttr, + ref name, + ref resultCode, + ref data, + ref target, + ref type, + ref userAgent); + + if (result is DependencyTelemetry dependency) + { + dependency.Data = data; + dependency.Target = target; + dependency.Data = data; + dependency.ResultCode = resultCode; + + if (string.IsNullOrEmpty(dependency.Type)) + { + dependency.Type = type; + } + } + else if (result is RequestTelemetry request) + { + if (Uri.TryCreate(data, UriKind.RelativeOrAbsolute, out var url)) + { + request.Url = url; + } + + request.ResponseCode = resultCode; + } + var linkId = 0; foreach (var link in span.Links.Links) { - AddPropertyWithAdjustedName(props, "link" + linkId + "_traceId", link.Context.TraceId.ToHexString()); - AddPropertyWithAdjustedName(props, "link" + linkId + "_spanId", link.Context.SpanId.ToHexString()); + AddPropertyWithAdjustedName(result.Properties, "link" + linkId + "_traceId", link.Context.TraceId.ToHexString()); + AddPropertyWithAdjustedName(result.Properties, "link" + linkId + "_spanId", link.Context.SpanId.ToHexString()); foreach (var attr in link.Attributes) { - AddPropertyWithAdjustedName(props, "link" + linkId + "_" + attr.Key, attr.Value.ToString()); + AddPropertyWithAdjustedName(result.Properties, "link" + linkId + "_" + attr.Key, attr.Value.ToString()); } ++linkId; @@ -150,65 +218,25 @@ public Task ExportAsync(IEnumerable spanDataList) this.telemetryClient.Track(log); } - this.OverwriteSpanKindFromAttribute(spanKindAttr, ref resultKind); this.OverwriteErrorAttribute(errorAttr, ref success); - this.OverwriteFieldsForHttpSpans( - httpMethodAttr, - httpUrlAttr, - httpHostAttr, - httpPathAttr, - httpStatusCodeAttr, - httpUserAgentAttr, - httpRouteAttr, - httpPortAttr, - ref name, - ref resultCode, - ref data, - ref target, - ref type, - ref userAgent); - // BUILDING resulting telemetry - OperationTelemetry result; - if (resultKind == SpanKind.Client || resultKind == SpanKind.Producer) - { - var resultD = new DependencyTelemetry - { - ResultCode = resultCode, - Data = data, - Target = target, - Type = type, - }; - - result = resultD; - } - else + result.Success = success; + if (statusDescription != null) { - var resultR = new RequestTelemetry(); - resultR.ResponseCode = resultCode; - Uri.TryCreate(data, UriKind.RelativeOrAbsolute, out var url); - resultR.Url = url; - result = resultR; + AddPropertyWithAdjustedName(result.Properties, "statusDescription", statusDescription); } - result.Success = success; - - result.Timestamp = timestamp; + result.Timestamp = span.StartTimestamp; result.Name = name; result.Context.Operation.Id = traceId; result.Context.User.UserAgent = userAgent; - foreach (var prop in props) - { - AddPropertyWithAdjustedName(result.Properties, prop.Key, prop.Value); - } - if (parentId != null) { result.Context.Operation.ParentId = string.Concat("|", traceId, ".", parentId, "."); } - // TODO: I don't understant why this concatanation is required + // TODO: this concatenation is required for Application Insights backward compatibility reasons result.Id = string.Concat("|", traceId, ".", spanId, "."); foreach (var ts in tracestate.Entries) @@ -220,7 +248,6 @@ public Task ExportAsync(IEnumerable spanDataList) // TODO: deal with those: // span.ChildSpanCount - // span.Context.IsValid; // span.Context.TraceOptions; this.telemetryClient.Track(result); @@ -242,22 +269,11 @@ private static void AddPropertyWithAdjustedName(IDictionary prop props.Add(n, value); } - private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, out DateTimeOffset timestamp, out string name, out string resultCode, out IDictionary props, out string traceId, out string spanId, out string parentId, out Tracestate tracestate, out bool? success, out TimeSpan duration) + private void ExtractGenericProperties(SpanData span, out string name, out string resultCode, out string statusDescription, out string traceId, out string spanId, out string parentId, out Tracestate tracestate, out bool? success, out TimeSpan duration) { - resultKind = span.Kind; - - // TODO: Should this be a part of generic logic? - if (resultKind == SpanKind.Internal) - { - resultKind = SpanKind.Client; - } - - // 1 tick is 100 ns - timestamp = new DateTimeOffset(span.StartTimestamp); - name = span.Name; - props = new Dictionary(); + statusDescription = null; traceId = span.Context.TraceId.ToHexString(); spanId = span.Context.SpanId.ToHexString(); @@ -275,7 +291,7 @@ private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, ou success = span.Status.IsOk; if (!string.IsNullOrEmpty(span.Status.Description)) { - props["statusDescription"] = span.Status.Description; + statusDescription = span.Status.Description; } } @@ -283,34 +299,6 @@ private void ExtractGenericProperties(SpanData span, out SpanKind resultKind, ou duration = span.EndTimestamp - span.StartTimestamp; } - private void OverwriteSpanKindFromAttribute(string spanKindAttr, ref SpanKind resultKind) - { - // override span kind with attribute named span.kind - if (spanKindAttr != null) - { - var kind = spanKindAttr; - - switch (kind.ToLower(CultureInfo.InvariantCulture)) - { - case "server": - resultKind = SpanKind.Server; - break; - case "client": - resultKind = SpanKind.Client; - break; - case "producer": - resultKind = SpanKind.Producer; - break; - case "consumer": - resultKind = SpanKind.Consumer; - break; - default: - resultKind = SpanKind.Internal; - break; - } - } - } - private void OverwriteErrorAttribute(string errorAttr, ref bool? success) { if (errorAttr != null) @@ -347,7 +335,7 @@ private void OverwriteFieldsForHttpSpans( { var urlString = httpUrlAttr; Uri.TryCreate(urlString, UriKind.RelativeOrAbsolute, out url); - } + } string httpMethod = null; string httpPath = null; diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs index c845b6b8758..707a9354050 100644 --- a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/TraceExporterHandlerTests.cs @@ -36,6 +36,7 @@ public class OpenTelemetryTelemetryConverterTests private const string TestTraceId = "d79bdda7eb9c4a9fa9bda52fe7b48b95"; private const string TestSpanId = "d7ddeb4aa9a5e78b"; private const string TestParentSpanId = "9ba79c9fbd2fb495"; + private const string TestChannelEndpoint = "https://applicationinsights.com"; private readonly byte[] testTraceIdBytes = { 0xd7, 0x9b, 0xdd, 0xa7, 0xeb, 0x9c, 0x4a, 0x9f, 0xa9, 0xbd, 0xa5, 0x2f, 0xe7, 0xb4, 0x8b, 0x95 }; private readonly byte[] testSpanIdBytes = { 0xd7, 0xdd, 0xeb, 0x4a, 0xa9, 0xa5, 0xe7, 0x8b }; @@ -55,6 +56,7 @@ private ConcurrentQueue ConvertSpan(SpanData data) ITelemetryChannel channel = new StubTelemetryChannel { OnSend = t => sentItems.Enqueue(t), + EndpointAddress = TestChannelEndpoint, }; configuration.TelemetryChannel = channel; @@ -278,6 +280,62 @@ public void OpenTelemetryTelemetryConverterTests_TracksClientDependency() Assert.True(string.IsNullOrEmpty(dependency.Type)); } + [Fact] + public void OpenTelemetryTelemetryConverterTests_TracksInternalSpanAsDependency() + { + // ARRANGE + this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); + + kind = SpanKind.Internal; + + var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); + + // ACT + var sentItems = this.ConvertSpan(span); + + // ASSERT + Assert.Single(sentItems); + Assert.True(sentItems.Single() is DependencyTelemetry); + + var dependency = sentItems.OfType().Single(); + Assert.Equal("spanName", dependency.Name); + Assert.Equal("InProc", dependency.Type); + Assert.Equal(now.AddSeconds(-1), dependency.Timestamp); + Assert.Equal(1, dependency.Duration.TotalSeconds); + + Assert.Equal(TestTraceId, dependency.Context.Operation.Id); + Assert.Null(dependency.Context.Operation.ParentId); + Assert.Equal($"|{TestTraceId}.{TestSpanId}.", dependency.Id); + + Assert.True(string.IsNullOrEmpty(dependency.ResultCode)); + Assert.False(dependency.Success.HasValue); + + // Assert.Equal("lf_unspecified-oc:0.0.0", dependency.Context.GetInternalContext().SdkVersion); + } + + [Fact] + public void OpenTelemetryTelemetryConverterTests_DoesNotTrackCallToAppInsights() + { + // ARRANGE + this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); + + kind = SpanKind.Client; + attributes = Attributes.Create(new Dictionary + { + { "http.url", TestChannelEndpoint }, + { "http.method", "POST" }, + { "http.status_code", 200 }, + }, 0); + + var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); + + // ACT + var sentItems = this.ConvertSpan(span); + + // ASSERT + Assert.Empty(sentItems); + } + [Fact] public void OpenTelemetryTelemetryConverterTests_TracksProducerDependency() { @@ -517,20 +575,6 @@ public void OpenTelemetryTelemetryConverterTests_TracksDependencyErrorAttribute( Assert.False(dependency.Success.Value); } - [Fact] - public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnServerSpanKindAttribute() - { - this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", "server" } }, 0); - - var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); - - var sentItems = this.ConvertSpan(span); - - Assert.True(sentItems.Single() is RequestTelemetry); - } - [Fact] public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnClientSpanKindAttribute() { @@ -563,22 +607,7 @@ public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnProducerSpa public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnConsumerSpanKindAttribute() { this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", "consumer" } }, 0); - - var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); - - var sentItems = this.ConvertSpan(span); - - Assert.True(sentItems.Single() is RequestTelemetry); - } - - [Fact] - public void OpenTelemetryTelemetryConverterTests_TracksRequestBasedOnOtherSpanKindAttribute() - { - this.GetDefaults(out var context, out var parentSpanId, out var resource, out var name, out var startTimestamp, out var attributes, out var events, out var links, out var childSpanCount, out var status, out var kind, out var endTimestamp); - kind = SpanKind.Client; - attributes = Attributes.Create(new Dictionary() { { "span.kind", "other" } }, 0); + kind = SpanKind.Consumer; var span = SpanData.Create(context, parentSpanId, resource, name, startTimestamp, attributes, events, links, childSpanCount, status, kind, endTimestamp); From 5d303912f0586c81916cc74ad346be28f9ba2b1e Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 2 Aug 2019 11:23:21 -0700 Subject: [PATCH 34/41] Add Azure collector (#161) * Add Azure collector * Url as the name * Full * Comments * More feedback * More * Start with OK span * fb * FB * undo * Http --- .../AzureSdkDiagnosticListener.cs | 90 +++++++++++++++++++ .../DependenciesCollector.cs | 6 +- 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs diff --git a/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs b/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs new file mode 100644 index 00000000000..6dceb006ddb --- /dev/null +++ b/src/OpenTelemetry.Collector.Dependencies/AzureSdkDiagnosticListener.cs @@ -0,0 +1,90 @@ +// +// 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.Collector.Dependencies +{ + using System; + using System.Diagnostics; + using OpenTelemetry.Collector.Dependencies.Common; + using OpenTelemetry.Trace; + + internal class AzureSdkDiagnosticListener : ListenerHandler + { + private readonly ITracer tracer; + + private readonly ISampler sampler; + + public AzureSdkDiagnosticListener(string sourceName, ITracer tracer, ISampler sampler) + : base(sourceName, tracer, null) + { + this.tracer = tracer; + this.sampler = sampler; + } + + public void OnCompleted() + { + } + + public void OnError(Exception error) + { + } + + public override void OnStartActivity(Activity current, object valueValue) + { + bool isHttp = false; + var operationName = current.OperationName; + foreach (var keyValuePair in current.Tags) + { + if (keyValuePair.Key == "http.url") + { + isHttp = true; + operationName = keyValuePair.Value; + break; + } + } + + var spanBuilder = this.tracer.SpanBuilder(operationName) + .SetCreateChild(false) + .SetSampler(this.sampler); + + spanBuilder.SetSpanKind(isHttp ? SpanKind.Client : SpanKind.Internal); + + var span = spanBuilder.StartSpan(); + + span.Status = Status.Ok; + + this.tracer.WithSpan(span); + } + + public override void OnStopActivity(Activity current, object valueValue) + { + var span = this.tracer.CurrentSpan; + foreach (var keyValuePair in current.Tags) + { + span.SetAttribute(keyValuePair.Key, keyValuePair.Value); + } + + this.tracer.CurrentSpan.End(); + } + + public override void OnException(Activity current, object valueValue) + { + 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 2ed0259ab94..dd838c693f8 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollector.cs @@ -40,7 +40,11 @@ public DependenciesCollector(DependenciesCollectorOptions options, ITracer trace { this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber( new Dictionary, ListenerHandler>>() - { { "HttpHandlerDiagnosticListener", (t, s) => new HttpHandlerDiagnosticListener(t, s) } }, + { + { "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) }, + }, tracer, x => { From fbdd3a1f34789538c96981104b93c6dec9f5e778 Mon Sep 17 00:00:00 2001 From: pcwiese Date: Tue, 6 Aug 2019 20:49:07 -0700 Subject: [PATCH 35/41] Multiple calls to DiagnosticSourceSubscriber::Dispose throw nullref (#178) * Multiple calls to DiagnosticSourceSubscriber::Dispose would throw nullrefs. All Dispose methods should be idempotent. - Switched the dispose flag check(s) from using Volatile to using Interlocked.CompareExchange and Interlocked.Read - Add null checks to the arguments - Added a simple unit test class for this internal class * Wrap InternalVisibleTo in a #if SIGNED preprocessor block * Applying the same Dispose pattern to DiagnosticSourceSubscriber in the Collector.Dependencies assembly --- .../AssemblyInfo.cs | 7 +++ .../DiagnosticSourceSubscriber.cs | 17 +++++--- .../DiagnosticSourceSubscriber.cs | 17 +++++--- .../DiagnosticsSourceSubscriberTests.cs | 43 +++++++++++++++++++ 4 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 test/OpenTelemetry.Collector.AspNetCore.Tests/DiagnosticsSourceSubscriberTests.cs diff --git a/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs b/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs index 23da982fdad..84bb3d80c36 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/AssemblyInfo.cs @@ -13,3 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. // +using System.Runtime.CompilerServices; + +#if SIGNED +[assembly: InternalsVisibleTo("OpenTelemetry.Collector.AspNetCore.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] +#else +[assembly: InternalsVisibleTo("OpenTelemetry.Collector.AspNetCore.Tests")] +#endif diff --git a/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceSubscriber.cs b/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceSubscriber.cs index ba2009409f6..4c7bb95ab46 100644 --- a/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceSubscriber.cs +++ b/src/OpenTelemetry.Collector.AspNetCore/Implementation/OpenTelemetry.Collector.AspNetCore.Common/DiagnosticSourceSubscriber.cs @@ -30,15 +30,15 @@ internal class DiagnosticSourceSubscriber : IDisposable, IObserver sampler; private ConcurrentDictionary subscriptions; - private bool disposing; + private long disposed; private IDisposable subscription; public DiagnosticSourceSubscriber(Dictionary, ListenerHandler>> handlers, ITracer tracer, Func sampler) { - this.subscriptions = new ConcurrentDictionary(); - this.handlers = handlers; - this.tracer = tracer; - this.sampler = sampler; + this.subscriptions = new ConcurrentDictionary(); + this.handlers = handlers ?? throw new ArgumentNullException(nameof(handlers)); + this.tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); + this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler)); } public void Subscribe() @@ -51,7 +51,7 @@ public void Subscribe() public void OnNext(DiagnosticListener value) { - if (!Volatile.Read(ref this.disposing) && this.subscriptions != null) + if ((Interlocked.Read(ref this.disposed) == 0) && this.subscriptions != null) { if (this.handlers.ContainsKey(value.Name)) { @@ -75,7 +75,10 @@ public void OnError(Exception error) public void Dispose() { - Volatile.Write(ref this.disposing, true); + if (Interlocked.CompareExchange(ref this.disposed, 1, 0) == 1) + { + return; + } var subsCopy = this.subscriptions; this.subscriptions = null; diff --git a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs index 6892b6b50ad..620d3adb7ee 100644 --- a/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs +++ b/src/OpenTelemetry.Collector.Dependencies/Implementation/OpenTelemetry.Collector.Dependencies.Common/DiagnosticSourceSubscriber.cs @@ -30,15 +30,15 @@ internal class DiagnosticSourceSubscriber : IDisposable, IObserver sampler; private ConcurrentDictionary subscriptions; - private bool disposing; + private long disposed; private IDisposable subscription; public DiagnosticSourceSubscriber(Dictionary, ListenerHandler>> handlers, ITracer tracer, Func sampler) { - this.subscriptions = new ConcurrentDictionary(); - this.handlers = handlers; - this.tracer = tracer; - this.sampler = sampler; + this.subscriptions = new ConcurrentDictionary(); + this.handlers = handlers ?? throw new ArgumentNullException(nameof(handlers)); + this.tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); + this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler)); } public void Subscribe() @@ -51,7 +51,7 @@ public void Subscribe() public void OnNext(DiagnosticListener value) { - if (!Volatile.Read(ref this.disposing) && this.subscriptions != null) + if ((Interlocked.Read(ref this.disposed) == 0) && this.subscriptions != null) { if (this.handlers.ContainsKey(value.Name)) { @@ -75,7 +75,10 @@ public void OnError(Exception error) public void Dispose() { - Volatile.Write(ref this.disposing, true); + if (Interlocked.CompareExchange(ref this.disposed, 1, 0) == 1) + { + return; + } var subsCopy = this.subscriptions; this.subscriptions = null; diff --git a/test/OpenTelemetry.Collector.AspNetCore.Tests/DiagnosticsSourceSubscriberTests.cs b/test/OpenTelemetry.Collector.AspNetCore.Tests/DiagnosticsSourceSubscriberTests.cs new file mode 100644 index 00000000000..3ca9d801a3c --- /dev/null +++ b/test/OpenTelemetry.Collector.AspNetCore.Tests/DiagnosticsSourceSubscriberTests.cs @@ -0,0 +1,43 @@ +// +// 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.Collector.AspNetCore.Tests +{ + using Xunit; + using OpenTelemetry.Collector.AspNetCore.Common; + using System.Collections.Generic; + using System; + using Moq; + using OpenTelemetry.Trace; + + public class DiagnosticsSourceSubscriberTests + { + [Fact] + public void DisposeIsIdempotent() + { + var subject = new DiagnosticSourceSubscriber( + new Dictionary, ListenerHandler>> + { + { "unused", (tracer, samplerFunc) => new Mock().Object }, + }, + new Mock().Object, + request => new Mock().Object); + + subject.Dispose(); + subject.Dispose(); + } + } +} From ca3c881e2f1e67fb4dde34f66c6079f0344b6853 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 6 Aug 2019 21:02:28 -0700 Subject: [PATCH 36/41] clean up some OpenCensus mentions in exporters (#174) --- .../ApplicationInsightsExporter.cs | 4 ++-- .../Implementation/TraceExporterHandler.cs | 4 ++-- src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs | 4 ++-- .../ZipkinTraceExporterOptions.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs index 22fe5a96446..6107a0fbb33 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/ApplicationInsightsExporter.cs @@ -25,7 +25,7 @@ namespace OpenTelemetry.Exporter.ApplicationInsights using OpenTelemetry.Trace.Export; /// - /// Exporter of Open Census traces and metrics to Azure Application Insights. + /// Exporter of OpenTelemetry spans and metrics to Azure Application Insights. /// public class ApplicationInsightsExporter { @@ -47,7 +47,7 @@ public class ApplicationInsightsExporter /// /// Initializes a new instance of the class. - /// This exporter allows to send Open Census data to Azure Application Insights. + /// This exporter allows to send OpenTelemetry data to Azure Application Insights. /// /// Exporter to get traces and metrics from. /// View manager to get stats from. diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs index 4901f0259a4..102db2b9aaa 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/TraceExporterHandler.cs @@ -34,8 +34,8 @@ internal class TraceExporterHandler : IHandler private const long NanosPerMillisecond = 1000 * 1000; private const long NanosPerSecond = NanosPerMillisecond * MillisPerSecond; - private static readonly string StatusCode = "census.status_code"; - private static readonly string StatusDescription = "census.status_description"; + private static readonly string StatusCode = "ot.status_code"; + private static readonly string StatusDescription = "ot.status_description"; private readonly ZipkinTraceExporterOptions options; private readonly ZipkinEndpoint localEndpoint; diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs index 53eca9c88ff..dd6a8f1a3a2 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporter.cs @@ -21,7 +21,7 @@ namespace OpenTelemetry.Exporter.Zipkin using OpenTelemetry.Trace.Export; /// - /// Exporter of Open Census traces to Zipkin. + /// Exporter of OpenTelemetry spans to Zipkin. /// public class ZipkinTraceExporter { @@ -39,7 +39,7 @@ public class ZipkinTraceExporter /// /// Initializes a new instance of the class. - /// This exporter sends Open Census traces to Zipkin. + /// This exporter sends OpenTelemetry spans to Zipkin. /// /// Zipkin exporter configuration options. /// Exporter to get traces from. diff --git a/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporterOptions.cs b/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporterOptions.cs index a248d06a653..de2bad65a68 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporterOptions.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/ZipkinTraceExporterOptions.cs @@ -37,7 +37,7 @@ public sealed class ZipkinTraceExporterOptions /// /// Gets or sets the name of the service reporting telemetry. /// - public string ServiceName { get; set; } = "Open Census Exporter"; + public string ServiceName { get; set; } = "Open Telemetry Exporter"; /// /// Gets or sets a value indicating whether short trace id should be used. From b9db143a4cc844a5613d5caf5c7cf7e011f468ce Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 6 Aug 2019 21:10:05 -0700 Subject: [PATCH 37/41] Make Thrift project not packable (#169) --- lib/Thrift/Thrift.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Thrift/Thrift.csproj b/lib/Thrift/Thrift.csproj index 89cbb63b6f1..99897d24b8a 100644 --- a/lib/Thrift/Thrift.csproj +++ b/lib/Thrift/Thrift.csproj @@ -6,6 +6,7 @@ https://opentelemetry.io/img/logos/opentelemetry-icon-color.png https://OpenTelemetry.io Tracing;OpenTelemetry;Management;Monitoring;Jaeger;distributed-tracing + false From ff8f7b6d44c3c4a85054546077b91999e1f585d8 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 6 Aug 2019 21:28:19 -0700 Subject: [PATCH 38/41] Better Assert (with error message) for timestampt range (#168) --- test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs index e3fabb9caaf..84fc638eb30 100644 --- a/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs +++ b/test/OpenTelemetry.Tests/Impl/Trace/SpanTest.cs @@ -699,8 +699,7 @@ public void Dispose() private void AssertApproxSameTimestamp(DateTime one, DateTime two) { var timeShift = Math.Abs((one - two).TotalMilliseconds); - Assert.True(timeShift > 0); - Assert.True(timeShift < 10); + Assert.InRange(timeShift, double.Epsilon, 10); } } } From 333484d142914d17435d4719f5760eee99a40a7a Mon Sep 17 00:00:00 2001 From: pcwiese Date: Wed, 7 Aug 2019 13:00:52 -0700 Subject: [PATCH 39/41] Fixing a bad Event definition in the OpenTelemetry.Collector.Dependencies EventSource (#181) Verified provider events using PerfView --- .../DependenciesCollectorEventSource.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs index b088d812c62..a18e0a3a9dc 100644 --- a/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs +++ b/src/OpenTelemetry.Collector.Dependencies/DependenciesCollectorEventSource.cs @@ -32,7 +32,7 @@ internal class DependenciesCollectorEventSource : EventSource [NonEvent] public void ExceptionInCustomSampler(Exception ex) { - if (Log.IsEnabled(EventLevel.Warning, EventKeywords.All)) + if (this.IsEnabled(EventLevel.Warning, EventKeywords.All)) { this.ExceptionInCustomSampler(ToInvariantString(ex)); } @@ -56,10 +56,21 @@ public void NullActivity(string eventName) this.WriteEvent(3, eventName); } - [Event(4, Message = "Unknown error processing event '{0}' from handler '{1}', Exception: {2}", Level = EventLevel.Error)] + [NonEvent] public void UnknownErrorProcessingEvent(string handlerName, string eventName, Exception ex) + { + if (!this.IsEnabled(EventLevel.Error, EventKeywords.All)) + { + return; + } + + this.UnknownErrorProcessingEvent(handlerName, eventName, ToInvariantString(ex)); + } + + [Event(4, Message = "Unknown error processing event '{0}' from handler '{1}', Exception: {2}", Level = EventLevel.Error)] + internal void UnknownErrorProcessingEvent(string handlerName, string eventName, string ex) { - this.WriteEvent(4, handlerName, eventName, ToInvariantString(ex)); + this.WriteEvent(4, handlerName, eventName, ex); } /// From 4cbc55c67d8e73399d52c4dc9d1a19b49acecb0a Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 8 Aug 2019 05:36:01 -0700 Subject: [PATCH 40/41] Remove redundant Thread.Sleep(minute) (#179) --- .../Implementation/MetricsExporterThread.cs | 2 - .../ApplicationInsightsExporterTests.cs | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsExporterTests.cs diff --git a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs index d5c7c3e1309..5ab06215edf 100644 --- a/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs +++ b/src/OpenTelemetry.Exporter.ApplicationInsights/Implementation/MetricsExporterThread.cs @@ -66,8 +66,6 @@ public void WorkerThread() Thread.Sleep(this.cancellationInterval); sleepInterval = sleepInterval.Subtract(this.cancellationInterval); } - - Thread.Sleep(sleepInterval); } } catch (Exception ex) diff --git a/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsExporterTests.cs b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsExporterTests.cs new file mode 100644 index 00000000000..ddfbf59c860 --- /dev/null +++ b/test/OpenTelemetry.Exporter.ApplicationInsights.Tests/Implementation/ApplicationInsightsExporterTests.cs @@ -0,0 +1,43 @@ +// +// 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 theLicense 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 System.Diagnostics; +using System.Threading.Tasks; +using Microsoft.ApplicationInsights.Extensibility; +using OpenTelemetry.Trace.Export; +using Xunit; + +namespace OpenTelemetry.Exporter.ApplicationInsights.Tests.Implementation +{ + public class ApplicationInsightsExporterTests + { + [Fact] + public async Task StartStopExporter() + { + var config = new TelemetryConfiguration { TelemetryChannel = new StubTelemetryChannel(), }; + var exporter = new ApplicationInsightsExporter(SpanExporter.Create(), Stats.Stats.ViewManager, config); + + exporter.Start(); + await Task.Delay(100); + + var sw = Stopwatch.StartNew(); + exporter.Stop(); + sw.Stop(); + + Assert.InRange(sw.ElapsedMilliseconds, 0, 1000); + } + } +} From fccdad2c573d1164f385f6f57567c9c26c490bda Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 8 Aug 2019 05:49:52 -0700 Subject: [PATCH 41/41] Update README.md (#180) --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 13f3ad55a26..79236f5eca3 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,11 @@ We encourage contributions. Use tags [up-for-grabs][up-for-grabs-issues] and ## Packages +### Nightly builds: +Myget feeds: +- NuGet V3 feed: https://www.myget.org/F/opentelemetry/api/v3/index.json +- NuGet V2 feed: https://www.myget.org/F/opentelemetry/api/v2 + ### API and implementation | Package | MyGet (CI) | NuGet (releases) |