java 使用redis记录logback日志,由自定义Appender与Jedis的使用实现。

2023-11-11

需求

1、获取日志的产生的线程名称,记录器名称,上下文产生时间,日志发生时间,自定义日志的信息
2、将获取的信息以json的形式保存到redis中

思路

1、配置logback使用自定义Appender实现,来获取对应的日志信息
2、配置一个单列的redis工具类(不影响其他业务),将获取的日志信息保存起来

依赖

1、logback

<!-- 日志:slf4j是接口,log4j是具体实现 -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.12</version>
</dependency>
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-core</artifactId>
  <version>1.1.1</version>
</dependency>
<!-- 实现slf4j接口并整合 -->
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.1.1</version>
</dependency>

2、redis

<!--redis-->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.7.3</version>
</dependency>

配置

1、logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--自定义日志-->
    <appender name="MyAppender" class="log.RedisAppender" />
    <root level="info">
        <appender-ref ref="MyAppender" />
    </root>
</configuration>

2、redis.properties

maxIdle=100
maxWait=3000
testOnBorrow=true

host=127.0.0.1
port=6379
timeout=3000
pass=你的密码

工具类

1、json转换类

package tool;

import com.fasterxml.jackson.databind.ObjectMapper;
import exception.DobeoneException;

/**
 * Created by yuyu on 2018/3/15.
 * json相关的函数
 */
public class JsonBuilder {
    /**
     * 将一个实体类转换成json字符串
     * @param object
     * @return
     */
    public static String getString(Object object){
        //安全判断
        if (object==null){
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        String back;
        try{
            back=mapper.writeValueAsString(object);
        }catch (Exception e){
            //抛出一个自定义异常
            throw new DobeoneException("json字符转换失败!-object-"+object,e);
        }
        return back;
    }
}

2、配置文件获取

package tool;

import exception.DobeoneException;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * Created by yuyu on 2018/3/12.
 * 用于参数配置文件中的数据获取
 */
public class PropertiesGetter {
    /**
     * 获取配置文件的配置信息
     * @param name
     * @return
     */
    public synchronized static Properties get(String name){
        String file="/properties/"+name+".properties";
        Properties prop = new Properties();
        InputStream in = PropertiesGetter.class.getResourceAsStream(file);
        try {
            prop.load(in);
        } catch (IOException e) {
            throw new DobeoneException("获取配置文件异常!-file-"+file,e);
        }
        return prop;
    }
}

3、日期转换

package tool;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by yuyu on 2018/3/15.
 * 用于日期处理相关函数
 */
public class DataFormatBuilder {

    /**
     * 根据传进来的时间戳 获取对应的时间格式
     * @param format 时间格式
     * @param stamp 时间戳
     * @return
     */
    public static  String getTimeStampFormat(String format,Long stamp){
        if (stamp==null){
            return null;
        }
        if (format==null){
            format="yyyy-MM-dd HH:mm:ss/SSS";
        }
        SimpleDateFormat df = new SimpleDateFormat(format);//设置日期格式
        return df.format(stamp);//传进来的时间戳为获取当前系统时间
    }
}

4、redis相关的操作

package tool;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.Properties;

/**
 * Created by yuyu on 2018/3/15.
 * redis相关的操作,获取一个单例的连接池
 */
public class RedisBuilder {

    private static JedisPool jedisPool;

    private static RedisBuilder singleRedisBuilder=new RedisBuilder();

    //单利模式
    private RedisBuilder(){
        //获取配置信息
        Properties properties=PropertiesGetter.get("redis");
        //设置连接池参数
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")));//最大的jedis实例
        config.setMaxWaitMillis(Integer.parseInt(properties.getProperty("maxWait")));//最大等待时间(毫秒)
        config.setTestOnBorrow(Boolean.parseBoolean(properties.getProperty("testOnBorrow")));//借用时测试
        //redis链接
        jedisPool=new JedisPool(config, properties.getProperty("host")
                , Integer.parseInt(properties.getProperty("port"))
                , Integer.parseInt(properties.getProperty("timeout"))
                ,  properties.getProperty("pass"));
    }

    /**
     * 从连接池中获取一个Jedis对象
     * @param db 数据库[0,15]
     * @return
     */
    public static Jedis getSingleJedis(Integer db) {
        if (db==null||(db<0&&db>15)){
            return null;
        }
        Jedis back=jedisPool.getResource();
        back.select(db);
        return back;
    }

