Skip to content

Commit

Permalink
Handle 128 bits trace Ids
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Hugues Jeanneret committed Jul 19, 2017
1 parent fe99ad4 commit 1c12086
Show file tree
Hide file tree
Showing 19 changed files with 631 additions and 392 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Compile Include="T_TraceManager.cs" />
<Compile Include="Utils\T_NumberUtils.cs" />
<Compile Include="Utils\T_TimeUtils.cs" />
<Compile Include="T_SpanState.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Criteo.Profiling.Tracing\Criteo.Profiling.Tracing.csproj">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ public void RecordShouldnotBeDispatchedIfStopped()
public void RecordsShouldBeDispatchedInOrder()
{
var sync = new CountdownEvent(2);

var firstRecord = new Record(new SpanState(1, 0, 1, SpanFlags.None), TimeUtils.UtcNow, Annotations.ClientRecv());
var secondRecord = new Record(new SpanState(1, 0, 1, SpanFlags.None), TimeUtils.UtcNow, Annotations.ClientRecv());
var traceId = 1;
var firstRecord = new Record(new SpanState(traceId, 0, 1, SpanFlags.None), TimeUtils.UtcNow, Annotations.ClientRecv());
var secondRecord = new Record(new SpanState(traceId, 0, 1, SpanFlags.None), TimeUtils.UtcNow, Annotations.ClientRecv());

var queue = new ConcurrentQueue<Record>();

Expand Down
68 changes: 68 additions & 0 deletions zipkin4net/Criteo.Profiling.Tracing.UTest/T_SpanState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using NUnit.Framework;

namespace Criteo.Profiling.Tracing.UTest
{
[TestFixture]
public class T_SpanState
{
private const long traceIdHigh = SpanState.NoTraceIdHigh;
private const long traceId = 1;
private const long spanId = 1;
private const SpanFlags flags = SpanFlags.None;

[Test]
public void HashCodeShouldVaryIfTraceIdsAreNotEqual()
{
var spanState1 = new SpanState(traceIdHigh, 1, null, spanId, flags);
var spanState2 = new SpanState(traceIdHigh, 2, null, spanId, flags);
Assert.AreNotEqual(spanState1.GetHashCode(), spanState2.GetHashCode());
}

[Test]
public void EqualsShouldReturnFalseIfTraceIdsAreNotEqual()
{
var spanState1 = new SpanState(traceIdHigh, 1, null, spanId, flags);
var spanState2 = new SpanState(traceIdHigh, 2, null, spanId, flags);
Assert.AreNotEqual(spanState1, spanState2);
}

[Test]
public void HashCodeShouldVaryIfTraceIdHighsAreNotEqual()
{
var spanState1 = new SpanState(1, traceId, null, spanId, flags);
var spanState2 = new SpanState(2, traceId, null, spanId, flags);
Assert.AreNotEqual(spanState1.GetHashCode(), spanState2.GetHashCode());
}

[Test]
public void EqualsShouldReturnFalseIfTraceIdHighsAreNotEqual()
{
var spanState1 = new SpanState(1, traceId, null, spanId, flags);
var spanState2 = new SpanState(2, traceId, null, spanId, flags);
Assert.AreNotEqual(spanState1, spanState2);
}

[Test]
public void HashCodeShouldVaryIfSpanIdsAreNotEqual()
{
var spanState1 = new SpanState(traceIdHigh, traceId, null, 1, flags);
var spanState2 = new SpanState(traceIdHigh, traceId, null, 2, flags);
Assert.AreNotEqual(spanState1.GetHashCode(), spanState2.GetHashCode());
}

[Test]
public void EqualsShouldReturnFalseIfSpanIdsAreNotEqual()
{
var spanState1 = new SpanState(traceIdHigh, traceId, null, 1, flags);
var spanState2 = new SpanState(traceIdHigh, traceId, null, 2, flags);
Assert.AreNotEqual(spanState1, spanState2);
}

[Test]
public void TraceIdHighDefaultToZero()
{
var spanState = new SpanState(traceId, null, spanId, flags);
Assert.AreEqual(SpanState.NoTraceIdHigh, spanState.TraceIdHigh);
}
}
}
18 changes: 17 additions & 1 deletion zipkin4net/Criteo.Profiling.Tracing.UTest/T_Trace.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
#if !NET_CORE
using System.Runtime.Serialization.Formatters.Binary;
Expand All @@ -19,6 +19,7 @@ public void SetUp()
{
TraceManager.ClearTracers();
TraceManager.Stop();
TraceManager.Trace128Bits = false;
}

[Test]
Expand Down Expand Up @@ -127,5 +128,20 @@ public void FlagUnsetShouldForwardForBackwardCompatibility()
dispatcher.Verify(d => d.Dispatch(It.IsAny<Record>()), Times.Once());
}

