EntLib6 Logging Application Block 通过CustomTraceListener实现自动按Category建立不同的log文件

对比log4net,EntLib 的可视化配置以及完善的文档实在是占了挺大的优势,但两者在文件日志方面都存在着相同的问题,就是不能根据Category(log4net里面是logger name)自动分类存放(所有的日志都记在一个日志文件里,当查看日志时会相对比较麻烦),如果想实现分类存放,那就需要在config文件里写上一大堆的配置,作为懒人,这肯定是不能接受的,当然是写的越少越好:P

在code之前先描述下设计思路:

首先说下前提,EntLib 的Logging Application Block支持SpecialSources,它包含三部分AllEvents、LoggingErrorsAndWarnings以及Unprocessed,这里面的Unprocessed对应的就是Unprocessed Category,所有未定义过的Categories都会被分配到此部分,如果Unprocessed没设置TraceListener,那就会由LoggingErrorsAndWarnings来处理这里日志

其次是思路,说白了很简单,就是根据Category动态创建新的RollingFlatFileTraceListener,然后在记录日志时,由Category对应的RollingFlatFileTraceListener来处理相应的日志,如果无法识别的日志,则由默认的RollingFlatFileTraceListener来处理

PS:由于还未实现对应的TraceListenerData,所以暂时还不支持通过配置文件来配置,只能通过编码方式添加,后续会将此部分补上

以下是具体code

    using System.IO;
    using System.Collections.Concurrent;
    using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
    using System.Diagnostics;
    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
    using Microsoft.Practices.EnterpriseLibrary.Common.Utility;
    /// <summary>
    /// 根据Category自动分类保存日志
    /// </summary>
    public class AutoCategoryRollingFlatFileTraceListener : CustomTraceListener
    {
        private ConcurrentDictionary<string, RollingFlatFileTraceListener> _dic = new ConcurrentDictionary<string, RollingFlatFileTraceListener>();
        private RollingFlatFileTraceListener _defaultListener;

        private readonly string _directory;
        private readonly string _extension;
        private readonly string _header;
        private readonly string _footer;
        private readonly int _rollSizeKB;
        private readonly string _timeStampPattern;
        private readonly RollFileExistsBehavior _rollFileExistsBehavior;
        private readonly RollInterval _rollInterval;
        private readonly int _maxArchivedFiles;

        /// <summary>
        /// Initializes a new instance of the <see cref="RollingFlatFileTraceListener"/> class.
        /// </summary>
        /// <param name="fileName">The filename where the entries will be logged.</param>
        /// <param name="header">The header to add before logging an entry.</param>
        /// <param name="footer">The footer to add after logging an entry.</param>
        /// <param name="formatter">The formatter.</param>
        /// <param name="rollSizeKB">The maxium file size (KB) before rolling.</param>
        /// <param name="timeStampPattern">The date format that will be appended to the new roll file.</param>
        /// <param name="rollFileExistsBehavior">Expected behavior that will be used when the roll file has to be created.</param>
        /// <param name="rollInterval">The time interval that makes the file rolles.</param>
        /// <param name="maxArchivedFiles">The maximum number of archived files to keep.</param>
        public AutoCategoryRollingFlatFileTraceListener(string fileName,
                                            string header = RollingFlatFileTraceListener.DefaultSeparator,
                                            string footer = RollingFlatFileTraceListener.DefaultSeparator,
                                            ILogFormatter formatter = null,
                                            int rollSizeKB = 0,
                                            string timeStampPattern = "yyyy-MM-dd",
                                            RollFileExistsBehavior rollFileExistsBehavior = RollFileExistsBehavior.Overwrite,
                                            RollInterval rollInterval = RollInterval.None,
                                            int maxArchivedFiles = 0)
        {
            Guard.ArgumentNotNullOrEmpty(fileName, "fileName");
            this._directory = Path.GetDirectoryName(fileName);
            this._extension = Path.GetExtension(fileName);
            this._header = header;
            this._footer = footer;
            this._rollSizeKB = rollSizeKB;
            this._timeStampPattern = timeStampPattern;
            this._rollFileExistsBehavior = rollFileExistsBehavior;
            this._rollInterval = rollInterval;
            this._maxArchivedFiles = maxArchivedFiles;

            this.Formatter = formatter;

            this._defaultListener = new RollingFlatFileTraceListener(fileName, this._header, this._footer,
                            this.Formatter, this._rollSizeKB, this._timeStampPattern,
                            this._rollFileExistsBehavior, this._rollInterval, this._maxArchivedFiles);
        }
        public override void Write(string message)
        {
            this._defaultListener.Write(message);
        }

        public override void WriteLine(string message)
        {
            this._defaultListener.WriteLine(message);
        }

        public override void Flush()
        {
            this._defaultListener.Flush();
        }

        /// <summary>
        /// Delivers the trace data to the underlying file.
        /// </summary>
        /// <param name="eventCache">The context information provided by <see cref="System.Diagnostics"/>.</param>
        /// <param name="source">The name of the trace source that delivered the trace data.</param>
        /// <param name="eventType">The type of event.</param>
        /// <param name="id">The id of the event.</param>
        /// <param name="data">The data to trace.</param>
        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
        {
            if (this.Filter == null || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))
            {
                var listener = this._defaultListener;
                if (data is LogEntry)
                {
                    ((LogEntry)data).Categories.ForEach((category) =>
                    {
                        var tmpListener = this.GetTraceListener(category);
                        tmpListener.TraceData(eventCache, source, eventType, id, data);
                        tmpListener.Flush();
                    });
                    return;
                }

                listener.TraceData(eventCache, source, eventType, id, data);
                listener.Flush();
            }
        }

        private RollingFlatFileTraceListener GetTraceListener(string category)
        {
            RollingFlatFileTraceListener listener = this._defaultListener;
            if (!string.IsNullOrWhiteSpace(category))
            {
                category = category.ToLower().Trim();
                if (this._dic.ContainsKey(category))
                {
                    return this._dic[category];
                }
                else
                {
                    try
                    {
                        string fileName = Path.Combine(this._directory, category, string.Format("{0}{1}", category, this._extension));
                        var tmpListener = new RollingFlatFileTraceListener(fileName, this._header, this._footer,
                            this.Formatter, this._rollSizeKB, this._timeStampPattern,
                            this._rollFileExistsBehavior, this._rollInterval, this._maxArchivedFiles);
                        this._dic.TryAdd(category, tmpListener);
                        listener = tmpListener;
                    }
                    catch
                    {
                    }
                }
            }
            return listener;
        }
    }