    /**
     *传入名称获取保存在redis中的Index号码
     * @param name
     * @return
     */
    public static Integer getRedisIndexByName(String name){
        if (name==null){
            return null;
        }
        Jedis jedis=RedisBuilder.getSingleJedis(15);
        Integer index;
        String value=jedis.get(name);
        //获取保存的index数据,没有的时候取0
        if (null==value){
            index=0;
        }else{
            index =Integer.parseInt(value)+1;
        }
        //将index保存
        jedis.set(name,index.toString());
        jedis.close();
        return index;
    }
}

实现

1、数据保存dto

package dto.log;

import ch.qos.logback.classic.spi.LoggingEvent;
import tool.DataFormatBuilder;

/**
 * Created by yuyu on 2018/3/15.
 * 用于保存日志数据
 */
public class LogData {

    private String message;//日志的信息
    private String loggerTime;//上下文产生时间
    private String loggerName;//记录器名称
    private String threadName;//线程名称
    private String happenStamp;//日志发生时间

    public LogData() {
    }

    public LogData(LoggingEvent loggingEvent) {

        this.message=loggingEvent.toString();
        this.loggerTime=DataFormatBuilder.getTimeStampFormat(null,
                loggingEvent.getContextBirthTime());
        this.loggerName=loggingEvent.getLoggerName();
        this.threadName=loggingEvent.getThreadName();
        this.happenStamp=DataFormatBuilder.getTimeStampFormat(null,
                loggingEvent.getTimeStamp());
    }
    //getter,setter略
}

2、自定义Appender

package log;

import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.AppenderBase;
import dto.log.LogData;
import redis.clients.jedis.Jedis;
import tool.JsonBuilder;
import tool.RedisBuilder;

/**
 * Created by yuyu on 2018/3/15.
 * 自定义日志处理
 */
public class RedisAppender extends AppenderBase<LoggingEvent> {

    @Override
    protected void append(LoggingEvent loggingEvent) {
        //获取日志数据
        LogData logData=new LogData(loggingEvent);
        //设置日志保存数据库
        Jedis jedis=RedisBuilder.getSingleJedis(2);
        //设置日志的key
        String key="logData";
        //获取日志条数
        Integer index=RedisBuilder.getRedisIndexByName(key);
        //保存日志
        jedis.set(key+index, JsonBuilder.getString(logData));
        //关闭链接
        jedis.close();

    }
}

测试

1、测试代码

package tool;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by yuyu on 2018/3/15.
 * 测试日志到redis
 */
public class TestLogger {

    private Logger logger= LoggerFactory.getLogger(this.getClass());

    @Test
    public void testLogger(){
        logger.info("hahha");
    }
}

2、redis数据截图
这里写图片描述
3、json数据结构

{
    "message":"[INFO] hahha",
    "loggerTime":"2018-03-15 20:00:55/694",
    "loggerName":"tool.TestLogger",
    "threadName":"main",
    "happenStamp":"2018-03-15 20:00:56/087"
}

总结

1、代码中出现使用的工具类都已经给出
2、每一次日志都提交记录的情况可能会消耗大量资源,可以设置缓存,然后到达一定条数再将记录写入redis中
3、想要具体获取再多的日志信息详情请查看,ch.qos.logback.classic.spi.LoggingEvent 提供的方法
4、更多请查看参考文章

参考文章

1、Log4j2、Log4j、Logback自定义Appender实现
2、logback-Appender 自定义详解
3、单例模式
4、jedis连接池配置

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 使用redis记录logback日志,由自定义Appender与Jedis的使用实现。 的相关文章

  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • 如何设计高性能的分布式锁

    什么是分布式锁 在 JVM 中 在多线程并发的情况下 我们可以使用同步锁或 Lock 锁 保证在同一时间内 只能有一个线程修改共享变量或执行代码块 但现在我们的服务都是基于分布式集群来实现部署的 对于一些共享资源 在分布式环境下使用 Jav
  • Antd Table 可编辑表格

    antd Table 官方文档提及了 可编辑单元格 可编辑行 这里解决 可编辑表格 主要思路是将 antd Table 可编辑行 与 antd Form List 相结合 将Table视为 Form List 中循环的 Form Item
  • 如何使用Hexo搭建属于自己的博客

    Hexo安装步骤 Hexo官网 环境准备 Nodejs Git node v npm v 安装Hexo npm install hexo cli g cd到你需要创建博客的文件夹 hexo init blog cd blog npm ins
  • Ubuntu系统连接罗技K380键盘

    近日向学习LInux系统的使用 便把windows系统卸载装上了Ubuntu 下面是罗技K380连接Ubuntu 系统的方法 先打开K380键盘的蓝牙 我选择2 然后进入电脑的终端 输入如下命令 bluetoothctl devices 此
  • 超详细的tomcat的下载安装和配置教程

