这里只是比较简单的介绍一下Dropwizard中的log,更详细的信息可以参考Logback和后续配置章节中对log配置的专门的介绍。
一、简介
Dropwizard使用Logback做日志处理,它提供了slf4j的实现,甚至还把java.util.logging
,Log4j
, Apache Commons Logging
都指向了Logback。(原话:and even routes all java.util.logging, Log4j, and Apache Commons Logging usage through Logback.
)
slf4j提供五种日志级别
ERROR
: 错误,打印错误日志并不代表app挂了,通常在写代码的时候,我习惯在catch
块中或者其他业务出错的地方,使用这个级别打印日志。
WARN
:可能对应用有害的高精
INFO
:主要显示app功能进展的信息。通常业务正常进度的日志,我也会使用这个级别。
DEBUG
: 比INFO
更细一点的日志,更多是用再DEBUG
程序的时候使用,release版本都会过滤掉这个级别。
TRACE
: 比DEBUG
更细一点的日志,没用过。
三步实现去掉logback
,使用别的日志:
-
pom
中去掉引用
io.dropwizard
dropwizard-core
{$dropwizard.version}
ch.qos.logback
logback-classic
ch.qos.logback
logback-access
org.slf4j
log4j-over-slf4j
- 配置文件中去掉
logback
的配置
server:
type: simple
applicationContextPath: /application
adminContextPath: /admin
requestLog:
type: external
logging:
type: external
- 在
Application
中重写log方法
public class ExampleApplication extends Application {
@Override
protected void bootstrapLogging() {
}
}
二、Log Format 格式化日志
Dropwizard的日志格式化的目标有三:
Be human readable.
Be machine parsable.
Be easy for sleepy ops folks to figure out why things are pear-shaped at 3:30AM using standard UNIXy tools liketail
andgrep
也就是程序员可读性,机器可解析性。第三点说的是提供类似tail
和grep
的命令差错,这一点我不是很明白,我觉得大部分的日志文件都可以支持这种方式吧。
注意点:
- 所有的时间都是UTC的并且是以ISO 8601规范格式化。
- 可以使用
grep
筛选日志级别、类、以及完整的一次堆栈和附带的日志消息
tail -f dw.log | grep '^WARN'
tail -f dw.log | grep 'com.example.dw.Thing'
tail -f dw.log | grep -B 1 '^\!'
- The ! prefix does not apply to syslog appenders, as stack traces are sent separately from the main message. Instead, t is used (this is the default value of the SyslogAppender that comes with Logback). This can be configured with the stackTracePrefix option when defining your appender.(由于堆栈信息和主消息是分开发送的,所以系统日志的
appenders
,!
不能作为开头,要用t
,在你定义appenders
的时候,可以使用stackTracePrefix
配置这个问题)
三、日志配置
在application.properties
中我们可以配置日志的总级别,然后为不同类型、不同包名的日志,根据需要重写他们的日志级别、日志格式、日志文件等。
# Logging settings.
logging:
# The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL.
level: INFO
# Logger-specific levels.
loggers:
# Overrides the level of com.example.dw.Thing and sets it to DEBUG.
"com.example.dw.Thing": DEBUG
# Enables the SQL query log and redirect it to a separate file
"org.hibernate.SQL":
level: DEBUG
# This line stops org.hibernate.SQL (or anything under it) from using the root logger
additive: false
appenders:
- type: file
currentLogFilename: ./logs/example-sql.log
archivedLogFilenamePattern: ./logs/example-sql-%d.log.gz
archivedFileCount: 5
Console
logging:
appenders:
- type: console
threshold: WARN
target: stderr
File
这里可以根据需要配置日志的分割方式。可以按时间等。比如下面的例子,如果文件格式为./logs/example-%d.log.gz
事默认以天分割并压缩,如果在d
后边加上时间格式,它就会根据你规定的格式去分割打包。
logging:
appenders:
- type: file
# The file to which current statements will be logged.
currentLogFilename: ./logs/example.log
# When the log file rotates, the archived log will be renamed to this and gzipped. The
# %d is replaced with the previous day (yyyy-MM-dd). Custom rolling windows can be created
# by passing a SimpleDateFormat-compatible format as an argument: "%d{yyyy-MM-dd-hh}".
archivedLogFilenamePattern: ./logs/example-%d.log.gz
# The number of archived files to keep.
archivedFileCount: 5
# The timezone used to format dates. HINT: USE THE DEFAULT, UTC.
timeZone: UTC
Syslog
Finally, Dropwizard can also log statements to syslog.
Note
Because Java doesn’t use the native syslog bindings, your syslog server must have an open network socket.
logging:
appenders:
- type: syslog
# The hostname of the syslog server to which statements will be sent.
# N.B.: If this is the local host, the local syslog instance will need to be configured to
# listen on an inet socket, not just a Unix socket.
host: localhost
# The syslog facility to which statements will be sent.
facility: local0
平时我们在配置日志的时候,实际上是会根据需要混合不同类型日志的配置:
logging:
# Permit DEBUG, INFO, WARN and ERROR messages to be logged by appenders.
level: DEBUG
appenders:
# Log warnings and errors to stderr
- type: console
threshold: WARN
target: stderr
# Log info, warnings and errors to our apps' main log.
# Rolled over daily and retained for 5 days.
- type: file
threshold: INFO
currentLogFilename: ./logs/example.log
archivedLogFilenamePattern: ./logs/example-%d.log.gz
archivedFileCount: 5
# Log debug messages, info, warnings and errors to our apps' debug log.
# Rolled over hourly and retained for 6 hours
- type: file
threshold: DEBUG
currentLogFilename: ./logs/debug.log
archivedLogFilenamePattern: ./logs/debug-%d{yyyy-MM-dd-hh}.log.gz
archivedFileCount: 6
注:在配置章节会有专门的大篇幅的讲解日志配置。
四、通过http请求修改日志配置
在Task
章节我们有提过,Dropwizard默认提供了log-level
的task,这样我们就可以通过HTTP
请求多日志做一些操作,比如修改日志的等级:
curl -X POST -d "logger=com.example.helloworld&level=INFO" http://localhost:8081/tasks/log-level
五、日志过滤器
除了按照日志级别配置日志外,有时候我们还需要对同一级别不同类型的日志进行过滤。日志过滤对普通日志和HTTP请求日志都有效。有时候我们需要过滤掉一些请求的日志,比如说:只打印请求body较大的,只打印请求响应较慢的,只打印请求失败的,不打印URL里面包含敏感信息的。下面我们举例过滤掉/secret
请求的日志。
@JsonTypeName("secret-filter-factory")
public class SecretFilterFactory implements FilterFactory {
@Override
public Filter build() {
return new Filter() {
@Override
public FilterReply decide(IAccessEvent event) {
if (event.getRequestURI().equals("/secret")) {
return FilterReply.DENY;
} else {
return FilterReply.NEUTRAL;
}
}
};
}
}
然后在日志中加上:
server:
requestLog:
appenders:
- type: console
filterFactories:
- type: secret-filter-factory
最后:
The last step is to add our class (in this case
com.example.SecretFilterFactory
) toMETA-INF/services/io.dropwizard.logging.filter.FilterFactory
in our resources folder.