1,pom.xml

               <!-- kafka -->
<dependency>
<groupId>com.github.danielwegener</groupId>
<artifactId>logback-kafka-appender</artifactId>
<version>0.2.0-RC1</version>
<scope>runtime</scope>
</dependency>
<!-- logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.0</version>
</dependency> <!-- other-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>

2, spring-logback.xml

<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false" scan="true" scanPeriod="600000">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<property name="LOG_HOME" value="/var/log" />
<contextName>${HOSTNAME}</contextName>
<springProperty scope="context" name="appName"
source="spring.application.name" />
<springProperty scope="context" name="ip"
source="spring.cloud.client.ipAddress" /> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<property name="CONSOLE_LOG_PATTERN"
value="[%d{yyyy-MM-dd HH:mm:ss.SSS} ${ip} ${appName} %highlight(%-5level) %yellow(%X{X-B3-TraceId}),%green(%X{X-B3-SpanId}),%blue(%X{X-B3-ParentSpanId}) %yellow(%thread) %green(%logger) %msg%n" /> <!-- <logger name="org.springframework.web" level="DEBUG" /> --> <!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<!--<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"
/> -->
<!--<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG"
/> -->
<!--<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" /> -->
<!--<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG"
/> --> <!-- <logger name="org.hibernate.SQL" level="DEBUG" /> -->
<logger name="logging.level.com.italktv.platform" level="info" /> <!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
</appender> <!-- 按照每天生成日志文件 -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_HOME}/bigdata/data-api.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/bigdata/data-api.%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>1MB</maxFileSize>
<totalSizeCap>10MB</totalSizeCap>
</rollingPolicy>
<encoder
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<pattern>
<pattern>
{
"level": "%level",
"trace": "%X{X-B3-TraceId:-}",
"requestId": "%X{requestId}",
"remoteIp": "%X{remoteIp}",
"span": "%X{X-B3-SpanId:-}",
"parent":
"%X{X-B3-ParentSpanId:-}",
"thread": "%thread",
"class":
"%logger{40}",
"message": "%message",
"stack_trace":
"%exception{10}"
}
</pattern>
</pattern>
</providers>
</encoder>
<!--日志文件最大的大小 <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10KB</MaxFileSize> </triggeringPolicy> -->
</appender> <!-- pom dependency <dependency>
<groupId>com.github.danielwegener</groupId>
<artifactId>logback-kafka-appender</artifactId>
<version>0.1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.11</version>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.11</version>
</dependency> -->
<!-- other appender
<appender name="kafkaAppenderAnotherEncode"
class="com.github.danielwegener.logback.kafka.KafkaAppender"> <encoder
class="com.github.danielwegener.logback.kafka.encoding.PatternLayoutKafkaMessageEncoder">
<layout class="net.logstash.logback.layout.LogstashLayout">
<includeMdc>true</includeMdc>
<includeContext>true</includeContext>
<includeCallerData>true</includeCallerData>
<customFields>{"system":"test"}</customFields>
<fieldNames class="net.logstash.logback.fieldnames.ShortenedFieldNames" />
</layout>
</encoder> <topic>tv_server_logstash_log</topic>
<keyingStrategy
class="com.github.danielwegener.logback.kafka.keying.HostNameKeyingStrategy" />
<deliveryStrategy
class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy" />
<producerConfig>bootstrap.servers=211.100.75.227:9092</producerConfig>
<producerConfig>acks=0</producerConfig>
<producerConfig>linger.ms=1000</producerConfig>
<producerConfig>block.on.buffer.full=false</producerConfig>
<appender-ref ref="STDOUT" />
</appender>
--> <!-- https://www.cnblogs.com/maxzhang1985/p/9522507.html
https://logback.qos.ch/manual/layouts.html
-->
<appender name="kafkaAppender"
class="com.github.danielwegener.logback.kafka.KafkaAppender"> <encoder charset="UTF-8"
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"> <providers>
<mdc />
<context />
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<pattern>
<pattern>
{ "level": "%level",
"trace": "%X{X-B3-TraceId:-}",
"span":
"%X{X-B3-SpanId:-}",
"parent": "%X{X-B3-ParentSpanId:-}",
"thread":
"%thread",
"class": "%logger{40}",
"message": "%message",
"stack_trace": "%exception{10}"
}
</pattern>
</pattern>
</providers>
</encoder> <topic>tv_server_logstash_log</topic>
<keyingStrategy
class="com.github.danielwegener.logback.kafka.keying.HostNameKeyingStrategy" />
<deliveryStrategy
class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy" />
<producerConfig>bootstrap.servers=127.0.0.1:9092</producerConfig>
<!-- don't wait for a broker to ack the reception of a batch. -->
<producerConfig>acks=0</producerConfig>
<!-- wait up to 1000ms and collect log messages before sending them as
a batch -->
<producerConfig>linger.ms=1000</producerConfig>
<!-- even if the producer buffer runs full, do not block the application
but start to drop messages -->
<!--<producerConfig>max.block.ms=0</producerConfig> -->
<producerConfig>block.on.buffer.full=false</producerConfig>
<!-- kafka连接失败后,使用下面配置进行日志输出 -->
<appender-ref ref="STDOUT" />
</appender> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="kafkaAppender" />
</appender> <!-- 日志输出级别 -->
<root level="INFO">
<!-- 生产上不输出stdout log -->
<appender-ref ref="STDOUT" />
<!-- <appender-ref ref="FILE" /> --> <!-- <appender-ref ref="kafkaAppender" /> -->
<appender-ref ref="ASYNC" /> </root> </configuration>

