Logback的一项新颖功能是SiftingAppender ( JavaDoc )。 简而言之,它是一个代理附加器,它为给定运行时属性的每个唯一值创建一个子附加器。 通常,此属性来自MDC 。 这是基于上面链接的官方文档的示例:

<?xml version="1.0" encoding="UTF-8"?>
<configuration><appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender"><discriminator><key>userid</key><defaultValue>unknown</defaultValue></discriminator><sift><appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender"><file>user-${userid}.log</file><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%d{HH:mm:ss:SSS} | %-5level | %thread | %logger{20} | %msg%n%rEx</pattern></layout></appender></sift></appender><root level="ALL"><appender-ref ref="SIFT" /></root>
</configuration>

注意, <file>属性是使用${userid}属性进行参数化的。 这个财产来自哪里? 它必须放在MDC中。 例如,在使用Spring Security的Web应用程序中,我倾向于在SecurityContextHolder的帮助下使用servlet过滤器:

import javax.servlet._
import org.slf4j.MDC
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetailsclass UserIdFilter extends Filter
{def init(filterConfig: FilterConfig) {}def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {val userid = Option(SecurityContextHolder.getContext.getAuthentication).collect{case u: UserDetails => u.getUsername}MDC.put("userid", userid.orNull)try {chain.doFilter(request, response)} finally {MDC.remove("userid")}}def destroy() {}
}

只要确保在Spring Security过滤器之后应用此过滤器即可。 但这不是重点。 文件名中${userid}占位符的存在会导致筛选追加程序为该属性的每个不同值(因此:不同的用户名)创建一个子追加程序。 如果未设置MDC属性,以这种配置运行Web应用程序将快速创建多个日志文件,例如user-alice.loguser-bob.loguser-unknown.log user-bob.log 。 另一个用例是使用线程名称而不是MDC属性。 不幸的是,它不是内置的,但是可以使用自定义Discriminator而不是默认的MDCBasedDiscriminator轻松插入:

public class ThreadNameBasedDiscriminator implements Discriminator<ILoggingEvent> {private static final String KEY = "threadName";private boolean started;@Overridepublic String getDiscriminatingValue(ILoggingEvent iLoggingEvent) {return Thread.currentThread().getName();}@Overridepublic String getKey() {return KEY;}public void start() {started = true;}public void stop() {started = false;}public boolean isStarted() {return started;}
}

现在,我们必须指示logback.xml使用我们的自定义标识符:

<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender"><discriminator class="com.blogspot.nurkiewicz.ThreadNameBasedDiscriminator"/><sift><appender class="ch.qos.logback.core.FileAppender"><file>app-${threadName}.log</file><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%d{HH:mm:ss:SSS} | %-5level | %logger{20} | %msg%n%rEx</pattern></layout></appender></sift>
</appender>

请注意,我们不再将%thread放入PatternLayout –不必要,因为线程名是日志文件名的一部分:

  • app-main.log
  • app-http-nio-8080-exec-1.log
  • app-taskScheduler-1
  • app-ForkJoinPool-1-worker-1.log
  • ……依此类推

对于服务器应用程序,这可能不是最方便的设置,但是在台式机上,如EDT ,IO线程等专注线程数量有限,这可能是一个重要的选择。

参考: SiftingAppender:在Java和社区博客中,我们的JCG合作伙伴 Tomasz Nurkiewicz将不同的线程记录到不同的日志文件中 。

翻译自: https://www.javacodegeeks.com/2013/04/siftingappender-logging-different-threads-to-different-log-files.html

SiftingAppender:将不同的线程记录到不同的日志文件中相关推荐

  1. jstack Dump日志文件中的线程状态

    jstack Dump 日志文件中的线程状态 dump 文件里,值得关注的线程状态有: 死锁,Deadlock(重点关注)  执行中,Runnable 等待资源,Waiting on conditio ...

  2. slf4j没有在linux中生成日志,slf4j日志记录问题 - 未生成日志文件

    我正在使用slf4j通过java实用程序日志记录.我试图放置logging.properties文件,以便它会被我的web应用程序拾取.以下是我的logging.properties文件怎么样子:sl ...

  3. gin 【日志记录】每天一个日志文件

    定义自己的logger package myloggerimport ("errors""fmt""os""sync"& ...

  4. linux awk 时间范围,如何用awk从日志文件中找到时间范围的记录

    日志格式如下 2013/08/16    01:10:11.111    E12345678900-0    6513    123    0    IN    OK()    0    0    0 ...

  5. 记录 || Python | 提取xml/tmx文件中的文本内容

    # -*- coding:utf-8 -*- import codecs import xml.etree.ElementTree as ET import sysdefaultencoding = ...

  6. Java读取Excel文件数据并将记录写入到新的文件中--POI技术实现

    1. apache poi包里有4个主要的类: Workbook----工作表,通过WorkbookFactory的create(FileInputStream fis)方法获取, Sheet---- ...

  7. 在执行批处理时将执行错误的语句记录下来并写到日志文件中去

     public static void executesqls(List<String> sqlList) throws IOException{//改      Connection ...

  8. python代码执行过程记录_详解python程序中记录日志的方法

    日志可以用来记录应用程序的状态.错误和信息消息,也经常作为调试程序的工具.它的重要性就不多说了,直接进入正题. python提供了一个标准的日志接口,就是logging模块.日志级别有DEBUG.IN ...

  9. Python的open函数文件读写线程不安全,logging模型文件读写线程安全!

    工作中遇到的问题:如何在多线程的程序中同时记录日志? 最初图省事,使用了最原始的open函数来写日志,因为开始使用的写文件模式的是追加('a'),发现并没有线程不安全的现象,各个线程的的日志信息都写入 ...

最新文章

  1. Struts2 中#、@、%和$符号的用途
  2. Linux state 方式 安装nginx 服务
  3. 【ZooKeeper Notes 28】ZooKeeper典型应用场景一览
  4. java自动投票代码,Java 投票(自动添一)
  5. “视网膜”重装来袭 AI技术为视频业务场景赋能
  6. [CareerCup][Google Interview] Find kth number in a BST
  7. 移植SlidingMenu Android library,和安装example出现的问题解决
  8. NERO9注册机使用
  9. linux怎么设置raid,如何在Linux中配置RAID-教程
  10. fatal: unsafe repository is owned by someone else 的解决方法
  11. Matlab c2d离散用法
  12. 高通平台修改msm8916_defconfig
  13. 大数据时代,我们需要“被遗忘权”(转)
  14. 表达式和语句的简单理解
  15. vue入门笔记(三)
  16. 大华摄像头的踩坑之路
  17. 好文转载—程序员的禅修之路
  18. 电脑知识:笔记本电脑边充电边用,对电池有损害吗?
  19. Handlebars的使用方法及技巧
  20. 使用Docker安装HomeAssistant

热门文章

  1. ajax调用后台java类_ajax调用java后台方法是什么
  2. java中的native关键字有什么作用?(java本地方法)
  3. Spring boot(十二):Spring boot 如何测试、打包、部署
  4. java oca_OCA第2部分中的Java难题
  5. 在Spring中使用多个动态缓存
  6. chrome gwt1.7_快速提示:使用Chrome开发工具调试GWT应用程序
  7. 简单工厂抽象工厂工厂方法_让工厂美丽
  8. vertx rest 跨域_在基于简单Vertx Rest的应用程序上为REST资源设置基本响应HTTP标头...
  9. Java 8 Stream中间操作(方法)示例
  10. java8 javafx_JavaFX技巧8:美丽深层