Updating exporters to use TagObjects instead of Tags (#1000)
* Update ZipkinExporter to use TagObjects instead of Tags * Updating JaegerExporter to use TagObjects * Updating OtlpExporter to use TagObjects * removing unused using * Removing duplicated logic Co-authored-by: Cijo Thomas <cithomas@microsoft.com>
This commit is contained in:
parent
4f8c351420
commit
53a579f507
|
|
@ -48,11 +48,11 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
|
|||
[SemanticConventions.AttributeNetPeerIp] = 2,
|
||||
["peer.hostname"] = 2,
|
||||
["peer.address"] = 2,
|
||||
["http.host"] = 3, // peer.service for Http.
|
||||
["db.instance"] = 3, // peer.service for Redis.
|
||||
[SemanticConventions.AttributeHttpHost] = 3, // peer.service for Http.
|
||||
[SemanticConventions.AttributeDbInstance] = 3, // peer.service for Redis.
|
||||
};
|
||||
|
||||
private static readonly DictionaryEnumerator<string, string, TagState>.ForEachDelegate ProcessActivityTagRef = ProcessActivityTag;
|
||||
private static readonly DictionaryEnumerator<string, object, TagState>.ForEachDelegate ProcessActivityTagRef = ProcessActivityTag;
|
||||
private static readonly ListEnumerator<ActivityLink, PooledListState<JaegerSpanRef>>.ForEachDelegate ProcessActivityLinkRef = ProcessActivityLink;
|
||||
private static readonly ListEnumerator<ActivityEvent, PooledListState<JaegerLog>>.ForEachDelegate ProcessActivityEventRef = ProcessActivityEvent;
|
||||
private static readonly DictionaryEnumerator<string, object, PooledListState<JaegerTag>>.ForEachDelegate ProcessTagRef = ProcessTag;
|
||||
|
|
@ -64,8 +64,8 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
|
|||
Tags = PooledList<JaegerTag>.Create(),
|
||||
};
|
||||
|
||||
DictionaryEnumerator<string, string, TagState>.AllocationFreeForEach(
|
||||
activity.Tags,
|
||||
DictionaryEnumerator<string, object, TagState>.AllocationFreeForEach(
|
||||
activity.TagObjects,
|
||||
ref jaegerTags,
|
||||
ProcessActivityTagRef);
|
||||
|
||||
|
|
@ -217,23 +217,16 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
|
|||
|
||||
public static JaegerTag ToJaegerTag(this KeyValuePair<string, object> attribute)
|
||||
{
|
||||
switch (attribute.Value)
|
||||
return attribute.Value switch
|
||||
{
|
||||
case string s:
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: s);
|
||||
case int i:
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: Convert.ToInt64(i));
|
||||
case long l:
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: l);
|
||||
case float f:
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: Convert.ToDouble(f));
|
||||
case double d:
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: d);
|
||||
case bool b:
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.BOOL, vBool: b);
|
||||
}
|
||||
|
||||
return new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: attribute.Value.ToString());
|
||||
string s => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: s),
|
||||
int i => new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: Convert.ToInt64(i)),
|
||||
long l => new JaegerTag(attribute.Key, JaegerTagType.LONG, vLong: l),
|
||||
float f => new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: Convert.ToDouble(f)),
|
||||
double d => new JaegerTag(attribute.Key, JaegerTagType.DOUBLE, vDouble: d),
|
||||
bool b => new JaegerTag(attribute.Key, JaegerTagType.BOOL, vBool: b),
|
||||
_ => new JaegerTag(attribute.Key, JaegerTagType.STRING, vStr: attribute.Value.ToString()),
|
||||
};
|
||||
}
|
||||
|
||||
public static long ToEpochMicroseconds(this DateTime utcDateTime)
|
||||
|
|
@ -256,9 +249,9 @@ namespace OpenTelemetry.Exporter.Jaeger.Implementation
|
|||
return microseconds - UnixEpochMicroseconds;
|
||||
}
|
||||
|
||||
private static bool ProcessActivityTag(ref TagState state, KeyValuePair<string, string> activityTag)
|
||||
private static bool ProcessActivityTag(ref TagState state, KeyValuePair<string, object> activityTag)
|
||||
{
|
||||
var jaegerTag = new JaegerTag(activityTag.Key, JaegerTagType.STRING, activityTag.Value);
|
||||
JaegerTag jaegerTag = activityTag.ToJaegerTag();
|
||||
|
||||
if (jaegerTag.VStr != null
|
||||
&& PeerServiceKeyResolutionDictionary.TryGetValue(activityTag.Key, out int priority)
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation
|
|||
EndTimeUnixNano = (ulong)(startTimeUnixNano + activity.Duration.ToNanoseconds()),
|
||||
};
|
||||
|
||||
foreach (var kvp in activity.Tags)
|
||||
foreach (var kvp in activity.TagObjects)
|
||||
{
|
||||
var attribute = ToOtlpAttribute(kvp);
|
||||
if (attribute != null && attribute.Key != SpanAttributeConstants.StatusCodeKey && attribute.Key != SpanAttributeConstants.StatusDescriptionKey)
|
||||
|
|
@ -219,39 +219,6 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation
|
|||
return otlpEvent;
|
||||
}
|
||||
|
||||
private static OtlpCommon.KeyValue ToOtlpAttribute(KeyValuePair<string, string> kvp)
|
||||
{
|
||||
// TODO: enforce no duplicate keys?
|
||||
// TODO: reverse?
|
||||
// To maintain full fidelity to downstream receivers convert to the proper attribute types
|
||||
|
||||
if (kvp.Value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } };
|
||||
|
||||
if (long.TryParse(kvp.Value, out var longValue))
|
||||
{
|
||||
attrib.Value.IntValue = longValue;
|
||||
}
|
||||
else if (double.TryParse(kvp.Value, out var doubleValue))
|
||||
{
|
||||
attrib.Value.DoubleValue = doubleValue;
|
||||
}
|
||||
else if (bool.TryParse(kvp.Value, out var boolValue))
|
||||
{
|
||||
attrib.Value.BoolValue = boolValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
attrib.Value.StringValue = kvp.Value;
|
||||
}
|
||||
|
||||
return attrib;
|
||||
}
|
||||
|
||||
private static OtlpCommon.KeyValue ToOtlpAttribute(KeyValuePair<string, object> kvp)
|
||||
{
|
||||
if (kvp.Value == null)
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
[SemanticConventions.AttributeNetPeerIp] = 2,
|
||||
["peer.hostname"] = 2,
|
||||
["peer.address"] = 2,
|
||||
["http.host"] = 3, // RemoteEndpoint.ServiceName for Http.
|
||||
["db.instance"] = 3, // RemoteEndpoint.ServiceName for Redis.
|
||||
[SemanticConventions.AttributeHttpHost] = 3, // RemoteEndpoint.ServiceName for Http.
|
||||
[SemanticConventions.AttributeDbInstance] = 3, // RemoteEndpoint.ServiceName for Redis.
|
||||
};
|
||||
|
||||
private static readonly string InvalidSpanId = default(ActivitySpanId).ToHexString();
|
||||
|
|
@ -46,7 +46,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
private static readonly ConcurrentDictionary<string, ZipkinEndpoint> LocalEndpointCache = new ConcurrentDictionary<string, ZipkinEndpoint>();
|
||||
private static readonly ConcurrentDictionary<string, ZipkinEndpoint> RemoteEndpointCache = new ConcurrentDictionary<string, ZipkinEndpoint>();
|
||||
|
||||
private static readonly DictionaryEnumerator<string, string, AttributeEnumerationState>.ForEachDelegate ProcessTagsRef = ProcessTags;
|
||||
private static readonly DictionaryEnumerator<string, object, AttributeEnumerationState>.ForEachDelegate ProcessTagsRef = ProcessTags;
|
||||
private static readonly ListEnumerator<ActivityEvent, PooledList<ZipkinAnnotation>>.ForEachDelegate ProcessActivityEventsRef = ProcessActivityEvents;
|
||||
|
||||
internal static ZipkinSpan ToZipkinSpan(this Activity activity, ZipkinEndpoint defaultLocalEndpoint, bool useShortTraceIds = false)
|
||||
|
|
@ -62,18 +62,18 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
|
||||
var attributeEnumerationState = new AttributeEnumerationState
|
||||
{
|
||||
Tags = PooledList<KeyValuePair<string, string>>.Create(),
|
||||
Tags = PooledList<KeyValuePair<string, object>>.Create(),
|
||||
};
|
||||
|
||||
DictionaryEnumerator<string, string, AttributeEnumerationState>.AllocationFreeForEach(activity.Tags, ref attributeEnumerationState, ProcessTagsRef);
|
||||
DictionaryEnumerator<string, object, AttributeEnumerationState>.AllocationFreeForEach(activity.TagObjects, ref attributeEnumerationState, ProcessTagsRef);
|
||||
|
||||
var activitySource = activity.Source;
|
||||
if (!string.IsNullOrEmpty(activitySource.Name))
|
||||
{
|
||||
PooledList<KeyValuePair<string, string>>.Add(ref attributeEnumerationState.Tags, new KeyValuePair<string, string>("library.name", activitySource.Name));
|
||||
PooledList<KeyValuePair<string, object>>.Add(ref attributeEnumerationState.Tags, new KeyValuePair<string, object>("library.name", activitySource.Name));
|
||||
if (!string.IsNullOrEmpty(activitySource.Version))
|
||||
{
|
||||
PooledList<KeyValuePair<string, string>>.Add(ref attributeEnumerationState.Tags, new KeyValuePair<string, string>("library.version", activitySource.Version));
|
||||
PooledList<KeyValuePair<string, object>>.Add(ref attributeEnumerationState.Tags, new KeyValuePair<string, object>("library.version", activitySource.Version));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,19 +161,14 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
|
||||
private static string ToActivityKind(Activity activity)
|
||||
{
|
||||
switch (activity.Kind)
|
||||
return activity.Kind switch
|
||||
{
|
||||
case ActivityKind.Server:
|
||||
return "SERVER";
|
||||
case ActivityKind.Producer:
|
||||
return "PRODUCER";
|
||||
case ActivityKind.Consumer:
|
||||
return "CONSUMER";
|
||||
case ActivityKind.Client:
|
||||
return "CLIENT";
|
||||
}
|
||||
|
||||
return null;
|
||||
ActivityKind.Server => "SERVER",
|
||||
ActivityKind.Producer => "PRODUCER",
|
||||
ActivityKind.Consumer => "CONSUMER",
|
||||
ActivityKind.Client => "CLIENT",
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
private static bool ProcessActivityEvents(ref PooledList<ZipkinAnnotation> annotations, ActivityEvent @event)
|
||||
|
|
@ -182,10 +177,10 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool ProcessTags(ref AttributeEnumerationState state, KeyValuePair<string, string> attribute)
|
||||
private static bool ProcessTags(ref AttributeEnumerationState state, KeyValuePair<string, object> attribute)
|
||||
{
|
||||
string key = attribute.Key;
|
||||
string strVal = attribute.Value;
|
||||
string strVal = attribute.Value as string;
|
||||
|
||||
if (strVal != null)
|
||||
{
|
||||
|
|
@ -205,12 +200,12 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
}
|
||||
else
|
||||
{
|
||||
PooledList<KeyValuePair<string, string>>.Add(ref state.Tags, new KeyValuePair<string, string>(key, strVal));
|
||||
PooledList<KeyValuePair<string, object>>.Add(ref state.Tags, new KeyValuePair<string, object>(key, strVal));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PooledList<KeyValuePair<string, string>>.Add(ref state.Tags, new KeyValuePair<string, string>(key, strVal));
|
||||
PooledList<KeyValuePair<string, object>>.Add(ref state.Tags, new KeyValuePair<string, object>(key, strVal));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -218,7 +213,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
|
||||
private struct AttributeEnumerationState
|
||||
{
|
||||
public PooledList<KeyValuePair<string, string>> Tags;
|
||||
public PooledList<KeyValuePair<string, object>> Tags;
|
||||
|
||||
public string RemoteEndpointServiceName;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
ZipkinEndpoint localEndpoint,
|
||||
ZipkinEndpoint remoteEndpoint,
|
||||
in PooledList<ZipkinAnnotation>? annotations,
|
||||
in PooledList<KeyValuePair<string, string>>? tags,
|
||||
in PooledList<KeyValuePair<string, object>>? tags,
|
||||
bool? debug,
|
||||
bool? shared)
|
||||
{
|
||||
|
|
@ -86,7 +86,7 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
|
||||
public PooledList<ZipkinAnnotation>? Annotations { get; }
|
||||
|
||||
public PooledList<KeyValuePair<string, string>>? Tags { get; }
|
||||
public PooledList<KeyValuePair<string, object>>? Tags { get; }
|
||||
|
||||
public bool? Debug { get; }
|
||||
|
||||
|
|
@ -282,7 +282,28 @@ namespace OpenTelemetry.Exporter.Zipkin.Implementation
|
|||
|
||||
foreach (var tag in this.Tags.Value)
|
||||
{
|
||||
writer.WriteString(tag.Key, tag.Value);
|
||||
if (tag.Value is int intValue)
|
||||
{
|
||||
writer.WriteNumber(tag.Key, intValue);
|
||||
}
|
||||
else if (tag.Value is bool boolVal)
|
||||
{
|
||||
writer.WriteBoolean(tag.Key, boolVal);
|
||||
}
|
||||
else if (tag.Value is double doubleVal)
|
||||
{
|
||||
writer.WriteNumber(tag.Key, doubleVal);
|
||||
}
|
||||
else if (tag.Value is string stringVal)
|
||||
{
|
||||
writer.WriteString(tag.Key, stringVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should we try to convert to string? Or
|
||||
// just drop it?
|
||||
writer.WriteString(tag.Key, tag.Value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
|
|||
|
||||
foreach (var kvp in attributes)
|
||||
{
|
||||
rootActivity.SetTag(kvp.Key, kvp.Value.ToString());
|
||||
rootActivity.SetTag(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
var startTime = new DateTime(2020, 02, 20, 20, 20, 20, DateTimeKind.Utc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue