浅谈java日志格式化

1.日志的重要性

不管我们使用何种语言开发,一旦程序发生异常,日志是一个很重要的数据。但是并不是意味着打印的日志越多越好,我们需要的是有用的日志。
曾经参与一个很重要的项目优化,他们的日志没有进行规范,开发、运维也没有把这个事情放在心上。等到压测的时候TPS和响应时间一直上不去。通过jstack分析发现,大部分的log数据在阻塞!
今天我们不讨论具体的日志规范,我从日志中心的角度来聊下LOG的规范

2.日志采集分析 -ELK

目前主流的ELK系统应该都是通过agent端(filebeat/flume)采集具体.log文件,对于日志没有多大处理的话,我们可能把整条日志采集过来后,通过logstash后把message存储到elasticsearch中。

1.当我们需要从每条日志中提取日志时间、日志级别等等信息的时候,我们需要在logstash配置相应的 grok语法解析其中的message信息。

2.当我们的日志中有异常信息,我们需要提取异常信息的时候,你会发现用grok来清洗message很困难!其实也有解决的方法,需要你去慢慢写正则匹配

不错,logstash强大的grok及mutate可以满足需求,但是当日志量很大的时候,logstash的grok和mutate会消耗大量的资源。那我们有没有更有的方案呢?

下面我们用java日志来举例吧

在想要得到答案之前,我们需要知道存储到es的最终数据是JSON,logstash清洗数据最终的结果是转换成JSON。一般的agent采集端仅仅只是做日志的采集,即使kafka做缓冲,kafka也不做处理。因此我们需要从日志的根源来解决这个问题。

3.为什么使用logstash处理Java的异常信息不好做呢?

这就涉及到日志框架输出的异常信息通常是多行的,这就意味着我们需要在filebeat(flume)或者logstash来处理多行的问题。当我们在日志的配置文件没有很好的区分日志的message和stack时,日志是糅杂一块的。提前其中的信息很难很难

4. 日志json化

既然原生的日志数据不好处理,那么我们需要对日志框架做些美容手术。
在日志中,我们一般都会打印,时间/日志级别/线程/日志内容/当前文件名/loggerName/异常信息等等。
其中 日志内容和异常信息可能会出现多行。这个需要处理下,下面我们使用fastjson来处理这两个字段,见代码

public class MsgConverter extends ClassicConverter {

 @Override
 public String convert(ILoggingEvent event) {
 return JsonUtils.serialize(event.getFormattedMessage());

 }
}
public class StackTraceConverter extends ThrowableProxyConverter {
 @Override
 public String convert(ILoggingEvent event) {
 IThrowableProxy throwableProxy = event.getThrowableProxy();
 // 如果没有异信息
 if (throwableProxy == null) {
 //返回字符串 : "\"\""
 return JsonUtils.serialize("");
 }
 String ex = super.convert(event);
 return JsonUtils.serialize(ex);
 }
}

其中JsonUtils可以选择合适的json框架来处理

之后在logback.xml中配置

<configuration>
 <conversionRule conversionWord="exdiy" converterClass="xxx.logback.converter.StackTraceConverter" />
 <conversionRule conversionWord="msgdiy" converterClass="xxx.logback.converter.MsgConverter" />
</configuration>

修改layout -> Pattern

<layout>
 <!--<Pattern>{"date":"%date{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","tid":"%tid","className":"%logger","fileLine":"%file:%line","msg":%message, "stack_trace":%ex }%n</Pattern>-->
 <Pattern>{"date":"%date{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","className":"%logger","fileName":"%file","thread":"%thread","msg":%msgdiy, "stack_trace":%exdiy}%n</Pattern>
</Pattern>
{
 "date":"2019-01-02 16:16:33.817",
 "level":"INFO",
 "className":"org.springframework.web.servlet.DispatcherServlet","fileName":"FrameworkServlet.java","thread":"http-nio-8762-exec-1","msg":"FrameworkServlet 'dispatcherServlet': initialization completed in 38 ms", "stack_trace":""
}

logstash将json字符串转换成json即可

json {
 source => "message"
 #target => "doc"
 remove_field => ["message"]
 }
 date {
 match => ["date","yyyy-MM-dd HH:mm:ss.SSS"]
 target => "@timestamp"
 locale => "cn"
 timezone => "Asia/Shanghai"
 }