[Test]
public void TraceIdHighIsGeneratedIf128BitsActivated()
{
TraceManager.Trace128Bits = true;
var trace = Trace.Create();
Assert.AreNotEqual(SpanState.NoTraceIdHigh, trace.CurrentSpan.TraceIdHigh);
}

[Test]
public void TraceIdHighIsNotGeneratedIf128BitsDeactivated()
{
TraceManager.Trace128Bits = false;
var trace = Trace.Create();
Assert.AreEqual(SpanState.NoTraceIdHigh, trace.CurrentSpan.TraceIdHigh);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void SpanCorrectlyConvertedToThrift(long? parentSpanId)
const string serviceName = "myCriteoService";
const string methodName = "GET";

var spanState = new SpanState(1, parentSpanId, 2, SpanFlags.None);
var spanState = new SpanState(2, 1, parentSpanId, 2, SpanFlags.None);
var timestamp = TimeUtils.UtcNow;
var span = new Span(spanState, timestamp) { Endpoint = new IPEndPoint(hostIp, hostPort), ServiceName = serviceName, Name = methodName };

Expand All @@ -129,8 +129,9 @@ public void SpanCorrectlyConvertedToThrift(long? parentSpanId)
Service_name = serviceName
};

Assert.AreEqual(1, thriftSpan.Trace_id);
Assert.AreEqual(2, thriftSpan.Id);
Assert.AreEqual(spanState.TraceIdHigh, thriftSpan.Trace_id_high);
Assert.AreEqual(spanState.TraceId, thriftSpan.Trace_id);
Assert.AreEqual(spanState.SpanId, thriftSpan.Id);
Assert.True(thriftSpan.Timestamp.HasValue);

if (span.IsRoot)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public void ShouldParseTraceWithoutFlags(string encodedParentSpanId)
Trace trace;
Assert.True(ZipkinHttpTraceExtractor.TryParseTrace(encodedTraceId: "0000000000000001", encodedSpanId: "00000000000000FA", encodedParentSpanId: encodedParentSpanId, sampledStr: null, flagsStr: null, trace: out trace));

Assert.AreEqual(1, trace.CurrentSpan.TraceId);
Assert.AreEqual(1L, trace.CurrentSpan.TraceId);
Assert.AreEqual(SpanState.NoTraceIdHigh, trace.CurrentSpan.TraceIdHigh);
Assert.AreEqual(250, trace.CurrentSpan.SpanId);
Assert.AreEqual(SpanFlags.None, trace.CurrentSpan.Flags);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using Criteo.Profiling.Tracing.Transport;
using Criteo.Profiling.Tracing.Utils;
using NUnit.Framework;

namespace Criteo.Profiling.Tracing.UTest.Transport
Expand Down Expand Up @@ -29,6 +30,19 @@ public void GetTraceThenSetHeadersEqualsOriginal(string encodedTraceId, string e
Assert.AreEqual(flagsStr, recreatedHeaders[ZipkinHttpHeaders.Flags]);
}

