Skip to content

Commit

Permalink
Updated Jaeger & Zipkin exporters to check for default activity.Paren…
Browse files Browse the repository at this point in the history
…tSpanId (#1433)

* Updated Jaeger & Zipkin exporters to check for default activity.ParentSpanId.

* Tabs are less filling, but spaces taste great.

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
  • Loading branch information
CodeBlanch and cijothomas authored Nov 2, 2020
1 parent 985c537 commit ddac284
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 32 deletions.
9 changes: 9 additions & 0 deletions examples/AspNet/Examples.AspNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
Expand Down Expand Up @@ -100,6 +101,14 @@
<Project>{ae3e3df5-4083-4c6e-a840-8271b0acde7e}</Project>
<Name>OpenTelemetry</Name>
</ProjectReference>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj">
<Project>{1afff251-3b0c-47ca-be94-937083732c0a}</Project>
<Name>OpenTelemetry.Exporter.Console</Name>
</ProjectReference>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj">
<Project>{7edae7fa-b44e-42ca-80fa-7df2faa2c5dd}</Project>
<Name>OpenTelemetry.Exporter.Zipkin</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
Expand Down
76 changes: 68 additions & 8 deletions examples/AspNet/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
// </copyright>

using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
Expand All @@ -33,17 +37,34 @@ public class WebApiApplication : HttpApplication

protected void Application_Start()
{
this.tracerProvider = Sdk.CreateTracerProviderBuilder()
var builder = Sdk.CreateTracerProviderBuilder()
.AddAspNetInstrumentation(options => options.Propagator = new B3Propagator())
.AddHttpClientInstrumentation(
httpClientOptions => httpClientOptions.Propagator = new B3Propagator(),
httpWebRequestOptions => httpWebRequestOptions.Propagator = new B3Propagator())
.AddJaegerExporter(jaegerOptions =>
{
jaegerOptions.AgentHost = "localhost";
jaegerOptions.AgentPort = 6831;
})
.Build();
httpWebRequestOptions => httpWebRequestOptions.Propagator = new B3Propagator());

switch (ConfigurationManager.AppSettings["UseExporter"].ToLowerInvariant())
{
case "jaeger":
builder.AddJaegerExporter(jaegerOptions =>
{
jaegerOptions.AgentHost = ConfigurationManager.AppSettings["JaegerHost"];
jaegerOptions.AgentPort = int.Parse(ConfigurationManager.AppSettings["JaegerPort"]);
});
break;
case "zipkin":
builder.AddZipkinExporter(zipkinOptions =>
{
zipkinOptions.Endpoint = new Uri(ConfigurationManager.AppSettings["ZipkinEndpoint"]);
});
break;
default:
Console.SetOut(new DebugStreamWriter());
builder.AddConsoleExporter();
break;
}

this.tracerProvider = builder.Build();

GlobalConfiguration.Configure(WebApiConfig.Register);

Expand All @@ -55,5 +76,44 @@ protected void Application_End()
{
this.tracerProvider?.Dispose();
}

private class DebugStreamWriter : StreamWriter
{
public DebugStreamWriter()
: base(new DebugStream(), Encoding.Unicode, 1024)
{
this.AutoFlush = true;
}

private sealed class DebugStream : Stream
{
public override bool CanRead => false;

public override bool CanSeek => false;

public override bool CanWrite => true;

public override long Length => throw new NotSupportedException();

public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}

public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();

public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();

public override void SetLength(long value) => throw new NotSupportedException();

public override void Write(byte[] buffer, int offset, int count)
{
Debug.Write(Encoding.Unicode.GetString(buffer, offset, count));
}

public override void Flush() => Debug.Flush();
}
}
}
}
24 changes: 20 additions & 4 deletions examples/AspNet/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<add key="webpages:Enabled" value="false"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
<add key="UseExporter" value="console"/>
<add key="JaegerHost" value="localhost"/>
<add key="JaegerPort" value="6831"/>
<add key="ZipkinEndpoint" value="http://localhost:9411/api/v2/spans"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.8"/>
Expand All @@ -23,14 +27,26 @@
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ public static JaegerSpan ToJaegerSpan(this Activity activity)
// TODO: The check above should be enforced by the usage of the exporter. Perhaps enforce at higher-level.
traceId = new Int128(activity.TraceId);
spanId = new Int128(activity.SpanId);
parentSpanId = new Int128(activity.ParentSpanId);
if (activity.ParentSpanId != default)
{
parentSpanId = new Int128(activity.ParentSpanId);
}
}

