• 新版网站前后台即将上线,2019年将致力于提高文章质量,加大原创力度,打造一个更加舒适的阅读体验!
  • 极客文库小编@勤劳的小蚂蚁,为您推荐每日资讯,欢迎关注!
  • 新版网站前后台即将上线,2019年将致力于提高文章质量,加大原创力度,打造一个更加舒适的阅读体验!
  • 如果有任何体验不佳的地方,欢迎向客服反馈!

Spring Boot 中使用 LogBack 配置

LogBack是一个日志框架,它与 Log4j 可以说是同出一源,都出自 CekiGülcü之手。( log4j的原型是早前由 CekiGülcü贡献给 Apache基金会的)下载地址 https://logback.qos.ch/download.html

LogBack、Slf4j 和 Log4j 之间的关系

Slf4j是 TheSimpleLoggingFacadeforJava的简称,是一个简单日志门面抽象框架,它本身只提供了日志 Facade API和一个简单的日志类实现,一般常配合 Log4jLogBackjava.util.logging使用。 Slf4j作为应用层的 Log 接入时,程序可以根据实际应用场景动态调整底层的日志实现框架 (Log4j/LogBack/JdkLog…)
LogBack和 Log4j都是开源日记工具库, LogBack是 Log4j的改良版本,比 Log4j拥有更多的特性,同时也带来很大性能提升。详细数据可参照下面地址: Reasonsto prefer logback over log4j
LogBack官方建议配合 Slf4j使用,这样可以灵活地替换底层日志框架。
TIPS:为了优化 log4j,以及更大性能的提升,Apache 基金会已经着手开发了 log4j2.0, 其中也借鉴和吸收了 logback的一些先进特性,目前 log4j2还处于 beta阶段

logback 取代 log4j 的理由

1、更快的实现: Logback的内核重写了,在一些关键执行路径上性能提升 10 倍以上。而且 logback不仅性能提升了,初始化内存加载也更小了。
2、非常充分的测试: Logback经过了几年,数不清小时的测试。 Logback的测试完全不同级别的。
3、 Logback-classic非常自然实现了 SLF4jLogback-classic实现了 SLF4j。在使用 SLF4j 中,你都感觉不到 logback-classic。而且因为 logback-classic非常自然地实现了 slf4j , 所 以切换到 log4j或者其他,非常容易,只需要提供成另一个 jar包就 OK,根本不需要去动那些通过 SLF4JAPI实现的代码。
4、非常充分的文档 官方网站有两百多页的文档。
5、自动重新加载配置文件,当配置文件修改了, Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在 JEE 环境里面。
6、 Lilith是 log事件的观察者,和 log4j的 chainsaw类似。而 lilith还能处理大数量的 log 数据 。
7、谨慎的模式和非常友好的恢复,在谨慎模式下,多个 FileAppender实例跑在多个 JVM 下,能 够安全地写道同一个日志文件。 RollingFileAppender会有些限制。 Logback的 FileAppender和它的子类包括 RollingFileAppender能够非常友好地从 I/O 异常中恢复。
8、配置文件可以处理不同的情况,开发人员经常需要判断不同的 Logback 配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,和来实现,这样一个配置文件就可以适应多个环境。
9、 Filters(过滤器)有些时候,需要诊断一个问题,需要打出日志。在 log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在 Logback,你可以继续 保持那个日志级别而除掉某种特殊情况,如 alice这个用户登录,她的日志将打在 DEBUG级别而其他用户可以继续打在 WARN级别。要实现这个功能只需加 4 行 XML配置。可以参考 MDCFIlter
10、 SiftingAppender(一个非常多功能的 Appender):它可以用来分割日志文件根据任何一个给定的运行参数。如, SiftingAppender能够区别日志事件跟进用户的 Session,然后每个用户会有一个日志文件。
11、自动压缩已经打出来的 logRollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。
12、堆栈树带有包版本: Logback在打出堆栈树日志时,会带上包的数据。
13、自动去除旧的日志文件:通过设置 TimeBasedRollingPolicy或者 SizeAndTimeBasedFNATPmaxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置 maxHistory12,那那些 log文件超过 12个月的都会被自动移除。

LogBack 的结构

LogBack 被分为 3 个组件, logback-core,logback-classic 和 logback-access
logback-core提供了 LogBack 的核心功能,是另外两个组件的基础。
logback-classic则实现了 Slf4j的 API,所以当想配合 Slf4j 使用时,需要将 logback-classic加入 classpath
logback-access是为了集成 Servlet环境而准备的,可提供 HTTP-access的日志接口。

配置详解

Github 代码

