haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。
erlang本身提供了日志管理,但这与其它语言中常见的log4xxx的日志框架很不同:
日志文件是二进制的,查看起来很不方便;
每条日志跨多行文本,也不方便查找和分析。
总之,这自带的日志系统让用惯log4xxx系列的人用起来很不习惯。后来陆续有log4erl这样的应用,lager算是后来者,不过在性能等方面有独到之处,这是因为它使用parse_transformation机制的原因。
一、lager使用的步骤
直接在代码中用lager:debug, lager:info, lager:warning, lager:error系列函数输出日志就行了。这些函数的参数和io:format基本一样,除了一点,日志字符串结尾不用自己手动加回车。
麻烦的是其它工作,包括编译方式、参数配置,lager应用的启动,不过好在都是一次性的:
1. 编译选项 parse_transformation
最笨的办法是在每个模块的开头使用编译指令
-compile([{parse_transform, lager_transform}]).
所有要使用lager的模块都加上这个指令代码无疑是很烦的事情,好在erlang编译器提供了一个选项,
见compile。
当然如果用rebar的话更加简单,只要在rebar.config配置文件中添加:
{erl_opts, [
{parse_transform, lager_transform}]}.
这样的编译就会自动织入lager代码,不需要给每个模块添加编译指令了。
2. lager应用的启动
这包括它依赖的两个erlang的lib应用:syntax_tools和compiler,一般用发布工具发布时会自动包含进来。但是开发中我们一般比较少直接使用发布工具,所以erl启动时lager不会也随之自动启动,lager本身作为应用要预先启动,有很多办法:
1) 最直观的,我们当然可以用 application:start(lager) 手工启动lager应用。但是lager还依赖compiler和syntax_tools,这两个应用要先启动,lager才能正常启动。虽然在lager应用的lager.app文件有在applications属性中指出这些依赖,但是这似乎只对发布有效,application:start/1不会坚持这些依赖并启动这些依赖。
2) 这里的问题是application:start/1函数只负责启动指定的application,如果它依赖的其它applications没有启动,则启动过程失败,该函数返回值:{error, {not_started, DepApp}}。
如果erlang能提供一个启动应用及其依赖的方法就好了。
后来,lager模块为此提供了一个专门的start方法,负责启动它自己依赖的这两个应用:
lager:start().
下面是它的源代码,有时候我们自己写应用直接的互相依赖可以借鉴一下:
-export([start/0]).
start() -> start(lager).
start(App) ->
start_ok(App, application:start(App, permanent)).
start_ok(_App, ok) -> ok;
start_ok(_App, {error, {already_started, _App}}) -> ok;
start_ok(App, {error, {not_started, Dep}}) ->
ok = start(Dep),
start(App);
start_ok(App, {error, Reason}) ->
erlang:error({app_start_failed, App, Reason}).
3) 如果是用工具发布的应用系统,例如rebar发布配置文件(reltool.config)中,在'rel' 列出的应用里增加lager,这样,发布后lager会自动在系统初始化时启动,如下
{sys, [
{lib_dirs, ["../../", "../deps/"]},
{rel, "rts", "1",
[
kernel,
stdlib,
sasl,
lager,
rts
]},
3. lager的配置
可以在发布的app.config(后来rebar改名成sys.config)中配置。配置参数很多,日志输出级别,日志输出方式,如果是以文件的方式,又包括日志文件名,日志文件大小,循环日志文件等等。列出这些配置参数很枯燥,还是直接看手册。
二、其它技巧
1.日志的颜色区分
当然你也可以用unix管道grep出你关心的日志,不过如果是需要参照出错附近的日志时。有时候直接在控制台上看日志更糙猛快点。
这种情况下如果能在一大堆日志中用不同颜色标出不同等级的日志信息无疑是很节省眼力的。
lager提供了这种支持,但不幸的是erlang是从R16版开始才官方支持,R15B版本erlang控制台并不直接支持ANSI ASCII字符。这需要修改erlang源代码重新编译,不过还好这不是什么难事:
修改erts/emulator/drivers/unix/ttsl_drv.c源代码(R15B03版)第915行开始的几行代码。
将如下代码
} else if (ch == '\n' || ch == '\r') {
write_buf(lbuf + buffpos, lpos - buffpos);
outc('\r');
if (ch == '\n')
outc('\n');
改成:
} else if (ch == '\e' || ch == '\n' || ch == '\r') {
write_buf(lbuf + buffpos, lpos - buffpos);
if (ch == '\e') {
outc('\e');
} else {
outc('\r');
if (ch == '\n')
outc('\n');
}
重新编译的Erlang/OTP R15B就能支持彩色ASCII的控制台了。
最后修改lager的配置(lager.app.src),colored设为true。现在可以在erlang控制台上看到各种颜色的日志信息了,debug没有变化,info是亮白色,warning是黄色,error是红色,等等
这些颜色当然也是可以自定义的,来自用term上bbs时代,或者了解ASCII字符艺术的同学对此应该并不陌生。
参考:Support ANSI in the console
http://erlang.org/pipermail/erlang-patches/2012-November/003127.html
三、常见问题和陷阱
lager:info/debug/warning/error函数未定义错误
当运行时出现有如下片断的错误:
... {'EXIT',{undef,[{lager,info, ...
(其中的info可以是 debug, warning等)
这是因为编译时的parse_transform没有“正确”设置的缘故,原因很多,以下是可能碰到的两个陷阱:
1. 只是修改配置信息(如修改rebar.config文件,加入{erl_opts, [{parse_transform, lager_transform}]} ),然后rebar compile是不会自动重新编译之前已有的编译好的代码的,必须清空已编译好的代码重新编译才行:rebar clean compile
原因其实也简单:rebar compile只会根据源代码的时间戳判断是否有必要重新编译,而编译配置选项的修改显然与之无关。
2. 对于rebar.config里的erl_opts配置,顺序很重要,{parse_transform, lager_transform} 必须在其他erl_opts的前面。
分享到:
相关推荐
SEW 550钢是一种适用于大型开放式锻造构件的材料,尤其是在较高温度下使用时。SEW 550钢锻件在化学成分和力学性能上均有特定的要求,适用于热处理或正火状态。该说明书强调了适用范围、材料的命名及相关的德国工业...
在奇幻文学领域,阿瓦隆是一个被广泛使用的设定,许多作家都以它为灵感源泉创作自己的故事。《迷雾之岛》通过细腻的叙述,不仅让读者沉浸在一个充满魔力的世界,还探讨了信仰、权力、爱情与背叛等主题,展现了人性的...
4. **滤波器和分析模块**:通过滤波器模块来提取电压信号中的闪变成分,然后使用分析模块(如傅立叶变换、功率谱分析等)来量化闪变的强度和频率分布。 5. **显示和记录模块**:实时显示电压波形,以便观察闪变现象...
在这种情况下,问题进一步细化为“Could not materialize checkpoint”,即无法实现检查点,原因是“Size of the state is larger than the maximum permitted memory-backed state”。这意味着在尝试保存的状态超过...
【标题】"yaffs_source_util_larger_page_nand.tar.gz_page_yaffs2" 提供的是一款针对YAFFS2文件系统优化的源码工具,特别设计来支持2K大小页面的NAND闪存设备。 【描述】"yaffs2 源码工具支持大页下载,2Kpage" ...
"larger5ab"可能是一个特定版本的标识或者项目的内部标记,它可能代表了固件的一个改进或优化版本。 压缩包内的STM32-PLC-FX1N-master目录很可能包含了整个项目的所有源代码、编译脚本、配置文件、文档以及可能的...
标题 "bluebutton-data-pipeline-sampledata-0.1.0-cbbd-149-benchmark-larger-samples-1.zip" 暗示我们正在处理一个与数据处理流水线相关的开源项目。这个项目的版本号是0.1.0,其中包含了特定的基准测试和较大规模...
本程序为卡尔曼滤波的一个简单小程序,使用者可直接使用。
本程序使用STRUTS2.0+SPRING2.5+HIBERNATE3.2框架编写的网站后台管理系统(无前台)
myeclise10 svn: E210004: Number is larger than maximum 解决方案 专门解决win7 64位操作系统 下svn插件问题。 下载文件包括: site-1.8.22.zip --->svn离线安装包 Slik-Subversion-1.8.9-x64 --->问题修复必选...
“SQL”是数据查询和操作的主要工具,对于大数据处理,我们可以使用SQL-on-Hadoop框架,如Presto、Spark SQL等,它们允许我们在Hadoop集群上执行SQL查询。此外,SQL的聚合函数和子查询功能在数据统计分析中扮演着...
- 使用Windbg等调试工具定期分析线程状态和内存使用情况,以便及时发现问题。 - 考虑调整GC策略,例如,使用不同类型的垃圾收集器,或者优化内存分配和释放的方式,减少GC压力。 6. **底层知识的重要性** - 分析...
3. **解密过程**:解密时使用私钥,与加密类似,只是将`Cipher.ENCRYPT_MODE`替换为`Cipher.DECRYPT_MODE`,并使用私钥初始化`Cipher`对象。 ```java cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] ...
5. **代码复用性**:如果`larger_of`函数在程序中多次使用,可以考虑将其封装进一个独立的头文件中,便于在其他模块中重复使用。 #### 结论 通过C语言比较两个整数的大小是编程学习中的基本概念,它不仅涉及基本的...
在GIS领域,尤其是在使用ArcGIS软件中的ArcMap组件时,数据的拓扑错误检查是一项至关重要的任务。拓扑错误指的是地理空间数据中存在的不一致或不正确的几何关系,这些错误可能包括但不限于悬挂节点、未闭合的多边形...
4. **代码实现**:在描述中提到的“IOS-RSA”压缩包中,应该包含了完整的Objective-C或Swift代码示例,用于演示如何在实际项目中使用RSA加密解密。这些代码可能包括密钥生成、公钥加密和私钥解密的关键函数,以及...
8. **比较和比例**:在比较或比例中,如“twice as many”,“three times larger”,数字通常用单词形式。 9. **约数和倍数**:表示大约或近似的数字,如“about three”,“several dozen”,可以用单词形式。 ...
如果源码是用Java编写的,那么可能利用了JavaFX或Swing来构建GUI,而Python则可能使用tkinter或者更现代的库如PyQt或wxPython。 在分析源码时,首先需要了解所使用的编程语言及其语法。例如,如果源码是C++,那么你...
在使用Qt进行串行通信开发时,可能会遇到一个与Qt Serialbus模块相关的错误,提示“dropping older ADU fragments due to larger than 3.5 char”。这个错误通常出现在处理CAN(Controller Area Network)协议的数据...