檢視原始碼 erl_tracer 行為 (erts v15.2)

Erlang 追蹤器行為。

這個行為模組實作了 Erlang 追蹤系統的後端。每當觸發追蹤探針時,就會呼叫這個模組中的函式。 enabledtrace 函式都會在觸發追蹤探針的實體上下文中呼叫。這表示啟用追蹤的額外開銷,很大程度取決於在這些函式中花費的時間。因此,在這些函式中盡可能少做工作。

注意

這個行為中的所有函式都必須實作為 NIF。這個限制可能會在未來的版本中移除。下方提供了一個追蹤器模組 NIF 範例

警告

請勿在任何回呼中傳送訊息或發出埠口命令給 Tracee。這是被禁止的,可能會導致各種奇怪的行為,包括但不限於無限遞迴。

Erl 追蹤器模組範例

在這個範例中,具有 NIF 後端的追蹤器模組會為每個僅包含傳送者和接收者的 send 追蹤標籤傳送訊息。使用這個追蹤器模組,可以使用更輕量的訊息追蹤器,它只記錄誰向誰傳送訊息。

以下是在 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");
}

摘要

回呼

每當觸發追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 call | return_to 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 garbage_collection 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 ports 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 procs 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 'receive' 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 running_ports 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 running_procs | running 的追蹤點時,就會呼叫此回呼。

每當觸發帶有追蹤旗標 send 的追蹤點時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_call/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_garbage_collection/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_ports/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_procs/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_receive/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_running_ports/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_running_procs/3 回呼傳回 trace 時,就會呼叫此回呼。

當觸發追蹤點且 Module:enabled_send/3 回呼傳回 trace 時,就會呼叫此回呼。

類型

連結到這個類型

trace_opts()

檢視原始碼 (自 OTP 19.0 起)
-type trace_opts() ::
          #{extra => term(),
            match_spec_result => term(),
            scheduler_id => non_neg_integer(),
            timestamp => timestamp | cpu_timestamp | monotonic | strict_monotonic}.

追蹤對象的選項

  • timestamp - 如果設定,則表示已要求追蹤器包含時間戳記。

  • extra - 如果設定,則表示追蹤點已包含關於追蹤事件的額外資料。額外資料的內容取決於觸發了哪個 TraceTagextra 追蹤資料對應於 trace:process/4 中描述的追蹤元組中的第五個元素。

  • match_spec_result - 如果設定,則表示已要求追蹤器包含執行過的匹配規格的輸出。

  • scheduler_id - 如果設定,則追蹤器將包含排程器 ID。

連結到這個類型

trace_tag()

檢視原始碼 (自 OTP 19.0 起)

追蹤器被呼叫時使用的不同追蹤標籤。

每個追蹤標籤都在 Module:trace/5 中詳細說明。

連結到這個類型

trace_tag_call()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_call() :: call | return_to | return_from | exception_from.
連結到這個類型

trace_tag_gc()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_gc() :: gc_minor_start | gc_minor_end | gc_major_start | gc_major_end.
連結到這個類型

trace_tag_ports()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_ports() :: open | closed | link | unlink | getting_linked | getting_unlinked.
連結到這個類型

trace_tag_procs()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_procs() ::
          spawn | spawned | exit | link | unlink | getting_linked | getting_unlinked | register |
          unregister.
連結到這個類型

trace_tag_receive()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_receive() :: 'receive'.
連結到這個類型

trace_tag_running_ports()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_running_ports() :: in | out | in_exiting | out_exiting | out_exited.
連結到這個類型

trace_tag_running_procs()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_running_procs() :: in | out | in_exiting | out_exiting | out_exited.
連結到這個類型

trace_tag_send()

檢視原始碼 (自 OTP 19.0 起)
-type trace_tag_send() :: send | send_to_non_existing_process.
連結到這個類型

tracee()

檢視原始碼 (自 OTP 19.0 起)
-type tracee() :: port() | pid() | undefined.

追蹤所屬的程序或埠口。

回呼

連結到這個回呼

enabled(TraceTag, TracerState, Tracee)

