在logback.xml中自定义动态属性的方法

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

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

  • 通过设置环境变量或传递系统属性(比如在程序启动时通过-D传递)的方式,两者是可以直接在logback.xml中通过 ${变量名} 获取的。
  • 自定义logback.xml的加载时机,在其加载前将需要设置的属性注入到logback的context中,这种方式相对复杂,本文不讨论。
  • 通过实现PropertyDefiner接口来提供属性值设置
  • 通过实现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中获取自定义属性值,主要是需要在加载前将对应的属性值进行设置,这样加载时才能有效获取。本文虽是自定义日志文件名称,但不局限于此,所有需要动态获取的变量都可以按这种方式实现。

(0)

相关推荐

  • logback的使用和logback.xml详解(小结)

    一.logback的介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch.它当前分为下面下个模块: logback-core:其它两个模块的基础模块 logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能 二.logba

  • 在logback.xml中自定义动态属性的方法

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

  • Python解析xml中dom元素的方法

    本文实例讲述了Python解析xml中dom元素的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: from xml.dom import minidom try:     xmlfile = open("path.xml", "a+")     #xmldoc = minidom.parse( sys.argv[1])     xmldoc = minidom.parse(xmlfile) except :     #updatelogger.

  • PHP往XML中添加节点的方法

    本文实例讲述了PHP往XML中添加节点的方法.分享给大家供大家参考.具体方法如下: 1. contacts.xml代码 复制代码 代码如下: <contact id="43956">      <personal>           <name>                <first>J</first>                <middle>J</middle>             

  • jquery遍历标签中自定义的属性方法

    在开发中我们有时会对html标签添加属性,如何遍历处理? <ul> <li name="li1" sortid="nav_1">aaaaaaa</li> <li name="li1" sortid="nav_2">bbbbbbb</li> <li name="li1" sortid="nav_3">cccccccc&

  • Android开发之在xml中设置自定义属性的方法

    xml中设置自定义属性 分三步: 1. 在项目中的values文件中创建attrs文件 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="QLoadingIndicatorView"> <attr name="indicatorId" format="integer"

  • 全面解析iOS应用中自定义UITableViewCell的方法

    有时候我们需要自己定义UITableViewCell的风格,其实就是向行中添加子视图.添加子视图的方法主要有两种:使用代码以及从.xib文件加载.当然后一种方法比较直观. 一.基本用法 我们这次要自定义一个Cell,使得它像QQ好友列表的一行一样:左边是一张图片,图片的右边是三行标签: 当然,我们不会搞得这么复杂,只是有点意思就行. 1.运行Xcode 4.2,新建一个Single View Application,名称为Custom Cell: 2.将图片资源导入到工程.为此,我找了14张50

  • 如何在Spring中自定义scope的方法示例

    大家对于 Spring 的 scope 应该都不会默认.所谓 scope,字面理解就是"作用域"."范围",如果一个 bean 的 scope 配置为 singleton,则从容器中获取 bean 返回的对象都是相同的:如果 scope 配置为prototype,则每次返回的对象都不同. 一般情况下,Spring 提供的 scope 都能满足日常应用的场景.但如果你的需求极其特殊,则本文所介绍自定义 scope 合适你. Spring 内置的 scope 默认时,所

  • .NET更新Xml中CDATA内容的方法实例

    假如 Xml 文件的内容如下: 1.XML 代码 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?><net_lover>  <sitename><![CDATA[<h2>.NET 开发</h2>]]></sitename>  <siteurl>http://www.jb51.net</siteurl></

  • smarty模板引擎中自定义函数的方法

    本文实例讲述了smarty 自定义函数方法,分享给大家供大家参考.具体如下: 本实例目的:输出 times 次 con的内容(输出4次hello world) 文件1: 复制代码 代码如下: <?php //创建smarty对象 require_once("./libs/Smarty.class.php"); $smarty = new Smarty(); //自定义一个函数 //说明:(1).$arr为一个数组:(2).tpl调用形式{test times="4&qu

  • Python中自定义函方法与参数具有默认值的函数

    目录 一.Python中自定义函数的方法 1自定义函数的语法 2自定义函数的实现 3自定义函数的调用 二.Python中参数具有默认值的函数 1参数是常量默认值的函数 2参数是常量默认值的函数 一.Python中自定义函数的方法 在Python编程中,可以使用已经定义好的函数,也可以自定义函数实现某些特殊的功能. 1 自定义函数的语法 在Python中,自定义函数的语法如下所示: def 函数名(参数):     函数体 其中,def是关键字:之后跟的是函数名,通过函数名来调用该函数:函数名之后

随机推荐