Tarantool development patches archive
 help / color / mirror / Atom feed
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: tml <tarantool-patches@dev.tarantool.org>
Subject: [Tarantool-patches] [PATCH v8 08/12] lua/log: allow to configure logging without a box
Date: Wed,  3 Jun 2020 01:18:13 +0300	[thread overview]
Message-ID: <20200602221817.645015-9-gorcunov@gmail.com> (raw)
In-Reply-To: <20200602221817.645015-1-gorcunov@gmail.com>

We bring in an ability to configure logger early without
calling box.cfg{}. For this sake log.cfg({}) becomes a
callable table. One can provide arguments of the looger
which later will be propagated back to box.cfg table on
demand.

Another notable change is that the settings in log module
become defaults value, thus if one configured log before
the box then new settings get propagated to box's default
logging settings (previously they are silently reset to
defaults).

Fixes #689

@TarantoolBot documnent
Title: Module log

To configure log module eary without initializing box module
at all call the `log.cfg({})` method, where the following
arguments are acceptable:

 - `log` to specify file, pipe or syslog (same as
   `box.cfg{log}` option); the default value is nil
   and stderr is used;

 - `level` to specify logging level (1-7); the default
   value is 5;

 - `format` to specify output encoding ('plain' or 'json');
   the default value is 'plain';

 - `nonblock` to open logging output in nonblocking mode
   (`true` or `false`); the default value is `false`.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 src/box/lua/load_cfg.lua |   9 +++
 src/lua/log.lua          | 132 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index 7612deb90..a9024ee64 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -481,6 +481,12 @@ local function modules_reload_cfg(cfg)
     log.box_api.on_reload_cfg(cfg)
 end
 
+-- Test if modules support dynamic change
+-- of the key provided.
+local function modules_may_dynamic_cfg(key, val)
+    return log.box_api.on_may_dynamic_cfg(key, val)
+end
+
 -- Return true if two configurations are equivalent.
 local function compare_cfg(cfg1, cfg2)
     if type(cfg1) ~= type(cfg2) then
@@ -506,6 +512,9 @@ local function reload_cfg(oldcfg, cfg)
     local ordered_cfg = {}
     -- iterate over original table because prepare_cfg() may store NILs
     for key, val in pairs(cfg) do
+        if not modules_may_dynamic_cfg(key, val) then
+            box.error(box.error.RELOAD_CFG, key);
+        end
         if dynamic_cfg[key] == nil and oldcfg[key] ~= val then
             box.error(box.error.RELOAD_CFG, key);
         end
diff --git a/src/lua/log.lua b/src/lua/log.lua
index 87ce313e5..33f7a5892 100644
--- a/src/lua/log.lua
+++ b/src/lua/log.lua
@@ -119,6 +119,27 @@ local log2box_keys = {
     ['format']      = 'log_format',
 }
 
+local box_module_cfg = nil
+
+-- Reflect changes in box.cfg (if
+-- box.cfg been initialized).
+local function update_box_cfg(k)
+    if box_module_cfg ~= nil then
+        local update = function(k, v)
+            if box_module_cfg[v] ~= log_cfg[k] then
+                box_module_cfg[v] = log_cfg[k]
+            end
+        end
+        if k ~= nil then
+            update(k, log2box_keys[k])
+        else
+            for k, v in pairs(log2box_keys) do
+                update(k, v)
+            end
+        end
+    end
+end
+
 local function say(level, fmt, ...)
     if ffi.C.log_level < level then
         -- don't waste cycles on debug.getinfo()
@@ -170,6 +191,7 @@ end
 local function log_level(level)
     ffi.C.say_set_log_level(level)
     rawset(log_cfg, 'level', level)
+    update_box_cfg('level')
 end
 
 local function log_format(name)
@@ -190,17 +212,47 @@ local function log_format(name)
         ffi.C.say_set_log_format(ffi.C.SF_PLAIN)
     end
     rawset(log_cfg, 'format', name)
+    update_box_cfg('format')
 end
 
 local function log_pid()
     return tonumber(ffi.C.log_pid)
 end
 
--- Apply defaut config to the box module
+-- The keys to be assigned once either
+-- from log.cfg interface or from box.cfg.
+local box2log_static_keys = {
+    ['log']         = 'log',
+    ['log_nonblock']= 'nonblock',
+}
+
+local function box_on_may_dynamic_cfg(box_key, box_val)
+    local log_key = box2log_static_keys[box_key]
+    -- Skip non ours keys (the box_keys iterate
+    -- over the global cummulative config).
+    if log_key ~= nil then
+        if box_val ~= log_cfg[log_key] then
+            return false
+        end
+    end
+    return true
+end
+
+-- Apply defaut config to the box module.
 local function box_on_apply_default_cfg(box_cfg)
     for k, v in pairs(log2box_keys) do
         if box_cfg[v] == nil then
             box_cfg[v] = log_cfg[k]
+        else
+            -- In case if we're already initialized
+            -- via the log.cfg() interface make
+            -- the key may be changed dynamically.
+            if ffi.C.say_logger_initialized() == true then
+                if not box_on_may_dynamic_cfg(v, box_cfg[v]) then
+                    local m = "log: '%s' can't be set dynamically"
+                    error(m:format(v))
+                end
+            end
         end
     end
 end
