如何在logback.xml中自定义动态属性

原文地址:http://blog.jboost.cn/trick-logback-prop.html

当使用logback来记录Web应用的日志时,我们通过在logback.xml中配置appender来指定日志输出格式及输出文件路径,这在一台主机或一个文件系统上部署单个实例没有问题,但是如果部署多个实例(比如通过容器的方式),多个实例同时往同一文件写日志可能就会引起问题。这时可以将每个实例的日志文件加以区分,如IP或UUID,或两者结合的形式。这其实就涉及如何在logback.xml中自定义动态属性的问题。

可以有4种方式来实现logback.xml中获取自定义变量值:

  1. 通过设置环境变量或传递系统属性(比如在程序启动时通过-D传递)的方式,两者是可以直接在logback.xml中通过 ${变量名} 获取的。
  2. 自定义logback.xml的加载时机,在其加载前将需要设置的属性注入到logback的context中,这种方式相对复杂,本文不讨论。
  3. 通过实现PropertyDefiner接口来提供属性值设置
  4. 通过实现LoggerContextListener接口来设置属性值

第一种方式简单,但不能通过程序生成属性值,第二种方式稍显复杂,本文主要介绍后两种方式。

PropertyDefiner方式

首先定义一个类,实现PropertyDefiner接口,可以通过继承PropertyDefinerBase会更方便

import ch.qos.logback.core.PropertyDefinerBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
/***
 * 将本地IP拼接到日志文件名中,以区分不同实例,避免存储到同一位置时的覆盖冲突问题
 * @Author ronwxy
 * @Date 2019/8/20 16:17
 */
public class IPLogDefiner extends PropertyDefinerBase {

    private static final Logger LOG = LoggerFactory.getLogger(IPLogDefiner.class);

    private String getUniqName() {
        String localIp = null;
        try {
            localIp = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            LOG.error("fail to get ip...", e);
        }
        String uniqName = UUID.randomUUID().toString().replace("-", "");
        if (localIp != null) {
            uniqName = localIp + "-" + uniqName;
        }
        return uniqName;
    }

    @Override
    public String getPropertyValue() {
        return getUniqName();
    }
}

然后在logback.xml中,添加 <define> 配置,指定属性名(本例中为localIP)及获取属性值的实现类,这样就可以在配置中通过 ${localIP}来引用该属性值了。在实现方法 getPropertyValue 中返回你需要生成的值,本例中是返回 本地IP-UUID 的形式。

<configuration>
    <define name="localIP" class="cn.jboost.common.IPLogDefiner"/>
    <appender name="interfaceLogFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoding>UTF-8</encoding>
        <File>D:\\logs\\elk\\interface-${localIP}.log</File>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
# 省略了其它配置

LoggerContextListener方式

定义一个实现LoggerContextListener接口的类,在start方法中,将需要设置的属性设置到logback的Context中,

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.LifeCycle;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;

/***
 * 第二种实现方式
 * @Author ronwxy
 * @Date 2019/8/20 18:45
 */