代码我已放到 Github ,导入 spring-boot-logback 项目
github spring-boot-logback

Maven 依赖

假如 maven 依赖中添加了 spring-boot-starter-logging
  1. <dependency>
  2.    <groupId>org.springframework.boot</groupId>
  3.    <artifactId>spring-boot-starter-logging</artifactId>
  4. </dependency>
那么,我们的 Spring Boot 应用将自动使用 logback 作为应用日志框架,Spring Boot 启动的时候,由 org.springframework.boot.logging.Logging-Application-Listener 根据情况初始化并使用。
但是呢,实际开发中我们不需要直接添加该依赖,你会发现 spring-boot-starter 其中包含了 spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback

配置文件

配置文件 logback-spring.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3.    <!-- 日志根目录-->
  4.    <springPropertyscope="context"name="LOG_HOME"source="logging.path"defaultValue="/data/logs/spring-boot-logback"/>
  5.    <!-- 日志级别 -->
  6.    <springPropertyscope="context"name="LOG_ROOT_LEVEL"source="logging.level.root"defaultValue="DEBUG"/>
  7.    <!--  标识这个"STDOUT" 将会添加到这个 logger -->
  8.    <springPropertyscope="context"name="STDOUT"source="log.stdout"defaultValue="STDOUT"/>
  9.    <!-- 日志文件名称-->
  10.    <propertyname="LOG_PREFIX"value="spring-boot-logback"/>
  11.    <!-- 日志文件编码-->
  12.    <propertyname="LOG_CHARSET"value="UTF-8"/>
  13.    <!-- 日志文件路径+日期-->
  14.    <propertyname="LOG_DIR"value="${LOG_HOME}/%d{yyyyMMdd}"/>
  15.    <!--对日志进行格式化-->
  16.    <propertyname="LOG_MSG"value="- | [%X{requestUUID}] | [%d{yyyyMMdd HH:mm:ss.SSS}] | [%level] | [${HOSTNAME}] | [%thread] | [%logger{36}] | --> %msg|%n "/>
  17.    <!--文件大小,默认 10MB-->
  18.    <propertyname="MAX_FILE_SIZE"value="50MB"/>
  19.    <!-- 配置日志的滚动时间 ,表示只保留最近 10 天的日志-->
  20.    <propertyname="MAX_HISTORY"value="10"/>
  21.    <!--输出到控制台-->
  22.    <appendername="STDOUT"class="ch.qos.logback.core.ConsoleAppender">
  23.        <!-- 输出的日志内容格式化-->
  24.        <layoutclass="ch.qos.logback.classic.PatternLayout">
  25.            <pattern>${LOG_MSG}</pattern>
  26.        </layout>
  27.    </appender>
  28.    <!--输出到文件-->
  29.    <appendername="0"class="ch.qos.logback.core.rolling.RollingFileAppender">
  30.    </appender>
  31.    <!-- 定义 ALL 日志的输出方式:-->
  32.    <appendername="FILE_ALL"class="ch.qos.logback.core.rolling.RollingFileAppender">
  33.        <!--日志文件路径,日志文件名称-->
  34.        <File>${LOG_HOME}/all_${LOG_PREFIX}.log</File>
  35.        <!-- 设置滚动策略,当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认 10MB -->
  36.        <rollingPolicyclass="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  37.            <!--日志文件路径,新的 ALL 日志文件名称,“ i ” 是个变量 -->
  38.            <FileNamePattern>${LOG_DIR}/all_${LOG_PREFIX}%i.log</FileNamePattern>
  39.            <!-- 配置日志的滚动时间 ,表示只保留最近 10 天的日志-->
  40.            <MaxHistory>${MAX_HISTORY}</MaxHistory>
  41.            <!--当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认 10MB-->
  42.            <timeBasedFileNamingAndTriggeringPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
  43.                <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
  44.            </timeBasedFileNamingAndTriggeringPolicy>
  45.        </rollingPolicy>
  46.        <!-- 输出的日志内容格式化-->
  47.        <layoutclass="ch.qos.logback.classic.PatternLayout">
  48.            <pattern>${LOG_MSG}</pattern>
  49.        </layout>
  50.    </appender>
  51.    <!-- 定义 ERROR 日志的输出方式:-->
  52.    <appendername="FILE_ERROR"class="ch.qos.logback.core.rolling.RollingFileAppender">
  53.        <!-- 下面为配置只输出 error 级别的日志 -->
  54.        <filterclass="ch.qos.logback.classic.filter.LevelFilter">
  55.            <level>ERROR</level>
  56.            <OnMismatch>DENY</OnMismatch>
  57.            <OnMatch>ACCEPT</OnMatch>
  58.        </filter>
  59.        <!--日志文件路径,日志文件名称-->
  60.        <File>${LOG_HOME}/err_${LOG_PREFIX}.log</File>
  61.        <!-- 设置滚动策略,当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认 10MB -->
  62.        <rollingPolicyclass="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  63.            <!--日志文件路径,新的 ERR 日志文件名称,“ i ” 是个变量 -->
  64.            <FileNamePattern>${LOG_DIR}/err_${LOG_PREFIX}%i.log</FileNamePattern>
  65.            <!-- 配置日志的滚动时间 ,表示只保留最近 10 天的日志-->
  66.            <MaxHistory>${MAX_HISTORY}</MaxHistory>
  67.            <!--当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认 10MB-->
  68.            <timeBasedFileNamingAndTriggeringPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
  69.                <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
  70.            </timeBasedFileNamingAndTriggeringPolicy>
  71.        </rollingPolicy>
  72.        <!-- 输出的日志内容格式化-->
  73.        <layoutclass="ch.qos.logback.classic.PatternLayout">
  74.            <Pattern>${LOG_MSG}</Pattern>
  75.        </layout>
  76.    </appender>
  77.    <!-- additivity 设为 false,则 logger 内容不附加至 root ,配置以配置包下的所有类的日志的打印,级别是 ERROR-->
  78.    <loggername="org.springframework"     level="ERROR"/>
  79.    <loggername="org.apache.commons"      level="ERROR"/>
  80.    <loggername="org.apache.zookeeper"    level="ERROR"  />
  81.    <loggername="com.alibaba.dubbo.monitor"level="ERROR"/>
  82.    <loggername="com.alibaba.dubbo.remoting"level="ERROR"/>
  83.    <!-- ${LOG_ROOT_LEVEL} 日志级别 -->
  84.    <rootlevel="${LOG_ROOT_LEVEL}">
  85.        <!-- 标识这个"${STDOUT}"将会添加到这个 logger -->
  86.        <appender-refref="${STDOUT}"/>
  87.        <!-- FILE_ALL 日志输出添加到 logger -->
  88.        <appender-refref="FILE_ALL"/>
  89.        <!-- FILE_ERROR 日志输出添加到 logger -->
  90.        <appender-refref="FILE_ERROR"/>
  91.    </root>
  92. </configuration>
