Add Additional Standard Tags in AddAspNetCoreInstrumentation
See original GitHub issueFeature Request
Is your feature request related to a problem?
There are several tags specified by the open telemetry specification that are not logged by default in AddAspNetCoreInstrumentation
. It would be nice if we could add an option to log them too.
Describe the solution you’d like:
I currently use the following code to log them:
options.Enrich = (activity, eventName, obj) =>
{
if (obj is HttpRequest request)
{
var context = request.HttpContext;
activity.AddTag(OpenTelemetryAttributeName.Http.Flavor, GetHttpFlavour(request.Protocol));
activity.AddTag(OpenTelemetryAttributeName.Http.Scheme, request.Scheme);
activity.AddTag(OpenTelemetryAttributeName.Http.ClientIP, context.Connection.RemoteIpAddress);
activity.AddTag(OpenTelemetryAttributeName.Http.RequestContentLength, request.ContentLength);
activity.AddTag(OpenTelemetryAttributeName.Http.RequestContentType, request.ContentType);
var user = context.User;
if (user.Identity?.Name is not null)
{
activity.AddTag(OpenTelemetryAttributeName.EndUser.Id, user.Identity.Name);
activity.AddTag(OpenTelemetryAttributeName.EndUser.Scope, string.Join(',', user.Claims.Select(x => x.Value)));
}
}
else if (obj is HttpResponse response)
{
activity.AddTag(OpenTelemetryAttributeName.Http.ResponseContentLength, response.ContentLength);
activity.AddTag(OpenTelemetryAttributeName.Http.ResponseContentType, response.ContentType);
}
static string GetHttpFlavour(string protocol)
{
if (HttpProtocol.IsHttp10(protocol))
{
return HttpFlavour.Http10;
}
else if (HttpProtocol.IsHttp11(protocol))
{
return HttpFlavour.Http11;
}
else if (HttpProtocol.IsHttp2(protocol))
{
return HttpFlavour.Http20;
}
else if (HttpProtocol.IsHttp3(protocol))
{
return HttpFlavour.Http30;
}
throw new InvalidOperationException($"Protocol {protocol} not recognised.");
}
};
/// <summary>
/// Constants for semantic attribute names outlined by the OpenTelemetry specifications.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/README.md"/>.
/// </summary>
public static class OpenTelemetryAttributeName
{
/// <summary>
/// Constants for deployment semantic attribute names outlined by the OpenTelemetry specifications.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/11cc73939a32e3a2e6f11bdeab843c61cf8594e9/specification/resource/semantic_conventions/deployment_environment.md"/>.
/// </summary>
public static class Deployment
{
/// <summary>
/// The name of the deployment environment (aka deployment tier).
/// </summary>
/// <example>staging; production.</example>
public const string Environment = "deployment.environment";
}
/// <summary>
/// Constants for end user semantic attribute names outlined by the OpenTelemetry specifications.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/span-general.md"/>.
/// </summary>
public static class EndUser
{
/// <summary>
/// Username or client_id extracted from the access token or Authorization header in the inbound request from outside the system.
/// </summary>
/// <example>E.g. username.</example>
public const string Id = "enduser.id";
/// <summary>
/// Actual/assumed role the client is making the request under extracted from token or application security context.
/// </summary>
/// <example>E.g. admin.</example>
public const string Role = "enduser.role";
/// <summary>
/// Scopes or granted authorities the client currently possesses extracted from token or application security context.
/// The value would come from the scope associated with an OAuth 2.0 Access Token or an attribute value in a SAML 2.0 Assertion.
/// </summary>
/// <example>E.g. read:message,write:files.</example>
public const string Scope = "enduser.scope";
}
/// <summary>
/// Constants for HTTP semantic attribute names outlined by the OpenTelemetry specifications.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md"/>.
/// </summary>
public static class Http
{
/// <summary>
/// The URI scheme identifying the used protocol.
/// </summary>
/// <example>E.g. http or https.</example>
public const string Scheme = "http.scheme";
/// <summary>
/// Kind of HTTP protocol used.
/// </summary>
/// <example>E.g. 1.0, 1.1, 2.0, SPDY or QUIC.</example>
public const string Flavor = "http.flavor";
/// <summary>
/// The IP address of the original client behind all proxies, if known (e.g. from X-Forwarded-For).
/// </summary>
/// <example>E.g. 83.164.160.102.</example>
public const string ClientIP = "http.client_ip";
/// <summary>
/// The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often,
/// but not always, present as the Content-Length header. For requests using transport encoding, this should be the
/// compressed size.
/// </summary>
/// <example>E.g. 3495.</example>
public const string RequestContentLength = "http.request_content_length";
/// <summary>
/// The content type of the request body.
/// </summary>
/// <example>E.g. application/json.</example>
public const string RequestContentType = "http.request_content_type";
/// <summary>
/// The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often,
/// but not always, present as the Content-Length header. For requests using transport encoding, this should be the
/// compressed size.
/// </summary>
/// <example>E.g. 3495.</example>
public const string ResponseContentLength = "http.response_content_length";
/// <summary>
/// The content type of the response body.
/// </summary>
/// <example>E.g. application/json.</example>
public const string ResponseContentType = "http.response_content_type";
}
/// <summary>
/// Constants for host semantic attribute names outlined by the OpenTelemetry specifications.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/11cc73939a32e3a2e6f11bdeab843c61cf8594e9/specification/resource/semantic_conventions/host.md"/>.
/// </summary>
public static class Host
{
/// <summary>
/// Name of the host. On Unix systems, it may contain what the hostname command returns, or the fully qualified hostname,
/// or another name specified by the user.
/// </summary>
/// <example>E.g. opentelemetry-test.</example>
public const string Name = "host.name";
}
/// <summary>
/// Constants for service semantic attribute names outlined by the OpenTelemetry specifications.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/messaging.md"/>.
/// </summary>
public static class Service
{
/// <summary>
/// The name of the service sending messages.
/// </summary>
public const string Name = "service.name";
}
}
Describe alternatives you’ve considered.
Currently using the Enrich
method to add additional tags but would be nice if these were built in as they are defined by the specification.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:4
- Comments:5 (1 by maintainers)
Top Results From Across the Web
NET OpenTelemetry auto-instrumentation
Additional attributes can be added here as comma-separated key=value pairs. Add the deployment.environment=[environment-name] tag as needed ...
Read more >OpenTelemetry .NET: All you need to know
Add attributes to your span by calling activity.SetTag . Attributes are key-value pairs which add indexes and operation-level information to ...
Read more >Tracing .NET Applications Easily With OpenTelemetry
In this article, we take a look at tracing in .NET applications, starting with the auto-instrumentation libraries and then custom traces.
Read more >Instrumenting C# .Net Apps With OpenTelemetry
To do this, we can add additional spans manually over sections of the code. Note that OpenTelemetry .NET maintains compatibility with existing .NET...
Read more >NET Observability with OpenTelemetry
OpenTelemetry (OTel) is a cross-platform, open standard for collecting and emitting ... Add(1); // Add a tag to the Activity activity?
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Is it even possible to obtain properties of the user this way? I’m just trying to do the same thing and the identity comes always empty, as if at the point where the
Enrich
callback is called it wasn’t populated yet.A rather janky solution for this might be an
EnrichOpenTelemetryIdentity
that runs afterUseAuthentication
and looks for theIHttpAuthenticationFeature
feature in context and hydrates from that. I don’t see a way to automatically plug that info however.