共计 5043 个字符,预计需要花费 13 分钟才能阅读完成。
前言
三位学弟实现前台编写后,须要进行集成测试,然而这个时候我却因为无奈实现日志零碎犯了难。最初本人查来查去发现潘老师居然有这个博客,由此是让本人大略了解了这个实现过程。
日志零碎形容
咱们心愿在以后零碎在产生 warning
或者 error
后,咱们可能及时的获取到错误信息,以便进行及时无效的解决。日志零碎应运而生,他的次要性能是记录每个零碎产生指定 level
的状况。
我的尝试过程
首先去查:如何获取日志
,抉择下图圈中的(第一个是广告,能够认为他就是第一个)。
理解 log4j2
Log4j
是 Apache
的一个开源我的项目,通过应用 Log4j
,咱们能够管制 日志信息
输送的目的地是 控制台
、 文件
、GUI 组件
,甚至是 套接口服务器
、NT 的事件记录器、UNIX Syslog 守护过程等;咱们也能够管制每一条日志的 输入格局
;通过定义每一条日志信息的 级别
,咱们可能更加粗疏地管制日志的生成过程。最令人感兴趣的就是,这些能够通过一个 配置文件
来灵便地进行配置,而不须要批改利用的代码。log4j2
则是 log4j
的升级版。
log4j2 应用:增加依赖
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
而后我就:
ERROR in ch.qos.logback.core.joran.spi.Interpreter@3:16 - no applicable action for [Appenders], current ElementPath is [[Configuration][Appenders]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:61 - no applicable action for [Console], current ElementPath is [[Configuration][Appenders][Console]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@6:80 - no applicable action for [PatternLayout], current ElementPath is [[Configuration][Appenders][Console][PatternLayout]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@9:14 - no applicable action for [Loggers], current ElementPath is [[Configuration][Loggers]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@10:29 - no applicable action for [Root], current ElementPath is [[Configuration][Loggers][Root]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@11:49 - no applicable action for [AppenderRef], current ElementPath is [[Configuration][Loggers][Root][AppenderRef]]
查了之后发现说须要把 Springboot
内置的 lockBack
删了,删了之后又来了其余的问题:JsonView
的依赖也被删了。
目前来看这条路我就走死了。如果有同样问题能够参考:Logback configuration error detected 的终极解决方案
我的项目日志零碎实现
具体代码实现和测试能够参考文章:spring-boot 下应用 LogBack,应用 HTTP 协定将日志推送到日志服务器
1. 增加依赖:
第一个依赖是
<!--http log-->
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-loggly</artifactId>
<version>0.1.5</version>
</dependency>
<!--log to json-->
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId>
<version>0.1.5</version>
</dependency>
<!--log to json-->
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-json-classic</artifactId>
<version>0.1.5</version>
</dependency>
配置lockback
: 新建 lockback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 启用 debug 模式后,将在 `spring-boot 大 LOG` 上方打印中 logBack 的配置信息 -->
<configuration debug="true">
<!-- 蕴含配置文件 org/springframework/boot/logging/logback/defaults.xml-->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<!-- 引入第三方 appender, 起名为 http-->
<appender name="HTTP" class="ch.qos.logback.ext.loggly.LogglyAppender">
<!-- 申请的地址 -->
<endpointUrl>http://localhost:8081/log</endpointUrl>
</appender>
<!-- 定义日志等级 -->
<root level="WARNING">
<!-- 启用第三个 appender 为 HTTP-->
<appender-ref ref="HTTP" />
</root>
</configuration>
咱们看一下 LogglyAppender
内容:
/**
* 事件传入
*/
protected void append(E var1) {String var2 = this.layout.doLayout(var1);
// 调用办法向 loggly 传输的办法
this.postToLoggly(var2);
}
private void postToLoggly(String var1) {
try {
assert this.endpointUrl != null;
// endpointUrl 为 xml 配置文件的传入属性值
URL var2 = new URL(this.endpointUrl);
HttpURLConnection var3;
if (this.proxy == null) {
// 与日志零碎连贯,例 localhost:8005/api/batchSave
var3 = (HttpURLConnection)var2.openConnection();} else {var3 = (HttpURLConnection)var2.openConnection(this.proxy);
}
var3.setRequestMethod("POST");
var3.setDoOutput(true);
var3.addRequestProperty("Content-Type", this.layout.getContentType());
var3.connect();
this.sendAndClose(var1, var3.getOutputStream());
var3.disconnect();
int var4 = var3.getResponseCode();
if (var4 != 200) {String var5 = this.readResponseBody(var3.getInputStream());
this.addError("Loggly post failed (HTTP" + var4 + "). Response body:\n" + var5);
}
} catch (IOException var6) {this.addError("IOException while attempting to communicate with Loggly", var6);
}
每条日志都会发送一次,这无疑给零碎减少了很大的难度,接下来改成本人的 logglyAppender,进而实现多少条或者多久发送一次。
private void postToLoggly(final String event) {events.add(event);
Calendar calendar = Calendar.getInstance();
// 日志条数够 100 条或者间隔上次发送够 6 分钟,则发送到日志零碎批量保留
if (events.size() >= 100 || (calendar.getTimeInMillis() - lastSendTime.getTimeInMillis() >= 6000)) {
try {
lastSendTime = calendar;
List<String> sendEvents = events;
events = new ArrayList<>();
assert this.endpointUrl != null;
URL endpoint = new URL(this.endpointUrl);
final HttpURLConnection connection;
if (this.proxy == null) {connection = (HttpURLConnection) endpoint.openConnection();} else {connection = (HttpURLConnection) endpoint.openConnection(this.proxy);
}
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.addRequestProperty("Content-Type", this.layout.getContentType());
connection.connect();
this.sendAndClose(sendEvents, connection.getOutputStream());
connection.disconnect();
final int responseCode = connection.getResponseCode();
if (responseCode != 200) {final String message = this.readResponseBody(connection.getInputStream());
this.addError("Loggly post failed (HTTP" + responseCode + "). Response body:\n" + message);
}
} catch (final IOException e) {this.addError("IOException while attempting to communicate with Loggly", e);
}
}
}
有个疑难:他为啥有时候过 5 分钟主动申请,有时又没反馈:
总结
教训比拟不足,在找团队我的项目应用的库始终没找到,本人找的也不会用,还是须要一直的积攒教训。最初也是感激团队,因为有了团队的资源能力让本人看的更远。