dyntrace(3)
β¨ NAME β¨
dyntrace β interface to dynamic tracing π
Okay bestie, this is dyntrace(3), the Erlang Module Definition for the dynamic tracing hookup. No cap. π«Ά
π DESCRIPTION π
This module implements interfaces to dynamic tracing, if that stuff got compiled into the virtual machine. For a standard and/or commercial build? no dynamic tracing is available, and in that case none of the functions in this module is usable or gives any effect. It's giving "feature not in this build" energy. π
If dynamic tracing is enabled in the current build β either by configuring with ./configure --with-dynamic-trace=dtrace or with ./configure --with-dynamic-trace=systemtap β then the module can be used for two things:
- Trigger the user-probe
user_trace_i4s4in the NIF librarydyntrace.soby callingdyntrace:p/{1,2,3,4,5,6,7,8}. π - Set a user specified tag that will be present in the trace messages of both the
efile_drvand the user-probe mentioned above. π·οΈβ¨
Both building with dynamic trace probes and using them is experimental and unsupported by Erlang/OTP. It is included as an option for the developer to trace and debug performance issues in their systems. So like, it's a real tool but not a supported one, iykyk. π
The original implementation is mostly done by Scott Lystiger Fritchie as an Open Source Contribution and it should be viewed as such even though the source for dynamic tracing as well as this module is included in the main distribution. However, the ability to use dynamic tracing of the virtual machine is a very valuable contribution which OTP has every intention to maintain as a tool for the developer. Slay, honestly. π
How to write d programs or systemtap scripts can be learned from books and from a lot of pages on the Internet. This manual page does not include any documentation about using the dynamic trace tools of respective platform. However, the examples directory of the runtime_tools application contains comprehensive examples of both d and systemtap programs that will help you get started. Another source of information is the dtrace and systemtap chapters in the Runtime Tools Users' Guide. ππ¦
π DATA TYPES π
probe_arg() :: integer() | iolist().
That's the whole data type, bestie β integer() or iolist(), and that's periodt. π
β¨ FUNCTIONS β¨
okay bestie, deep breath, here comes the whole function list. every arity, every return value, every vibe. no skipping, we don't do that here π
available() -> true | false.
This function uses the NIF library to determine if dynamic tracing is available.
It will throw an exception if the dyntrace NIF library could not be loaded by the on_load function in this module. so like, if it blows up at load time, that's what you're gonna see π
If you wanna know whether the run-time system itself supports dynamic tracing, use erlang:system_info(dynamic_trace) instead. two different questions, two different answers, don't @ me.
get_tag() -> binary() | undefined.
This one hands you back the user tag that's set in the current process. If no tag is set, or dynamic tracing just isn't available, you get undefined. simple.
Also (bc it's a whole thing): it returns the user tag set in the current process or, if there's no user tag present, the last user tag that was sent to the process together with a message β same way sequential trace tokens get spread to other processes alongside messages. For the full explanation of how user tags can hitch a ride with messages, go look at spread_tag/1. And if no tag is found at all, or dynamic tracing isn't available, yep β undefined again.
p() -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, and it sends a trace message with just the user tag and zeroes/empty strings in every other field. minimal. clean. iconic.
p(probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag plus your integer or string parameter dropped into the first integer/string field.
p(probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag and the integer() or string() parameters as the first fields of their respective type.
β οΈ the rule:integer()parameters go before anystring()parameters. order matters, bestie, it's not a suggestion.
so these calls work:
dyntrace:p(1, "Hello")dyntrace:p(1, 1)dyntrace:p("Hello", "Again")
and this one is invalid because the string argument comes before the integer argument:
dyntrace:p("Hello", 1)
p(probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag and the integer() or string() parameters as the first fields of their respective type.
And again, the golden rule: integer() parameters before any string() parameters. π«Ά
p(probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag and the integer() or string() parameters as the first fields of their respective type.
integer() parameters before any string() parameters. yes, still. every time. π₯
p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag and the integer() or string() parameters as the first fields of their respective type.
integer() parameters before any string() parameters.
And now the math starts biting: there can be no more than four parameters of each type, so with five args the first parameter must be of type integer() and the last parameter of type string().
p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag and the integer() or string() parameters as the first fields of their respective type.
integer() parameters before any string() parameters.
No more than four parameters of each type β so six args means the first two parameters must be integer() and the last two must be string().
p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message with the user tag and the integer() or string() parameters as the first fields of their respective type.
integer() parameters before any string() parameters.
Same ceiling, seven args: the first three parameters must be of type integer() and the last three of type string().
p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg.
Calling this triggers the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing all the integer() and string() parameters you provided, plus any user tag set in the current process. full main character moment, every field filled π
put_tag(undefined | iodata()) -> binary() | undefined.
This sets the user tag of the current process.
The user tag is a binary(), but you're allowed to pass any iodata() β this function converts it to a binary for you automatically. slay, no manual conversion π
Your user tag gets handed to the user probes triggered by the dyntrace:p/{1,2,3,4,5,6,7,8} calls, as well as to probes in the efile driver. And like⦠in the future, user tags might get added to more probes too. watch this space.
You get the old user tag back (if there was one), or undefined if no user tag was present β or if dynamic tracing isn't enabled.
restore_tag(true | {non_neg_integer(), binary() | []}) -> true.
Puts the previous state of user tags and their spreading back exactly how it was before a call to spread_tag/1. undo button, but for tags.
Heads up: the restoring isn't limited to the same process. You can use this to turn spreading off in one process and then restore it in a freshly created process that's actually the one about to send messages:
f() ->
TagData = dyntrace:spread_tag(false),
spawn(fun() ->
dyntrace:restore_tag(TagData),
do_something()
end),
do_something_else(),
dyntrace:restore_tag(TagData).
π« real talk: handling user tags and their spreading correctly can take some effort, because Erlang programs send and receive messages in ways that sometimes make the user tag get lost β double receives, talking to a port, all that. (Ports do not handle user tags, in the same way they don't handle regular sequential trace tokens.)
spread_tag(boolean()) -> true | {non_neg_integer(), binary() | []}.
This controls whether user tags get spread to other processes with the next message.
Spreading of user tags works just like spreading of sequential trace tokens: a received user tag stays active in the process until the next message arrives (unless that message also carries the user tag). so it lingers, then it's gone. periodt.
This is the machinery used when a client process talks to a file I/O-server: it spreads the user tag over to the I/O-server and then on down to the efile driver. Using spread_tag/1 and restore_tag/1 you can flip spreading on or off and then put the previous state of the user tag right back. The TagData you get back from this call holds all the previous info, so a later call to restore_tag/1 restores the state completely β including any user tags that were already spread.
π‘ thefilemodule already spreads tags, so there's no need to manually call this function just to get user tags spread to theefiledriver through that module. it's handled.
Where this one really earns its keep is when you're, say, using the io module to talk to an I/O-server for a regular file, like this:
f() ->
{ok, F} = file:open("test.tst", [write]),
Saved = dyntrace:spread_tag(true),
io:format(F, "Hello world!", []),
dyntrace:restore_tag(Saved),
file:close(F).
In that example, any user tag set in the calling process gets spread to the I/O-server when the io:format/3 call happens. β¨
and that's the whole page, bestie, you made it π thanks for reading all the way through β this one's brought to you by Ericsson AB, runtime_tools version 2.4, living under dyntrace(3). now go set a tag and spread it π
π¦
π¦ where this page comes from
- ubuntu stonking: erlang-doc 1:29.0.6+dfsg-1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms