Created
March 29, 2022 21:02
-
-
Save bgavrilMS/067a913480ae3e96aea0ca0407f82521 to your computer and use it in GitHub Desktop.
Logging prototype 2
This file contains hidden or 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
using System; | |
using System.Diagnostics.Tracing; | |
namespace ConsoleApp2.p4 | |
{ | |
/// <summary> | |
/// With Global PII setting. | |
/// </summary> | |
public class Prototype4 | |
{ | |
public static void Prototype() | |
{ | |
// App developer configures logger | |
IIdentityLogger logger = new ConsoleLoggerImpl(EventLevel.Verbose); | |
MsalLogger msalInternalLogging = | |
Adapter.FromIIdentityLogger(logger, new RequestContext() { CorrelationId = "correlationId", UsePii = true }); | |
WithLogging(LogCallback callbacl, LogLevel level, bool capturePii); | |
WithLogging(LogCallback callbacl, Func<LogLevel, bool> isLoggingEnabled, bool capturePii); | |
WithLogging(IIdentityLogger logger, bool capturePii); | |
WithLogging(IIdentityLogger logger, ILogScrubber scrubber); | |
// How to adapt IIdentityLoggger to MsalLogger? | |
// Now MSAL outputs some log messages | |
//LogHelper msalInternalLogging = new LogHelper(logger, "activity_id"); | |
msalInternalLogging.Log(LogLevel.Info, "Info message no pii", "Info message with pii"); | |
//msalInternalLogging.Log(LogLevel.Info, "Info message2 no pii"); | |
//msalInternalLogging.Log(EventLevel.Verbose, "Verobse message no pii", "Verbose with pii"); | |
//msalInternalLogging.Log(EventLevel.Verbose, "Verobse message2 no pii"); | |
//msalInternalLogging.Log(EventLevel.LogAlways, "LogAlways message no pii", "LogAlways message with pii"); | |
//msalInternalLogging.Log(EventLevel.LogAlways, "LogAlways message2 no pii"); | |
//msalInternalLogging.Log(EventLevel.Error, "Error message no pii", "Error message with pii"); | |
//msalInternalLogging.Log(EventLevel.Error, "Error message2 no pii"); | |
if (msalInternalLogging.IsLoggingEnabled(LogLevel.Verbose)) | |
{ | |
msalInternalLogging.Log(LogLevel.Verbose, GetExpensiveLogMessage(), null); | |
} | |
} | |
private static string GetExpensiveLogMessage() | |
{ | |
Console.WriteLine("EXPENSIVE LOG MESSAGE COMPUTED. Is this expected?"); | |
return "This is an expensive verbose message"; | |
} | |
} | |
public class MsalLogger | |
{ | |
private readonly LogCallback _loggingCallback; | |
private readonly bool _isPiiEnabled; | |
private readonly Func<LogLevel, bool> _isEnabled; | |
//private readonly LogLevel _minLogLevel; | |
public MsalLogger(LogCallback loggingCallback, bool isPiiEnabled, LogLevel logLevel) | |
{ | |
this._loggingCallback = loggingCallback; | |
this._isPiiEnabled = isPiiEnabled; | |
//this._minLogLevel = logLevel; | |
_isEnabled = (level) => level <= logLevel; | |
} | |
public MsalLogger(LogCallback loggingCallback, bool isPiiEnabled, Func<LogLevel, bool> isEnabled) | |
{ | |
this._loggingCallback = loggingCallback; | |
this._isPiiEnabled = isPiiEnabled; | |
this._isEnabled = isEnabled; | |
} | |
public void Log(LogLevel logLevel, string messageWithPii, string messageScrubbed) | |
{ | |
if (IsLoggingEnabled(logLevel)) | |
{ | |
bool messageWithPiiExists = !string.IsNullOrWhiteSpace(messageWithPii); | |
// If we have a message with PII, and PII logging is enabled, use the PII message, else use the scrubbed message. | |
bool isLoggingPii = messageWithPiiExists && _isPiiEnabled; | |
string messageToLog = isLoggingPii ? messageWithPii : messageScrubbed; | |
_loggingCallback.Invoke(logLevel, messageWithPii, isLoggingPii); | |
} | |
} | |
public bool IsLoggingEnabled(LogLevel logLevel) | |
{ | |
//return _loggingCallback != null && logLevel <= _minLogLevel; | |
return _loggingCallback != null && _isEnabled(logLevel); | |
} | |
} | |
public class RequestContext | |
{ | |
public string CorrelationId; | |
public bool UsePii; | |
} | |
public class Adapter | |
{ | |
public static MsalLogger FromIIdentityLogger(IIdentityLogger identityLogger, RequestContext context) | |
{ | |
LogCallback callback = (lvl, msg, pii) => | |
{ | |
var eventLevel = GetLevel(lvl); | |
if (identityLogger.IsEnabled(eventLevel)) | |
{ | |
LogEntry entry = new LogEntry() | |
{ | |
EventLevel = GetLevel(lvl), | |
CorrelationId = context.CorrelationId, | |
Message = msg | |
}; | |
identityLogger.Log(entry); | |
} | |
}; | |
Func<LogLevel, bool> isEnabledFunc = (level) => | |
{ | |
return identityLogger.IsEnabled(GetLevel(level)); | |
}; | |
MsalLogger msalLogger = new MsalLogger(callback, context.UsePii, isEnabledFunc); | |
return msalLogger; | |
} | |
private static EventLevel GetLevel(LogLevel logLevel) | |
{ | |
switch (logLevel) | |
{ | |
case LogLevel.Verbose: | |
return EventLevel.Verbose; | |
case LogLevel.Info: | |
return EventLevel.Informational; | |
case LogLevel.Warning: | |
return EventLevel.Warning; | |
case LogLevel.Error: | |
return EventLevel.Error; | |
case LogLevel.Always: | |
return EventLevel.LogAlways; | |
default: | |
return EventLevel.Warning; | |
} | |
} | |
//private static LogLevel GetLevel(EventLevel eventLevel) | |
//{ | |
// switch (eventLevel) | |
// { | |
// case EventLevel.LogAlways: | |
// return LogLevel.Always; | |
// case EventLevel.Critical: | |
// return LogLevel.Error; | |
// case EventLevel.Error: | |
// return LogLevel.Error; | |
// case EventLevel.Warning: | |
// return LogLevel.Warning; | |
// case EventLevel.Informational: | |
// return LogLevel.Info; | |
// case EventLevel.Verbose: | |
// return LogLevel.Verbose; | |
// default: | |
// break; | |
// } | |
//} | |
} | |
public delegate void LogCallback(LogLevel level, string message, bool containsPii); | |
public enum LogLevel | |
{ | |
/// <summary> | |
/// Includes logs of important health metrics to help with diagnostics of MSAL operations. | |
/// </summary> | |
Always = -1, | |
/// <summary> | |
/// Includes logs when something has gone wrong and an error was generated. Used for debugging and identifying problems. | |
/// </summary> | |
Error = 0, | |
/// <summary> | |
/// Includes logs in scenarios when there hasn't necessarily been an error or failure, but are intended for diagnostics and pinpointing problems. | |
/// </summary> | |
Warning = 1, | |
/// <summary> | |
/// Default. Includes logs of general events intended for informational purposes, not necessarily intended for debugging. | |
/// </summary> | |
Info = 2, | |
/// <summary> | |
/// Includes logs of the full details of library behavior. | |
/// </summary> | |
Verbose = 3 | |
} | |
//public class LogHelper | |
//{ | |
// private readonly IIdentityLogger _logger; | |
// private readonly string _correlationId; | |
// public const string MsalVersion = "1.0.0"; | |
// public static bool GlobalPiiSetting = true; | |
// public LogHelper(IIdentityLogger logger, string correlationId) | |
// { | |
// _logger = logger; | |
// _correlationId = correlationId; | |
// } | |
// public bool IsEnabled(EventLevel level) | |
// { | |
// return _logger.IsEnabled(level); | |
// } | |
// public void Log(EventLevel level, string messageNoPii) | |
// { | |
// if (IsEnabled(level)) | |
// { | |
// _logger.Log(new LogEntry() | |
// { | |
// EventLevel = level, | |
// Message = messageNoPii, | |
// }); | |
// } | |
// } | |
// public void Log(EventLevel level, string messageNoPii, string messageWithPii) | |
// { | |
// if (IsEnabled(level)) | |
// { | |
// string messageToLog = (GlobalPiiSetting == true) ? messageWithPii : messageNoPii; | |
// _logger.Log(new LogEntry() | |
// { | |
// EventLevel = level, | |
// Message = messageToLog, | |
// CorrelationId = _correlationId, | |
// }); | |
// } | |
// } | |
//} | |
public class ConsoleLoggerImpl : IIdentityLogger | |
{ | |
private readonly EventLevel _minLevel; | |
public ConsoleLoggerImpl(EventLevel minLevel) | |
{ | |
_minLevel = minLevel; | |
} | |
public bool IsEnabled(EventLevel level) | |
{ | |
return (level <= _minLevel); | |
} | |
public void Log(LogEntry entry) | |
{ | |
Console.WriteLine($"{entry.EventLevel} {entry.Message} "); | |
} | |
} | |
public interface IIdentityLogger // part of new package | |
{ | |
bool IsEnabled(EventLevel level); | |
/// <summary> | |
/// Writes a log entry. | |
/// </summary> | |
/// <param name="entry">Defines a structured message to be logged at the provided <see cref="LogEntry.EventLevel"/>.</param> | |
void Log(LogEntry entry); | |
} | |
/// </summary> | |
public class LogEntry // part of new package | |
{ | |
/// <summary> | |
/// Defines the <see cref="EventLevel"/>. | |
/// </summary> | |
public EventLevel EventLevel { get; set; } | |
/// <summary> | |
/// Message to be logged. | |
/// </summary> | |
public string Message { get; set; } | |
/// <summary> | |
/// A unique identifier for a request that can help with diagnostics across components. | |
/// </summary> | |
public string CorrelationId { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment