瀏覽代碼

ft: 代码修改

master
SisMaker 3 年之前
父節點
當前提交
197e66ec6f
共有 6 個檔案被更改,包括 287 行新增24 行删除
  1. +3
    -3
      README.md
  2. +257
    -0
      c_src/tracer/erl_tracer_nif.c
  3. +17
    -3
      c_src/tracer/tpTracerNif.c
  4. 二進制
      priv/tpTracerNif.so
  5. +0
    -16
      rebar.config
  6. +10
    -2
      src/tracer/tpTracerNif.erl

+ 3
- 3
README.md 查看文件

@ -212,14 +212,14 @@ end.
当出于分析目的而跟踪文件时,您很可能不关心某些事件,例如链接的进程。要禁用任何不必要的事件分析,请传递mode选项:
```
1> lg:trace('_', lg_file_tracer, "traces.lz4", #{mode => utils}).
1> lg:trace('_', lg_file_tracer, "traces.lz4", #{mode => profile}).
```
[[tracing_running]]
您还可以通过启用选项来获得仅对配置文件有用的额外事件。 该running选项将启用事件,这些事件指示何时安排进出流程。 启用它通常会很有用,因为它可以启用其他统计信息,但会占用大量资源,因此默认情况下未启用:
```
1> lg:trace('_', lg_file_tracer, "traces.lz4", #{mode => utils, running => true}).
1> lg:trace('_', lg_file_tracer, "traces.lz4", #{mode => profile, running => true}).
```
[[tracing_send]]
@ -241,7 +241,7 @@ fEventFrame。这两个选项使您可以控制文件写入或旋转的频率。
以下示例将文件大小限制为100MB:
```
1> eTpf:trace('_', lg_file_tracer, #{fBaseName => "traces.lz4", fMaxSize => 100000000}, #{mode => utils, running =>true}).
1> eTpf:trace('_', lg_file_tracer, #{fBaseName => "traces.lz4", fMaxSize => 100000000}, #{mode => profile, running =>true}).
```
在测试此功能期间,目前实施的轮换似乎很昂贵,因此您应注意不要设置太低的值。

+ 257
- 0
c_src/tracer/erl_tracer_nif.c 查看文件

