| File: Logging\FakeLogRecord.cs | Web Access |
| Project: src\src\Libraries\Microsoft.Extensions.Diagnostics.Testing\Microsoft.Extensions.Diagnostics.Testing.csproj (Microsoft.Extensions.Diagnostics.Testing) |
// 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 Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Logging.Testing; /// <summary> /// A single log record tracked by <see cref="FakeLogger"/>. /// </summary> public class FakeLogRecord { /// <summary> /// Initializes a new instance of the <see cref="FakeLogRecord"/> class. /// </summary> /// <param name="level">The level used when producing the log record.</param> /// <param name="id">The ID representing the specific log statement.</param> /// <param name="state">The opaque state supplied by the caller when creating the log record.</param> /// <param name="exception">An optional exception associated with the log record.</param> /// <param name="message">The formatted message text for the record.</param> /// <param name="scopes">List of active scopes active for this log record.</param> /// <param name="category">The optional category for this record, which corresponds to the T in <see cref="ILogger{T}"/>.</param> /// <param name="enabled">Whether the log level was enabled or not when the <see cref="FakeLogger.Log"/> method was called.</param> /// <param name="timestamp">The time at which the log record was created.</param> public FakeLogRecord(LogLevel level, EventId id, object? state, Exception? exception, string message, IReadOnlyList<object?> scopes, string? category, bool enabled, DateTimeOffset timestamp) { Level = level; Id = id; State = state; Exception = exception; Message = Throw.IfNull(message); Scopes = Throw.IfNull(scopes); Category = category; LevelEnabled = enabled; Timestamp = timestamp; } /// <summary> /// Gets the level used when producing the log record. /// </summary> public LogLevel Level { get; } /// <summary> /// Gets the ID representing the specific log statement. /// </summary> public EventId Id { get; } /// <summary> /// Gets the opaque state supplied by the caller when creating the log record. /// </summary> public object? State { get; } /// <summary> /// Gets the opaque state supplied by the caller when creating the log record as a read-only list. /// </summary> /// <remarks> /// When logging using the code generator logging model, the arguments you supply to the logging method are packaged into a single state object which is delivered to the <see cref="ILogger.Log"/> /// method. This state can be retrieved as a set of name/value pairs encoded in a read-only list. /// /// The object returned by this property is the same as what <see cref="State"/> returns, except it has been cast to a read-only list. /// </remarks> /// <exception cref="InvalidCastException">The state object is not compatible with supported logging model and is not a read-only list.</exception> public IReadOnlyList<KeyValuePair<string, string?>>? StructuredState => (IReadOnlyList<KeyValuePair<string, string?>>?)State; /// <summary> /// Gets the value of a particular key value pair in the record's structured state. /// </summary> /// <param name="key">The key to search for in the record's structured state.</param> /// <returns> /// The value associated with the key, or <see langword="null"/> if the key was not found. If the structured /// state contains multiple entries with the same key, the value associated with the first matching key encountered is returned. /// </returns> public string? GetStructuredStateValue(string key) { if (StructuredState is not null) { foreach (var kvp in StructuredState) { if (kvp.Key == key) { return kvp.Value; } } } return null; } /// <summary> /// Gets an optional exception associated with the log record. /// </summary> public Exception? Exception { get; } /// <summary> /// Gets the formatted message text for the record. /// </summary> public string Message { get; } /// <summary> /// Gets the logging scopes active when the log record was created. /// </summary> public IReadOnlyList<object?> Scopes { get; } /// <summary> /// Gets the optional category of this record. /// </summary> /// <remarks> /// The category corresponds to the T value in <see cref="ILogger{T}" />. /// </remarks> public string? Category { get; } /// <summary> /// Gets a value indicating whether the log level was enabled or disabled when this record was collected. /// </summary> public bool LevelEnabled { get; } /// <summary> /// Gets the time at which the log record was created. /// </summary> public DateTimeOffset Timestamp { get; } /// <summary> /// Returns a string representing this object. /// </summary> /// <returns>A string that helps identity this object.</returns> public override string ToString() => Formatter(this); internal static string Formatter(FakeLogRecord record) { // these strings are kept to the same length so the output lines up nicely var level = record.Level switch { LogLevel.Debug => "debug", LogLevel.Information => " info", LogLevel.Warning => " warn", LogLevel.Error => "error", LogLevel.Critical => " crit", LogLevel.Trace => "trace", LogLevel.None => " none", _ => "invld", }; return $"[{record.Timestamp:mm:ss.fff}, {level}] {record.Message}"; } }