Remove zpages (#4604)

This commit is contained in:
Reiley Yang 2023-06-20 18:18:12 -07:00 committed by GitHub
parent 4712c3a9b0
commit b7821f7ee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 3 additions and 1493 deletions

View File

@ -54,7 +54,6 @@
"utkarsh",
"vishwesh",
"xunit",
"zipkin",
"zpages"
"zipkin"
]
}

View File

@ -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}"

View File

@ -30,12 +30,11 @@
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.ZPages\OpenTelemetry.Exporter.ZPages.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Shims.OpenTracing\OpenTelemetry.Shims.OpenTracing.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus.HttpListener\OpenTelemetry.Exporter.Prometheus.HttpListener.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
</ItemGroup>
</Project>

View File

@ -33,7 +33,6 @@ namespace Examples.Console
/// 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 @@ namespace Examples.Console
/// <param name="args">Arguments from command line.</param>
public static void Main(string[] args)
{
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, MetricsOptions, LogsOptions, GrpcNetClientOptions, HttpClientOptions, ZPagesOptions, ConsoleOptions, OpenTelemetryShimOptions, OpenTracingShimOptions, OtlpOptions, InMemoryOptions>(args)
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, MetricsOptions, LogsOptions, GrpcNetClientOptions, HttpClientOptions, ConsoleOptions, OpenTelemetryShimOptions, OpenTracingShimOptions, OtlpOptions, InMemoryOptions>(args)
.MapResult(
(JaegerOptions options) => TestJaegerExporter.Run(options.Host, options.Port),
(ZipkinOptions options) => TestZipkinExporter.Run(options.Uri),
@ -55,7 +54,6 @@ namespace Examples.Console
(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 @@ namespace Examples.Console
{
}
[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
{

View File

@ -1,66 +0,0 @@
// <copyright file="TestZPagesExporter.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
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);
}
}
}
}

View File

@ -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<System.Diagnostics.Activity> 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<OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions> configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder
virtual OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Dispose(bool disposing) -> void

View File

@ -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<System.Diagnostics.Activity> 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<OpenTelemetry.Exporter.ZPages.ZPagesExporterOptions> configure = null) -> OpenTelemetry.Trace.TracerProviderBuilder
virtual OpenTelemetry.Exporter.ZPages.ZPagesExporterStatsHttpServer.Dispose(bool disposing) -> void

View File

@ -1,22 +0,0 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Runtime.CompilerServices;
#if SIGNED
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.ZPages.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
#else
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.ZPages.Tests")]
#endif

View File

@ -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

View File

@ -1,94 +0,0 @@
// <copyright file="ZPagesActivityAggregate.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics;
namespace OpenTelemetry.Exporter.ZPages.Implementation
{
/// <summary>
/// Stores the activity information aggregated according to activity name.
/// </summary>
internal sealed class ZPagesActivityAggregate
{
/// <summary>
/// Initializes a new instance of the <see cref="ZPagesActivityAggregate"/> class.
/// </summary>
public ZPagesActivityAggregate()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ZPagesActivityAggregate"/> class when activity data is provided.
/// </summary>
/// <param name="activity">Input activity data to be used for initialization.</param>
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;
}
/// <summary>
/// Gets or sets the name of the activity.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the total count of the activity.
/// </summary>
public long Count { get; set; }
/// <summary>
/// Gets or sets the total count of the ended activity.
/// </summary>
public long EndedCount { get; set; }
/// <summary>
/// Gets or sets the total error count of the activity.
/// </summary>
public long ErrorCount { get; set; }
/// <summary>
/// Gets or sets the total average latency of the activity.
/// </summary>
public long AvgLatencyTotal { get; set; }
/// <summary>
/// Gets or sets the total latency of all activities.
/// </summary>
public long TotalLatency { get; set; }
/// <summary>
/// Gets or sets the last updated timestamp.
/// </summary>
public long LastUpdated { get; set; }
/// <summary>
/// Calculates and returns the total average latency.
/// </summary>
/// <returns>Total average latency.</returns>
public long GetTotalAverageLatency()
{
this.AvgLatencyTotal = this.TotalLatency / this.EndedCount;
this.LastUpdated = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds();
return this.AvgLatencyTotal;
}
}
}

View File

