1,简介

     从2.2版本开始,Catel使用了一个自定义的日志系统,这种方式,针对log4net的引用可以被移除,做这个修改主要是为了不强迫用户使用log4net,同时,log4net看起来很长时间不更新了,其他的日志系统如NLog看起来在增长,新的日志系统将允许许多基础的日志,这样,日志将将非常简单,并且如果他需要,真正的日志将被用户执行。

1.1 Log和ILog

     所有的日志将通过ILog接口。这个接口被自动的注册到Catel中的所有对象上作为Log字段,ILog接口仅仅有一个实现,每个对象能够调用Log自动的方法来记录任何信息。

     在Catel中,仅仅有一个类继承与ILog接口,那就是Log类,这个类确保了日志消息能够正确的格式化,并且在消息写入日志的时候会触发LogMessage事件。

    Cate内部创建了一个独立的Log类型,这样,开发者能够在许多日志中筛选它自己感兴趣的日志。

1.2 LogManager

 

  LogManager是一个管理类,它将为类型创建新的日志,但是也跟踪所有的日志和日志监听,为了返回一个指定类的日志,可以使用如下代码。

 

private static readonly ILog Log = LogManager.GetCurrentClassLogger();

 

1.3 用代码记录日志

使用代码记录日志,ILog接口实现一些基础的方法来记录信息和一些额外数据选项,有一些扩展方法可以记录异常,字符串格式,等等,下面是记录履历的例子:

Log.Warning("Customer '{0}' does not exist", customerId);

或者,如果异常有效,也能写入到日志中。

Log.Error(ex, "Failed to delete file '{0}'", fileName);

 

1.4 记录到output窗口或者console中

默认情况下,Catel并不增加任何监听,然后,它包含一个立即可用的实现将日志写入到output窗口或者console中,这个就是DebugLogListener,为了注册这个监听,可以使用如下代码。

#if DEBUG
LogManager.AddDebugListener();
#endif

在Catel3.8之前,使用的是LogManager.RegisterDebugListener()

 

1.5 重写全局的标记级别

从3.8开始可以针对所有的监听重写全区日志标记,如果要这样做,在LogManager上设置一直的值,例如,在所有的监听上强制显示调试履历,使用如下代码:

LogManager.IsDebugEnabled = true;

要重写设置override,设置值为空:

LogManager.IsDebugEnabled = null;

2,自定义监听

每一个监听都可以自定义来返回监听者感兴趣的日志,这样,监听者如果不感兴趣,可以不返回事件,例如,仅仅返回错误,创建一个新的监听如下:

var listener = new MyLogListener();
listener.IsDebugEnabled = false;
listener.IsInfoEnabled = false;
listener.IsWarningEnabled = false;
listener.IsErrorEnabled = true;

默认情况下,所有的日志都会被监听。

3,批量日志监听

批量日志监听是继承IBatchLogListener接口的类(大部分可能继承与BatchLogListenerBase),这个接口增加了一个Flushmethod方法,允许监听者被清理掉,进一步的是日志监听写了一个较慢的监听存储。这个将不会访问每一个源头,而只是批量处理。

3.1 Flushing所有的监听者

       当使用批量日志监听者时,当应用程序异常或者是退出时清理所有监听者时很重要的,这是因为有些重要的日志没有持久化到文件中的会丢失掉。

  要flushing所有的监听者需要使用如下代码

LogManager.FlushAll();

3.2 实现一个自定义的IBatchLogListener

当实现一个通用的批量日志监听者,常用的方式是继承BatchLogListenerBase类,这个有如下优点:

1,BatchLogListenerBase是线程安全的

2,BatchLogListenerBase每5秒钟会自动的flushes监听者。

你只需要实现WriteLog方法来决定持久化存储的入口,下面是例子:

public class FileLogListener : BatchLogListenerBase
{
private readonly string _filePath;
private readonly int _maxSizeInKiloBytes;
public FileLogListener(string filePath, int maxSizeInKiloBytes)
{
Argument.IsNotNullOrWhitespace(() => filePath);
_filePath = filePath;
_maxSizeInKiloBytes = maxSizeInKiloBytes;
}
protected override void WriteBatch(System.Collections.Generic.List<LogBatchEntry> batchEntries)
{
try
{
var fileInfo = new FileInfo(_filePath);
if (fileInfo.Exists && (fileInfo.Length / 1024 >= _maxSizeInKiloBytes))
{
CreateCopyOfCurrentLogFile(_filePath);
}
using (var fileStream = new FileStream(_filePath, FileMode.Append, FileAccess.Write, FileShare.Read))
{
using (var writer = new StreamWriter(fileStream))
{
foreach (var batchEntry in batchEntries)
{
var message = FormatLogEvent(batchEntry.Log, batchEntry.Message, batchEntry.LogEvent, batchEntry.ExtraData);
writer.WriteLine(message);
}
}
}
}
catch (Exception)
{
// Swallow
}
}
private void CreateCopyOfCurrentLogFile(string filePath)
{
for (int i = 1; i < 999; i++)
{
var possibleFilePath = string.Format("{0}.{1:000}", filePath, i);
if (!File.Exists(possibleFilePath))
{
File.Move(filePath, possibleFilePath);
}
}
}
}

5,集成第三方日志功能

     Catel中的日志默认并不写任何输出,这个给了开发者自由,可以使用任何最终的日志机制来处理它。例如Catel可以很容易的使用log4net或者NLOG来集成,通常,下面步骤需要来执行去集成日志。

1,创建自己的或者使用LogListenerBase创建一个自定义的ILogListener

2, 使用LogManager.AddListener将其注册进去。

  1. 5.1 集成Log4net方法

下面的例子为Log4net提供了一个ILogListener,但是有些额外的Log库可以被使用。

5.1.1 创建Listener

通过继承LogListenerBase来创建一个新的类:

 

public class Log4netListener : LogListenerBase
{
protected override void Debug(ILog log, string message, object extraData)
{
var finalLog = log4net.LogManager.GetLogger(log.TargetType);
finalLog.Debug(message);
} protected override void Info(ILog log, string message, object extraData)
{
var finalLog = log4net.LogManager.GetLogger(log.TargetType);
finalLog.Info(message);
} protected override void Warning(ILog log, string message, object extraData)
{
var finalLog = log4net.LogManager.GetLogger(log.TargetType);
finalLog.Warn(message);
} protected override void Error(ILog log, string message, object extraData)
{
var finalLog = log4net.LogManager.GetLogger(log.TargetType);
finalLog.Error(message);
}
}

 

5.1.2 注册一个监听

     最后同样重要的,去注册这个监听

LogManager.AddListener(new Log4netListener());

 

5.1.3 配置log4net

    注意,这仅仅是一个简单的配置,请查看log4net文档看所有的选项:

1,增加log4net的引用

2,增加[assembly: log4net.Config.XmlConfigurator(Watch = true)] 到AssemblyInfo.cs

3,在app.config中配置log4net的实际数据

 

 

5.2继承NLog方法

下面的例子为NLog提供了一个ILogListener,但是有些额外的Log库可以被使用。

5.2.1 创建Listener

通过继承LogListenerBase来创建一个新的类:

 

public class NLogListener : LogListenerBase
{
protected override void Debug(ILog log, string message, object extraData)
{
var finalLog = NLog.LogManager.GetLogger(log.TargetType.ToString());
finalLog.Debug(message);
} protected override void Info(ILog log, string message, object extraData)
{
var finalLog = NLog.LogManager.GetLogger(log.TargetType.ToString());
finalLog.Info(message);
} protected override void Warning(ILog log, string message, object extraData)
{
var finalLog = NLog.LogManager.GetLogger(log.TargetType.ToString());
finalLog.Warn(message);
} protected override void Error(ILog log, string message, object extraData)
{
var finalLog = NLog.LogManager.GetLogger(log.TargetType.ToString());
finalLog.Error(message);
}
}

5.1.2 注册一个监听

     最后同样重要的,去注册这个监听

LogManager.AddListener(new NLogListener());

 

 

 

 

6,将日志写入到磁盘

Catel也支持非常轻量监听来允许其他的外部库,创建一个监听,先创建一个新的类来继承与ILogListener,下一步,将其注册到LogManager中。

ILogListener针对每个LogEvent有一个独立的方法,但是也有一个共享的方法来调用,例如,如果debug信息被写入日志中,Write和Debug方法都会在ILogListener上被调用。

注意:要看批量写入磁盘的例子,可以看前面的日志更新

注意:Catel已经包含了一个FileLogListener,不需要重写这个类,它作为一个例子是很容易理解的。

 

6.1创建一个监听

可以写一个新的类继承于LogListenerBase。