配置文件 application.properties
  1. #日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为 WARN,则低于 WARN 的信息都不会输出
  2. logging.level.root=trace
  3. logging.path=/data/logs/spring-boot-logback

节点介绍

这里参考,嘟嘟独立博客,和 Albin 的文章
Spring Boot 干货系列:(七)默认日志 logback 配置解析
logback 节点配置详解
日志会每天新建一个文件夹,日文文件配置的每 50 兆,一个文本文件,超过新写入一个
  1. 文件夹:20171031
  2. 文件夹内容:all_spring-boot-logback0.log
  3. 文件夹内容:all_spring-boot-logback1.log
  4. 文件夹内容:all_spring-boot-logback2.log
  5. 文件夹内容:err_spring-boot-logback0.log

MDC requestUUID

一种多线程下日志管理实践方式
logback MDC(Mapped Diagnostic Context)与分布式系统的跟踪系统
Slf4j MDC 使用和 基于 Logback 的实现分析
MDC 介绍 — 一种多线程下日志管理实践方式
  MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。某些应用程序采用多线程的方式来处理多个用户的请求。在一个用户的使用过程中,可能有多个不同的线程来进行处理。典型的例子是 Web 应用服务器。当用户访问某个页面时,应用服务器可能会创建一个新的线程来处理该请求,也可能从线程池中复用已有的线程。在一个用户的会话存续期间,可能有多个线程处理过该用户的请求。这使得比较难以区分不同用户所对应的日志。当需要追踪某个用户在系统中的相关日志记录时,就会变得很麻烦。
一种解决的办法是采用自定义的日志格式,把用户的信息采用某种方式编码在日志记录中。这种方式的问题在于要求在每个使用日志记录器的类中,都可以访问到用户相关的信息。这样才可能在记录日志时使用。这样的条件通常是比较难以满足的。MDC 的作用是解决这个问题。
  MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。
