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.

On Wed, Oct 31, 2012 at 2:24 PM,  <j...@apache.org> 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 <j...@apache.org>
> Authored: Fri Oct 26 20:12:06 2012 +0200
> Committer: Jan Lehnardt <j...@apache.org>
> 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) ->
>

Reply via email to