-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AOT] Refactor Logger function to improve performance and mark managedCommon as AOT compatible #36327
base: main
Are you sure you want to change the base?
[AOT] Refactor Logger function to improve performance and mark managedCommon as AOT compatible #36327
Changes from all commits
6acfda1
f648b7a
0c03d2c
8c41509
925f44c
e86fbef
e0a2758
5ce827e
69244d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,15 +15,14 @@ namespace ManagedCommon | |
{ | ||
public static class Logger | ||
{ | ||
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly(); | ||
private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion; | ||
|
||
private static readonly string Error = "Error"; | ||
private static readonly string Warning = "Warning"; | ||
private static readonly string Info = "Info"; | ||
private static readonly string Debug = "Debug"; | ||
private static readonly string TraceFlag = "Trace"; | ||
|
||
private static readonly string Version = GetVersion(); | ||
|
||
/// <summary> | ||
/// Initializes the logger and sets the path for logging. | ||
/// </summary> | ||
|
@@ -53,18 +52,37 @@ public static void InitializeLogger(string applicationLogPath, bool isLocalLow = | |
Trace.AutoFlush = true; | ||
} | ||
|
||
public static string GetVersion() | ||
{ | ||
string applicationName = "PowerToys.exe"; | ||
try | ||
{ | ||
var versionInfo = FileVersionInfo.GetVersionInfo(Path.Combine(System.AppContext.BaseDirectory, applicationName)); | ||
if (versionInfo != null) | ||
{ | ||
return versionInfo.ProductVersion; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
return "0.0.0.1"; | ||
} | ||
|
||
return "0.0.0.1"; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void LogError(string message) | ||
public static void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) | ||
{ | ||
Log(message, Error); | ||
Log(message, Error, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void LogError(string message, Exception ex) | ||
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); | ||
Log(message, Error, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
else | ||
{ | ||
|
@@ -83,38 +101,38 @@ public static void LogError(string message, Exception ex) | |
"Stack trace: " + Environment.NewLine + | ||
ex.StackTrace; | ||
|
||
Log(exMessage, Error); | ||
Log(exMessage, Error, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void LogWarning(string message) | ||
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); | ||
Log(message, Warning, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void LogInfo(string message) | ||
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); | ||
Log(message, Info, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void LogDebug(string message) | ||
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) | ||
{ | ||
Log(message, Debug); | ||
Log(message, Debug, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void LogTrace() | ||
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); | ||
Log(string.Empty, TraceFlag, memberName, sourceFilePath, sourceLineNumber); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May be we don't need this one anymore. |
||
private static void Log(string message, string type) | ||
private static void Log(string message, string type, string memberName, string sourceFilePath, int sourceLineNumber) | ||
{ | ||
Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo()); | ||
Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo(memberName, sourceFilePath, sourceLineNumber)); | ||
Trace.Indent(); | ||
if (message != string.Empty) | ||
{ | ||
|
@@ -124,49 +142,27 @@ private static void Log(string message, string type) | |
Trace.Unindent(); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
private static string GetCallerInfo() | ||
{ | ||
StackTrace stackTrace = new(); | ||
|
||
var callerMethod = GetCallerMethod(stackTrace); | ||
|
||
return $"{callerMethod?.DeclaringType?.Name}::{callerMethod.Name}"; | ||
} | ||
|
||
private static MethodBase GetCallerMethod(StackTrace stackTrace) | ||
private static string GetCallerInfo(string memberName, string sourceFilePath, int sourceLineNumber) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For sourceLineNumber. Last but not least, do we know how to view PowerToys log? If we can parrse the log and show a summary of before after, it will give confidence of this changes. |
||
{ | ||
const int topFrame = 3; | ||
|
||
var topMethod = stackTrace.GetFrame(topFrame)?.GetMethod(); | ||
string callerFileName = "Unknown"; | ||
|
||
try | ||
{ | ||
if (topMethod?.Name == nameof(IAsyncStateMachine.MoveNext) && typeof(IAsyncStateMachine).IsAssignableFrom(topMethod?.DeclaringType)) | ||
string fileNameWithoutEx = Path.GetFileNameWithoutExtension(sourceFilePath); | ||
if (!string.IsNullOrEmpty(fileNameWithoutEx)) | ||
{ | ||
// Async method; return actual method as determined by heuristic: | ||
// "Nearest method on stack to async state-machine's MoveNext() in same namespace but in a different type". | ||
// There are tighter ways of determining the actual method, but this is good enough and probably faster. | ||
for (int deepFrame = topFrame + 1; deepFrame < stackTrace.FrameCount; deepFrame++) | ||
{ | ||
var deepMethod = stackTrace.GetFrame(deepFrame)?.GetMethod(); | ||
|
||
if (deepMethod?.DeclaringType != topMethod?.DeclaringType && deepMethod?.DeclaringType?.Namespace == topMethod?.DeclaringType?.Namespace) | ||
{ | ||
return deepMethod; | ||
} | ||
} | ||
callerFileName = fileNameWithoutEx; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
// Ignore exceptions in Release. The code above won't throw, but if it does, we don't want to crash the app. | ||
callerFileName = "Unknown"; | ||
#if DEBUG | ||
throw; | ||
#endif | ||
} | ||
|
||
return topMethod; | ||
return $"{callerFileName}::{memberName}"; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// 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 System.Text.Json.Serialization; | ||
using static ManagedCommon.LanguageHelper; | ||
|
||
namespace ManagedCommon; | ||
|
||
[JsonSerializable(typeof(OutGoingLanguageSettings))] | ||
internal sealed partial class ManagedCommonJsonSerializerContext : JsonSerializerContext | ||
{ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just ask the caller to pass in its own class type?
From Github copilot, the following code should be AOT compatible:
var versionInfo = FileVersionInfo.GetVersionInfo(typeof(Program).Assembly.Location);
Console.WriteLine($"Version: {versionInfo.FileVersion}