[Test]
public void Supports128BitsTraceId()
{
var traceIdHigh = 1L;
var traceId = 2L;
var encodedTraceId = NumberUtils.EncodeLongToHexString(traceIdHigh) + NumberUtils.EncodeLongToHexString(traceId);

Trace parsedTrace;
Assert.True(ZipkinHttpTraceExtractor.TryParseTrace(encodedTraceId, "0000000000000000", "0000000000000000", null, "", out parsedTrace));
Assert.AreEqual(traceIdHigh, parsedTrace.CurrentSpan.TraceIdHigh);
Assert.AreEqual(traceId, parsedTrace.CurrentSpan.TraceId);
}

[TestCase(null)]
[TestCase(9845431L)]
public void SetHeadersThenGetTraceEqualsOriginal(long? parentSpanId)
Expand All @@ -39,7 +53,7 @@ public void SetHeadersThenGetTraceEqualsOriginal(long? parentSpanId)

private static void CheckSetHeadersThenGetTrace_Dict(long? parentSpanId)
{
var spanState = new SpanState(1, parentSpanId, 2, SpanFlags.None);
var spanState = new SpanState(2, 1, parentSpanId, 2, SpanFlags.None);
var originalTrace = Trace.CreateFromId(spanState);

var headers = new Dictionary<string, string>();
Expand All @@ -51,12 +65,11 @@ private static void CheckSetHeadersThenGetTrace_Dict(long? parentSpanId)
Assert.True(extractor.TryExtract(headers, out deserializedTrace));

Assert.AreEqual(originalTrace, deserializedTrace);
Assert.AreEqual(originalTrace.CurrentSpan.Flags, deserializedTrace.CurrentSpan.Flags);
}

