logback的使用
1.引入依赖
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
2.准备好logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<contextName>logback</contextName>
<property name="log.path" value="F:\\logback.log" />
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="com.example.logback.filter.MyFilter" /> -->
<!--这里是搞了个过滤器,这里level会影响最后的打印 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName cclovezbf [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
</root>
<!-- 注意这里的ProducerConfig 我设置为warn了-->
<logger name="org.apache.kafka.clients.producer.ProducerConfig" level="warn"/>
<logger name="com.example.logback" level="info" />
</configuration>
kafka代码
import org.apache.kafka.clients.admin.AdminClient;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.common.serialization.StringSerializer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class kafkaTest {
Properties props = new Properties();
AdminClient adminClient;
Producer producer;
KafkaConsumer<String, String> consumer;
private String topic = "test-ia-label";//test-ia-label
private String group = "cc3";
public void buildProperties() {
props.put("bootstrap.servers", "9.135.68.201:9092");//9.135.68.201
props.put("acks", "all");
props.put("delivery.timeout.ms", 30000);
props.put("batch.size", 16384);
props.put("buffer.memory", 33554432);
props.put("key.serializer", StringSerializer.class.getName());
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
producer = new KafkaProducer<String, String>(props);
adminClient = AdminClient.create(props);
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("group.id", group);
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
//props.put("auto.commit.interval.ms", "1000");
consumer = new KafkaConsumer<>(props);
}
public void close(){
producer.close();
consumer.close();
adminClient.close();
}
}
logbackTest代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
private static Logger logger = LoggerFactory.getLogger(LogbackTest.class.getName());
public static void main(String[] args) {
System.out.println("slf4jApiTest2");
logger.info("info");
logger.error("error");
kafkaTest kafkaTest = new kafkaTest();
kafkaTest.buildProperties();
kafkaTest.close();
}
}
我们的目的是什么?
1.能够打印自己的logger.info
2.能够打印kafka的log
实现不同系统的不同类的日志级别?
我们要更进一步控制kafka的log级别,
比如produce的日志我不需要 只要warn 级别的
admin 和consumer的日志我需要info 和warn error
添加
<logger name="org.apache.kafka.clients.producer.ProducerConfig" level="warn"/>
知道这个有什么用?比如我们引入了某个框架,再打印jdbc的时候会把连接串打印出来,我觉得这样都有风险,我想屏蔽这个类的打印日志 ,这个时候我们可以把非关注点的日志的类 日志级别设置为warn
实现不同系统的的日志级别?
比如上面说的,我不想看到kafak 的produce info日志
同时我觉得admin 和consumer的日志也没有用 我也不想看到,
我只想看到warn级别,因为warn级别代表我有哪些参数没配好,我关注点在这里就好了。
办法1
<logger name="org.apache.kafka.clients.producer.ProducerConfig" level="warn"/> <logger name="org.apache.kafka.clients.admin.AdminClientConfig" level="warn"/> <logger name="org.apache.kafka.clients.consumer.ConsumerConfig" level="warn"/>
结果发现这三个类确实没有打印info日志了,只打印了warn日志,比较符合我们的想法。
但是发现还有kafka包里的AppInfoParser 打印了一些info日志,这种我也不想要咋办...
一个个添加是不是不太好?不美观
<logger name="org.apache.kafka.*" level="warn"/>
原以为设置为*就可以发现还是不行。。这样才行
<logger name="org.apache.kafka" level="warn"/>
办法二 使用filter
<filter class="ch.qos.logback.classic.filter.LevelFilter"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
这两个其实就一个区别.一个是大于等于。一个是等于。什么情况下用到呢?举个例子
记录错误日志的时候。我们日志一般分为普通的info 和warn 还有error
为了节约服务器的磁盘,日志落盘的时候 我们就可以设置是保存warn+error 还是只要error
只打印kafka的warn日志....
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<contextName>logback</contextName>
<property name="log.path" value="F:\\logback.log" />
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="com.example.logback.filter.MyFilter" /> -->
<!-- 临界值过滤器 trace debug就不打印, info debug error就打印 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
<!--DENY 直接拒绝 都不用看后面的了 -->
<!--accept 符合条件 日志立即被处理 -->
<!--neutral 让下个过滤器来处理 -->
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName cclovezbf-console [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="console2" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="com.example.logback.filter.MyFilter" /> -->
<!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName cclovezbf-console2 [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="console2" />
</root>
<!-- <logger name="org.apache.kafka" level="warn"/>-->
<!-- <logger name="org.apache.kafka.clients.producer.ProducerConfig" level="warn"/>-->
<!-- <logger name="org.apache.kafka.clients.admin.AdminClientConfig" level="warn"/>-->
<!-- <logger name="org.apache.kafka.clients.consumer.ConsumerConfig" level="warn"/>-->
<logger name="com.example.logback" level="info" ></logger>
</configuration>
这里可以看到cosole2 的appender只打印了warn日志
其实这里没有处理好
比如 我们自己有 warn info error 。kafka 也有warn info error
我设置的是 console打印 info warn error(我和kafka的)
console2 打印warn (我和kafka)
里面有很多重复打印的warn,这里只是为了展示filter的作用。
但是想来想去觉得没解决不舒服
自定义一个Filter 解决。
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
public class MyKafkaFilter extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent iLoggingEvent) {
String loggerName = iLoggingEvent.getLoggerName();
Level level = iLoggingEvent.getLevel();
Integer integer = level.toInteger();
//loggername里含有kafka 这里写的比较简单。 并且日志泣别小于等于info的 拒绝打印
if (loggerName.contains("kafka") & (integer - 20000) <= 0) {
return FilterReply.DENY;
}
if (level.isGreaterOrEqual(Level.INFO)) {
return FilterReply.ACCEPT;
}
return FilterReply.DENY;
}
}
这有什么用。比如我们引入了kafka flink 我指向看到flink的日志和我自己的log日志,和kafka相关的任何日志我都不想看到,就可以自定义一个filter