    tomcat运行的前提是安装并配置了JDK 若没有安装配置JDK 先去安装配置JDK 如下链接 JDK 1 8的下载安装和环境变量的配置 详细步骤 一 下载tomcat 1 进入tomcat的下载 tomcat下载官网 2 点击进入 点击
  • FastDFS在Docker集群安装

    一 简介 FastDFS是由国人余庆所开发 其项目地址 https github com happyfish100 FastDFS是一个轻量级的开源分布式文件系统 主要解决了大容量的文件存储和高并发访问的问题 文件存取时实现了负载均衡 Fa
  • 基于Matlab模拟宇宙射线μ

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 更多Matlab仿真内容点击 智能优化算法 神经网络预测 雷达通信 无线传感器 电力系统 信号
  • springboot+react实现前后端交互

    一 搭建springboot后台 1 创建一个Springboot项目 然后导入pom依赖 本着一切从简的原则 如果不连接数据库的话 有个spring boot starter web的依赖就够用了
  • webpack5 loader

    文章目录 作用 基本使用 内联loader loader执行顺序 loader pitch 中断 pitch pitch示例 自定义loader 查找loader loader方法参数 同步loader return方式 this call
  • mysql - 索引

    索引的分类 主键索引 唯一索引 普通索引 组合索引 以及全文索引 主键索引 非空唯一索引 一个表只有一个主键索引 在 innodb 中 主键索引的B 树包含表数据信息 PRIMARY KEY key 唯一索引 不可以出现相同的值 可以有NU
  • React 组件与状态

    企业项目实战 gt 第二部分 gt React 基础回顾 React 组件与 State 什么是组件 组件是什么 每个程序员都有自己的理解 在传统语言中 组件的定义一般来说是一个从特定的组件类中派生出来的特定的对象 而在早期的前端开发者眼里
  • 复变函数第三章-复变函数的积分

    3 复变函数的积分 3 1 概念 3 2 柯西 古萨基本定理 3 3 复合闭路定理 3 4 原函数与不定积分 3 5 柯西积分公式 3 6 解析函数的高阶导数 3 7 调和函数 3 复变函数的积分 3 1 概念 闭曲线积分 Cf z dz
  • React是什么,React的优点、缺点

    React是什么 React的优点 缺点 与Vue对比 在React源码中的React哲学里有这样一句话 我们认为 React是用JavaScript构建快速响应的大型的Web应用程序的首选方案 由此可见 关键在于快速响应 大型web应用
  • 为了一张图

    我的作业图
  • Quartus系列:Quartus II 功能仿真设置流程

    1 新建一个波形文件 2 右键点击Name下空白框 在弹出的菜单中选择 Inert gt Insert Node or Bus 如果已经知道端口名称和端口类型 直接在弹出的对话框中键入Name后 相应的信息会自动识别到对话框中 如下 如果不
  • MVVM模式下,ViewModel和View,Model有什么区别

    摘自正美的5群 Model 很简单 就是业务逻辑相关的数据对象 通常从数据库映射而来 我们可以说是与数据库对应的model View 也很简单 就是展现出来的用户界面 基本上 绝大多数软件所做的工作无非就是从数据存储中读出数据 展现到用户界
  • Java EnumSet allOf()方法具有什么功能呢?

    转自 Java EnumSet allOf 方法具有什么功能呢 下文笔者讲述Java中EnumSet allOf 方法的功能简介说明 如下所示 EnumSet allOf 方法的功能 返回枚举集合中所有的值 EnumSet allOf 方法
  • 【附源码】用手写数字字母为例,演示“一行代码不写,完成大多数分类任务”

    基于MATLAB 2021a 录制的深度学习之图像分类 新手保姆级入门课程 就算是小学生跟着操作都能懂了 掌握了这个 很多分类任务都是换汤不换药了 一行代码不写就可以完成手写数字和字母共计36类图片的分类 按照此方法 理论上可以一行代码不写
  • Web小白基础教程-第三篇-HTML基础常用标签名(一)

    谈起Html就不得不简单说一说Web网页制作 Web标准的构成分为三个部分 HTML CSS和JavaScript 三层分离 互相独立 HTML Web的结构部分 通俗点来说就是Web页面上的元素和内容 CSS Web的表现部分 通俗点来说
  • java 使用redis记录logback日志,由自定义Appender与Jedis的使用实现。

    需求 1 获取日志的产生的线程名称 记录器名称 上下文产生时间 日志发生时间 自定义日志的信息 2 将获取的信息以json的形式保存到redis中 思路 1 配置logback使用自定义Appender实现 来获取对应的日志信息 2 配置一