[英]How to Add User Information to nlog Error Logging
我最近開始使用 nLog 來記錄我的應用程序上的錯誤。 但是,我來這里是想看看如果在異常發生時用戶當前已登錄應用程序,是否有任何方法可以將有關應用程序當前登錄用戶的一些信息添加到日志布局中。
目前我有以下布局:
<target xsi:type="File" name="errorlogs" fileName="./logs/error-logs/${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
但是,如果在應用程序上有登錄用戶時發生異常,我希望添加當前登錄用戶的電子郵件。
我的應用程序在 ASP.Net Core 3.1 上運行。
如何將其添加到布局中。
謝謝
也許不是 100% 合適,因為您的問題依賴於用戶登錄到您的應用程序,以及您的應用程序在其用戶上下文中運行,但以下內容在“正常”應用程序編程中對我有用......
創建一個新的公共靜態類。 我稱我的為“記錄”。 如果您的程序集還沒有它,請添加對 NLog 的引用。
輸出格式是免費提供的 Microsoft CMTrace 實用程序使用的格式。 可在此處獲得: CMTrace 下載鏈接
添加以下內容:
public static class Logging
{
#region Fields
private static bool _IsSetup = false;
private static Logger _Log = LogManager.GetCurrentClassLogger();
#endregion
#region Private Methods
[MethodImpl(MethodImplOptions.NoInlining)]
private static string GetCurrentMethod()
{
StackTrace st = new StackTrace();
int FrameNumber = 1;
StackFrame sf = st.GetFrame(FrameNumber); // Get the previous stack frame
string MethodName = sf.GetMethod().Name;
string ClassName = sf.GetMethod().ReflectedType.FullName;
while (MethodName == "Log" || MethodName.StartsWith("Write")) // If it's the "Log" or "Write" method calling this, get the method before that one.
{
FrameNumber++;
if (FrameNumber < 6)
{
try
{
MethodName = st.GetFrame(FrameNumber).GetMethod().Name;
ClassName = st.GetFrame(FrameNumber).GetMethod().ReflectedType.FullName;
}
catch
{
}
}
else // Prevent an infinite loop
{
MethodName = "Unknown Method";
ClassName = "Unknown Class";
}
}
return ClassName + "." + MethodName;
}
#endregion
#region Public Methods
/// <summary>
/// Append the specified text to the given TextBox
/// </summary>
/// <param name="Message">The message to append</param>
/// <param name="Control">The TextBox to target</param>
public static void LogToTextbox(string Message, TextBox Control)
{
if (Message.Length > 0)
{
Control.AppendText(Message + Environment.NewLine);
Control.Refresh();
Application.DoEvents();
}
}
/// <summary>
/// Setup Logging
/// </summary>
/// <param name="Overwrite">If set to true, any existing file will be over-written</param>
public static void Setup(bool Overwrite = false)
{
LoggingConfiguration Config = new LoggingConfiguration();
FileTarget File = new FileTarget();
Config.AddTarget("File", File);
File.Layout = "${message}";
File.FileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Application.CompanyName, System.Diagnostics.Process.GetCurrentProcess().ProcessName) + ".log";
File.AutoFlush = true;
File.KeepFileOpen = false;
File.ArchiveFileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Application.CompanyName, System.Diagnostics.Process.GetCurrentProcess().ProcessName) + "_{#}.log";
File.ArchiveNumbering = ArchiveNumberingMode.Rolling;
File.ArchiveEvery = FileArchivePeriod.Day;
File.MaxArchiveDays = 31;
if (Overwrite)
{
File.DeleteOldFileOnStartup = true;
}
// Create rules
LoggingRule Rule1 = new LoggingRule("*", LogLevel.Trace, File);
// Apply rules
Config.LoggingRules.Add(Rule1);
// Activate logging
LogManager.Configuration = Config;
// Cleanup
_IsSetup = true;
}
/// <summary>
/// Write the specified message type and string to the logfile, located at %PROGRAMDATA/[Application.CompanyName]
/// </summary>
/// <param name="Level">The level of message to write</param>
/// <param name="Message">The message to write</param>
public static void Write(LogLevel Level, string Message)
{
string Severity;
string OutputMessage;
DateTime UtcNow = DateTime.UtcNow;
DateTime Now = DateTime.Now;
string UtcDate = UtcNow.ToString("MM-dd-yyyy");
string UtcTime = UtcNow.ToString("HH:mm:ss.") + UtcNow.Millisecond;
string Date = Now.ToString("dd-MM-yyyy");
string Time = Now.ToString("HH:mm:ss.") + UtcNow.Millisecond;
string TZOffset = TimeZoneInfo.Local.GetUtcOffset(Now).TotalHours.ToString("+000");
if (!_IsSetup)
{
Setup();
}
Trace.WriteLine(Message);
Message = $"{Date} {Time}: {Message}";
switch (Level.Name)
{
default:
Severity = "0";
break;
case "Info":
Severity = "1";
break;
case "Warn":
Severity = "2";
break;
case "Error":
Severity = "3";
break;
}
// https://adamtheautomator.com/building-logs-for-cmtrace-powershell/
OutputMessage = $"<![LOG[{Message}]LOG]!><time=\"{UtcTime}{TZOffset}\" date=\"{UtcDate}\" component=\"{GetCurrentMethod()}\" context=\"{Environment.UserName}\" type=\"{Severity}\" thread=\"{Thread.CurrentThread.ManagedThreadId}\" file=\"{System.Diagnostics.Process.GetCurrentProcess().ProcessName}\">";
// The following can be used as a catch-all
//try
//{
_Log.Log(Level, OutputMessage);
//}
//catch (Exception e)
//{
// // If we cannot write to the log file, write to the EventLog instead.
// using (EventLog eventLog = new EventLog("Application"))
// {
// string OutputFolderName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Application.CompanyName);
// string ExecutableName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
// eventLog.Source = "Application";
// eventLog.WriteEntry($"Failed to write to application logfile (in {OutputFolderName}) for {ExecutableName}. The error was: {e.Message}", EventLogEntryType.Error, 101, 1);
// }
//}
}
/// <summary>
/// Write a error message to the logfile, located at %PROGRAMDATA/[Application.CompanyName]
/// </summary>
/// <param name="Message">The message to write</param>
public static void WriteError(string Message)
{
Write(LogLevel.Error, Message);
}
/// <summary>
/// Write an informational message to the logfile, located at %PROGRAMDATA/[Application.CompanyName]
/// </summary>
/// <param name="Message">The message to write</param>
public static void WriteInfo(string Message)
{
Write(LogLevel.Info, Message);
}
/// <summary>
/// Write a warning message to the logfile, located at %PROGRAMDATA/[Application.CompanyName]
/// </summary>
/// <param name="Message">The message to write</param>
public static void WriteWarning(string Message)
{
Write(LogLevel.Warn, Message);
}
#endregion
}
用法:
Logging.Setup();
Logging.WriteInfo("Application startup");
Logging.WriteError($"{DestinationFilename}: Cannot overwrite file. User advised to delete file manually. The error was: {ex.Message}");
示例輸出:
<![LOG[20-11-2020 13:22:48.626: Application startup]LOG]!><time="05:22:48.626+008" date="11-20-2020" component="Bitberry.Elda.GetLatest.frmMain..ctor" context="DaveR" type="1" thread="1" file="GetLatest">
具體來說,'context="USERNAME"' 部分就是您所要求的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.