自定义拦截器 logback requestUUID
  1. /**
  2. * 描述: 自定义拦截器 logback requestUUID
  3. *
  4. * @author yanpenglei
  5. * @create 2017-10-30 16:15
  6. **/
  7. publicclassControllerInterceptorextendsHandlerInterceptorAdapter{
  8.    privateLogger LOGGER =LoggerFactory.getLogger(ControllerInterceptor.class);
  9.    //在请求处理之前回调方法
  10.    @Override
  11.    publicboolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{
  12.        String requestUUID = MDC.get("requestUUID");
  13.        if(requestUUID ==null||"".equals(requestUUID)){
  14.            String uuid = UUID.randomUUID().toString();
  15.            uuid = uuid.replaceAll("-","").toUpperCase();
  16.            MDC.put("requestUUID", uuid);
  17.            LOGGER.info("ControllerInterceptor preHandle 在请求处理之前生成 logback requestUUID:{}", uuid);
  18.        }
  19.        returntrue;// 只有返回 true 才会继续向下执行,返回 false 取消当前请求
  20.    }
  21.    //请求处理之后回调方法
  22.    @Override
  23.    publicvoid postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView)throwsException{
  24.        /* 线程结束后需要清除,否则当前线程会一直占用这个 requestId 值 */
  25.        MDC.remove("requestUUID");
  26.        LOGGER.info("ControllerInterceptor postHandle 请求处理之后清除 logback MDC requestUUID");
  27.    }
  28.    //整个请求处理完毕回调方法
  29.    @Override
  30.    publicvoid afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throwsException{
  31.        /*整个请求线程结束后需要清除,否则当前线程会一直占用这个 requestId 值 */
  32.        MDC.clear();
  33.        LOGGER.info("ControllerInterceptor afterCompletion 整个请求处理完毕清除 logback MDC requestUUID");
  34.    }
  35. }
对日志进行格式化,时候用到
  1. <propertyname="LOG_MSG"value="- | [%X{requestUUID}] | [%d{yyyyMMdd HH:mm:ss.SSS}] | [%level] | [${HOSTNAME}] | [%thread] | [%logger{36}] | --> %msg|%n "/>
  1. /**
  2. * 描述:拦截器配置
  3. *
  4. * @author yanpenglei
  5. * @create 2017-10-30 16:54
  6. **/
  7. @Configuration
  8. publicclassMyWebMvcConfigurerextendsWebMvcConfigurerAdapter{
  9.    @Override
  10.    publicvoid addInterceptors(InterceptorRegistry registry){
  11.        /**
  12.         * 多个拦截器组成一个拦截器链
  13.         * addPathPatterns 用于添加拦截规则
  14.         * excludePathPatterns 用于排除拦截
  15.         */
  16.        registry.addInterceptor(newControllerInterceptor()).addPathPatterns("/**");
  17.        super.addInterceptors(registry);
  18.    }
  19. }

日志切面

  1. @Aspect
  2. @Component
  3. publicclassLogAspect{
  4.    privatestaticfinalLogger log =LoggerFactory.getLogger(LogAspect.class);
  5.    privatestaticfinalString dateFormat ="yyyy-MM-dd HH:mm:ss";
  6.    privatestaticfinalString STRING_START ="n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>n";
  7.    privatestaticfinalString STRING_END   ="n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<n";
  8.    @Pointcut("execution(* io.ymq.logback.controller..*(..))")
  9.    publicvoid serviceLog(){
  10.    }
  11.    @Around("serviceLog()")
  12.    publicObject around(ProceedingJoinPoint joinPoint){
  13.        try{
  14.            MethodSignature signature =(MethodSignature) joinPoint.getSignature();
  15.            Method method = signature.getMethod();
  16.            Class<?> targetClass = method.getDeclaringClass();
  17.            StringBuffer classAndMethod =newStringBuffer();
  18.            Log classAnnotation = targetClass.getAnnotation(Log.class);
  19.            Log methodAnnotation = method.getAnnotation(Log.class);
  20.            if(classAnnotation !=null){
  21.                if(classAnnotation.ignore()){
  22.                    return joinPoint.proceed();
  23.                }
  24.                classAndMethod.append(classAnnotation.value()).append("-");
  25.            }
  26.            if(methodAnnotation !=null){
  27.                if(methodAnnotation.ignore()){
  28.                    return joinPoint.proceed();
  29.                }
  30.                classAndMethod.append(methodAnnotation.value());
  31.            }
  32.            String target = targetClass.getName()+"#"+ method.getName();
  33.            Stringparams=JSONObject.toJSONStringWithDateFormat(joinPoint.getArgs(), dateFormat,SerializerFeature.WriteMapNullValue);
  34.            log.info(STRING_START +"{} 开始调用--> {} 参数:{}", classAndMethod.toString(), target,params);
  35.            long start =System.currentTimeMillis();
  36.            Object result = joinPoint.proceed();
  37.            long timeConsuming =System.currentTimeMillis()- start;
  38.            log.info("n{} 调用结束<-- {} 返回值:{} 耗时:{}ms"+ STRING_END, classAndMethod.toString(), target,JSONObject.toJSONStringWithDateFormat(result, dateFormat,SerializerFeature.WriteMapNullValue), timeConsuming);
  39.            return result;
  40.        }catch(Throwable throwable){
  41.            log.error(throwable.getMessage(), throwable);
  42.        }
  43.        returnnull;
  44.    }
  45. }

