Here are some messages from using redbug in the shell:
% 02:49:02 <0.116.0>({cowboy_protocol,init,4})
% func1:start(<<"/second">>, [some])
% 02:49:02 <0.116.0>({cowboy_protocol,init,4})
% func1:looper(<<"/home/second">>, #{data => []}])
Is there are way to also print line numbers in redbug messages?
redbug:help() does show this:
print_fun () custom print handler, fun/1 or fun/2;
fun(TrcMsg) -> <ignored>
fun(TrcMsg,AccOld) -> AccNew
But there is no good explanation anywhere how to use it, so I couldn't try to see if I could add line numbers to the message
It doesn't seem you can do it in any straight forward way.
Easiest way to check this, it to just print all data you receive in your print_fun
1> PrintFun = fun (Msg) -> io:format( ">>> ~p~n" , [Msg]) end.
#Fun<erl_eval.6.90072148>
2> redbug:start("erlang" , [{print_fun, PrintFun}]).
{30,249}
>>> {call,{{erlang,demonitor,[#Ref<0.0.0.40>]},<<>>},
{<0.33.0>,{erlang,apply,2}},
{11,40,31,554200}}
>>> {call,{{erlang,atom_to_list,['PrintFun']},<<>>},
{<0.33.0>,{erlang,apply,2}},
{11,40,31,554210}}
>>> {call,{{erlang,group_leader,[]},<<>>},
{<0.33.0>,{erlang,apply,2}},
{11,40,31,554213}}
>>> {call,{{erlang,monitor,[process,<0.26.0>]},<<>>},
{<0.33.0>,{erlang,apply,2}},
{11,40,31,554215}}
>>> {call,{{erlang,port_control,[#Port<0.491>,101,[]]},<<>>},
{<0.24.0>,user_drv},
{11,40,31,554231}}
>>> {call,{{erlang,module_loaded,[calendar]},<<>>},
{<0.20.0>,code_server},
{11,40,31,554257}}
>>> {call,{{erlang,atom_to_list,[calendar]},<<>>},
{<0.20.0>,code_server},
{11,40,31,554263}}
>>> {call,{{erlang,'++',["calendar",".beam"]},<<>>},
{<0.20.0>,code_server},
{11,40,31,554265}}
>>> {call,{{erlang,'++',["ebin","/calendar.beam"]},<<>>},
{<0.20.0>,code_server},
{11,40,31,554268}}
>>> {call,{{erlang,whereis,[erl_prim_loader]},<<>>},
{<0.20.0>,code_server},
{11,40,31,554270}}
redbug done, msg_count - 10
As you can see, all you get is MFA ({Module, Function, Arguments}
), calling process, and time stamp.
To get actual line of function call you would have to dig into debug_info
attached to beam file (if there is any) with beam_lib
module. I think seampleas way to do it would be using beam_lib:chunks( Module, [abstract_code]).
, just like this
{ok,{redbug,[{abstract_code,{raw_abstract_v1,[{attribute,1,
file,
{"src/redbug.erl",1}},
{attribute,9,module,redbug},
{attribute,11,export,[{help,0}]},
{attribute,13,export,[{unix,1}]},
{attribute,15,export,
[{start,1},{start,2},{start,3},{start,4},{start,5}]},
{attribute,16,export,[{stop,0}]},
{attribute,1,file,{"src/log.hrl",1}},
{function,17,'?log',2,
[{clause,17,[{var,17,...},{var,...}],[[{...}]],[{...}]},
{clause,18,[{var,...},{...}],[],[...]}]},
{attribute,19,file,{"src/redbug.erl",19}},
{attribute,22,record,
{cnf,[{record_field,24,{...},...},
{record_field,25,...},
{record_field,...},
{...}|...]}},
{function,57,help,0,[{clause,57,[],...}]},
{function,123,unix,1,
[{clause,123,...},{clause,...},{...}|...]},
{function,146,to_term,1,[{clause,...},{...}]},
{function,154,maybe_halt,1,[{...}]},
{function,160,is_in_shell,0,[...]},
{function,167,stop,0,...},
{function,174,start,...},
{function,176,...},
{function,...},
{...}|...]}}]}}
There you can find list, on which you could find tuples like {function, LineNumber, FunctionName, Arity, FunctionCodeAsList }
. So by going trough this list and finding function you are looking for you can extract LineNumber
.
Still you need to take under account few things that might not work.
.beam
debug_info
might fail in producing this abstract syntax tree. You need to decide if that is might be your case, and how would you like to handle this.beams
might be encrypted, some might have other issues. You should read beam_lib
module documentation just to get feel what you are dealing with.If you do come up with something, please do share. Happy hacking !