return new JaegerSpan(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ internal static class ZipkinActivityConversionExtensions
private const long UnixEpochTicks = 621355968000000000L; // = DateTimeOffset.FromUnixTimeMilliseconds(0).Ticks
private const long UnixEpochMicroseconds = UnixEpochTicks / TicksPerMicrosecond;

private static readonly string InvalidSpanId = default(ActivitySpanId).ToHexString();

#if !NET452
private static readonly ConcurrentDictionary<(string, int), ZipkinEndpoint> RemoteEndpointCache = new ConcurrentDictionary<(string, int), ZipkinEndpoint>();
#else
Expand All @@ -41,11 +39,9 @@ internal static ZipkinSpan ToZipkinSpan(this Activity activity, ZipkinEndpoint l
{
var context = activity.Context;

string parentId = EncodeSpanId(activity.ParentSpanId);
if (string.Equals(parentId, InvalidSpanId, StringComparison.Ordinal))
{
parentId = null;
}
string parentId = activity.ParentSpanId == default ?
null
: EncodeSpanId(activity.ParentSpanId);

var tagState = new TagEnumerationState
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ static JaegerActivityConversionTest()
ActivitySource.AddActivityListener(listener);
}

[Fact]
public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_AllPropertiesSet()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void JaegerActivityConverterTest_ConvertActivityToJaegerSpan_AllPropertiesSet(bool isRootSpan)
{
var activity = CreateTestActivity();
var activity = CreateTestActivity(isRootSpan: isRootSpan);
var traceIdAsInt = new Int128(activity.Context.TraceId);
var spanIdAsInt = new Int128(activity.Context.SpanId);
var linkTraceIdAsInt = new Int128(activity.Links.Single().Context.TraceId);
Expand Down Expand Up @@ -438,14 +440,15 @@ internal static Activity CreateTestActivity(
bool addEvents = true,
bool addLinks = true,
Resource resource = null,
ActivityKind kind = ActivityKind.Client)
ActivityKind kind = ActivityKind.Client,
bool isRootSpan = false)
{
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 parentSpanId = isRootSpan ? default : ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 });

var attributes = new Dictionary<string, object>
{
Expand Down
18 changes: 11 additions & 7 deletions test/OpenTelemetry.Exporter.Zipkin.Tests/ZipkinExporterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,11 @@ public void SuppresssesInstrumentation()
}

[Theory]
[InlineData(true, false)]
[InlineData(false, false)]
[InlineData(false, true)]
public void IntegrationTest(bool useShortTraceIds, bool useTestResource)
[InlineData(true, false, false)]
[InlineData(false, false, false)]
[InlineData(false, true, false)]
[InlineData(false, false, true)]
public void IntegrationTest(bool useShortTraceIds, bool useTestResource, bool isRootSpan)
{
Guid requestId = Guid.NewGuid();

Expand All @@ -149,7 +150,7 @@ public void IntegrationTest(bool useShortTraceIds, bool useTestResource)

var serviceName = ZipkinExporterOptions.DefaultServiceName;
var resoureTags = string.Empty;
var activity = CreateTestActivity();
var activity = CreateTestActivity(isRootSpan: isRootSpan);
if (useTestResource)
{
serviceName = "MyService";
Expand Down Expand Up @@ -183,14 +184,17 @@ public void IntegrationTest(bool useShortTraceIds, bool useTestResource)
ipInformation.Append($@",""ipv6"":""{exporter.LocalEndpoint.Ipv6}""");
}

var parentId = isRootSpan ? string.Empty : $@"""parentId"":""{ZipkinActivityConversionExtensions.EncodeSpanId(activity.ParentSpanId)}"",";

var traceId = useShortTraceIds ? TraceId.Substring(TraceId.Length - 16, 16) : TraceId;

Assert.Equal(
$@"[{{""traceId"":""{traceId}"",""name"":""Name"",""parentId"":""{ZipkinActivityConversionExtensions.EncodeSpanId(activity.ParentSpanId)}"",""id"":""{ZipkinActivityConversionExtensions.EncodeSpanId(context.SpanId)}"",""kind"":""CLIENT"",""timestamp"":{timestamp},""duration"":60000000,""localEndpoint"":{{""serviceName"":""{serviceName}""{ipInformation}}},""remoteEndpoint"":{{""serviceName"":""http://localhost:44312/""}},""annotations"":[{{""timestamp"":{eventTimestamp},""value"":""Event1""}},{{""timestamp"":{eventTimestamp},""value"":""Event2""}}],""tags"":{{{resoureTags}""stringKey"":""value"",""longKey"":""1"",""longKey2"":""1"",""doubleKey"":""1"",""doubleKey2"":""1"",""longArrayKey"":""1,2"",""boolKey"":""True"",""http.host"":""http://localhost:44312/"",""library.name"":""CreateTestActivity"",""peer.service"":""http://localhost:44312/""}}}}]",
$@"[{{""traceId"":""{traceId}"",""name"":""Name"",{parentId}""id"":""{ZipkinActivityConversionExtensions.EncodeSpanId(context.SpanId)}"",""kind"":""CLIENT"",""timestamp"":{timestamp},""duration"":60000000,""localEndpoint"":{{""serviceName"":""{serviceName}""{ipInformation}}},""remoteEndpoint"":{{""serviceName"":""http://localhost:44312/""}},""annotations"":[{{""timestamp"":{eventTimestamp},""value"":""Event1""}},{{""timestamp"":{eventTimestamp},""value"":""Event2""}}],""tags"":{{{resoureTags}""stringKey"":""value"",""longKey"":""1"",""longKey2"":""1"",""doubleKey"":""1"",""doubleKey2"":""1"",""longArrayKey"":""1,2"",""boolKey"":""True"",""http.host"":""http://localhost:44312/"",""library.name"":""CreateTestActivity"",""peer.service"":""http://localhost:44312/""}}}}]",
Responses[requestId]);
}

internal static Activity CreateTestActivity(
bool isRootSpan = false,
bool setAttributes = true,
Dictionary<string, object> additionalAttributes = null,
bool addEvents = true,
Expand All @@ -203,7 +207,7 @@ internal static Activity CreateTestActivity(
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 parentSpanId = isRootSpan ? default : ActivitySpanId.CreateFromBytes(new byte[] { 12, 23, 34, 45, 56, 67, 78, 89 });

var attributes = new Dictionary<string, object>
{
Expand Down

0 comments on commit ddac284

Please sign in to comment.