Exporter spec updates. (#1609)

* Exporter spec updates.

* CHANGELOG updates.

Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
This commit is contained in:
Mikel Blanchard 2020-11-23 10:24:35 -08:00 committed by GitHub
parent 9f27b4cfe4
commit d3edc476e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 111 additions and 41 deletions

View File

@ -8,6 +8,13 @@
* Jaeger will now set the `error` tag when `otel.status_code` is set to `Error`.
([#1579](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1579))
* Jaeger will no longer send the `otel.status_code` tag if the value is `Unset`.
([#1609](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1609))
* Span Event.Name will now be populated as the `event` field on Jaeger Logs
instead of `message`.
([#1609](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1609))
## 1.0.0-rc1.1
Released 2020-Nov-17

View File

@ -162,10 +162,11 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
timedEvent.EnumerateTags(ref jaegerTags);
// Matches what OpenTracing and OpenTelemetry defines as the event name.
// https://github.com/opentracing/specification/blob/master/semantic_conventions.md#log-fields-table
// https://github.com/open-telemetry/opentelemetry-specification/pull/397/files
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("message", JaegerTagType.STRING, vStr: timedEvent.Name));
if (!jaegerTags.HasEvent)
{
// https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk_exporters/jaeger.md#events
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("event", JaegerTagType.STRING, vStr: timedEvent.Name));
}
// TODO: Use the same function as JaegerConversionExtensions or check that the perf here is acceptable.
return new JaegerLog(timedEvent.Timestamp.ToEpochMicroseconds(), jaegerTags.Tags);
@ -256,9 +257,16 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
{
PeerServiceResolver.InspectTag(ref state, key, jaegerTag.VStr);
if (key == SpanAttributeConstants.StatusCodeKey && jaegerTag.VStr == "Error")
if (key == SpanAttributeConstants.StatusCodeKey)
{
PooledList<JaegerTag>.Add(ref state.Tags, new JaegerTag("error", JaegerTagType.BOOL, vBool: true));
if (jaegerTag.VStr == "Error")
{
PooledList<JaegerTag>.Add(ref state.Tags, new JaegerTag("error", JaegerTagType.BOOL, vBool: true));
}
else if (jaegerTag.VStr == "Unset")
{
return;
}
}
}
else if (jaegerTag.VLong.HasValue)
@ -342,6 +350,8 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
{
public PooledList<JaegerTag> Tags;
public bool HasEvent;
public bool ForEach(KeyValuePair<string, object> tag)
{
if (tag.Value is Array)
@ -353,6 +363,11 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
PooledList<JaegerTag>.Add(ref this.Tags, tag.ToJaegerTag());
}
if (tag.Key == "event")
{
this.HasEvent = true;
}
return true;
}
}

View File

@ -5,6 +5,13 @@
* Zipkin will now set the `error` tag when `otel.status_code` is set to `Error`.
([#1579](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1579))
* Zipkin will no longer send the `otel.status_code` tag if the value is `Unset`.
([#1609](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1609))
* Zipkin bool tag values will now be sent as `true`/`false` instead of
`True`/`False`.
([#1609](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1609))
## 1.0.0-rc1.1
Released 2020-Nov-17

View File

@ -175,9 +175,17 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
{
PeerServiceResolver.InspectTag(ref this, key, strVal);
if (key == SpanAttributeConstants.StatusCodeKey && strVal == "Error")
if (key == SpanAttributeConstants.StatusCodeKey)
{
PooledList<KeyValuePair<string, object>>.Add(ref this.Tags, new KeyValuePair<string, object>("error", "true"));
if (strVal == "Error")
{
PooledList<KeyValuePair<string, object>>.Add(ref this.Tags, new KeyValuePair<string, object>("error", "true"));
}
else if (strVal == "Unset")
{
// Unset Status is not sent: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk_exporters/zipkin.md#status
return true;
}
}
}
else if (activityTag.Value is int intVal && activityTag.Key == SemanticConventions.AttributeNetPeerPort)

View File

@ -41,8 +41,8 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
long? duration,
ZipkinEndpoint localEndpoint,
ZipkinEndpoint remoteEndpoint,
in PooledList<ZipkinAnnotation>? annotations,
in PooledList<KeyValuePair<string, object>>? tags,
in PooledList<ZipkinAnnotation> annotations,
in PooledList<KeyValuePair<string, object>> tags,
bool? debug,
bool? shared)
{
@ -89,9 +89,9 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
public ZipkinEndpoint RemoteEndpoint { get; }
public PooledList<ZipkinAnnotation>? Annotations { get; }
public PooledList<ZipkinAnnotation> Annotations { get; }
public PooledList<KeyValuePair<string, object>>? Tags { get; }
public PooledList<KeyValuePair<string, object>> Tags { get; }
public bool? Debug { get; }
@ -99,8 +99,8 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
public void Return()
{
this.Annotations?.Return();
this.Tags?.Return();
this.Annotations.Return();
this.Tags.Return();
}
#if NET452
@ -168,12 +168,12 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
this.RemoteEndpoint.Write(writer);
}
if (this.Annotations.HasValue)
if (!this.Annotations.IsEmpty)
{
writer.WritePropertyName("annotations");
writer.WriteStartArray();
foreach (var annotation in this.Annotations.Value)
foreach (var annotation in this.Annotations)
{
writer.WriteStartObject();
@ -189,7 +189,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
writer.WriteEndArray();
}
if (this.Tags.HasValue || this.LocalEndpoint.Tags != null)
if (!this.Tags.IsEmpty || this.LocalEndpoint.Tags != null)
{
writer.WritePropertyName("tags");
writer.WriteStartObject();
@ -203,13 +203,13 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
foreach (var tag in this.LocalEndpoint.Tags ?? Enumerable.Empty<KeyValuePair<string, object>>())
{
writer.WritePropertyName(tag.Key);
writer.WriteValue(this.ConvertObjectToString(tag.Value));
writer.WriteValue(ConvertObjectToString(tag.Value));
}
foreach (var tag in this.Tags ?? Enumerable.Empty<KeyValuePair<string, object>>())
foreach (var tag in this.Tags)
{
writer.WritePropertyName(tag.Key);
writer.WriteValue(this.ConvertObjectToString(tag.Value));
writer.WriteValue(ConvertObjectToString(tag.Value));
}
}
finally
@ -278,12 +278,12 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
this.RemoteEndpoint.Write(writer);
}
if (this.Annotations.HasValue)
if (!this.Annotations.IsEmpty)
{
writer.WritePropertyName("annotations");
writer.WriteStartArray();
foreach (var annotation in this.Annotations.Value)
foreach (var annotation in this.Annotations)
{
writer.WriteStartObject();
@ -297,7 +297,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
writer.WriteEndArray();
}
if (this.Tags.HasValue || this.LocalEndpoint.Tags != null)
if (!this.Tags.IsEmpty || this.LocalEndpoint.Tags != null)
{
writer.WritePropertyName("tags");
writer.WriteStartObject();
@ -310,12 +310,12 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
{
foreach (var tag in this.LocalEndpoint.Tags ?? Enumerable.Empty<KeyValuePair<string, object>>())
{
writer.WriteString(tag.Key, this.ConvertObjectToString(tag.Value));
writer.WriteString(tag.Key, ConvertObjectToString(tag.Value));
}
foreach (var tag in this.Tags ?? Enumerable.Empty<KeyValuePair<string, object>>())
foreach (var tag in this.Tags)
{
writer.WriteString(tag.Key, this.ConvertObjectToString(tag.Value));
writer.WriteString(tag.Key, ConvertObjectToString(tag.Value));
}
}
finally
@ -332,17 +332,24 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private string ConvertObjectToString(object obj)
private static string ConvertObjectToString(object obj)
{
return obj switch
{
string stringVal => stringVal,
bool boolVal => GetBoolString(boolVal),
int[] arrayValue => string.Join(",", arrayValue),
long[] arrayValue => string.Join(",", arrayValue),
double[] arrayValue => string.Join(",", arrayValue),
bool[] arrayValue => string.Join(",", arrayValue),
bool[] arrayValue => string.Join(",", arrayValue.Select(GetBoolString)),
_ => obj.ToString(),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string GetBoolString(bool value)
{
return value ? "true" : "false";
}
}
}

View File

@ -116,7 +116,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
Assert.Equal("string_array", eventField.Key);
Assert.Equal("b", eventField.VStr);
eventField = eventFields[3];
Assert.Equal("message", eventField.Key);
Assert.Equal("event", eventField.Key);
Assert.Equal("Event1", eventField.VStr);
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
@ -128,7 +128,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
Assert.Equal("key", eventField.Key);
Assert.Equal("value", eventField.VStr);
eventField = eventFields[1];
Assert.Equal("message", eventField.Key);
Assert.Equal("event", eventField.Key);
Assert.Equal("Event2", eventField.VStr);
}
@ -175,7 +175,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
Assert.Equal("key", eventField.Key);
Assert.Equal("value", eventField.VStr);
eventField = eventFields[3];
Assert.Equal("message", eventField.Key);
Assert.Equal("event", eventField.Key);
Assert.Equal("Event1", eventField.VStr);
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
@ -187,7 +187,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
Assert.Equal("key", eventField.Key);
Assert.Equal("value", eventField.VStr);
eventField = eventFields[1];
Assert.Equal("message", eventField.Key);
Assert.Equal("event", eventField.Key);
Assert.Equal("Event2", eventField.VStr);
}
@ -340,7 +340,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
Assert.Equal("key", eventField.Key);
Assert.Equal("value", eventField.VStr);
eventField = eventFields[3];
Assert.Equal("message", eventField.Key);
Assert.Equal("event", eventField.Key);
Assert.Equal("Event1", eventField.VStr);
Assert.Equal(activity.Events.First().Timestamp.ToEpochMicroseconds(), jaegerLog.Timestamp);
@ -351,7 +351,7 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
Assert.Equal("key", eventField.Key);
Assert.Equal("value", eventField.VStr);
eventField = eventFields[1];
Assert.Equal("message", eventField.Key);
Assert.Equal("event", eventField.Key);
Assert.Equal("Event2", eventField.VStr);
}
@ -456,6 +456,18 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests.Implementation
var jaegerSpan = activity.ToJaegerSpan();
// Assert
if (statusCode == StatusCode.Unset)
{
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == SpanAttributeConstants.StatusCodeKey);
}
else
{
Assert.Equal(
StatusHelper.GetStringNameForStatusCode(statusCode),
jaegerSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).VStr);
}
if (hasErrorFlag)
{
Assert.Contains(jaegerSpan.Tags, t => t.Key == "error" && t.VType == JaegerTagType.BOOL && (t.VBool ?? false));

View File

@ -17,6 +17,7 @@
using System;
using System.Linq;
using OpenTelemetry.Exporter.Zipkin.Implementation;
using OpenTelemetry.Internal;
using OpenTelemetry.Trace;
using Xunit;
@ -45,7 +46,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
Assert.Equal((long)(activity.Duration.TotalMilliseconds * 1000), zipkinSpan.Duration);
int counter = 0;
var tagsArray = zipkinSpan.Tags.Value.ToArray();
var tagsArray = zipkinSpan.Tags.ToArray();
foreach (var tags in activity.TagObjects)
{
@ -70,12 +71,12 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
var zipkinSpan = activity.ToZipkinSpan(DefaultZipkinEndpoint);
Assert.Equal(ZipkinSpanName, zipkinSpan.Name);
Assert.Empty(zipkinSpan.Annotations.Value);
Assert.Empty(zipkinSpan.Annotations);
Assert.Equal(activity.TraceId.ToHexString(), zipkinSpan.TraceId);
Assert.Equal(activity.SpanId.ToHexString(), zipkinSpan.Id);
int counter = 0;
var tagsArray = zipkinSpan.Tags.Value.ToArray();
var tagsArray = zipkinSpan.Tags.ToArray();
foreach (var tags in activity.TagObjects)
{
@ -108,13 +109,25 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests.Implementation
var zipkinSpan = activity.ToZipkinSpan(DefaultZipkinEndpoint);
// Assert
if (hasErrorFlag)
if (statusCode == StatusCode.Unset)
{
Assert.Contains(zipkinSpan.Tags.Value, t => t.Key == "error" && (string)t.Value == "true");
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == SpanAttributeConstants.StatusCodeKey);
}
else
{
Assert.DoesNotContain(zipkinSpan.Tags.Value, t => t.Key == "error");
Assert.Equal(
StatusHelper.GetStringNameForStatusCode(statusCode),
zipkinSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).Value);
}
if (hasErrorFlag)
{
Assert.Contains(zipkinSpan.Tags, t => t.Key == "error" && (string)t.Value == "true");
}
else
{
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == "error");
}
}
}

View File

@ -193,7 +193,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests
var traceId = useShortTraceIds ? TraceId.Substring(TraceId.Length - 16, 16) : TraceId;
Assert.Equal(
$@"[{{""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/"",""otel.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"",""boolArrayKey"":""true,false"",""http.host"":""http://localhost:44312/"",""otel.library.name"":""CreateTestActivity"",""peer.service"":""http://localhost:44312/""}}}}]",
Responses[requestId]);
}
@ -223,6 +223,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests
{ "doubleKey2", 1F },
{ "longArrayKey", new long[] { 1, 2 } },
{ "boolKey", true },
{ "boolArrayKey", new bool[] { true, false } },
{ "http.host", "http://localhost:44312/" }, // simulating instrumentation tag adding http.host
};
if (additionalAttributes != null)