Skip to content

Commit

Permalink
Added support for LoggerFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasArdal committed Oct 16, 2024
1 parent ca3ff45 commit 79fccd5
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 35 deletions.
4 changes: 3 additions & 1 deletion src/LoggerVisualizer/LoggerDebuggerVisualizerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ namespace LoggerVisualizer
internal class LoggerDebuggerVisualizerProvider : DebuggerVisualizerProvider
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("ConstantExpressionEvaluator", "CEE0027:String not localized", Justification = "")]
public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new("Logger Visualizer", typeof(Logger<>))
public override DebuggerVisualizerProviderConfiguration DebuggerVisualizerProviderConfiguration => new(
new VisualizerTargetType("Logger Visualizer", typeof(Logger<>)),
new VisualizerTargetType("Logger Factory Visualizer", typeof(LoggerFactory)))
{
VisualizerObjectSourceType = new(typeof(LoggerObjectSource)),
};
Expand Down
36 changes: 18 additions & 18 deletions src/LoggerVisualizerSource/LoggerModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ namespace LoggerVisualizerSource
public class LoggerModel
{
[DataMember]
public string Name { get; set; }
public string Name { get; set; } = "N/A";

[DataMember]
public string Enabled { get; set; }
public string Enabled { get; set; } = "N/A";

[DataMember]
public string MinLevel { get; set; }
public string MinLevel { get; set; } = "N/A";

[DataMember]
public List<Logger> Loggers { get; set; } = [];
Expand All @@ -23,54 +23,54 @@ public class LoggerModel
public class Logger
{
[DataMember]
public string Name { get; set; }
public string Name { get; set; } = "N/A";

[DataMember]
public string ExternalScope { get; set; }
public string ExternalScope { get; set; } = "N/A";

[DataMember]
public string MinLevel { get; set; }
public string MinLevel { get; set; } = "N/A";

#region Console
[DataMember]
public string FormatterName { get; set; }
public string FormatterName { get; set; } = "N/A";

[DataMember]
public string DisableColors { get; set; }
public string DisableColors { get; set; } = "N/A";

[DataMember]
public string LogToStandardErrorThreshold { get; set; }
public string LogToStandardErrorThreshold { get; set; } = "N/A";

[DataMember]
public string MaxQueueLength { get; set; }
public string MaxQueueLength { get; set; } = "N/A";

[DataMember]
public string QueueFullMode { get; set; }
public string QueueFullMode { get; set; } = "N/A";

[DataMember]
public string TimestampFormat { get; set; }
public string TimestampFormat { get; set; } = "N/A";

[DataMember]
public string UseUtcTimestamp { get; set; }
public string UseUtcTimestamp { get; set; } = "N/A";
#endregion

#region EventLog
[DataMember]
public string MachineName { get; set; }
public string MachineName { get; set; } = "N/A";

[DataMember]
public string SourceName { get; set; }
public string SourceName { get; set; } = "N/A";

[DataMember]
public string LogName { get; set; }
public string LogName { get; set; } = "N/A";
#endregion

#region ElmahIo
[DataMember]
public string ApiKey { get; set; }
public string ApiKey { get; set; } = "N/A";

[DataMember]
public string LogId { get; set; }
public string LogId { get; set; } = "N/A";
#endregion
}
}
111 changes: 95 additions & 16 deletions src/LoggerVisualizerSource/LoggerObjectSource.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.DebuggerVisualizers;
using System;
using System.Collections;
using System.IO;
using System.Reflection;

