文档章节

如何开启Dubbo框架内部的日志?

Bieber
 Bieber
发布于 2015/03/25 13:49
字数 1633
阅读 525
收藏 7

欢迎加入DUBBO交流群:259566260

这里将对如何在自己的项目里面开启dubbo框架自己的日志,并对输出的日志进行控制。在讲这些之前,先看看dubbo在处理日志的时候是怎么做的?  

在dubbo框架内所有的日志输出都是通过 LoggerFactory这个静态工厂类来获得Logger的对象实体,并且抽离了一个LoggerAdapter用于对接第三方日志框架,所以就有了JDKLoggerAdapter,Log4jLoggerAdapter,SLF4JLoggerAdapter等一些实现子类,分别对接了不同Log第三方实现。既然dubbo能够支持这么多log实现,那么这些实现在dubbo中优先级是在呢么样的呢?这里的优先级是只未配置指定的logger提供方的情况下,由dubbo框架自己选择。优先级如下:  
 

第三方日志框架 优先级
Log4j 最高(默认就用这个)
SLF4J 次高(上面没有采用这个)
Common Logging(jcl就是common logging) 次低(Log4j和SLF4J在项目中均没有就用这个)
JDK log 最低(最后的选择)

上面说的有和没有是指你的项目classpath下面有没有对应的jar包,如果有则表示支持对应的日志实现。下面粘贴出Dubbo选择日志提供方的代码:

// 查找常用的日志框架
    static {
        String logger = System.getProperty("dubbo.application.logger");
        if ("slf4j".equals(logger)) {
            setLoggerAdapter(new Slf4jLoggerAdapter());
        } else if ("jcl".equals(logger)) {
            setLoggerAdapter(new JclLoggerAdapter());
        } else if ("log4j".equals(logger)) {
            setLoggerAdapter(new Log4jLoggerAdapter());
        } else if ("jdk".equals(logger)) {
            setLoggerAdapter(new JdkLoggerAdapter());
        } else {
            try {
                setLoggerAdapter(new Log4jLoggerAdapter());
            } catch (Throwable e1) {
                try {
                    setLoggerAdapter(new Slf4jLoggerAdapter());
                } catch (Throwable e2) {
                    try {
                        setLoggerAdapter(new JclLoggerAdapter());
                    } catch (Throwable e3) {
                        setLoggerAdapter(new JdkLoggerAdapter());
                    }
                }
            }
        }
    }



  上面这段静态块是在LoggerFactory里面,说明只要LoggerFactory类一加载就会去选择对应的日志提供方。大家可能会发现对日志的提供方其实是可以通过配置来指定的,因为静态块一开始是从当前jvm环境中获取dubbo.application.logger,这个参数是同java -Ddubbo.application.logger=xxxx去指定的,如果是放在容器里面,就需要配置在容器启动的jvm参数里面。上面介绍了dubbo中日志相关的实现。下面讲讲在项目总怎么来让dubbo能够在项目里面输出日志。  
一、你项目当前使用的是Log4j来提供日志输出  
恭喜你,你不用做过多的处理就可以开启dubbo的日志,因为dubbo默认就是使用log4j。你唯一需要做的就是配置一个name是"com.alibaba.dubbo"的logger就可以了,然后关联到对应的appender。如下:  

<appender name="dubboAppender" class="org.apache.log4j.DailyRollingFileAppender"> 
        <param name="File" value="E:/dubbo.log" />  
        <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />  
        <layout class="org.apache.log4j.PatternLayout"> 
         <param name="ConversionPattern"
            value="[%d{MMdd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n" /> 
        </layout>  
</appender> 
<logger name="com.alibaba.dubbo" additivity="false"> 
        <priority value ="info"/>  
        <appender-ref ref="dubboAppender" />  
</logger>



二、你的项目当前使用的是非Log4j来提供日志输出 这种情况,默认是看不到dubbo的日志输出的,除非出现异常,被你当前系统的日志框架拦截住了。我这里就拿当前使用最多的日志框架logback来做示例。我们知道logback天生和slf4j进行了集成,所以要在项目里面使用logback,调用slf4j暴露的接口就可以。所以要把dubbo的日志输出切换到logback,也就变成了切换到slf4j了。一下列举出几种情况来切换。  
1)通过设置jvm启动参数来指定slf4j  
这个方式最简单,但是也很粗暴,因为你需要在jvm启动参数上动手脚,这样导致对于项目部署来说不是方便。  
2)当前项目只依赖slf4j和logback的包,并没有依赖log4j的包  
这个就需要严格确定,不能存在log4j的相关接口的包,这个排查起来可能比较痛苦。如果使用maven那就更痛苦了,因为你可能会间接的依赖log4j的包,更可恶的就是有些jar包把log4j的接口直接打到它自己的包里面,这种“捆绑销售”让我们很为难。如果排查清楚了,确定没有log4j,那么这是最好了。  
3)编程方式来指定slf4j  
这种方式貌似比第一种更粗暴,但是如果遇到了那种"捆绑销售"的现象,我们还能怎么办呢?这里的编程方式是怎么来实现的呢?我们从上面知道dubbo在选择日志提供方的时候是在static块里面,那么就说明是在加载LoggerFactory的时候去选择的。首先他是会检查jvm环境中是否配置了"dubbo.application.logger"参数,如果配置了则使用指定的日志提供方。那么这里的切入点就是要在加载LoggerFactory之前往jvm里面设置"dubbo.application.logger"参数,虽然这种方式和第一种类似,但是这种方式对于应用来说更加的灵活。要在加载LoggerFactory之前植入这个参数,就需要知道什么时候加载LoggerFactory这个类的,既然LoggerFactory是dubbo里面的,那就是启动dubbo框架之前设置肯定可以。由于大部分场景都是dubbo+spring的方式,所以这里就通过spring来做这件事情吧。我做了下面一件事情:  

