Skip to content

Commit

Permalink
Initial ideal how to refactor provider (#1008)
Browse files Browse the repository at this point in the history
* initial ideal how to refactor provider

* dumping more ideas

* more improvements

* update example

* improve perf when no sampler is specified

* put more examples

* composite processor

* update the tutorial

* more check

* nit

* update tutorial
  • Loading branch information
reyang authored Aug 6, 2020
1 parent 73bff75 commit c4484a7
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 46 deletions.
10 changes: 7 additions & 3 deletions docs/trace/building-your-own-exporter/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ public class Program

public static void Main()
{
using var otel = Sdk.CreateTracerProvider(b => b
.AddActivitySource("MyCompany.MyProduct.MyLibrary")
.UseMyExporter());
using var tracerProvider = Sdk.CreateTracerProvider(
new string[]
{
"MyCompany.MyProduct.MyLibrary",
})
.AddMyExporter();

using (var activity = MyActivitySource.StartActivity("SayHello"))
{
activity?.SetTag("foo", 1);
activity?.SetTag("bar", "Hello, World!");
activity?.SetTag("baz", new int[] { 1, 2, 3 });
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="TracerProviderBuilderExtensions.cs" company="OpenTelemetry Authors">
// <copyright file="TracerProviderExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -17,15 +17,10 @@
using System;
using OpenTelemetry.Trace;

internal static class TracerProviderBuilderExtensions
internal static class TracerProviderExtensions
{
public static TracerProviderBuilder UseMyExporter(this TracerProviderBuilder builder)
public static TracerProvider AddMyExporter(this TracerProvider provider)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

return builder.AddProcessorPipeline(p => p.SetExporter(new MyExporter()));
return provider?.AddProcessor(new SimpleActivityProcessor(new MyExporter()));
}
}
19 changes: 9 additions & 10 deletions docs/trace/building-your-own-processor/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,19 @@ public class Program

public static void Main()
{
using var otel = Sdk.CreateTracerProvider(b => b
.AddActivitySource("MyCompany.MyProduct.MyLibrary")
using var tracerProvider = Sdk.CreateTracerProvider(
new string[]
{
"MyCompany.MyProduct.MyLibrary",
})
.AddProcessor(new MyActivityProcessor("A"))
.AddProcessor(new MyActivityProcessor("B"));

// TODO: seems buggy as ShutdownAsync is called 6 times
// TODO: need to discuss the expectation, currently FlushAsync is not called by default
// TODO: should the dispose order be C, B, A or A, B C?
.AddProcessorPipeline(p => p.AddProcessor(current => new MyActivityProcessor("A")))
.AddProcessorPipeline(p => p.AddProcessor(current => new MyActivityProcessor("B")))
.AddProcessorPipeline(p => p.AddProcessor(current => new MyActivityProcessor("C"))));

using (var activity = MyActivitySource.StartActivity("SayHello"))
using (var activity = MyActivitySource.StartActivity("Foo"))
{
activity?.SetTag("foo", 1);
activity?.SetTag("bar", "Hello, World!");
activity?.SetTag("baz", new int[] { 1, 2, 3 });
}
}
}
12 changes: 8 additions & 4 deletions docs/trace/building-your-own-sampler/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Exporter.Console;
using OpenTelemetry.Trace;

public class Program
Expand All @@ -25,10 +26,13 @@ public class Program

public static void Main()
{
using var otel = Sdk.CreateTracerProvider(b => b
.AddActivitySource("MyCompany.MyProduct.MyLibrary")
.SetSampler(new MySampler()) // TODO: it is NOT working at this moment
.UseConsoleExporter());
using var tracerProvider = Sdk.CreateTracerProvider(
new string[]
{
"MyCompany.MyProduct.MyLibrary",
},
new MySampler())
.AddProcessor(new SimpleActivityProcessor(new ConsoleExporter(new ConsoleExporterOptions())));

using (var activity = MyActivitySource.StartActivity("SayHello"))
{
Expand Down
11 changes: 8 additions & 3 deletions docs/trace/getting-started/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Exporter.Console;
using OpenTelemetry.Trace;

public class Program
Expand All @@ -25,9 +26,13 @@ public class Program

public static void Main()
{
using var otel = Sdk.CreateTracerProvider(b => b
.AddActivitySource("MyCompany.MyProduct.MyLibrary")
.UseConsoleExporter());
using var tracerProvider = Sdk.CreateTracerProvider(
new string[]
{
"MyCompany.MyProduct.MyLibrary",
});

tracerProvider.AddProcessor(new SimpleActivityProcessor(new ConsoleExporter(new ConsoleExporterOptions())));

using (var activity = MyActivitySource.StartActivity("SayHello"))
{
Expand Down
89 changes: 73 additions & 16 deletions src/OpenTelemetry/Sdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand All @@ -22,6 +23,7 @@
using OpenTelemetry.Context;
using OpenTelemetry.Metrics;
using OpenTelemetry.Metrics.Export;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using OpenTelemetry.Trace.Internal;
using OpenTelemetry.Trace.Samplers;
Expand Down Expand Up @@ -161,30 +163,85 @@ public static TracerProvider CreateTracerProvider(Action<TracerProviderBuilder>
return tracerProviderSdk;
}

public static TracerProvider CreateTracerProvider(IEnumerable<string> sources, Sampler sampler = null, Resource resource = null)
{
var activitySources = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);

foreach (var name in sources)
{
activitySources[name] = true;
}

var provider = new TracerProviderSdk
{
Resource = resource,
Sampler = sampler,
};

provider.ActivityListener = new ActivityListener
{
// Callback when Activity is started.
ActivityStarted = (activity) =>
{
if (activity.IsAllDataRequested)
{
activity.SetResource(resource);
}

provider.ActivityProcessor?.OnStart(activity);
},

// Callback when Activity is stopped.
ActivityStopped = (activity) =>
{
provider.ActivityProcessor?.OnEnd(activity);
},

// Function which takes ActivitySource and returns true/false to indicate if it should be subscribed to
// or not.
ShouldListenTo = (activitySource) => activitySources.ContainsKey(activitySource.Name),

// Setting this to true means TraceId will be always
// available in sampling callbacks and will be the actual
// traceid used, if activity ends up getting created.
AutoGenerateRootContextTraceId = true,

// This delegate informs ActivitySource about sampling decision when the parent context is an ActivityContext.
GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> options) => ComputeActivityDataRequest(options, sampler),
};

ActivitySource.AddActivityListener(provider.ActivityListener);

return provider;
}

internal static ActivityDataRequest ComputeActivityDataRequest(
in ActivityCreationOptions<ActivityContext> options,
Sampler sampler)
{
var isRootSpan = /*TODO: Put back once AutoGenerateRootContextTraceId is removed.
options.Parent.TraceId == default ||*/ options.Parent.SpanId == default;

// As we set ActivityListener.AutoGenerateRootContextTraceId = true,
// Parent.TraceId will always be the TraceId of the to-be-created Activity,
// if it get created.
ActivityTraceId traceId = options.Parent.TraceId;

var samplingParameters = new SamplingParameters(
options.Parent,
traceId,
options.Name,
options.Kind,
options.Tags,
options.Links);

var shouldSample = sampler.ShouldSample(samplingParameters);
if (shouldSample.IsSampled)
if (sampler != null)
{
return ActivityDataRequest.AllDataAndRecorded;
// As we set ActivityListener.AutoGenerateRootContextTraceId = true,
// Parent.TraceId will always be the TraceId of the to-be-created Activity,
// if it get created.
ActivityTraceId traceId = options.Parent.TraceId;

var samplingParameters = new SamplingParameters(
options.Parent,
traceId,
options.Name,
options.Kind,
options.Tags,
options.Links);

var shouldSample = sampler.ShouldSample(samplingParameters);
if (shouldSample.IsSampled)
{
return ActivityDataRequest.AllDataAndRecorded;
}
}

// If it is the root span select PropagationData so the trace ID is preserved
Expand Down
Loading

0 comments on commit c4484a7

Please sign in to comment.