Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
erl_tracer(3)		   Erlang Module Definition		 erl_tracer(3)

NAME
       erl_tracer - Erlang tracer behavior.

DESCRIPTION
       This behavior module implements the back	end of the Erlang tracing sys-
       tem. The	functions in this module are called whenever a trace probe  is
       triggered.  Both	the enabled and	trace functions	are called in the con-
       text of the entity that triggered the trace probe. This means that  the
       overhead	 by having the tracing enabled is greatly effected by how much
       time is spent in	these functions. So, do	as little work as possible  in
       these functions.

   Note:
       All  functions in this behavior must be implemented as NIFs. This limi-
       tation can be removed in	a future releases. An  example	tracer	module
       NIF implementation is provided at the end of this page.

   Warning:
       Do not send messages or issue port commands to the Tracee in any	of the
       callbacks. This is not allowed and can cause all	sorts of  strange  be-
       havior, including, but not limited to, infinite recursions.

DATA TYPES
       trace_tag_call()	=
	   call	| return_to | return_from | exception_from

       trace_tag_gc() =
	   gc_minor_start | gc_minor_end | gc_major_start | gc_major_end

       trace_tag_ports() =
	   open	|
	   closed |
	   link	|
	   unlink |
	   getting_linked |
	   getting_unlinked

       trace_tag_procs() =
	   spawn |
	   spawned |
	   exit	|
	   link	|
	   unlink |
	   getting_linked |
	   getting_unlinked |
	   register |
	   unregister

       trace_tag_receive() = 'receive'

       trace_tag_running_ports() =
	   in |	out | in_exiting | out_exiting | out_exited

       trace_tag_running_procs() =
	   in |	out | in_exiting | out_exiting | out_exited

       trace_tag_send()	= send | send_to_non_existing_process

       trace_tag() =
	   trace_tag_send() |
	   trace_tag_receive() |
	   trace_tag_call() |
	   trace_tag_procs() |
	   trace_tag_ports() |
	   trace_tag_running_procs() |
	   trace_tag_running_ports() |
	   trace_tag_gc()

	      The  different  trace  tags that the tracer is called with. Each
	      trace tag	is described in	detail in Module:trace/5.

       tracee()	= port() | pid() | undefined

	      The process or port that the trace belongs to.

       trace_opts() =
	   #{extra => term(),
	     match_spec_result => term(),
	     scheduler_id => integer() >= 0,
	     timestamp =>
		 timestamp | cpu_timestamp | monotonic | strict_monotonic}

	      The options for the tracee:

		timestamp:
		  If set the tracer has	 been  requested  to  include  a  time
		  stamp.

		extra:
		  If set the tracepoint	has included additional	data about the
		  trace	event. What the	additional data	is  depends  on	 which
		  TraceTag  has	 been  triggered.  The extra trace data	corre-
		  sponds to the	fifth element in the trace tuples described in
		  erlang:trace/3.

		match_spec_result:
		  If  set  the tracer has been requested to include the	output
		  of a match specification that	was run.

		scheduler_id:
		  If set the scheduler id is to	be included by the tracer.

       tracer_state() =	term()

	      The   state   specified	when   calling	 erlang:trace(PidPort-
	      Spec,true,[{tracer,Module,TracerState}]).	The tracer state is an
	      immutable	value that is passed to	erl_tracer callbacks and is to
	      contain all the data that	is needed to generate the trace	event.

CALLBACK FUNCTIONS
       The  following functions	are to be exported from	an erl_tracer callback
       module:

	 Module:enabled/3:
	   Mandatory

	 Module:trace/5:
	   Mandatory

	 Module:enabled_call/3:
	   Optional

	 Module:trace_call/5:
	   Optional

	 Module:enabled_garbage_collection/3:
	   Optional

	 Module:trace_garbage_collection/5:
	   Optional

	 Module:enabled_ports/3:
	   Optional

	 Module:trace_ports/5:
	   Optional

	 Module:enabled_procs/3:
	   Optional

	 Module:trace_procs/5:
	   Optional

	 Module:enabled_receive/3:
	   Optional

	 Module:trace_receive/5:
	   Optional

	 Module:enabled_running_ports/3:
	   Optional

	 Module:trace_running_ports/5:
	   Optional

	 Module:enabled_running_procs/3:
	   Optional

	 Module:trace_running_procs/5:
	   Optional

	 Module:enabled_send/3:
	   Optional

	 Module:trace_send/5:
	   Optional

