Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Part1] Support Activity Status and status description in Zipkin Exporter. #3003

Merged
merged 33 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1ab2baa
initial commit
Yun-Ting Mar 9, 2022
573bcdf
Merge branch 'yunl/status' of https://github.com/Yun-Ting/opentelemet…
Yun-Ting Mar 9, 2022
f7c6482
Revert "initial commit"
Yun-Ting Mar 9, 2022
29c17bc
Revert "Revert "initial commit""
Yun-Ting Mar 9, 2022
2539d45
organize
Yun-Ting Mar 9, 2022
902d2ba
revert unrelated change
Yun-Ting Mar 10, 2022
8f8ca9e
changelog
Yun-Ting Mar 10, 2022
e708247
additional tags will not be dropped
Yun-Ting Mar 10, 2022
751fd0e
fix comment
Yun-Ting Mar 10, 2022
53733c3
fix integration test; tag order matters
Yun-Ting Mar 10, 2022
fddecd0
comment and nit
Yun-Ting Mar 11, 2022
91f83a9
bugs
Yun-Ting Mar 11, 2022
d934786
fix port
Yun-Ting Mar 11, 2022
3bb525b
comment, integration test, reorder
Yun-Ting Mar 11, 2022
0248d74
fix AV
Yun-Ting Mar 14, 2022
18593f5
Update src/OpenTelemetry.Api/CHANGELOG.md
Yun-Ting Mar 14, 2022
d0ceec8
Merge branch 'yunl/status' of https://github.com/Yun-Ting/opentelemet…
Yun-Ting Mar 14, 2022
af8835c
comment
Yun-Ting Mar 14, 2022
03094e5
Merge branch 'main' into yunl/status
Yun-Ting Mar 17, 2022
b0a0077
changelog
Yun-Ting Mar 17, 2022
ab085c8
comment on a comment
Yun-Ting Mar 17, 2022
b8bfa7a
testcase
Yun-Ting Mar 17, 2022
2901813
Merge branch 'main' into yunl/status
cijothomas Mar 17, 2022
3a4b310
comment
Yun-Ting Mar 18, 2022
cc46c97
Merge branch 'yunl/status' of https://github.com/Yun-Ting/opentelemet…
Yun-Ting Mar 18, 2022
9086968
changelog
Yun-Ting Mar 21, 2022
d009201
sacrificing perf for easier reviewer experience by not changing the t…
Yun-Ting Mar 21, 2022
380f514
fix error precedence
Yun-Ting Mar 21, 2022
900e84f
Merge branch 'main' into yunl/status
cijothomas Mar 22, 2022
ff54ea2
comment
Yun-Ting Mar 22, 2022
ac081d7
Merge branch 'yunl/status' of https://github.com/Yun-Ting/opentelemet…
Yun-Ting Mar 22, 2022
3216b16
trigger CI
Yun-Ting Mar 22, 2022
578d445
Update src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md
Yun-Ting Mar 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Support Activity Status and status description in Zipkin Exporter.
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved
([#3003](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3003))

## 1.2.0-rc3

Released 2022-Mar-04
Expand Down
18 changes: 18 additions & 0 deletions src/OpenTelemetry.Api/Internal/StatusHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// </copyright>

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using OpenTelemetry.Trace;

Expand Down Expand Up @@ -43,6 +44,23 @@ public static string GetTagValueForStatusCode(StatusCode statusCode)
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetTagValueForActivityStatusCode(ActivityStatusCode activityStatusCode)
{
return activityStatusCode switch
{
/*
* Note: Order here does matter for perf. Unset is
* first because assumption is most spans will be
* Unset, then Error, then Ok.
*/
ActivityStatusCode.Unset => UnsetStatusCodeTagValue,
ActivityStatusCode.Error => ErrorStatusCodeTagValue,
ActivityStatusCode.Ok => OkStatusCodeTagValue,
_ => null,
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static StatusCode? GetStatusCodeForTagValue(string statusCodeTagValue)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,20 @@ internal static ZipkinSpan ToZipkinSpan(this Activity activity, ZipkinEndpoint l
Tags = PooledList<KeyValuePair<string, object>>.Create(),
};

activity.EnumerateTags(ref tagState);
if (activity.Status == ActivityStatusCode.Ok || activity.Status == ActivityStatusCode.Error)
{
PooledList<KeyValuePair<string, object>>.Add(
ref tagState.Tags,
new KeyValuePair<string, object>(
SpanAttributeConstants.StatusCodeKey,
StatusHelper.GetTagValueForActivityStatusCode(activity.Status)));
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
// In the rare cases when both ActivityStatus and Status Tags were set,
// ActivityStatus takes precedence over status tags.
activity.EnumerateTags(ref tagState);
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved
}

var activitySource = activity.Source;
if (!string.IsNullOrEmpty(activitySource.Name))
Expand All @@ -72,9 +85,17 @@ internal static ZipkinSpan ToZipkinSpan(this Activity activity, ZipkinEndpoint l
}
}

if (tagState.StatusCode == StatusCode.Error)
// Error flag rule from https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/zipkin.md#status
if (activity.StatusDescription != null)
{
PooledList<KeyValuePair<string, object>>.Add(
Yun-Ting marked this conversation as resolved.
Show resolved Hide resolved
ref tagState.Tags,
new KeyValuePair<string, object>(
ZipkinErrorFlagTagName,
activity.StatusDescription ?? string.Empty));
}
else if (tagState.StatusCode == StatusCode.Error)
{
// Error flag rule from https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/zipkin.md#status
PooledList<KeyValuePair<string, object>>.Add(
ref tagState.Tags,
new KeyValuePair<string, object>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
// </copyright>

using System.Diagnostics;
using System.Linq;
using OpenTelemetry.Exporter.Zipkin.Tests;
using OpenTelemetry.Internal;
Expand Down Expand Up @@ -125,5 +126,74 @@ public void ToZipkinSpan_Status_ErrorFlagTest(StatusCode expectedStatusCode, str
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == "error");
}
}

[Theory]
[InlineData(ActivityStatusCode.Unset)]
[InlineData(ActivityStatusCode.Ok)]
[InlineData(ActivityStatusCode.Error)]
public void ToZipkinSpan_Activity_Status_And_StatusDescription_is_Set(ActivityStatusCode expectedStatusCode)
{
// Arrange
const string description = "Description when ActivityStatusCode is Error.";
var activity = ZipkinExporterTests.CreateTestActivity();
activity.SetStatus(expectedStatusCode, description);

// Act
var zipkinSpan = activity.ToZipkinSpan(DefaultZipkinEndpoint);

// Assert
if (expectedStatusCode == ActivityStatusCode.Unset)
{
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == SpanAttributeConstants.StatusCodeKey);
}
else
{
Assert.Equal(
StatusHelper.GetTagValueForActivityStatusCode(expectedStatusCode),
zipkinSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).Value);
}

if (expectedStatusCode == ActivityStatusCode.Error)
{
Assert.Contains(zipkinSpan.Tags, t => t.Key == "error" && (string)t.Value == description);
}
else
{
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == "error");
}
}

