Exporter spec updates. (#1609)
* Exporter spec updates. * CHANGELOG updates. Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
This commit is contained in:
parent
9f27b4cfe4
commit
d3edc476e7
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue