版本信息
- Erlang18.3
- 参考Erlang22.2中logger_formatter.erl文件
模板化的日志文件
- 1.设置模板格式
%% 默认的日志模板
-define(DEFAULT_FORMAT_TEMPLATE_HEADER,
[[logger_formatter,header],"\n(",registername,":",pid,":",module,":",line, ")", mfa,":", msg, "\n"]).`
即设置默认的日志模板格式,最后的结构就是:
- 2.代码分析
-type log_event() :: #{
level =>level(), % 日志打印等级
msg => {io:format(),[term()]}, % 日志内容格式
meta=>metadata() % 额外需要的参数
}.
-type metadata() ::{
pid =>pid(), % 日志打印的进程id
gl => pid(), % group_leader,
time => interger(), % 时间戳
mfa =>{module(),atom(),term()},
line => non_neg_integer() % 日志打印的行数
atom() => term() % 其他的信息
}.
-type config() :: {
depath =>pos_integer() | unlimted, % 表明可显示的长度,超过则用 ... 表示
legacy_header => boolean(), % 是否使用默认的头部
max_size =>non_neg_integer(), % 最大长度
single_line => boolean(), % 是否单行显示
template => template() % 自定义模板
}.
-spec format(LogEvent, Config) -> string() when
LogEvent :: log_event(),
Config :: config().
其中logevent参数主要是这是消息打印信息相关的设置,config则用来限制消息打印的格式,长度等信息
Erlang的数据结构类型
- tuple 元组格式
- list 列表格式
- float 浮点型
- integer 整型
- char 字符
- string 字符串
- pid 进程
- refrence() 引用
- atom() 原子
Erlang的输出格式
- ~w
- ~p/~tp
- ~s/~ts
..... 未完
Erlang的数据结构
- record(record_tag{ arg1,arg2})
- maps()
字符编码
- 默认erlang使用的是latin1(可通过io:printable_range()查看)
- 转换为unicode编码:unicode:characters_to_binary()
- 转换为utf8:xmerl_ucs:to_utf8()
清理文本格式
string_p1([]) ->[];
string_p1([$\n|T]) -> string_p1(T); % 换行符
string_p1([$\r|T]) -> string_p1(T); % 回车符
string_p1([$\s|T]) -> string_p1(T); % 空格
string_p1([$\t|T]) -> string_p1(T); %水平制表符
string_p1([$\v|T]) -> string_p1(T); %垂直制表符
string_p1([$\b|T]) -> string_p1(T); %退格
string_p1([$\f|T]) -> string_p1(T); %换页键
string_p1([$\e|T]) -> string_p1(T); %ESC(换码-溢出)
string_p1([$#|T]) -> string_p1(T);
string_p1([H|T]) ->
[H|string_p1(T)].
工作中遇到的问题
- 1.通过format之后,写入文件时无法写入;启动erl设置 +pc unicode
原因:是因为format之后文件格式是latin1,所以不能写入文件;但是,如果是系统的堆栈是可以的,表明系统内部是已经编码为unicode,但如果是代码中的,则编码格式是latin1,需要转码;转码为unicode之后,在werl框中会乱码,需要注意。 - 2.需要将日志发送到央服,但是央服的数据格式是asc码的转换,不能显示成中文字符
原因:unicode格式不能直接保存到数据库中,数据库设置格式是utf-8,所以需要将unicode转码为utf-8
注意:如果存在中文,直接讲format的生成字符串直接进行utf8转码会报错,需要io_lib:format("~ts",[LogInfo])之后才行。 - 3.在远程http写库是,如果是数据库报错,会一直写不进去,后来查明,是因为央服日志会对收到的信息进行检测,如果有mysql相关语句,或者特殊字符,都会失败
注意:不能直接发送数据库的报错,并且对特殊字符进行过滤
测试用例
?ERR("player:~w not skill:~w add skill:~w old:~w new:~w", [111111, [111,222], 584, [1,2,3],[4,5,6]]),
?ERR("玩家 新 ,,,,,,,,"),
?ERR("玩家:~w 不存在的技能:~w 新加技能点:~w 旧:~w 新:~w", [111111, [111,222], 584, [1,2,3],[4,5,6]]),
?DEBUG("玩家:~w 不存在的技能:~w 新加技能点:~w 旧:~w 新:~w", [111111, [111,222], 584, [1,2,3],[4,5,6]]),
?WARNING("玩家:~w 不存在的技能:~w 新加技能点:~w 旧:~w 新:~w", [111111, [111,222], 584, [1,2,3],[4,5,6]]),
?INFO("玩家:~w 不存在的技能:~w 新加技能点:~w 旧:~w 新:~w", [111111, [111,222], 584, [1,2,3],[4,5,6]]),
?ERR("float:~p,tuple = ~p, makeref=~p, list = ~tp, pid = ~p, int=~p ", [1.114, {1,2,3},make_ref(),[1,34,5],self(),123]),
1/0,
throw("test log"),
关于Erl22.2鱼Erl18.3
- 1.Erl22.2做了很多底层的优化,提供了更加丰富的接口类型
- 2.Erl18.3已经有点过时,如果可以,建议升级版本
- 3.虽然老爷子也强调maps的的使用,想要放弃record,但是从实际的开发来看,record也是有他特有的优势,maps也确实好用
总结
- 1.处理问题一定要有条理,才能做到心平气和,更快更稳妥的解决问题
- 2.一定要对系统有个全面的了解,修改彻底,避免漏掉,而造成一些无法预知的错误
- 3.测试!测试!测试!优化!优化!优化!
- 4.一定要搞清楚源码,才能做一些修改,不然会有很多副作用,也要看源码的测试用例,可以加深理解
- 5.碰到陌生的代码,一定要相信会看懂的,时间问题罢了,我看这个源码也是看了有一周左右,才动手修改,做自己的定制
来源:oschina
链接:https://my.oschina.net/gaoxepro/blog/3207779