Sweet, thanks! :) On Nov 1, 2012, at 17:49 , Paul Davis <[email protected]> wrote:
> I should've been more clear that I don't think this is a blocker, I > just wanted to make a note that the common case was going to end up > being to ets tables (assuming most people don't list nearly every > module with a custom format). The mochiglobal approach is easy enough > that we can drop in a replacement in the future without an API change > so I'm not worried about letting this through given how useful it > looks. > > On Thu, Nov 1, 2012 at 7:41 AM, Jan Lehnardt <[email protected]> wrote: >> >> On Nov 1, 2012, at 00:05 , Paul Davis <[email protected]> wrote: >> >>> Clever. Though I worry a bit about turning each log statement into two >>> ets lookups in the common case. We could look into mochiweb_global.erl >>> or similar that would turn that try/etc/catch/ets into a single >>> function call. >> >> Thanks for the review! >> >> Each request already makes several requests to ets for stats. Do you >> think two more make a big difference? >> >> I’ll have a look at mochiweb_global.erl and see how I can apply that. >> >> Cheers >> Jan >> -- >> >>> >>> On Wed, Oct 31, 2012 at 2:24 PM, <[email protected]> wrote: >>>> Updated Branches: >>>> refs/heads/1585-feature-per-module-log-levels [created] 72a9f86db >>>> >>>> >>>> Module Level Logging >>>> >>>> With this patch, you can set log levels per CouchDB module that >>>> overrides the default set in `[log] level = `. >>>> >>>> For example: >>>> >>>> [log] >>>> level = info >>>> >>>> [log_level_by_module] >>>> couch_httpd = debug >>>> >>>> This will have all modules log at level 'info' and `couch_httpd` log >>>> at level 'debug'. >>>> >>>> See src/*/*.erl for the various CouchDB modules. >>>> >>>> Based on work started by Robert Newson. >>>> >>>> >>>> Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo >>>> Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/72a9f86d >>>> Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/72a9f86d >>>> Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/72a9f86d >>>> >>>> Branch: refs/heads/1585-feature-per-module-log-levels >>>> Commit: 72a9f86db8479f91388773c4a712e9626f468e54 >>>> Parents: 8ccf696 >>>> Author: Jan Lehnardt <[email protected]> >>>> Authored: Fri Oct 26 20:12:06 2012 +0200 >>>> Committer: Jan Lehnardt <[email protected]> >>>> Committed: Wed Oct 31 19:00:36 2012 +0100 >>>> >>>> ---------------------------------------------------------------------- >>>> etc/couchdb/local.ini | 7 ++++++ >>>> src/couchdb/couch_db.hrl | 4 +- >>>> src/couchdb/couch_log.erl | 43 ++++++++++++++++++++++++++++++++++++--- >>>> 3 files changed, 48 insertions(+), 6 deletions(-) >>>> ---------------------------------------------------------------------- >>>> >>>> >>>> http://git-wip-us.apache.org/repos/asf/couchdb/blob/72a9f86d/etc/couchdb/local.ini >>>> ---------------------------------------------------------------------- >>>> diff --git a/etc/couchdb/local.ini b/etc/couchdb/local.ini >>>> index 9e711e1..a5db26f 100644 >>>> --- a/etc/couchdb/local.ini >>>> +++ b/etc/couchdb/local.ini >>>> @@ -37,6 +37,13 @@ >>>> [log] >>>> ;level = debug >>>> >>>> +[log_level_by_module] >>>> +; In this section you can specify any of the four log levels 'none', >>>> 'info', >>>> +; 'error' or 'debug' on a per-module basis. See src/*/*.erl for various >>>> +; modules. >>>> +;couch_httpd = error >>>> + >>>> + >>>> [os_daemons] >>>> ; For any commands listed here, CouchDB will attempt to ensure that >>>> ; the process remains alive. Daemons should monitor their environment >>>> >>>> http://git-wip-us.apache.org/repos/asf/couchdb/blob/72a9f86d/src/couchdb/couch_db.hrl >>>> ---------------------------------------------------------------------- >>>> diff --git a/src/couchdb/couch_db.hrl b/src/couchdb/couch_db.hrl >>>> index 65eb7f0..325fb98 100644 >>>> --- a/src/couchdb/couch_db.hrl >>>> +++ b/src/couchdb/couch_db.hrl >>>> @@ -37,14 +37,14 @@ >>>> -define(DEFAULT_ATTACHMENT_CONTENT_TYPE, <<"application/octet-stream">>). >>>> >>>> -define(LOG_DEBUG(Format, Args), >>>> - case couch_log:debug_on() of >>>> + case couch_log:debug_on(?MODULE) of >>>> true -> >>>> couch_log:debug(Format, Args); >>>> false -> ok >>>> end). >>>> >>>> -define(LOG_INFO(Format, Args), >>>> - case couch_log:info_on() of >>>> + case couch_log:info_on(?MODULE) of >>>> true -> >>>> couch_log:info(Format, Args); >>>> false -> ok >>>> >>>> http://git-wip-us.apache.org/repos/asf/couchdb/blob/72a9f86d/src/couchdb/couch_log.erl >>>> ---------------------------------------------------------------------- >>>> diff --git a/src/couchdb/couch_log.erl b/src/couchdb/couch_log.erl >>>> index fc7b393..047a4d4 100644 >>>> --- a/src/couchdb/couch_log.erl >>>> +++ b/src/couchdb/couch_log.erl >>>> @@ -17,6 +17,7 @@ >>>> -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([debug_on/1, info_on/1, get_level/1, get_level_integer/1, >>>> set_level/2]). >>>> -export([read/2]). >>>> >>>> % gen_event callbacks >>>> @@ -73,18 +74,26 @@ init([]) -> >>>> ("log", "level") -> >>>> ?MODULE:stop(); >>>> ("log", "include_sasl") -> >>>> + ?MODULE:stop(); >>>> + ("log_level_by_module", _) -> >>>> ?MODULE:stop() >>>> end), >>>> >>>> Filename = couch_config:get("log", "file", "couchdb.log"), >>>> Level = level_integer(list_to_atom(couch_config:get("log", "level", >>>> "info"))), >>>> Sasl = couch_config:get("log", "include_sasl", "true") =:= "true", >>>> + LevelByModule = couch_config:get("log_level_by_module"), >>>> >>>> case ets:info(?MODULE) of >>>> undefined -> ets:new(?MODULE, [named_table]); >>>> _ -> ok >>>> end, >>>> ets:insert(?MODULE, {level, Level}), >>>> + lists:foreach(fun({Module, ModuleLevel}) -> >>>> + ModuleLevelInteger = level_integer(list_to_atom(ModuleLevel)), >>>> + ets:insert(?MODULE, {Module, ModuleLevelInteger}) >>>> + end, LevelByModule), >>>> + >>>> >>>> case file:open(Filename, [append]) of >>>> {ok, Fd} -> >>>> @@ -101,12 +110,24 @@ debug_on() -> >>>> info_on() -> >>>> get_level_integer() =< ?LEVEL_INFO. >>>> >>>> +debug_on(Module) -> >>>> + get_level_integer(Module) =< ?LEVEL_DEBUG. >>>> + >>>> +info_on(Module) -> >>>> + get_level_integer(Module) =< ?LEVEL_INFO. >>>> + >>>> set_level(LevelAtom) -> >>>> set_level_integer(level_integer(LevelAtom)). >>>> >>>> +set_level(Module, LevelAtom) -> >>>> + set_level_integer(Module, level_integer(LevelAtom)). >>>> + >>>> get_level() -> >>>> level_atom(get_level_integer()). >>>> >>>> +get_level(Module) -> >>>> + level_atom(get_level_integer(Module)). >>>> + >>>> get_level_integer() -> >>>> try >>>> ets:lookup_element(?MODULE, level, 2) >>>> @@ -114,18 +135,28 @@ get_level_integer() -> >>>> ?LEVEL_ERROR >>>> end. >>>> >>>> +get_level_integer(Module0) -> >>>> + Module = atom_to_list(Module0), >>>> + try >>>> + [{_Module, Level}] = ets:lookup(?MODULE, Module), >>>> + Level >>>> + catch error:_ -> >>>> + get_level_integer() >>>> + end. >>>> + >>>> set_level_integer(Int) -> >>>> gen_event:call(error_logger, couch_log, {set_level_integer, Int}). >>>> >>>> +set_level_integer(Module, Int) -> >>>> + gen_event:call(error_logger, couch_log, {set_level_integer, Module, >>>> Int}). >>>> + >>>> handle_event({couch_error, ConMsg, FileMsg}, State) -> >>>> log(State, ConMsg, FileMsg), >>>> {ok, State}; >>>> -handle_event({couch_info, ConMsg, FileMsg}, #state{level = LogLevel} = >>>> State) >>>> -when LogLevel =< ?LEVEL_INFO -> >>>> +handle_event({couch_info, ConMsg, FileMsg}, #state{level = LogLevel} = >>>> State) -> >>>> log(State, ConMsg, FileMsg), >>>> {ok, State}; >>>> -handle_event({couch_debug, ConMsg, FileMsg}, #state{level = LogLevel} = >>>> State) >>>> -when LogLevel =< ?LEVEL_DEBUG -> >>>> +handle_event({couch_debug, ConMsg, FileMsg}, #state{level = LogLevel} = >>>> State) -> >>>> log(State, ConMsg, FileMsg), >>>> {ok, State}; >>>> handle_event({error_report, _, {Pid, _, _}}=Event, #state{sasl = true} = >>>> St) -> >>>> @@ -141,6 +172,10 @@ handle_event(_Event, State) -> >>>> >>>> handle_call({set_level_integer, NewLevel}, State) -> >>>> ets:insert(?MODULE, {level, NewLevel}), >>>> + {ok, ok, State#state{level = NewLevel}}; >>>> + >>>> +handle_call({set_level_integer, Module, NewLevel}, State) -> >>>> + ets:insert(?MODULE, {Module, NewLevel}), >>>> {ok, ok, State#state{level = NewLevel}}. >>>> >>>> handle_info(_Info, State) -> >>>> >>
