| File: Internal\HostingRequestFinishedLog.cs | Web Access |
| Project: src\aspnetcore\src\Hosting\Hosting\src\Microsoft.AspNetCore.Hosting.csproj (Microsoft.AspNetCore.Hosting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.Diagnostics; using System.Globalization; namespace Microsoft.AspNetCore.Hosting; using static HostingRequestStartingLog; internal sealed class HostingRequestFinishedLog : IReadOnlyList<KeyValuePair<string, object?>> { internal static readonly Func<object, Exception?, string> Callback = (state, exception) => ((HostingRequestFinishedLog)state).ToString(); private const string OriginalFormat = "Request finished {Protocol} {Method} {Scheme}://{Host}{PathBase}{Path}{QueryString} - {StatusCode} {ContentLength} {ContentType} {ElapsedMilliseconds}ms"; private readonly HostingApplication.Context _context; private string? _cachedToString; public TimeSpan Elapsed { get; } public int Count => 12; public KeyValuePair<string, object?> this[int index] { get { Debug.Assert(_context.HttpContext != null); var request = _context.HttpContext.Request; var response = _context.HttpContext.Response; return index switch { 0 => new KeyValuePair<string, object?>("ElapsedMilliseconds", Elapsed.TotalMilliseconds), 1 => new KeyValuePair<string, object?>(nameof(response.StatusCode), response.StatusCode), 2 => new KeyValuePair<string, object?>(nameof(response.ContentType), response.ContentType), 3 => new KeyValuePair<string, object?>(nameof(response.ContentLength), response.ContentLength), 4 => new KeyValuePair<string, object?>(nameof(request.Protocol), request.Protocol), 5 => new KeyValuePair<string, object?>(nameof(request.Method), request.Method), 6 => new KeyValuePair<string, object?>(nameof(request.Scheme), request.Scheme), 7 => new KeyValuePair<string, object?>(nameof(request.Host), request.Host.Value), 8 => new KeyValuePair<string, object?>(nameof(request.PathBase), request.PathBase.Value), 9 => new KeyValuePair<string, object?>(nameof(request.Path), request.Path.Value), 10 => new KeyValuePair<string, object?>(nameof(request.QueryString), request.QueryString.Value), 11 => new KeyValuePair<string, object?>("{OriginalFormat}", OriginalFormat), _ => throw new ArgumentOutOfRangeException(nameof(index)), }; } } public HostingRequestFinishedLog(HostingApplication.Context context, TimeSpan elapsed) { _context = context; Elapsed = elapsed; } public override string ToString() { if (_cachedToString == null) { Debug.Assert(_context.HttpContext != null); var request = _context.HttpContext.Request; var response = _context.HttpContext.Response; _cachedToString = $"Request finished {request.Protocol} {request.Method} {request.Scheme}://{request.Host.Value}{request.PathBase.Value}{request.Path.Value}{request.QueryString.Value} - {response.StatusCode.ToString(CultureInfo.InvariantCulture)} {ValueOrEmptyMarker(response.ContentLength)} {EscapedValueOrEmptyMarker(response.ContentType)} {Elapsed.TotalMilliseconds.ToString("0.0000", CultureInfo.InvariantCulture)}ms"; } return _cachedToString; } public IEnumerator<KeyValuePair<string, object?>> GetEnumerator() { for (var i = 0; i < Count; i++) { yield return this[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }