【问题标题】:Erlang Tracing - How to ignore messages to erlang processesErlang Tracing - 如何忽略到 erlang 进程的消息
【发布时间】:2012-03-03 15:30:48
【问题描述】:

我有一个应用程序正在跟踪 [send, 'receive'] 的进程。但是,应用程序正在接收跟踪消息,表明被跟踪进程正在与进程 code_server 交换消息,消息如 {code_server,{module,random}}

有什么方法可以过滤掉这些来自“系统进程”的消息吗?

【问题讨论】:

    标签: erlang trace


    【解决方案1】:

    您可以编写自己的事件处理程序并添加到 error_logger 事件管理器。在事件句柄函数中过滤你的消息。

    从couchdb开源项目复制的两个文件,例如couch_log.erl、couch_event_sup.erl

    couch_event_sup.erl
    
    % 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.
    
    -module(couch_log).
    -behaviour(gen_event).
    
    -export([start_link/0,stop/0]).
    -export([debug/2, info/2, error/2]).
    -export([debug_on/0,info_on/0,get_level/0,get_level_integer/0, set_level/1]).
    -export([init/1, handle_event/2, terminate/2, code_change/3, handle_info/2, handle_call/2]).
    -export([read/2]).
    
    -define(LEVEL_ERROR, 3).
    -define(LEVEL_INFO, 2).
    -define(LEVEL_DEBUG, 1).
    -define(LEVEL_TMI, 0).
    
    debug(Format, Args) ->
        {ConsoleMsg, FileMsg} = get_log_messages(self(), debug, Format, Args),
        gen_event:sync_notify(error_logger, {couch_debug, ConsoleMsg, FileMsg}).
    
    info(Format, Args) ->
        {ConsoleMsg, FileMsg} = get_log_messages(self(), info, Format, Args),
        gen_event:sync_notify(error_logger, {couch_info, ConsoleMsg, FileMsg}).
    
    error(Format, Args) ->
        {ConsoleMsg, FileMsg} = get_log_messages(self(), error, Format, Args),
        gen_event:sync_notify(error_logger, {couch_error, ConsoleMsg, FileMsg}).
    
    
    level_integer(error)    -> ?LEVEL_ERROR;
    level_integer(info)     -> ?LEVEL_INFO;
    level_integer(debug)    -> ?LEVEL_DEBUG;
    level_integer(tmi)      -> ?LEVEL_TMI;
    level_integer(_Else)    -> ?LEVEL_ERROR. % anything else default to ERROR level
    
    level_atom(?LEVEL_ERROR) -> error;
    level_atom(?LEVEL_INFO) -> info;
    level_atom(?LEVEL_DEBUG) -> debug;
    level_atom(?LEVEL_TMI) -> tmi.
    
    
    start_link() ->
        couch_event_sup:start_link({local, couch_log}, error_logger, couch_log, []).
    
    stop() ->
        couch_event_sup:stop(couch_log).
    
    init([]) ->
        % read config and register for configuration changes
    
        % just stop if one of the config settings change. couch_server_sup
        % will restart us and then we will pick up the new settings.
        ok = couch_config:register(
            fun("log", "file") ->
                ?MODULE:stop();
            ("log", "level") ->
                ?MODULE:stop();
            ("log", "include_sasl") ->
                ?MODULE:stop()
            end),
    
        Filename = couch_config:get("log", "file", "couchdb.log"),
        Level = level_integer(list_to_atom(couch_config:get("log", "level", "info"))),
        Sasl = list_to_atom(couch_config:get("log", "include_sasl", "true")),
    
        case ets:info(?MODULE) of
        undefined -> ets:new(?MODULE, [named_table]);
        _ -> ok
        end,
        ets:insert(?MODULE, {level, Level}),
    
        case file:open(Filename, [append]) of
        {ok, Fd} ->
            {ok, {Fd, Level, Sasl}};
        {error, eacces} ->
            {stop, {file_permission_error, Filename}};
        Error ->
            {stop, Error}
        end.
    
    debug_on() ->
        get_level_integer() =< ?LEVEL_DEBUG.
    
    info_on() ->
        get_level_integer() =< ?LEVEL_INFO.
    
    set_level(LevelAtom) ->
        set_level_integer(level_integer(LevelAtom)).
    
    get_level() ->
        level_atom(get_level_integer()).
    
    get_level_integer() ->
        try
            ets:lookup_element(?MODULE, level, 2)
        catch error:badarg ->
            ?LEVEL_ERROR
        end.
    
    set_level_integer(Int) ->
        gen_event:call(error_logger, couch_log, {set_level_integer, Int}).
    
    handle_event({couch_error, ConMsg, FileMsg}, {Fd, _LogLevel, _Sasl}=State) ->
        log(Fd, ConMsg, FileMsg),
        {ok, State};
    handle_event({couch_info, ConMsg, FileMsg}, {Fd, LogLevel, _Sasl}=State)
    when LogLevel =< ?LEVEL_INFO ->
        log(Fd, ConMsg, FileMsg),
        {ok, State};
    handle_event({couch_debug, ConMsg, FileMsg}, {Fd, LogLevel, _Sasl}=State)
    when LogLevel =< ?LEVEL_DEBUG ->
        log(Fd, ConMsg, FileMsg),
        {ok, State};
    handle_event({error_report, _, {Pid, _, _}}=Event, {Fd, _LogLevel, Sasl}=State)
    when Sasl =/= false ->
        {ConMsg, FileMsg} = get_log_messages(Pid, error, "~p", [Event]),
        log(Fd, ConMsg, FileMsg),
        {ok, State};
    handle_event({error, _, {Pid, Format, Args}}, {Fd, _LogLevel, Sasl}=State)
    when Sasl =/= false ->
        {ConMsg, FileMsg} = get_log_messages(Pid, error, Format, Args),
        log(Fd, ConMsg, FileMsg),
        {ok, State};
    handle_event({_, _, {Pid, _, _}}=Event, {Fd, LogLevel, _Sasl}=State)
    when LogLevel =< ?LEVEL_TMI ->
        % log every remaining event if tmi!
        log(Fd, Pid, tmi, "~p", [Event]),
        {ok, State};
    handle_event(_Event, State) ->
        {ok, State}.
    
    handle_call({set_level_integer, NewLevel}, {Fd, _LogLevel, Sasl}) ->
        ets:insert(?MODULE, {level, NewLevel}),
        {ok, ok, {Fd, NewLevel, Sasl}}.
    
    handle_info(_Info, State) ->
        {ok, State}.
    
    code_change(_OldVsn, State, _Extra) ->
        {ok, State}.
    
    terminate(_Arg, {Fd, _LoggingLevel, _Sasl}) ->
        file:close(Fd).
    
    log(Fd, Pid, Level, Format, Args) ->
        Msg = io_lib:format(Format, Args),
        ok = io:format("[~s] [~p] ~s~n", [Level, Pid, Msg]), % dump to console too
        Msg2 = re:replace(lists:flatten(Msg),"\\r\\n|\\r|\\n", "\r\n",
            [global, {return, list}]),
        ok = io:format(Fd, "[~s] [~s] [~p] ~s\r~n", [httpd_util:rfc1123_date(), Level, Pid, Msg2]).
    
    log(Fd, ConsoleMsg, FileMsg) ->
        ok = io:put_chars(ConsoleMsg),
        ok = io:put_chars(Fd, FileMsg).
    
    get_log_messages(Pid, Level, Format, Args) ->
        ConsoleMsg = unicode:characters_to_binary(io_lib:format(
            "[~s] [~p] " ++ Format ++ "~n", [Level, Pid | Args])),
        FileMsg = ["[", httpd_util:rfc1123_date(), "] ", ConsoleMsg],
        {ConsoleMsg, iolist_to_binary(FileMsg)}.
    
    read(Bytes, Offset) ->
        LogFileName = couch_config:get("log", "file"),
        LogFileSize = filelib:file_size(LogFileName),
        MaxChunkSize = list_to_integer(
            couch_config:get("httpd", "log_max_chunk_size", "1000000")),
        case Bytes > MaxChunkSize of
        true ->
            throw({bad_request, "'bytes' cannot exceed " ++
                integer_to_list(MaxChunkSize)});
        false ->
            ok
        end,
    
        {ok, Fd} = file:open(LogFileName, [read]),
        Start = lists:max([LogFileSize - Bytes, 0]) + Offset,
    
        % TODO: truncate chopped first line
        % TODO: make streaming
    
        {ok, Chunk} = file:pread(Fd, Start, LogFileSize),
        ok = file:close(Fd),
        Chunk.
    
    %%%couch_event_sup.erl
    % 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.
    
    %% The purpose of this module is to allow event handlers to particpate in Erlang
    %% supervisor trees. It provide a monitorable process that crashes if the event
    %% handler fails. The process, when shutdown, deregisters the event handler.
    
    -module(couch_event_sup).
    -behaviour(gen_server).
    
    -include("couch_db.hrl").
    
    -export([start_link/3,start_link/4, stop/1]).
    -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2,code_change/3]).
    
    %
    % Instead calling the
    % ok = gen_event:add_sup_handler(error_logger, my_log, Args)
    %
    % do this:
    % {ok, LinkedPid} = couch_event_sup:start_link(error_logger, my_log, Args)
    %
    % The benefit is the event is now part of the process tree, and can be
    % started, restarted and shutdown consistently like the rest of the server
    % components.
    %
    % And now if the "event" crashes, the supervisor is notified and can restart
    % the event handler.
    %
    % Use this form to named process:
    % {ok, LinkedPid} = couch_event_sup:start_link({local, my_log}, error_logger, my_log, Args)
    %
    
    start_link(EventMgr, EventHandler, Args) ->
        gen_server:start_link(couch_event_sup, {EventMgr, EventHandler, Args}, []).
    
    start_link(ServerName, EventMgr, EventHandler, Args) ->
        gen_server:start_link(ServerName, couch_event_sup, {EventMgr, EventHandler, Args}, []).
    
    stop(Pid) ->
        gen_server:cast(Pid, stop).
    
    init({EventMgr, EventHandler, Args}) ->
        case gen_event:add_sup_handler(EventMgr, EventHandler, Args) of
        ok ->
            {ok, {EventMgr, EventHandler}};
        {stop, Error} ->
            {stop, Error}
        end.
    
    terminate(_Reason, _State) ->
        ok.
    
    handle_call(_Whatever, _From, State) ->
        {ok, State}.
    
    handle_cast(stop, State) ->
        {stop, normal, State}.
    
    handle_info({gen_event_EXIT, _Handler, Reason}, State) ->
        {stop, Reason, State}.
    
    code_change(_OldVsn, State, _Extra) ->
        {ok, State}.
    

    【讨论】:

    • 你能举个例子吗?
    猜你喜欢
    • 2014-06-07
    • 2012-04-27
    • 2023-03-31
    • 2016-04-30
    • 2011-05-07
    • 2014-11-29
    • 2014-05-19
    • 2016-04-30
    • 2011-10-14
    相关资源
    最近更新 更多