erlang日志的一些思考

编程

版本信息

  • Erlang18.3
  • 参考Erlang22.2中logger_formatter.erl文件

模板化的日志文件

  • 1.设置模板格式

%% 默认的日志模板

-define(DEFAULT_FORMAT_TEMPLATE_HEADER,

[[logger_formatter,header],"

(",registername,":",pid,":",module,":",line, ")", mfa,":", msg, "

"]).`

即设置默认的日志模板格式,最后的结构就是:

  • 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([$

|T]) -> string_p1(T); % 换行符

string_p1([$|T]) -> string_p1(T); % 回车符

string_p1([$s|T]) -> string_p1(T); % 空格

string_p1([$ |T]) -> string_p1(T); %水平制表符

string_p1([$v|T]) -> string_p1(T); %垂直制表符

string_p1([$|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.碰到陌生的代码,一定要相信会看懂的,时间问题罢了,我看这个源码也是看了有一周左右,才动手修改,做自己的定制

以上是 erlang日志的一些思考 的全部内容, 来源链接: utcz.com/z/514602.html

回到顶部