[otlp] Switch to TagWriter for handling of tags/attributes (#5585)
This commit is contained in:
parent
e95ae72649
commit
ac0d1d1fab
|
|
@ -237,19 +237,18 @@ internal static class ActivityExtensions
|
|||
};
|
||||
|
||||
int maxTags = sdkLimitOptions.SpanLinkAttributeCountLimit ?? int.MaxValue;
|
||||
|
||||
var otlpLinkAttributes = otlpLink.Attributes;
|
||||
|
||||
foreach (ref readonly var tag in activityLink.EnumerateTagObjects())
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(tag, out var attribute, sdkLimitOptions.AttributeValueLengthLimit))
|
||||
if (otlpLinkAttributes.Count == maxTags)
|
||||
{
|
||||
if (otlpLink.Attributes.Count < maxTags)
|
||||
{
|
||||
otlpLink.Attributes.Add(attribute);
|
||||
}
|
||||
else
|
||||
{
|
||||
otlpLink.DroppedAttributesCount++;
|
||||
}
|
||||
otlpLink.DroppedAttributesCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref otlpLinkAttributes, tag, sdkLimitOptions.AttributeValueLengthLimit);
|
||||
}
|
||||
|
||||
otlpLink.Flags = ToOtlpSpanFlags(activityLink.Context.TraceFlags, activityLink.Context.IsRemote);
|
||||
|
|
@ -267,19 +266,18 @@ internal static class ActivityExtensions
|
|||
};
|
||||
|
||||
int maxTags = sdkLimitOptions.SpanEventAttributeCountLimit ?? int.MaxValue;
|
||||
|
||||
var otlpEventAttributes = otlpEvent.Attributes;
|
||||
|
||||
foreach (ref readonly var tag in activityEvent.EnumerateTagObjects())
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(tag, out var attribute, sdkLimitOptions.AttributeValueLengthLimit))
|
||||
if (otlpEventAttributes.Count == maxTags)
|
||||
{
|
||||
if (otlpEvent.Attributes.Count < maxTags)
|
||||
{
|
||||
otlpEvent.Attributes.Add(attribute);
|
||||
}
|
||||
else
|
||||
{
|
||||
otlpEvent.DroppedAttributesCount++;
|
||||
}
|
||||
otlpEvent.DroppedAttributesCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref otlpEventAttributes, tag, sdkLimitOptions.AttributeValueLengthLimit);
|
||||
}
|
||||
|
||||
return otlpEvent;
|
||||
|
|
@ -322,6 +320,8 @@ internal static class ActivityExtensions
|
|||
|
||||
public void EnumerateTags(Activity activity, int maxTags)
|
||||
{
|
||||
var otlpSpanAttributes = this.Span.Attributes;
|
||||
|
||||
foreach (ref readonly var tag in activity.EnumerateTagObjects())
|
||||
{
|
||||
if (tag.Value == null)
|
||||
|
|
@ -341,26 +341,22 @@ internal static class ActivityExtensions
|
|||
continue;
|
||||
}
|
||||
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(tag, out var attribute, this.SdkLimitOptions.AttributeValueLengthLimit))
|
||||
if (otlpSpanAttributes.Count == maxTags)
|
||||
{
|
||||
if (this.Span.Attributes.Count < maxTags)
|
||||
{
|
||||
this.Span.Attributes.Add(attribute);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Span.DroppedAttributesCount++;
|
||||
}
|
||||
this.Span.DroppedAttributesCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref otlpSpanAttributes, tag, this.SdkLimitOptions.AttributeValueLengthLimit);
|
||||
}
|
||||
|
||||
if (attribute.Value.ValueCase == AnyValue.ValueOneofCase.StringValue)
|
||||
{
|
||||
// Note: tag.Value is used and not attribute.Value here because attribute.Value may be truncated
|
||||
PeerServiceResolver.InspectTag(ref this, key, tag.Value as string);
|
||||
}
|
||||
else if (attribute.Value.ValueCase == AnyValue.ValueOneofCase.IntValue)
|
||||
{
|
||||
PeerServiceResolver.InspectTag(ref this, key, attribute.Value.IntValue);
|
||||
}
|
||||
if (tag.Value is string tagStringValue)
|
||||
{
|
||||
PeerServiceResolver.InspectTag(ref this, key, tagStringValue);
|
||||
}
|
||||
else if (tag.Value is int tagIntValue)
|
||||
{
|
||||
PeerServiceResolver.InspectTag(ref this, key, tagIntValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,12 +414,11 @@ internal static class MetricItemExtensions
|
|||
otlpExemplar.AsDouble = Convert.ToDouble(value);
|
||||
}
|
||||
|
||||
var otlpExemplarFilteredAttributes = otlpExemplar.FilteredAttributes;
|
||||
|
||||
foreach (var tag in exemplar.FilteredTags)
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(tag, out var result))
|
||||
{
|
||||
otlpExemplar.FilteredAttributes.Add(result);
|
||||
}
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref otlpExemplarFilteredAttributes, tag);
|
||||
}
|
||||
|
||||
return otlpExemplar;
|
||||
|
|
@ -429,10 +428,7 @@ internal static class MetricItemExtensions
|
|||
{
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(tag, out var result))
|
||||
{
|
||||
attributes.Add(result);
|
||||
}
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref attributes, tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,10 +436,7 @@ internal static class MetricItemExtensions
|
|||
{
|
||||
foreach (var tag in meterTags)
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(tag, out var result))
|
||||
{
|
||||
attributes.Add(result);
|
||||
}
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref attributes, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,15 +137,15 @@ internal sealed class OtlpLogRecordTransformer
|
|||
|
||||
if (!string.IsNullOrEmpty(logRecord.EventId.Name))
|
||||
{
|
||||
AddStringAttribute(otlpLogRecord, ExperimentalOptions.LogRecordEventNameAttribute, logRecord.EventId.Name, attributeValueLengthLimit, attributeCountLimit);
|
||||
AddStringAttribute(otlpLogRecord, ExperimentalOptions.LogRecordEventNameAttribute, logRecord.EventId.Name, attributeCountLimit, attributeValueLengthLimit);
|
||||
}
|
||||
}
|
||||
|
||||
if (logRecord.Exception != null)
|
||||
{
|
||||
AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name, attributeValueLengthLimit, attributeCountLimit);
|
||||
AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message, attributeValueLengthLimit, attributeCountLimit);
|
||||
AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString(), attributeValueLengthLimit, attributeCountLimit);
|
||||
AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name, attributeCountLimit, attributeValueLengthLimit);
|
||||
AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message, attributeCountLimit, attributeValueLengthLimit);
|
||||
AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString(), attributeCountLimit, attributeValueLengthLimit);
|
||||
}
|
||||
|
||||
bool bodyPopulatedFromFormattedMessage = false;
|
||||
|
|
@ -166,9 +166,9 @@ internal sealed class OtlpLogRecordTransformer
|
|||
{
|
||||
otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = attribute.Value as string };
|
||||
}
|
||||
else if (OtlpTagTransformer.Instance.TryTransformTag(attribute, out var result, attributeValueLengthLimit))
|
||||
else
|
||||
{
|
||||
AddAttribute(otlpLogRecord, result, attributeCountLimit);
|
||||
AddAttribute(otlpLogRecord, attribute, attributeCountLimit, attributeValueLengthLimit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -224,10 +224,7 @@ internal sealed class OtlpLogRecordTransformer
|
|||
}
|
||||
else
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(scopeItem, out var result, attributeValueLengthLimit))
|
||||
{
|
||||
AddAttribute(otlpLog, result, attributeCountLimit);
|
||||
}
|
||||
AddAttribute(otlpLog, scopeItem, attributeCountLimit, attributeValueLengthLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -241,36 +238,34 @@ internal sealed class OtlpLogRecordTransformer
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AddAttribute(OtlpLogs.LogRecord logRecord, OtlpCommon.KeyValue attribute, int maxAttributeCount)
|
||||
private static void AddAttribute(OtlpLogs.LogRecord logRecord, KeyValuePair<string, object> attribute, int maxAttributeCount, int? maxValueLength)
|
||||
{
|
||||
if (logRecord.Attributes.Count < maxAttributeCount)
|
||||
var logRecordAttributes = logRecord.Attributes;
|
||||
|
||||
if (logRecordAttributes.Count == maxAttributeCount)
|
||||
{
|
||||
logRecord.Attributes.Add(attribute);
|
||||
logRecord.DroppedAttributesCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
logRecord.DroppedAttributesCount++;
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref logRecordAttributes, attribute, maxValueLength);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AddStringAttribute(OtlpLogs.LogRecord logRecord, string key, string value, int? maxValueLength, int maxAttributeCount)
|
||||
private static void AddStringAttribute(OtlpLogs.LogRecord logRecord, string key, string value, int maxAttributeCount, int? maxValueLength)
|
||||
{
|
||||
var attributeItem = new KeyValuePair<string, object>(key, value);
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(attributeItem, out var result, maxValueLength))
|
||||
{
|
||||
AddAttribute(logRecord, result, maxAttributeCount);
|
||||
}
|
||||
|
||||
AddAttribute(logRecord, attributeItem, maxAttributeCount, maxValueLength);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AddIntAttribute(OtlpLogs.LogRecord logRecord, string key, int value, int maxAttributeCount)
|
||||
{
|
||||
var attributeItem = new KeyValuePair<string, object>(key, value);
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(attributeItem, out var result))
|
||||
{
|
||||
AddAttribute(logRecord, result, maxAttributeCount);
|
||||
}
|
||||
|
||||
AddAttribute(logRecord, attributeItem, maxAttributeCount, maxValueLength: null);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System.Diagnostics;
|
||||
using OpenTelemetry.Internal;
|
||||
using OtlpCommon = OpenTelemetry.Proto.Common.V1;
|
||||
|
||||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
|
||||
|
||||
internal sealed class OtlpTagTransformer : TagTransformer<OtlpCommon.KeyValue>
|
||||
{
|
||||
private OtlpTagTransformer()
|
||||
{
|
||||
}
|
||||
|
||||
public static OtlpTagTransformer Instance { get; } = new();
|
||||
|
||||
protected override OtlpCommon.KeyValue TransformIntegralTag(string key, long value)
|
||||
{
|
||||
return new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) };
|
||||
}
|
||||
|
||||
protected override OtlpCommon.KeyValue TransformFloatingPointTag(string key, double value)
|
||||
{
|
||||
return new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) };
|
||||
}
|
||||
|
||||
protected override OtlpCommon.KeyValue TransformBooleanTag(string key, bool value)
|
||||
{
|
||||
return new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) };
|
||||
}
|
||||
|
||||
protected override OtlpCommon.KeyValue TransformStringTag(string key, string value)
|
||||
{
|
||||
return new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) };
|
||||
}
|
||||
|
||||
protected override OtlpCommon.KeyValue TransformArrayTag(string key, Array array)
|
||||
{
|
||||
var arrayValue = new OtlpCommon.ArrayValue();
|
||||
|
||||
foreach (var item in array)
|
||||
{
|
||||
arrayValue.Values.Add(ToAnyValue(item));
|
||||
}
|
||||
|
||||
return new OtlpCommon.KeyValue { Key = key, Value = new OtlpCommon.AnyValue { ArrayValue = arrayValue } };
|
||||
}
|
||||
|
||||
protected override void OnUnsupportedTagDropped(
|
||||
string tagKey,
|
||||
string tagValueTypeFullName)
|
||||
{
|
||||
OpenTelemetryProtocolExporterEventSource.Log.UnsupportedAttributeType(
|
||||
tagValueTypeFullName,
|
||||
tagKey);
|
||||
}
|
||||
|
||||
private static OtlpCommon.AnyValue ToAnyValue(long value)
|
||||
=> new() { IntValue = value };
|
||||
|
||||
private static OtlpCommon.AnyValue ToAnyValue(double value)
|
||||
=> new() { DoubleValue = value };
|
||||
|
||||
private static OtlpCommon.AnyValue ToAnyValue(bool value)
|
||||
=> new() { BoolValue = value };
|
||||
|
||||
private static OtlpCommon.AnyValue ToAnyValue(string value)
|
||||
=> new() { StringValue = value };
|
||||
|
||||
private static OtlpCommon.AnyValue ToAnyValue(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
return value switch
|
||||
{
|
||||
char => ToAnyValue(Convert.ToString(value)!),
|
||||
string s =>
|
||||
/* Note: No need to call TruncateString here. That is taken care of
|
||||
in base class via ConvertToStringArrayThenTransformArrayTag */
|
||||
ToAnyValue(s),
|
||||
bool b => ToAnyValue(b),
|
||||
byte b => ToAnyValue(b),
|
||||
sbyte b => ToAnyValue(b),
|
||||
short s => ToAnyValue(s),
|
||||
ushort s => ToAnyValue(s),
|
||||
int i => ToAnyValue(i),
|
||||
uint i => ToAnyValue(i),
|
||||
long l => ToAnyValue(l),
|
||||
float f => ToAnyValue(f),
|
||||
double d => ToAnyValue(d),
|
||||
_ => DefaultCase(value),
|
||||
};
|
||||
|
||||
static OtlpCommon.AnyValue DefaultCase(object value)
|
||||
{
|
||||
// Note: This should never be executed. In the base class the
|
||||
// default case in TransformArrayTagInternal converts everything
|
||||
// not explicitly supported to strings
|
||||
|
||||
Debug.Fail("Default case executed");
|
||||
|
||||
var stringValue = Convert.ToString(value);
|
||||
|
||||
if (stringValue == null)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
return ToAnyValue(stringValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#nullable enable
|
||||
|
||||
using Google.Protobuf.Collections;
|
||||
using OpenTelemetry.Internal;
|
||||
using OtlpCommon = OpenTelemetry.Proto.Common.V1;
|
||||
|
||||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
|
||||
|
||||
internal sealed class OtlpTagWriter : TagWriter<RepeatedField<OtlpCommon.KeyValue>, OtlpCommon.ArrayValue>
|
||||
{
|
||||
private OtlpTagWriter()
|
||||
: base(new OtlpArrayTagWriter())
|
||||
{
|
||||
}
|
||||
|
||||
public static OtlpTagWriter Instance { get; } = new();
|
||||
|
||||
internal static OtlpCommon.AnyValue ToAnyValue(long value)
|
||||
=> new() { IntValue = value };
|
||||
|
||||
internal static OtlpCommon.AnyValue ToAnyValue(double value)
|
||||
=> new() { DoubleValue = value };
|
||||
|
||||
internal static OtlpCommon.AnyValue ToAnyValue(bool value)
|
||||
=> new() { BoolValue = value };
|
||||
|
||||
internal static OtlpCommon.AnyValue ToAnyValue(string value)
|
||||
=> new() { StringValue = value };
|
||||
|
||||
protected override void WriteIntegralTag(ref RepeatedField<OtlpCommon.KeyValue> tags, string key, long value)
|
||||
{
|
||||
tags.Add(new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) });
|
||||
}
|
||||
|
||||
protected override void WriteFloatingPointTag(ref RepeatedField<OtlpCommon.KeyValue> tags, string key, double value)
|
||||
{
|
||||
tags.Add(new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) });
|
||||
}
|
||||
|
||||
protected override void WriteBooleanTag(ref RepeatedField<OtlpCommon.KeyValue> tags, string key, bool value)
|
||||
{
|
||||
tags.Add(new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) });
|
||||
}
|
||||
|
||||
protected override void WriteStringTag(ref RepeatedField<OtlpCommon.KeyValue> tags, string key, string value)
|
||||
{
|
||||
tags.Add(new OtlpCommon.KeyValue { Key = key, Value = ToAnyValue(value) });
|
||||
}
|
||||
|
||||
protected override void WriteArrayTag(ref RepeatedField<OtlpCommon.KeyValue> tags, string key, ref OtlpCommon.ArrayValue value)
|
||||
{
|
||||
tags.Add(new OtlpCommon.KeyValue
|
||||
{
|
||||
Key = key,
|
||||
Value = new OtlpCommon.AnyValue
|
||||
{
|
||||
ArrayValue = value,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnUnsupportedTagDropped(
|
||||
string tagKey,
|
||||
string tagValueTypeFullName)
|
||||
{
|
||||
OpenTelemetryProtocolExporterEventSource.Log.UnsupportedAttributeType(
|
||||
tagValueTypeFullName,
|
||||
tagKey);
|
||||
}
|
||||
|
||||
private sealed class OtlpArrayTagWriter : ArrayTagWriter<OtlpCommon.ArrayValue>
|
||||
{
|
||||
public override OtlpCommon.ArrayValue BeginWriteArray() => new();
|
||||
|
||||
public override void WriteNullValue(ref OtlpCommon.ArrayValue array)
|
||||
{
|
||||
array.Values.Add(new OtlpCommon.AnyValue());
|
||||
}
|
||||
|
||||
public override void WriteIntegralValue(ref OtlpCommon.ArrayValue array, long value)
|
||||
{
|
||||
array.Values.Add(ToAnyValue(value));
|
||||
}
|
||||
|
||||
public override void WriteFloatingPointValue(ref OtlpCommon.ArrayValue array, double value)
|
||||
{
|
||||
array.Values.Add(ToAnyValue(value));
|
||||
}
|
||||
|
||||
public override void WriteBooleanValue(ref OtlpCommon.ArrayValue array, bool value)
|
||||
{
|
||||
array.Values.Add(ToAnyValue(value));
|
||||
}
|
||||
|
||||
public override void WriteStringValue(ref OtlpCommon.ArrayValue array, string value)
|
||||
{
|
||||
array.Values.Add(ToAnyValue(value));
|
||||
}
|
||||
|
||||
public override void EndWriteArray(ref OtlpCommon.ArrayValue array)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,12 +13,11 @@ internal static class ResourceExtensions
|
|||
{
|
||||
var processResource = new OtlpResource.Resource();
|
||||
|
||||
var processResourceAttributes = processResource.Attributes;
|
||||
|
||||
foreach (KeyValuePair<string, object> attribute in resource.Attributes)
|
||||
{
|
||||
if (OtlpTagTransformer.Instance.TryTransformTag(attribute, out var result))
|
||||
{
|
||||
processResource.Attributes.Add(result);
|
||||
}
|
||||
OtlpTagWriter.Instance.TryWriteTag(ref processResourceAttributes, attribute);
|
||||
}
|
||||
|
||||
if (!processResource.Attributes.Any(kvp => kvp.Key == ResourceSemanticConventions.AttributeServiceName))
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="$(RepoRoot)\src\Shared\PeriodicExportingMetricReaderHelper.cs" Link="Includes\PeriodicExportingMetricReaderHelper.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\PeerServiceResolver.cs" Link="Includes\PeerServiceResolver.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\TagTransformer.cs" Link="Includes\TagTransformer.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\TagWriter\ArrayTagWriter.cs" Link="Includes\TagWriter\ArrayTagWriter.cs" />
|
||||
<Compile Include="$(RepoRoot)\src\Shared\TagWriter\TagWriter.cs" Link="Includes\TagWriter\TagWriter.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
|
||||
namespace OpenTelemetry.Internal;
|
||||
|
||||
|
|
@ -80,7 +79,7 @@ internal abstract class TagWriter<TTagState, TArrayState>
|
|||
default:
|
||||
try
|
||||
{
|
||||
var stringValue = TruncateString(Convert.ToString(tag.Value, CultureInfo.InvariantCulture), tagValueMaxLength);
|
||||
var stringValue = TruncateString(Convert.ToString(tag.Value/*TODO: , CultureInfo.InvariantCulture*/), tagValueMaxLength);
|
||||
if (stringValue == null)
|
||||
{
|
||||
return this.LogUnsupportedTagTypeAndReturnFalse(tag.Key, tag.Value);
|
||||
|
|
@ -203,7 +202,7 @@ internal abstract class TagWriter<TTagState, TArrayState>
|
|||
var item = array.GetValue(i);
|
||||
stringArray[i] = item == null
|
||||
? null
|
||||
: TruncateString(Convert.ToString(item, CultureInfo.InvariantCulture), tagValueMaxLength);
|
||||
: TruncateString(Convert.ToString(item/*TODO: , CultureInfo.InvariantCulture*/), tagValueMaxLength);
|
||||
}
|
||||
|
||||
this.WriteStringsToArray(ref arrayState, new(stringArray, 0, array.Length));
|
||||
|
|
@ -222,47 +221,47 @@ internal abstract class TagWriter<TTagState, TArrayState>
|
|||
{
|
||||
if (typeof(TItem) == typeof(char))
|
||||
{
|
||||
this.arrayWriter.WriteStringTag(ref arrayState, Convert.ToString((char)(object)item)!);
|
||||
this.arrayWriter.WriteStringValue(ref arrayState, Convert.ToString((char)(object)item)!);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(bool))
|
||||
{
|
||||
this.arrayWriter.WriteBooleanTag(ref arrayState, (bool)(object)item);
|
||||
this.arrayWriter.WriteBooleanValue(ref arrayState, (bool)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(byte))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (byte)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (byte)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(sbyte))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (sbyte)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (sbyte)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(short))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (short)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (short)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(ushort))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (ushort)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (ushort)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(int))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (int)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (int)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(uint))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (uint)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (uint)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(long))
|
||||
{
|
||||
this.arrayWriter.WriteIntegralTag(ref arrayState, (long)(object)item);
|
||||
this.arrayWriter.WriteIntegralValue(ref arrayState, (long)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(float))
|
||||
{
|
||||
this.arrayWriter.WriteFloatingPointTag(ref arrayState, (float)(object)item);
|
||||
this.arrayWriter.WriteFloatingPointValue(ref arrayState, (float)(object)item);
|
||||
}
|
||||
else if (typeof(TItem) == typeof(double))
|
||||
{
|
||||
this.arrayWriter.WriteFloatingPointTag(ref arrayState, (double)(object)item);
|
||||
this.arrayWriter.WriteFloatingPointValue(ref arrayState, (double)(object)item);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -279,11 +278,11 @@ internal abstract class TagWriter<TTagState, TArrayState>
|
|||
{
|
||||
if (item == null)
|
||||
{
|
||||
this.arrayWriter.WriteNullTag(ref arrayState);
|
||||
this.arrayWriter.WriteNullValue(ref arrayState);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.arrayWriter.WriteStringTag(ref arrayState, item);
|
||||
this.arrayWriter.WriteStringValue(ref arrayState, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
using Google.Protobuf.Collections;
|
||||
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
|
||||
using Xunit;
|
||||
using OtlpCommon = OpenTelemetry.Proto.Common.V1;
|
||||
|
|
@ -13,19 +14,19 @@ public class OtlpAttributeTests
|
|||
public void NullValueAttribute()
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", null);
|
||||
Assert.False(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var _));
|
||||
Assert.False(TryTransformTag(kvp, out var _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyArrays()
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", Array.Empty<int>());
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
|
||||
Assert.Empty(attribute.Value.ArrayValue.Values);
|
||||
|
||||
kvp = new KeyValuePair<string, object>("key", Array.Empty<object>());
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out attribute));
|
||||
Assert.True(TryTransformTag(kvp, out attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
|
||||
Assert.Empty(attribute.Value.ArrayValue.Values);
|
||||
}
|
||||
|
|
@ -48,7 +49,7 @@ public class OtlpAttributeTests
|
|||
public void IntegralTypesSupported(object value)
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", value);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
|
||||
switch (value)
|
||||
{
|
||||
|
|
@ -77,7 +78,7 @@ public class OtlpAttributeTests
|
|||
public void FloatingPointTypesSupported(object value)
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", value);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
|
||||
switch (value)
|
||||
{
|
||||
|
|
@ -104,7 +105,7 @@ public class OtlpAttributeTests
|
|||
public void BooleanTypeSupported(object value)
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", value);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
|
||||
switch (value)
|
||||
{
|
||||
|
|
@ -131,7 +132,7 @@ public class OtlpAttributeTests
|
|||
public void StringTypesSupported(object value)
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", value);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.StringValue, attribute.Value.ValueCase);
|
||||
Assert.Equal(Convert.ToString(value), attribute.Value.StringValue);
|
||||
}
|
||||
|
|
@ -143,12 +144,12 @@ public class OtlpAttributeTests
|
|||
var stringArray = new string[] { "a", "b", "c", string.Empty, null };
|
||||
|
||||
var kvp = new KeyValuePair<string, object>("key", charArray);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
|
||||
Assert.Equal(charArray.Select(x => x.ToString()), attribute.Value.ArrayValue.Values.Select(x => x.StringValue));
|
||||
|
||||
kvp = new KeyValuePair<string, object>("key", stringArray);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out attribute));
|
||||
Assert.True(TryTransformTag(kvp, out attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
|
||||
|
||||
for (var i = 0; i < stringArray.Length; ++i)
|
||||
|
|
@ -188,7 +189,7 @@ public class OtlpAttributeTests
|
|||
foreach (var value in testValues)
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", value);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.StringValue, attribute.Value.ValueCase);
|
||||
Assert.Equal(value.ToString(), attribute.Value.StringValue);
|
||||
}
|
||||
|
|
@ -196,7 +197,7 @@ public class OtlpAttributeTests
|
|||
foreach (var value in testArrayValues)
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", value);
|
||||
Assert.True(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var attribute));
|
||||
Assert.True(TryTransformTag(kvp, out var attribute));
|
||||
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
|
||||
|
||||
var array = value as Array;
|
||||
|
|
@ -220,10 +221,25 @@ public class OtlpAttributeTests
|
|||
public void ExceptionInToStringIsCaught()
|
||||
{
|
||||
var kvp = new KeyValuePair<string, object>("key", new MyToStringMethodThrowsAnException());
|
||||
Assert.False(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var _));
|
||||
Assert.False(TryTransformTag(kvp, out var _));
|
||||
|
||||
kvp = new KeyValuePair<string, object>("key", new object[] { 1, false, new MyToStringMethodThrowsAnException() });
|
||||
Assert.False(OtlpTagTransformer.Instance.TryTransformTag(kvp, out var _));
|
||||
Assert.False(TryTransformTag(kvp, out var _));
|
||||
}
|
||||
|
||||
private static bool TryTransformTag(KeyValuePair<string, object> tag, out OtlpCommon.KeyValue attribute)
|
||||
{
|
||||
var destination = new RepeatedField<OtlpCommon.KeyValue>();
|
||||
|
||||
if (OtlpTagWriter.Instance.TryWriteTag(ref destination, tag))
|
||||
{
|
||||
Assert.NotEmpty(destination);
|
||||
attribute = destination[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
attribute = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private class MyToStringMethodThrowsAnException
|
||||
|
|
|
|||
|
|
@ -61,6 +61,21 @@ internal static class OtlpTestHelpers
|
|||
AssertOtlpAttributeValue(stringArray[j], actual[i].Value.ArrayValue.Values[j]);
|
||||
}
|
||||
|
||||
expectedSize++;
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = (Array)current;
|
||||
|
||||
Assert.Equal(source.Length, actual[i].Value.ArrayValue.Values.Count);
|
||||
|
||||
for (int j = 0; j < source.Length; j++)
|
||||
{
|
||||
var item = source.GetValue(j);
|
||||
|
||||
AssertOtlpAttributeValue(item, actual[i].Value.ArrayValue.Values[j]);
|
||||
}
|
||||
|
||||
expectedSize++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ public class OtlpTraceExporterTests
|
|||
new KeyValuePair<string, object>("int_array", new int[] { 1, 2 }),
|
||||
new KeyValuePair<string, object>("double_array", new double[] { 1.0, 2.09 }),
|
||||
new KeyValuePair<string, object>("string_array", new string[] { "a", "b" }),
|
||||
new KeyValuePair<string, object>("datetime_array", new DateTime[] { DateTime.UtcNow, DateTime.Now }),
|
||||
};
|
||||
|
||||
foreach (var kvp in attributes)
|
||||
|
|
|
|||
Loading…
Reference in New Issue