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

news2024/11/17 16:49:00

原文地址: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接口来设置属性值

第一种方式简单,但不能通过程序生成属性值

需要在spring-boot启动类中加入设置环境变量的代码,如下:
在这里插入图片描述
修改logback.xml中的代码如下:

在这里插入图片描述

第二种方式稍显复杂,本文主要介绍后两种方式

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/375740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

K8S静态存储与动态存储工作流

静态存储 Kubernetes 同样将操作系统和 Docker 的 Volume 概念延续了下来&#xff0c;并且对其进一步细化。Kubernetes 将 Volume 分为持久化的 PersistentVolume 和非持久化的普通 Volume 两类。为了不与前面定义的 Volume 这个概念产生混淆&#xff0c;后面特指 Kubernetes …

Type and Value

Type and Value前言一、reflect.Type1.1 数据结构1.2 方法1.2.1 所有类型通用方法1.2.2 不同基础类型的专有方法二、reflect.Value总结参考资料前言 reflect.Type和reflect.Value是go 反射的两大基本类型&#xff0c;一个管变量的类型方面&#xff0c;一个管变量的值方面。 一…

PTA L1-058 6翻了(详解)

前言&#xff1a;内容包括&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; “666”是一种网络用语&#xff0c;大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”&#xff0c;意思是“6翻了”&#xff0…

vue源码分析-动态组件

前面花了两节的内容介绍了组件&#xff0c;从组件的原理讲到组件的应用&#xff0c;包括异步组件和函数式组件的实现和使用场景。众所周知&#xff0c;组件是贯穿整个Vue设计理念的东西&#xff0c;并且也是指导我们开发的核心思想&#xff0c;所以接下来的几篇文章&#xff0c…

LLaMA-META发布单卡就能跑的大模型

2023年2月25日&#xff0c;Meta使用2048张A100 GPU&#xff0c;花费21天训练的Transformer大模型LLaMA开源了。 1.4T tokenstakes approximately 21 days 以下是觉得论文中重要的一些要点 1&#xff09;相对较小的模型也可以获得不错的性能 研究者发现在给定计算能力限制的情…

【YOLO系列】YOLOv4论文超详细解读1(翻译 +学习笔记)

前言 经过上一期的开篇介绍&#xff0c;我们知道YOLO之父Redmon在twitter正式宣布退出cv界&#xff0c;大家都以为YOLO系列就此终结的时候&#xff0c;天空一声巨响&#xff0c;YOLOv4闪亮登场&#xff01;v4作者是AlexeyAB大神&#xff0c;虽然换人了&#xff0c;但论文中给出…

【BN层的作用】论文阅读 | How Does Batch Normalization Help Optimization?

前言&#xff1a;15年Google提出Batch Normalization&#xff0c;成为深度学习最成功的设计之一&#xff0c;18年MIT团队将原论文中提出的BN层的作用进行了一一反驳&#xff0c;重新揭示BN层的意义 2015年Google团队论文&#xff1a;【here】 2018年MIT团队论文&#xff1a;【h…

谷粒学苑第六天

谷粒学苑第六天 https://hyy-0212.oss-cn-hangzhou.aliyuncs.com/%E5%A4%B4%E5%83%8F.jpg AccessKey看私密文件 后端&#xff1a; idea导入项目后文件颜色不对解决方法 解决&#xff1a;https://blog.csdn.net/m0_37735176/article/details/88916844 后端 私有转为公有&am…

C语言——字符串函数与内存函数

目录 前言 一. 函数介绍 1.1 strlen 1.2 strcpy 1.3 strcat 1.4 strcmp 1.5 strncpy 1.6 strncat 1.7 strncmp 1.8 strstr 1.9 strtok 1.10 strerror 1.11 字符分类函数 1.12 memcpy 1.13 memmove 1.14 memcmp 二. 函数的模拟实现 2.1 模拟实现strlen 2.2 模拟实现st…

阿里测试员晒薪资条,看完真的扎心了...

