log
常听说的日志关键词
每个项目都离不开日志,好的日志框架既能帮助分析问题,还能还原用户行为。
SLF4J
Simple Logging Facade for Java(SLF4J)用作各种日志框架(例如 java.util.logging,logback,log4j)的简单外观或抽象,允许最终用户在部署时插入所需的日志框架。 要切换日志框架,只需替换类路径上的 slf4j 绑定。 例如,要从 java.util.logging 切换到 log4j,只需将 slf4j-jdk14-1.8.0-beta2.jar 替换为 slf4j-log4j12-1.8.0-beta2.jar。
因此,slf4j 就是众多日志接口的集合,他不负责具体的日志实现,只在编译时负责寻找合适的日志系统进行绑定.

Log4j2
Apache Log4j 2是对 Log4j 的升级,与 Logback 一样,Log4j2 提供对 SLF4J 的支持,自动重新加载日志配置,并支持高级过滤选项。 它还允许基于 lambda 表达式对日志语句进行延迟评估,为低延迟系统提供异步记录器,并提供无垃圾模式以避免由垃圾收集器操作引起的任何延迟。
Logback
logback 是由 log4j 创始人设计的又一个开源日志组件,作为流行的 log4j 项目的后续版本,从而替代 log4j。
Logback 的体系结构足够通用,以便在不同情况下应用。 目前,logback 分为三个模块:logback-core,logback-classic和logback-access。
- logback-core:模块为其他两个模块的基础。
- logback-classic:模块可以被看做是log4j的改进版本。此外,logback-classic 本身实现了 SLF4J API,因此可以在 logback 和其他日志框架(如 log4j 或 java.util.logging(JUL))之间来回切换。
- logback-access:模块与 Servlet 容器(如 Tomcat 和 Jetty)集成,以提供 HTTP 访问日志功能。
需求和现状
以下说的是普通的web service接口开发场景
日志分类,分别打到info、error、sql开头的三个文件
- 一般的日志都打到info文件里)
- 所有的sql单独打印到一个文件里
- 手动或者自动抛出的异常都打到error文件里,方便监听
区分dev和其他环境
- dev环境能把log打到控制台,不切换窗口查看log
- 非dev环境所有log不打控制台
现状
使用logback作为日志框架的实现,使用了如下配置的xml文件
<appender name="SQLFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/sql-hc.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/sql-hc.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- keep 30 days of history -->
<maxHistory>10</maxHistory>
</rollingPolicy>
<encoder>
<charset>UTF-8</charset>
<pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
</encoder>
</appender>
<logger name="jdbc.sqlonly" level="INFO" additivity="false">
<appender-ref ref="SQLFILE"/>
<appender-ref ref="STDOUT"/>
</logger>
不足
- dev环境输出log多的话,都在控制台会导致cider卡死,无法灵活选择哪些日志打到cider,哪些到文件
- 用户的一个行为被分成几个文件,不易还原业务行为
- 多服务器的情况,日志分散
- log太多,打log的代价,timbre怎么异步?
最新方案
引入新的日志库,解决第一个不足,与logback兼容,log分文件输出(我想更好的方案应该是丢掉logback,在timbre上配置多个appender) 引入timbre库 关于它的版本查看doc
- test
(ns dude)
(require '[clojure.tools.logging :as log])
(require '[taoensso.timbre :as timbre])
(defn test-fn
[]
(log/debug "test ctl debug level")
(log/info "test ctl info")
(timbre/debug "test timbre debug level")
(timbre/info "test timbre info"))
(println "before setting log level")
(test-fn)
(alter-var-root #'timbre/*config* #(assoc %1 :min-level :info))
(println "after setting log level to :info")
(test-fn)
(println "with-level :debug")
(timbre/with-level :debug
(test-fn))
(timbre/set-level! :debug)
(println "after setting log level to :debug")
(test-fn)
(timbre/infof "Hello %s" 123)
(log/infof "Hello %s" 123)
(timbre/swap-config! assoc-in [:appenders :spit] (timbre/spit-appender {:fname "/tmp/timbre.log"}))
(log/infof "Hello %s" 123)
- 最后推荐的配置
(require '[taoensso.timbre :as timbre
:refer [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]])
(defn log-config
"设置timbre的基础日志规则:
系统中有sl4j的日志和timbre的日志, 如果在`project.clj`中引入依赖:
[com.fzakaria/slf4j-timbre \"0.3.21\"], 则sl4j的日志会自动输出到timbre.
如果不引入此依赖, 日志会有两套系统, sl4j的日志会输出到
- `sql-device-sensor`
- `info-device-sensor`
- `error-device-sensor`
1. 函数参数`level`统一设置了log级别 :trace :debug :info :warn :error
指定系统的最低级别的日志输出, appender级别可以比它更高
2. 统一设置了时间输出格式, 使用本地时区 + 时间(时间精确到毫秒)
3. 文件输出统一到`log/trace-rolling.log`, 每天滚动
3. appender分为
- `console` : 控制台输出, 级别设置为`:info`
- `spit` : 文件输出, 每天输出一个, 级别为`:trace`
`spit` 中使用去除了异常的颜色文本输出, 更加可读"
[level]
(timbre/merge-config!
{:level level
;; :ns-blacklist []
:ns-filter {:allow #{"foo" "bar.*"} :deny #{"foo.*.bar.*"}}
:timestamp-opts {:pattern "yy-MM-dd HH:mm:ss:SSS",
:locale :jvm-default,
:timezone (TimeZone/getDefault)}
:appenders {:println (merge (appenders/println-appender )
{:min-level :info})
:spit (merge (rolling/rolling-appender
{:path "log/trace-rolling.log"
:pattern :daily})
{:min-level :trace
;; :async? true
:output-fn (partial timbre/default-output-fn {:stacktrace-fonts {}})})}}))
(log-config :debug)
注意:
引入[com.fzakaria/slf4j-timbre "0.3.21"]以后, 则sl4j的日志会自动输出到timbre,因此在project里不需要引入这个依赖。
其他
写半天发现公司blog里已经有了CLOJURE中的LOG
视频中最后时间关系没有跑出来ulog的context页面。timber的最新版本5.0也加入了context的,怎么使用后续补充。