Add ASP.NET Core ILogger instrumentation for logs injection#1549
Add ASP.NET Core ILogger instrumentation for logs injection#1549andrewlock wants to merge 22 commits into
Conversation
| namespace Datadog.Trace.AspNetCore | ||
| { | ||
| // Implementation based on AspNetCore Hosting implementation: https://github.com/dotnet/aspnetcore/blob/1a2b3260c6161ae9b7f639de228a6eb0488a1075/src/Hosting/Hosting/src/Internal/HostingLoggerExtensions.cs#L114 | ||
| internal class DatadogLoggingScope : IReadOnlyList<KeyValuePair<string, object>> |
There was a problem hiding this comment.
Wonder if we should make this public, so customers can use it with manual instrumentation?
There was a problem hiding this comment.
Oh, is this for non-aspnetcore use cases? I was thinking we would start by only exposing an ApplicationBuilder extension method that the user can call, and this could be an implementation detail.
There was a problem hiding this comment.
Yeah, I was thinking non-aspnetcore use cases. The ApplicationBuilder makes sense, but then we would have to take dependencies on the aspnetcore packages, which I wasn't sure if we'd want to? We can always make this public later if we want to, so probably makes sense to keep it internal for now.
There was a problem hiding this comment.
but then we would have to take dependencies on the aspnetcore packages
In a new Datadog.Trace.AspNetCore package! 😅
| { | ||
| if (index == 0) | ||
| { | ||
| return new KeyValuePair<string, object>("dd_service", _service); |
There was a problem hiding this comment.
These identifiers are "serilog" style. If users are using ILogger injection and NLog/Log4NET, then they will have two sets of identifiers I think. Not sure what the best way to tackle that is
There was a problem hiding this comment.
Yeah they'll have two sets of identifiers...perhaps we'll have a better idea of how to tackle it once we see it in use?
2c1597d to
bf5b530
Compare
| "Samples.AspNetCoreMvc21" => Framework == TargetFramework.NETCOREAPP2_1, | ||
| "Samples.AspNetCoreMvc30" => Framework == TargetFramework.NETCOREAPP3_0, | ||
| "Samples.AspNetCoreMvc31" => Framework == TargetFramework.NETCOREAPP3_1, | ||
| "Samples.AspNetCoreMvc31" => Framework == TargetFramework.NETCOREAPP3_1 || Framework == TargetFramework.NET5_0, |
There was a problem hiding this comment.
No Samples.AspNetCoreMvc50? 😝
There was a problem hiding this comment.
It's a reasonable question, tbh, and given we have separate projects for 3.0 and 3.1, maybe we should?🤔
There was a problem hiding this comment.
Not in this PR of course. To the backlog!
1dde0da to
eca92e8
Compare
|
I wonder if we should provide a way to disable this log injection integration. It's written as part of the aspnetcore integration, but given it isn't totally complete (i.e. it only works for aspnetcore requests, not all Those other integrations can be "disabled" by just not wiring them up, but we don't have a way of disabling this |
4e1fd51 to
98d0e8c
Compare
| /// <summary> | ||
| /// Gets the diagnostics field | ||
| /// </summary> | ||
| [Duck(Name = "_diagnostics", Kind = DuckKind.Field)] |
There was a problem hiding this comment.
If #1601 is merged soon, then we can refactor this to
[DuckField(Name = "_diagnostics")]
How about we change the |
| where TTarget : IHostingApplication | ||
| { | ||
| IDisposable disposable = null; | ||
| if (Tracer.Instance.Settings.LogsInjectionEnabled) |
There was a problem hiding this comment.
I think we'll need to modify the check to also check the integration:
if (Tracer.Instance.Settings.LogsInjectionEnabled && Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationId))paired with
private static readonly IntegrationInfo IntegrationId = IntegrationRegistry.GetIntegrationInfo(IntegrationName);…onsole logger and file logger that use structured logging
…actual implementation class we'd need to pass to ILogger. The next step is figuring out where to add it to ILogger and how
…automatically add the log scope
- Fix content root - Configure loggers - log using middleware (so we confirm 404s get the trace id etc too) - Add Startup log that will not be traced - Exclude other logs by default
Could/Should make these separate tests, but keeping them the same for now for speed/simplicity
Avoids unexpected TraceId: 0
Don't support tracing yet, so won't get any TraceIds, but can inject service/env/version into logs
This wasn't possible before, because the .NET Core 2.1 implementation of ILogger, Logger, used explicit interface implementation. This is now supported out of the box thanks to #1555
Co-authored-by: Lucas Pimentel-Ordyna <lucas.pimentel@datadoghq.com>
98d0e8c to
9ff60d4
Compare
zacharycmontoya
left a comment
There was a problem hiding this comment.
LGTM, and since I hadn't looked at this in a while I think I acquired an objective perspective to review it properly 😆
|
Superseded by #1663. I'll pull the additional tests (for .NET Framework etc) out in a separate PR |
The initial implementation was done by @zacharycmontoya - I added tests and extended to cover .NET Core 3+
This instruments the
HostingApplication.ProcessRequestAsyncmethod, which wraps execution of the middleware pipeline, _after theDiagnosticSource.BeginRequesthas executed (and hence after aTraceIdhas been generated).Limitations:
SpanIdto the logs. Doing so would require a different instrumentation point.TraceIdinjection is disabled for .NET Framework. The integration is still enabled, but as the diagnostic-source based tracing doesn't work, thetrace_idwould always be0, which defeats the point of logs injection.dd_service,dd_env, anddd_versionare added though.As part of this integration, I also updated the 3.1 sample to run and test against .NET 5, and the 2.1 to test and run against .NET Framework (to confirm existing no-tracing/no-trace_id behaviour)
@DataDog/apm-dotnet