public class LoggerStartupListener extends ContextAwareBase
    implements LoggerContextListener, LifeCycle {

    private boolean started = false;

    @Override
    public void start() {
        if (started) {
            return;
        }
        Context context = getContext();
        context.putProperty("localIP", getUniqName());
        started = true;
    }

    private String getUniqName() {
        String localIp = null;
        try {
            localIp = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            //LOG.error("fail to get ip...", e);
        }
        String uniqName = UUID.randomUUID().toString().replace("-", "");
        if (localIp != null) {
            uniqName = localIp + "-" + uniqName;
        }
        return uniqName;
    }
//省略了其它函数

然后在logback.xml中,配置如上监听器类,这样就可以通过 ${localIP} 获取到上面 context.putProperty("localIP", getUniqName()); 设置的值了。

<configuration>

    <!--<define name="localIP" class="com.cnbot.common.IPLogDefiner"/>-->
    <contextListener class="cn.jboost.common.LoggerStartupListener"/>
    <define name="localIP" class="com.cnbot.common.IPLogDefiner"/>
    <appender name="interfaceLogFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoding>UTF-8</encoding>
        <File>D:\\logs\\elk\\interface-${localIP}.log</File>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
# 省略了其它配置

这种方式能设置任意个数的属性值,比前一种方式灵活。

总结

在logback.xml中获取自定义属性值,主要是需要在加载前将对应的属性值进行设置,这样加载时才能有效获取。本文虽是自定义日志文件名称,但不局限于此,所有需要动态获取的变量都可以按这种方式实现。

如果觉得有帮助,请帮忙转发、推荐。欢迎关注我的微信公众号:jboost-ksxy
———————————————————————————————————————————————————————————————

原文地址:https://www.cnblogs.com/spec-dog/p/11386668.html

时间: 2024-08-29 10:34:23

如何在logback.xml中自定义动态属性的相关文章

如何在.net/MVC4中自定义页面验证的前端脚本

其实是很少发技术类文章的, 只是在最近的一次项目中,由于这个位置的技术短板导致折腾好几天,而网上搜的内容又都不直接说明,所以还是决定写出来给人参考一下, 可以帮助大家省点时间. 先来看一下需求: 很是草稿的图片请别介意.需求是这样,当选中图中的下拉菜单选项为第一个时,使用文字验证,当下拉菜单选为第二个选项时,使用数字验证. 这种需求其实比较普遍,很多流程化管理的页面都会有这种需求.比如在申请证件时候可选项是护照还是身份证的时候,对填入内容的验证规则可以是不一样的. 但微软自带的model绑定规则

如何在Fiddler Script中自定义修改请求参数

-更改RequestHeaders中的内容 //根据host判断 if(oSession.host=="www.baidu.com"){ oSession.RequestHeaders.Remove("User-Agent"); oSession.RequestHeaders.Add("User-Agent","Dalvik/2.1.0 (Linux; U; Android 9.0.1; onePlus666 Build/MOB31K)

Logback.xml 给变量指定默认值

随着通用日志组件转入 Slf4j,logback 也变成了默认的日志实现,像 log4j 一样,logback.xml 中也可以使用系统属性或环境变量,如 ${catalina.home}.在 log4j.properties 中,如果变量在系统属性和环境变量中找不到的话默认为 "" 空字符串,而到了 logback.xml 中如果某个变量找不到默认就是 "变量名_IS_UNDEFINED" 了,这样就比较奇怪了. 那如何在没有配置 catalina.home 系统

servlet和spring框架使用logback.xml的区别

之前用spring框架写web项目,在resources目录下配置的logback.xml文件如下: <configuration> <appender name="JEEOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEnco

在pom.xml中使用distributionManagement将项目打包上传到nexus私服

本文介绍 如何在pom.xml中使用distributionManagement将项目打包上传到nexus私服 1.pom.xml文件添加distributionManagement节点 <!-- 使用分发管理将本项目打成jar包,直接上传到指定服务器 --> <distributionManagement> <!--正式版本--> <repository> <!-- nexus服务器中用户名:在settings.xml中<server>的

Android开发如何在4.0及以上系统中自定义TitleBar

本文将通过一个实例讲解怎么实现在4.0及以上系统版本中实现自定义TitleBar,这只是我自己找到的一种方法; xml布局文件 activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="m

Android XML中引用自定义内部类view的四个why

今天碰到了在XML中应用以内部类形式定义的自定义view,结果遇到了一些坑.虽然通过看了一些前辈写的文章解决了这个问题,但是我看到的几篇都没有完整说清楚why,于是决定做这个总结. 使用自定义内部类view的规则 本文主要是总结why,所以先把XML布局文件中引用内部类的自定义view的做法摆出来,有四点: 自定义的类必须是静态类: 使用view作为XML文件中的tag,注意,v是小写字母,小写字母v,小写字母v: 添加class属性,注意,没有带android:命名空间的,表明该自定义view

如何在xml中设置textview不可见

可见(visible)XML文件:android:visibility="visible"Java代码:view.setVisibility(View.VISIBLE);不可见(invisible)XML文件:android:visibility="invisible"Java代码:view.setVisibility(View.INVISIBLE);隐藏(GONE)XML文件:android:visibility="gone"Java代码:vi

SpringBoot中logback.xml使用application.yml中属性

教你如何使用 springProfile 与 springProperty 让你的logback.xml 配置显得更有逼格,当别人还在苦苦挣扎弄logback-{profile}.xml的时候 你一个文件就搞定了- - springProfile 该 <springProfile> 标签允许我们更加灵活配置文件,可选地包含或排除配置部分.元素中的任何位置均支持轮廓部分.使用该name属性指定哪个配置文件接受配置.可以使用逗号分隔列表指定多个配置文件. <springProfile nam