个人网站开发(三) 日志系统

功能需求说明

  • 记录错误
    在网站开发中、发布后肯定会出现很多错误,有大有小,不但不能将这些错误提示给使用人员(优化用户体验),还需要通过日志功能将这些异常记录下来。开发人员可以通过日志迅速发现问题,进而修复问题。
  • 记录访问、操作信息
    在网站运行中需要对访问者的访问记录、操作进行记录。

功能实现

以前就是使用自己开发一个简单的日志类,进行记录。但是因为个人能力的不够,在使用的过程中出现了很多问题。于是在网上看看比较好的开源日志插件,最终选择使用Nlog这个。

  • 关于Nlog的安装使用
    这个是简书上我感觉这个是比较清楚的一个Nlog教程
  • 难点
    • 记录系统异常时需要记录异常的具体信息,在Nlog中使用Layout布局非常方便,使用Nlog的内置参数可以很清楚的记录错误的信息,这个是Nlog内置参数表。这个我用来记录系统异常的ConfigLayout配置。主要是将异常记录到文本中,将用户的操作和访问记录上传到数据库中.
  <variable name="variable1" value="
  ${newline}
  date(记录时间):   ${date}${newline}
  level(错误级别):  ${level}${newline}
  logger(记录器名称):    ${logger}${newline}
  machinename(机器名称):    ${machinename}${newline}
  appdomain(程序作用域): ${appdomain}${newline}
  assembly-version(程序版本):   ${assembly-version}${newline}
  basedir(程序目录):    ${basedir}${newline}
  callsite(类名称、方法名称和相关信息的源信息):  ${callsite:className=True:fileName=True:includeSourcePath=True:methodName=True}${newline}
  processid(进程ID):  ${processid}${newline}
  processname(进程的名称):   ${processname}${newline}
  message(错误提示-自定义):    ${message}${newline}
  exception(错误内容-信息):${exception}${newline}
  exception(错误内容-堆栈):${exception:format=StackTrace}${newline}
  -----------------------------------------------------------" />
  <targets>
    <target name="ErrorFile" xsi:type="File" fileName="file.txt"  layout="${variable1}" />
    <target name="LogRec" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
      <target type="Database" dbProvider="mssql" connectionString="Data Source=">
        <commandText>
          INSERT INTO Logs VALUES(@Level,@AuthorizationID,@Dates,@LogKinds,@PermissionID,@OpContent,@PermissionID,
          @OpRes,@IpAddress,@PageNameID);
        </commandText>
        <!-- database connection parameters -->
        <parameter name="@Level" layout="${event-context:item=Level}" />
        <parameter name="@AuthorizationID" layout="${event-context:item=AuthorizationID}" />
        <parameter name="@Dates" layout="${date}" />
        <parameter name="@LogKinds" layout="${event-context:item=LogKinds}" />
        <parameter name="@PermissionID" layout="${event-context:item=PermissionID}" />
        <parameter name="@OpContent" layout="${event-context:item=OpContent}" />
        <parameter name="@PermissionID" layout="${event-context:item=PermissionID}" />
        <parameter name="@OpRes" layout="${event-context:item=OpRes}" />
        <parameter name="@IpAddress" layout="${event-context:item=IpAddress}" />
        <parameter name="@PageNameID" layout="${event-context:item=PageNameID}" />
      </target>
    </target>
  </targets>

  <rules>
    <logger name="*" level="Info" writeTo="LogRec" />
    <logger name="*" minlevel="Error" writeTo="ErrorFile" />
  </rules>

异常是记录到程序根目录的file.txt文件中的

  • 记录用户访问、操作历史时需要使用到自定义的参数,这个我在数据库中用来记录用户访问、操作历史的表LogRec
字段名称 字段类型 字段说明
RecId int 记录的主键
Level nvarchar(20) 日志级别
AuthorizationID guid 进行操作的授权ID
Dates datetime 产生的时间
LogKinds nvarchar(20) 操作类型
PermissionID int 进行操作的ID
OpContent nvarchar(200) 操作的具体内容
OpRes bit 操作的结果
IpAddress varchar(20) 访客的IP地址
PageNameID int 具体的网址页面ID

Nlog配置与系统异常是一致的,只是这里要注意我使用了自定义参数

  • 程序中调用
    首先定义了一个Logs基础类
