|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Compliance.Classification;
using Microsoft.Extensions.Http.Diagnostics;
using Microsoft.Shared.Data.Validation;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Extensions.Http.Logging;
/// <summary>
/// Options to configure HTTP client requests logging.
/// </summary>
public class LoggingOptions
{
private const int MaxIncomingBodySize = 1_572_864; // 1.5 MB
private const int Millisecond = 1;
private const int Minute = 60000;
private const int DefaultReadSizeLimit = 32 * 1024; // ≈ 32K
private const OutgoingPathLoggingMode DefaultPathLoggingMode = OutgoingPathLoggingMode.Formatted;
private const HttpRouteParameterRedactionMode DefaultPathParameterRedactionMode = HttpRouteParameterRedactionMode.Strict;
/// <summary>
/// Gets or sets a value indicating whether the request is logged additionally before any further processing.
/// </summary>
/// <value>
/// The default value is <see langword="false"/>.
/// </value>
/// <remarks>
/// When enabled, two entries will be logged for each incoming request - one for request and one for response, if available.
/// When disabled, only one entry will be logged for each incoming request, which includes both request and response data.
/// </remarks>
public bool LogRequestStart { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the HTTP request and response body are logged.
/// </summary>
/// <value>
/// The default value is <see langword="false"/>.
/// </value>
/// <remarks>
/// Avoid enabling this option in a production environment as it might lead to leaking privacy information.
/// </remarks>
public bool LogBody { get; set; }
/// <summary>
/// Gets or sets the maximum number of bytes of the request or response body to read.
/// </summary>
/// <value>
/// The default value is ≈ 32K.
/// </value>
/// <remarks>
/// The number should ideally be below 85000 bytes to not be allocated on the <see href="https://learn.microsoft.com/dotnet/standard/garbage-collection/large-object-heap">large object heap</see>.
/// </remarks>
[Range(1, MaxIncomingBodySize)]
public int BodySizeLimit { get; set; } = DefaultReadSizeLimit;
/// <summary>
/// Gets or sets the maximum amount of time to wait for the request or response body to be read.
/// </summary>
/// <value>
/// The default value is 1 second.
/// </value>
/// <remarks>
/// The value should be in the range of 1 millisecond to 1 minute.
/// </remarks>
[TimeSpan(Millisecond, Minute)]
public TimeSpan BodyReadTimeout { get; set; } = TimeSpan.FromSeconds(1);
/// <summary>
/// Gets or sets the list of HTTP request content types which are considered text and thus possible to serialize.
/// </summary>
[SuppressMessage("Usage", "CA2227:Collection properties should be read only",
Justification = "Options pattern.")]
[Required]
public ISet<string> RequestBodyContentTypes { get; set; } = new HashSet<string>();
/// <summary>
/// Gets or sets the list of HTTP response content types which are considered text and thus possible to serialize.
/// </summary>
[SuppressMessage("Usage", "CA2227:Collection properties should be read only",
Justification = "Options pattern.")]
[Required]
public ISet<string> ResponseBodyContentTypes { get; set; } = new HashSet<string>();
/// <summary>
/// Gets or sets the set of HTTP request headers to log and their respective data classifications to use for redaction.
/// </summary>
/// <value>
/// The default value is <see cref="HashSet{T}"/>.
/// </value>
/// <remarks>
/// If empty, no HTTP request headers will be logged.
/// If the data class is <see cref="DataClassification.None"/>, no redaction will be done.
/// </remarks>
[SuppressMessage("Usage", "CA2227:Collection properties should be read only",
Justification = "Options pattern.")]
[Required]
public IDictionary<string, DataClassification> RequestHeadersDataClasses { get; set; } = new Dictionary<string, DataClassification>();
/// <summary>
/// Gets or sets the set of HTTP response headers to log and their respective data classifications to use for redaction.
/// </summary>
/// <value>
/// The default value is <see cref="HashSet{T}"/>.
/// </value>
/// <remarks>
/// If the data class is <see cref="DataClassification.None"/>, no redaction will be done.
/// If empty, no HTTP response headers will be logged.
/// </remarks>
[SuppressMessage("Usage", "CA2227:Collection properties should be read only",
Justification = "Options pattern.")]
[Required]
public IDictionary<string, DataClassification> ResponseHeadersDataClasses { get; set; } = new Dictionary<string, DataClassification>();
/// <summary>
/// Gets or sets a value indicating how the outgoing HTTP request path should be logged.
/// </summary>
/// <value>
/// The default value is <see cref="OutgoingPathLoggingMode.Formatted"/>.
/// </value>
/// <remarks>
/// This option is applied only when the <see cref="RequestPathParameterRedactionMode"/> option is not set to
/// <see cref="HttpRouteParameterRedactionMode.None"/>,
/// otherwise this setting is ignored and the non-redacted HTTP request path is logged.
/// </remarks>
public OutgoingPathLoggingMode RequestPathLoggingMode { get; set; } = DefaultPathLoggingMode;
/// <summary>
/// Gets or sets a value indicating how outgoing HTTP request path parameters should be redacted.
/// </summary>
/// <value>
/// The default value is <see cref="HttpRouteParameterRedactionMode.Strict"/>.
/// </value>
public HttpRouteParameterRedactionMode RequestPathParameterRedactionMode { get; set; } = DefaultPathParameterRedactionMode;
/// <summary>
/// Gets or sets the route parameters to redact with their corresponding data classifications to apply appropriate redaction.
/// </summary>
[Required]
[SuppressMessage("Usage", "CA2227:Collection properties should be read only",
Justification = "Options pattern.")]
public IDictionary<string, DataClassification> RouteParameterDataClasses { get; set; } = new Dictionary<string, DataClassification>();
/// <summary>
/// Gets or sets a value indicating whether the HTTP request and response content headers are logged.
/// </summary>
/// <value>
/// The default value is <see langword="false"/>.
/// </value>
/// <remarks>
/// This property controls whether the logging of HTTP request and response representation headers (e.g. <c>Content-Type</c>) is enabled.
/// Keep this option disabled if <see cref="RequestHeadersDataClasses"/> or <see cref="ResponseHeadersDataClasses"/>
/// don't contain any representation headers, otherwise it will create unnecessary minor performance impact on the headers logging.
/// </remarks>
[Experimental(diagnosticId: DiagnosticIds.Experiments.Telemetry, UrlFormat = DiagnosticIds.UrlFormat)]
public bool LogContentHeaders { get; set; }
}
|