@@ -208,10 +260,82 @@ end
 -- Update own values from box interface.
 local function box_on_load_cfg(box_cfg)
     for k, v in pairs(log2box_keys) do
-        if box_cfg[v] ~= log_cfg[k] then
+        if box_cfg[v] ~= nil and box_cfg[v] ~= log_cfg[k] then
             log_cfg[k] = box_cfg[v]
         end
     end
+    -- Remember the backreference to box
+    -- module config table.
+    box_module_cfg = box_cfg
+end
+
+-- Setup dynamic parameters.
+local function dynamic_cfg(cfg)
+    for _,v in pairs(box2log_static_keys) do
+        if cfg[v] ~= nil and cfg[v] ~= log_cfg[v] then
+            local m = "log: '%s' can't be set dynamically"
+            error(m:format(v))
+        end
+    end
+
+    if cfg.level ~= nil then
+        log_level(cfg.level)
+    end
+
+    if cfg.format ~= nil then
+        log_format(cfg.format)
+    end
+
+    -- The log_x helpers above update box
+    -- settings on their own, so no need
+    -- for more update_box_cfg calls.
+end
+
+-- Load or reload configuration via log.cfg({}) call.
+local function load_cfg(oldcfg, cfg)
+    cfg = cfg or {}
+
+    if cfg.format ~= nil then
+        if fmt_str2num[cfg.format] == nil then
+            local m = "log: 'format' must be %s"
+            error(m:format(fmt_list()))
+        end
+    end
+
+    if cfg.level ~= nil then
+        if type(cfg.level) ~= 'number' then
+            error("log: 'level' option must be a number")
+        end
+    end
+
+    if cfg.nonblock ~= nil then
+        if type(cfg.nonblock) ~= 'boolean' then
+            error("log: 'nonblock' option must be 'true' or 'false'")
+        end
+    end
+
+    if ffi.C.say_logger_initialized() == true then
+        return dynamic_cfg(cfg)
+    end
+
+    cfg.level = cfg.level or log_cfg.level
+    cfg.format = cfg.format or log_cfg.format
+    cfg.nonblock = cfg.nonblock or log_cfg.nonblock
+
+    -- We never allow confgure the logger in background
+    -- mode since we don't know how the box will be configured
+    -- later.
+    ffi.C.say_logger_init(cfg.log, cfg.level,
+                          cfg.nonblock, cfg.format, 0)
+
+    -- Update log_cfg vars to show them in module
+    -- configuration output.
+    rawset(log_cfg, 'log', cfg.log)
+    rawset(log_cfg, 'level', cfg.level)
+    rawset(log_cfg, 'nonblock', cfg.nonblock)
+    rawset(log_cfg, 'format', cfg.format)
+
+    update_box_cfg()
 end
 
 local compat_warning_said = false
@@ -235,6 +359,9 @@ local log = {
     pid = log_pid,
     level = log_level,
     log_format = log_format,
+    cfg = setmetatable(log_cfg, {
+        __call = load_cfg,
+    }),
 
     -- Internal API to box module, not for users,
     -- names can be changed.
@@ -247,6 +374,7 @@ local log = {
         end,
         on_load_cfg = box_on_load_cfg,
         on_reload_cfg = box_on_load_cfg,
+        on_may_dynamic_cfg = box_on_may_dynamic_cfg,
         on_apply_default_cfg = box_on_apply_default_cfg,
     },
 }
-- 
2.26.2

  parent reply	other threads:[~2020-06-02 22:19 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-02 22:18 [Tarantool-patches] [PATCH v8 00/12] lua/log: add an ability to setup logger without box.cfg{} Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 01/12] core/say: do not reconfig early set up logger Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 02/12] core/say: use say_logger_initialized in say_logger_free Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 03/12] lua/log: declare say_logger_init and say_logger_initialized Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 04/12] lua/log: put string constants to map Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 05/12] lua/log: do not allow to set json for boot logger Cyrill Gorcunov
2020-06-03  6:59   ` Oleg Babin
2020-06-03  7:34     ` Cyrill Gorcunov
2020-06-03  9:44       ` Kirill Yukhin
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 06/12] lua/log: declare log as separate variable Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 07/12] lua/log: use log module settings inside box.cfg Cyrill Gorcunov
2020-06-03  7:00   ` Oleg Babin
2020-06-02 22:18 ` Cyrill Gorcunov [this message]
2020-06-03  7:01   ` [Tarantool-patches] [PATCH v8 08/12] lua/log: allow to configure logging without a box Oleg Babin
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 09/12] test: logger -- use log module directly Cyrill Gorcunov
2020-06-03  7:02   ` Oleg Babin
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 10/12] log/lua: allow to specify logging level as a string Cyrill Gorcunov
2020-06-03  7:03   ` Oleg Babin
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 11/12] lua/log: use log_cfg instead of ffi's instances Cyrill Gorcunov
2020-06-02 22:18 ` [Tarantool-patches] [PATCH v8 12/12] test: logger -- consider more cases Cyrill Gorcunov
2020-06-03  7:03   ` Oleg Babin
2020-06-03  6:59 ` [Tarantool-patches] [PATCH v8 00/12] lua/log: add an ability to setup logger without box.cfg{} Oleg Babin
2020-06-03  7:09 ` Oleg Babin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200602221817.645015-9-gorcunov@gmail.com \
    --to=gorcunov@gmail.com \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v8 08/12] lua/log: allow to configure logging without a box' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox