提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
为什么突然想用到trace
在我们的游戏开发过程中用消息号与前端传递消息时,偶尔有发生前后端各自的原因导致消息号没发出而不自知的问题,因此想到使用trace监控消息号的收发
一、trace是什么?
trace是erlang内置的用于监控进程的函数,可以理解为一种调试工具,用官方语句来说:无需用特殊方式编译你的代码就能跟踪某个进程。跟踪一个(或多个)进程是一种强有力的方式,它既能让你理解系统行为,又能在不改动代码的前提下测试复杂系统。
二、trace的使用
1.erlnag:trace(PidPortSpec, How, FlagList)
PidPortSpec:就是你要监听的进程,可以填 进程id/端口号/或者其他已定的原子(all、existing…)
How:代表开启或关闭跟踪 true/false
FlagList:用于设置跟踪事件的选项,比较常用的有以下几个(
send: 跟踪send操作,即消息发送操作; receive: 跟踪receive操作,即消息接收操作; call: 跟踪函数调用操作;
return: 跟踪函数返回操作; exception: 跟踪异常操作,即函数抛出异常; gc: 跟踪垃圾回收操作。
)
这个函数最好搭配上另一个函数作为进程的消息接收 以此来输出
2.erlang:trace_pattern(MFA, MatchSpec, FlagList)
这个函数可以指定你的trace跟踪哪个函数
MFA:是一个{Module, Function, Args}元组 例:{Mod,‘‘,’’} Mod模块里任意函数(不论参数数量多少)
MatchSpec:代表是否启用跟踪 true/false 不过书中还介绍MatchSpec是一个模式,会在每次进入MFA指定的函数时进行测试,但没有详细介绍,这里就用布尔型可以了
FlagList:规定了跟踪条件满足时要做什么 是一组选项列表
3.示例
代码如下(示例):
start_trace(RoleId) ->
RolePid = lib_player:get_pid(RoleId),
Fun = fun() ->
erlang:trace_pattern({lib_send, respond_to_client_by_sid, 2}, true, [local]),//监听lib_send模块里//respond_to_client_by_sid(_,_,_)的函数
erlang:trace(RolePid, true, [call, 'receive']),
case catch trace_loop() of
Reason ->
io:format("exit reason is ~w~n", [Reason])
end
end,
Pid = spawn(Fun),
erlang:put({?MODULE, trace_pid}, Pid).
trace_loop() ->
try
receive
{trace, _, 'receive', Receive} ->
case Receive of
{'$gen_cast', {socket_msg, Msg, Proto}} ->
io:format("Receive :{~p:~p} ~n", [Msg, Proto]);
_ ->
ignore
end,
trace_loop();
{trace, _, call, X} ->
io:format("Call :~p ~n", [X])
trace_loop();
Other ->
io:format("~n Other :~p ~n", [Other]),
trace_loop()
end
catch
throw:{error, Reason} -> io:format(" exit trace reason is ~w~n", [Reason])
end.
总结
erlang不止这个调试工具,只是这个比较灵活,且其他工具也是封装的这个,例如recon_trace、dbg、redbug 等库