-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
1e4654c
commit 9b1c93f
Showing
12 changed files
with
373 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
namespace PSRule.Runtime; | ||
|
||
/// <summary> | ||
/// Identifies a logging event. | ||
/// The primary identifier is the "Id" property, with the "Name" property providing a short description of this type of event. | ||
/// </summary> | ||
public readonly struct EventId : IEquatable<EventId> | ||
{ | ||
/// <summary> | ||
/// Implicitly creates an EventId from the given <see cref="int"/>. | ||
/// </summary> | ||
/// <param name="i">The <see cref="int"/> to convert to an EventId.</param> | ||
public static implicit operator EventId(int i) | ||
{ | ||
return new EventId(i); | ||
} | ||
|
||
/// <summary> | ||
/// Checks if two specified <see cref="EventId"/> instances have the same value. They are equal if they have the same Id. | ||
/// </summary> | ||
/// <param name="left">The first <see cref="EventId"/>.</param> | ||
/// <param name="right">The second <see cref="EventId"/>.</param> | ||
/// <returns><see langword="true" /> if the objects are equal.</returns> | ||
public static bool operator ==(EventId left, EventId right) | ||
{ | ||
return left.Equals(right); | ||
} | ||
|
||
/// <summary> | ||
/// Checks if two specified <see cref="EventId"/> instances have different values. | ||
/// </summary> | ||
/// <param name="left">The first <see cref="EventId"/>.</param> | ||
/// <param name="right">The second <see cref="EventId"/>.</param> | ||
/// <returns><see langword="true" /> if the objects are not equal.</returns> | ||
public static bool operator !=(EventId left, EventId right) | ||
{ | ||
return !left.Equals(right); | ||
} | ||
|
||
/// <summary> | ||
/// Initializes an instance of the <see cref="EventId"/> struct. | ||
/// </summary> | ||
/// <param name="id">The numeric identifier for this event.</param> | ||
/// <param name="name">The name of this event.</param> | ||
public EventId(int id, string? name = null) | ||
{ | ||
Id = id; | ||
Name = name; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the numeric identifier for this event. | ||
/// </summary> | ||
public int Id { get; } | ||
|
||
/// <summary> | ||
/// Gets the name of this event. | ||
/// </summary> | ||
public string? Name { get; } | ||
|
||
/// <inheritdoc /> | ||
public override string ToString() | ||
{ | ||
return Name ?? Id.ToString(); | ||
} | ||
|
||
/// <summary> | ||
/// Indicates whether the current object is equal to another object of the same type. Two events are equal if they have the same id. | ||
/// </summary> | ||
/// <param name="other">An object to compare with this object.</param> | ||
/// <returns><see langword="true" /> if the current object is equal to the other parameter; otherwise, <see langword="false" />.</returns> | ||
public bool Equals(EventId other) | ||
{ | ||
return Id == other.Id; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override bool Equals(object? obj) | ||
{ | ||
if (obj is null) return false; | ||
|
||
return obj is EventId eventId && Equals(eventId); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override int GetHashCode() | ||
{ | ||
return Id; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections; | ||
|
||
namespace PSRule.Runtime; | ||
|
||
/// <summary> | ||
/// Enable formatted log values in diagnostic messages. | ||
/// </summary> | ||
internal readonly struct FormattedLogValues : IReadOnlyList<KeyValuePair<string, object?>> | ||
{ | ||
private const string NullFormat = "[null]"; | ||
|
||
private readonly object?[]? _Values; | ||
private readonly string _OriginalMessage; | ||
|
||
public FormattedLogValues(string? format, params object?[]? values) | ||
{ | ||
_OriginalMessage = format ?? NullFormat; | ||
_Values = values; | ||
} | ||
|
||
public KeyValuePair<string, object?> this[int index] | ||
{ | ||
get | ||
{ | ||
if (index < 0 || index >= Count) throw new IndexOutOfRangeException(nameof(index)); | ||
|
||
if (index == Count - 1) | ||
{ | ||
return new KeyValuePair<string, object?>("{OriginalFormat}", _OriginalMessage); | ||
} | ||
|
||
return new KeyValuePair<string, object?>($"{index}", _Values?[index]); | ||
} | ||
} | ||
|
||
public int Count | ||
{ | ||
get | ||
{ | ||
return _Values == null ? 1 : _Values.Length + 1; | ||
} | ||
} | ||
|
||
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator() | ||
{ | ||
for (int i = 0; i < Count; ++i) | ||
{ | ||
yield return this[i]; | ||
} | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return string.Format(Thread.CurrentThread.CurrentCulture, _OriginalMessage, _Values); | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
namespace PSRule.Runtime; | ||
|
||
/// <summary> | ||
/// Log diagnostic messages at runtime. | ||
/// </summary> | ||
public interface ILogger | ||
{ | ||
/// <summary> | ||
/// Determine if the specified type of diagnostic message should be logged. | ||
/// </summary> | ||
/// <param name="logLevel">The type of the diagnostic message.</param> | ||
/// <returns>Returns <c>true</c> if the <see cref="LogLevel"/> should be logged.</returns> | ||
public bool IsEnabled(LogLevel logLevel); | ||
|
||
/// <summary> | ||
/// Log a diagnostic message. | ||
/// </summary> | ||
/// <typeparam name="TState">Additional information that describes the diagnostic state to log.</typeparam> | ||
/// <param name="logLevel">The type of the diagnostic message.</param> | ||
/// <param name="eventId">An event identifier for the diagnostic message.</param> | ||
/// <param name="state">Additional information that describes the diagnostic state to log.</param> | ||
/// <param name="exception">An optional exception which the diagnostic message is related to.</param> | ||
/// <param name="formatter">A function to format the diagnostic message for the outpuyt stream.</param> | ||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
namespace PSRule.Runtime; | ||
|
||
/// <summary> | ||
/// A set of log levels which indicate different types of diagnostic messages. | ||
/// </summary> | ||
public enum LogLevel | ||
{ | ||
/// <summary> | ||
/// | ||
/// </summary> | ||
Trace = 0, | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
Debug = 1, | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
Information = 2, | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
Warning = 3, | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
Error = 4, | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
Critical = 5, | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
None = 6 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
namespace PSRule.Runtime; | ||
|
||
/// <summary> | ||
/// Extension for <see cref="ILogger"/> to log diagnostic messages. | ||
/// </summary> | ||
public static class LoggerExtensions | ||
{ | ||
private static readonly Func<FormattedLogValues, Exception?, string> _messageFormatter = MessageFormatter; | ||
|
||
/// <summary> | ||
/// Log a warning message. | ||
/// </summary> | ||
/// <param name="logger">A valid <see cref="ILogger"/> instance.</param> | ||
/// <param name="eventId">An event identifier for the warning.</param> | ||
/// <param name="message">The format message text.</param> | ||
/// <param name="args">Additional arguments to use within the format message.</param> | ||
public static void LogWarning(this ILogger logger, EventId eventId, string? message, params object?[] args) | ||
{ | ||
logger.Log(LogLevel.Warning, eventId, default, message, args); | ||
} | ||
|
||
/// <summary> | ||
/// Log an error message. | ||
/// </summary> | ||
/// <param name="logger">A valid <see cref="ILogger"/> instance.</param> | ||
/// <param name="eventId">An event identifier for the error.</param> | ||
/// <param name="exception">An optional exception which the error message is related to.</param> | ||
/// <param name="message">The format message text.</param> | ||
/// <param name="args">Additional arguments to use within the format message.</param> | ||
public static void LogError(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args) | ||
{ | ||
logger.Log(LogLevel.Error, eventId, exception, message, args); | ||
} | ||
|
||
/// <summary> | ||
/// Log a diagnostic message. | ||
/// </summary> | ||
/// <param name="logger">A valid <see cref="ILogger"/> instance.</param> | ||
/// <param name="logLevel">The type of diagnostic message.</param> | ||
/// <param name="eventId">An event identifier for the diagnostic message.</param> | ||
/// <param name="exception">An optional exception which the diagnostic message is related to.</param> | ||
/// <param name="message">The format message text.</param> | ||
/// <param name="args">Additional arguments to use within the format message.</param> | ||
public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, Exception? exception, string? message, params object?[] args) | ||
{ | ||
if (logger == null || !logger.IsEnabled(logLevel)) | ||
return; | ||
|
||
logger.Log(logLevel, eventId, new FormattedLogValues(message, args), exception, _messageFormatter); | ||
} | ||
|
||
/// <summary> | ||
/// Format log messages with values. | ||
/// </summary> | ||
private static string MessageFormatter(FormattedLogValues state, Exception? error) | ||
{ | ||
return state.ToString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.