我有一个应用程序正在跟踪[send,'receive']的进程。但是,应用程序正在接收跟踪消息,跟踪进程正在使用code_server
等消息与进程{code_server,{module,random}}
交换消息。
有没有办法从“系统进程”中过滤掉这些消息?
答案 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}.