@ -0,0 +1,257 @@
/*
* %CopyrightBegin%
*
* Copyright Ericsson 2015-2016. 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%
*/
/*
* Purpose: NIF library for process/port tracer
*
*/
#define STATIC_ERLANG_NIF 1
#include "erl_nif.h"
#include "config.h"
#include "sys.h"
#ifdef VALGRIND
# include <valgrind/memcheck.h>
#endif
/* 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_tracer, nif_funcs, load, NULL, upgrade, unload)
#define ATOMS \
ATOM_DECL(call); \
ATOM_DECL(command); \
ATOM_DECL(cpu_timestamp); \
ATOM_DECL(discard); \
ATOM_DECL(exception_from); \
ATOM_DECL(extra); \
ATOM_DECL(match_spec_result); \
ATOM_DECL(monotonic); \
ATOM_DECL(ok); \
ATOM_DECL(remove); \
ATOM_DECL(return_from); \
ATOM_DECL(scheduler_id); \
ATOM_DECL(send); \
ATOM_DECL(send_to_non_existing_process); \
ATOM_DECL(seq_trace); \
ATOM_DECL(spawn); \
ATOM_DECL(strict_monotonic); \
ATOM_DECL(timestamp); \
ATOM_DECL(trace); \
ATOM_DECL(trace_status); \
ATOM_DECL(trace_ts); \
ATOM_DECL(true); \
ATOM_DECL(gc_minor_start); \
ATOM_DECL(gc_minor_end); \
ATOM_DECL(gc_major_start); \
ATOM_DECL(gc_major_end);
#define ATOM_DECL(A) static ERL_NIF_TERM atom_##A
ATOMS
#undef ATOM_DECL
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
#define ATOM_DECL(A) atom_##A = enif_make_atom(env, #A)
ATOMS
#undef ATOM_DECL
*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) {
return -1; /* Don't know how to do that */
}
if (*priv_data != NULL) {
return -1; /* Don't know how to do that */
}
if (load(env, priv_data, load_info)) {
return -1;
}
return 0;
}
static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifPid to_pid;
ErlNifPort to_port;
ERL_NIF_TERM ret = enif_is_identical(argv[0], atom_trace_status) ?
atom_remove : atom_discard;
ASSERT(argc == 3);
if (enif_get_local_pid(env, argv[1], &to_pid)) {
if (!enif_is_process_alive(env, &to_pid))
/* tracer is dead so we should remove this trace point */
return ret;
} else if (enif_get_local_port(env, argv[1], &to_port)) {
if (!enif_is_port_alive(env, &to_port))
/* tracer is dead so we should remove this trace point */
return ret;
} else {
/* The state was not a pid or a port */
return ret;
}
/* Only generate trace for when tracer != tracee */
if (enif_is_identical(argv[1], argv[2])) {
return atom_discard;
}
return atom_trace;
}
/*
-spec trace(seq_trace, TracerState :: pid() | port(),
Label :: non_neg_integer(),
Msg :: term(),
Opts :: map()) -> ignored();
trace(Tag :: atom(), TracerState :: pid() | port(),
Tracee :: pid() || port() || undefined,
Msg :: term(),
Opts :: map()) -> ignored().
*/
static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM value, msg, tt[8], opts;
ErlNifPid to_pid;
ErlNifPort to_port;
size_t tt_sz = 0;
int is_port = 0;
size_t opts_sz = 0;
ASSERT(argc == 5);
if (!enif_get_local_pid(env, argv[1], &to_pid)) {
if (!enif_get_local_port(env, argv[1], &to_port)) {
/* This only fails if argv[1] is a not a local port/pid
which should not happen as it is checked in enabled */
ASSERT(0);
return atom_ok;
}
is_port = 1;
}
opts = argv[4];
if (!enif_get_map_size(env, opts, &opts_sz))
opts_sz = 0;
if (opts_sz && enif_get_map_value(env, opts, atom_extra, &value)) {
tt[tt_sz++] = atom_trace;
tt[tt_sz++] = argv[2];
tt[tt_sz++] = argv[0];
tt[tt_sz++] = argv[3];
tt[tt_sz++] = value;
} else {
if (enif_is_identical(argv[0], atom_seq_trace)) {
tt[tt_sz++] = atom_seq_trace;
tt[tt_sz++] = argv[2];
tt[tt_sz++] = argv[3];
} else {
tt[tt_sz++] = atom_trace;
tt[tt_sz++] = argv[2];
tt[tt_sz++] = argv[0];
tt[tt_sz++] = argv[3];
}
}
if (opts_sz && enif_get_map_value(env, opts, atom_match_spec_result, &value)) {
tt[tt_sz++] = value;
}
if (opts_sz && enif_get_map_value(env, opts, atom_scheduler_id, &value)) {
tt[tt_sz++] = value;
}
if (opts_sz && enif_get_map_value(env, opts, atom_timestamp, &value)) {
ERL_NIF_TERM ts;
if (enif_is_identical(value, atom_monotonic)) {
ErlNifTime mon = enif_monotonic_time(ERL_NIF_NSEC);
ts = enif_make_int64(env, mon);
} else if (enif_is_identical(value, atom_strict_monotonic)) {
ErlNifTime mon = enif_monotonic_time(ERL_NIF_NSEC);
ERL_NIF_TERM unique = enif_make_unique_integer(
env, ERL_NIF_UNIQUE_MONOTONIC);
ts = enif_make_tuple2(env, enif_make_int64(env, mon), unique);
} else if (enif_is_identical(value, atom_timestamp)) {
ts = enif_now_time(env);
} else if (enif_is_identical(value, atom_cpu_timestamp)) {
ts = enif_cpu_time(env);
} else {
ASSERT(0);
goto error;
}
tt[tt_sz++] = ts;
if (tt[0] == atom_trace)
tt[0] = atom_trace_ts;
}
msg = enif_make_tuple_from_array(env, tt, tt_sz);
if (is_port) {
ErlNifBinary bin;
if (!enif_term_to_binary(env, msg, &bin))
goto error;
msg = enif_make_binary(env, &bin);
(void) enif_port_command(env, &to_port, NULL, msg);
/* if failure: port has probably died, enabled will clean up */
enif_release_binary(&bin);
} else {
(void) enif_send(env, &to_pid, NULL, msg);
/* if failure: process has probably died, enabled will clean up */
}
error:
return atom_ok;
}

