1erl_tracer(3)              Erlang Module Definition              erl_tracer(3)
2
3
4

NAME

6       erl_tracer - Erlang tracer behavior.
7

DESCRIPTION

9       This behavior module implements the back end of the Erlang tracing sys‐
10       tem. The functions in this module are called whenever a trace probe  is
11       triggered.  Both the enabled and trace functions are called in the con‐
12       text of the entity that triggered the trace probe. This means that  the
13       overhead  by having the tracing enabled is greatly effected by how much
14       time is spent in these functions. So, do as little work as possible  in
15       these functions.
16
17   Note:
18       All  functions in this behavior must be implemented as NIFs. This limi‐
19       tation can be removed in a future releases. An  example  tracer  module
20       NIF implementation is provided at the end of this page.
21
22
23   Warning:
24       Do not send messages or issue port commands to the Tracee in any of the
25       callbacks. This is not allowed and  can  cause  all  sorts  of  strange
26       behavior, including, but not limited to, infinite recursions.
27
28

DATA TYPES

30       trace_tag_call() =
31           call | return_to | return_from | exception_from
32
33       trace_tag_gc() =
34           gc_minor_start | gc_minor_end | gc_major_start | gc_major_end
35
36       trace_tag_ports() =
37           open |
38           closed |
39           link |
40           unlink |
41           getting_linked |
42           getting_unlinked
43
44       trace_tag_procs() =
45           spawn |
46           spawned |
47           exit |
48           link |
49           unlink |
50           getting_linked |
51           getting_unlinked |
52           register |
53           unregister
54
55       trace_tag_receive() = 'receive'
56
57       trace_tag_running_ports() =
58           in | out | in_exiting | out_exiting | out_exited
59
60       trace_tag_running_procs() =
61           in | out | in_exiting | out_exiting | out_exited
62
63       trace_tag_send() = send | send_to_non_existing_process
64
65       trace_tag() =
66           trace_tag_send() |
67           trace_tag_receive() |
68           trace_tag_call() |
69           trace_tag_procs() |
70           trace_tag_ports() |
71           trace_tag_running_procs() |
72           trace_tag_running_ports() |
73           trace_tag_gc()
74
75              The  different  trace  tags that the tracer is called with. Each
76              trace tag is described in detail in Module:trace/5.
77
78       tracee() = port() | pid() | undefined
79
80              The process or port that the trace belongs to.
81
82       trace_opts() =
83           #{extra => term(),
84             match_spec_result => term(),
85             scheduler_id => integer() >= 0,
86             timestamp =>
87                 timestamp | cpu_timestamp | monotonic | strict_monotonic}
88
89              The options for the tracee:
90
91                timestamp:
92                  If set the tracer has  been  requested  to  include  a  time
93                  stamp.
94
95                extra:
96                  If set the tracepoint has included additional data about the
97                  trace event. What the additional data is  depends  on  which
98                  TraceTag  has  been  triggered.  The extra trace data corre‐
99                  sponds to the fifth element in the trace tuples described in
100                  erlang:trace/3.
101
102                match_spec_result:
103                  If  set  the tracer has been requested to include the output
104                  of a match specification that was run.
105
106                scheduler_id:
107                  If set the scheduler id is to be included by the tracer.
108
109       tracer_state() = term()
110
111              The   state   specified   when   calling   erlang:trace(PidPort‐
112              Spec,true,[{tracer,Module,TracerState}]). The tracer state is an
113              immutable value that is passed to erl_tracer callbacks and is to
114              contain all the data that is needed to generate the trace event.
115

CALLBACK FUNCTIONS

117       The  following functions are to be exported from an erl_tracer callback
118       module:
119
120         Module:enabled/3:
121           Mandatory
122
123         Module:trace/5:
124           Mandatory
125
126         Module:enabled_call/3:
127           Optional
128
129         Module:trace_call/5:
130           Optional
131
132         Module:enabled_garbage_collection/3:
133           Optional
134
135         Module:trace_garbage_collection/5:
136           Optional
137
138         Module:enabled_ports/3:
139           Optional
140
141         Module:trace_ports/5:
142           Optional
143
144         Module:enabled_procs/3:
145           Optional
146
147         Module:trace_procs/5:
148           Optional
149
150         Module:enabled_receive/3:
151           Optional
152
153         Module:trace_receive/5:
154           Optional
155
156         Module:enabled_running_ports/3:
157           Optional
158
159         Module:trace_running_ports/5:
160           Optional
161
162         Module:enabled_running_procs/3:
163           Optional
164
165         Module:trace_running_procs/5:
166           Optional
167
168         Module:enabled_send/3:
169           Optional
170
171         Module:trace_send/5:
172           Optional
173

EXPORTS

175       Module:enabled(TraceTag, TracerState, Tracee) -> Result
176
177              Types:
178
179                 TraceTag =  trace_tag() | trace_status
180                 TracerState = term()
181                 Tracee = tracee()
182                 Result = trace | discard | remove
183
184              This callback is called whenever a tracepoint is  triggered.  It
185              allows  the  tracer to decide whether a trace is to be generated
186              or not. This check is made as early as  possible  to  limit  the
187              amount   of  overhead  associated  with  tracing.  If  trace  is
188              returned, the necessary trace data  is  created  and  the  trace
189              callback  of  the tracer is called. If discard is returned, this
190              trace call is discarded and no call to trace is done.
191
192              trace_status is a special type of TraceTag,  which  is  used  to
193              check  if the tracer is still to be active. It is called in mul‐
194              tiple scenarios, but most significantly it is used when  tracing
195              is  started  using  this  tracer. If remove is returned when the
196              trace_status is checked, the tracer is removed from the tracee.
197
198              This function can be called multiple times per tracepoint, so it
199              is important that it is both fast and without side effects.
200
201       Module:enabled_call(TraceTag, TracerState, Tracee) -> Result
202
203              Types:
204
205                 TraceTag =  trace_tag_call()
206                 TracerState = term()
207                 Tracee = tracee()
208                 Result = trace | discard | remove
209
210              This  callback  is  called whenever a tracepoint with trace flag
211              call | return_to is triggered.
212
213              If  enabled_call/3  is  undefined,  Module:enabled/3  is  called
214              instead.
215
216       Module:enabled_garbage_collection(TraceTag,   TracerState,  Tracee)  ->
217       Result
218
219              Types:
220
221                 TraceTag =  trace_tag_gc()
222                 TracerState = term()
223                 Tracee = tracee()
224                 Result = trace | discard | remove
225
226              This callback is called whenever a tracepoint  with  trace  flag
227              garbage_collection is triggered.
228
229              If  enabled_garbage_collection/3  is undefined, Module:enabled/3
230              is called instead.
231
232       Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result
233
234              Types:
235
236                 TraceTag =  trace_tag_ports()
237                 TracerState = term()
238                 Tracee = tracee()
239                 Result = trace | discard | remove
240
241              This callback is called whenever a tracepoint  with  trace  flag
242              ports is triggered.
243
244              If  enabled_ports/3  is  undefined,  Module:enabled/3  is called
245              instead.
246
247       Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result
248
249              Types:
250
251                 TraceTag =  trace_tag_procs()
252                 TracerState = term()
253                 Tracee = tracee()
254                 Result = trace | discard | remove
255
256              This callback is called whenever a tracepoint  with  trace  flag
257              procs is triggered.
258
259              If  enabled_procs/3  is  undefined,  Module:enabled/3  is called
260              instead.
261
262       Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result
263
264              Types:
265
266                 TraceTag =  trace_tag_receive()
267                 TracerState = term()
268                 Tracee = tracee()
269                 Result = trace | discard | remove
270
271              This callback is called whenever a tracepoint  with  trace  flag
272              'receive' is triggered.
273
274              If  enabled_receive/3  is  undefined, Module:enabled/3 is called
275              instead.
276
277       Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> Result
278
279              Types:
280
281                 TraceTag =  trace_tag_running_ports()
282                 TracerState = term()
283                 Tracee = tracee()
284                 Result = trace | discard | remove
285
286              This callback is called whenever a tracepoint  with  trace  flag
287              running_ports is triggered.
288
289              If  enabled_running_ports/3  is  undefined,  Module:enabled/3 is
290              called instead.
291
292       Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result
293
294              Types:
295
296                 TraceTag =  trace_tag_running_procs()
297                 TracerState = term()
298                 Tracee = tracee()
299                 Result = trace | discard | remove
300
301              This callback is called whenever a tracepoint  with  trace  flag
302              running_procs | running is triggered.
303
304              If  enabled_running_procs/3  is  undefined,  Module:enabled/3 is
305              called instead.
306
307       Module:enabled_send(TraceTag, TracerState, Tracee) -> Result
308
309              Types:
310
311                 TraceTag =  trace_tag_send()
312                 TracerState = term()
313                 Tracee = tracee()
314                 Result = trace | discard | remove
315
316              This callback is called whenever a tracepoint  with  trace  flag
317              send is triggered.
318
319              If  enabled_send/3  is  undefined,  Module:enabled/3  is  called
320              instead.
321
322       Module:trace(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
323
324              Types:
325
326                 TraceTag =  trace_tag()
327                 TracerState = term()
328                 Tracee = tracee()
329                 TraceTerm = term()
330                 Opts = trace_opts()
331                 Result = ok
332
333              This callback is called when a tracepoint is triggered  and  the
334              Module:enabled/3 callback returned trace. In it any side effects
335              needed by the tracer are to be done. The tracepoint  payload  is
336              located  in  the TraceTerm. The content of the TraceTerm depends
337              on which TraceTag is triggered.  TraceTerm  corresponds  to  the
338              fourth element in the trace tuples described in erlang:trace/3.
339
340              If  the trace tuple has five elements, the fifth element will be
341              sent as the extra value in the Opts maps.
342
343       Module:trace(seq_trace,  TracerState,  Label,  SeqTraceInfo,  Opts)  ->
344       Result
345
346              Types:
347
348                 TracerState = term()
349                 Label = term()
350                 SeqTraceInfo = term()
351                 Opts = trace_opts()
352                 Result = ok
353
354              The TraceTag seq_trace is handled slightly differently. There is
355              no Tracee for seq_trace, instead the Label associated  with  the
356              seq_trace event is specified.
357
358              For  more information on what Label and SeqTraceInfo can be, see
359              seq_trace(3).
360
361       Module:trace_call(TraceTag, TracerState, Tracee,  TraceTerm,  Opts)  ->
362       Result
363
364              Types:
365
366                 TraceTag =  trace_tag_call()
367                 TracerState = term()
368                 Tracee = tracee()
369                 TraceTerm = term()
370                 Opts = trace_opts()
371                 Result = ok
372
373              This  callback  is called when a tracepoint is triggered and the
374              Module:enabled_call/3 callback returned trace.
375
376              If trace_call/5 is undefined, Module:trace/5 is called instead.
377
378       Module:trace_garbage_collection(TraceTag,     TracerState,      Tracee,
379       TraceTerm, Opts) -> Result
380
381              Types:
382
383                 TraceTag =  trace_tag_gc()
384                 TracerState = term()
385                 Tracee = tracee()
386                 TraceTerm = term()
387                 Opts = trace_opts()
388                 Result = ok
389
390              This  callback  is called when a tracepoint is triggered and the
391              Module:enabled_garbage_collection/3 callback returned trace.
392
393              If trace_garbage_collection/5 is  undefined,  Module:trace/5  is
394              called instead.
395
396       Module:trace_ports(TraceTag,  TracerState,  Tracee, TraceTerm, Opts) ->
397       Result
398
399              Types:
400
401                 TraceTag =  trace_tag()
402                 TracerState = term()
403                 Tracee = tracee()
404                 TraceTerm = term()
405                 Opts = trace_opts()
406                 Result = ok
407
408              This callback is called when a tracepoint is triggered  and  the
409              Module:enabled_ports/3 callback returned trace.
410
411              If trace_ports/5 is undefined, Module:trace/5 is called instead.
412
413       Module:trace_procs(TraceTag,  TracerState,  Tracee, TraceTerm, Opts) ->
414       Result
415
416              Types:
417
418                 TraceTag =  trace_tag()
419                 TracerState = term()
420                 Tracee = tracee()
421                 TraceTerm = term()
422                 Opts = trace_opts()
423                 Result = ok
424
425              This callback is called when a tracepoint is triggered  and  the
426              Module:enabled_procs/3 callback returned trace.
427
428              If trace_procs/5 is undefined, Module:trace/5 is called instead.
429
430       Module:trace_receive(TraceTag, TracerState, Tracee, TraceTerm, Opts) ->
431       Result
432
433              Types:
434
435                 TraceTag =  trace_tag_receive()
436                 TracerState = term()
437                 Tracee = tracee()
438                 TraceTerm = term()
439                 Opts = trace_opts()
440                 Result = ok
441
442              This callback is called when a tracepoint is triggered  and  the
443              Module:enabled_receive/3 callback returned trace.
444
445              If   trace_receive/5  is  undefined,  Module:trace/5  is  called
446              instead.
447
448       Module:trace_running_ports(TraceTag,  TracerState,  Tracee,  TraceTerm,
449       Opts) -> Result
450
451              Types:
452
453                 TraceTag =  trace_tag_running_ports()
454                 TracerState = term()
455                 Tracee = tracee()
456                 TraceTerm = term()
457                 Opts = trace_opts()
458                 Result = ok
459
460              This  callback  is called when a tracepoint is triggered and the
461              Module:enabled_running_ports/3 callback returned trace.
462
463              If trace_running_ports/5 is undefined, Module:trace/5 is  called
464              instead.
465
466       Module:trace_running_procs(TraceTag,  TracerState,  Tracee,  TraceTerm,
467       Opts) -> Result
468
469              Types:
470
471                 TraceTag =  trace_tag_running_procs()
472                 TracerState = term()
473                 Tracee = tracee()
474                 TraceTerm = term()
475                 Opts = trace_opts()
476                 Result = ok
477
478              This callback is called when a tracepoint is triggered  and  the
479              Module:enabled_running_procs/3 callback returned trace.
480
481              If  trace_running_procs/5 is undefined, Module:trace/5 is called
482              instead.
483
484       Module:trace_send(TraceTag, TracerState, Tracee,  TraceTerm,  Opts)  ->
485       Result
486
487              Types:
488
489                 TraceTag =  trace_tag_send()
490                 TracerState = term()
491                 Tracee = tracee()
492                 TraceTerm = term()
493                 Opts = trace_opts()
494                 Result = ok
495
496              This  callback  is called when a tracepoint is triggered and the
497              Module:enabled_send/3 callback returned trace.
498
499              If trace_send/5 is undefined, Module:trace/5 is called instead.
500

ERL TRACER MODULE EXAMPLE

502       In this example, a tracer module with a NIF back end  sends  a  message
503       for  each send trace tag containing only the sender and receiver. Using
504       this tracer module, a much more lightweight  message  tracer  is  used,
505       which only records who sent messages to who.
506
507       The following is an example session using it on Linux:
508
509       $ gcc -I erts-8.0/include/ -fPIC -shared -o erl_msg_tracer.so erl_msg_tracer.c
510       $ erl
511       Erlang/OTP 19 [DEVELOPMENT] [erts-8.0] [source-ed2b56b] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
512
513       Eshell V8.0  (abort with ^G)
514       1> c(erl_msg_tracer), erl_msg_tracer:load().
515       ok
516       2> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
517       <0.37.0>
518       3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]).
519       0
520       {trace,<0.39.0>,<0.27.0>}
521       4> {ok, D} = file:open("/tmp/tmp.data",[write]).
522       {trace,#Port<0.486>,<0.40.0>}
523       {trace,<0.40.0>,<0.21.0>}
524       {trace,#Port<0.487>,<0.4.0>}
525       {trace,#Port<0.488>,<0.4.0>}
526       {trace,#Port<0.489>,<0.4.0>}
527       {trace,#Port<0.490>,<0.4.0>}
528       {ok,<0.40.0>}
529       {trace,<0.41.0>,<0.27.0>}
530       5>
531
532       erl_msg_tracer.erl:
533
534       -module(erl_msg_tracer).
535
536       -export([enabled/3, trace/5, load/0]).
537
538       load() ->
539           erlang:load_nif("erl_msg_tracer", []).
540
541       enabled(_, _, _) ->
542           error.
543
544       trace(_, _, _, _, _) ->
545           error.
546
547       erl_msg_tracer.c:
548
549       #include <erl_nif.h>
550
551       /* NIF interface declarations */
552       static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
553       static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
554       static void unload(ErlNifEnv* env, void* priv_data);
555
556       /* The NIFs: */
557       static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
558       static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
559
560       static ErlNifFunc nif_funcs[] = {
561           {"enabled", 3, enabled},
562           {"trace", 5, trace}
563       };
564
565       ERL_NIF_INIT(erl_msg_tracer, nif_funcs, load, NULL, upgrade, unload)
566
567       static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
568       {
569           *priv_data = NULL;
570           return 0;
571       }
572
573       static void unload(ErlNifEnv* env, void* priv_data)
574       {
575
576       }
577
578       static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
579                    ERL_NIF_TERM load_info)
580       {
581           if (*old_priv_data != NULL || *priv_data != NULL) {
582            return -1; /* Don't know how to do that */
583           }
584           if (load(env, priv_data, load_info)) {
585            return -1;
586           }
587           return 0;
588       }
589
590       /*
591        * argv[0]: TraceTag
592        * argv[1]: TracerState
593        * argv[2]: Tracee
594        */
595       static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
596       {
597           ErlNifPid to_pid;
598           if (enif_get_local_pid(env, argv[1], &to_pid))
599               if (!enif_is_process_alive(env, &to_pid))
600                   if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
601                       /* tracer is dead so we should remove this tracepoint */
602                       return enif_make_atom(env, "remove");
603                   else
604                       return enif_make_atom(env, "discard");
605
606           /* Only generate trace for when tracer != tracee */
607           if (enif_is_identical(argv[1], argv[2]))
608               return enif_make_atom(env, "discard");
609
610           /* Only trigger trace messages on 'send' */
611           if (enif_is_identical(enif_make_atom(env, "send"), argv[0]))
612               return enif_make_atom(env, "trace");
613
614           /* Have to answer trace_status */
615           if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
616               return enif_make_atom(env, "trace");
617
618           return enif_make_atom(env, "discard");
619       }
620
621       /*
622        * argv[0]: TraceTag, should only be 'send'
623        * argv[1]: TracerState, process to send {Tracee, Recipient} to
624        * argv[2]: Tracee
625        * argv[3]: Message
626        * argv[4]: Options, map containing Recipient
627        */
628       static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
629       {
630           ErlNifPid to_pid;
631           ERL_NIF_TERM recipient, msg;
632
633           if (enif_get_local_pid(env, argv[1], &to_pid)) {
634             if (enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"), &recipient)) {
635               msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient);
636               enif_send(env, &to_pid, NULL, msg);
637             }
638           }
639
640           return enif_make_atom(env, "ok");
641       }
642
643
644
645Ericsson AB                      erts 10.3.5.2                   erl_tracer(3)
Impressum