Expand All @@ -10,7 +11,58 @@ public class LoggerObjectSource : VisualizerObjectSource
{
public override void GetData(object target, Stream outgoingData)
{
if (target.GetType().IsGenericType && target.GetType().GetGenericTypeDefinition() == typeof(Logger<>))
if (target.GetType() == typeof(LoggerFactory))
{
var field = GetPrivateField(target, "_providerRegistrations");
var result = new LoggerModel
{
Loggers = []
};

Type listType = field.GetType();
if (typeof(IEnumerable).IsAssignableFrom(listType))
{
// Cast the value to IEnumerable to access the elements
IEnumerable list = (IEnumerable)field;

foreach (var item in list)
{
var provider = GetPublicField(item, "Provider") as ILoggerProvider;
var providerTypeValue = provider?.GetType();

Logger loggerModel = new()
{
Name = providerTypeValue?.FullName,
};

switch (provider?.GetType().FullName)
{
case "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider":
{
var optionsMonitor = GetPrivateField(provider, "_options");
var options = GetPublicProperty(optionsMonitor, "CurrentValue");
loggerModel = ConsoleOptions(options, loggerModel);
break;
}
case "Microsoft.Extensions.Logging.EventLog.EventLogLoggerProvider":
{
loggerModel = EventLogSettings(provider, loggerModel);
break;
}
case "Elmah.Io.Extensions.Logging.ElmahIoLoggerProvider":
{
loggerModel = ElmahIoOptions(provider, loggerModel);
break;
}
}

result.Loggers.Add(loggerModel);
}
}

SerializeAsJson(outgoingData, result);
}
else if (target.GetType().IsGenericType && target.GetType().GetGenericTypeDefinition() == typeof(Logger<>))
{
var logger = GetPrivateField(target, "_logger") as ILogger;
if (logger?.GetType().FullName != "Microsoft.Extensions.Logging.Logger") return;
Expand Down Expand Up @@ -53,29 +105,17 @@ public override void GetData(object target, Stream outgoingData)
case "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider":
{
var options = GetNonPublicProperty(internalLogger, "Options");
loggerModel.FormatterName = GetPublicProperty(options, "FormatterName")?.ToString();
loggerModel.TimestampFormat = GetPublicProperty(options, "TimestampFormat")?.ToString();
loggerModel.QueueFullMode = GetPublicProperty(options, "QueueFullMode")?.ToString();
loggerModel.DisableColors = GetPublicProperty(options, "DisableColors")?.ToString();
loggerModel.LogToStandardErrorThreshold = GetPublicProperty(options, "LogToStandardErrorThreshold")?.ToString();
loggerModel.MaxQueueLength = GetPublicProperty(options, "MaxQueueLength")?.ToString();
loggerModel.UseUtcTimestamp = GetPublicProperty(options, "UseUtcTimestamp")?.ToString();
loggerModel = ConsoleOptions(options, loggerModel);
break;
}
case "Microsoft.Extensions.Logging.EventLog.EventLogLoggerProvider":
{
var settings = GetPrivateField(internalLogger, "_settings");
loggerModel.LogName = GetPublicProperty(settings, "LogName")?.ToString();
loggerModel.MachineName = GetPublicProperty(settings, "MachineName")?.ToString();
loggerModel.SourceName = GetPublicProperty(settings, "SourceName")?.ToString();
loggerModel = EventLogSettings(internalLogger, loggerModel);
break;
}
case "Elmah.Io.Extensions.Logging.ElmahIoLoggerProvider":
{
var options = GetPrivateField(internalLogger, "_options");
loggerModel.ApiKey = GetPublicProperty(options, "ApiKey")?.ToString();
var logId = GetPublicProperty(options, "LogId") as Guid?;
loggerModel.LogId = logId == Guid.Empty ? "" : logId?.ToString();
loggerModel = ElmahIoOptions(internalLogger, loggerModel);
break;
}
}
Expand All @@ -87,6 +127,36 @@ public override void GetData(object target, Stream outgoingData)
}
}

private Logger ElmahIoOptions(object objWithOptions, Logger loggerModel)
{
var options = GetPrivateField(objWithOptions, "_options");
loggerModel.ApiKey = GetPublicProperty(options, "ApiKey")?.ToString();
var logId = GetPublicProperty(options, "LogId") as Guid?;
loggerModel.LogId = logId == Guid.Empty ? "" : logId?.ToString();
return loggerModel;
}

private Logger EventLogSettings(object objWithSettings, Logger loggerModel)
{
var settings = GetPrivateField(objWithSettings, "_settings");
loggerModel.LogName = GetPublicProperty(settings, "LogName")?.ToString();
loggerModel.MachineName = GetPublicProperty(settings, "MachineName")?.ToString();
loggerModel.SourceName = GetPublicProperty(settings, "SourceName")?.ToString();
return loggerModel;
}

private Logger ConsoleOptions(object options, Logger loggerModel)
{
loggerModel.FormatterName = GetPublicProperty(options, "FormatterName")?.ToString();
loggerModel.TimestampFormat = GetPublicProperty(options, "TimestampFormat")?.ToString();
loggerModel.QueueFullMode = GetPublicProperty(options, "QueueFullMode")?.ToString();
loggerModel.DisableColors = GetPublicProperty(options, "DisableColors")?.ToString();
loggerModel.LogToStandardErrorThreshold = GetPublicProperty(options, "LogToStandardErrorThreshold")?.ToString();
loggerModel.MaxQueueLength = GetPublicProperty(options, "MaxQueueLength")?.ToString();
loggerModel.UseUtcTimestamp = GetPublicProperty(options, "UseUtcTimestamp")?.ToString();
return loggerModel;
}

static object FirstOrNull(Array messageLoggers, ILogger logger)
{
if (messageLoggers is null || messageLoggers.Length == 0)
Expand Down Expand Up @@ -165,5 +235,14 @@ private static object GetPrivateField(object obj, string name)
return theValue;
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "")]
private static object GetPublicField(object obj, string name)
{
FieldInfo fieldInfo = obj.GetType().GetField(name, BindingFlags.Public | BindingFlags.Instance);
if (fieldInfo == null) return null;
var theValue = fieldInfo.GetValue(obj);
return theValue;
}

}
}

0 comments on commit 79fccd5

Please sign in to comment.