public class FileLogListener : LogListenerBase
{
private readonly TextWriter _textWriter; public FileLogListener(string fileName)
{
Argument.IsNotNullOrWhitespace("fileName", fileName);
FileName = fileName; _textWriter = new StreamWriter(fileName, true);
} public string FileName { get; private set; } public override void Write(ILog log, string message, LogEvent logEvent)
{
_textWriter.WriteLine(message);
}
}

 

6.2 注册监听

最后同样重要的注册这个监听

LogManager.AddListener(new FileLogListener("<log_file_path>"));

 

 

7,通过配置文件来创建监听

 

从3.8开始,可以通过配置文件初始化LogListener,下面是一个例子

 

 

<configSections>
<sectionGroup name="catel">
<section name="logging" type="Catel.Logging.LoggingConfigurationSection, Catel.Core" />
</sectionGroup>
</configSections> <catel>
<logging>
<listeners>
<listener type="Catel.Logging.FileLogListener" FilePath="CatelLogging.txt" IgnoreCatelLogging="true" IsDebugEnabled="false" IsInfoEnabled="true" IsWarningEnabled="true" IsErrorEnabled="true"/>
</listeners>
</logging>
</catel>

上面Logging节点,需要保护一个没有限制数量的监听,每个监听中至少要提供类型的命名空间

<listener type="Catel.Logging.FileLogListener" />

其他的属性是自定义的,者意味着可以自定义每个加入进来的监听,下面是注册FileLogListener的配置

<listener type="Catel.Logging.FileLogListener" FilePath="CatelLogging.txt" IgnoreCatelLogging="true"
IsDebugEnabled="false" IsInfoEnabled="true" IsWarningEnabled="true" IsErrorEnabled="true"/>

ILogListenr属性(IsDebugEnabled, IsInfoEnabled, IsWarningEnabled and IsErrorEnabled)是对所有的监听有效的,其他的选项依赖于具体的监听类,这样可以提高运行时的灵活性。

 

 

8,Antor.Catel.Fody

       日志对应用程序是非常重要的,他在应用程序已经部署了很多客户端后,提供了应用程序运行的细节信息。这也是为什么日志是Catel框架中的第一个类。

     通常日志通过定义一个继承ILog类的事例来完成。

 

private static readonly ILog Log = LogManager.GetCurrentClassLogger();

 

然后通过如下方式来进行调用

Log.Info("This is a logging with a format '{0}'", "test");

    写日志定义是无聊和重复的,幸运的是Simon Cropp作为这个的一个解决方案出现了,称之为Antor.Catel.Fody,通过Anotar的实现,引用将被加入到解决方案中,然后在编译了程序集后会被移除,所有针对Log调用的类将会被Catel中实际的类所替换。

8.1 如何使用Antor

     使用Antor非常简单,只需要调用LogTo类的静态方法,如下所示:

LogTo.Info("This is a logging with a format '{0}'", "test");

   注意,再不需要Log字段了,它将被Anotar自动添加,除了它非常好用外,它执行效率非常高,GetCurrentClassLogger类使用反射来确定当前类,第一次(只会执行一次,因为是静态的)被使用的时候不太影响效率。Anotar通过如下的方式替换调用实现。

private static readonly ILog Log = LogManager.GetLogger(typeof(MyClass));

 

8.2 附加属性

8.2.1 不显示方法名和行号

     通过默认的Anotar记录时会显示方法名和行号

03:58:11:858 => [DEBUG] [AnotarDemo.Program] Method: 'Void Main(String[])'. Line: ~19. this is a test

如果你不想要这样输出,你可以增加如下特性:

[assembly: LogMinimalMessage]

那么输出文件会显示成如下信息

03:59:36:344 => [DEBUG] [AnotarDemo1.Program] this is a test

 

8.2.2 自动记录异常

    可以再一个方法中自动记录异常,要达到这个目的需要使用LogToDebugOnException特性来声明方法。

[LogToDebugOnException]
public static void ExceptionalMethod()
{
throw new Exception("This will be logged automatically");
}

这样声明后,则会打印如下履历。

04:01:48:331 => [DEBUG] [AnotarDemo.Program] Exception occurred in 'Void ExceptionalMethod()'.  | [Exception] System.Exception: This will be logged automatically
at AnotarDemo.Program.ExceptionalMethod() in c:\Source\AnotarDemo\AnotarDemo\Program.cs:line 27