檢視原始碼 (自 OTP 19.0 起)
-callback enabled(TraceTag, TracerState, Tracee) -> Result
                     when
                         TraceTag :: trace_tag() | trace_status,
                         TracerState :: term(),
                         Tracee :: tracee(),
                         Result :: trace | discard | remove.

每當觸發追蹤點時,就會呼叫此回呼。

它允許追蹤器決定是否要產生追蹤。這個檢查會盡可能提前進行,以限制與追蹤相關的額外開銷。如果傳回 trace,則會建立必要的追蹤資料,並呼叫追蹤器的追蹤回呼。如果傳回 discard,則會捨棄這個追蹤呼叫,且不會進行追蹤呼叫。

trace_status 是一種特殊的 TraceTag 類型,用於檢查追蹤器是否仍處於活動狀態。它會在多種情境下呼叫,但最重要的是當使用此追蹤器啟動追蹤時。如果在檢查 trace_status 時傳回 remove,則會從追蹤對象中移除追蹤器。

這個函式可能會在每個追蹤點被呼叫多次,因此務必使其快速且沒有副作用。

連結到這個回呼

enabled_call(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_call(TraceTag, TracerState, Tracee) -> Result
                          when
                              TraceTag :: trace_tag_call(),
                              TracerState :: term(),
                              Tracee :: tracee(),
                              Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 call | return_to 的追蹤點時,就會呼叫此回呼。

如果未定義 enabled_call/3,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_garbage_collection(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result
                                        when
                                            TraceTag :: trace_tag_gc(),
                                            TracerState :: term(),
                                            Tracee :: tracee(),
                                            Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 garbage_collection 的追蹤點時,就會呼叫此回呼。

如果未定義 enabled_garbage_collection/3,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_ports(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_ports(TraceTag, TracerState, Tracee) -> Result
                           when
                               TraceTag :: trace_tag_ports(),
                               TracerState :: term(),
                               Tracee :: tracee(),
                               Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 ports 的追蹤點時,就會呼叫此回呼。

如果 enabled_ports/3 未定義,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_procs(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_procs(TraceTag, TracerState, Tracee) -> Result
                           when
                               TraceTag :: trace_tag_procs(),
                               TracerState :: term(),
                               Tracee :: tracee(),
                               Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 procs 的追蹤點時,就會呼叫此回呼。

如果 enabled_procs/3 未定義,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_receive(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_receive(TraceTag, TracerState, Tracee) -> Result
                             when
                                 TraceTag :: trace_tag_receive(),
                                 TracerState :: term(),
                                 Tracee :: tracee(),
                                 Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 'receive' 的追蹤點時,就會呼叫此回呼。

如果 enabled_receive/3 未定義,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_running_ports(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_running_ports(TraceTag, TracerState, Tracee) -> Result
                                   when
                                       TraceTag :: trace_tag_running_ports(),
                                       TracerState :: term(),
                                       Tracee :: tracee(),
                                       Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 running_ports 的追蹤點時,就會呼叫此回呼。

如果 enabled_running_ports/3 未定義,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_running_procs(TraceTag, TracerState, Tracee)

檢視原始碼 (自 OTP 19.0 起)
-callback enabled_running_procs(TraceTag, TracerState, Tracee) -> Result
                                   when
                                       TraceTag :: trace_tag_running_procs(),
                                       TracerState :: term(),
                                       Tracee :: tracee(),
                                       Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 running_procs | running 的追蹤點時,就會呼叫此回呼。

如果 enabled_running_procs/3 未定義,則會改為呼叫 Module:enabled/3

連結到這個回呼

enabled_send(TraceTag, TracerState, Tracee)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback enabled_send(TraceTag, TracerState, Tracee) -> Result
                          when
                              TraceTag :: trace_tag_send(),
                              TracerState :: term(),
                              Tracee :: tracee(),
                              Result :: trace | discard | remove.

每當觸發帶有追蹤旗標 send 的追蹤點時,就會呼叫此回呼。

如果 enabled_send/3 未定義,則會改為呼叫 Module:enabled/3

連結到這個回呼

trace(Tag, TracerState, Tracee, Msg, Opts)

檢視原始碼 (自 OTP 19.0 起)
-callback trace(seq_trace, TracerState, Label, SeqTraceInfo, Opts) -> Result
                   when
                       TracerState :: term(),
                       Label :: term(),
                       SeqTraceInfo :: term(),
                       Opts :: trace_opts(),
                       Result :: ok;
               (TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                   when
                       TraceTag :: trace_tag(),
                       TracerState :: term(),
                       Tracee :: tracee(),
                       TraceTerm :: term(),
                       Opts :: trace_opts(),
                       Result :: ok.

當觸發追蹤點且 Module:enabled/3 回呼傳回 trace 時,就會呼叫此回呼。

追蹤器所需的任何副作用都應在此執行。追蹤點的有效負載位於 TraceTerm 中。TraceTerm 的內容取決於觸發的 TraceTagTraceTerm 對應於 trace:process/4 中描述的追蹤元組中的第四個元素。

如果追蹤元組有五個元素,則第五個元素將作為 Opts 對應中的 extra 值傳送。

TraceTag seq_trace 的處理方式略有不同。對於 seq_trace 沒有 Tracee,而是指定與 seq_trace 事件相關聯的 Label

如需有關 LabelSeqTraceInfo 可以是什麼的更多資訊,請參閱 seq_trace

連結到這個回呼

trace_call(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_call(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                        when
                            TraceTag :: trace_tag_call(),
                            TracerState :: term(),
                            Tracee :: tracee(),
                            TraceTerm :: term(),
                            Opts :: trace_opts(),
                            Result :: ok.

當觸發追蹤點且 Module:enabled_call/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_call/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_garbage_collection(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_garbage_collection(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                                      when
                                          TraceTag :: trace_tag_gc(),
                                          TracerState :: term(),
                                          Tracee :: tracee(),
                                          TraceTerm :: term(),
                                          Opts :: trace_opts(),
                                          Result :: ok.

當觸發追蹤點且 Module:enabled_garbage_collection/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_garbage_collection/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                         when
                             TraceTag :: trace_tag(),
                             TracerState :: term(),
                             Tracee :: tracee(),
                             TraceTerm :: term(),
                             Opts :: trace_opts(),
                             Result :: ok.

當觸發追蹤點且 Module:enabled_ports/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_ports/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                         when
                             TraceTag :: trace_tag(),
                             TracerState :: term(),
                             Tracee :: tracee(),
                             TraceTerm :: term(),
                             Opts :: trace_opts(),
                             Result :: ok.

當觸發追蹤點且 Module:enabled_procs/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_procs/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_receive(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_receive(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                           when
                               TraceTag :: trace_tag_receive(),
                               TracerState :: term(),
                               Tracee :: tracee(),
                               TraceTerm :: term(),
                               Opts :: trace_opts(),
                               Result :: ok.

當觸發追蹤點且 Module:enabled_receive/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_receive/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_running_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_running_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                                 when
                                     TraceTag :: trace_tag_running_ports(),
                                     TracerState :: term(),
                                     Tracee :: tracee(),
                                     TraceTerm :: term(),
                                     Opts :: trace_opts(),
                                     Result :: ok.

當觸發追蹤點且 Module:enabled_running_ports/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_running_ports/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_running_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (自 OTP 19.0 起)
-callback trace_running_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                                 when
                                     TraceTag :: trace_tag_running_procs(),
                                     TracerState :: term(),
                                     Tracee :: tracee(),
                                     TraceTerm :: term(),
                                     Opts :: trace_opts(),
                                     Result :: ok.

當觸發追蹤點且 Module:enabled_running_procs/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_running_procs/5 未定義,則會改為呼叫 Module:trace/5

連結到這個回呼

trace_send(TraceTag, TracerState, Tracee, TraceTerm, Opts)

檢視原始碼 (選用) (自 OTP 19.0 起)
-callback trace_send(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result
                        when
                            TraceTag :: trace_tag_send(),
                            TracerState :: term(),
                            Tracee :: tracee(),
                            TraceTerm :: term(),
                            Opts :: trace_opts(),
                            Result :: ok.

當觸發追蹤點且 Module:enabled_send/3 回呼傳回 trace 時,就會呼叫此回呼。

如果 trace_send/5 未定義,則會改為呼叫 Module:trace/5