Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal sealed class HttpLoggingRedactionInterceptor : IHttpLoggingInterceptor
private readonly HeaderReader _responseHeadersReader;
private readonly string[] _excludePathStartsWith;
private readonly FrozenDictionary<string, DataClassification> _parametersToRedactMap;
private readonly bool _includeUnmatchedRoutes;

public HttpLoggingRedactionInterceptor(
IOptions<LoggingRedactionOptions> options,
Expand All @@ -59,6 +60,7 @@ public HttpLoggingRedactionInterceptor(
_responseHeadersReader = new(optionsValue.ResponseHeadersDataClasses, redactorProvider, HttpLoggingTagNames.ResponseHeaderPrefix);

_excludePathStartsWith = optionsValue.ExcludePathStartsWith.ToArray();
_includeUnmatchedRoutes = optionsValue.IncludeUnmatchedRoutes;
}

public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
Expand Down Expand Up @@ -115,6 +117,10 @@ public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
}
}
}
else if (_includeUnmatchedRoutes)
{
path = context.Request.Path.ToString();
}
}
else if (request.Path.HasValue)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ public class LoggingRedactionOptions
#pragma warning disable CA2227 // Collection properties should be read only
public ISet<string> ExcludePathStartsWith { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
#pragma warning restore CA2227 // Collection properties should be read only

/// <summary>
/// Gets or sets a value indicating whether to report unmatched routes.
/// </summary>
/// <remarks>
/// If set to true, instead of logging <i>unknown</i> value for path attribute it will log whole path of routes not identified by ASP.NET Routing.
/// </remarks>
/// <value>Defaults to <see langword="true"/>.</value>
#pragma warning disable CA1805 // Do not initialize unnecessarily
public bool IncludeUnmatchedRoutes { get; set; } = false;
#pragma warning restore CA1805 // Do not initialize unnecessarily
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@
const string Content = "Client: hello!";

using var content = new StringContent(Content, null, requestContentType);
using var response = await client.PostAsync("/", content).ConfigureAwait(false);
using var response = await client.PostAsync("/myroute/123", content).ConfigureAwait(false);
Assert.True(response.IsSuccessStatusCode);

await WaitForLogRecordsAsync(logCollector, _defaultLogTimeout);
Expand Down Expand Up @@ -267,6 +267,49 @@
});
}

[Fact]
public async Task HttpLogging_WhenIncludeUnmatchedRoutes_LogRequestPath()
{
await RunAsync(
LogLevel.Information,
services => services.AddHttpLogging(x =>
{
x.MediaTypeOptions.Clear();
x.MediaTypeOptions.AddText("text/*");
x.LoggingFields |= HttpLoggingFields.RequestBody;
}).AddHttpLoggingRedaction(options => options.IncludeUnmatchedRoutes = true),
async (logCollector, client) =>
{
const string Content = "Client: hello!";

using var content = new StringContent(Content, null, MediaTypeNames.Text.Html);
using var response = await client.PostAsync("/myroute/123", content).ConfigureAwait(false);
Assert.True(response.IsSuccessStatusCode);

await WaitForLogRecordsAsync(logCollector, _defaultLogTimeout);

Assert.Equal(1, logCollector.Count);
Assert.Null(logCollector.LatestRecord.Exception);
Assert.Equal(LogLevel.Information, logCollector.LatestRecord.Level);
Assert.Equal(LoggingCategory, logCollector.LatestRecord.Category);

var responseStatus = ((int)response.StatusCode).ToInvariantString();
var state = logCollector.LatestRecord.StructuredState!;

Assert.DoesNotContain(state, x => x.Key == HttpLoggingTagNames.ResponseBody);
Assert.DoesNotContain(state, x => x.Key.StartsWith(HttpLoggingTagNames.RequestHeaderPrefix));
Assert.DoesNotContain(state, x => x.Key.StartsWith(HttpLoggingTagNames.ResponseHeaderPrefix));
Assert.Single(state, x => x.Key == HttpLoggingTagNames.Host && !string.IsNullOrEmpty(x.Value));
Assert.Single(state, x => x.Key == HttpLoggingTagNames.Path && x.Value == "/myroute/123");
Assert.Single(state, x => x.Key == HttpLoggingTagNames.StatusCode && x.Value == responseStatus);
Assert.Single(state, x => x.Key == HttpLoggingTagNames.Method && x.Value == HttpMethod.Post.ToString());
Assert.Single(state, x => x.Key == HttpLoggingTagNames.Duration &&
x.Value != null &&
int.Parse(x.Value, CultureInfo.InvariantCulture) == SlashRouteProcessingTimeMs);
});
}

Check failure on line 311 in test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Correctness WarningsCheck)

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs#L311

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs(311,1): error IDE2000: (NETCORE_ENGINEERING_TELEMETRY=Build) Avoid multiple blank lines (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000)

Check failure on line 311 in test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs

View check run for this annotation

Azure Pipelines / extensions-ci (Correctness WarningsCheck)

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs#L311

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs(311,1): error IDE2000: (NETCORE_ENGINEERING_TELEMETRY=Build) Avoid multiple blank lines (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000)

Check failure on line 311 in test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs

View check run for this annotation

Azure Pipelines / extensions-ci

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs#L311

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs(311,1): error IDE2000: (NETCORE_ENGINEERING_TELEMETRY=Build) Avoid multiple blank lines (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000)

Check failure on line 311 in test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs

View check run for this annotation

Azure Pipelines / extensions-ci

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs#L311

test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Logging/AcceptanceTests.cs(311,1): error IDE2000: (NETCORE_ENGINEERING_TELEMETRY=Build) Avoid multiple blank lines (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000)

[Fact]
public async Task HttpLogging_WhenLogLevelInfo_LogRequestStart()
{
Expand Down
Loading