前几天&#xff0c;有位老粉私信我&#xff0c;说看到某95后学弟晒出阿里的工资单&#xff0c;他是真酸了…想狠补下技术&#xff0c;努力冲一把大厂。 为了帮到他&#xff0c;也为了大家能在最短的时间内做面试复习&#xff0c;我把软件测试面试系列都汇总在这一篇文章了。 …

Windows10 把两张图片合并成一张图片

Windows10把两张图片合并成一张图片 文章目录Windows10把两张图片合并成一张图片1. 背景2. "画图"实现多图拼接1. 背景 相比截图功能&#xff0c;在 Google 的 Chrome 浏览器上&#xff0c;整页截屏功能仍需要安装额外的插件才能完成&#xff0c;这一点 微软的 bing…

【K3s】第18篇 详解 Kubernetes 调度器工作原理

目录 1、概述 2、kube-scheduler 3、kube-scheduler 调度流程 4、支持两种方式配置调度器的过滤和打分行为 4.1 调度策略 4.2 调度策略 5、总结 1、概述 在 Kubernetes 中&#xff0c;调度 是指将Pod放置到合适的节点上&#xff0c;以便对应节点上kubelet能够运行这些 P…

ChatGPT来临,架构师何去何从?

你好&#xff0c;我是李运华。 最近科技圈大火的事件就是ChatGPT的全球火热流行。这款由OpenAI公司在2022年11月底推出的聊天机器人&#xff0c;创造了史上消费应用最快达成1亿用户的历史&#xff0c;在推出仅仅两个月后&#xff0c;月活跃用户估计已达1亿&#xff0c;成为历史…

dbever连接kerberos认证的hive

文章目录一、本地安装kerberos客户端二、本地kerberos客户端登录三、dbever连接hive一、本地安装kerberos客户端 下载地址&#xff1a;https://web.mit.edu/kerberos/dist/index.html 安装&#xff1a;下一步或者自定义安装即可 安装后会自动生成配置文件&#xff1a;C:\Pro…

强化学习RL 01: Reinforcement Learning 基础

目录 RL理解要点 1. RL数学基础 1.1 Random Variable 随机变量 1.2 概率密度函数 Probability Density Function(PDF) 1.3 期望 Expectation 1.4 随机抽样 Random Sampling 2. RL术语 Terminologies 2.1 agent、state 和 action 2.2 策略 policy π 2.3 奖励 reward …

利用GPT-3 Fine-tunes训练专属语言模型

利用GPT-3 Fine-tunes训练专属语言模型 文章目录什么是模型微调&#xff08;fine-tuning&#xff09;&#xff1f;为什么需要模型微调&#xff1f;微调 vs 重新训练微调 vs 提示设计训练专属模型数据准备清洗数据构建模型微调模型评估模型部署模型总结什么是模型微调&#xff0…

cesium: 绘制线段(008)

第008个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中绘制线段,左键点击开始绘制,右键点击取消绘制 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共139行)相关API参考:专栏目标示例效果 配置方式 1)…

Win11的两个实用技巧系列清理磁盘碎片、设置系统还原点的方法

Win11如何清理磁盘碎片?Win11清理磁盘碎片的方法磁盘碎片过多&#xff0c;会影响电脑的运行速度&#xff0c;所以需要定期清理&#xff0c;这篇文章将以Win11为例&#xff0c;给大家分享的整理磁盘碎片方法相信很多用户都会发现&#xff0c;随着电脑使用时间的增加&#xff0c…

一文了解 requestAnimationFrame

requestAnimationFrame 的基本使用 requestAnimationFrame 是什么 window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画&#xff0c;并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数&#xff0c;该回调函数会在浏…

想要实现无人机控制算法二次开发,一定不要错过这个matlab工具包

什么是Matlab工具包 Matlab工具包提供了无人机位置环控制算法、Simulink示例程序&#xff0c;通过Matlab ROS Toolbox建立Matlab&#xff08;Simulink&#xff09;与ROS之间的通信链路&#xff0c;Prometheus项目中将提供转为Matlab设计的控制接口&#xff0c;同时将继承Prome…