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

xiaoxiao2021-02-28  42

需求

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连接池配置

转载请注明原文地址: https://www.6miu.com/read-2623085.html

最新回复(0)