@ -1,133 +0,0 @@
// <copyright file="ZPagesActivityTracker.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Collections.Concurrent;
using System.Timers;
namespace OpenTelemetry.Exporter.ZPages.Implementation
{
/// <summary>
/// Implements the ZPages Activity Queue which stores all the required activity information.
/// </summary>
internal static class ZPagesActivityTracker
{
private static readonly long StartTime;
/// <summary>
/// Initializes static members of the <see cref="ZPagesActivityTracker"/> class.
/// </summary>
static ZPagesActivityTracker()
{
ZQueue = new LinkedList<Dictionary<string, ZPagesActivityAggregate>>();
ProcessingList = new Dictionary<string, long>();
CurrentMinuteList = new ConcurrentDictionary<string, ZPagesActivityAggregate>();
CurrentHourList = new ConcurrentDictionary<string, ZPagesActivityAggregate>();
TotalCount = new Dictionary<string, long>();
TotalEndedCount = new Dictionary<string, long>();
TotalErrorCount = new Dictionary<string, long>();
TotalLatency = new Dictionary<string, long>();
StartTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
}
/// <summary>
/// Gets or sets ZQueue which stores the minute-wise activity information.
/// </summary>
public static LinkedList<Dictionary<string, ZPagesActivityAggregate>> ZQueue { get; set; }
/// <summary>
/// Gets or sets the current minute activity information list.
/// </summary>
public static ConcurrentDictionary<string, ZPagesActivityAggregate> CurrentMinuteList { get; set; }
/// <summary>
/// Gets or sets the current hour activity information list.
/// </summary>
public static ConcurrentDictionary<string, ZPagesActivityAggregate> CurrentHourList { get; set; }
/// <summary>
/// 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.
/// </summary>
public static Dictionary<string, long> ProcessingList { get; set; }
/// <summary>
/// Gets or sets the count of activities name-wise.
/// </summary>
public static Dictionary<string, long> TotalCount { get; set; }
/// <summary>
/// Gets or sets the count of ended activities name-wise.
/// </summary>
public static Dictionary<string, long> TotalEndedCount { get; set; }
/// <summary>
/// Gets or sets the count of activity errors according to activity name.
/// </summary>
public static Dictionary<string, long> TotalErrorCount { get; set; }
/// <summary>
/// Gets or sets the total latency of activities name-wise.
/// </summary>
public static Dictionary<string, long> TotalLatency { get; set; }
/// <summary>
/// Gets or sets the retention time (in milliseconds) for the metrics.
/// </summary>
public static long RetentionTime { get; set; }
/// <summary>
/// Triggers Calculations every minute.
/// </summary>
/// <param name="source">Source.</param>
/// <param name="e">Event Arguments.</param>
public static void PurgeCurrentMinuteData(object source, ElapsedEventArgs e)
{
// Enqueue the last minute's activity information list to ZQueue
ZQueue.AddFirst(new Dictionary<string, ZPagesActivityAggregate>(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();
}
}
/// <summary>
/// Triggers Calculations every hour.
/// </summary>
/// <param name="source">Source.</param>
/// <param name="e">Event Arguments.</param>
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();
}
}
}

View File

@ -1,75 +0,0 @@
// <copyright file="ZPagesExporterEventSource.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics.Tracing;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter.ZPages.Implementation
{
/// <summary>
/// EventSource events emitted from the project.
/// </summary>
[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);
}
}
}

View File

@ -1,23 +0,0 @@
// <copyright file="ZPagesStatsBuilder.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
namespace OpenTelemetry.Exporter.ZPages.Implementation
{
internal sealed class ZPagesStatsBuilder
{
public const string ContentType = "text/html";
}
}

View File

@ -1,20 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
<Description>ZPages exporter for OpenTelemetry .NET</Description>
<PackageTags>$(PackageTags);ZPages;distributed-tracing</PackageTags>
<!-- this is temporary. will remove in future PR. -->
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\ExceptionExtensions.cs" Link="Includes\ExceptionExtensions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>
</Project>

View File

@ -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/)

View File

@ -1,64 +0,0 @@
// <copyright file="ZPagesExporter.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics;
using System.Timers;
using OpenTelemetry.Exporter.ZPages.Implementation;
using OpenTelemetry.Internal;
using Timer = System.Timers.Timer;
namespace OpenTelemetry.Exporter.ZPages
{
/// <summary>
/// Implements ZPages exporter.
/// </summary>
public class ZPagesExporter : BaseExporter<Activity>
{
internal readonly ZPagesExporterOptions Options;
private readonly Timer minuteTimer;
private readonly Timer hourTimer;
/// <summary>
/// Initializes a new instance of the <see cref="ZPagesExporter"/> class.
/// </summary>
/// <param name="options">Options for the exporter.</param>
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;
}
/// <inheritdoc />
public override ExportResult Export(in Batch<Activity> batch)
{
// var spanDatas = batch as SpanData[] ?? batch.ToArray();
return ExportResult.Success;
}
}
}