+ 17
- 3
c_src/tracer/tpTracerNif.c 查看文件

@ -125,14 +125,26 @@ static ERL_NIF_TERM enabled_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM a
return atom_trace;
}
static ERL_NIF_TERM enabled_send(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
// We always want both send and send_to_non_existing_process.
return atom_trace;
}
static ERL_NIF_TERM enabled_receive(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
// We always want receive.
return atom_trace;
}
static ERL_NIF_TERM enabled_running_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
// We always want both in and out.
return atom_trace;
}
static ERL_NIF_TERM enabled_send(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
static ERL_NIF_TERM enabled_garbage_collection(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
// We always want both send and send_to_non_existing_process.
// We always want both gc_minor_start, gc_max_heap_size, and gc_minor_end.
return atom_trace;
}
@ -221,8 +233,10 @@ static ErlNifFunc nifFuns[] = {
{"enabled", 3, enabled},
{"enabled_call", 3, enabled_call},
{"enabled_procs", 3, enabled_procs},
{"enabled_running_procs", 3, enabled_running_procs},
{"enabled_send", 3, enabled_send},
{"enabled_receive", 3, enabled_receive},
{"enabled_running_procs", 3, enabled_running_procs},
{"enabled_garbage_collection", 3, enabled_garbage_collection},
{"trace", 5, trace},
};

二進制
priv/tpTracerNif.so 查看文件


+ 0
- 16
rebar.config 查看文件

@ -1,16 +0,0 @@
{erl_opts, [debug_info]}.
{deps, [
{eFmt, ".*", {git, "http://47.108.26.175:53000/SisMaker/eFmt.git", {branch, "master"}}},
{eGbh, ".*", {git, "http://47.108.26.175:53000/SisMaker/eGbh.git", {branch, "master"}}}
]}.
{shell, [
% {config, "config/sys.config"},
{apps, [eTpf]}
]}.
% {pre_hooks,
% [{"", compile, "escript c_src/eNpc compile"}]}.
% {post_hooks,
% [{"", clean, "escript c_src/eNpc clean"}]}.

+ 10
- 2
src/tracer/tpTracerNif.erl 查看文件

@ -4,8 +4,10 @@
enabled/3
, enabled_call/3
, enabled_procs/3
, enabled_running_procs/3
, enabled_send/3
, enabled_receive/3
, enabled_running_procs/3
, enabled_garbage_collection/3
, trace/5
]).
@ -34,10 +36,16 @@ enabled_call(_, _, _) ->
enabled_procs(_, _, _) ->
erlang:nif_error({not_loaded, ?MODULE}).
enabled_send(_, _, _) ->
erlang:nif_error({not_loaded, ?MODULE}).
enabled_receive(_, _, _) ->
erlang:nif_error({not_loaded, ?MODULE}).
enabled_running_procs(_, _, _) ->
erlang:nif_error({not_loaded, ?MODULE}).
enabled_send(_, _, _) ->
enabled_garbage_collection(_, _, _) ->
erlang:nif_error({not_loaded, ?MODULE}).
trace(_, _, _, _, _) ->

Loading…
取消
儲存