diff --git a/src/Datadog.Tracer.IntegrationTests/SendTracesToAgent.cs b/src/Datadog.Tracer.IntegrationTests/SendTracesToAgent.cs index 6f01b0743096..acc8e1583c65 100644 --- a/src/Datadog.Tracer.IntegrationTests/SendTracesToAgent.cs +++ b/src/Datadog.Tracer.IntegrationTests/SendTracesToAgent.cs @@ -1,4 +1,4 @@ -using System; +using System; using Xunit; namespace Datadog.Tracer.IntegrationTests @@ -10,7 +10,7 @@ public void MinimalSpan() { var tracer = new Tracer(new Api(new Uri("http://localhost:8126"))); tracer.BuildSpan("Operation") - .WithTag(Tags.Resource, "This is a resource") + .WithTag(Tags.ResourceName, "This is a resource") .Start() .Finish(); } @@ -20,8 +20,20 @@ public void CustomServiceName() { var tracer = new Tracer(new Api(new Uri("http://localhost:8126"))); tracer.BuildSpan("Operation") - .WithTag(Tags.Resource, "This is a resource") - .WithTag(Tags.Service, "Service1") + .WithTag(Tags.ResourceName, "This is a resource") + .WithTag(Tags.ServiceName, "Service1") + .Start() + .Finish(); + } + + [Fact] + public void Utf8Everywhere() + { + var tracer = new Tracer(new Api(new Uri("http://localhost:8126"))); + tracer.BuildSpan("Aᛗᚪᚾᚾᚪ") + .WithTag(Tags.ResourceName, "η γλώσσα μου έδωσαν ελληνική") + .WithTag(Tags.ServiceName, "На берегу пустынных волн") + .WithTag("யாமறிந்த", "ნუთუ კვლა") .Start() .Finish(); } diff --git a/src/Datadog.Tracer.Tests/SpanBuilderTests.cs b/src/Datadog.Tracer.Tests/SpanBuilderTests.cs index 2f557b8a1b20..265904a48a27 100644 --- a/src/Datadog.Tracer.Tests/SpanBuilderTests.cs +++ b/src/Datadog.Tracer.Tests/SpanBuilderTests.cs @@ -48,12 +48,12 @@ public void Start_AsChildOfSpan_ChildReferencesParent() .AsChildOf(root) .Start(); - Assert.Null(root.DatadogContext.ParentId); - Assert.NotEqual(0, root.DatadogContext.SpanId); - Assert.NotEqual(0, root.DatadogContext.TraceId); - Assert.Equal(root.DatadogContext.SpanId, child.DatadogContext.ParentId); - Assert.Equal(root.DatadogContext.TraceId, child.DatadogContext.TraceId); - Assert.NotEqual(0, child.DatadogContext.SpanId); + Assert.Null(root.Context.ParentId); + Assert.NotEqual(0, root.Context.SpanId); + Assert.NotEqual(0, root.Context.TraceId); + Assert.Equal(root.Context.SpanId, child.Context.ParentId); + Assert.Equal(root.Context.TraceId, child.Context.TraceId); + Assert.NotEqual(0, child.Context.SpanId); } [Fact] @@ -61,15 +61,15 @@ public void Start_AsChildOfSpanContext_ChildReferencesParent() { var root = (Span)CreateSpanBuilder().Start(); var child = (Span)CreateSpanBuilder() - .AsChildOf(root.DatadogContext) + .AsChildOf(root.Context) .Start(); - Assert.Null(root.DatadogContext.ParentId); - Assert.NotEqual(0, root.DatadogContext.SpanId); - Assert.NotEqual(0, root.DatadogContext.TraceId); - Assert.Equal(root.DatadogContext.SpanId, child.DatadogContext.ParentId); - Assert.Equal(root.DatadogContext.TraceId, child.DatadogContext.TraceId); - Assert.NotEqual(0, child.DatadogContext.SpanId); + Assert.Null(root.Context.ParentId); + Assert.NotEqual(0, root.Context.SpanId); + Assert.NotEqual(0, root.Context.TraceId); + Assert.Equal(root.Context.SpanId, child.Context.ParentId); + Assert.Equal(root.Context.TraceId, child.Context.TraceId); + Assert.NotEqual(0, child.Context.SpanId); } [Fact] @@ -77,15 +77,15 @@ public void Start_ReferenceAsChildOf_ChildReferencesParent() { var root = (Span)CreateSpanBuilder().Start(); var child = (Span)CreateSpanBuilder() - .AddReference(References.ChildOf, root.DatadogContext) + .AddReference(References.ChildOf, root.Context) .Start(); - Assert.Null(root.DatadogContext.ParentId); - Assert.NotEqual(0, root.DatadogContext.SpanId); - Assert.NotEqual(0, root.DatadogContext.TraceId); - Assert.Equal(root.DatadogContext.SpanId, child.DatadogContext.ParentId); - Assert.Equal(root.DatadogContext.TraceId, child.DatadogContext.TraceId); - Assert.NotEqual(0, child.DatadogContext.SpanId); + Assert.Null(root.Context.ParentId); + Assert.NotEqual(0, root.Context.SpanId); + Assert.NotEqual(0, root.Context.TraceId); + Assert.Equal(root.Context.SpanId, child.Context.ParentId); + Assert.Equal(root.Context.TraceId, child.Context.TraceId); + Assert.NotEqual(0, child.Context.SpanId); } [Fact] @@ -108,7 +108,7 @@ public void Start_WithTags_TagsAreProperlySet() public void Start_SettingService_ServiceIsSet() { var span = (Span)CreateSpanBuilder() - .WithTag(Tags.Service, "MyService") + .WithTag("service.name", "MyService") .Start(); Assert.Equal("MyService", span.ServiceName); @@ -118,7 +118,7 @@ public void Start_SettingService_ServiceIsSet() public void Start_SettingResource_ResourceIsSet() { var span = (Span)CreateSpanBuilder() - .WithTag(Tags.Resource, "MyResource") + .WithTag("resource.name", "MyResource") .Start(); Assert.Equal("MyResource", span.ResourceName); @@ -128,7 +128,7 @@ public void Start_SettingResource_ResourceIsSet() public void Start_SettingType_TypeIsSet() { var span = (Span)CreateSpanBuilder() - .WithTag(Tags.Type, "web") + .WithTag("span.type", "web") .Start(); Assert.Equal("web", span.Type); @@ -138,7 +138,7 @@ public void Start_SettingType_TypeIsSet() public void Start_SettingError_ErrorIsSet() { var span = (Span)CreateSpanBuilder() - .WithTag(Tags.Error, true) + .WithTag(OpenTracing.Tags.Error, true) .Start(); Assert.Equal(true, span.Error); diff --git a/src/Datadog.Tracer.Tests/SpanTests.cs b/src/Datadog.Tracer.Tests/SpanTests.cs index c8ab80693851..1584e3f05e39 100644 --- a/src/Datadog.Tracer.Tests/SpanTests.cs +++ b/src/Datadog.Tracer.Tests/SpanTests.cs @@ -23,7 +23,7 @@ public SpanTests() [Fact] public void SetTag_Tags_TagsAreProperlySet() { - var span = new Span(_tracerMock.Object, null, null, null); + var span = new Span(_tracerMock.Object, null, null, null, null); span.SetTag("StringKey", "What's tracing"); span.SetTag("IntKey", 42); @@ -40,7 +40,7 @@ public void SetTag_Tags_TagsAreProperlySet() [Fact] public void SetOperationName_ValidOperationName_OperationNameIsProperlySet() { - var span = new Span(_tracerMock.Object, null, null, null); + var span = new Span(_tracerMock.Object, null, null, null, null); span.SetOperationName("Op1"); @@ -52,7 +52,7 @@ public void SetOperationName_ValidOperationName_OperationNameIsProperlySet() public void Finish_StartTimeInThePastWithNoEndTime_DurationProperlyComputed() { var startTime = DateTimeOffset.UtcNow.AddMinutes(-1); - var span = new Span(_tracerMock.Object, null, null, startTime); + var span = new Span(_tracerMock.Object, null, null, null, startTime); span.Finish(); @@ -63,7 +63,7 @@ public void Finish_StartTimeInThePastWithNoEndTime_DurationProperlyComputed() [Fact] public async Task Finish_NoEndTimeProvided_SpanWriten() { - var span = new Span(_tracerMock.Object, null, null, null); + var span = new Span(_tracerMock.Object, null, null, null, null); await Task.Delay(TimeSpan.FromMilliseconds(1)); span.Finish(); @@ -76,7 +76,7 @@ public void Finish_EndTimeProvided_SpanWritenWithCorrectDuration() { var startTime = DateTimeOffset.UtcNow; var endTime = DateTime.UtcNow.AddMilliseconds(10); - var span = new Span(_tracerMock.Object, null, null, startTime); + var span = new Span(_tracerMock.Object, null, null, null, startTime); span.Finish(endTime); @@ -89,7 +89,7 @@ public void Finish_EndTimeInThePast_DurationIs0() { var startTime = DateTimeOffset.UtcNow; var endTime = DateTime.UtcNow.AddMilliseconds(-10); - var span = new Span(_tracerMock.Object, null, null, startTime); + var span = new Span(_tracerMock.Object, null, null, null, startTime); span.Finish(endTime); @@ -101,7 +101,7 @@ public void Finish_EndTimeInThePast_DurationIs0() public void Dispose_ExitUsing_SpanWriten() { Span span; - using (span = new Span(_tracerMock.Object, null, null, null)) + using (span = new Span(_tracerMock.Object, null, null, null, null)) { } diff --git a/src/Datadog.Tracer.Tests/TracerTests.cs b/src/Datadog.Tracer.Tests/TracerTests.cs index 1167e2f96d5f..0ecddc8afc67 100644 --- a/src/Datadog.Tracer.Tests/TracerTests.cs +++ b/src/Datadog.Tracer.Tests/TracerTests.cs @@ -1,7 +1,7 @@ using Moq; using System; +using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using Xunit; @@ -9,12 +9,12 @@ namespace Datadog.Tracer.Tests { public class TracerTests { - private Mock _apiMock = new Mock(MockBehavior.Strict); + private Mock _apiMock = new Mock(); [Fact] - public void BuildSpan_NoParameterAutomaticContextPropagation_DefaultParameters() + public void BuildSpan_NoParameter_DefaultParameters() { - var tracer = new Tracer(_apiMock.Object, automaticContextPropagation: true); + var tracer = new Tracer(_apiMock.Object); var builder = tracer.BuildSpan("Op1"); var span = (Span)builder.Start(); @@ -24,21 +24,9 @@ public void BuildSpan_NoParameterAutomaticContextPropagation_DefaultParameters() } [Fact] - public void BuildSpan_NoParameterNoAutomaticContextPropagation_DefaultParameters() + public void BuildSpan_OneChild_ChildParentProperlySet() { - var tracer = new Tracer(_apiMock.Object, automaticContextPropagation: false); - - var builder = tracer.BuildSpan("Op1"); - var span = (Span)builder.Start(); - - Assert.Equal(Constants.UnkownService, span.ServiceName); - Assert.Equal("Op1", span.OperationName); - } - - [Fact] - public void BuildSpan_OneChildAutomaticContextPropagation_ChildParentProperlySet() - { - var tracer = new Tracer(_apiMock.Object, automaticContextPropagation: true); + var tracer = new Tracer(_apiMock.Object); var root = (Span)tracer .BuildSpan("Root") @@ -48,13 +36,13 @@ public void BuildSpan_OneChildAutomaticContextPropagation_ChildParentProperlySet .Start(); Assert.Equal(root.TraceContext, child.TraceContext); - Assert.Equal(root.DatadogContext.SpanId, child.DatadogContext.ParentId); + Assert.Equal(root.Context.SpanId, child.Context.ParentId); } [Fact] - public void BuildSpan_2ChildrenOfRootAutomaticContextPropagation_ChildrenParentProperlySet() + public void BuildSpan_2ChildrenOfRoot_ChildrenParentProperlySet() { - var tracer = new Tracer(_apiMock.Object, automaticContextPropagation: true); + var tracer = new Tracer(_apiMock.Object); var root = (Span)tracer .BuildSpan("Root") @@ -68,15 +56,15 @@ public void BuildSpan_2ChildrenOfRootAutomaticContextPropagation_ChildrenParentP .Start(); Assert.Equal(root.TraceContext, child1.TraceContext); - Assert.Equal(root.DatadogContext.SpanId, child1.DatadogContext.ParentId); + Assert.Equal(root.Context.SpanId, child1.Context.ParentId); Assert.Equal(root.TraceContext, child2.TraceContext); - Assert.Equal(root.DatadogContext.SpanId, child2.DatadogContext.ParentId); + Assert.Equal(root.Context.SpanId, child2.Context.ParentId); } [Fact] - public void BuildSpan_2LevelChildrenAutomaticContextPropagation_ChildrenParentProperlySet() + public void BuildSpan_2LevelChildren_ChildrenParentProperlySet() { - var tracer = new Tracer(_apiMock.Object, automaticContextPropagation: true); + var tracer = new Tracer(_apiMock.Object); var root = (Span)tracer .BuildSpan("Root") @@ -89,15 +77,15 @@ public void BuildSpan_2LevelChildrenAutomaticContextPropagation_ChildrenParentPr .Start(); Assert.Equal(root.TraceContext, child1.TraceContext); - Assert.Equal(root.DatadogContext.SpanId, child1.DatadogContext.ParentId); + Assert.Equal(root.Context.SpanId, child1.Context.ParentId); Assert.Equal(root.TraceContext, child2.TraceContext); - Assert.Equal(child1.DatadogContext.SpanId, child2.DatadogContext.ParentId); + Assert.Equal(child1.Context.SpanId, child2.Context.ParentId); } [Fact] - public async Task BuildSpan_AsyncChildrenCreationAutomaticContextPropagation_ChildrenParentProperlySet() + public async Task BuildSpan_AsyncChildrenCreation_ChildrenParentProperlySet() { - var tracer = new Tracer(_apiMock.Object, automaticContextPropagation: true); + var tracer = new Tracer(_apiMock.Object); var tcs = new TaskCompletionSource(); var root = (Span)tracer @@ -111,12 +99,12 @@ public async Task BuildSpan_AsyncChildrenCreationAutomaticContextPropagation_Chi tcs.SetResult(true); Assert.Equal(root.TraceContext, syncChild.TraceContext); - Assert.Equal(root.DatadogContext.SpanId, syncChild.DatadogContext.ParentId); + Assert.Equal(root.Context.SpanId, syncChild.Context.ParentId); foreach(var task in tasks) { var span = await task; Assert.Equal(root.TraceContext, span.TraceContext); - Assert.Equal(root.DatadogContext.SpanId, span.DatadogContext.ParentId); + Assert.Equal(root.Context.SpanId, span.Context.ParentId); } } } diff --git a/src/Datadog.Tracer/Api.cs b/src/Datadog.Tracer/Api.cs index 907a8d414d71..9bce35e85adb 100644 --- a/src/Datadog.Tracer/Api.cs +++ b/src/Datadog.Tracer/Api.cs @@ -46,7 +46,7 @@ public Api(Uri baseEndpoint) _servicesEndpoint = new Uri(baseEndpoint, ServicesPath); // TODO:bertrand add header for os version _client.DefaultRequestHeaders.Add("Datadog-Meta-Lang", ".NET"); - _client.DefaultRequestHeaders.Add("Datadog-Meta-Lang-Version", RuntimeInformation.FrameworkDescription); + _client.DefaultRequestHeaders.Add("Datadog-Meta-Lang-Interpreter", RuntimeInformation.FrameworkDescription); _client.DefaultRequestHeaders.Add("Datadog-Meta-Tracer-Version", Assembly.GetEntryAssembly().GetName().Version.ToString()); } diff --git a/src/Datadog.Tracer/RandomUtils.cs b/src/Datadog.Tracer/RandomUtils.cs index 52415a0e531a..804f46d85811 100644 --- a/src/Datadog.Tracer/RandomUtils.cs +++ b/src/Datadog.Tracer/RandomUtils.cs @@ -4,12 +4,12 @@ namespace Datadog.Tracer { public static class RandomUtils { - public static UInt64 NextUInt64(this Random rnd) + public static UInt64 NextUInt63(this Random rnd) { // From https://stackoverflow.com/a/677390 var buffer = new byte[sizeof(UInt64)]; rnd.NextBytes(buffer); - return BitConverter.ToUInt64(buffer, 0); + return BitConverter.ToUInt64(buffer, 0) & (~(1 << 63)); } } } diff --git a/src/Datadog.Tracer/Span.cs b/src/Datadog.Tracer/Span.cs index 03b1cfad39eb..4acf334a0219 100644 --- a/src/Datadog.Tracer/Span.cs +++ b/src/Datadog.Tracer/Span.cs @@ -2,49 +2,49 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Text; namespace Datadog.Tracer { - // TODO:bertrand, should a Span be thread safe? public class Span : ISpan { + private Object _lock = new Object(); private IDatadogTracer _tracer; private Dictionary _tags; private bool _isFinished; private SpanContext _context; private Stopwatch _sw; - public ISpanContext Context => _context; + ISpanContext ISpan.Context => _context; - internal SpanContext DatadogContext => _context; + internal SpanContext Context => _context; internal ITraceContext TraceContext => _context.TraceContext; internal DateTimeOffset StartTime { get; } - internal TimeSpan Duration { get; set; } + internal TimeSpan Duration { get; private set; } - internal string OperationName { get; set; } + internal string OperationName { get; private set; } - internal string ResourceName { get; set; } + internal string ResourceName { get; private set; } internal string ServiceName => _context.ServiceName; - internal string Type { get; set; } + internal string Type { get; private set; } - internal bool Error { get; set; } + internal bool Error { get; private set; } internal bool IsRootSpan { get { return _context.ParentId == null; } } + // This is threadsafe only if used after the span has been closed. + // It is acceptable because this property is internal. But if we were to make it public we would need to add some checks. internal IReadOnlyDictionary Tags { get { return _tags; } } - internal Span(IDatadogTracer tracer, SpanContext parent, string operationName, DateTimeOffset? start) + internal Span(IDatadogTracer tracer, SpanContext parent, string operationName, string serviceName, DateTimeOffset? start) { _tracer = tracer; - _context = new SpanContext(parent?.TraceContext ?? _tracer.GetTraceContext()); - _context.ServiceName = _context.ServiceName ?? _tracer.DefaultServiceName; + _context = new SpanContext(parent?.TraceContext ?? _tracer.GetTraceContext(), serviceName ?? parent?.ServiceName ?? tracer.DefaultServiceName); OperationName = operationName; if (start.HasValue) { @@ -64,34 +64,50 @@ public void Dispose() public void Finish() { - if (!_isFinished) + // If the startTime was explicitely provided, we don't use a StopWatch to compute the duration + if (_sw == null) { - // If the startTime was explicitely provided, we don't use a StopWatch to compute the duration - if (_sw == null) + Finish(DateTimeOffset.UtcNow); + return; + } + else + { + var shouldCloseSpan = false; + lock (_lock) { - Finish(DateTimeOffset.UtcNow); - return; + if (!_isFinished) + { + Duration = _sw.Elapsed; + _isFinished = true; + shouldCloseSpan = true; + } } - else + if (shouldCloseSpan) { - Duration = _sw.Elapsed; + _context.TraceContext.CloseSpan(this); } - _context.TraceContext.CloseSpan(this); - _isFinished = true; } } public void Finish(DateTimeOffset finishTimestamp) { - if (!_isFinished) + lock (_lock) { - Duration = finishTimestamp - StartTime; - if (Duration < TimeSpan.Zero) + var shouldCloseSpan = false; + if (!_isFinished) + { + Duration = finishTimestamp - StartTime; + if (Duration < TimeSpan.Zero) + { + Duration = TimeSpan.Zero; + } + _isFinished = true; + shouldCloseSpan = true; + } + if (shouldCloseSpan) { - Duration = TimeSpan.Zero; + _context.TraceContext.CloseSpan(this); } - _context.TraceContext.CloseSpan(this); - _isFinished = true; } } @@ -127,8 +143,11 @@ public ISpan SetBaggageItem(string key, string value) public ISpan SetOperationName(string operationName) { - OperationName = operationName; - return this; + lock (_lock) + { + OperationName = operationName; + return this; + } } public ISpan SetTag(string key, bool value) @@ -148,33 +167,40 @@ public ISpan SetTag(string key, int value) public ISpan SetTag(string key, string value) { - switch (key) { - case Datadog.Tracer.Tags.Service: - this._context.ServiceName = value; - return this; - case Datadog.Tracer.Tags.Resource: - ResourceName = value; - return this; - case Datadog.Tracer.Tags.Error: - Error = value == "True"; - return this; - case Datadog.Tracer.Tags.Type: - Type = value; - return this; - } - if(_tags == null) + lock (_lock) { - _tags = new Dictionary(); + if (_isFinished) + { + // TODO:log an error instead + } + switch (key) { + case Datadog.Tracer.Tags.ResourceName: + ResourceName = value; + return this; + case OpenTracing.Tags.Error: + Error = value == "True"; + return this; + case Datadog.Tracer.Tags.SpanType: + Type = value; + return this; + } + if (_tags == null) + { + _tags = new Dictionary(); + } + _tags[key] = value; + return this; } - _tags[key] = value; - return this; } internal string GetTag(string key) { - string s = null; - _tags?.TryGetValue(key, out s); - return s; + lock (_lock) + { + string s = null; + _tags?.TryGetValue(key, out s); + return s; + } } public override string ToString() diff --git a/src/Datadog.Tracer/SpanBuilder.cs b/src/Datadog.Tracer/SpanBuilder.cs index d34ef3c13c2f..299aaa8c9de1 100644 --- a/src/Datadog.Tracer/SpanBuilder.cs +++ b/src/Datadog.Tracer/SpanBuilder.cs @@ -6,11 +6,13 @@ namespace Datadog.Tracer { public class SpanBuilder : ISpanBuilder { + private Object _lock = new Object(); private IDatadogTracer _tracer; private string _operationName; private SpanContext _parent; private DateTimeOffset? _start; private Dictionary _tags; + private string _serviceName; internal SpanBuilder(IDatadogTracer tracer, string operationName) { @@ -20,24 +22,33 @@ internal SpanBuilder(IDatadogTracer tracer, string operationName) public ISpanBuilder AddReference(string referenceType, ISpanContext referencedContext) { - if (referenceType == References.ChildOf) + lock (_lock) { - _parent = referencedContext as SpanContext; - return this; + if (referenceType == References.ChildOf) + { + _parent = referencedContext as SpanContext; + return this; + } } throw new NotImplementedException(); } public ISpanBuilder AsChildOf(ISpan parent) { - _parent = parent.Context as SpanContext; - return this; + lock (_lock) + { + _parent = parent.Context as SpanContext; + return this; + } } public ISpanBuilder AsChildOf(ISpanContext parent) { - _parent = parent as SpanContext; - return this; + lock (_lock) + { + _parent = parent as SpanContext; + return this; + } } public ISpanBuilder FollowsFrom(ISpan parent) @@ -52,22 +63,28 @@ public ISpanBuilder FollowsFrom(ISpanContext parent) public ISpan Start() { - var span = new Span(_tracer, _parent, _operationName, _start); - span.TraceContext.AddSpan(span); - if(_tags != null) + lock (_lock) { - foreach(var pair in _tags) + var span = new Span(_tracer, _parent, _operationName, _serviceName, _start); + span.TraceContext.AddSpan(span); + if (_tags != null) { - span.SetTag(pair.Key, pair.Value); + foreach (var pair in _tags) + { + span.SetTag(pair.Key, pair.Value); + } } + return span; } - return span; } public ISpanBuilder WithStartTimestamp(DateTimeOffset startTimestamp) { - _start = startTimestamp; - return this; + lock (_lock) + { + _start = startTimestamp; + return this; + } } public ISpanBuilder WithTag(string key, bool value) @@ -87,12 +104,20 @@ public ISpanBuilder WithTag(string key, int value) public ISpanBuilder WithTag(string key, string value) { - if(_tags == null) + lock (_lock) { - _tags = new Dictionary(); + if (key == Tags.ServiceName) + { + _serviceName = value; + return this; + } + if (_tags == null) + { + _tags = new Dictionary(); + } + _tags[key] = value; + return this; } - _tags[key] = value; - return this; } } } diff --git a/src/Datadog.Tracer/SpanContext.cs b/src/Datadog.Tracer/SpanContext.cs index cc17e7787386..0f3df1def320 100644 --- a/src/Datadog.Tracer/SpanContext.cs +++ b/src/Datadog.Tracer/SpanContext.cs @@ -14,13 +14,13 @@ internal class SpanContext : ISpanContext public UInt64 SpanId { get; } - // TODO:bertrand do we really want ServiceName to be mutable? - public string ServiceName { get; set; } + public string ServiceName { get; } public ITraceContext TraceContext { get; } - public SpanContext(ITraceContext traceContext) + public SpanContext(ITraceContext traceContext, string serviceName) { + ServiceName = serviceName; // TODO:bertrand pool the random objects Random r = new Random(); var parent = traceContext.GetCurrentSpanContext(); @@ -30,12 +30,12 @@ public SpanContext(ITraceContext traceContext) TraceId = parent.TraceId; ServiceName = parent.ServiceName; TraceContext = parent.TraceContext; - SpanId = r.NextUInt64(); + SpanId = r.NextUInt63(); } else { - TraceId = r.NextUInt64(); - SpanId = r.NextUInt64(); + TraceId = r.NextUInt63(); + SpanId = r.NextUInt63(); TraceContext = traceContext; } } diff --git a/src/Datadog.Tracer/SpanMsgpackSerializer.cs b/src/Datadog.Tracer/SpanMsgpackSerializer.cs index 18024970980f..70312d66daed 100644 --- a/src/Datadog.Tracer/SpanMsgpackSerializer.cs +++ b/src/Datadog.Tracer/SpanMsgpackSerializer.cs @@ -15,7 +15,7 @@ protected override void PackToCore(Packer packer, Span value) // First, pack array length (or map length). // It should be the number of members of the object to be serialized. var len = 8; - if (value.DatadogContext.ParentId != null) + if (value.Context.ParentId != null) { len += 1; } @@ -29,9 +29,9 @@ protected override void PackToCore(Packer packer, Span value) } packer.PackMapHeader(len); packer.PackString("trace_id"); - packer.Pack(value.DatadogContext.TraceId); + packer.Pack(value.Context.TraceId); packer.PackString("span_id"); - packer.Pack(value.DatadogContext.SpanId); + packer.Pack(value.Context.SpanId); packer.PackString("name"); packer.PackString(value.OperationName); packer.PackString("resource"); @@ -44,10 +44,10 @@ protected override void PackToCore(Packer packer, Span value) packer.Pack(value.StartTime.ToUnixTimeNanoseconds()); packer.PackString("duration"); packer.Pack(value.Duration.ToNanoseconds()); - if (value.DatadogContext.ParentId != null) + if (value.Context.ParentId != null) { packer.PackString("parent_id"); - packer.Pack(value.DatadogContext.ParentId); + packer.Pack(value.Context.ParentId); } if (value.Error) { diff --git a/src/Datadog.Tracer/Tags.cs b/src/Datadog.Tracer/Tags.cs index 8fa3c31880f6..a441f48ce95b 100644 --- a/src/Datadog.Tracer/Tags.cs +++ b/src/Datadog.Tracer/Tags.cs @@ -1,13 +1,9 @@ -using System; -using System.Collections.Generic; - -namespace Datadog.Tracer +namespace Datadog.Tracer { public static class Tags { - public const string Service = "Datadog.Service"; - public const string Resource = "Datadog.Resource"; - public const string Error = "Datadog.Error"; - public const string Type = "Datadog.Type"; + public const string ServiceName = "service.name"; + public const string ResourceName = "resource.name"; + public const string SpanType = "span.type"; } } diff --git a/src/Datadog.Tracer/TraceContext.cs b/src/Datadog.Tracer/TraceContext.cs index 81f941b37737..5e014149a3cd 100644 --- a/src/Datadog.Tracer/TraceContext.cs +++ b/src/Datadog.Tracer/TraceContext.cs @@ -27,7 +27,7 @@ public void AddSpan(Span span) { lock (_lock) { - _currentSpanContext.Value = span.DatadogContext; + _currentSpanContext.Value = span.Context; _spans.Add(span); _openSpans++; } @@ -43,9 +43,14 @@ public void CloseSpan(Span span) { if (_openSpans != 0) { - //TODO:bertrand log warning + // TODO:bertrand log error and do not send anything + // Instead detect if we are being garbage collected and warn at that point } - _tracer.Write(_spans); + else + { + _tracer.Write(_spans); + } + // TODO:bertrand make sure the tracecontext is reset } } } diff --git a/src/Datadog.Tracer/Tracer.cs b/src/Datadog.Tracer/Tracer.cs index 3efff6bbf48b..469fac20e466 100644 --- a/src/Datadog.Tracer/Tracer.cs +++ b/src/Datadog.Tracer/Tracer.cs @@ -12,36 +12,34 @@ internal class Tracer : ITracer, IDatadogTracer { private AsyncLocal _currentContext = new AsyncLocal(); private string _defaultServiceName; - private bool _automaticContextPropagation; private IApi _api; private Dictionary _services = new Dictionary(); string IDatadogTracer.DefaultServiceName => _defaultServiceName; - public Tracer(IApi api, List serviceInfo = null, string defaultServiceName = Constants.UnkownService, bool automaticContextPropagation = true) + public Tracer(IApi api, List serviceInfo = null, string defaultServiceName = Constants.UnkownService) { _api = api; - //TODO:bertrand be smarter about the service name + // TODO:bertrand be smarter about the service name _defaultServiceName = defaultServiceName; - _automaticContextPropagation = true; - if(serviceInfo != null) + if (defaultServiceName == Constants.UnkownService) { - if(defaultServiceName == Constants.UnkownService) + _services[Constants.UnkownService] = new ServiceInfo { - _services[Constants.UnkownService] = new ServiceInfo - { - ServiceName = Constants.UnkownService, - App = Constants.UnkownApp, - AppType = Constants.WebAppType, - }; - } + ServiceName = Constants.UnkownService, + App = Constants.UnkownApp, + AppType = Constants.WebAppType, + }; + } + if (serviceInfo != null) + { foreach(var service in serviceInfo) { _services[service.ServiceName] = service; } - // TODO:bertrand handle errors properly - Task.WhenAll(_services.Values.Select(_api.SendServiceAsync)).Wait(); } + // TODO:bertrand handle errors properly + Task.WhenAll(_services.Values.Select(_api.SendServiceAsync)).Wait(); } public ISpanBuilder BuildSpan(string operationName) @@ -70,10 +68,6 @@ void IDatadogTracer.Write(List trace) ITraceContext IDatadogTracer.GetTraceContext() { - if (!_automaticContextPropagation) - { - return new TraceContext(this); - } if(_currentContext.Value == null) { _currentContext.Value = new TraceContext(this);