• 如果您想对本站表示支持,请随手点击一下广告即可~
  • 本站致力于提供原创、优秀的技术文章~
  • 有任何疑问或建议 均可以在站点右侧栏处 通过各种方式联系站长哦~
  • Logback动态日志配置教程

    JAVA EXP 347阅读 0评论

    By EXP 2014-09-12



    参考资料

    Logback中文手册 下载

    1. 前言

    在阅读本文前,先保证你熟悉logback的配置方式,能够实现logback的基本日志配置,并明白你的日志是如何通过你的代码找到应该输出到哪个日志文件的。

    否则,请先自学上述内容。因为本文不会提及这些东西,若无上述基础,下面的内容是看不懂的

    2. 问题背景

    无论是 log4j 还是 logback,通常配置日志的顺序都是:
      (1)在代码中指定唯一的logger名称;
      (2)在日志配置文件通过<logger>关联该名称。
      (3)在日志配置文件中把<logger>的日志输出到<append>。

    换而言之,logger的名称在开发的时候就需要固定了,后期无论增改logger都需要重新编译代码使之生效。

    而实际上,经常有多线程(多用户、或多会话等)环境,需要分别打印自身日志到不同的日志文件

    而多线程是无法预测数量的,即logger无法分别预设(起码在你未看过这篇文章前是这样)。因此往往的解决办法,要么固定多线程的数量和名字、要么全都打到同一份日志。

    这两种做法其实都不理想,其实可以通过利用MDC完美解决这个问题

    3. MDC介绍

    MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。某些应用程序采用多线程的方式来处理多个用户的请求。在一个用户的使用过程中,可能有多个不同的线程来进行处理。

    MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。

    4. 实战:应用MDC配置动态日志

    4.1. Logback配置:使用SiftingAppender包装你的Append

    在说明SiftingAppender之前,先看一个一般的Append配置:

    图1 简单的Append配置

    图1 简单的Append配置

    通过这个值配置,可以简单地做到把日志输出到【固定名称】的日志文件your_log_name.log中。

    而要通过MDC动态输出日志到【非固定名称】的日志文件,则需要使用SiftingAppender包装你的Append:

    图2 SiftingAppender包装的Append

    图2 SiftingAppender包装的Append

    绿框中的其实就是原本的Append部分,区别在于固定名称your_log_name被替换成变量{YOUR_MDC_KEY}。 实则上MDC就是一个Hash表,在打印日志前,它会在Hash表中找到真正的日志名称,然后替换掉{YOUR_MDC_KEY},从而实现日志动态化。

    需要注意的是,SiftingAppender中定义了MDC的参数,其中<Key>值虽然可自定义,但是由于用于代码中的MDC关联,因此确定后就不能再修改,否则你需要重新编译代码。

    而<DefaultValue>是当logback在MDC找不到键所对应的值时,就会把日志输出到OTHER.log的意思。除非故意把<Key>配成与代码定义的值不一致,否则一般不会出现此情况。

    完整的日志配置如下:


    4.2. 代码预设 – MDC的简单封装

    要在代码中利用MDC打印日志,首先你需要用slf4j定义一个Logger,Logger的名称保证与logback配置文件的<logger>同名:

    然后在每次打印日志的时候,都需要先预设MDC环境:

    于是根据上一节的MDC日志配置,就可以自动生成两份日志文件 your_log_name_a.log 和 your_log_name_b.log ,并且在 your_log_name_a.log 中打印了 This is A,在 your_log_name_b.log 中打印了 This is B。

    然而这种做是很麻烦的,因此建议做一个简单的封装类:

    尔后,在实际的应用中,就可以通过在项目的配置文件去配置 your_log_name_X ,用代码加载后再put到MDC中,实现日志的动态化。


    4.3. MDC使用的总结

    针对前两节内容,要使用logback打印动态日志,无非以下几个步骤:
      (1)先用SiftingAppender包装好既有的Append,同时修改日志名称为MDC键名称。
      (2)在代码中定义一个专用于打印动态日志的Logger,每次用它打印日志器前先调用 MDC.put(mdc_key, log_name_X) 预设环境,其中 log_name_X 配置在项目的配置文件中。
      (3)最后就可以用一个Logger打印N份日志了。

    5. MDC的多线程安全性

    由于MDC所提供的put方法预设环境是静态的,可能有人会担心其多线程的安全性问题。这个问题无需考虑,MDC明确是多线程安全的

    MDC中的put方法其实就是将键值对放入一个Hashtable对象中,然后赋值给当前线程的ThreadLocal.ThreadLocalMap对象,即threadLocals,这保证了各个线程的在MDC键值对的独立性。


    6. 完整的样例源码

    logvack动态日志-Java源码 下载

    解压后导入Eclipse即可(编码为UTF-8)。


    转载请注明:EXP 技术分享博客 » Logback动态日志配置教程

    喜欢 (1) 分享 (0)
    发表我的评论
    取消评论

    表情

    Hi,您需要填写昵称和邮箱!

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址