3, 添加一个mdc在logback

import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; @Component
public class LogInterceptor implements HandlerInterceptor { private final static String REQUEST_ID = "requestId";
private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class); @Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String xForwardedForHeader = httpServletRequest.getHeader("X-Forwarded-For");
String remoteIp = httpServletRequest.getRemoteAddr();
String uuid = UUID.randomUUID().toString();
LOGGER.info("put requestId ({}) to logger", uuid);
LOGGER.info("request id:{}, client ip:{}, X-Forwarded-For:{}", uuid, remoteIp, xForwardedForHeader);
MDC.put(REQUEST_ID, uuid);
MDC.put("remoteIp", remoteIp);
return true;
} @Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
ModelAndView modelAndView) throws Exception {
String uuid = MDC.get(REQUEST_ID);
LOGGER.info("remove requestId ({}) from logger", uuid);
MDC.remove(REQUEST_ID);
} @Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e)
throws Exception { }
}

4,添加切面 intercept

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Autowired
private LogInterceptor logInterceptor; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor);
super.addInterceptors(registry);
}
}

参考:

logback 手册:https://logback.qos.ch/manual/layouts.html

http://www.importnew.com/28541.html

https://www.jianshu.com/p/a26da0c55255

https://blog.csdn.net/Soinice/article/details/84033382

https://examples.javacodegeeks.com/enterprise-java/logback/logback-kafka-appender-example/

http://stevetarver.github.io/2016/04/20/whole-product-logging.html 讲解详细

logback输出json格式日志(包括mdc)发送到kafka的更多相关文章

  1. Maven项目配置Logback输出JSON格式日志

    最近,项目提出需求,日志需要固定输出为JSON格式,以便后端Flink程序解析. 项目背景 项目为简单的Maven项目,日志由Filebeat采集,因此不需要配置输出至Logstash. 下面为pom ...

  2. filebeat收集nginx的json格式日志

    一.在nginx主机上安装filebeat组件 [root@zabbix_server nginx]# cd /usr/local/src/ [root@zabbix_server src]# wge ...

  3. Logback 输出 JPA SQL日志 到文件

    Logback 输出 JPA SQL日志 到文件 使用Spring Boot 配置 JPA 时可以指定如下配置在控制台查看执行的SQL语句 spring.jpa.show-sql=true Sprin ...

  4. PHP、Java输出json格式数据

      PHP 输出json. $result = mysql_query($sql); //查询结果 $users=array(); $i=0; while($row=mysql_fetch_array ...

  5. 在JSP页面中输出JSON格式数据

    JSON-taglib是一套使在JSP页面中输出JSON格式数据的标签库. JSON-taglib主页: http://json-taglib.sourceforge.net/index.html J ...

  6. python json.dumps()函数输出json格式,使用indent参数对json数据格式化输出

    在python中,要输出json格式,需要对json数据进行编码,要用到函数:json.dumps json.dumps() :是对数据进行编码 #coding=gbkimport json dict ...

  7. WCF兼容WebAPI输出Json格式数据,从此WCF一举两得

    问题起源: 很多时候为了业务层调用(后台代码),一些公共服务就独立成了WCF,使用起来非常方便,添加服务引用,然后简单配置就可以调用了. 如果这个时候Web站点页面需要调用怎么办呢? 复杂的XML , ...

  8. php直接输出json格式

    php直接输出json格式,很多新手有一个误区,以为用echo json_encode($data);这样就是输出json数据了,没错这样输出文本是json格式文本而不是json数据,正确的写法是应该 ...

  9. ELK之收集Nginx、Tomcat的json格式日志

    1.安装Nginx yum -y install nginx vim /etc/nginx/nginx.conf # 修改日志格式为json格式,并创建一个nginxweb的网站目录 log_form ...

随机推荐

  1. HTML文档命名规则

    HTML文档是展示Web前段开发工程师成果的最好表示方式,为了便于文档规范化管理,在编写HTML文档时,必须遵循HTML文件命名规则. HTML文档命名规则如下: (1)文档的扩展名为htm或者htm ...

  2. 都 9012了,该选择 Angular、React,还是Vue?

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 尽管 Web开发的典型应用场景除了将服务器用作平台.浏览器用作客户端之外,几乎很少活跃于其他业务领域,但不可 ...

  3. typescript中类的继承

    typescript中类的继承用到的是:extends和super 先看一下typescript中类的写法: class Demo{ //类的属性 name:string; age:number; / ...

  4. Hadoop 3.1.2(HA)+Zookeeper3.4.13+Hbase1.4.9(HA)+Hive2.3.4+Spark2.4.0(HA)高可用集群搭建

    目录 目录 1.前言 1.1.什么是 Hadoop? 1.1.1.什么是 YARN? 1.2.什么是 Zookeeper? 1.3.什么是 Hbase? 1.4.什么是 Hive 1.5.什么是 Sp ...

  5. MyDAL - .QueryOneAsync() 使用

    索引: 目录索引 一.API 列表 .QueryOneAsync() .QueryOneAsync<M>() 如: .QueryOneAsync<Agent>() , 用于 单 ...

  6. centos7网络配置总结

    centos7网络配置 --wang 一.通过配置文件 配置/etc/sysconfig/network-scripts/en.. 记忆信息量大,易出错,不推荐使用.配置多台电脑静态ip可以通过复制模 ...

  7. SQLServer创建用户登录

    创建用户登录注意事项 密码是区分大小写的. 只有创建SQL Server登录时,才支持对密码预先进行哈希运算. 如果指定MUST_CHANGE,则CHECK_EXPIRATION和 CHECK_POL ...

  8. 当锚点遇到fixed

    问题:页面内容导航fixed+锚点错位 solution: 锚点定位跟外边距没有关系. 我们使用内边距padding-top=fixed导航高度来使锚点可以精准定位: 此时新的问题产生了,内边距的存在 ...

  9. PHPstorm快捷键Ctrl + Alt + Left 或Right不起作用

    最近遇到一个问题,就是安装的phpstorm的回撤快捷键不起作用了,死活用不了!折磨了好久,终于找到解决方法了,具体请看我的github文章: 快捷键Ctrl + Alt + Left 或Right不 ...

  10. C++11のlambd表达式

    在其他语言中,我们常见lambda表达式,c++11中也引入了. 利用Lambda表达式,可以方便的定义和创建匿名函数.今天,我们就来简单介绍一下C++中Lambda表达式的简单使用. 一.lambd ...