private static void CheckSetHeadersThenGetTrace_NVC(long? parentSpanId)
{
var spanState = new SpanState(1, parentSpanId, 2, SpanFlags.None);
var spanState = new SpanState(2, 1, parentSpanId, 2, SpanFlags.None);
var originalTrace = Trace.CreateFromId(spanState);

var headers = new NameValueCollection();
Expand All @@ -68,8 +81,6 @@ private static void CheckSetHeadersThenGetTrace_NVC(long? parentSpanId)
Assert.True(extractor.TryExtract(headers, out deserializedTrace));

Assert.AreEqual(originalTrace, deserializedTrace);
Assert.AreEqual(originalTrace.CurrentSpan.Flags, deserializedTrace.CurrentSpan.Flags);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace Criteo.Profiling.Tracing.UTest.Utils
[TestFixture]
internal class T_NumberUtils
{

[Test]
public void TransformationIsReversible()
{
Expand Down
19 changes: 16 additions & 3 deletions zipkin4net/Criteo.Profiling.Tracing/SpanState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ namespace Criteo.Profiling.Tracing
[Serializable]
public sealed class SpanState : IEquatable<SpanState>
{
public long TraceIdHigh { get; private set; }

public long TraceId { get; private set; }

public long? ParentSpanId { get; private set; }

public long SpanId { get; private set; }

internal const long NoTraceIdHigh = 0;

public SamplingStatus SamplingStatus
{
get
Expand All @@ -28,7 +32,12 @@ public SamplingStatus SamplingStatus
public SpanFlags Flags { get; private set; }

public SpanState(long traceId, long? parentSpanId, long spanId, SpanFlags flags)
: this(NoTraceIdHigh, traceId, parentSpanId, spanId, flags)
{ }

public SpanState(long traceIdHigh, long traceId, long? parentSpanId, long spanId, SpanFlags flags)
{
TraceIdHigh = traceIdHigh;
TraceId = traceId;
ParentSpanId = parentSpanId;
SpanId = spanId;
Expand All @@ -47,7 +56,10 @@ public bool Equals(SpanState other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return TraceId == other.TraceId && ParentSpanId == other.ParentSpanId && SpanId == other.SpanId;
return TraceIdHigh == other.TraceIdHigh
&& TraceId == other.TraceId
&& ParentSpanId == other.ParentSpanId
&& SpanId == other.SpanId;
}

public override bool Equals(object obj)
Expand All @@ -62,15 +74,16 @@ public override int GetHashCode()
{
unchecked
{
var hashCode = TraceId.GetHashCode();
var hashCode = TraceIdHigh.GetHashCode();
hashCode = (hashCode * 397) ^ TraceId.GetHashCode();
hashCode = (hashCode * 397) ^ SpanId.GetHashCode();
return hashCode;
}
}

public override string ToString()
{
return string.Format("{0}.{1}<:{2}", TraceId, SpanId, ParentSpanId.HasValue ? ParentSpanId.Value.ToString(CultureInfo.InvariantCulture) : "_");
return string.Format("{0}{1}.{2}<:{3}", TraceIdHigh == SpanState.NoTraceIdHigh ? "" : TraceIdHigh.ToString(), TraceId, SpanId, ParentSpanId.HasValue ? ParentSpanId.Value.ToString(CultureInfo.InvariantCulture) : "_");
}

}
Expand Down
7 changes: 4 additions & 3 deletions zipkin4net/Criteo.Profiling.Tracing/Trace.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using Criteo.Profiling.Tracing.Annotation;
using Criteo.Profiling.Tracing.Utils;

Expand Down Expand Up @@ -52,6 +52,7 @@ public static Trace Create()
private Trace()
{
var traceId = RandomUtils.NextLong();
var traceIdHigh = TraceManager.Trace128Bits ? RandomUtils.NextLong() : 0;
var spanId = RandomUtils.NextLong();

var isSampled = TraceManager.Sampler.Sample(traceId);
Expand All @@ -62,7 +63,7 @@ private Trace()
flags = flags | SpanFlags.Sampled;
}

CurrentSpan = new SpanState(traceId: traceId, parentSpanId: null, spanId: spanId, flags: flags);
CurrentSpan = new SpanState(traceIdHigh: traceIdHigh, traceId: traceId, parentSpanId: null, spanId: spanId, flags: flags);
CorrelationId = NumberUtils.LongToGuid(traceId);
}

Expand Down Expand Up @@ -90,7 +91,7 @@ private Trace(SpanState spanState)
/// <returns></returns>
public Trace Child()
{
var childState = new SpanState(traceId: CurrentSpan.TraceId, parentSpanId: CurrentSpan.SpanId, spanId: RandomUtils.NextLong(), flags: CurrentSpan.Flags);
var childState = new SpanState(traceIdHigh: CurrentSpan.TraceIdHigh, traceId: CurrentSpan.TraceId, parentSpanId: CurrentSpan.SpanId, spanId: RandomUtils.NextLong(), flags: CurrentSpan.Flags);
return new Trace(childState);
}

Expand Down
5 changes: 5 additions & 0 deletions zipkin4net/Criteo.Profiling.Tracing/TraceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public static bool Started
get { return _status == (int)Status.Started; }
}

public static bool Trace128Bits
{
get; set;
}

/// <summary>
/// Start tracing, records will be forwarded to the registered tracers.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ private void SerializeSpan(StreamWriter writer, Span span)
writer.Write(comma);
writer.WriteField(name, span.Name ?? SerializerUtils.DefaultRpcMethodName);
writer.Write(comma);
writer.WriteField(traceId, NumberUtils.EncodeLongToLowerHexString(span.SpanState.TraceId));
var hexTraceIdHigh = TraceManager.Trace128Bits ? NumberUtils.EncodeLongToHexString(span.SpanState.TraceIdHigh) : "";
writer.WriteField(traceId,
hexTraceIdHigh
+ NumberUtils.EncodeLongToHexString(span.SpanState.TraceId));

if (span.SpanStarted.HasValue)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public static Thrift.Span ConvertToThrift(Span span)
var thriftSpan = new Thrift.Span()
{
Id = span.SpanState.SpanId,
Trace_id_high = span.SpanState.TraceIdHigh,
Trace_id = span.SpanState.TraceId,
Name = span.Name ?? SerializerUtils.DefaultRpcMethodName,
Debug = false
Expand Down Expand Up @@ -118,6 +119,6 @@ private static Thrift.Endpoint ConvertToThrift(IPEndPoint ipEndPoint, string ser
Port = (short)ipEndPoint.Port,
Service_name = serviceName
};
}
}
}
}
Loading

0 comments on commit 1c12086

Please sign in to comment.