最终效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中"尽情"的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名严谨的程序员,怎么能让这种事情发生呢?所以下面我们就来了解一下关于日志的那些正确使用姿势. 正文 日志规范 命名 首先是日志文件的命名,尽量要做到见名知意,团队里面也必须使用统一的命名规范,不然"脏乱差"的日志文件会影响大家排查问题的效率.这里推荐以"proj

  • java 日志的数据脱敏的实现方法

    数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号.手机号.卡号.客户号等个人信息都需要进行数据脱敏,数据库安全技术之一. 比如我们现在有个user表,含有名字,性别,邮箱,电话号码等字段,但是当查看这些数据时,我们又不希望这些数据被暴露,这时可以对这些数据进行脱敏处理,当然可以根据需要选择哪些字段需要脱敏,然后再输出,至于怎么选择的,是另外一回事

  • Java日志组件间关系详解

    一. 总览 本文章不对日志组件进行优劣评价,只是对关系进行对比.在日志中组件中存在这样的几种关系, 这几种关系理解清楚, 有助于我们对日志的引入和使用. 二. 日志门面 日志门面就是指直接引入我们程序中进行记录日志的日志组件,作为日志门面的这些组件会在程序中直接依赖, 上图中就列举的几种常见的日志门面的组件.像一些软件直接回默认使用一些组件, 比如Spring使用的就是commons-logging, activiti使用的日志门面就是slf4j, 其他的软件也都会选用自己认为好用的日志门面.

  • 浅谈Java slf4j日志简单理解

    一.理解 slf4j(Simple Logging Facade for Java),表示为java提供的简单日志门面,更底层一点说就是接口.通过将程序中的信息导入到日志系统并记录,实现程序和日志系统的解耦 日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用.由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,就好像JDBC与各种不同的数据库之间的结合需要对应的

  • 浅谈java日志格式化

    1.日志的重要性 不管我们使用何种语言开发,一旦程序发生异常,日志是一个很重要的数据.但是并不是意味着打印的日志越多越好,我们需要的是有用的日志. 曾经参与一个很重要的项目优化,他们的日志没有进行规范,开发.运维也没有把这个事情放在心上.等到压测的时候TPS和响应时间一直上不去.通过jstack分析发现,大部分的log数据在阻塞! 今天我们不讨论具体的日志规范,我从日志中心的角度来聊下LOG的规范 2.日志采集分析 -ELK 目前主流的ELK系统应该都是通过agent端(filebeat/flu

  • 浅谈Java中格式化输出

    格式化控制台输出 要点提示: 在控制台上显示格式化输出:System.out.printf方法 常用的格式标识符 (图片来源: java核心技术卷1(第九版)) 格式标识符的解释 % 4 . 2 f 4为域宽度.输出的浮点数条目宽度至少为4,包括小数点和小数点后两位数字.这样,给小数点前分配了1位数字. 如果该条目小数点前的位数小于1,就在数字前面加空格. 如果该条目小数点前的位数大于7,则自动增加宽度. 2为精度().即想要输出的小数点的长度. f为转换码 指定宽度和精度的例子 举例 输出 %

  • 浅谈Java日志框架slf4j作用及其实现原理

    SLF4J是一个日志框架抽象层,底下绑定具体的日志框架,比如说Log4J,Logback,Java Logging API等.SLF4J也有自身的默认实现,但是我们还是主要以日志框架抽象层的身份使用SLF4J. 要使用SLF4J,得包含对"org.slf4j:slf4j-api"的依赖. 简单回顾门面模式 slf4j是门面模式的典型应用,因此在讲slf4j前,我们先简单回顾一下门面模式, 门面模式,其核心为外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用.用一

  • 浅谈Java springboot日志管理

    一.前言 springboot默认使用Logback组件作为日志管理.Logback是由log4j创始人设计的一个开源日志组件. 在springboot项目中我们不需要额外的添加Logback的依赖,因为在spring-boot-starter或者spring-boot-starter-web中已经包含了Logback的依赖 Logback读取配置文件的步骤 在classpath下查找文件logback-test.xml 如果文件不存在,则查找logback.xml 如果上面两个文件都不存在,L

  • 浅谈Java中注解Annotation的定义、使用、解析

    此例子,用于说明如何在Java中对"注解 Annotation"的定义.使用和解析的操作.注解一般用于自定义开发框架中,至于为什么使用,此处不作过多说明,这里只说明如何使用,以作备记.下面例子已测试,可以正常运行通过. 1.注解自定义. 这里定义两个注解,分别用来注解类和注解属性. package cc.rulian.ann; import java.lang.annotation.ElementType; import java.lang.annotation.Retention;

  • 浅谈Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 /** * 业务接口 * @author pc * */ public interface UserService { // 增加一个用户 public void addUser(); // 编辑账户 public void editUser(); } 2.业务实现类 /** * 业务实现类 * @author pc

  • 浅谈java分页三个类 PageBean ResponseUtil StringUtil

    如下所示: package ssmy.page; /** * 分页类 * @author Jesse * */ public class PageBean { private int page;//第几页 private int pageSize;//每页显示的记录数 private int start ;//起始记录数 public int getPage() { return page; } public void setPage(int page) { this.page = page;

  • 浅谈java中六大时间类的使用和区别

    java.util.Date java.sql.Date java.sql.Time java.sql.Timestamp java.text.SimpleDateFormat java.util.Calendar java.util.Date日期格式为:年月日时分秒 java.sql.Date日期格式为:年月日 java.sql.Time日期格式为:时分秒 java.sql.Timestamp日期格式为:年月日时分秒纳秒(毫微秒) 从数据库中取出来的日期一般都用getTimestamp()方法

  • 浅谈Java BitSet使用场景和代码示例

    一.什么是BitSet? 注:以下内容来自JDK API: BitSet类实现了一个按需增长的位向量.位Set的每一个组件都有一个boolean值.用非负的整数将BitSet的位编入索引.可以对每个编入索引的位进行测试.设置或者清除.通过逻辑与.逻辑或和逻辑异或操作,可以使用一个 BitSet修改另一个 BitSet的内容. 默认情况下,set 中所有位的初始值都是false. 每个位 set 都有一个当前大小,也就是该位 set 当前所用空间的位数.注意,这个大小与位 set 的实现有关,所以

  • 浅谈JAVA 责任链模式

    顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为型模式. 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 介绍 意图: 避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止. 主要解决

随机推荐