/
trace.erl
1331 lines (1043 loc) · 53.3 KB
/
trace.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2024. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(trace).
-moduledoc #{since => "OTP 27.0"}.
-moduledoc """
The Erlang trace interface.
The Erlang run-time system exposes several trace points that allow users
to be notified when they are triggered. Trace points are things such as
function calls, message sending and receiving, garbage collection, and
process scheduling.
The functions in this module can be used directly, but can also be
used as building blocks to build more sophisticated debugging or
profiling tools. For debugging Erlang code it is recommended to use
`m:dbg` and for profiling to use `m:tprof`.
## Trace Sessions
All tracing is done within a trace session. Trace sessions can be
[created](`session_create/3`) and [destroyed](`session_destroy/1`)
dynamically. Each session has its own tracer that will receive all trace
messages. Several sessions can exist at the same time without interfering with
each other. When a trace session is destroyed, all its trace settings are
automatically cleaned up.
*Example*:
```erlang
%% Create a tracer process that will receive the trace events
1> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
<0.91.0>
%% Create a session using the Tracer
2> Session = trace:session_create(my_session, Tracer, []).
{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}
%% Setup call tracing on self()
3> trace:process(Session, self(), true, [call]).
1
%% Setup call tracing on lists:seq/2
4> trace:function(Session, {lists,seq,2}, [], []).
1
%% Call the traced function
5> lists:seq(1, 10).
{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message
[1,2,3,4,5,6,7,8,9,10] % The return value
%% Cleanup the trace session
6> trace:session_destroy(Session).
ok
```
## Node Local Tracing Only
The functions in this module only operates on the local node. That is, both the
traced processes/ports as well as the tracer process/port/module must all reside
on the same local node as the call is made. To trace remote nodes use `m:dbg` or
`m:ttb`.
> #### Change {: .info }
>
> This `trace` module was introduced in OTP 27.0. The interface and semantics are
> similar to the older functions `erlang:trace/3`, `erlang:trace_pattern/3`,
> and `erlang:trace_info/2`.
>
> The main difference is the old functions operate on a single static
> trace session per node. That could impose the problem that different
> users and tools would interfere with each other's trace settings. The new trace
> functions in this module all operate on dynamically created trace sesssions
> isolated from each other. Also, this makes it easier to safely disable all trace
> settings when done by a single call to `session_destroy/1`.
>
> To change an existing tool to use the interface the following table can be
> useful:
>
> | Old function call | corresponds to |
> | ------------------------------------------- | ------------------------------------------------------------------ |
> | [`erlang:trace(Pid, ...)`][1] | [`process(S, Pid, ...)`][p] |
> | [`erlang:trace(processes, ...)`][1] | [`process(S, all, ...)`][p] |
> | [`erlang:trace(existing_processes, ...)`][1] | [`process(S, existing, ...)`][p] |
> | [`erlang:trace(new_processes, ...)`][1] | [`process(S, new, ...)`][p] |
> | [`erlang:trace(ports, ...)`][1] | [`port(S, all, ...)`][o] |
> | [`erlang:trace(existing_ports, ...)`][1] | [`port(S, existing, ...)`][o] |
> | [`erlang:trace(new_ports, ...)`][1] | [`port(S, new, ...)`][o] |
> | [`erlang:trace(all, ...)`][1] | [`process(S, all, ...)`][p] and [`port(S, all, ...)`][o] |
> | [`erlang:trace(existing, ...)`][1] | [`process(S, existing, ...)`][p] and [`port(S, existing, ...)`][o] |
> | [`erlang:trace(new, ...)`][1] | [`process(S, new, ...)`][p] and [`port(S, new, ...)`][o] |
> | [`erlang:trace_pattern(MFA, ...)`][2] | [`function(S, MFA, ...)`][f] |
> | [`erlang:trace_pattern(send, ...)`][2] | [`send(S, ...)`][s] |
> | [`erlang:trace_pattern('receive', ...)`][2] | [`recv(S, ...)`][r] |
> | [`erlang:trace_info(...)`][3] | [`info(S, ...)`][i] |
>
> Argument `S` is the trace session that must first be created with
> `session_create/3`. The other arguments (implied by `...`) are mostly the
> same. The only other difference is that the tracer is always the tracer
> specified when the session was created. Options `{tracer,T}`, `{tracer,M,S}`,
> `{meta,T}`, and `{meta,M,S}` are therefore not allowed, and the default tracer is
> never the calling process.
[1]: `erlang:trace/3`
[2]: `erlang:trace_pattern/3`
[3]: `erlang:trace_info/2`
[p]: `process/4`
[o]: `port/4`
[f]: `function/4`
[s]: `send/3`
[r]: `recv/3`
[i]: `info/3`
""".
-export([function/4,
send/3,
recv/3,
process/4,
port/4,
info/3,
delivered/2,
session_create/3,
session_destroy/1,
session_info/1]).
%% We must inline these functions so that the stacktrace points to
%% the correct function.
-compile({inline, [error_with_inherited_info/3]}).
-export_type([session/0,
session_strong_ref/0,
session_weak_ref/0]).
-doc """
A handle to an isolated trace session.
""".
-doc #{ since => "OTP 27.0" }.
-type session() :: {session_strong_ref(), session_weak_ref()}
| session_weak_ref().
-opaque session_strong_ref() :: reference().
-doc """
A weak session handle as returned by `session_info/1`. A weak session handle can
be used like a full session handle, but it will not prevent the session from
being destroyed when the last strong handle is garbage collected.
""".
-opaque session_weak_ref() :: {atom(), integer()}.
-type trace_info_flag() ::
arity |
call |
exiting |
garbage_collection |
monotonic_timestamp |
procs |
ports |
'receive' |
return_to |
running |
running_procs |
running_ports |
send |
set_on_first_link |
set_on_first_spawn |
set_on_link |
set_on_spawn |
silent |
strict_monotonic_timestamp |
timestamp.
-type trace_flag() ::
trace_info_flag() | all | cpu_timestamp.
-type trace_pattern_mfa() ::
{atom(),atom(),arity() | '_'}.
-type match_variable() :: atom(). % Approximation of '$1' | '$2' | ...
-type trace_match_spec() ::
[{[term()] | '_' | match_variable() ,[term()],[term()]}].
-type trace_pattern_flag() ::
global | local |
meta | {meta, Pid :: pid()} |
{meta, TracerModule :: module(), TracerState :: term()} |
call_count |
call_time |
call_memory.
-type trace_info_item_result() ::
{traced, global | local | false | undefined} |
{match_spec, trace_match_spec() | false | undefined} |
{meta, pid() | port() | false | undefined | []} |
{meta, module(), term() } |
{meta_match_spec, trace_match_spec() | false | undefined} |
{call_count, non_neg_integer() | boolean() | undefined} |
{call_time | call_memory, [{pid(), non_neg_integer(),
non_neg_integer(), non_neg_integer()}] | boolean() | undefined}.
-type trace_info_return() ::
undefined |
{flags, [trace_info_flag()]} |
{tracer, pid() | port() | []} |
{tracer, module(), term()} |
trace_info_item_result() |
{all, [ trace_info_item_result() ] | false | undefined}.
%% process/4
-doc """
Turn on or off trace flags for one or more processes.
Argument `Session` is the trace session to operate on as returned by
`session_create/3`.
Argument `PidSpec` is either a process identifier (pid) for a local process or
one of the following atoms:
- **`all`** - All currently existing processes and all that will be
created in the future.
- **`existing`** - All currently existing processes.
- **`new`** - All processes that will be created in the future.
Argument `How` is either `true` to turn on trace flags or `false` to turn them off.
Argument `FlagList` can contain any number of the following flags (the "message
tags" refers to the list of [`trace messages`](#process_trace_messages)):
- **`all`** - Sets all trace flags except `cpu_timestamp`, which
is in its nature different than the others.
- **`send`** - Traces sending of messages. Limit which sent messages to trace by
calling `send/3`.
Message tags: [`send`](#process_trace_messages_send) and
[`send_to_non_existing_process`](#process_trace_messages_send_to_non_existing_process).
- **`'receive'`** - Traces receiving of messages. Limit which received messages
to trace by calling `recv/3`.
Message tags: [`'receive'`](#process_trace_messages_receive).
- **`call`** - Traces certain function calls. Specify which function calls to
trace by calling `function/4`.
Message tags: [`call`](#process_trace_messages_call) and
[`return_from`](#process_trace_messages_return_from).
- **`silent`** - Used with the `call` trace flag. The `call`, `return_from`, and
`return_to` trace messages are inhibited if this flag is set, but they are
executed as normal if there are match specifications.
Silent mode is inhibited by executing `trace:process(_, _, false, [silent|_])`, or
by a match specification executing the function `{silent, false}`.
The `silent` trace flag facilitates setting up a trace on many or even all
processes in the system. The trace can then be activated and deactivated using
the match specification function `{silent,Bool}`, giving a high degree of
control of which functions with which arguments that trigger the trace.
Message tags: [`call`](#process_trace_messages_call),
[`return_from`](#process_trace_messages_return_from), and
[`return_to`](#process_trace_messages_return_to). Or rather, the
absence of.
- **`return_to`** - Used with the `call` trace flag. Traces the return from a
traced function back to its caller. Only works for functions traced with
option `local` to `function/4`.
The semantics is that a trace message is sent when a call traced function
returns, that is, when a chain of tail recursive calls ends. Only one trace
message is sent per chain of tail recursive calls, so the properties of tail
recursiveness for function calls are kept while tracing with this flag. Using
`call` and `return_to` trace together makes it possible to know exactly in
which function a process executes at any time.
To get trace messages containing return values from functions, use the
`{return_trace}` match specification action instead.
Message tags: [`return_to`](#process_trace_messages_return_to).
- **`procs`** - Traces process-related events.
Message tags: [`spawn`](#process_trace_messages_spawn),
[`spawned`](#process_trace_messages_spawned),
[`exit`](#process_trace_messages_exit),
[`register`](#process_trace_messages_register),
[`unregister`](#process_trace_messages_unregister),
[`link`](#process_trace_messages_link),
[`unlink`](#process_trace_messages_unlink),
[`getting_linked`](#process_trace_messages_getting_linked), and
[`getting_unlinked`](#process_trace_messages_getting_unlinked).
- **`running`** - Traces scheduling of processes.
Message tags: [`in`](#process_trace_messages_in_proc) and
[`out`](#process_trace_messages_out_proc).
- **`exiting`** - Traces scheduling of exiting processes.
Message tags:
[`in_exiting`](#process_trace_messages_in_exiting_proc),
[`out_exiting`](#process_trace_messages_out_exiting_proc), and
[`out_exited`](#process_trace_messages_out_exited_proc).
- **`running_procs`** - Traces scheduling of processes just like `running`.
However, this option also includes schedule events when the process executes
within the context of a port without being scheduled out itself.
Message tags: [`in`](#process_trace_messages_in_proc) and
[`out`](#process_trace_messages_out_proc).
- **`garbage_collection`** - Traces garbage collections of processes.
Message tags:
[`gc_minor_start`](#process_trace_messages_gc_minor_start),
[`gc_max_heap_size`](#process_trace_messages_gc_max_heap_size), and
[`gc_minor_end`](#process_trace_messages_gc_minor_end).
- **`timestamp`{: #timestamp }** - Includes a time stamp in all trace
messages. The time stamp (Ts) has the same form as returned by
`erlang:now/0`.
- **`cpu_timestamp`** - A global trace flag for the Erlang node that makes all
trace time stamps using flag `timestamp` to be in CPU time, not wall clock
time. That is, `cpu_timestamp` is not be used if `monotonic_timestamp` or
`strict_monotonic_timestamp` is enabled. Only allowed with `PidPortSpec==all`.
If the host machine OS does not support high-resolution CPU time measurements,
`process/4` exits with `badarg`. Notice that most OS do not
synchronize this value across cores, so be prepared that time can seem to go
backwards when using this option.
- **`monotonic_timestamp`** - Includes an
[Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) time stamp
in all trace messages. The time stamp (Ts) has the same format and value as
produced by [`erlang:monotonic_time(nanosecond)`](`erlang:monotonic_time/1`). This
flag overrides flag `cpu_timestamp`.
- **`strict_monotonic_timestamp`** - Includes an time stamp consisting of
[Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) and a
monotonically increasing integer in all trace messages. The time stamp (Ts)
has the same format and value as produced by `{`
[`erlang:monotonic_time(nanosecond)`](`erlang:monotonic_time/1`)`,`
[`erlang:unique_integer([monotonic])`](`erlang:unique_integer/1`)`}`. This flag
overrides flag `cpu_timestamp`.
If multiple time stamp flags are passed, `timestamp` has precedence over
`strict_monotonic_timestamp`, which in turn has precedence over
`monotonic_timestamp`. All time stamp flags are remembered, so if two are
passed and the one with highest precedence later is disabled, the other one
becomes active.
- **`arity`** - Used with the `call` trace flag. `{M, F, Arity}` is specified
instead of `{M, F, Args}` in call trace messages.
- **`set_on_spawn`** - Makes any process created by a traced process inherit all
its trace flags, including flag `set_on_spawn` itself.
- **`set_on_first_spawn`** - Makes the first process created by a traced process
inherit all its trace flags, excluding flag `set_on_first_spawn` itself. That
is, after the first spawn is done, `set_on_first_spawn` will be cleared in
both the spawned process and the spawning process.
If both are set, `set_on_first_spawn` will supersede `set_on_spawn`.
- **`set_on_link`** - Makes any process linked by a traced process inherit all
its trace flags, including flag `set_on_link` itself.
- **`set_on_first_link`** - Makes the first process linked to by a traced
process inherit all its trace flags, excluding flag `set_on_first_link`
itself. That is, after the first link is done, `set_on_first_link` will be
cleared in both the linked process and the linking process.
If both are set, `set_on_first_link` will supersede `set_on_link`.
The tracing process receives the _trace messages_ described in the following
list. `Pid` is the process identifier of the traced process in which the traced
event has occurred. The third tuple element is the message tag.
If flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is
specified, the first tuple element is `trace_ts` instead, and the time stamp is
added as an extra element last in the message tuple.
If a match specification (applicable only for `call`, `send`, and `'receive'`
tracing) contains a `{message}` action function with a non-boolean value, that
value is added as an extra element to the message tuple either in the last
position or before the timestamp (if it is present).
Trace messages:
[](){: #process_trace_messages }
- **`{trace, Pid, send, Msg, To}`{: #process_trace_messages_send }** - When
process `Pid` sends message `Msg` to process `To`.
- **`{trace, Pid, send_to_non_existing_process, Msg, To}`{:
#process_trace_messages_send_to_non_existing_process }** - When process `Pid`
sends message `Msg` to the non-existing process `To`.
- **`{trace, Pid, 'receive', Msg}`{: #process_trace_messages_receive }** -
When process `Pid` receives message `Msg`. If `Msg` is set to time-out, a receive
statement can have timed out, or the process received a message with the
payload `timeout`.
- **`{trace, Pid, call, {M, F, Args}}`{: #process_trace_messages_call }** - When
process `Pid` calls a traced function. The return values of calls are never
supplied, only the call and its arguments.
Trace flag `arity` can be used to change the contents of this message, so that
`Arity` is specified instead of `Args`.
- **`{trace, Pid, return_to, {M, F, Arity}}`{: #process_trace_messages_return_to
}** - When process `Pid` returns _to_ the specified function. This trace
message is sent if both the flags `call` and `return_to` are set, and the
function is set to be traced on _local_ function calls. The message is only
sent when returning from a chain of tail recursive function calls, where at
least one call generated a `call` trace message (that is, the functions match
specification matched, and `{message, false}` was not an action).
- **`{trace, Pid, return_from, {M, F, Arity}, ReturnValue}`{:
#process_trace_messages_return_from }** - When `Pid` returns _from_ the
specified function. This trace message is sent if flag `call` is set, and the
function has a match specification with a `return_trace` or `exception_trace`
action.
- **`{trace, Pid, exception_from, {M, F, Arity}, {Class, Value}}`{:
#process_trace_messages_exception_from }** - When `Pid` exits _from_ the
specified function because of an exception. This trace message is sent if flag
`call` is set, and the function has a match specification with an
`exception_trace` action.
- **`{trace, Pid, spawn, Pid2, {M, F, Args}}`{: #process_trace_messages_spawn
}** - When `Pid` spawns a new process `Pid2` with the specified function call
as entry point.
`Args` is supposed to be the argument list, but can be any term if the spawn
is erroneous.
- **`{trace, Pid, spawned, Pid2, {M, F, Args}}`{:
#process_trace_messages_spawned }** - When `Pid` is spawned by process `Pid2`
with the specified function call as entry point.
`Args` is supposed to be the argument list, but can be any term if the spawn
is erroneous.
- **`{trace, Pid, exit, Reason}`{: #process_trace_messages_exit }** - When `Pid`
exits with reason `Reason`.
- **`{trace, Pid, register, RegName}`{: #process_trace_messages_register
}** - When process `Pid` gets the name `RegName` registered.
- **`{trace, Pid, unregister, RegName}`{: #process_trace_messages_unregister
}** - When process `Pid` gets the name `RegName` unregistered. This is done
automatically when a registered process or port exits.
- **`{trace, Pid, link, Pid2}`{: #process_trace_messages_link }** - When `Pid`
links to a process `Pid2`.
- **`{trace, Pid, unlink, Pid2}`{: #process_trace_messages_unlink }** - When
`Pid` removes the link from a process `Pid2`.
- **`{trace, Pid, getting_linked, Pid2}`{:
#process_trace_messages_getting_linked }** - When `Pid` gets linked to a
process `Pid2`.
- **`{trace, Pid, getting_unlinked, Pid2}`{:
#process_trace_messages_getting_unlinked }** - When `Pid` gets unlinked
from a process `Pid2`.
- **`{trace, Port, open, Pid, Driver}`{: #process_trace_messages_open }** - When
`Pid` opens a new port `Port` with the running `Driver`.
`Driver` is the name of the driver as an atom.
- **[](){: #process_trace_messages_in_proc }
`{trace, Pid, in | in_exiting, {M, F, Arity} | 0}`{:
#process_trace_messages_in_exiting_proc }**
When `Pid` is scheduled to run. The process runs in function `{M, F, Arity}`.
On some rare occasions, the current function cannot be determined, then the
last element is `0`.
- **[](){: #process_trace_messages_out_proc } [](){:
#process_trace_messages_out_exiting_proc }
`{trace, Pid, out | out_exiting | out_exited, {M, F, Arity} | 0}`{:
#process_trace_messages_out_exited_proc }**
When `Pid` is scheduled out. The process was running in function `{M, F,
Arity}`. On some rare occasions, the current function cannot be determined,
then the last element is `0`.
- **`{trace, Pid, gc_minor_start, Info}`{:
#process_trace_messages_gc_minor_start }** - [](){: #gc_minor_start } Sent
when a garbage collection of the young generation is about to be started.
`Info` is a list of two-element tuples, where the first element is a key,
and the second is the value. Do not depend on any order of the tuples.
The following keys are defined:
- **`heap_size`** - The size of the used part of the heap.
- **`heap_block_size`** - The size of the memory block used for storing the
heap and the stack.
- **`old_heap_size`** - The size of the used part of the old heap.
- **`old_heap_block_size`** - The size of the memory block used for storing
the old heap.
- **`stack_size`** - The size of the stack.
- **`recent_size`** - The size of the data that survived the previous garbage
collection.
- **`mbuf_size`** - The combined size of message buffers associated with the
process.
- **`bin_vheap_size`** - The total size of unique off-heap binaries referenced
from the process heap.
- **`bin_vheap_block_size`** - The total size of binaries allowed in the
virtual heap in the process before doing a garbage collection.
- **`bin_old_vheap_size`** - The total size of unique off-heap binaries
referenced from the process old heap.
- **`bin_old_vheap_block_size`** - The total size of binaries allowed in the
virtual old heap in the process before doing a garbage collection.
- **`wordsize`** - For the `gc_minor_start` event it is the size of the need
that triggered the GC. For the corresponding `gc_minor_end` event it is the
size of reclaimed memory = start `heap_size` - end `heap_size`.
All sizes are in words.
- **`{trace, Pid, gc_max_heap_size, Info}`{:
#process_trace_messages_gc_max_heap_size }** - Sent when the
[`max_heap_size`](`e:erts:erlang#process_flag_max_heap_size`) is reached during
garbage collection. `Info` contains the same kind of list as in message
`gc_start`, but the sizes reflect the sizes that triggered `max_heap_size` to
be reached.
- **`{trace, Pid, gc_minor_end, Info}`{: #process_trace_messages_gc_minor_end
}** - Sent when young garbage collection is finished. `Info` contains the same
kind of list as in message `gc_minor_start`, but the sizes reflect the new
sizes after garbage collection.
- **`{trace, Pid, gc_major_start, Info}`{:
#process_trace_messages_gc_major_start }** - Sent when fullsweep garbage
collection is about to be started. `Info` contains the same kind of list as in
message `gc_minor_start`.
- **`{trace, Pid, gc_major_end, Info}`{: #process_trace_messages_gc_major_end
}** - Sent when fullsweep garbage collection is finished. `Info` contains the
same kind of list as in message `gc_minor_start`, but the sizes reflect the
new sizes after a fullsweep garbage collection.
If the tracing process dies or the tracer module returns `remove`, the
flags are silently removed.
Returns a number indicating the number of processes that matched `PidSpec`.
If `PidSpec` is a process identifier, the return value is `1`. If
`PidSpec` is `all` or `existing`, the return value is the number of
processes running. If `PidSpec` is `new`, the return value is `0`.
Failure: `badarg` if the specified arguments are not supported. For example,
`cpu_timestamp` is not supported on all platforms.
""".
-doc #{ since => <<"OTP 27.0">> }.
-spec process(Session, Procs, How, FlagList) -> integer() when
Session :: session(),
Procs :: pid() | all | existing | new,
How :: boolean(),
FlagList :: [trace_flag()].
process(Session, Procs, How, FlagList) ->
ensure_tracer_module_loaded(tracer, FlagList),
try
BifProcs = case Procs of
_ when is_pid(Procs) -> Procs;
all -> processes;
existing -> existing_processes;
new -> new_processes;
processes -> Procs;
existing_processes -> Procs;
new_processes -> Procs
end,
erts_internal:trace(Session, BifProcs, How, FlagList)
catch
error:R:Stk ->
error_with_inherited_info(R, [Session, Procs, How, FlagList], Stk)
end.
%% port/4
-doc """
Turn on or off trace flags for one or more ports.
Argument `Session` is the trace session to operate on as returned by
`session_create/3`.
`PortSpec` is either a port identifier for a local port or one of the following atoms:
- **`all`** - All currently existing ports and all that will be
created in the future.
- **`existing`** - All currently existing ports.
- **`new`** - All ports that will be created in the future.
`FlagList` can contain any number of the following flags (the "message tags"
refers to the list of [`trace messages`](#port_trace_messages)):
- **`all`** - Sets all trace flags except `cpu_timestamp`, which are in its
nature different than the others.
- **`send`** - Traces sending of messages.
Message tags: [`send`](#port_trace_messages_send) and
[`send_to_non_existing_process`](#port_trace_messages_send_to_non_existing_process).
- **`'receive'`** - Traces receiving of messages.
Message tags: [`'receive'`](#port_trace_messages_receive).
- **`ports`** - Traces port-related events.
Message tags: [`open`](#port_trace_messages_open),
[`closed`](#port_trace_messages_closed),
[`register`](#port_trace_messages_register),
[`unregister`](#port_trace_messages_unregister),
[`getting_linked`](#port_trace_messages_getting_linked), and
[`getting_unlinked`](#port_trace_messages_getting_unlinked).
- **`running_ports`** - Traces scheduling of ports.
Message tags: [`in`](#port_trace_messages_in_port) and
[`out`](#port_trace_messages_out_port).
- **`timestamp`**, **`cpu_timestamp`**, **`monotonic_timestamp`**,
**`strict_monotonic_timestamp`** - Same as for timestamps in
[`process/4`](#timestamp).
The tracing process receives the _trace messages_ described in the following
list. `Port` is the port identifier of the traced port in which the traced
event has occurred. The third tuple element is the message tag.
If flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is
specified, the first tuple element is `trace_ts` instead, and the time stamp is
added as an extra element last in the message tuple. If multiple time stamp
flags are passed, `timestamp` has precedence over `strict_monotonic_timestamp`,
which in turn has precedence over `monotonic_timestamp`. All time stamp flags
are remembered, so if two are passed and the one with highest precedence later
is disabled, the other one becomes active.
If a match specification (applicable only for `send` and `'receive'`
tracing) contains a `{message}` action function with a non-boolean value, that
value is added as an extra element to the message tuple either in the last
position or before the timestamp (if it is present).
Trace messages:
[](){: #port_trace_messages }
- **`{trace, Port, send, Msg, To}`{: #port_trace_messages_send }** - When
`Port` sends message `Msg` to process `To`.
- **`{trace, Port, send_to_non_existing_process, Msg, To}`{:
#port_trace_messages_send_to_non_existing_process }** - When `Port`
sends message `Msg` to the non-existing process `To`.
- **`{trace, Port, 'receive', Msg}`{: #port_trace_messages_receive }** -
When `Port` receives message `Msg`. If `Msg` is set to time-out, a receive
statement can have timed out, or the process received a message with the
payload `timeout`.
- **`{trace, Port, register, RegName}`{: #port_trace_messages_register
}** - When `Port` gets the name `RegName` registered.
- **`{trace, Port, unregister, RegName}`{: #port_trace_messages_unregister
}** - When `Port` gets the name `RegName` unregistered. This is done
automatically when a registered process or port exits.
- **`{trace, Port, getting_linked, Pid2}`{:
#port_trace_messages_getting_linked }** - When `Port` gets linked to a
process `Pid2`.
- **`{trace, Port, getting_unlinked, Pid2}`{:
#port_trace_messages_getting_unlinked }** - When `Port` gets unlinked
from a process `Pid2`.
- **`{trace, Port, open, Pid, Driver}`{: #port_trace_messages_open }** - When
`Pid` opens a new port `Port` with the running `Driver`.
`Driver` is the name of the driver as an atom.
- **`{trace, Port, closed, Reason}`{: #port_trace_messages_closed }** - When
`Port` closes with `Reason`.
- **`{trace, Port, in, Command | 0}`{: #port_trace_messages_in_port }** -
When `Port` is scheduled to run. `Command` is the first thing the port will
execute, it can however run several commands before being scheduled out. On
some rare occasions, the current function cannot be determined, then the last
element is `0`.
The possible commands are `call`, `close`, `command`, `connect`, `control`,
`flush`, `info`, `link`, `open`, and `unlink`.
- **`{trace, Port, out, Command | 0}`{: #port_trace_messages_out_port }** -
When `Port` is scheduled out. The last command run was `Command`. On some rare
occasions, the current function cannot be determined, then the last element is
`0`. `Command` can contain the same commands as `in`
If the tracing process/port dies or the tracer module returns `remove`, the
flags are silently removed.
Returns a number indicating the number of ports that matched `PortSpec`.
If `PortSpec` is a port identifier, the return value is `1`. If
`PortSpec` is `all` or `existing`, the return value is the number of
existing ports. If `PortSpec` is `new`, the return value is `0`.
Failure: `badarg` if the specified arguments are not supported. For example,
`cpu_timestamp` is not supported on all platforms.
""".
-doc #{ since => <<"OTP 27.0">> }.
-spec port(Session, Ports, How, FlagList) -> integer() when
Session :: session(),
Ports :: port() | all | existing | new,
How :: boolean(),
FlagList :: [trace_flag()].
port(Session, Ports, How, FlagList) ->
ensure_tracer_module_loaded(tracer, FlagList),
try
BifPorts = case Ports of
_ when is_port(Ports) -> Ports;
all -> ports;
existing -> existing_ports;
new -> new_ports;
ports -> Ports;
existing_ports -> Ports;
new_ports -> Ports
end,
erts_internal:trace(Session, BifPorts, How, FlagList)
catch error:R:Stk ->
error_with_inherited_info(R, [Session, Ports, How, FlagList], Stk)
end.
%% function/4
-doc """
Enable or disable _call tracing_ for one or more functions.
Must be combined with `process/4` to set the `call` trace flag for one or more
processes.
Conceptually, call tracing works as follows. In each trace session, a
set of processes and a set of functions haven been marked for
tracing. If a traced process calls a traced function, the trace action
is taken. Otherwise, nothing happens.
To add or remove one or more processes to the set of traced processes, use
`process/4`.
Use this function to add or remove functions to the set of traced functions
in a trace session.
Argument `Session` is the trace session to operate on as returned by
`session_create/3`.
Argument **`MFA`** is to be a tuple, such as `{Module, Function, Arity}`, or the
atom `on_load` (described below). The `MFA` tuple specifies the module,
function, and arity for the functions to be traced. The atom `'_'` can be used
as a wildcard in any of the following ways:
- **`{Module,Function,'_'}`** - All functions of any arity named `Function` in
module `Module`.
- **`{Module,'_','_'}`** - All functions in module `Module`.
- **`{'_','_','_'}`** - All functions in all loaded modules.
Other combinations, such as `{Module,'_',Arity}`, are not allowed.
If argument `MFA` is the atom `on_load`, the match specification and flag list
are used on all functions in all modules that are newly loaded.
Argument **`MatchSpec`** can take the following forms:
- **`true`** - Enable tracing for the matching functions. Any match
specification is removed.
- **`false`** - Disable tracing for the matching functions. Any match
specification is removed.
- **`MatchExpression`** - A match specification. An empty list is equivalent to
`true`. For a description of match specifications, see section
[Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide
for the ERTS application.
- **`restart`** - For the `FlagList` options `call_count`, `call_time` and
`call_memory`: restarts the existing counters. The behavior is undefined for
other `FlagList` options.
- **`pause`** - For the `FlagList` options `call_count`, `call_time` and
`call_memory`: pauses the existing counters. The behavior is undefined for
other `FlagList` options.
Argument **`FlagList`** is a list of options. The following are the valid options:
- **`global`** - Turn on or off call tracing for global function calls (that
is, calls specifying the module explicitly). Only exported functions match and
only global calls generate trace messages. **This is the default if `FlagList`
is empty**.
- **`local`** - Turn on or off call tracing for all types of function calls.
Trace messages are sent whenever any of the specified functions are called,
regardless of how they are called. If flag `return_to` is set for the process,
a `return_to` message is also sent when this function returns to its caller.
- **`meta`** - Turn on or off meta-tracing for all types of function
calls. Trace messages are sent to the tracer whenever any of the specified
functions are called.
Meta-tracing traces all processes and does not care about the process trace
flags set by `process/4`, the trace flags are instead fixed to
`[call, timestamp]`.
The match specification function `{return_trace}` works with meta-trace.
- **`call_count`**{: #call_count } - Start (`MatchSpec == true`) or stop
(`MatchSpec == false`) call count tracing for all types of function calls. For
every function, a counter is incremented when the function is called, in any
process. No process trace flags need to be activated.
If call count tracing is started while already running, the count is restarted
from zero. To pause running counters, use `MatchSpec == pause`. Paused and
running counters can be restarted from zero with `MatchSpec == restart`.
To read the counter value for a function, call
[`trace:info(_, MFA, call_count)`](`info/3`).
- **`call_time`**{: #call_time } - Start (`MatchSpec` is `true`) or stops (`MatchSpec` is `false`)
call time tracing for all types of function calls. For every function, a
counter is incremented when the function is called and the time spent in the
function is measured and accumulated in another counter. The counters are
stored for each call traced process.
If call time tracing is started while already running, the count and time
restart from zero. To pause running counters, use `MatchSpec == pause`. Paused
and running counters can be restarted from zero with `MatchSpec == restart`.
To read the counter values, use `info/3`.
- **`call_memory`**{: #call_memory } - Start (`MatchSpec == true`) or stop
(`MatchSpec == false`) call memory tracing for all types of function calls.
If call memory tracing is started while already running, counters and
allocations restart from zero. To pause running counters, use
`MatchSpec == pause`. Paused and running counters can be restarted from zero
with `MatchSpec == restart`.
To read the counter value, use `info/3`.
Option `global` cannot be combined with any of the other options, which all
perform some kind of local tracing. If global tracing is specified for
a set of functions, then `local`, `meta`, `call_count`, `call_time`,
and `call_memory` tracing for the matching set of functions are
disabled, and vice versa.
When disabling trace, the option must match the type of trace set on the
function. That is, local tracing must be disabled with option `local` and global
tracing with option `global` (or no option), and so on.
Part of a match specification cannot be changed directly. If a function has
a match specification, it can be replaced with a new one. Function `info/3` can
be used to retrieve the existing match specification.
Returns the number of functions matching argument `MFA`. Zero is returned if
none matched or if `on_load` was specified.
Fails by raising an error exception with an error reason of:
- **`badarg`** - If an argument is invalid.
- **`system_limit`** - If a match specification passed as argument has excessive
nesting which causes scheduler stack exhaustion for the scheduler that the
calling process is executing on.
[Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured
when starting the runtime system.
""".
-doc #{ since => <<"OTP 27.0">> }.
-spec function(Session, MFA, MatchSpec, FlagList) -> non_neg_integer() when
Session :: session(),
MFA :: trace_pattern_mfa() | on_load,
MatchSpec :: trace_match_spec()
| boolean()
| restart
| pause,
FlagList :: [ trace_pattern_flag() ].
function(Session, MFA, MatchSpec, FlagList) ->
ensure_tracer_module_loaded(meta, FlagList),
try erts_internal:trace_pattern(Session, MFA, MatchSpec, FlagList) of
Res -> Res
catch error:R:Stk ->
error_with_inherited_info(R, [Session, MFA, MatchSpec, FlagList], Stk)
end.
%% send/3
-doc """
Set trace pattern for _message sending_.
Must be combined with `process/4` or `port/4` to set the `send` trace flag for
one or more processes or ports.
Argument `Session` is the trace session to operate on as returned by
`session_create/3`.
The default value for the `send` trace pattern in each session is
`true`. That is, all messages sent from processes having `send` trace
enabled will be traced. Use this function to limit traced `send`
events based on the message content, the sender, and/or the receiver.
Argument `MatchSpec` can take the following forms:
- **`MatchExpression`** - A match specification. The matching is done on
the list `[Receiver, Msg]`. `Receiver` is the process or port identity of the
receiver and `Msg` is the message term. The pid of the sending process can be
accessed with the guard function `self/0`. An empty list is the same as
`true`. For more information, see section
[Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide
for the ERTS application.
- **`true`** - Enable tracing for all sent messages (from `send` traced
processes). Any match specification is removed.
- **`false`** - Disable tracing for all sent messages. Any match specification
is removed.
Argument `FlagList` must be `[]`.
The return value is always `1`.
*Examples:*
Only trace messages to a specific process `Pid`:
```erlang
> trace:send(Session, [{[Pid, '_'],[],[]}], []).
1
```
Only trace messages matching `{reply, _}`:
```erlang
> trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).
1
```
Only trace messages sent to the sender itself:
```erlang
> trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).
1
```
Only trace messages sent to other nodes:
```erlang
> trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
1
```
> #### Note {: .info }
>
> A match specification for `send` trace can use all guard and body functions
> except `caller`.
Fails by raising an error exception with an error reason of:
- **`badarg`** - If an argument is invalid.
- **`system_limit`** - If a match specification passed as argument has excessive
nesting which causes scheduler stack exhaustion for the scheduler that the
calling process is executing on.
[Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured
when starting the runtime system.
""".