Erlang跟踪 - 如何忽略消息到erlang进程

时间:2012-02-11 12:03:31

标签: erlang tracing

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

有没有办法从“系统进程”中过滤掉这些消息?

1 个答案:

答案 0 :(得分:0)

您可以编写自己的事件处理程序并添加到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}.