View File

@ -1,47 +0,0 @@
// <copyright file="ZPagesExporterHelperExtensions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using OpenTelemetry.Exporter.ZPages;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Extension methods to simplify registering of Zipkin exporter.
/// </summary>
public static class ZPagesExporterHelperExtensions
{
/// <summary>
/// Registers a Zipkin exporter that will receive <see cref="System.Diagnostics.Activity"/> instances.
/// </summary>
/// <param name="builder"><see cref="TracerProviderBuilder"/> builder to use.</param>
/// <param name="configure">Exporter configuration options.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
public static TracerProviderBuilder AddZPagesExporter(
this TracerProviderBuilder builder,
Action<ZPagesExporterOptions> 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));
}
}
}

View File

@ -1,34 +0,0 @@
// <copyright file="ZPagesExporterOptions.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
namespace OpenTelemetry.Exporter.ZPages
{
/// <summary>
/// Options to run zpages exporter.
/// </summary>
public class ZPagesExporterOptions
{
/// <summary>
/// Gets or sets the URL to listen to. Typically it ends with /rpcz like http://localhost:7284/rpcz/.
/// </summary>
public string Url { get; set; }
/// <summary>
/// Gets or sets the retention time (in milliseconds) for the metrics. Default: 100000.
/// </summary>
public long RetentionTime { get; set; } = 100000;
}
}

View File

@ -1,194 +0,0 @@
// <copyright file="ZPagesExporterStatsHttpServer.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Collections.Concurrent;
using System.Net;
using OpenTelemetry.Exporter.ZPages.Implementation;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Exporter.ZPages
{
/// <summary>
/// A HTTP listener used to expose ZPages stats.
/// </summary>
public class ZPagesExporterStatsHttpServer : IDisposable
{
private readonly HttpListener httpListener = new();
private readonly object syncObject = new();
private CancellationTokenSource tokenSource;
private Task workerThread;
/// <summary>
/// Initializes a new instance of the <see cref="ZPagesExporterStatsHttpServer"/> class.
/// </summary>
/// <param name="exporter">The <see cref="ZPagesExporterStatsHttpServer"/> instance.</param>
public ZPagesExporterStatsHttpServer(ZPagesExporter exporter)
{
Guard.ThrowIfNull(exporter?.Options?.Url);
this.httpListener.Prefixes.Add(exporter.Options.Url);
}
/// <summary>
/// Start exporter.
/// </summary>
/// <param name="token">An optional <see cref="CancellationToken"/> that can be used to stop the http server.</param>
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);
}
}
/// <summary>
/// Stop exporter.
/// </summary>
public void Stop()
{
lock (this.syncObject)
{
if (this.tokenSource == null)
{
return;
}
this.tokenSource.Cancel();
this.workerThread.Wait();
this.tokenSource = null;
}
}
/// <summary>
/// Disposes of managed resources.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases the unmanaged resources used by this class and optionally releases the managed resources.
/// </summary>
/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (this.httpListener != null && this.httpListener.IsListening)
{
this.Stop();
}
}
private void WorkerThread()
{
try
{
while (!this.tokenSource.IsCancellationRequested)
{
Task<HttpListenerContext> 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("<!DOCTYPE html>");
writer.WriteLine("<html><head><title>RPC Stats</title>" +
"<meta charset=\"utf-8\">" +
"<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css\">" +
"<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js\"></script>" +
"<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js\"></script>" +
"</head>");
writer.WriteLine("<body><div class=\"col-sm-1\"></div><div class=\"container col-sm-10\"><div class=\"jumbotron table-responsive\"><h1>RPC Stats</h2>" +
"<table class=\"table table-bordered table-hover table-striped\">" +
"<thead><tr><th>Span Name</th><th>Total Count</th><th>Count in last minute</th><th>Count in last hour</th><th>Average Latency (ms)</th>" +
"<th>Average Latency in last minute (ms)</th><th>Average Latency in last hour (ms)</th><th>Total Errors</th><th>Errors in last minute</th><th>Errors in last minute</th><th>Last Updated</th></tr></thead>" +
"<tbody>");
ConcurrentDictionary<string, ZPagesActivityAggregate> currentHourSpanList = ZPagesActivityTracker.CurrentHourList;
ConcurrentDictionary<string, ZPagesActivityAggregate> 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("<tr><td>" + hourSpanInformation.Name + "</td><td>" + ZPagesActivityTracker.TotalCount[spanName] + "</td><td>" + countInLastMinute + "</td><td>" + countInLastHour + "</td>" +
"<td>" + totalAverageLatency + "</td><td>" + averageLatencyInLastMinute + "</td><td>" + averageLatencyInLastHour + "</td>" +
"<td>" + ZPagesActivityTracker.TotalErrorCount[spanName] + "</td><td>" + errorCountInLastMinute + "</td><td>" + errorCountInLastHour + "</td><td>" + dateTimeOffset + " GMT" + "</td></tr>");
}
writer.WriteLine("</tbody></table>");
writer.WriteLine("</div></div></body></html>");
}
}
catch (OperationCanceledException ex)
{
ZPagesExporterEventSource.Log.CanceledExport(ex);
}
catch (Exception ex)
{
ZPagesExporterEventSource.Log.FailedExport(ex);
}
finally
{
this.httpListener.Stop();
this.httpListener.Close();
}
}
}
}

