初探logback日志框架

初探logback日志框架

logback简介

Logback is intended as a successor to the popular log4j project. It was designed by Ceki Gülcü, log4j’s founder. It builds upon a decade of experience gained in designing industrial-strength logging systems. The resulting product, i.e. logback, is faster and has a smaller footprint than all existing logging systems, sometimes by a wide margin. Just as importantly, logback offers unique and rather useful features missing in other logging systems.

对比其他日志框架

1.logback属于slf4j阵营;log4j2属于common logging阵营。
2.Java中,logback和log4j2都是目前最流行的日志框架。
3.开发公司不同,log4j2是apache开发,而logback由qos开发。

执行流程

大体流程:创建LoggerFactory->创建Logger->过滤日志->根据日志级别输出日志->根据同异步处理日志
1.通过StaticLoggerBinder创建了一个单例的LoggerFactory,初始化时利用了双从检验锁的形式获得了一个单例的LoggerFactory。

 		if (INITIALIZATION_STATE == UNINITIALIZED) {
   
            synchronized (LoggerFactory.class) {
   
                if (INITIALIZATION_STATE == UNINITIALIZED) {
   
                    INITIALIZATION_STATE = ONGOING_INITIALIZATION;
                    performInitialization();
                }
            }
        }

2.利用获得的LoggerFactory创建了一个树状的Logger树,当然也会用缓存存一份来加快加载速度,缓存用了concurrentHashMap来保证线程安全。

		// if the desired logger does not exist, them create all the loggers
        // in between as well (if they don't already exist)
        String childName;
        while (true) {
   
            int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
            if (h == -1) {
   
                childName = name;
            } else {
   
                childName = name.substring(0, h);
            }
            // move i left of the last point
            i = h + 1;
            synchronized (logger) {
   
                childLogger = logger.getChildByName(childName);
                if (childLogger == null) {
   
                    childLogger = logger.createChildByName(childName);
                    loggerCache.put(childName, childLogger);
                    incSize();
                }
            }
            logger = childLogger;
            if (h == -1) {
   
                return childLogger;
            }

可以看到用了loggerCache作为缓存,真正加载日志树的时候也用了synchronized来保证线程安全。
真正创建日志树节点的在:

	Logger createChildByName(final String childName) {
   
        int i_index = LoggerNameUtil.getSeparatorIndexOf(childName, this.name.length() + 1);
        if (i_index != -1) {
   
            throw new IllegalArgumentException("For logger [" + this.name + "] child name [" + childName
                            + " passed as parameter, may not include '.' after index" + (this.name.length() + 1));
        }

        if (childrenList == null) {
   
            childrenList = new CopyOnWriteArrayList<Logger>();
        }
        Logger childLogger;
        childLogger = new Logger(childName, this, this.loggerContext);
        childrenList.add(childLogger);
        childLogger.effectiveLevelInt = this.effectiveLevelInt;
        return childLogger;
    }

可以看到初始化了一个个的日志树节点,但是节点却用到了CopyOnWriteArrayList来保证线程安全,而且这个方法只有一个地方在调用,调用的地方用了synchronized锁,理论上在这里使用CopyOnWriteArrayList是多余的,反而会增加开销。 但是,synchronized锁的是一个日志树的节点。

在真正调用logger.info/logger.debug…时,根据配置的TurboFilterChain和effectiveLevelInt来确定是否输出日志

	private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,
                    final Throwable t) {
   

        final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t);

        if (decision == FilterReply.NEUTRAL
  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值