Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 43 additions & 24 deletions src/common/ManagedCommon/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using PowerToys.Interop;

Expand Down Expand Up @@ -136,48 +135,45 @@ public static void LogError(string message, [System.Runtime.CompilerServices.Cal

public static void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
if (ex == null)
{
Log(message, Error, memberName, sourceFilePath, sourceLineNumber);
}
else
{
var exMessage =
message + Environment.NewLine +
ex.GetType() + " (" + ex.HResult + "): " + ex.Message + Environment.NewLine;

if (ex.InnerException != null)
{
exMessage +=
"Inner exception: " + Environment.NewLine +
ex.InnerException.GetType() + " (" + ex.InnerException.HResult + "): " + ex.InnerException.Message + Environment.NewLine;
}

exMessage +=
"Stack trace: " + Environment.NewLine +
ex.StackTrace;

Log(exMessage, Error, memberName, sourceFilePath, sourceLineNumber);
}
var logMessage = GenerateExceptionMessage(message, ex);
LogError(logMessage, memberName, sourceFilePath, sourceLineNumber);
}

public static void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Log(message, Warning, memberName, sourceFilePath, sourceLineNumber);
}

public static void LogWarning(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
var logMessage = GenerateExceptionMessage(message, ex);
LogWarning(logMessage, memberName, sourceFilePath, sourceLineNumber);
}

public static void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Log(message, Info, memberName, sourceFilePath, sourceLineNumber);
}

public static void LogInfo(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
var logMessage = GenerateExceptionMessage(message, ex);
LogInfo(logMessage, memberName, sourceFilePath, sourceLineNumber);
}

public static void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
#if DEBUG
Log(message, Debug, memberName, sourceFilePath, sourceLineNumber);
#endif
}

public static void LogDebug(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
var logMessage = GenerateExceptionMessage(message, ex);
LogDebug(logMessage, memberName, sourceFilePath, sourceLineNumber);
}

public static void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Log(string.Empty, TraceFlag, memberName, sourceFilePath, sourceLineNumber);
Expand All @@ -195,6 +191,29 @@ private static void Log(string message, string type, string memberName, string s
Trace.Unindent();
}

private static string GenerateExceptionMessage(string message, Exception ex)
{
var finalMessage = message;
if (ex is not null)
{
finalMessage = message + Environment.NewLine +
ex.GetType() + " (" + ex.HResult + "): " + ex.Message + Environment.NewLine;

if (ex.InnerException != null)
{
finalMessage +=
"Inner exception: " + Environment.NewLine +
ex.InnerException.GetType() + " (" + ex.InnerException.HResult + "): " + ex.InnerException.Message + Environment.NewLine;
}

finalMessage +=
"Stack trace: " + Environment.NewLine +
ex.StackTrace;
}

return finalMessage;
}

private static string GetCallerInfo(string memberName, string sourceFilePath, int sourceLineNumber)
{
string callerFileName = "Unknown";
Expand Down
140 changes: 140 additions & 0 deletions src/modules/cmdpal/Microsoft.CmdPal.Common/CmdPalLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using ManagedCommon;
using Microsoft.Extensions.Logging;

namespace Microsoft.CmdPal.Common;

// Adapter implementing Microsoft.Extensions.Logging.ILogger,
// delegating to ManagedCommon.Logger.
public sealed partial class CmdPalLogger : Extensions.Logging.ILogger
{
private static readonly AsyncLocal<Stack<object>> _scopeStack = new();
private readonly LogLevel _minLevel;

public string CurrentVersionLogDirectoryPath => Logger.CurrentVersionLogDirectoryPath;

public CmdPalLogger(LogLevel minLevel = LogLevel.Information)
{
_minLevel = minLevel;

// Ensure underlying logger initialized (idempotent if already done elsewhere).
Logger.InitializeLogger("\\CmdPal\\Logs\\");
}

public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None && logLevel >= _minLevel;

public IDisposable? BeginScope<TState>(TState state)
where TState : notnull
{
var stack = _scopeStack.Value;
if (stack is null)
{
stack = new Stack<object>();
_scopeStack.Value = stack;
}

stack.Push(state);
return new Scope(stack);
}

public void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}

ArgumentNullException.ThrowIfNull(formatter);
var message = formatter(state, exception);
if (string.IsNullOrEmpty(message) && exception is null)
{
return;
}

var scopeSuffix = BuildScopeSuffix();
var eventPrefix = eventId.Id != 0 ? $"[{eventId.Id}/{eventId.Name}] " : string.Empty;
var finalMessage = $"{eventPrefix}{message}{scopeSuffix}";

switch (logLevel)
{
case LogLevel.Trace:
// Existing stack: Trace logs an empty line; append message via Debug.
Logger.LogTrace();

if (!string.IsNullOrEmpty(message))
{
Logger.LogDebug(finalMessage, exception);
}

break;

case LogLevel.Debug:
Logger.LogDebug(finalMessage, exception);

break;

case LogLevel.Information:
Logger.LogInfo(finalMessage, exception);

break;

case LogLevel.Warning:
Logger.LogWarning(finalMessage, exception);

break;

case LogLevel.Error:
case LogLevel.Critical:
Logger.LogError(finalMessage, exception);

break;

case LogLevel.None:
default:
break;
}
}

private static string BuildScopeSuffix()
{
var stack = _scopeStack.Value;
if (stack is null || stack.Count == 0)
{
return string.Empty;
}

// Show most-recent first.
return $" [Scopes: {string.Join(" => ", stack.ToArray())}]";
}

private sealed partial class Scope : IDisposable
{
private readonly Stack<object> _stack;
private bool _disposed;

public Scope(Stack<object> stack) => _stack = stack;

public void Dispose()
{
if (_disposed)
{
return;
}

if (_stack.Count > 0)
{
_stack.Pop();
}

_disposed = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>

Expand Down
Loading
Loading