注册代码如下

Logger.Writer.Configure(config =>
            {
                AutoCategoryRollingFlatFileTraceListener acListener = new AutoCategoryRollingFlatFileTraceListener("../applog/auto/auto.log", rollFileExistsBehavior: RollFileExistsBehavior.Increment,
                    rollInterval: RollInterval.Minute, timeStampPattern: "yyyyMMddHHmm");
                config.SpecialSources.Unprocessed.AddAsynchronousTraceListener(acListener);//异步执行
            });

实际使用的与正常日志无区别

Logger.Write(string.Format("Get Single Product By ID:{0}", id), "Product");//Product在config中有配置
Logger.Write(string.Format("Get Single Product By ID:{0}", id), "ProductU");//ProductU在config中未配置
Logger.Write(string.Format("Get Single Product By ID:{0}", id), new List<string>() { "ProductX", "ProductXX" });//ProductX、ProductXX在config中未配置
				
时间: 2024-08-03 23:44:27

EntLib6 Logging Application Block 通过CustomTraceListener实现自动按Category建立不同的log文件的相关文章

Enterprise Library 6——Using the Logging Application Block

原文参考 http://msdn.microsoft.com/en-us/library/dn440731(v=pandp.60).aspx 一.简介 日志通常满足两个主要的要求:1.监控应用程序性能并提供信息.性能方面,日志可以监控程序内部发生了什么,有时也监控程序外部发生了什么.2.更重要的是用于审计.这种日志可以跟踪用户的行为并且记录用户执行的一系列任务.读取和修改的信息.访问的资源. 日志模块是一个高灵活和可配置的解决方案,它允许以灵活多样的方式创建和存储日志信息于各种位置.分类并过滤信

Enterprise Library 6.0 Semantic Logging Application Block Configuration

使用Enterprise Library 6.0的Logging application 模块,配置步骤如下: 1.Nuget 安装 Enterprise Library Logging模块 命令行:Install-package EnterpriseLibrary.Logging. 2.配置文件: 当前基本都是通过Enterprise Library 配置的,但是很不幸,我的总是安装失败,于是自己baidu了一把,然后进行配置,配置如下: <configSections> <secti

Enterprise Library 6——Using the Logging Application Block2

原文参考?http://msdn.microsoft.com/en-us/library/dn440731(v=pandp.60).aspx 一.简介 日志通常满足两个主要的要求:1.监控应用程序性能并提供信息.性能方面,日志可以监控程序内部发生了什么,有时也监控程序外部发生了什么.2.更重要的是用于审计.这种日志可以跟踪用户的行为并且记录用户执行的一系列任务.读取和修改的信息.访问的资源. 日志模块是一个高灵活和可配置的解决方案,它允许以灵活多样的方式创建和存储日志信息于各种位置.分类并过滤信

[EntLib]微软企业库6 基于Data Access Application Block的Repository

名字起得有点夸张了,其实就是实现基于Data Access Application Block的DAL基类和约束 首先Repository部分没什么好描述的,如果有不了解的可以直接百度或者谷歌相关内容,直接上具体代码 注意此部分没有写批量查询的方法(比如FindAll,这跟后面的基类设定有关) /// <summary> /// DataAccess Repository /// </summary> /// <typeparam name="T1">

Enterprise Library - Data Access Application Block 6.0.1304

Enterprise Library - Data Access Application Block 6.0.1304 企业库,数据访问应用程序块 6.0.1304 企业库的数据访问应用程序块的任务简化了开发实现通用数据访问功能. 应用程序可以使用这个应用程序块在不同的情况下,例如读取数据显示,通过应用程序层传递数据,提交更改的数据的数据库系统. 安装企业库,数据访问应用程序块,运行以下命令 包管理器控制台 PM> Install-Package EnterpriseLibrary.Data h

Visual C++ 编译器自动假定带 .C 扩展名的文件是 C 文件而不是 C++ 文件,并且拒绝 C++ 语法和关键字(c语言只能在大括号最前面申明变量)

今天在编译OpenGL红宝书附带源码中的light.c文件时遇到一个诡异的问题: 如图light .c,在不做任何修改的情况编译OK.然而只要在某些地方写了可执行代码,则会无法通过编译器编译! (这几行代码如果写在main函数里的第一句则OK) 我用的VS08.我把该文件发给其他朋友(用的VS10),同样也是这样的问题. 然而,我把文件名改成light.cpp后,问题解决了. 现在的问题是,代码文件按的后缀背后,会如何影响编辑器的编译呢? 可以做一个简单的测试: [cpp] view plain

自动更新开奖数据的excel文件,供大家下载

自动更新开奖数据的excel文件,供大家下载 2010-03-14 20:22 228492人阅读打印来源:乐彩网 作者:eren 很多人拥有自制excel电子表格,常要更新最基本的开奖信息.如有多期未更新,则费时更多.乐彩网为大家提供八种彩票的自动更新文件,供下载.您只需点击更新按钮,就能得到最及时全面的开奖信息,省时省力. 2011年10月12日修改说明:已更新全部开奖数据.福彩3Dexcel文件中,因描述更新范围的高度小了,导致更新后,最下面内容会右移.如此文件单独存在,请直接下载.如已将

C# 程序自动批量生成 google maps 的KML文件

原文:C# 程序自动批量生成 google maps 的KML文件 google maps 的 KML 文件可以用于静态的地图标注,在某些应用中,我们手上往往有成百上千个地址,我们需要把这些地址和描述批量标注到 google maps 上去,如果手工来做,太耗时间,在这里我写了一个程序批量来生成这个 KML 文件. 首先看一下 KML 文件的格式: <?xml version="1.0" encoding="UTF-8"?> <kml xmlns=

Linux FTP自动登陆下载备份,上传文件脚本

使用远程的服务器,对另外一台远程的服务器进行FTP操作,速度要比本地机器操作快很多. 之前写过一篇关于FTP如何手工的在Linux进行远程操作, 今天找到一个自动批量的脚本,感觉很好.满足了我的需要. 我的A网站在香港 我的B服务器Linux的在国内.这样就可以把A网站自动备份到B服务器了. 希望本篇博客能给需要的同学一些帮助. #####从ftp服务器上的/home/data 到 本地的/home/databackup#### #!/bin/bash ftp -n<<! open 192.1