Selaa lähdekoodia

ft: 代码格式化

master
SisMaker 4 vuotta sitten
vanhempi
commit
33a9ce75e3
8 muutettua tiedostoa jossa 89 lisäystä ja 103 poistoa
  1. +47
    -59
      README.md
  2. +1
    -1
      include/eRum.hrl
  3. +23
    -23
      include/rumDef.hrl
  4. +8
    -8
      src/backend/rumBkdFile.erl
  5. +1
    -1
      src/crashLog/rumCrashLog.erl
  6. +2
    -2
      src/eRum1.erl
  7. +2
    -2
      src/utils/rumStdlib.erl
  8. +5
    -7
      进度.md

+ 47
- 59
README.md Näytä tiedosto

@ -23,20 +23,25 @@ eRum is a Erlang logger. 基于lager3.9.0 rewrite
使用
-----
在应用程序中使用eRum,需要将其定义为rebar dep,或者使用其他方法将其包含在Erlang的dep路径中。然后添加下面的编译选项:
```erlang
{parse_transform, rumTransform}
```
或者,你可以将它添加到你希望编译的模块中,并启用日志记录:
```erlang
-compile([{parse_transform, rumTransform}]).
```
在记录任何消息之前,您需要启动eRum应用程序。eRum模块的start函数负责启动 加载并启动eRum需要的任何依赖项
```erlang
eRum:start().
```
You can also start eRum on startup with a switch to `erl`:
```erlang
erl -pa path/to/eRum/ebin -s eRum
```
@ -47,6 +52,7 @@ erl -pa path/to/eRum/ebin -s eRum
eRum:error("Some message")
eRum:warning("Some message with a term: ~p", [Term])
```
一般形式是`eRum:Severity()`,其中`Severity`是上面提到的日志级别之一。
配置选项
@ -66,27 +72,29 @@ eRum:warning("Some message with a term: ~p", [Term])
]}.
```
每个后端可用的配置选项都列在它们的模块文档中。
接受器(Sinks)
-----
eRum传统上支持名为`eRumEmm`的单一接收器(sink)(实现为`gen_emm`管理器),所有后端都连接到该接收器。
eRum现在支持额外的接收器(sink);每个接收器(sink)可以有不同的 sync/async 消息阈值和不同的后端。
eRum传统上支持名为`eRumEmm`的单一接收器(sink)(实现为`gen_emm`管理器),所有后端都连接到该接收器。 eRum现在支持额外的接收器(sink);每个接收器(sink)可以有不同的 sync/async
消息阈值和不同的后端。
### 接收器的配置
要使用多个接收器(超出lager和lager_event的内置接收器),您需要:
1. 设置rebar.config
2. 在app.config中配置后端
#### 名字
每个接收器都有两个名称:一个原子类似于模块名用作发送消息,而该原子后面附加`_lager_event`后面附加用于后端配置。
这反映了旧的行为:lager:info,critical或debug等)是一种将消息发送到名为`lager_event`的接收器。
现在开发人员可以调用`audit:info`或`myCompanyName:debug`只要对应的`audit_lager_event`或`myCompanyName_lager_event`接收器已配置。
这反映了旧的行为:lager:info,critical或debug等)是一种将消息发送到名为`lager_event`的接收器。 现在开发人员可以调用`audit:info`或`myCompanyName:debug`
只要对应的`audit_lager_event`或`myCompanyName_lager_event`接收器已配置。
#### rebar.config
include a list of sink names (without the `_lager_event` suffix) in `erl_opts`:
`{lager_extra_sinks, [audit]}`
@ -138,18 +146,13 @@ exports `format(#lager_log_message{},Config#any())`. It is specified as part of
包括lager_default_formatter。这使用类似于Erlang的iolist的结构(称为“ semi-iolist”)为日志消息提供了一种通用的默认格式 :
配置中的任何传统iolist元素均按原样打印。
配置中的原子被视为较大元数据的占位符,并从日志消息中提取。
占位符date,time,message,sev并severity会一直存在。
sev是缩写的严重性,它被解释为严重性级别的大写单字母编码(例如'debug'-> $D)
占位符pid,file,line,module,function,和node 永远如果使用解析变换存在。
application如果使用解析转换,则占位符可能存在。它取决于查找应用程序app.src文件。
如果使用错误记录器集成,则占位符pid 将始终存在并且占位符name可能存在。
应用程序可以定义自己的元数据占位符。
元组{atom(), semi-iolist()}允许原子占位符的后备。如果找不到由原子表示的值,则将解释半iolist。
一个元组{atom(), semi-iolist(), semi-iolist()}代表一个条件运算符:如果可以找到原子占位符的值,则将输出第一个半iolist。否则,将使用第二个。
元组{pterm, atom()}将尝试从 OTP 21.2中添加的persistent_term功能中查找指定原子的值 。默认值为""。如果找不到密钥或在OTP 21之前的OTP版本中指定了此格式术语,则将使用默认值。
元组{pterm, atom(), semi-iolist()}将尝试从OTP 21.2中添加的persistent_term功能中查找指定原子的值。默认值为指定的semi-iolist()。如果找不到密钥,或者在OTP 21之前的OTP版本中指定了此格式术语,则将使用默认值。
配置中的任何传统iolist元素均按原样打印。 配置中的原子被视为较大元数据的占位符,并从日志消息中提取。 占位符date,time,message,sev并severity会一直存在。
sev是缩写的严重性,它被解释为严重性级别的大写单字母编码(例如'debug'-> $D) 占位符pid,file,line,module,function,和node 永远如果使用解析变换存在。
application如果使用解析转换,则占位符可能存在。它取决于查找应用程序app.src文件。 如果使用错误记录器集成,则占位符pid 将始终存在并且占位符name可能存在。 应用程序可以定义自己的元数据占位符。 元组{atom(),
semi-iolist()}允许原子占位符的后备。如果找不到由原子表示的值,则将解释半iolist。 一个元组{atom(), semi-iolist(), semi-iolist()
}代表一个条件运算符:如果可以找到原子占位符的值,则将输出第一个半iolist。否则,将使用第二个。 元组{pterm, atom()}将尝试从 OTP 21.2中添加的persistent_term功能中查找指定原子的值 。默认值为""
。如果找不到密钥或在OTP 21之前的OTP版本中指定了此格式术语,则将使用默认值。 元组{pterm, atom(), semi-iolist()}将尝试从OTP
21.2中添加的persistent_term功能中查找指定原子的值。默认值为指定的semi-iolist()。如果找不到密钥,或者在OTP 21之前的OTP版本中指定了此格式术语,则将使用默认值。
Examples:
@ -246,10 +249,10 @@ and for sinks:
```
### 接收器(Sink) Killer
在某些高容量情况下,最好丢弃所有待处理的日志消息,而不是让它们随着时间流失。
如果您愿意,可以选择使用水槽杀手来减轻负载。在此操作模式下,如果gen_event邮箱超过可配置的高水位线,则在可配置的冷却时间后,水槽将被杀死并重新安装。
您可以使用以下配置指令来配置此行为:
如果您愿意,可以选择使用水槽杀手来减轻负载。在此操作模式下,如果gen_event邮箱超过可配置的高水位线,则在可配置的冷却时间后,水槽将被杀死并重新安装。 您可以使用以下配置指令来配置此行为:
```erlang
{killerHwm, 1000},
@ -263,8 +266,8 @@ and for sinks:
--------
不安全的代码路径会绕过普通的啤酒格式代码,并使用与OTP中的error_logger相同的代码。这可以稍微提高您的日志记录代码的速度(在基准测试期间,我们测得的改进幅度为0.5-1.3%;其他报告的改进则更好。)
这是一个危险的功能。它不会保护您免受大型日志消息的侵害-大型消息可能会杀死您的应用程序,甚至由于内存耗尽而导致Erlang VM死机,因为在故障级联中反复复制大量术语。我们强烈建议此代码路径仅用于上限大小约为500字节的有边界的日志消息。
如果日志消息有可能超过该限制,则应使用常规的更大的消息格式化代码,该代码将提供适当的大小限制并防止内存耗尽。
如果要格式化不安全的日志消息,则可以使用严重性级别(照常),然后使用_unsafe。这是一个例子:
如果日志消息有可能超过该限制,则应使用常规的更大的消息格式化代码,该代码将提供适当的大小限制并防止内存耗尽。 如果要格式化不安全的日志消息,则可以使用严重性级别(照常),然后使用_unsafe。这是一个例子:
```erlang
lager:info_unsafe("The quick brown ~s jumped over the lazy ~s", ["fox", "dog"]).
```
@ -465,25 +468,22 @@ lager:trace_file("logs/example.com.error", [{vhost, "example.com"}], error)
lager:md([{zone, forbidden}])
```
请注意,lager:md将仅接受由原子键控的键/值对的列表。
您也可以省略最后一个参数,日志级别默认为 debug。
跟踪到控制台是类似的:
请注意,lager:md将仅接受由原子键控的键/值对的列表。 您也可以省略最后一个参数,日志级别默认为 debug。 跟踪到控制台是类似的:
```erlang
lager:trace_console([{request, 117}])
```
在上面的示例中,省略了日志级别,但是如果需要,可以将其指定为第二个参数。
您还可以在过滤器中指定多个表达式,或将*原子用作通配符以匹配具有该属性的任何消息,而不管其值如何。您也可以使用特殊值!来表示,仅在不存在此键的情况下才选择。
在上面的示例中,省略了日志级别,但是如果需要,可以将其指定为第二个参数。 您还可以在过滤器中指定多个表达式,或将*原子用作通配符以匹配具有该属性的任何消息,而不管其值如何。您也可以使用特殊值!来表示,仅在不存在此键的情况下才选择。
还支持跟踪到现有日志文件(但请参阅下面的“多接收器支持”):
```erlang
lager:trace_file("log/error.log", [{module, mymodule}, {function, myfunction}], warning)
```
要查看活动的日志后端和跟踪,可以使用该lager:status() 功能。要清除所有活动迹线,可以使用lager:clear_all_traces()。
要删除特定跟踪,请在创建跟踪时存储该跟踪的句柄,然后将其传递给lager:stop_trace/1:
to `lager:stop_trace/1`:
要删除特定跟踪,请在创建跟踪时存储该跟踪的句柄,然后将其传递给lager:stop_trace/1: to `lager:stop_trace/1`:
```erlang
{ok, Trace} = lager:trace_file("log/error.log", [{module, mymodule}]),
@ -498,6 +498,7 @@ lager:trace_console([{pid, "<0.410.0>"}])
```
### 过滤表达式
从更大的3.3.1版本开始,您还可以在跟踪第二个元素是比较运算符的地方使用3元组。当前支持的比较运算符为:
* `<` - less than
@ -520,25 +521,26 @@ Using `=` is equivalent to the 2-tuple form.
```erlang
lager:trace_console([{all, [{request, '>', 117}, {request, '<', 120}]}])
```
any在过滤器之间具有“或样式”逻辑评估的效果;all 表示过滤器之间的“ AND样式”逻辑评估。这些合成过滤器期望附加过滤器表达式的列表作为它们的值。
### 空过滤器
该null滤波器具有特殊的意义。过滤器{null, false}充当黑洞;什么都没有通过。筛选器{null, true}意味着 一切都会通过。null过滤器的其他任何值均无效,将被拒绝。
### 支持多个接收器
如果使用多个接收器,则应注意跟踪的限制。
跟踪特定于接收器,可以通过跟踪过滤器进行指定:
如果使用多个接收器,则应注意跟踪的限制。 跟踪特定于接收器,可以通过跟踪过滤器进行指定:
```erlang
lager:trace_file("log/security.log", [{sink, audit_event}, {function, myfunction}], warning)
```
如果未指定接收器,则将使用默认的更大接收器。
这有两个后果:
跟踪无法拦截发送到其他接收器的消息。
lager:trace_file仅当指定了相同的接收器时,才能跟踪到已经通过打开的文件。
可以通过打开多条迹线来改善前者。后者可以通过重新配置更大的文件后端来解决,但尚未解决。
跟踪无法拦截发送到其他接收器的消息。 lager:trace_file仅当指定了相同的接收器时,才能跟踪到已经通过打开的文件。 可以通过打开多条迹线来改善前者。后者可以通过重新配置更大的文件后端来解决,但尚未解决。
### 配置跟踪
@ -570,11 +572,8 @@ Lager支持通过注册回调函数从外部源提供元数据。即使进程死
通常,您不需要使用此功能。但是,它在以下情况下很有用:
seq_trace提供的跟踪信息
有关您的应用程序的上下文信息
默认占位符未提供的持久性信息
在每次记录调用之前必须设置元数据的情况
您可以使用{lager_parse_transform_functions, X} 选项添加回调。仅在使用时可用parse_transform。在钢筋中,您可以将其添加erl_opts如下:
seq_trace提供的跟踪信息 有关您的应用程序的上下文信息 默认占位符未提供的持久性信息 在每次记录调用之前必须设置元数据的情况 您可以使用{lager_parse_transform_functions, X}
选项添加回调。仅在使用时可用parse_transform。在钢筋中,您可以将其添加erl_opts如下:
```erlang
{erl_opts, [{parse_transform, lager_transform},
@ -592,22 +591,14 @@ seq_trace提供的跟踪信息
on_emit:
直到后端发出消息后,回调函数才能解析。
如果回调函数无法解析,未加载或产生未处理的错误,undefined则将返回该函数。
由于回调函数依赖于进程,因此有可能在依赖进程死亡导致undefined返回后发出消息。这个过程也可以是你自己的过程
直到后端发出消息后,回调函数才能解析。 如果回调函数无法解析,未加载或产生未处理的错误,undefined则将返回该函数。 由于回调函数依赖于进程,因此有可能在依赖进程死亡导致undefined返回后发出消息。这个过程也可以是你自己的过程
on_log:
无论是否
发出消息,都将解析回调函数
如果无法解析或未加载回调函数,则啤酒本身不会处理错误。
回调中的任何潜在错误都应在回调函数本身中处理。
由于该函数在日志记录时已解析,因此在解决该依赖进程之前,依赖进程死机的可能性应该较小,尤其是如果您正在从包含回调的应用程序进行日志记录时。
第三个元素是函数的回调,该函数由形式的元组组成{Module Function}。无论使用on_emit还是,回调都应如下所示on_log:
应该将其导出
它不应该接受任何参数,例如arity为0
它应该返回任何传统的iolist元素或原子 undefined
有关在回调中生成的错误,请参见上面的解析类型文档。
无论是否 发出消息,都将解析回调函数 如果无法解析或未加载回调函数,则啤酒本身不会处理错误。 回调中的任何潜在错误都应在回调函数本身中处理。
由于该函数在日志记录时已解析,因此在解决该依赖进程之前,依赖进程死机的可能性应该较小,尤其是如果您正在从包含回调的应用程序进行日志记录时。 第三个元素是函数的回调,该函数由形式的元组组成{Module
Function}。无论使用on_emit还是,回调都应如下所示on_log:
应该将其导出 它不应该接受任何参数,例如arity为0 它应该返回任何传统的iolist元素或原子 undefined 有关在回调中生成的错误,请参见上面的解析类型文档。
如果回调返回,undefined则它将遵循与“自定义格式”部分中记录的相同的后备和条件运算符规则 。
此示例可以使用,on_emit但与一起使用可能是不安全的 on_log。如果呼叫失败,on_emit则默认为undefined,但是on_log会出错。
@ -635,8 +626,7 @@ my_callback() ->
end.
```
注意,回调可以是任何Module:Function / 0。它不是您的应用程序的一部分。例如,您可以 像这样将其cpu_sup:avg1/0用作
回调函数{cpu_avg1, on_emit, {cpu_sup, avg1}}
注意,回调可以是任何Module:Function / 0。它不是您的应用程序的一部分。例如,您可以 像这样将其cpu_sup:avg1/0用作 回调函数{cpu_avg1, on_emit, {cpu_sup, avg1}}
例子:
@ -701,9 +691,7 @@ lager:install_trace(Pid, notice, [{count, 100}, {timeout, 5000}, {format_string,
跟踪选项当前为:
超时-跟踪保持安装的时间infinity:(默认)或毫秒超时
count-要记录的跟踪事件数:(infinity默认)或正数
format_string-用于记录事件的格式字符串。对于提供的2个参数,必须具有2个格式说明符。
超时-跟踪保持安装的时间infinity:(默认)或毫秒超时 count-要记录的跟踪事件数:(infinity默认)或正数 format_string-用于记录事件的格式字符串。对于提供的2个参数,必须具有2个格式说明符。
这将在OTP进程的每个“系统事件”上(通常是入站消息,答复和状态更改)在指定的日志级别生成一个更大的消息。
完成以下操作后,您可以删除跟踪:
@ -723,8 +711,8 @@ trace_state函数的第三个参数是上面记录的“选项”列表。
控制台输出到另一个组长进程
----------------------------------------------
如果要将控制台输出发送到另一个group_leader(通常在另一个节点上),则可以为{group_leader, Pid}控制台后端提供一个参数。
可以将其与另一个控制台配置选项id和gen_event结合使用,{Module, ID}以允许通过nodetool远程跟踪节点以进行标准输出:
如果要将控制台输出发送到另一个group_leader(通常在另一个节点上),则可以为{group_leader, Pid}控制台后端提供一个参数。 可以将其与另一个控制台配置选项id和gen_event结合使用,{Module,
ID}以允许通过nodetool远程跟踪节点以进行标准输出:
```erlang
GL = erlang:group_leader(),

+ 1
- 1
include/eRum.hrl Näytä tiedosto

@ -28,7 +28,7 @@
_ ->
ok
end).
%%eRum:dispatch_log(Sink, Severity, Pid, Node, Module, Function, File, Line, Metadata, Format, Args, Size, Safety)).
%%eRum:dispatch_log(Sink, Severity, Pid, Node, Module, Function, File, Line, Metadata, Format, Args, Size, Safety)).
-define(rumNone(Format), ?rumLog(?none, Format, undefined, safe)).
-define(rumNone(Format, Args), ?rumLog(?none, Format, Args, safe)).

+ 23
- 23
include/rumDef.hrl Näytä tiedosto

@ -24,32 +24,32 @@
%% rumBkdConsole的选项
-type rumConsoleOpt() ::
{id, atom() | {atom(), atom()}} |
{use_stderr, boolean()} |
{group_leader, false | pid() | atom()} |
{formatTer, atom()} |
{formatCfg, list()}.
{id, atom() | {atom(), atom()}} |
{use_stderr, boolean()} |
{group_leader, false | pid() | atom()} |
{formatTer, atom()} |
{formatCfg, list()}.
%% rumBkdFile的选项
-type rumFileOpt() ::
{file, binary()} |
{level, rumAtomLevel() | atom()} |
{size, non_neg_integer()} |
{date, string()} |
{count, non_neg_integer()} |
{rotator, atom()} |
{hWM, non_neg_integer()} |
%% 使
{flushQueue, boolean()} |
%% flush_queue为true0
%% flush_queue为true
{flushThr, non_neg_integer()} |
{syncInt, non_neg_integer()} |
{syncSize, non_neg_integer()} |
{syncOn, rumAtomLevel()} |
{checkInt, non_neg_integer()} |
{formatTer, atom()} |
{formatCfg, term()}.
{file, binary()} |
{level, rumAtomLevel() | atom()} |
{size, non_neg_integer()} |
{date, string()} |
{count, non_neg_integer()} |
{rotator, atom()} |
{hWM, non_neg_integer()} |
%% 使
{flushQueue, boolean()} |
%% flush_queue为true0
%% flush_queue为true
{flushThr, non_neg_integer()} |
{syncInt, non_neg_integer()} |
{syncSize, non_neg_integer()} |
{syncOn, rumAtomLevel()} |
{checkInt, non_neg_integer()} |
{formatTer, atom()} |
{formatCfg, term()}.
%% BkdFile选项默认值
-define(RumDefLogLevel, info).

