From 4712c3a9b0f9cedcb27297d46b08001fc13282cf Mon Sep 17 00:00:00 2001 From: Vishwesh Bankwar Date: Tue, 20 Jun 2023 15:08:58 -0700 Subject: [PATCH 1/3] [perf] Minor Httpclient improvement (#4572) --- .../HttpClientInstrumentation.cs | 24 +++++++++++++++---- .../HttpClientMetrics.cs | 11 ++++++++- .../HttpClientInstrumentationBenchmarks.cs | 14 +++++------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs b/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs index c7ffe545f21..842cd0b9af3 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpClientInstrumentation.cs @@ -22,10 +22,26 @@ namespace OpenTelemetry.Instrumentation.Http /// internal sealed class HttpClientInstrumentation : IDisposable { + private static readonly HashSet ExcludedDiagnosticSourceEventsNet7OrGreater = new() + { + "System.Net.Http.Request", + "System.Net.Http.Response", + "System.Net.Http.HttpRequestOut", + }; + + private static readonly HashSet ExcludedDiagnosticSourceEvents = new() + { + "System.Net.Http.Request", + "System.Net.Http.Response", + }; + private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber; - private readonly Func isEnabled = (activityName, obj1, obj2) - => !activityName.Equals("System.Net.Http.HttpRequestOut"); + private readonly Func isEnabled = (eventName, _, _) + => !ExcludedDiagnosticSourceEvents.Contains(eventName); + + private readonly Func isEnabledNet7OrGreater = (eventName, _, _) + => !ExcludedDiagnosticSourceEventsNet7OrGreater.Contains(eventName); /// /// Initializes a new instance of the class. @@ -41,11 +57,11 @@ public HttpClientInstrumentation(HttpClientInstrumentationOptions options) // so that the sampler's decision is respected. if (HttpHandlerDiagnosticListener.IsNet7OrGreater) { - this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerDiagnosticListener(options), this.isEnabled); + this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerDiagnosticListener(options), this.isEnabledNet7OrGreater); } else { - this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerDiagnosticListener(options), null); + this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerDiagnosticListener(options), this.isEnabled); } this.diagnosticSourceSubscriber.Subscribe(); diff --git a/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs b/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs index e48af04a625..3bf57029d8a 100644 --- a/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Http/HttpClientMetrics.cs @@ -29,16 +29,25 @@ internal sealed class HttpClientMetrics : IDisposable internal static readonly string InstrumentationName = AssemblyName.Name; internal static readonly string InstrumentationVersion = AssemblyName.Version.ToString(); + private static readonly HashSet ExcludedDiagnosticSourceEvents = new() + { + "System.Net.Http.Request", + "System.Net.Http.Response", + }; + private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber; private readonly Meter meter; + private readonly Func isEnabled = (activityName, obj1, obj2) + => !ExcludedDiagnosticSourceEvents.Contains(activityName); + /// /// Initializes a new instance of the class. /// public HttpClientMetrics() { this.meter = new Meter(InstrumentationName, InstrumentationVersion); - this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerMetricsDiagnosticListener("HttpHandlerDiagnosticListener", this.meter), null); + this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(new HttpHandlerMetricsDiagnosticListener("HttpHandlerDiagnosticListener", this.meter), this.isEnabled); this.diagnosticSourceSubscriber.Subscribe(); } diff --git a/test/Benchmarks/Instrumentation/HttpClientInstrumentationBenchmarks.cs b/test/Benchmarks/Instrumentation/HttpClientInstrumentationBenchmarks.cs index a25570b9064..2583b32cf0d 100644 --- a/test/Benchmarks/Instrumentation/HttpClientInstrumentationBenchmarks.cs +++ b/test/Benchmarks/Instrumentation/HttpClientInstrumentationBenchmarks.cs @@ -24,19 +24,19 @@ using OpenTelemetry.Trace; /* -BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.23424.1000) -Intel Core i7-9700 CPU 3.00GHz, 1 CPU, 8 logical and 8 physical cores -.NET SDK=7.0.203 +BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22621.1702/22H2/2022Update/SunValley2) +Intel Core i7-8850H CPU 2.60GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores +.NET SDK=7.0.302 [Host] : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2 DefaultJob : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2 | Method | EnableInstrumentation | Mean | Error | StdDev | Gen0 | Allocated | |------------------ |---------------------- |---------:|--------:|--------:|-------:|----------:| -| HttpClientRequest | None | 222.7 us | 4.28 us | 4.75 us | - | 2.45 KB | -| HttpClientRequest | Traces | 233.0 us | 4.08 us | 3.81 us | 0.4883 | 4.36 KB | -| HttpClientRequest | Metrics | 208.9 us | 4.17 us | 7.53 us | 0.4883 | 3.76 KB | -| HttpClientRequest | Traces, Metrics | 230.9 us | 3.29 us | 2.92 us | 0.4883 | 4.38 KB | +| HttpClientRequest | None | 161.0 us | 1.27 us | 0.99 us | 0.4883 | 2.45 KB | +| HttpClientRequest | Traces | 173.1 us | 1.65 us | 1.54 us | 0.4883 | 4.26 KB | +| HttpClientRequest | Metrics | 165.8 us | 1.33 us | 1.18 us | 0.7324 | 3.66 KB | +| HttpClientRequest | Traces, Metrics | 175.6 us | 1.96 us | 1.83 us | 0.4883 | 4.28 KB | */ namespace Benchmarks.Instrumentation From b7821f7ee0c1023e15f6cba9d2b76e184e6e6ba0 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 20 Jun 2023 18:18:12 -0700 Subject: [PATCH 2/3] Remove zpages (#4604) --- .vscode/settings.json | 3 +- OpenTelemetry.sln | 4 - examples/Console/Examples.Console.csproj | 3 +- examples/Console/Program.cs | 9 +- examples/Console/TestZPagesExporter.cs | 66 ----- .../.publicApi/net462/PublicAPI.Shipped.txt | 0 .../.publicApi/net462/PublicAPI.Unshipped.txt | 21 -- .../netstandard2.0/PublicAPI.Shipped.txt | 0 .../netstandard2.0/PublicAPI.Unshipped.txt | 21 -- .../AssemblyInfo.cs | 22 -- .../CHANGELOG.md | 148 ---------- .../Implementation/ZPagesActivityAggregate.cs | 94 ------- .../Implementation/ZPagesActivityTracker.cs | 133 --------- .../ZPagesExporterEventSource.cs | 75 ----- .../Implementation/ZPagesStatsBuilder.cs | 23 -- .../OpenTelemetry.Exporter.ZPages.csproj | 20 -- src/OpenTelemetry.Exporter.ZPages/README.md | 26 -- .../ZPagesExporter.cs | 64 ----- .../ZPagesExporterHelperExtensions.cs | 47 ---- .../ZPagesExporterOptions.cs | 34 --- .../ZPagesExporterStatsHttpServer.cs | 194 ------------- .../ZPagesProcessor.cs | 117 -------- ...nTelemetry.AotCompatibility.TestApp.csproj | 1 - .../EventSourceTest.cs | 31 -- ...OpenTelemetry.Exporter.ZPages.Tests.csproj | 32 --- .../ZPagesActivityTrackerTests.cs | 43 --- .../ZPagesExporterTests.cs | 265 ------------------ 27 files changed, 3 insertions(+), 1493 deletions(-) delete mode 100644 examples/Console/TestZPagesExporter.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Shipped.txt delete mode 100644 src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt delete mode 100644 src/OpenTelemetry.Exporter.ZPages/AssemblyInfo.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md delete mode 100644 src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityTracker.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/OpenTelemetry.Exporter.ZPages.csproj delete mode 100644 src/OpenTelemetry.Exporter.ZPages/README.md delete mode 100644 src/OpenTelemetry.Exporter.ZPages/ZPagesExporter.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/ZPagesExporterHelperExtensions.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/ZPagesExporterOptions.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/ZPagesExporterStatsHttpServer.cs delete mode 100644 src/OpenTelemetry.Exporter.ZPages/ZPagesProcessor.cs delete mode 100644 test/OpenTelemetry.Exporter.ZPages.Tests/EventSourceTest.cs delete mode 100644 test/OpenTelemetry.Exporter.ZPages.Tests/OpenTelemetry.Exporter.ZPages.Tests.csproj delete mode 100644 test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesActivityTrackerTests.cs delete mode 100644 test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesExporterTests.cs diff --git a/.vscode/settings.json b/.vscode/settings.json index f82a1be7f59..09d712afee5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -54,7 +54,6 @@ "utkarsh", "vishwesh", "xunit", - "zipkin", - "zpages" + "zipkin" ] } diff --git a/OpenTelemetry.sln b/OpenTelemetry.sln index 6685c16e446..7c75ed0c9b2 100644 --- a/OpenTelemetry.sln +++ b/OpenTelemetry.sln @@ -72,8 +72,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.Ho EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.OpenTelemetryProtocol", "src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj", "{A38AC295-2745-4B85-8B6B-DCA864CEDD5B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.ZPages", "src\OpenTelemetry.Exporter.ZPages\OpenTelemetry.Exporter.ZPages.csproj", "{56A34828-621A-478B-A0B8-C065FE938383}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Console", "src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj", "{1AFFF251-3B0C-47CA-BE94-937083732C0A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Zipkin.Tests", "test\OpenTelemetry.Exporter.Zipkin.Tests\OpenTelemetry.Exporter.Zipkin.Tests.csproj", "{1D778D2E-9523-450E-A6E0-A36897C7E78E}" @@ -125,8 +123,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D2E73927-5 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.Grpc.Tests", "test\OpenTelemetry.Instrumentation.Grpc.Tests\OpenTelemetry.Instrumentation.Grpc.Tests.csproj", "{305E9DFD-E73B-4A28-8769-795C25551020}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.ZPages.Tests", "test\OpenTelemetry.Exporter.ZPages.Tests\OpenTelemetry.Exporter.ZPages.Tests.csproj", "{98F9556B-116F-49B5-9211-BB1D418446FF}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.Console", "examples\Console\Examples.Console.csproj", "{FF3E6E08-E8E4-4523-B526-847CD989279F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.AspNetCore", "examples\AspNetCore\Examples.AspNetCore.csproj", "{0935622B-9377-4056-8343-AE6ECDC274CF}" diff --git a/examples/Console/Examples.Console.csproj b/examples/Console/Examples.Console.csproj index 02438fb885e..ee9d4d0c6ce 100644 --- a/examples/Console/Examples.Console.csproj +++ b/examples/Console/Examples.Console.csproj @@ -30,12 +30,11 @@ - - + diff --git a/examples/Console/Program.cs b/examples/Console/Program.cs index 8dffaef6a03..db0fb90389f 100644 --- a/examples/Console/Program.cs +++ b/examples/Console/Program.cs @@ -33,7 +33,6 @@ public class Program /// dotnet run --project Examples.Console.csproj -- jaeger -h localhost -p 6831 /// dotnet run --project Examples.Console.csproj -- prometheus -p 9464 /// dotnet run --project Examples.Console.csproj -- otlp -e "http://localhost:4317" -p "grpc" - /// dotnet run --project Examples.Console.csproj -- zpages /// dotnet run --project Examples.Console.csproj -- metrics --help /// /// To see all available examples in the project run: @@ -46,7 +45,7 @@ public class Program /// Arguments from command line. public static void Main(string[] args) { - Parser.Default.ParseArguments(args) + Parser.Default.ParseArguments(args) .MapResult( (JaegerOptions options) => TestJaegerExporter.Run(options.Host, options.Port), (ZipkinOptions options) => TestZipkinExporter.Run(options.Uri), @@ -55,7 +54,6 @@ public static void Main(string[] args) (LogsOptions options) => TestLogs.Run(options), (GrpcNetClientOptions options) => TestGrpcNetClient.Run(), (HttpClientOptions options) => TestHttpClient.Run(), - (ZPagesOptions options) => TestZPagesExporter.Run(), (ConsoleOptions options) => TestConsoleExporter.Run(options), (OpenTelemetryShimOptions options) => TestOTelShimWithConsoleExporter.Run(options), (OpenTracingShimOptions options) => TestOpenTracingShim.Run(options), @@ -129,11 +127,6 @@ internal class HttpClientOptions { } - [Verb("zpages", HelpText = "Specify the options required to test ZPages")] - internal class ZPagesOptions - { - } - [Verb("console", HelpText = "Specify the options required to test console exporter")] internal class ConsoleOptions { diff --git a/examples/Console/TestZPagesExporter.cs b/examples/Console/TestZPagesExporter.cs deleted file mode 100644 index 2162725520d..00000000000 --- a/examples/Console/TestZPagesExporter.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright The 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.Diagnostics; -using OpenTelemetry; -using OpenTelemetry.Exporter.ZPages; -using OpenTelemetry.Trace; - -namespace Examples.Console -{ - internal class TestZPagesExporter - { - internal static object Run() - { - var zpagesOptions = new ZPagesExporterOptions() { Url = "http://localhost:7284/rpcz/", RetentionTime = 3600000 }; - using var zpagesExporter = new ZPagesExporter(zpagesOptions); - using var httpServer = new ZPagesExporterStatsHttpServer(zpagesExporter); - - // Start the server - httpServer.Start(); - - using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddSource("zpages-test") - .AddZPagesExporter(o => - { - o.Url = zpagesOptions.Url; - o.RetentionTime = zpagesOptions.RetentionTime; - }) - .Build(); - - using var activitySource = new ActivitySource("zpages-test"); - - while (true) - { - // Create a scoped activity. It will end automatically when using statement ends - using (activitySource.StartActivity("Main")) - { - System.Console.WriteLine("About to do a busy work in Main"); - } - - Thread.Sleep(3000); - - // Create a scoped activity. It will end automatically when using statement ends - using (activitySource.StartActivity("Test")) - { - System.Console.WriteLine("About to do a busy work in Test"); - } - - Thread.Sleep(5000); - } - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Unshipped.txt deleted file mode 100644 index faf071f21a0..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/.publicApi/net462/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,21 +0,0 @@ -OpenTelemetry.Exporter.ZPages.ZPagesExporter -OpenTelemetry.Exporter.ZPages.ZPagesExporter.ZPagesExporter(OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions options) -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.RetentionTime.get -> long -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.RetentionTime.set -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.Url.get -> string -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.Url.set -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.ZPagesExporterOptions() -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Dispose() -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Stop() -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.ZPagesExporterStatsHttpServer(OpenTelemetry.Exporter.ZPages.ZPagesExporter exporter) -> void -OpenTelemetry.Exporter.ZPages.ZPagesProcessor -OpenTelemetry.Exporter.ZPages.ZPagesProcessor.ZPagesProcessor(OpenTelemetry.Exporter.ZPages.ZPagesExporter exporter) -> void -OpenTelemetry.Trace.ZPagesExporterHelperExtensions -override OpenTelemetry.Exporter.ZPages.ZPagesExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult -override OpenTelemetry.Exporter.ZPages.ZPagesProcessor.OnEnd(System.Diagnostics.Activity activity) -> void -override OpenTelemetry.Exporter.ZPages.ZPagesProcessor.OnStart(System.Diagnostics.Activity activity) -> void -static OpenTelemetry.Trace.ZPagesExporterHelperExtensions.AddZPagesExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder -virtual OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Dispose(bool disposing) -> void \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Shipped.txt b/src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Shipped.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt deleted file mode 100644 index faf071f21a0..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ /dev/null @@ -1,21 +0,0 @@ -OpenTelemetry.Exporter.ZPages.ZPagesExporter -OpenTelemetry.Exporter.ZPages.ZPagesExporter.ZPagesExporter(OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions options) -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.RetentionTime.get -> long -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.RetentionTime.set -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.Url.get -> string -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.Url.set -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions.ZPagesExporterOptions() -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Dispose() -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Start(System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Stop() -> void -OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.ZPagesExporterStatsHttpServer(OpenTelemetry.Exporter.ZPages.ZPagesExporter exporter) -> void -OpenTelemetry.Exporter.ZPages.ZPagesProcessor -OpenTelemetry.Exporter.ZPages.ZPagesProcessor.ZPagesProcessor(OpenTelemetry.Exporter.ZPages.ZPagesExporter exporter) -> void -OpenTelemetry.Trace.ZPagesExporterHelperExtensions -override OpenTelemetry.Exporter.ZPages.ZPagesExporter.Export(in OpenTelemetry.Batch batch) -> OpenTelemetry.ExportResult -override OpenTelemetry.Exporter.ZPages.ZPagesProcessor.OnEnd(System.Diagnostics.Activity activity) -> void -override OpenTelemetry.Exporter.ZPages.ZPagesProcessor.OnStart(System.Diagnostics.Activity activity) -> void -static OpenTelemetry.Trace.ZPagesExporterHelperExtensions.AddZPagesExporter(this OpenTelemetry.Trace.TracerProviderBuilder builder, System.Action configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder -virtual OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Dispose(bool disposing) -> void \ No newline at end of file diff --git a/src/OpenTelemetry.Exporter.ZPages/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.ZPages/AssemblyInfo.cs deleted file mode 100644 index 0332b70b3e2..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright The 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.Runtime.CompilerServices; - -#if SIGNED -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.ZPages.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] -#else -[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.ZPages.Tests")] -#endif diff --git a/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md b/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md deleted file mode 100644 index f036fbdbd8b..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/CHANGELOG.md +++ /dev/null @@ -1,148 +0,0 @@ -# Changelog - -## Unreleased - -## 1.5.0-beta.1 - -Released 2023-Jun-05 - -* Bumped the package version to `1.5.0-beta.1` to keep its major and minor - version in sync with that of the core packages. This would make it more - intuitive for users to figure out what version of core packages would work - with a given version of this package. The pre-release identifier has also been - changed from `rc` to `beta` as we believe this more accurately reflects the - status of this package. We believe the `rc` identifier will be more - appropriate as semantic conventions reach stability. - -## 1.0.0-rc9.14 - -Released 2023-Feb-24 - -* Updated OTel SDK dependency to 1.4.0 - -## 1.4.0-rc9.13 - -Released 2023-Feb-10 - -## 1.0.0-rc9.12 - -Released 2023-Feb-01 - -## 1.0.0-rc9.11 - -Released 2023-Jan-09 - -## 1.0.0-rc9.10 - -Released 2022-Dec-12 - -## 1.0.0-rc9.9 - -Released 2022-Nov-07 - -## 1.0.0-rc9.8 - -Released 2022-Oct-17 - -## 1.0.0-rc9.7 - -Released 2022-Sep-29 - -## 1.0.0-rc9.6 - -Released 2022-Aug-18 - -## 1.0.0-rc9.5 - -Released 2022-Aug-02 - -## 1.0.0-rc9.4 - -Released 2022-Jun-03 - -* Removes .NET Framework 4.6.1. The minimum .NET Framework - version supported is .NET 4.6.2. ([#3190](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3190)) - -## 1.0.0-rc9.3 - -Released 2022-Apr-15 - -## 1.0.0-rc9.2 - -Released 2022-Apr-12 - -## 1.0.0-rc9.1 - -Released 2022-Mar-30 - -## 1.0.0-rc10 (broken. use 1.0.0-rc9.1 and newer) - -Released 2022-Mar-04 - -## 1.0.0-rc9 - -Released 2022-Feb-02 - -## 1.0.0-rc8 - -Released 2021-Oct-08 - -* Removes .NET Framework 4.5.2, 4.6 support. The minimum .NET Framework version - supported is .NET 4.6.1. ([2138](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2138)) - -## 1.0.0-rc7 - -Released 2021-Jul-12 - -## 1.0.0-rc6 - -Released 2021-Jun-25 - -## 1.0.0-rc5 - -Released 2021-Jun-09 - -## 1.0.0-rc3 - -Released 2021-Mar-19 - -## 1.0.0-rc2 - -Released 2021-Jan-29 - -## 1.0.0-rc1.1 - -Released 2020-Nov-17 - -## 0.8.0-beta.1 - -Released 2020-Nov-5 - -## 0.7.0-beta.1 - -Released 2020-Oct-16 - -## 0.6.0-beta.1 - -Released 2020-Sep-15 - -## 0.5.0-beta.2 - -Released 2020-08-28 - -* Renamed extension method from `UseZPagesExporter` to `AddZPagesExporter`. - ([#1066](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1066)) -* Changed `ZPagesExporter` to use `ZPagesProcessor` by default. - ([#1108](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1108)) - -## 0.4.0-beta.2 - -Released 2020-07-24 - -* First beta release - -## 0.3.0-beta - -Released 2020-07-23 - -* Initial release diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs deleted file mode 100644 index b15fa015a2c..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityAggregate.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright The 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.Diagnostics; - -namespace OpenTelemetry.Exporter.ZPages.Implementation -{ - /// - /// Stores the activity information aggregated according to activity name. - /// - internal sealed class ZPagesActivityAggregate - { - /// - /// Initializes a new instance of the class. - /// - public ZPagesActivityAggregate() - { - } - - /// - /// Initializes a new instance of the class when activity data is provided. - /// - /// Input activity data to be used for initialization. - public ZPagesActivityAggregate(Activity activity) - { - this.Name = activity.DisplayName; - this.Count = 1; - this.EndedCount = 0; - this.LastUpdated = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds(); - this.TotalLatency = 0; - this.AvgLatencyTotal = 0; - this.ErrorCount = 0; - } - - /// - /// Gets or sets the name of the activity. - /// - public string Name { get; set; } - - /// - /// Gets or sets the total count of the activity. - /// - public long Count { get; set; } - - /// - /// Gets or sets the total count of the ended activity. - /// - public long EndedCount { get; set; } - - /// - /// Gets or sets the total error count of the activity. - /// - public long ErrorCount { get; set; } - - /// - /// Gets or sets the total average latency of the activity. - /// - public long AvgLatencyTotal { get; set; } - - /// - /// Gets or sets the total latency of all activities. - /// - public long TotalLatency { get; set; } - - /// - /// Gets or sets the last updated timestamp. - /// - public long LastUpdated { get; set; } - - /// - /// Calculates and returns the total average latency. - /// - /// Total average latency. - public long GetTotalAverageLatency() - { - this.AvgLatencyTotal = this.TotalLatency / this.EndedCount; - this.LastUpdated = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds(); - return this.AvgLatencyTotal; - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityTracker.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityTracker.cs deleted file mode 100644 index e9200db6939..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesActivityTracker.cs +++ /dev/null @@ -1,133 +0,0 @@ -// -// Copyright The 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.Concurrent; -using System.Timers; - -namespace OpenTelemetry.Exporter.ZPages.Implementation -{ - /// - /// Implements the ZPages Activity Queue which stores all the required activity information. - /// - internal static class ZPagesActivityTracker - { - private static readonly long StartTime; - - /// - /// Initializes static members of the class. - /// - static ZPagesActivityTracker() - { - ZQueue = new LinkedList>(); - ProcessingList = new Dictionary(); - CurrentMinuteList = new ConcurrentDictionary(); - CurrentHourList = new ConcurrentDictionary(); - TotalCount = new Dictionary(); - TotalEndedCount = new Dictionary(); - TotalErrorCount = new Dictionary(); - TotalLatency = new Dictionary(); - StartTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - } - - /// - /// Gets or sets ZQueue which stores the minute-wise activity information. - /// - public static LinkedList> ZQueue { get; set; } - - /// - /// Gets or sets the current minute activity information list. - /// - public static ConcurrentDictionary CurrentMinuteList { get; set; } - - /// - /// Gets or sets the current hour activity information list. - /// - public static ConcurrentDictionary CurrentHourList { get; set; } - - /// - /// Gets or sets the processing activity information list. This holds the names of the activities which have not ended yet, along with the active count. - /// - public static Dictionary ProcessingList { get; set; } - - /// - /// Gets or sets the count of activities name-wise. - /// - public static Dictionary TotalCount { get; set; } - - /// - /// Gets or sets the count of ended activities name-wise. - /// - public static Dictionary TotalEndedCount { get; set; } - - /// - /// Gets or sets the count of activity errors according to activity name. - /// - public static Dictionary TotalErrorCount { get; set; } - - /// - /// Gets or sets the total latency of activities name-wise. - /// - public static Dictionary TotalLatency { get; set; } - - /// - /// Gets or sets the retention time (in milliseconds) for the metrics. - /// - public static long RetentionTime { get; set; } - - /// - /// Triggers Calculations every minute. - /// - /// Source. - /// Event Arguments. - public static void PurgeCurrentMinuteData(object source, ElapsedEventArgs e) - { - // Enqueue the last minute's activity information list to ZQueue - ZQueue.AddFirst(new Dictionary(CurrentMinuteList)); - - // Clear the current minute activity list to start recording new activities only - CurrentMinuteList.Clear(); - - // Remove the stale activity information which is at the end of the list - if (DateTimeOffset.Now.ToUnixTimeMilliseconds() - StartTime >= RetentionTime) - { - ZQueue.RemoveLast(); - } - } - - /// - /// Triggers Calculations every hour. - /// - /// Source. - /// Event Arguments. - public static void PurgeCurrentHourData(object source, ElapsedEventArgs e) - { - // Clear the last hour's activity information list - CurrentHourList.Clear(); - } - - internal static void Reset() - { - TotalCount.Clear(); - TotalLatency.Clear(); - CurrentHourList.Clear(); - CurrentMinuteList.Clear(); - ZQueue.Clear(); - ProcessingList.Clear(); - TotalEndedCount.Clear(); - TotalErrorCount.Clear(); - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs deleted file mode 100644 index acdddea8b18..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesExporterEventSource.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright The 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.Diagnostics.Tracing; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Exporter.ZPages.Implementation -{ - /// - /// EventSource events emitted from the project. - /// - [EventSource(Name = "OpenTelemetry-Exporter-ZPages")] - internal sealed class ZPagesExporterEventSource : EventSource - { - public static ZPagesExporterEventSource Log = new(); - - [NonEvent] - public void FailedExport(Exception ex) - { - if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) - { - this.FailedExport(ex.ToInvariantString()); - } - } - - [NonEvent] - public void CanceledExport(Exception ex) - { - if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) - { - this.CanceledExport(ex.ToInvariantString()); - } - } - - [NonEvent] - public void FailedProcess(Exception ex) - { - if (this.IsEnabled(EventLevel.Error, EventKeywords.All)) - { - this.FailedProcess(ex.ToInvariantString()); - } - } - - [Event(1, Message = "Failed to export activities: '{0}'", Level = EventLevel.Error)] - public void FailedExport(string exception) - { - this.WriteEvent(1, exception); - } - - [Event(2, Message = "Canceled to export activities: '{0}'", Level = EventLevel.Error)] - public void CanceledExport(string exception) - { - this.WriteEvent(2, exception); - } - - [Event(3, Message = "Failed to process activity: '{0}'", Level = EventLevel.Error)] - public void FailedProcess(string exception) - { - this.WriteEvent(3, exception); - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs b/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs deleted file mode 100644 index 2409d02ef86..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesStatsBuilder.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright The 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.ZPages.Implementation -{ - internal sealed class ZPagesStatsBuilder - { - public const string ContentType = "text/html"; - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/OpenTelemetry.Exporter.ZPages.csproj b/src/OpenTelemetry.Exporter.ZPages/OpenTelemetry.Exporter.ZPages.csproj deleted file mode 100644 index e5b6fbc3f20..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/OpenTelemetry.Exporter.ZPages.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - - netstandard2.0;net462 - ZPages exporter for OpenTelemetry .NET - $(PackageTags);ZPages;distributed-tracing - - - disable - - - - - - - - - - diff --git a/src/OpenTelemetry.Exporter.ZPages/README.md b/src/OpenTelemetry.Exporter.ZPages/README.md deleted file mode 100644 index 28d49716560..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# ZPages Exporter for OpenTelemetry .NET - -[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Exporter.ZPages.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.ZPages) -[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Exporter.ZPages.svg)](https://www.nuget.org/packages/OpenTelemetry.Exporter.ZPages) - -## Installation - -```shell -dotnet add package --prerelease OpenTelemetry.Exporter.ZPages -``` - -## Configuration - -You can configure the `ZPagesExporter` by following the directions below: - -* `Url`: The url to listen to. Typically it ends with `/rpcz` like `http://localhost:7284/rpcz/`. -* `RetentionTime`: The retention time (in milliseconds) for the metrics. - -See the -[`TestZPagesExporter.cs`](../../examples/Console/TestZPagesExporter.cs) -for an example of how to use the exporter. - -## References - -* [OpenTelemetry Project](https://opentelemetry.io/) -* [zPages](https://opencensus.io/zpages/) diff --git a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporter.cs b/src/OpenTelemetry.Exporter.ZPages/ZPagesExporter.cs deleted file mode 100644 index 973e966b8ec..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporter.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright The 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.Diagnostics; -using System.Timers; -using OpenTelemetry.Exporter.ZPages.Implementation; -using OpenTelemetry.Internal; -using Timer = System.Timers.Timer; - -namespace OpenTelemetry.Exporter.ZPages -{ - /// - /// Implements ZPages exporter. - /// - public class ZPagesExporter : BaseExporter - { - internal readonly ZPagesExporterOptions Options; - private readonly Timer minuteTimer; - private readonly Timer hourTimer; - - /// - /// Initializes a new instance of the class. - /// - /// Options for the exporter. - public ZPagesExporter(ZPagesExporterOptions options) - { - Guard.ThrowIfNull(options?.RetentionTime); - - ZPagesActivityTracker.RetentionTime = options.RetentionTime; - - this.Options = options; - - // Create a timer with one minute interval - this.minuteTimer = new Timer(60000); - this.minuteTimer.Elapsed += new ElapsedEventHandler(ZPagesActivityTracker.PurgeCurrentMinuteData); - this.minuteTimer.Enabled = true; - - // Create a timer with one hour interval - this.hourTimer = new Timer(3600000); - this.hourTimer.Elapsed += new ElapsedEventHandler(ZPagesActivityTracker.PurgeCurrentHourData); - this.hourTimer.Enabled = true; - } - - /// - public override ExportResult Export(in Batch batch) - { - // var spanDatas = batch as SpanData[] ?? batch.ToArray(); - return ExportResult.Success; - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterHelperExtensions.cs b/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterHelperExtensions.cs deleted file mode 100644 index a7bcea87246..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterHelperExtensions.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright The 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.Exporter.ZPages; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Trace -{ - /// - /// Extension methods to simplify registering of Zipkin exporter. - /// - public static class ZPagesExporterHelperExtensions - { - /// - /// Registers a Zipkin exporter that will receive instances. - /// - /// builder to use. - /// Exporter configuration options. - /// The instance of to chain the calls. - public static TracerProviderBuilder AddZPagesExporter( - this TracerProviderBuilder builder, - Action configure = null) - { - Guard.ThrowIfNull(builder); - - var exporterOptions = new ZPagesExporterOptions(); - configure?.Invoke(exporterOptions); - var zpagesExporter = new ZPagesExporter(exporterOptions); - - // TODO: Pick Simple vs Batching based on ZipkinExporterOptions - return builder.AddProcessor(new ZPagesProcessor(zpagesExporter)); - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterOptions.cs b/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterOptions.cs deleted file mode 100644 index 221382b455d..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterOptions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright The 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.ZPages -{ - /// - /// Options to run zpages exporter. - /// - public class ZPagesExporterOptions - { - /// - /// Gets or sets the URL to listen to. Typically it ends with /rpcz like http://localhost:7284/rpcz/. - /// - public string Url { get; set; } - - /// - /// Gets or sets the retention time (in milliseconds) for the metrics. Default: 100000. - /// - public long RetentionTime { get; set; } = 100000; - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterStatsHttpServer.cs b/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterStatsHttpServer.cs deleted file mode 100644 index 360a12e2a6b..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/ZPagesExporterStatsHttpServer.cs +++ /dev/null @@ -1,194 +0,0 @@ -// -// Copyright The 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.Concurrent; -using System.Net; -using OpenTelemetry.Exporter.ZPages.Implementation; -using OpenTelemetry.Internal; - -namespace OpenTelemetry.Exporter.ZPages -{ - /// - /// A HTTP listener used to expose ZPages stats. - /// - public class ZPagesExporterStatsHttpServer : IDisposable - { - private readonly HttpListener httpListener = new(); - private readonly object syncObject = new(); - - private CancellationTokenSource tokenSource; - private Task workerThread; - - /// - /// Initializes a new instance of the class. - /// - /// The instance. - public ZPagesExporterStatsHttpServer(ZPagesExporter exporter) - { - Guard.ThrowIfNull(exporter?.Options?.Url); - - this.httpListener.Prefixes.Add(exporter.Options.Url); - } - - /// - /// Start exporter. - /// - /// An optional that can be used to stop the http server. - public void Start(CancellationToken token = default) - { - lock (this.syncObject) - { - if (this.tokenSource != null) - { - return; - } - - // link the passed in token if not null - this.tokenSource = token == default ? - new CancellationTokenSource() : - CancellationTokenSource.CreateLinkedTokenSource(token); - - this.httpListener.Start(); - - this.workerThread = Task.Factory.StartNew(this.WorkerThread, default, TaskCreationOptions.LongRunning, TaskScheduler.Default); - } - } - - /// - /// Stop exporter. - /// - public void Stop() - { - lock (this.syncObject) - { - if (this.tokenSource == null) - { - return; - } - - this.tokenSource.Cancel(); - this.workerThread.Wait(); - this.tokenSource = null; - } - } - - /// - /// Disposes of managed resources. - /// - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases the unmanaged resources used by this class and optionally releases the managed resources. - /// - /// to release both managed and unmanaged resources; to release only unmanaged resources. - protected virtual void Dispose(bool disposing) - { - if (this.httpListener != null && this.httpListener.IsListening) - { - this.Stop(); - } - } - - private void WorkerThread() - { - try - { - while (!this.tokenSource.IsCancellationRequested) - { - Task ctxTask = this.httpListener.GetContextAsync(); - ctxTask.Wait(this.tokenSource.Token); - - var ctx = ctxTask.Result; - - ctx.Response.StatusCode = 200; - ctx.Response.ContentType = ZPagesStatsBuilder.ContentType; - - using Stream output = ctx.Response.OutputStream; - using var writer = new StreamWriter(output); - writer.WriteLine(""); - writer.WriteLine("RPC Stats" + - "" + - "" + - "" + - "" + - ""); - writer.WriteLine("

RPC Stats

" + - "" + - "" + - "" + - ""); - - ConcurrentDictionary currentHourSpanList = ZPagesActivityTracker.CurrentHourList; - ConcurrentDictionary currentMinuteSpanList = ZPagesActivityTracker.CurrentMinuteList; - - // Put span information in each row of the table - foreach (var spanName in currentHourSpanList.Keys) - { - long countInLastMinute = 0; - long countInLastHour = 0; - long averageLatencyInLastMinute = 0; - long averageLatencyInLastHour = 0; - long errorCountInLastMinute = 0; - long errorCountInLastHour = 0; - - if (currentMinuteSpanList.ContainsKey(spanName)) - { - currentMinuteSpanList.TryGetValue(spanName, out ZPagesActivityAggregate minuteSpanInformation); - countInLastMinute = minuteSpanInformation.EndedCount + ZPagesActivityTracker.ProcessingList[spanName]; - averageLatencyInLastMinute = minuteSpanInformation.AvgLatencyTotal; - errorCountInLastMinute = minuteSpanInformation.ErrorCount; - } - - currentHourSpanList.TryGetValue(spanName, out ZPagesActivityAggregate hourSpanInformation); - countInLastHour = hourSpanInformation.EndedCount + ZPagesActivityTracker.ProcessingList[spanName]; - averageLatencyInLastHour = hourSpanInformation.AvgLatencyTotal; - errorCountInLastHour = hourSpanInformation.ErrorCount; - - long totalAverageLatency = ZPagesActivityTracker.TotalLatency[spanName] / ZPagesActivityTracker.TotalEndedCount[spanName]; - - DateTimeOffset dateTimeOffset; - - dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(hourSpanInformation.LastUpdated); - - writer.WriteLine("" + - "" + - ""); - } - - writer.WriteLine("
Span NameTotal CountCount in last minuteCount in last hourAverage Latency (ms)Average Latency in last minute (ms)Average Latency in last hour (ms)Total ErrorsErrors in last minuteErrors in last minuteLast Updated
" + hourSpanInformation.Name + "" + ZPagesActivityTracker.TotalCount[spanName] + "" + countInLastMinute + "" + countInLastHour + "" + totalAverageLatency + "" + averageLatencyInLastMinute + "" + averageLatencyInLastHour + "" + ZPagesActivityTracker.TotalErrorCount[spanName] + "" + errorCountInLastMinute + "" + errorCountInLastHour + "" + dateTimeOffset + " GMT" + "
"); - writer.WriteLine("
"); - } - } - catch (OperationCanceledException ex) - { - ZPagesExporterEventSource.Log.CanceledExport(ex); - } - catch (Exception ex) - { - ZPagesExporterEventSource.Log.FailedExport(ex); - } - finally - { - this.httpListener.Stop(); - this.httpListener.Close(); - } - } - } -} diff --git a/src/OpenTelemetry.Exporter.ZPages/ZPagesProcessor.cs b/src/OpenTelemetry.Exporter.ZPages/ZPagesProcessor.cs deleted file mode 100644 index c7a0c7951c6..00000000000 --- a/src/OpenTelemetry.Exporter.ZPages/ZPagesProcessor.cs +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright The 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.Diagnostics; -using OpenTelemetry.Exporter.ZPages.Implementation; -using OpenTelemetry.Trace; - -namespace OpenTelemetry.Exporter.ZPages -{ - /// - /// Implements the zpages span processor that exports spans in OnEnd call without batching. - /// - public class ZPagesProcessor : BaseProcessor - { - private readonly ZPagesExporter exporter; - - /// - /// Initializes a new instance of the class. - /// - /// Zpages Span processor instance. - public ZPagesProcessor(ZPagesExporter exporter) - { - this.exporter = exporter; - } - - /// - public override void OnStart(Activity activity) - { - Debug.Assert(activity != null, "Activity should not be null"); - - if (!ZPagesActivityTracker.ProcessingList.ContainsKey(activity.DisplayName)) - { - // If the span name is not in the processing span list, add it to the span list, the total count list, the ended count list and the error count list. - ZPagesActivityTracker.ProcessingList.Add(activity.DisplayName, 1); - ZPagesActivityTracker.TotalCount.Add(activity.DisplayName, 1); - ZPagesActivityTracker.TotalEndedCount.Add(activity.DisplayName, 0); - ZPagesActivityTracker.TotalErrorCount.Add(activity.DisplayName, 0); - ZPagesActivityTracker.TotalLatency.Add(activity.DisplayName, 0); - } - else - { - // If the span name already exists, then increment the numbers in processing list as well as the total count list. - ZPagesActivityTracker.ProcessingList.TryGetValue(activity.DisplayName, out var activeCount); - ZPagesActivityTracker.ProcessingList[activity.DisplayName] = activeCount + 1; - ZPagesActivityTracker.TotalCount.TryGetValue(activity.DisplayName, out var totalCount); - ZPagesActivityTracker.TotalCount[activity.DisplayName] = totalCount + 1; - } - } - - /// - public override void OnEnd(Activity activity) - { - Debug.Assert(activity != null, "Activity should not be null"); - try - { - // If the span name is not in the current minute list, add it to the span list. - if (!ZPagesActivityTracker.CurrentMinuteList.ContainsKey(activity.DisplayName)) - { - ZPagesActivityTracker.CurrentMinuteList.TryAdd(activity.DisplayName, new ZPagesActivityAggregate(activity)); - } - - // If the span name is not in the current hour list, add it to the span list. - if (!ZPagesActivityTracker.CurrentHourList.ContainsKey(activity.DisplayName)) - { - ZPagesActivityTracker.CurrentHourList.TryAdd(activity.DisplayName, new ZPagesActivityAggregate(activity)); - } - - ZPagesActivityTracker.CurrentMinuteList.TryGetValue(activity.DisplayName, out var minuteSpanInformation); - ZPagesActivityTracker.CurrentHourList.TryGetValue(activity.DisplayName, out var hourSpanInformation); - ZPagesActivityTracker.ProcessingList.TryGetValue(activity.DisplayName, out var activeCount); - - // Decrement the active span count in processing list, Increment the count of ended spans and calculate the average latency values for one minute and one hour. - ZPagesActivityTracker.ProcessingList[activity.DisplayName] = activeCount - 1; - minuteSpanInformation.EndedCount++; - hourSpanInformation.EndedCount++; - minuteSpanInformation.TotalLatency += (long)activity.Duration.TotalMilliseconds; - hourSpanInformation.TotalLatency += (long)activity.Duration.TotalMilliseconds; - ZPagesActivityTracker.TotalLatency[activity.DisplayName] += (long)activity.Duration.TotalMilliseconds; - minuteSpanInformation.GetTotalAverageLatency(); - hourSpanInformation.GetTotalAverageLatency(); - ZPagesActivityTracker.TotalEndedCount.TryGetValue(activity.DisplayName, out var endedCount); - ZPagesActivityTracker.TotalEndedCount[activity.DisplayName] = endedCount + 1; - - // Increment the error count, if it applies in all applicable lists. - if (activity.GetStatus() != Status.Ok) - { - minuteSpanInformation.ErrorCount++; - hourSpanInformation.ErrorCount++; - ZPagesActivityTracker.TotalErrorCount.TryGetValue(activity.DisplayName, out var errorCount); - ZPagesActivityTracker.TotalErrorCount[activity.DisplayName] = errorCount + 1; - } - - // Set the last updated timestamp. - minuteSpanInformation.LastUpdated = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds(); - hourSpanInformation.LastUpdated = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds(); - } - catch (Exception ex) - { - ZPagesExporterEventSource.Log.FailedProcess(ex); - Console.Write("OnEnd {0}", ex); - } - } - } -} diff --git a/test/OpenTelemetry.AotCompatibility.TestApp/OpenTelemetry.AotCompatibility.TestApp.csproj b/test/OpenTelemetry.AotCompatibility.TestApp/OpenTelemetry.AotCompatibility.TestApp.csproj index ef9a89b3874..8bdc01e944f 100644 --- a/test/OpenTelemetry.AotCompatibility.TestApp/OpenTelemetry.AotCompatibility.TestApp.csproj +++ b/test/OpenTelemetry.AotCompatibility.TestApp/OpenTelemetry.AotCompatibility.TestApp.csproj @@ -16,7 +16,6 @@ - diff --git a/test/OpenTelemetry.Exporter.ZPages.Tests/EventSourceTest.cs b/test/OpenTelemetry.Exporter.ZPages.Tests/EventSourceTest.cs deleted file mode 100644 index 03db587cc39..00000000000 --- a/test/OpenTelemetry.Exporter.ZPages.Tests/EventSourceTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright The 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.Exporter.ZPages.Implementation; -using OpenTelemetry.Tests; -using Xunit; - -namespace OpenTelemetry.Exporter.ZPages.Tests -{ - public class EventSourceTest - { - [Fact] - public void EventSourceTest_ZPagesExporterEventSource() - { - EventSourceTestHelper.MethodsAreImplementedConsistentlyWithTheirAttributes(ZPagesExporterEventSource.Log); - } - } -} diff --git a/test/OpenTelemetry.Exporter.ZPages.Tests/OpenTelemetry.Exporter.ZPages.Tests.csproj b/test/OpenTelemetry.Exporter.ZPages.Tests/OpenTelemetry.Exporter.ZPages.Tests.csproj deleted file mode 100644 index b8a159610c9..00000000000 --- a/test/OpenTelemetry.Exporter.ZPages.Tests/OpenTelemetry.Exporter.ZPages.Tests.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - - net6.0 - $(TargetFrameworks);net462 - - - disable - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - - - - - diff --git a/test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesActivityTrackerTests.cs b/test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesActivityTrackerTests.cs deleted file mode 100644 index 80aa1ae66a4..00000000000 --- a/test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesActivityTrackerTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright The 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.Diagnostics; -using OpenTelemetry.Exporter.ZPages.Implementation; -using Xunit; - -namespace OpenTelemetry.Exporter.ZPages.Tests -{ - public class ZPagesActivityTrackerTests - { - [Fact] - public void CheckingPurge() - { - using var activity1 = new Activity("new"); - ZPagesActivityTracker.CurrentHourList.TryAdd("new", new ZPagesActivityAggregate(activity1)); - Assert.NotEmpty(ZPagesActivityTracker.CurrentHourList); - ZPagesActivityTracker.PurgeCurrentHourData(null, null); - Assert.Empty(ZPagesActivityTracker.CurrentHourList); - - using var activity2 = new Activity("new"); - ZPagesActivityTracker.CurrentMinuteList.TryAdd("new", new ZPagesActivityAggregate(activity2)); - Assert.NotEmpty(ZPagesActivityTracker.CurrentMinuteList); - ZPagesActivityTracker.PurgeCurrentMinuteData(null, null); - Assert.Empty(ZPagesActivityTracker.CurrentMinuteList); - - ZPagesActivityTracker.ProcessingList.Clear(); - } - } -} diff --git a/test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesExporterTests.cs b/test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesExporterTests.cs deleted file mode 100644 index 82fe22bc65c..00000000000 --- a/test/OpenTelemetry.Exporter.ZPages.Tests/ZPagesExporterTests.cs +++ /dev/null @@ -1,265 +0,0 @@ -// -// Copyright The 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.Diagnostics; -using System.Net.Http; -using OpenTelemetry.Exporter.ZPages.Implementation; -using OpenTelemetry.Resources; -using OpenTelemetry.Tests; -using OpenTelemetry.Trace; -using Xunit; - -namespace OpenTelemetry.Exporter.ZPages.Tests -{ - public class ZPagesExporterTests - { - private static readonly HttpClient HttpClient = new(); - - static ZPagesExporterTests() - { - Activity.DefaultIdFormat = ActivityIdFormat.W3C; - Activity.ForceDefaultIdFormat = true; - - var listener = new ActivityListener - { - ShouldListenTo = _ => true, - Sample = (ref ActivityCreationOptions options) => ActivitySamplingResult.AllData, - }; - - ActivitySource.AddActivityListener(listener); - } - - [Fact] - public void CheckingBadArgs() - { - TracerProviderBuilder builder = null; - Assert.Throws(() => builder.AddZPagesExporter()); - } - - [Fact] - public void CheckingCustomActivityProcessor() - { - const string ActivitySourceName = "zpages.test"; - Guid requestId = Guid.NewGuid(); - TestActivityProcessor testActivityProcessor = new TestActivityProcessor(); - - bool startCalled = false; - bool endCalled = false; - - testActivityProcessor.StartAction = - (a) => - { - startCalled = true; - }; - - testActivityProcessor.EndAction = - (a) => - { - endCalled = true; - }; - - using var tracerProvider = Sdk.CreateTracerProviderBuilder() - .AddSource(ActivitySourceName) - .AddProcessor(testActivityProcessor) - .AddZPagesExporter() - .Build(); - - using var source = new ActivitySource(ActivitySourceName); - using var activity = source.StartActivity("Test Zipkin Activity"); - activity?.Stop(); - - Assert.True(startCalled); - Assert.True(endCalled); - - ZPagesActivityTracker.Reset(); - } - - [Fact] - public void CheckingCustomOptions() - { - ZPagesExporterOptions options = new ZPagesExporterOptions - { - RetentionTime = 100_000, - Url = "http://localhost:7284/rpcz/", - }; - - ZPagesExporter exporter = new ZPagesExporter(options); - - Assert.Equal(options.Url, exporter.Options.Url); - Assert.Equal(options.RetentionTime, exporter.Options.RetentionTime); - } - - [Fact] - public async Task CheckingZPagesProcessor() - { - const string ActivitySourceName = "zpages.test"; - ZPagesExporterOptions options = new ZPagesExporterOptions - { - RetentionTime = 100_000, - Url = "http://localhost:7284/rpcz/", - }; - ZPagesExporter exporter = new ZPagesExporter(options); - var zpagesProcessor = new ZPagesProcessor(exporter); - - using var source = new ActivitySource(ActivitySourceName); - using var activity0 = source.StartActivity("Test Zipkin Activity 1"); - zpagesProcessor.OnStart(activity0); - - // checking size of dictionaries from ZPagesActivityTracker - Assert.Equal(1, ZPagesActivityTracker.ProcessingList.First().Value); - Assert.Equal(1, ZPagesActivityTracker.TotalCount.First().Value); - Assert.Single(ZPagesActivityTracker.TotalEndedCount); - Assert.Single(ZPagesActivityTracker.TotalErrorCount); - Assert.Single(ZPagesActivityTracker.TotalLatency); - - using var activity1 = source.StartActivity("Test Zipkin Activity 1"); - zpagesProcessor.OnStart(activity1); - - // checking size of dictionaries from ZPagesActivityTracker - Assert.Equal(2, ZPagesActivityTracker.ProcessingList.First().Value); - Assert.Equal(2, ZPagesActivityTracker.TotalCount.First().Value); - Assert.Single(ZPagesActivityTracker.TotalEndedCount); - Assert.Single(ZPagesActivityTracker.TotalErrorCount); - Assert.Single(ZPagesActivityTracker.TotalLatency); - - using var activity2 = source.StartActivity("Test Zipkin Activity 2"); - zpagesProcessor.OnStart(activity2); - - // checking size of dictionaries from ZPagesActivityTracker - Assert.Equal(2, ZPagesActivityTracker.ProcessingList.Count); - Assert.Equal(2, ZPagesActivityTracker.TotalCount.Count); - Assert.Equal(2, ZPagesActivityTracker.TotalEndedCount.Count); - Assert.Equal(2, ZPagesActivityTracker.TotalErrorCount.Count); - Assert.Equal(2, ZPagesActivityTracker.TotalLatency.Count); - - activity0?.Stop(); - activity1?.Stop(); - activity2?.Stop(); - zpagesProcessor.OnEnd(activity0); - zpagesProcessor.OnEnd(activity1); - zpagesProcessor.OnEnd(activity2); - - // checking if activities were processed - Assert.Equal(0, ZPagesActivityTracker.ProcessingList.First().Value); - Assert.Equal(0, ZPagesActivityTracker.ProcessingList.Last().Value); - Assert.Empty(ZPagesActivityTracker.ZQueue); - - var zpagesServer = new ZPagesExporterStatsHttpServer(exporter); - zpagesServer.Start(); - - using var httpResponseMessage = await HttpClient.GetAsync("http://localhost:7284/rpcz/").ConfigureAwait(false); - Assert.True(httpResponseMessage.IsSuccessStatusCode); - - var content = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); - Assert.Contains($"Test Zipkin Activity 1", content); - Assert.Contains($"Test Zipkin Activity 2", content); - - zpagesProcessor.Dispose(); - zpagesServer.Stop(); - zpagesServer.Dispose(); - exporter.Dispose(); - } - - internal static Activity CreateTestActivity( - bool setAttributes = true, - Dictionary additionalAttributes = null, - bool addEvents = true, - bool addLinks = true, - Resource resource = null, - ActivityKind kind = ActivityKind.Client) - { - var startTimestamp = DateTime.UtcNow; - var endTimestamp = startTimestamp.AddSeconds(60); - var eventTimestamp = DateTime.UtcNow; - var traceId = ActivityTraceId.CreateFromString("e8ea7e9ac72de94e91fabc613f9686b2".AsSpan()); - - var parentSpanId = ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 }); - - var attributes = new Dictionary - { - { "stringKey", "value" }, - { "longKey", 1L }, - { "longKey2", 1 }, - { "doubleKey", 1D }, - { "doubleKey2", 1F }, - { "boolKey", true }, - }; - if (additionalAttributes != null) - { - foreach (var attribute in additionalAttributes) - { - attributes.Add(attribute.Key, attribute.Value); - } - } - - var events = new List - { - new ActivityEvent( - "Event1", - eventTimestamp, - new ActivityTagsCollection(new Dictionary - { - { "key", "value" }, - })), - new ActivityEvent( - "Event2", - eventTimestamp, - new ActivityTagsCollection(new Dictionary - { - { "key", "value" }, - })), - }; - - var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan()); - - var activitySource = new ActivitySource(nameof(CreateTestActivity)); - - var tags = setAttributes ? - attributes.Select(kvp => new KeyValuePair(kvp.Key, kvp.Value.ToString())) - : null; - var links = addLinks ? - new[] - { - new ActivityLink(new ActivityContext( - traceId, - linkedSpanId, - ActivityTraceFlags.Recorded)), - } - : null; - - var activity = activitySource.StartActivity( - "Name", - kind, - parentContext: new ActivityContext(traceId, parentSpanId, ActivityTraceFlags.Recorded), - tags, - links, - startTime: startTimestamp); - - if (addEvents) - { - foreach (var evnt in events) - { - activity.AddEvent(evnt); - } - } - - activity.SetEndTime(endTimestamp); - activity.Stop(); - - return activity; - } - } -} From 7333a557b4147d7ac01a73b95a2f57836dc909f4 Mon Sep 17 00:00:00 2001 From: mfogliatto <2962955+mfogliatto@users.noreply.github.com> Date: Wed, 21 Jun 2023 03:53:15 +0200 Subject: [PATCH 3/3] Add ToOtlpLog unit tests for scopes (cont.) (#4578) --- .../OtlpLogExporterTests.cs | 267 ++++++++++++++++++ 1 file changed, 267 insertions(+) diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs index d71303c845a..cdd73675b9c 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using System.Collections.ObjectModel; using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -676,6 +677,7 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeStrin // Assert. var logRecord = logRecords.Single(); var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); Assert.NotNull(actualScope); Assert.Equal(scopeKey, actualScope.Key); @@ -714,6 +716,7 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeBoolV // Assert. var logRecord = logRecords.Single(); var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); Assert.NotNull(actualScope); Assert.Equal(scopeKey, actualScope.Key); @@ -764,6 +767,7 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeIntVa // Assert. var logRecord = logRecords.Single(); var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); Assert.NotNull(actualScope); Assert.Equal(scopeKey, actualScope.Key); @@ -802,6 +806,7 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeDoubl // Assert. var logRecord = logRecords.Single(); var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); Assert.NotNull(actualScope); Assert.Equal(scopeKey, actualScope.Key); @@ -840,12 +845,274 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeDoubl // Assert. var logRecord = logRecords.Single(); var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); Assert.NotNull(actualScope); Assert.Equal(scopeKey, actualScope.Key); Assert.Equal(scopeValue.ToString(), actualScope.Value.DoubleValue.ToString()); } + [Fact] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfTypeString_ScopeIsIgnored() + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + const string scopeState = "Some scope state"; + + // Act. + using (logger.BeginScope(scopeState)) + { + logger.LogInformation("Some log information message."); + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.NotNull(otlpLogRecord); + Assert.Single(otlpLogRecord.Attributes); + } + + [Theory] + [InlineData(typeof(int))] + [InlineData(typeof(float))] + [InlineData(typeof(decimal))] + [InlineData(typeof(char))] + [InlineData(typeof(bool))] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfPrimitiveTypes_ScopeIsIgnored(Type typeOfScopeState) + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + var scopeState = Activator.CreateInstance(typeOfScopeState); + + // Act. + using (logger.BeginScope(scopeState)) + { + logger.LogInformation("Some log information message."); + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.NotNull(otlpLogRecord); + Assert.Single(otlpLogRecord.Attributes); + } + + [Fact] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfDictionaryType_ScopeIsProcessed() + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + const string scopeKey = "Some scope key"; + var scopeState = new Dictionary() { { scopeKey, "Some scope value" } }; + + // Act. + using (logger.BeginScope(scopeState)) + { + logger.LogInformation("Some log information message."); + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); + var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); + Assert.NotNull(actualScope); + Assert.Equal(scopeKey, actualScope.Key); + } + + [Theory] + [InlineData(typeof(List>))] + [InlineData(typeof(ReadOnlyCollection>))] + [InlineData(typeof(HashSet>))] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfEnumerableType_ScopeIsProcessed(Type typeOfScopeState) + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + const string scopeKey = "Some scope key"; + var scopeValues = new List> { new KeyValuePair(scopeKey, "Some scope value") }; + var scopeState = Activator.CreateInstance(typeOfScopeState, scopeValues) as ICollection>; + + // Act. + using (logger.BeginScope(scopeState)) + { + logger.LogInformation("Some log information message."); + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + Assert.Equal(2, otlpLogRecord.Attributes.Count); + var actualScope = TryGetAttribute(otlpLogRecord, scopeKey); + Assert.NotNull(actualScope); + Assert.Equal(scopeKey, actualScope.Key); + } + + [Theory] + [InlineData("Same scope key", "Same scope key")] + [InlineData("Scope key 1", "Scope key 2")] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndMultipleScopesAreAdded_ContainsAllAddedScopeValues(string scopeKey1, string scopeKey2) + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + const string scopeValue1 = "Some scope value"; + const string scopeValue2 = "Some other scope value"; + + // Act. + using (logger.BeginScope(new List> + { + new KeyValuePair(scopeKey1, scopeValue1), + new KeyValuePair(scopeKey2, scopeValue2), + })) + { + logger.LogInformation("Some log information message."); + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + var allScopeValues = otlpLogRecord.Attributes + .Where(_ => _.Key == scopeKey1 || _.Key == scopeKey2) + .Select(_ => _.Value.StringValue); + Assert.Equal(2, allScopeValues.Count()); + Assert.Contains(scopeValue1, allScopeValues); + Assert.Contains(scopeValue2, allScopeValues); + } + + [Theory] + [InlineData("Same scope key", "Same scope key")] + [InlineData("Scope key 1", "Scope key 2")] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndMultipleScopeLevelsAreAdded_ContainsAllAddedScopeValues(string scopeKey1, string scopeKey2) + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + const string scopeValue1 = "Some scope value"; + const string scopeValue2 = "Some other scope value"; + + // Act. + using (logger.BeginScope(new List> { new KeyValuePair(scopeKey1, scopeValue1) })) + { + using (logger.BeginScope(new List> { new KeyValuePair(scopeKey2, scopeValue2) })) + { + logger.LogInformation("Some log information message."); + } + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + var allScopeValues = otlpLogRecord.Attributes + .Where(_ => _.Key == scopeKey1 || _.Key == scopeKey2) + .Select(_ => _.Value.StringValue); + Assert.Equal(2, allScopeValues.Count()); + Assert.Contains(scopeValue1, allScopeValues); + Assert.Contains(scopeValue2, allScopeValues); + } + + [Theory] + [InlineData("Same scope key", "Same scope key")] + [InlineData("Scope key 1", "Scope key 2")] + public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeIsUsedInLogMethod_ContainsAllAddedScopeValues(string scopeKey1, string scopeKey2) + { + // Arrange. + var logRecords = new List(1); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.IncludeScopes = true; + options.AddInMemoryExporter(logRecords); + }); + }); + var logger = loggerFactory.CreateLogger(nameof(OtlpLogExporterTests)); + + const string scopeValue1 = "Some scope value"; + const string scopeValue2 = "Some other scope value"; + + // Act. + using (logger.BeginScope(new List> + { + new KeyValuePair(scopeKey1, scopeValue1), + })) + { + logger.Log( + LogLevel.Error, + new EventId(1), + new List> { new KeyValuePair(scopeKey2, scopeValue2) }, + exception: new Exception("Some exception message"), + formatter: (s, e) => string.Empty); + } + + // Assert. + var logRecord = logRecords.Single(); + var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions); + var allScopeValues = otlpLogRecord.Attributes + .Where(_ => _.Key == scopeKey1 || _.Key == scopeKey2) + .Select(_ => _.Value.StringValue); + Assert.Equal(2, allScopeValues.Count()); + Assert.Contains(scopeValue1, allScopeValues); + Assert.Contains(scopeValue2, allScopeValues); + } + private static OtlpCommon.KeyValue TryGetAttribute(OtlpLogs.LogRecord record, string key) { return record.Attributes.FirstOrDefault(att => att.Key == key);