EXPORTS
       Module:enabled(TraceTag,	TracerState, Tracee) ->	Result

	      Types:

		 TraceTag =  trace_tag() | trace_status
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint is	triggered.  It
	      allows  the  tracer to decide whether a trace is to be generated
	      or not. This check is made as early as  possible	to  limit  the
	      amount  of  overhead  associated	with  tracing. If trace	is re-
	      turned, the necessary trace data is created and the trace	 call-
	      back of the tracer is called. If discard is returned, this trace
	      call is discarded	and no call to trace is	done.

	      trace_status is a	special	type of	TraceTag,  which  is  used  to
	      check  if	the tracer is still to be active. It is	called in mul-
	      tiple scenarios, but most	significantly it is used when  tracing
	      is  started  using  this	tracer.	If remove is returned when the
	      trace_status is checked, the tracer is removed from the tracee.

	      This function can	be called multiple times per tracepoint, so it
	      is important that	it is both fast	and without side effects.

       Module:enabled_call(TraceTag, TracerState, Tracee) -> Result

	      Types:

		 TraceTag =  trace_tag_call()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This  callback  is  called whenever a tracepoint with trace flag
	      call | return_to is triggered.

	      If enabled_call/3	is undefined, Module:enabled/3 is  called  in-
	      stead.

       Module:enabled_garbage_collection(TraceTag, TracerState,	Tracee)	-> Re-
       sult

	      Types:

		 TraceTag =  trace_tag_gc()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      garbage_collection is triggered.

	      If  enabled_garbage_collection/3	is undefined, Module:enabled/3
	      is called	instead.

       Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result

	      Types:

		 TraceTag =  trace_tag_ports()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      ports is triggered.

	      If  enabled_ports/3 is undefined,	Module:enabled/3 is called in-
	      stead.

       Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result

	      Types:

		 TraceTag =  trace_tag_procs()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      procs is triggered.

	      If  enabled_procs/3 is undefined,	Module:enabled/3 is called in-
	      stead.

       Module:enabled_receive(TraceTag,	TracerState, Tracee) ->	Result

	      Types:

		 TraceTag =  trace_tag_receive()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      'receive'	is triggered.

	      If  enabled_receive/3  is	 undefined, Module:enabled/3 is	called
	      instead.

       Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> Result

	      Types:

		 TraceTag =  trace_tag_running_ports()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      running_ports is triggered.

	      If  enabled_running_ports/3  is  undefined,  Module:enabled/3 is
	      called instead.

       Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result

	      Types:

		 TraceTag =  trace_tag_running_procs()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      running_procs | running is triggered.

	      If  enabled_running_procs/3  is  undefined,  Module:enabled/3 is
	      called instead.

       Module:enabled_send(TraceTag, TracerState, Tracee) -> Result

	      Types:

		 TraceTag =  trace_tag_send()
		 TracerState = term()
		 Tracee	= tracee()
		 Result	= trace	| discard | remove

	      This callback is called whenever a tracepoint  with  trace  flag
	      send is triggered.

	      If  enabled_send/3  is undefined,	Module:enabled/3 is called in-
	      stead.

       Module:trace(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result

	      Types:

		 TraceTag =  trace_tag()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This callback is called when a tracepoint	is triggered  and  the
	      Module:enabled/3 callback	returned trace.	In it any side effects
	      needed by	the tracer are to be done. The tracepoint  payload  is
	      located  in  the TraceTerm. The content of the TraceTerm depends
	      on which TraceTag	is triggered.  TraceTerm  corresponds  to  the
	      fourth element in	the trace tuples described in erlang:trace/3.

	      If  the trace tuple has five elements, the fifth element will be
	      sent as the extra	value in the Opts maps.

       Module:trace(seq_trace, TracerState, Label, SeqTraceInfo, Opts) ->  Re-
       sult

	      Types:

		 TracerState = term()
		 Label = term()
		 SeqTraceInfo =	term()
		 Opts =	trace_opts()
		 Result	= ok

	      The TraceTag seq_trace is	handled	slightly differently. There is
	      no Tracee	for seq_trace, instead the Label associated  with  the
	      seq_trace	event is specified.

	      For  more	information on what Label and SeqTraceInfo can be, see
	      seq_trace(3).

       Module:trace_call(TraceTag, TracerState,	Tracee,	 TraceTerm,  Opts)  ->
       Result

	      Types:

		 TraceTag =  trace_tag_call()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This  callback  is called	when a tracepoint is triggered and the
	      Module:enabled_call/3 callback returned trace.

	      If trace_call/5 is undefined, Module:trace/5 is called instead.

       Module:trace_garbage_collection(TraceTag,     TracerState,      Tracee,
       TraceTerm, Opts)	-> Result

	      Types:

		 TraceTag =  trace_tag_gc()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This  callback  is called	when a tracepoint is triggered and the
	      Module:enabled_garbage_collection/3 callback returned trace.

	      If trace_garbage_collection/5 is	undefined,  Module:trace/5  is
	      called instead.

       Module:trace_ports(TraceTag,  TracerState,  Tracee, TraceTerm, Opts) ->
       Result

	      Types:

		 TraceTag =  trace_tag()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This callback is called when a tracepoint	is triggered  and  the
	      Module:enabled_ports/3 callback returned trace.

	      If trace_ports/5 is undefined, Module:trace/5 is called instead.

       Module:trace_procs(TraceTag,  TracerState,  Tracee, TraceTerm, Opts) ->
       Result

	      Types:

		 TraceTag =  trace_tag()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This callback is called when a tracepoint	is triggered  and  the
	      Module:enabled_procs/3 callback returned trace.

	      If trace_procs/5 is undefined, Module:trace/5 is called instead.

       Module:trace_receive(TraceTag, TracerState, Tracee, TraceTerm, Opts) ->
       Result

	      Types:

		 TraceTag =  trace_tag_receive()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This callback is called when a tracepoint	is triggered  and  the
	      Module:enabled_receive/3 callback	returned trace.

	      If  trace_receive/5  is  undefined, Module:trace/5 is called in-
	      stead.

       Module:trace_running_ports(TraceTag,  TracerState,  Tracee,  TraceTerm,
       Opts) ->	Result

	      Types:

		 TraceTag =  trace_tag_running_ports()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This  callback  is called	when a tracepoint is triggered and the
	      Module:enabled_running_ports/3 callback returned trace.

	      If trace_running_ports/5 is undefined, Module:trace/5 is	called
	      instead.

       Module:trace_running_procs(TraceTag,  TracerState,  Tracee,  TraceTerm,
       Opts) ->	Result

	      Types:

		 TraceTag =  trace_tag_running_procs()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This callback is called when a tracepoint	is triggered  and  the
	      Module:enabled_running_procs/3 callback returned trace.

	      If  trace_running_procs/5	is undefined, Module:trace/5 is	called
	      instead.

       Module:trace_send(TraceTag, TracerState,	Tracee,	 TraceTerm,  Opts)  ->
       Result

	      Types:

		 TraceTag =  trace_tag_send()
		 TracerState = term()
		 Tracee	= tracee()
		 TraceTerm = term()
		 Opts =	trace_opts()
		 Result	= ok

	      This  callback  is called	when a tracepoint is triggered and the
	      Module:enabled_send/3 callback returned trace.

	      If trace_send/5 is undefined, Module:trace/5 is called instead.

ERL TRACER MODULE EXAMPLE
       In this example,	a tracer module	with a NIF back	end  sends  a  message
       for  each send trace tag	containing only	the sender and receiver. Using
       this tracer module, a much more lightweight  message  tracer  is	 used,
       which only records who sent messages to who.

       The following is	an example session using it on Linux:

       $ gcc -I	erts-8.0/include/ -fPIC	-shared	-o erl_msg_tracer.so erl_msg_tracer.c
       $ erl
       Erlang/OTP 19 [DEVELOPMENT] [erts-8.0] [source-ed2b56b] [64-bit]	[smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

       Eshell V8.0  (abort with	^G)
       1> c(erl_msg_tracer), erl_msg_tracer:load().
       ok
       2> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]),	F() end	end).
       <0.37.0>
       3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]).
       0
       {trace,<0.39.0>,<0.27.0>}
       4> {ok, D} = file:open("/tmp/tmp.data",[write]).
       {trace,#Port<0.486>,<0.40.0>}
       {trace,<0.40.0>,<0.21.0>}
       {trace,#Port<0.487>,<0.4.0>}
       {trace,#Port<0.488>,<0.4.0>}
       {trace,#Port<0.489>,<0.4.0>}
       {trace,#Port<0.490>,<0.4.0>}
       {ok,<0.40.0>}
       {trace,<0.41.0>,<0.27.0>}
       5>

       erl_msg_tracer.erl:

       -module(erl_msg_tracer).

       -export([enabled/3, trace/5, load/0]).

       load() ->
	   erlang:load_nif("erl_msg_tracer", []).

       enabled(_, _, _)	->
	   error.

       trace(_,	_, _, _, _) ->
	   error.

       erl_msg_tracer.c:

       #include	<erl_nif.h>

       /* NIF interface	declarations */
       static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
       static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
       static void unload(ErlNifEnv* env, void*	priv_data);

       /* The NIFs: */
       static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM	argv[]);
       static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);

       static ErlNifFunc nif_funcs[] = {
	   {"enabled", 3, enabled},
	   {"trace", 5,	trace}
       };

       ERL_NIF_INIT(erl_msg_tracer, nif_funcs, load, NULL, upgrade, unload)

       static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
       {
	   *priv_data =	NULL;
	   return 0;
       }

       static void unload(ErlNifEnv* env, void*	priv_data)
       {

       }

       static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
		    ERL_NIF_TERM load_info)
       {
	   if (*old_priv_data != NULL || *priv_data != NULL) {
	    return -1; /* Don't	know how to do that */
	   }
	   if (load(env, priv_data, load_info))	{
	    return -1;
	   }
	   return 0;
       }

       /*
	* argv[0]: TraceTag
	* argv[1]: TracerState
	* argv[2]: Tracee
	*/
       static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM	argv[])
       {
	   ErlNifPid to_pid;
	   if (enif_get_local_pid(env, argv[1],	&to_pid))
	       if (!enif_is_process_alive(env, &to_pid))
		   if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
		       /* tracer is dead so we should remove this tracepoint */
		       return enif_make_atom(env, "remove");
		   else
		       return enif_make_atom(env, "discard");

	   /* Only generate trace for when tracer != tracee */
	   if (enif_is_identical(argv[1], argv[2]))
	       return enif_make_atom(env, "discard");

	   /* Only trigger trace messages on 'send' */
	   if (enif_is_identical(enif_make_atom(env, "send"), argv[0]))
	       return enif_make_atom(env, "trace");

	   /* Have to answer trace_status */
	   if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
	       return enif_make_atom(env, "trace");

	   return enif_make_atom(env, "discard");
       }

       /*
	* argv[0]: TraceTag, should only be 'send'
	* argv[1]: TracerState,	process	to send	{Tracee, Recipient} to
	* argv[2]: Tracee
	* argv[3]: Message
	* argv[4]: Options, map	containing Recipient
	*/
       static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
       {
	   ErlNifPid to_pid;
	   ERL_NIF_TERM	recipient, msg;

	   if (enif_get_local_pid(env, argv[1],	&to_pid)) {
	     if	(enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"),	&recipient)) {
	       msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient);
	       enif_send(env, &to_pid, NULL, msg);
	     }
	   }

	   return enif_make_atom(env, "ok");
       }

Ericsson AB			   erts	10.3			 erl_tracer(3)

NAME | DESCRIPTION | DATA TYPES | CALLBACK FUNCTIONS | EXPORTS | ERL TRACER MODULE EXAMPLE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=erl_tracer&sektion=3&manpath=FreeBSD+12.2-RELEASE+and+Ports>

home | help