erl_tracer(3)



erl_tracer(3erl)           Erlang Module Definition           erl_tracer(3erl)

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(3erl).

       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 11.0.2                 erl_tracer(3erl)

Man(1) output converted with man2html
list of all man pages