Clojure世界:日志管理——clojure.tools.logging
2023-03-14 22:30:20 时间
处理日志是任何一个产品级的程序都需要仔细处理的模块。在Java中,我们经常使用的是log4j就是一个日志框架。在clojure里,同样有一套日志框架——clojure.tools.logging,它不仅提供了常用的日志输出功能,还屏蔽了Java各种日志框架之间的差异,如slf4j,commons-logging,log4j,java.util.logging等,让你可以透明地使用这些框架来处理日志。
名称:clojure.tools.logging
主页:https://github.com/clojure/tools.logging
依赖:
使用:
常用宏和方法:
1.除了上面例子的info和error宏,还可以包括warn,trace,debug,fatal等常用宏,分别对应相应的日志级别。这些方法会自动判断当前logger的级别是否有效,有效的前提下才会输出日志。也就是说在Java里,你经常需要这样:
最后,info还有个infof的方法,用于输出格式化日志:
2.spy宏,同时输出表达式的form和结果,例如
3.with-logs宏可以在将*out*和*err*流重定向到日志的情况下求值表达式,例如:
4.事务中(dosync中)的日志输出,tools.logging做了特殊处理,默认情况下当且仅当事务成功提交的时候并且日志级别是warn或者info会通过agent异步写入日志。tools.logging定义了一个全局的agent——*logging-agent*。当判断当前是在事务中调用log宏,并且日志级别在集合*tx-agent-levels*内,就会在事务提交成功的时候将日志发送给*logging-agent*异步处理。可以通过*tx-agent-levels*改变使用agent输出日志的级别范围,默认是#{:info :warn}。还可以通过改变*force*变量来强制使用direct或者agent的方式输出日志,*force*可以为:agent或者:direct。
5.默认日志框架的是从classpath查找的,查找的顺序是sl4j,commons-logging,log4j,java.util.logging,找到哪个可用就用哪个。如果你的classpath里存在多个日志框架,如同时存在sl4j和commons-logging,那么如果你希望强制使用commons-logging,可以通过改变*logger-factory*变量来使用:
名称:clojure.tools.logging
主页:https://github.com/clojure/tools.logging
依赖:
[org.clojure/tools.logging "0.2.3"]
<dependency>
<groupId>org.clojure</groupId>
<artifactId>tools.logging</artifactId>
<version>0.2.3</version>
</dependency>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>tools.logging</artifactId>
<version>0.2.3</version>
</dependency>
使用:
(ns example.core
(:use [clojure.tools.logging :only (info error)]))
(defn divide [x y]
(try
(info "dividing" x "by" y)
(/ x y)
(catch Exception ex (error ex "There was an error in calculation"))))
(:use [clojure.tools.logging :only (info error)]))
(defn divide [x y]
(try
(info "dividing" x "by" y)
(/ x y)
(catch Exception ex (error ex "There was an error in calculation"))))
常用宏和方法:
1.除了上面例子的info和error宏,还可以包括warn,trace,debug,fatal等常用宏,分别对应相应的日志级别。这些方法会自动判断当前logger的级别是否有效,有效的前提下才会输出日志。也就是说在Java里,你经常需要这样:
if (logger.isDebugEnabled()) {
logger.debug(x + " plus " + y + " is " + (x + y));
}
在使用 tools.logging的时候是不需要的,因为这些宏帮你做了这个判断。另外,我们在使用log4j的时候需要指定log的namespace,在tools.logging里不需要,默认会取当前的namespace也就是*ns*。logger.debug(x + " plus " + y + " is " + (x + y));
}
最后,info还有个infof的方法,用于输出格式化日志:
(infof "%s is %d years old" "kid" 3)
日志输出:
2012-02-12 20:23:07,394 INFO log: kid is 3 years old
其他方法也有类似的如warnf,debugf等。2.spy宏,同时输出表达式的form和结果,例如
(spy (+1 2))
输出日志
2012-02-12 20:11:47,415 DEBUG log: (+ 1 2)
=> 3
=> 3
3.with-logs宏可以在将*out*和*err*流重定向到日志的情况下求值表达式,例如:
(with-logs *ns* (prn "hello world"))
输出日志:
2012-02-12 20:17:32,592 INFO log: "hello world"
with-logs需要明确指定log-ns,默认out的输出级别是info,而err的级别是error,可以指定输出级别(with-logs [*ns* :info :error] ......)4.事务中(dosync中)的日志输出,tools.logging做了特殊处理,默认情况下当且仅当事务成功提交的时候并且日志级别是warn或者info会通过agent异步写入日志。tools.logging定义了一个全局的agent——*logging-agent*。当判断当前是在事务中调用log宏,并且日志级别在集合*tx-agent-levels*内,就会在事务提交成功的时候将日志发送给*logging-agent*异步处理。可以通过*tx-agent-levels*改变使用agent输出日志的级别范围,默认是#{:info :warn}。还可以通过改变*force*变量来强制使用direct或者agent的方式输出日志,*force*可以为:agent或者:direct。
(binding [*force* :agent]
(log :info "hello world"))
这里特别使用了log宏,需要明确指定日志级别为info。(log :info "hello world"))
5.默认日志框架的是从classpath查找的,查找的顺序是sl4j,commons-logging,log4j,java.util.logging,找到哪个可用就用哪个。如果你的classpath里存在多个日志框架,如同时存在sl4j和commons-logging,那么如果你希望强制使用commons-logging,可以通过改变*logger-factory*变量来使用:
(ns example
(:use [clojure.tools.logging.impl :only [cl-factory]]))
(binding [*logger-factory* (cl-factory)]
(info "hello world"))
*logger-factory*是dynamic变量,可以通过binding改变(前面提到的*force*等变量也一样),如果不希望每次都用binding,而是全局改变,则需要特殊处理:(:use [clojure.tools.logging.impl :only [cl-factory]]))
(binding [*logger-factory* (cl-factory)]
(info "hello world"))
(alter-var-root (var *logger-factory*) (constantly (cl-factory)))
其他logger factory还包括slf4j-factory,log4j-factory,jul-factory。
6.每个日志框架的配置跟使用java没有什么两样,比如你用log4j,就需要在classpath下放置一个log4j.properties等。如果你希望用编程的方式配置,可以使用clj-logging-config。
文章转自庄周梦蝶 ,原文发布时间2012-02-12
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的