测试 logback

浏览器访问:http://127.0.0.1:8080/index/?content=”我是测试内容”
  1. @RestController
  2. @RequestMapping(value ="/index")
  3. publicclassIndexController{
  4.    privatefinalLogger LOGGER =LoggerFactory.getLogger(this.getClass());
  5.    /**
  6.     * http://127.0.0.1:8080/index/?content="我是测试内容"
  7.     *
  8.     * @param content
  9.     * @return
  10.     */
  11.    @Log("首页 IndexController")
  12.    @RequestMapping(value="", method=RequestMethod.GET)
  13.    publicString index(@RequestParamString content){
  14.        LocalDateTime localDateTime =LocalDateTime.now();
  15.        LOGGER.trace("请求参数:content:{}", content);
  16.        LOGGER.debug("请求参数:content:{}", content);
  17.        LOGGER.info("请求参数:content:{}", content);
  18.        LOGGER.warn("请求参数:content:{}", content);
  19.        LOGGER.error("请求参数:content:{}", content);
  20.        return localDateTime +",content:"+ content;
  21.    }
  22. }
前面的 07E94BA525CF4C97851E4B9E4ABB4890 就是通过 logback 的 MDC 做到的
  1. 首页IndexController开始调用--> io.ymq.logback.controller.IndexController#index 参数:[""我是测试内容""]|
  2. -|[07E94BA525CF4C97851E4B9E4ABB4890]|[2017110110:02:35.589]|[DEBUG]|[DESKTOP-VG43S0C]|[http-nio-8080-exec-1]|[i.y.l.controller.IndexController]|-->请求参数:content:"我是测试内容"|
  3. -|[07E94BA525CF4C97851E4B9E4ABB4890]|[2017110110:02:35.589]|[INFO]|[DESKTOP-VG43S0C]|[http-nio-8080-exec-1]|[i.y.l.controller.IndexController]|-->请求参数:content:"我是测试内容"|
  4. -|[07E94BA525CF4C97851E4B9E4ABB4890]|[2017110110:02:35.589]|[WARN]|[DESKTOP-VG43S0C]|[http-nio-8080-exec-1]|[i.y.l.controller.IndexController]|-->请求参数:content:"我是测试内容"|
  5. -|[07E94BA525CF4C97851E4B9E4ABB4890]|[2017110110:02:35.590]|[ERROR]|[DESKTOP-VG43S0C]|[http-nio-8080-exec-1]|[i.y.l.controller.IndexController]|-->请求参数:content:"我是测试内容"|
  6. -|[07E94BA525CF4C97851E4B9E4ABB4890]|[2017110110:02:35.606]|[INFO]|[DESKTOP-VG43S0C]|[http-nio-8080-exec-1]|[i.y.logback.config.commons.LogAspect]|-->
  7. 首页IndexController调用结束<-- io.ymq.logback.controller.IndexController#index 返回值:"2017-11-01T10:02:35.589,content:"我是测试内容"" 耗时:23ms
从上图可以看到,日志输出内容元素具体如下:
requestUUID:一次请求是唯一的
时间日期:精确到毫秒
日志级别:ERROR,WARN,INFO,DEBUGorTRACE
主机名:
进程ID
类路径:
分隔符:-->标识实际日志的开始
日志内容:
日志切面的响应:
  1. 首页IndexController开始调用--> io.ymq.logback.controller.IndexController#index 参数:[""我是测试内容""]|
  2. 首页IndexController调用结束<-- io.ymq.logback.controller.IndexController#index 返回值:"2017-11-01T10:02:35.589,content:"我是测试内容"" 耗时:23ms
代码我已放到 Github ,导入 spring-boot-logback 项目
github spring-boot-logback
slf4j-logback 日志以 json 格式导入 ELK

Contact

  • 作者:鹏磊
  • 出处:http://www.ymq.io
  • Email:admin@souyunku.com
  • GitHub:https://github.com/souyunku
  • Segment Fault:http://sf.gg/blog/souyunku
  • 版权归作者所有,转载请注明出处
  • Wechat:关注公众号,搜云库,分享技术,分享生活

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Spring Boot 中使用 LogBack 配置
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

欢迎 注册账号 登录 发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00