Catel帮助手册-Catel.Core(6):日志管理的更多相关文章

  1. Catel帮助手册-Catel.Core:(1)参数检查

      我们检查方法是否正确,一般是返回对错,或者是是否抛出一个异常,大部分人不检查异常的正确性,那么这种错误在很深的堆栈中,很难查看. Catel与一般的检查方法不同,一般是使用   public vo ...

  2. ABP(现代ASP.NET样板开发框架)系列之8、ABP日志管理

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之8.ABP日志管理 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...

  3. SQL Server中的事务日志管理(3/9):事务日志,备份与恢复

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  4. ABP日志管理

    ABP日志管理 基于DDD的现代ASP.NET开发框架--ABP系列之8.ABP日志管理 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP ...

  5. [置顶] 使用sping AOP 操作日志管理

    记录后台操作人员的登陆.退出.进入了哪个界面.增加.删除.修改等操作 在数据库中建立一张SYSLOG表,使用Sping 的AOP实现日志管理,在Sping.xml中配置 <!-- Spring ...

  6. 八.利用springAMQP实现异步消息队列的日志管理

    经过前段时间的学习和铺垫,已经对spring amqp有了大概的了解.俗话说学以致用,今天就利用springAMQP来完成一个日志管理模块.大概的需求是这样的:系统中有很多地方需要记录操作日志,比如登 ...

  7. Spring Boot 入门(五):集成 AOP 进行日志管理

    本篇文章是接着 Spring boot 入门(四):集成 Shiro 实现登陆认证和权限管理写的,按照前面几篇博客的教程,可以搭建一个简单的项目,主要包含了 Pagehelper+MyBatis 分页 ...

  8. Docker日志管理--docker部署安装ELK (十一)--技术流ken

    Docker logs 对于一个运行的容器,Docker 会将日志发送到 容器的 标准输出设备(STDOUT)和标准错误设备(STDERR),STDOUT 和 STDERR 实际上就是容器的控制台终端 ...

  9. 使用Common.Logging+log4net规范日志管理【转载】

    使用Common.Logging+log4net规范日志管理   Common.Logging+(log4net/NLog/) common logging是一个通用日志接口,log4net是一个强大 ...

随机推荐

  1. 新安装ubuntu后几项配置

    新安的ubuntu13.04 为了编程方便 进行如下设置 安装右键terminal    sudo apt-get install nautilus-open-terminal 安装远程连接ssh   ...

  2. PHP扩展开发(5) - PHP常量的定义和读取

    1. 定义   //定义PHP常量REGISTER_STRINGL_CONSTANT("SIMPLE_VERSION", PHP_SIMPLE_VERSION, sizeof(PH ...

  3. Canvas -画图 关键字

    颜色.样式和阴影 属性 描述 fillStyle 设置或返回用于填充绘画的颜色.渐变或模式 strokeStyle 设置或返回用于笔触的颜色.渐变或模式 shadowColor 设置或返回用于阴影的颜 ...

  4. js console.log 打印 对像 数组 详解

    console.log是什么东西,其实就是一个打印js数组和对像的函数而已,就像是php的print_r,var_dump.console.log这个函数本身没什么好说的,这篇博客告诉大家怎么去用这个 ...

  5. Objective C内存管理之理解autorelease------面试题

    Objective C内存管理之理解autorelease   Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的A ...

  6. 热门usb无线网卡

    拓实 N910 N95 N82 N81 N89 都是3070的 拓实 N87 G618 是8187的硬功夫 216 310 217 218 300 315 335 350 370 380 510 53 ...

  7. Oracle12c中新建用户

    运行SQLPlus,以  sysdba打开 新建用户需要 create user C##[username] identified by [password] grant dba to C##[use ...

  8. Android入门学习:Android 系统框架及应用程序执行过程

    Android基础知识学习 新手上路,还请多多帮助.由于初学,博客内容难免有不正确的地方,还请各位多多指教,相互学习! 主要内容: 1.Android层次架构及主要功能 2.Android编程模型,程 ...

  9. HDOJ(HDU) 1678 Shopaholic

    Problem Description Lindsay is a shopaholic. Whenever there is a discount of the kind where you can ...

  10. 关于C/C++函数指针声明的理解

    [前言] 由于最近对函数指针的理解比较模糊,所有又重新学习了一把关于函数指针的知识,参考了很多书籍和网上的文章.现在本人进行一下分享和总结.本文的其实只是整理和总结别人现有的文章,作为备用参考文档. ...