OperatorLog
CREATE TABLE [dbo].[OperatorLog]( [Id] [BIGINT] IDENTITY(1,1) NOT NULL, [Createdate] [DATETIME] NOT NULL DEFAULT (GETDATE()), [CreatedBy] [NVARCHAR](50) NULL, [IsDeleted] [BIT] NOT NULL, [ModuleName] [NVARCHAR](30) NULL, [Origin] [NVARCHAR](50) NULL, [Type] [NVARCHAR](50) NULL, [LogLevel] [NVARCHAR](20) NOT NULL, [LogMessage] [NVARCHAR](500) NULL, [Exception] [NVARCHAR](500) NULL, [Logger] [NVARCHAR](500) NULL CONSTRAINT [PK_OperatorLog] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志表主键ID' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Createdate' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建人' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'CreatedBy' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否删除' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'IsDeleted' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'模块名称' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'ModuleName' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'来源' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Origin' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'类型' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Type' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志级别' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'LogLevel' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志内容' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'LogMessage' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'异常信息' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Exception' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志名称' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog', @level2type=N'COLUMN',@level2name=N'Logger' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日志记录' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'OperatorLog' GO
PathHelper
using System; using System.IO; using System.Reflection; namespace ShiShuo.Utilities { public static class PathHelper { private static readonly string _appDir; private static readonly string _configDir; private static readonly string _dataDir; static PathHelper() { //网站与后台服务路径不同,网站需要上翻一级;后台服务则不需要;通过判断使用的配置文件是否是web.config来判断是网站,还是服务。 bool isWeb = false; var appDomain = AppDomain.CurrentDomain; if (appDomain != null) { var startInfo = appDomain.SetupInformation; if (startInfo != null) { if (startInfo.ConfigurationFile != null) { if (startInfo.ConfigurationFile.EndsWith("web.config", StringComparison.OrdinalIgnoreCase)) { isWeb = true; //配置文件是网站 } } } } _appDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Substring(8))); //获取此处配置文件在程序目录 //_appDir = _appDir.Substring(0, _appDir.Length - 4); if (isWeb) { _appDir = _appDir.Substring(0, _appDir.LastIndexOf("\", StringComparison.Ordinal)); // LastIndexOf("\") => LastIndexOf(@""),向上翻一级 } _configDir = Path.Combine(_appDir, "Config\"); _dataDir = Path.Combine(_appDir, "App_Data\"); } #region 公共目录 /// <summary> /// 应用程序所在的目录 /// </summary> public static string AppDir => _appDir; /// <summary> /// 根目录中的Cinfig文件夹 /// </summary> public static string ConfigDir => _configDir; /// <summary> /// 根目录中的App_Data文件夹 /// </summary> public static string DataDir => _dataDir; #endregion } }
NLogger
using NLog; using NLog.Config; using System; using System.IO; namespace ShiShuo.Utilities { public class NLogger { readonly Logger _logger; private static NLogger _instance; private static readonly object _syncObject = new object(); public static NLogger GetInstance() { if (_instance != null) { return _instance; } lock (_syncObject) { if (_instance != null) { return _instance; } string configPath = Path.Combine(PathHelper.ConfigDir, "NLog.config"); LogManager.Configuration = new XmlLoggingConfiguration(configPath, true); _instance = new NLogger("MyLogger"); //_instance = new NLogger(NLog.LogManager.GetCurrentClassLogger()); return _instance; } } private NLogger(NLog.Logger logger) { this._logger = logger; } public NLogger(string name) : this(NLog.LogManager.GetLogger(name)) { } public static NLogger Default { get; private set; } private LogEventInfo lei = new LogEventInfo(); static NLogger() { string configPath = Path.Combine(PathHelper.ConfigDir, "NLog.config"); LogManager.Configuration = new XmlLoggingConfiguration(configPath, true); Default = new NLogger("MyLogger"); //Default = new NLogger(NLog.LogManager.GetCurrentClassLogger()); } #region Debug public void Debug(string msg, params object[] args) { _logger.Debug(msg, args); } public void Debug(string msg, Exception err) { _logger.Debug(err, msg); } #endregion #region Info public void Info(string msg, params object[] args) { _logger.Info(msg, args); } public void Info(string msg, Exception err) { _logger.Info(err, msg); } #endregion #region Warn /// <summary> ///警告 /// </summary> /// <param name="msg">警告信息</param> /// <param name="args">动态参数</param> public void Warn(string msg, params object[] args) { _logger.Warn(msg, args); } /// <summary> ///警告 /// </summary> /// <param name="msg">警告信息</param> /// <param name="err">异常信息</param> public void Warn(string msg, Exception err) { _logger.Warn(err, msg); } #endregion #region Trace /// <summary> /// 使用指定的参数在跟踪级别写入诊断消息 /// </summary> /// <param name="msg">跟踪信息</param> /// <param name="args">动态参数</param> public void Trace(string msg, params object[] args) { _logger.Trace(msg, args); } /// <summary> /// 使用指定的参数在跟踪级别写入诊断消息 /// </summary> /// <param name="msg">跟踪信息</param> /// <param name="args">异常信息</param> public void Trace(string msg, Exception err) { _logger.Trace(err, msg); } #endregion #region Error /// <summary> /// 使用指定的参数在错误级别写入诊断消息。 /// </summary> /// <param name="msg">错误信息</param> /// <param name="args">动态参数</param> public void Error(string msg, params object[] args) { _logger.Error(msg, args); } /// <summary> /// 使用指定的参数在错误级别写入诊断消息。 /// </summary> /// <param name="msg">错误信息</param> /// <param name="args">异常信息</param> public void Error(string msg, Exception err) { _logger.Error(err, msg); } #endregion #region Fatal /// <summary> /// 使用指定的参数在致命级别写入诊断消息。 /// </summary> /// <param name="msg">致命错误</param> /// <param name="args">动态参数</param> public void Fatal(string msg, params object[] args) { _logger.Fatal(msg, args); } /// <summary> /// 使用指定的参数在致命级别写入诊断消息。 /// </summary> /// <param name="msg">致命错误</param> /// <param name="args">异常信息</param> public void Fatal(string msg, Exception err) { _logger.Fatal(err, msg); } #endregion /// <summary> /// 写入日志信息 /// </summary> /// <param name="operatorLogModel">操作信息</param> public void InsOperatorLog(OperatorLogModel operatorLogModel) { var level = LogLevel.Info; if (!string.IsNullOrEmpty(operatorLogModel.LogLevel)) { switch (operatorLogModel.LogLevel) { case "Trace": level = LogLevel.Trace; break; case "Debug": level = LogLevel.Debug; break; case "Info": level = LogLevel.Info; break; case "Warn": level = LogLevel.Warn; break; case "Error": level = LogLevel.Error; break; case "Fatal": level = LogLevel.Fatal; break; } } if (operatorLogModel.LogMessage.Length > 3000) { operatorLogModel.LogMessage = operatorLogModel.LogMessage.Substring(0, 3000); } lei.Properties["Createdate"] = operatorLogModel.Createdate; lei.Properties["IsDeleted"] = operatorLogModel.IsDeleted; lei.Properties["CreatedBy"] = operatorLogModel.CreatedBy; lei.Properties["ModuleName"] = operatorLogModel.ModuleName; lei.Properties["Origin"] = operatorLogModel.Origin; lei.Properties["LogMessage"] = operatorLogModel.LogMessage; lei.Properties["Type"] = operatorLogModel.Type; lei.Level = level; lei.Message = operatorLogModel.LogMessage; _logger.Log(level, lei); } } }
Nlog.config
<?xml version="1.0" encoding="utf-8"?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwConfigExceptions="true" internalLogLevel="Debug" internalLogToTrace="true"> <targets> <!--写入文件--> <target xsi:type="File" name="DebugFile" fileName="${basedir}/Logs/Debug/${shortdate}.log" layout="日志时间:${longdate}${newline}日志来源:${callsite}${newline}日志级别:${uppercase:${level}}${newline}消息内容:${message}${newline}异常信息:${exception}${newline}==============================================================${newline}" > </target> <target xsi:type="File" name="InfoFile" fileName="${basedir}/Logs/Debug/${shortdate}.log" layout="日志时间:${longdate}${newline}日志来源:${callsite}${newline}日志级别:${uppercase:${level}}${newline}消息内容:${message}${newline}异常信息:${exception}${newline}==============================================================${newline}" > </target> <target xsi:type="File" name="ErrorFile" fileName="${basedir}/Logs/Debug/${shortdate}.log" layout="日志时间:${longdate}${newline}日志来源:${callsite}${newline}日志级别:${uppercase:${level}}${newline}消息内容:${message}${newline}异常信息:${exception}${newline}==============================================================${newline}" > </target> <target xsi:type="Database" name="DBLogFile" > <dbProvider>System.Data.SqlClient</dbProvider> <connectionString> Data Source=.sql2014;Initial Catalog=YIDaSi_richdata;Persist Security Info=true;User ID=sa;Password=Aa123456; </connectionString> <commandText> INSERT INTO OperatorLog(Createdate,CreatedBy,IsDeleted,ModuleName,Origin,Type,LogLevel,LogMessage,Exception,Logger) VALUES(@Createdate,@CreatedBy,@IsDeleted,@ModuleName,@Origin,@Type,@LogLevel,@LogMessage,@Exception,@Logger) </commandText> <!--<parameter name="@Createdate" layout="${event-context:item=Createdate}" />--> <parameter name="@Createdate" layout="${date}" /> <parameter name="@CreatedBy" layout="${event-context:item=CreatedBy}" /> <parameter name="@IsDeleted" layout="${event-context:item=IsDeleted}" /> <parameter name="@ModuleName" layout="${event-context:item=ModuleName}" /> <parameter name="@Origin" layout="${event-context:item=Origin}" /> <parameter name="@Type" layout="${event-context:item=Type}" /> <parameter name="@LogLevel" layout="${level}" /> <!--<parameter name="@LogMessage" layout="${event-context:item=LogMessage}" />--> <parameter name="@LogMessage" layout="${message}" /> <parameter name="@Exception" layout=" ${exception}" /> <parameter name="@Logger" layout=" ${logger}" /> </target> </targets> <rules> <!--根据日志级别分别写文件,也可以放一个文件中--> <!--<logger name="DbLogger" levels="Debug,Info,Error" writeTo="MyFile" />--> <logger name="MyLogger" level="Debug" writeTo="DebugFile" /> <logger name="MyLogger" level="Info" writeTo="InfoFile" /> <logger name="MyLogger" level="Error" writeTo="ErrorFile" /> <!--写数据库--> <logger name="MyLogger" levels="Trace,Debug,Info,Error" writeTo="DBLogFile"/> </rules> </nlog>
日志插件对比
https://dotnet.libhunt.com/project/log4net/vs/semantic-logging?rel=cmp-cmp
日志记录插件源码:
https://github.com/NLog/NLog
https://github.com/serilog/serilog
https://github.com/apache/log4net
https://github.com/elmah/Elmah
https://github.com/logary/logary
https://www.cnblogs.com/yiliukejich0614-1234/p/9914376.html NLog组件
https://www.cnblogs.com/TianFang/p/4003749.html
https://blog.csdn.net/Dandelion_gong/article/details/78018056
https://blog.csdn.net/weixin_33915554/article/details/85521919
https://www.cnblogs.com/tider1999/p/4308440.html