public class Logs
    {
        public enum Levels
        {
            Debug, Trace, Error, Fatal, Info
        }

        public int RecId { get; set; }
        public LogLevel Level { get; set; }
        public Guid AuthorizationID { get; set; }
        public DateTime Dates { get; set; }
        public string LogKinds { get; set; }
        public int PermissionID { get; set; }
        public string OpContent { get; set; }
        public bool OpRes { get; set; }
        public string IpAddress { get; set; }
        public int PageNameID { get; set; }

        public Logs(User user,string logkinds, Levels logLevel,string opContent,bool opRes,int permissionID)
        {
            AuthorizationID = user.AuthorizationID;
            IpAddress = user.LoginIp;
            PageNameID = user.PageNameID;
            Dates = DateTime.Now;
            LogKinds = logkinds;         
            OpContent = opContent;
            OpRes = opRes;
            PermissionID = permissionID;

            switch(logLevel)
            {
                case Levels.Debug:
                    {
                        Level = LogLevel.Debug;
                        break;
                    }
                case Levels.Trace:
                    {
                        Level = LogLevel.Trace;
                        break;
                    }
                case Levels.Error:
                    {
                        Level = LogLevel.Error;
                        break;
                    }
                case Levels.Fatal:
                    {
                        Level = LogLevel.Fatal;
                        break;
                    }
                case Levels.Info:
                    {
                        Level = LogLevel.Info;
                        break;
                    }
                default:
                    {
                        Level = LogLevel.Info;
                        break;
                    }
            }

        }
    }

再定义了一个Logger使用类

public class Logger
    {
        NLog.Logger _logger;

        private Logger(NLog.Logger logger)
        {
            _logger = logger;
        }

        public Logger(string name) : this(LogManager.GetLogger(name))
        {

        }

        public static Logger Default { get; private set; }
        static Logger()
        {
            Default = new Logger(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);
        }

        /// <summary>
        /// 记录系统异常
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="err"></param>
        public void Info(string msg, Exception err)
        {
            _logger.Error(err, msg);
        }
        #endregion

        #region Warn
        public void Warn(string msg, params object[] args)
        {
            _logger.Warn(msg, args);
        }

        public void Warn(string msg, Exception err)
        {
            _logger.Warn(err, msg);
        }
        #endregion

        #region Trace
        public void Trace(string msg, params object[] args)
        {
            _logger.Trace(msg, args);
        }

        public void Trace(string msg, Exception err)
        {
            _logger.Trace(err, msg);
        }
        #endregion

        #region Error
        public void Error(string msg, params object[] args)
        {
            _logger.Error(msg, args);
        }

        public void Error(string msg, Exception err)
        {
            _logger.Error(err, msg);
        }
        #endregion

        #region Fatal
        public void Fatal(string msg, params object[] args)
        {
            _logger.Fatal(msg, args);
        }

        public void Fatal(string msg, Exception err)
        {
            _logger.Fatal(err, msg);
        }
        #endregion



        #region Custom

        /// <summary>
        /// 记录用户操作、访问记录
        /// </summary>
        /// <param name="log"></param>
        public void Process(Logs log)
        {

            var ei = new MyLogEventInfo(log.Level, _logger.Name, log.LogKinds);
            ei.TimeStamp = log.Dates;
            ei.Properties["Action"] = log.IpAddress;
            ei.Properties["Amount"] = log.OpContent;

            _logger.Log(log.Level, ei);
        }

        #endregion

        /// <summary>
        /// Flush any pending log messages (in case of asynchronous targets).
        /// </summary>
        /// <param name="timeoutMilliseconds">Maximum time to allow for the flush. Any messages after that time will be discarded.</param>
        public void Flush(int? timeoutMilliseconds = null)
        {
            if (timeoutMilliseconds != null)
                NLog.LogManager.Flush(timeoutMilliseconds.Value);

            NLog.LogManager.Flush();
        }
    }

    public class MyLogEventInfo : LogEventInfo
    {
        public MyLogEventInfo() { }
        public MyLogEventInfo(LogLevel level, string loggerName, string message) : base(level, loggerName, message)
        { }

        public override string ToString()
        {
            //Message format
            //Log Event: Logger='XXX' Level=Info Message='XXX' SequenceID=5
            return FormattedMessage;
        }
    }

在程序中调用的时候,如果需要记录异常

try
{
      //执行代码
}
catch (Exception e1)
{
       //进行异常记录
       Logger.Default.Error("用户登录校验", e1);
}

如果要记录用户的访问记录

 Logs logs = new Logs(user, "新增", Logs.Levels.Info, "新增标签记录"+results, true, 100001);
 Logger.Default.Process(logs);

至此基本的日志功能就搭建好了,因为目前网站处于基础的开发阶段,后面要对日志进行更细致的分类记录,到时候再和大家探讨下!就酱了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容