+ 8
- 8
src/backend/rumBkdFile.erl Näytä tiedosto

@ -78,12 +78,12 @@ init(Opts) ->
FormatCfg =
case CfgFormatCfg of
[] ->
Whitelist = rumUtil:get_env(metadataWhitelist, []),
rumFormatTer:formatCfg(Whitelist);
_ ->
CfgFormatCfg
end,
[] ->
Whitelist = rumUtil:get_env(metadataWhitelist, []),
rumFormatTer:formatCfg(Whitelist);
_ ->
CfgFormatCfg
end,
scheduleRotation(Date, FileName),
Shaper = rumUtil:maybeFlush(Flush, #rumShaper{hwm = HWM, flushThr = FlushThr, id = FileName}),
@ -202,7 +202,7 @@ writeLog(#state{fileName = FileName, fd = Fd, inode = Inode, cTime = CTime, flap
%% go around the loop again, we'll do another rotation check and hit the next clause of ensureLogFile
writeLog(TemState, Timestamp, Level, Msg);
{error, Reason} ->
?IIF(Flap, State, begin ?INT_LOG(error, "Failed to rotate log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end)
?IIF(Flap, State, begin ?INT_LOG(error, "Failed to rotate log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end)
end;
_ ->
%% update our last check and try again
@ -210,7 +210,7 @@ writeLog(#state{fileName = FileName, fd = Fd, inode = Inode, cTime = CTime, flap
writeFile(TemState, Level, Msg)
end;
{error, Reason} ->
?IIF(Flap, State, begin ?INT_LOG(error, "Failed to reopen log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end)
?IIF(Flap, State, begin ?INT_LOG(error, "Failed to reopen log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end)
end;
_ ->
writeFile(State, Level, Msg)

+ 1
- 1
src/crashLog/rumCrashLog.erl Näytä tiedosto

@ -98,7 +98,7 @@ otherNodeSuffix(Pid) when node(Pid) =/= node() ->
PidNode = node(Pid),
case PidNode =/= node() of
true ->
<<"** at node ", (atom_to_binary(node(Pid), utf8))/binary, " **\n">>;
<<"** at node ", (atom_to_binary(node(Pid), utf8))/binary, " **\n">>;
_ ->
<<"">>
end.

+ 2
- 2
src/eRum1.erl Näytä tiedosto

@ -82,9 +82,9 @@ stop() ->
%% this is the same check that the parse transform bakes into the module at compile time see rumTransform (lines 173-216)
dispatch_log(Sink, Severity, Pid, Node, Module, Function, File, Line, Metadata, Format, Args, Size, Safety) ->
SeverityAsInt = rumUtil:levelToNum(Severity),
case {whereis(Sink), rumConfig:get({Sink, loglevel}, {?none, []})} of
case {whereis(Sink), rumConfig:get({Sink, loglevel}, {?none, []})} of
{undefined, _} -> {error, lager_not_running};
{SinkPid, {Level, Traces}} when Safety =:= safe andalso ((Level band SeverityAsInt) /= 0 orelse Traces /= []) ->
{SinkPid, {Level, Traces}} when Safety =:= safe andalso ((Level band SeverityAsInt) /= 0 orelse Traces /= []) ->
do_log(Severity, Pid, Node, Module, Function, File, Line, Metadata, Format, Args, Size, SeverityAsInt, Level, Traces, Sink, SinkPid);
{SinkPid, {Level, Traces}} when Safety =:= unsafe andalso ((Level band SeverityAsInt) /= 0 orelse Traces /= []) ->
do_log_unsafe(Severity, Pid, Node, Module, Function, File, Line, Metadata, Format, Args, Size, SeverityAsInt, Level, Traces, Sink, SinkPid);

+ 2
- 2
src/utils/rumStdlib.erl Näytä tiedosto

@ -73,11 +73,11 @@ format_mfa({M, F, Args} = StartF, FmtMaxBytes) ->
pp_fun(FmtMaxBytes) ->
fun(Term, _I) ->
eFmt:formatBin(<<"~p">>, [Term], [{charsLimit ,FmtMaxBytes}])
eFmt:formatBin(<<"~p">>, [Term], [{charsLimit, FmtMaxBytes}])
end.
format_tag(Tag, Data, FmtMaxBytes) ->
eFmt:formatBin(<<"~p: ~p~n">>, [Tag, Data], [{charsLimit ,FmtMaxBytes}]).
eFmt:formatBin(<<"~p: ~p~n">>, [Tag, Data], [{charsLimit, FmtMaxBytes}]).
%% From OTP stdlib's lib.erl ... These functions aren't exported.

+ 5
- 7
进度.md Näytä tiedosto

@ -1,30 +1,28 @@
# Done complete
# Done complete
eRum_sup
eRum.app.src
rumHWatcherSup
rumRotatorExm
# Done incomplete
app.config done
eRum_app
rumHWatcherSrv 部分还需要修改 删除测试代码
rumRotatorIns 旋转日志格式还需要修改
# Doing
# 优化改进之处:
日志旋转date格式转换函数修改(注释 对于某些月份 不存在29 30 或者 31天时 要避免M29 M30 M31的配法 代码并没有修复此种情况)
io_lib:format 修改为eFmt:format
# TODO
rumBkdFile 默认值修改
eRum.sameple.config 默认值修改
rumMsg.erl 删掉掉
io_lib:format 替换为 eFmt:formatBin
各个模块审查一下
reamde.me 整理

Ladataan…
Peruuta
Tallenna