Skip to content

Commit

Permalink
Fix handling of OTLP ArrayValue attributes (#3238)
Browse files Browse the repository at this point in the history
* Fix handling of OTLP ArrayValue attributes

* Update changelog

Co-authored-by: Cijo Thomas <[email protected]>
  • Loading branch information
alanwest and cijothomas authored May 2, 2022
1 parent f2b6671 commit dff1996
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 42 deletions.
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ option
can still be used with .NET5.0 apps.
([#3147](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3147))

* Fix handling of array-valued attributes for the OTLP trace exporter.
([#3238](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3238))

## 1.3.0-beta.1

Released 2022-Apr-15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ public bool ForEach(KeyValuePair<string, object> activityTag)
this.Created = true;
}

OtlpCommon.ArrayValue arrayValue;

switch (activityTag.Value)
{
case string s:
Expand All @@ -416,39 +418,49 @@ public bool ForEach(KeyValuePair<string, object> activityTag)
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { DoubleValue = d }));
break;
case int[] intArray:
arrayValue = new OtlpCommon.ArrayValue();
foreach (var item in intArray)
{
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { IntValue = item }));
arrayValue.Values.Add(new OtlpCommon.AnyValue { IntValue = item });
}

PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
break;
case double[] doubleArray:
arrayValue = new OtlpCommon.ArrayValue();
foreach (var item in doubleArray)
{
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { DoubleValue = item }));
arrayValue.Values.Add(new OtlpCommon.AnyValue { DoubleValue = item });
}

PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
break;
case bool[] boolArray:
arrayValue = new OtlpCommon.ArrayValue();
foreach (var item in boolArray)
{
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { BoolValue = item }));
arrayValue.Values.Add(new OtlpCommon.AnyValue { BoolValue = item });
}

PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
break;
case string[] stringArray:
arrayValue = new OtlpCommon.ArrayValue();
foreach (var item in stringArray)
{
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, item == null ? null : new OtlpCommon.AnyValue { StringValue = item }));
arrayValue.Values.Add(item == null ? new OtlpCommon.AnyValue() : new OtlpCommon.AnyValue { StringValue = item });
}

PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
break;
case long[] longArray:
arrayValue = new OtlpCommon.ArrayValue();
foreach (var item in longArray)
{
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { IntValue = item }));
arrayValue.Values.Add(new OtlpCommon.AnyValue { IntValue = item });
}

PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
break;
default:
PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { StringValue = activityTag.Value.ToString() }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,86 +33,84 @@ public static void AssertOtlpAttributes(
for (int i = 0; i < expectedAttributes.Count; i++)
{
var current = expectedAttributes[i].Value;
Assert.Equal(expectedAttributes[i].Key, actual[i].Key);

if (current.GetType().IsArray)
{
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, actual[i].Value.ValueCase);
if (current is bool[] boolArray)
{
int index = 0;
foreach (var item in boolArray)
Assert.Equal(boolArray.Length, actual[i].Value.ArrayValue.Values.Count);
for (var j = 0; j < boolArray.Length; ++j)
{
Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
AssertOtlpAttributeValue(item, actual[i + index]);
index++;
expectedSize++;
AssertOtlpAttributeValue(boolArray[j], actual[i].Value.ArrayValue.Values[j]);
}

expectedSize++;
}
else if (current is int[] intArray)
{
int index = 1;
foreach (var item in intArray)
Assert.Equal(intArray.Length, actual[i].Value.ArrayValue.Values.Count);
for (var j = 0; j < intArray.Length; ++j)
{
Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
AssertOtlpAttributeValue(item, actual[i + index]);
index++;
expectedSize++;
AssertOtlpAttributeValue(intArray[j], actual[i].Value.ArrayValue.Values[j]);
}

expectedSize++;
}
else if (current is double[] doubleArray)
{
int index = 2;
foreach (var item in doubleArray)
Assert.Equal(doubleArray.Length, actual[i].Value.ArrayValue.Values.Count);
for (var j = 0; j < doubleArray.Length; ++j)
{
Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
AssertOtlpAttributeValue(item, actual[i + index]);
index++;
expectedSize++;
AssertOtlpAttributeValue(doubleArray[j], actual[i].Value.ArrayValue.Values[j]);
}

expectedSize++;
}
else if (current is string[] stringArray)
{
int index = 3;
foreach (var item in stringArray)
Assert.Equal(stringArray.Length, actual[i].Value.ArrayValue.Values.Count);
for (var j = 0; j < stringArray.Length; ++j)
{
Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
AssertOtlpAttributeValue(item, actual[i + index]);
index++;
expectedSize++;
AssertOtlpAttributeValue(stringArray[j], actual[i].Value.ArrayValue.Values[j]);
}

expectedSize++;
}
}
else
{
Assert.Equal(expectedAttributes[i].Key, actual[i].Key);
AssertOtlpAttributeValue(current, actual[i]);
AssertOtlpAttributeValue(current, actual[i].Value);
expectedSize++;
}
}

Assert.Equal(expectedSize, actual.Count);
}

private static void AssertOtlpAttributeValue(object expected, OtlpCommon.KeyValue actual)
private static void AssertOtlpAttributeValue(object expected, OtlpCommon.AnyValue actual)
{
switch (expected)
{
case string s:
Assert.Equal(s, actual.Value.StringValue);
Assert.Equal(s, actual.StringValue);
break;
case bool b:
Assert.Equal(b, actual.Value.BoolValue);
Assert.Equal(b, actual.BoolValue);
break;
case long l:
Assert.Equal(l, actual.Value.IntValue);
Assert.Equal(l, actual.IntValue);
break;
case double d:
Assert.Equal(d, actual.Value.DoubleValue);
Assert.Equal(d, actual.DoubleValue);
break;
case int i:
Assert.Equal(i, actual.Value.IntValue);
Assert.Equal(i, actual.IntValue);
break;
default:
Assert.Equal(expected.ToString(), actual.Value.StringValue);
Assert.Equal(expected.ToString(), actual.StringValue);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,13 +333,12 @@ public void ToOtlpSpanActivitiesWithNullArrayTest()

Assert.NotNull(otlpSpan);

var stringArray = otlpSpan.Attributes.Where(kvp => kvp.Key == "stringArray").ToList();
var stringArray = otlpSpan.Attributes.FirstOrDefault(kvp => kvp.Key == "stringArray");

Assert.NotNull(stringArray);
Assert.Equal(3, stringArray.Count);
Assert.Equal("test", stringArray[0].Value.StringValue);
Assert.Equal(string.Empty, stringArray[1].Value.StringValue);
Assert.Null(stringArray[2].Value);
Assert.Equal("test", stringArray.Value.ArrayValue.Values[0].StringValue);
Assert.Equal(string.Empty, stringArray.Value.ArrayValue.Values[1].StringValue);
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.None, stringArray.Value.ArrayValue.Values[2].ValueCase);
}

[Theory]
Expand Down

0 comments on commit dff1996

Please sign in to comment.