[Theory]
[InlineData(ActivityStatusCode.Error, "OK")]
[InlineData(ActivityStatusCode.Ok, "ERROR")]
public void ActivityStatus_Takes_precedence_Over_Status_Tags(ActivityStatusCode activityStatus, string statusCodeTagValue)
{
// Arrange
const string description = "Description when ActivityStatusCode is Error.";
var activity = ZipkinExporterTests.CreateTestActivity();

activity.SetStatus(activityStatus, description);
activity.SetTag(SpanAttributeConstants.StatusCodeKey, statusCodeTagValue);

// Act
var zipkinSpan = activity.ToZipkinSpan(DefaultZipkinEndpoint);

// Assert
Assert.Equal(
StatusHelper.GetTagValueForActivityStatusCode(activityStatus),
zipkinSpan.Tags.FirstOrDefault(t => t.Key == SpanAttributeConstants.StatusCodeKey).Value);

if (activityStatus == ActivityStatusCode.Error)
{
Assert.Contains(zipkinSpan.Tags, t => t.Key == "error" && (string)t.Value == description);

// ActivityStatusDescription takes higher precedence.
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == "error" && (string)t.Value == statusCodeTagValue);
}
else
{
Assert.DoesNotContain(zipkinSpan.Tags, t => t.Key == "error");
}
}
}
}