Skip to content

Commit

Permalink
Step 1 - Use new Activity to Replace OT Span (#660)
Browse files Browse the repository at this point in the history
  • Loading branch information
cijothomas authored May 13, 2020
1 parent 92963a3 commit 44b3a43
Show file tree
Hide file tree
Showing 13 changed files with 801 additions and 6 deletions.
12 changes: 10 additions & 2 deletions samples/Exporters/Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class Program
/// <param name="args">Arguments from command line.</param>
public static void Main(string[] args)
{
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, HttpClientOptions, ZPagesOptions, ConsoleOptions, OtlpOptions>(args)
Parser.Default.ParseArguments<JaegerOptions, ZipkinOptions, PrometheusOptions, HttpClientOptions, ZPagesOptions, ConsoleOptions, ConsoleActivityOptions, OtlpOptions>(args)
.MapResult(
(JaegerOptions options) => TestJaeger.Run(options.Host, options.Port),
(ZipkinOptions options) => TestZipkin.Run(options.Uri),
Expand All @@ -46,6 +46,7 @@ public static void Main(string[] args)
(RedisOptions options) => TestRedis.Run(options.Uri),
(ZPagesOptions options) => TestZPages.Run(),
(ConsoleOptions options) => TestConsole.Run(options),
(ConsoleActivityOptions options) => TestConsoleActivity.Run(options),
(OtlpOptions options) => TestOtlp.Run(options.Endpoint),
errs => 1);

Expand Down Expand Up @@ -105,10 +106,17 @@ internal class ZPagesOptions
[Verb("console", HelpText = "Specify the options required to test console exporter")]
internal class ConsoleOptions
{
[Option('p', "pretty", HelpText = "Specify if the output should be pretty printed (default: false)", Default = false)]
[Option('p', "pretty", HelpText = "Specify if the output should be pretty printed (default: true)", Default = true)]
public bool Pretty { get; set; }
}

[Verb("consoleactivity", HelpText = "Specify the options required to test console activity exporter")]
internal class ConsoleActivityOptions
{
[Option('p', "displayasjson", HelpText = "Specify if the output should be displayed as json or not (default: false)", Default = false)]
public bool DisplayAsJson { get; set; }
}

[Verb("otlp", HelpText = "Specify the options required to test OpenTelemetry Protocol (OTLP)")]
internal class OtlpOptions
{
Expand Down
23 changes: 19 additions & 4 deletions samples/Exporters/Console/TestConsole.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
// <auto-generated/>
// <copyright file="TestConsole.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.Trace.Configuration;
using OpenTelemetry.Exporter.Console;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Configuration;

namespace Samples
{
Expand All @@ -13,14 +27,15 @@ internal static object Run(ConsoleOptions options)
// map test project settings to ConsoleExporterSetting
var exporterOptions = new ConsoleExporterOptions
{
Pretty = options.Pretty
Pretty = options.Pretty,
};

// create exporter
var exporter = new ConsoleExporter(exporterOptions);

// Create tracer
using var tracerFactory = TracerFactory.Create(builder => {
using var tracerFactory = TracerFactory.Create(builder =>
{
builder.AddProcessorPipeline(p => p.SetExporter(exporter));
});
var tracer = tracerFactory.GetTracer("console-test");
Expand Down
89 changes: 89 additions & 0 deletions samples/Exporters/Console/TestConsoleActivity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// <copyright file="TestConsoleActivity.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.Diagnostics;
using OpenTelemetry.Exporter.Console;
using OpenTelemetry.Trace.Configuration;

namespace Samples
{
internal class TestConsoleActivity
{
internal static object Run(ConsoleActivityOptions options)
{
// Enable OpenTelemetry for the source "MyCompany.MyProduct.MyWebServer"
// and use Console exporter
OpenTelemetrySdk.EnableOpenTelemetry(
(builder) => builder.AddActivitySource("MyCompany.MyProduct.MyWebServer")
.UseConsoleActivityExporter(opt => opt.DisplayAsJson = options.DisplayAsJson));

// The above line is required only in Applications
// which decide to use OT.

// Libraries would simply write the following lines of code to
// emit activities, which are the .NET representation of OT Spans.
var source = new ActivitySource("MyCompany.MyProduct.MyWebServer");

// The below commented out line shows more likely code in a real world webserver.
// using (var parent = source.StartActivity("HttpIn", ActivityKind.Server, HttpContext.Request.Headers["traceparent"] ))
using (var parent = source.StartActivity("HttpIn", ActivityKind.Server))
{
// TagNames can follow the OT guidelines
// from https://github.com/open-telemetry/opentelemetry-specification/tree/master/specification/trace/semantic_conventions
parent?.AddTag("http.method", "GET");
parent?.AddTag("http.host", "MyHostName");
if (parent != null)
{
parent.DisplayName = "HttpIn DisplayName";
}

try
{
// Actual code to achieve the purpose of the library.
// For websebserver example, this would be calling
// user middlware pipeline.

// There can be child activities.
// In this example HttpOut is a child of HttpIn.
using (var child = source.StartActivity("HttpOut", ActivityKind.Client))
{
child?.AddTag("http.url", "www.mydependencyapi.com");
try
{
// do actual work.

child?.AddEvent(new ActivityEvent("sample activity event."));
child?.AddTag("http.status_code", "200");
}
catch (Exception)
{
child?.AddTag("http.status_code", "500");
}
}

parent?.AddTag("http.status_code", "200");
}
catch (Exception)
{
parent?.AddTag("http.status_code", "500");
}
}

return null;
}
}
}
97 changes: 97 additions & 0 deletions src/OpenTelemetry.Exporter.Console/ConsoleActivityExporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// <copyright file="ConsoleActivityExporter.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.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Trace.Export;

namespace OpenTelemetry.Exporter.Console
{
public class ConsoleActivityExporter : ActivityExporter
{
private readonly JsonSerializerOptions serializerOptions;
private bool displayAsJson;

public ConsoleActivityExporter(ConsoleActivityExporterOptions options)
{
this.serializerOptions = new JsonSerializerOptions()
{
WriteIndented = true,
};

this.displayAsJson = options.DisplayAsJson;

this.serializerOptions.Converters.Add(new JsonStringEnumConverter());
this.serializerOptions.Converters.Add(new ActivitySpanIdConverter());
this.serializerOptions.Converters.Add(new ActivityTraceIdConverter());
}

public override Task<ExportResult> ExportAsync(IEnumerable<Activity> activityBatch, CancellationToken cancellationToken)
{
foreach (var activity in activityBatch)
{
if (this.displayAsJson)
{
System.Console.WriteLine(JsonSerializer.Serialize(activity, this.serializerOptions));
}
else
{
System.Console.WriteLine("Activity ID - " + activity.Id);
if (!string.IsNullOrEmpty(activity.ParentId))
{
System.Console.WriteLine("Activity ParentId - " + activity.ParentId);
}

System.Console.WriteLine("Activity OperationName - " + activity.OperationName);
System.Console.WriteLine("Activity DisplayName - " + activity.DisplayName);
System.Console.WriteLine("Activity StartTime - " + activity.StartTimeUtc);
System.Console.WriteLine("Activity Duration - " + activity.Duration);
if (activity.Tags.Count() > 0)
{
System.Console.WriteLine("Activity Tags");
foreach (var tag in activity.Tags)
{
System.Console.WriteLine($"\t {tag.Key} : {tag.Value}");
}
}

if (activity.Events.Any())
{
System.Console.WriteLine("Activity Events");
foreach (var activityEvent in activity.Events)
{
System.Console.WriteLine($"Event Name: {activityEvent.Name} TimeStamp: {activityEvent.Timestamp}");
}
}

System.Console.WriteLine("\n");
}
}

return Task.FromResult(ExportResult.Success);
}

public override Task ShutdownAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// <copyright file="ConsoleActivityExporterOptions.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.Console
{
public class ConsoleActivityExporterOptions
{
public bool DisplayAsJson { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// <copyright file="OpenTelemetryBuilderExtensions.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 OpenTelemetry.Trace.Configuration;

namespace OpenTelemetry.Exporter.Console
{
public static class OpenTelemetryBuilderExtensions
{
/// <summary>
/// Registers a ConsoleActivity exporter.
/// </summary>
/// <param name="builder">Open Telemetry builder to use.</param>
/// <param name="configure">Exporter configuration options.</param>
/// <returns>The instance of <see cref="OpenTelemetryBuilder"/> to chain the calls.</returns>
public static OpenTelemetryBuilder UseConsoleActivityExporter(this OpenTelemetryBuilder builder, Action<ConsoleActivityExporterOptions> configure)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}

var exporterOptions = new ConsoleActivityExporterOptions();
configure(exporterOptions);
var consoleExporter = new ConsoleActivityExporter(exporterOptions);
return builder.SetProcessorPipeline(pipeline => pipeline.SetExporter(consoleExporter));
}
}
}
Loading

0 comments on commit 44b3a43

Please sign in to comment.