Skip to content

Commit

Permalink
[HttpClient] Add error.type for traces and metrics (#5005)
Browse files Browse the repository at this point in the history
Co-authored-by: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com>
Co-authored-by: Timothy Mothra <tilee@microsoft.com>
Co-authored-by: Mikel Blanchard <mblanchard@macrosssoftware.com>
  • Loading branch information
4 people authored Nov 8, 2023
1 parent 91ed41f commit 4a3c8d3
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 81 deletions.
16 changes: 16 additions & 0 deletions src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@
`http` or `http/dup`.
([#5003](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5003))

* An additional attribute `error.type` will be added to activity and
`http.client.request.duration` metric in case of failed requests as per the
[specification](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#common-attributes).

Users moving to `net8.0` or newer frameworks from lower versions will see
difference in values in case of an exception. `net8.0` or newer frameworks add
the ability to further drill down the exceptions to a specific type through
[HttpRequestError](https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror?view=net-8.0)
enum. For lower versions, the individual types will be rolled in to a single
type. This could be a **breaking change** if alerts are set based on the values.

The attribute will only be added when `OTEL_SEMCONV_STABILITY_OPT_IN`
environment variable is set to `http` or `http/dup`.

([#5005](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5005))

## 1.6.0-beta.2

Released 2023-Oct-26
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ public void OnStopActivity(Activity activity, object payload)

if (TryFetchResponse(payload, out HttpResponseMessage response))
{
if (currentStatusCode == ActivityStatusCode.Unset)
{
activity.SetStatus(SpanHelper.ResolveSpanStatusForHttpStatusCode(activity.Kind, (int)response.StatusCode));
}

if (this.emitOldAttributes)
{
activity.SetTag(SemanticConventions.AttributeHttpStatusCode, TelemetryHelper.GetBoxedStatusCode(response.StatusCode));
Expand All @@ -279,11 +284,10 @@ public void OnStopActivity(Activity activity, object payload)
if (this.emitNewAttributes)
{
activity.SetTag(SemanticConventions.AttributeHttpResponseStatusCode, TelemetryHelper.GetBoxedStatusCode(response.StatusCode));
}

if (currentStatusCode == ActivityStatusCode.Unset)
{
activity.SetStatus(SpanHelper.ResolveSpanStatusForHttpStatusCode(activity.Kind, (int)response.StatusCode));
if (activity.Status == ActivityStatusCode.Error)
{
activity.SetTag(SemanticConventions.AttributeErrorType, TelemetryHelper.GetBoxedStatusCode(response.StatusCode));
}
}

try
Expand Down Expand Up @@ -337,6 +341,11 @@ public void OnException(Activity activity, object payload)
return;
}

if (this.emitNewAttributes)
{
activity.SetTag(SemanticConventions.AttributeErrorType, GetErrorType(exc));
}

if (this.options.RecordException)
{
activity.RecordException(exc);
Expand Down Expand Up @@ -372,4 +381,33 @@ static bool TryFetchException(object payload, out Exception exc)
return true;
}
}

private static string GetErrorType(Exception exc)
{
#if NET8_0_OR_GREATER
// For net8.0 and above exception type can be found using HttpRequestError.
// https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror?view=net-8.0
if (exc is HttpRequestException httpRequestException)
{
return httpRequestException.HttpRequestError switch
{
HttpRequestError.NameResolutionError => "name_resolution_error",
HttpRequestError.ConnectionError => "connection_error",
HttpRequestError.SecureConnectionError => "secure_connection_error",
HttpRequestError.HttpProtocolError => "http_protocol_error",
HttpRequestError.ExtendedConnectNotSupported => "extended_connect_not_supported",
HttpRequestError.VersionNegotiationError => "version_negotiation_error",
HttpRequestError.UserAuthenticationError => "user_authentication_error",
HttpRequestError.ProxyTunnelError => "proxy_tunnel_error",
HttpRequestError.InvalidResponse => "invalid_response",
HttpRequestError.ResponseEnded => "response_ended",
HttpRequestError.ConfigurationLimitExceeded => "configuration_limit_exceeded",

// Fall back to the exception type name in case of HttpRequestError.Unknown
_ => exc.GetType().FullName,
};
}
#endif
return exc.GetType().FullName;
}
}
Loading

0 comments on commit 4a3c8d3

Please sign in to comment.