View File

@ -1,117 +0,0 @@
// <copyright file="ZPagesProcessor.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
using System.Diagnostics;
using OpenTelemetry.Exporter.ZPages.Implementation;
using OpenTelemetry.Trace;
namespace OpenTelemetry.Exporter.ZPages
{
/// <summary>
/// Implements the zpages span processor that exports spans in OnEnd call without batching.
/// </summary>
public class ZPagesProcessor : BaseProcessor<Activity>
{
private readonly ZPagesExporter exporter;
/// <summary>
/// Initializes a new instance of the <see cref="ZPagesProcessor"/> class.
/// </summary>
/// <param name="exporter">Zpages Span processor instance.</param>
public ZPagesProcessor(ZPagesExporter exporter)
{
this.exporter = exporter;
}
/// <inheritdoc />
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;
}
}
/// <inheritdoc />
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);
}
}
}
}

View File

@ -16,7 +16,6 @@
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" />
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Prometheus.HttpListener" />
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.Zipkin" />
<TrimmerRootAssembly Include="OpenTelemetry.Exporter.ZPages" />
<TrimmerRootAssembly Include="OpenTelemetry.Extensions.Hosting" />
<TrimmerRootAssembly Include="OpenTelemetry.Extensions.Propagators" />
<TrimmerRootAssembly Include="OpenTelemetry.Instrumentation.AspNetCore" />

View File

@ -1,31 +0,0 @@
// <copyright file="EventSourceTest.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
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);
}
}
}

View File

@ -1,32 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<!-- this is temporary. will remove in future PR. -->
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.ZPages\OpenTelemetry.Exporter.ZPages.csproj" />
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\EventSourceTestHelper.cs" Link="EventSourceTestHelper.cs" />
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\TestActivityProcessor.cs" Link="TestActivityProcessor.cs" />
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\TestEventListener.cs" Link="TestEventListener.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>

View File

@ -1,43 +0,0 @@
// <copyright file="ZPagesActivityTrackerTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
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();
}
}
}

View File

@ -1,265 +0,0 @@
// <copyright file="ZPagesExporterTests.cs" company="OpenTelemetry Authors">
// 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.
// </copyright>
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<ActivityContext> options) => ActivitySamplingResult.AllData,
};
ActivitySource.AddActivityListener(listener);
}
[Fact]
public void CheckingBadArgs()
{
TracerProviderBuilder builder = null;
Assert.Throws<ArgumentNullException>(() => 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($"<td>Test Zipkin Activity 1</td>", content);
Assert.Contains($"<td>Test Zipkin Activity 2</td>", content);
zpagesProcessor.Dispose();
zpagesServer.Stop();
zpagesServer.Dispose();
exporter.Dispose();
}
internal static Activity CreateTestActivity(
bool setAttributes = true,
Dictionary<string, object> 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<string, object>
{
{ "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<ActivityEvent>
{
new ActivityEvent(
"Event1",
eventTimestamp,
new ActivityTagsCollection(new Dictionary<string, object>
{
{ "key", "value" },
})),
new ActivityEvent(
"Event2",
eventTimestamp,
new ActivityTagsCollection(new Dictionary<string, object>
{
{ "key", "value" },
})),
};
var linkedSpanId = ActivitySpanId.CreateFromString("888915b6286b9c41".AsSpan());
var activitySource = new ActivitySource(nameof(CreateTestActivity));
var tags = setAttributes ?
attributes.Select(kvp => new KeyValuePair<string, object>(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;
}
}
}