public class CustomContextLoaderListener extends ContextLoaderListener {
    static{
        //设置dubbo使用slf4j来记录日志
        System.setProperty("dubbo.application.logger","slf4j");
    }
}



<listener>
    <listener-class> com.xxx.xxx.CustomContextLoaderListener</listener-class>
</listener>



我写了一个spring的ContextLoaderListener,里面只有一个静态块,设置"dubbo.application.logger"参数。由于dubbo+spring模式,dubbo框架是由spring框架来触发初始化的,所以在这里做手脚在适合不过了。那么这样我就可以通过编程的方式来配置输出日志的提供方了。  
下面贴出logback的日志配置:  

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <substitutionProperty name="LOG_HOME_DUBBO" value="C:/wls/dubbo"/>
    <timestamp key="byDate" datePattern="yyyyMMdd"/>
    <!-- dubbo log -->
    <appender name="dubboRolling" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <Encoding>UTF-8</Encoding>
        <file>${LOG_HOME_DUBBO}/MTP-DUBBO.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME_DUBBO}/DEMO-%d{yyyy-MM-dd}.%i-DUBBO.zip</fileNamePattern>
            <maxHistory>30</maxHistory>
            <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>100MB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <immediateFlush>true</immediateFlush>
        </encoder>
    </appender>
    <logger name="com.alibaba.dubbo" level="DEBUG">
        <appender-ref ref="dubboRolling"/>
    </logger>
</configuration>



对与使用其他日志提供方的,也可以采取logback方式类似的途径来达到效果。【想知道更多dubbo内容点这里  

© 著作权归作者所有

共有 人打赏支持
Bieber
粉丝 208
博文 36
码字总数 83312
作品 1
杭州
高级程序员
私信 提问
RPC-非阻塞通信下的同步API实现原理,以Dubbo为例

Netty在Java NIO领域基本算是独占鳌头,涉及到高性能网络通信,基本都会以Netty为底层通信框架,Dubbo 也不例外。以下将以Dubbo实现为例介绍其是如何在NIO非阻塞通信基础上实现同步通信的。 ...

echov
2018/01/14
2
0
Dubbo 的 Swagger 服务文档 - swagger-dubbo

swagger-dubbo支持dubbo以swagger方式展示文档和rest风格的HTTP模拟测试,主要应用场景有以下几点: 通过dubbo与swagger的集成,提供接口文档的阅读 开发人员可以用它来自测服务接口,也可以...

Sayi
2018/06/07
0
0
独家专访阿里高级技术专家北纬:Dubbo开源重启半年来的快意江湖

罗毅,花名北纬。这个名字,如果是混过天涯论坛的大龄网民应该都不陌生,北纬67度3分周公子(简称北纬)虐杀易烨卿MM的世纪大战至今还是天涯神贴 ,当时更是有看客赋诗形容:“目睹此帖,开怀...

阿里云头条
2018/05/15
0
0
高性能 RPC 框架 Dubbo 从入门到深入(详细原理介绍限时9.99)

课程简介 整体来说,一个公司业务系统的演进流程基本都是从单体应用到多应用。在单体应用时,不同业务模块相互调用直接在本地 JVM 进程内就可以完成,而变为多个应用时,相互之间进行通信的方...

阿里加多
2018/04/25
0
0
阿里Dubbo疯狂更新,关Spring Cloud什么事?

最近,开源社区发生了一件大事,那个全国 Java 开发者使用最广的开源服务框架 Dubbo 低调重启维护,并且 3 个月连续发布了 4 个维护版本。 我上次在写放弃Dubbo,选择最流行的Spring Cloud微...

纯洁的虫纸
2017/11/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

学习设计模式之路

https://java-design-patterns.com/patterns/ https://www.oodesign.com/ https://www.programering.com/a/MTNxAzMwATY.html https://design-patterns.readthedocs.io/zh_CN/latest/ https:/......

晨猫
今天
1
0
JDK1.8 jar包说明

JDK 1.8 lib:access-bridge-64.jarcharsets.jarcldrdata.jardeploy.jardnsns.jarjaccess.jarjavawa.jarjce.jarjfr.jarjfxrt.jarjfxswt.jarjsse.jarlocaledata.jar......

冷基
今天
1
0
判断用户的icloud是否开启【Swift4.2】

使用icloudkit存储用户私人数据时,必须判断用户的icloud是否开启【Swift4.2】 func isICloudContainerAvailable()-> Bool { if FileManager.default.ubiquityIdentityToken != ni......

叶落花开
今天
1
0
今天的学习

1、执行git add *命令就把改动提交到了暂存区,执行git pull命令将远程仓库的数据拉到当前分支并合并,执行git checkout [branch-name]切换分支 2、执行git commit -m '说明' 命令就把改动提...

墨冥
昨天
0
0
Android4.4 及以下TextView,Button等控件使用矢量图报错

1 问题描述 最近项目开发中,图标资源我尽量使用了矢量图,然而配置了基本的兼容设置,程序在低版本中运行还是出现了问题。 xml布局文件中,在TextView中使用矢量图,比如android:drawableS...

newtrek
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部