Skip to content

Commit

Permalink
Merge branch 'master' into cijothomas/activity3adapter1a_alternate
Browse files Browse the repository at this point in the history
  • Loading branch information
cijothomas committed Jun 2, 2020
2 parents 170ad87 + 0867c66 commit 0832e71
Show file tree
Hide file tree
Showing 8 changed files with 468 additions and 26 deletions.
44 changes: 33 additions & 11 deletions samples/Exporters/Console/TestZPages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System;
using System.Threading;
using OpenTelemetry.Exporter.ZPages;
using OpenTelemetry.Exporter.ZPages.Implementation;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Configuration;
using OpenTelemetry.Trace.Export;
Expand All @@ -29,28 +30,49 @@ internal static object Run()
{
var zpagesOptions = new ZPagesExporterOptions() { Url = "http://localhost:7284/rpcz/" };
var zpagesExporter = new ZPagesExporter(zpagesOptions);
var spanProcessor = new SimpleSpanProcessor(zpagesExporter);
var spanProcessor = new ZPagesSpanProcessor(zpagesExporter);
ZPagesSpans.RetentionTime = 3600000;
var httpServer = new ZPagesExporterStatsHttpServer(zpagesExporter, spanProcessor);

// Start the server
httpServer.Start();

// Configure exporter
using var tracerFactory = TracerFactory.Create(builder => builder
using (var tracerFactory = TracerFactory.Create(builder => builder
.AddProcessorPipeline(b => b
.SetExporter(zpagesExporter)
.SetExportingProcessor(e => spanProcessor)));
var tracer = tracerFactory.GetTracer("zpages-test");

while (true)
.SetExportingProcessor(e => spanProcessor))))
{
// Create a scoped span. It will end automatically when using statement ends
using (tracer.WithSpan(tracer.StartSpan("Main")))
var tracer = tracerFactory.GetTracer("zpages-test");

while (true)
{
Console.WriteLine("Starting Span");
}
// Create a scoped span.
TelemetrySpan telemetrySpan = tracer.StartSpan("Main");
telemetrySpan.Status = Status.Unavailable;

using (tracer.WithSpan(telemetrySpan))
{
Console.WriteLine("Starting Span");
}

Thread.Sleep(3000);

Thread.Sleep(500);
telemetrySpan.End();

// Create a scoped span.
TelemetrySpan telemetrySpan2 = tracer.StartSpan("TestSpan");
telemetrySpan2.Status = Status.Ok;

using (tracer.WithSpan(telemetrySpan2))
{
Console.WriteLine("Starting Span2");
}

Thread.Sleep(5000);

telemetrySpan2.End();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// <copyright file="ZPagesSpanInformation.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;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using OpenTelemetry.Trace.Export;

namespace OpenTelemetry.Exporter.ZPages.Implementation
{
/// <summary>
/// Stores the span information aggregated according to span name.
/// </summary>
public class ZPagesSpanInformation
{
/// <summary>
/// Initializes a new instance of the <see cref="ZPagesSpanInformation"/> class.
/// </summary>
public ZPagesSpanInformation()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ZPagesSpanInformation"/> class when span data is provided.
/// </summary>
/// <param name="spanData">Input span data to be used for initialization.</param>
public ZPagesSpanInformation(SpanData spanData)
{
this.Name = spanData.Name;
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 span.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Gets or sets the total count of the span.
/// </summary>
public long Count { get; set; }

/// <summary>
/// Gets or sets the total count of the ended span.
/// </summary>
public long EndedCount { get; set; }

/// <summary>
/// Gets or sets the total error count of the span.
/// </summary>
public long ErrorCount { get; set; }

/// <summary>
/// Gets or sets the total average latency of the span.
/// </summary>
public long AvgLatencyTotal { get; set; }

/// <summary>
/// Gets or sets the total latency of all spans.
/// </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;
}
}
}
123 changes: 123 additions & 0 deletions src/OpenTelemetry.Exporter.ZPages/Implementation/ZPagesSpans.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// <copyright file="ZPagesSpans.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;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Timers;

namespace OpenTelemetry.Exporter.ZPages.Implementation
{
/// <summary>
/// Implements the ZPages Span Queue which stores all the required span information.
/// </summary>
public static class ZPagesSpans
{
private static long startTime;

/// <summary>
/// Initializes static members of the <see cref="ZPagesSpans"/> class.
/// </summary>
static ZPagesSpans()
{
ZQueue = new LinkedList<Dictionary<string, ZPagesSpanInformation>>();
ProcessingSpanList = new Dictionary<string, long>();
CurrentMinuteSpanList = new ConcurrentDictionary<string, ZPagesSpanInformation>();
CurrentHourSpanList = new ConcurrentDictionary<string, ZPagesSpanInformation>();
TotalSpanCount = new Dictionary<string, long>();
TotalEndedSpanCount = new Dictionary<string, long>();
TotalSpanErrorCount = new Dictionary<string, long>();
TotalSpanLatency = new Dictionary<string, long>();
startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
}

/// <summary>
/// Gets or sets ZQueue which stores the minute-wise span information.
/// </summary>
public static LinkedList<Dictionary<string, ZPagesSpanInformation>> ZQueue { get; set; }

/// <summary>
/// Gets or sets the current minute span information list.
/// </summary>
public static ConcurrentDictionary<string, ZPagesSpanInformation> CurrentMinuteSpanList { get; set; }

/// <summary>
/// Gets or sets the current hour span information list.
/// </summary>
public static ConcurrentDictionary<string, ZPagesSpanInformation> CurrentHourSpanList { get; set; }

/// <summary>
/// Gets or sets the processing span information list. This holds the names of the spans which have not ended yet, along with the active count.
/// </summary>
public static Dictionary<string, long> ProcessingSpanList { get; set; }

/// <summary>
/// Gets or sets the count of spans name-wise.
/// </summary>
public static Dictionary<string, long> TotalSpanCount { get; set; }

/// <summary>
/// Gets or sets the count of ended spans name-wise.
/// </summary>
public static Dictionary<string, long> TotalEndedSpanCount { get; set; }

/// <summary>
/// Gets or sets the count of span errors according to span name.
/// </summary>
public static Dictionary<string, long> TotalSpanErrorCount { get; set; }

/// <summary>
/// Gets or sets the total latency of spans name-wise.
/// </summary>
public static Dictionary<string, long> TotalSpanLatency { 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 span information list to ZQueue
ZQueue.AddFirst(new Dictionary<string, ZPagesSpanInformation>(CurrentMinuteSpanList));

// Clear the current minute span list to start recording new spans only
CurrentMinuteSpanList.Clear();

// Remove the stale span 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 span information list
CurrentHourSpanList.Clear();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ namespace OpenTelemetry.Exporter.ZPages.Implementation
{
internal class ZPagesStatsBuilder
{
public const string ContentType = "text/plain; version = 0.0.4";
public const string ContentType = "text/html";
}
}
19 changes: 19 additions & 0 deletions src/OpenTelemetry.Exporter.ZPages/ZPagesExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using OpenTelemetry.Exporter.ZPages.Implementation;
using OpenTelemetry.Trace.Export;
using Timer = System.Timers.Timer;

namespace OpenTelemetry.Exporter.ZPages
{
Expand All @@ -26,6 +32,8 @@ namespace OpenTelemetry.Exporter.ZPages
public class ZPagesExporter : SpanExporter
{
internal readonly ZPagesExporterOptions Options;
private Timer minuteTimer;
private Timer hourTimer;

/// <summary>
/// Initializes a new instance of the <see cref="ZPagesExporter"/> class.
Expand All @@ -34,11 +42,22 @@ public class ZPagesExporter : SpanExporter
public ZPagesExporter(ZPagesExporterOptions options)
{
this.Options = options;

// Create a timer with one minute interval
this.minuteTimer = new Timer(60000);
this.minuteTimer.Elapsed += new ElapsedEventHandler(ZPagesSpans.PurgeCurrentMinuteData);
this.minuteTimer.Enabled = true;

// Create a timer with one hour interval
this.hourTimer = new Timer(3600000);
this.hourTimer.Elapsed += new ElapsedEventHandler(ZPagesSpans.PurgeCurrentHourData);
this.hourTimer.Enabled = true;
}

/// <inheritdoc />
public override Task<ExportResult> ExportAsync(IEnumerable<SpanData> batch, CancellationToken cancellationToken)
{
var spanDatas = batch as SpanData[] ?? batch.ToArray();
return Task.FromResult(ExportResult.Success);
}

Expand Down

0 comments on commit 0832e71

Please sign in to comment.