[tarantool-patches] [PATCH] Expose log.init function from log module
Ilya Konyukhov
runsfor at gmail.com
Tue Aug 27 18:46:42 MSK 2019
This now allows to initialize logging subsystem without calling box.cfg.
This is helpful when you want to do something before database
initialization (i.e. setup cluster connections)
Related PR: https://github.com/tarantool/tarantool/pull/4406/files
---
extra/exports | 2 ++
src/box/lua/load_cfg.lua | 30 +++++++++++++---
src/lib/core/say.c | 3 ++
src/lib/core/say.h | 1 +
src/lua/log.lua | 60 +++++++++++++++++++++++++++++++
test/app-tap/logger_init.test.lua | 42 ++++++++++++++++++++++
6 files changed, 133 insertions(+), 5 deletions(-)
create mode 100755 test/app-tap/logger_init.test.lua
diff --git a/extra/exports b/extra/exports
index 7b84a1452..90d690b9c 100644
--- a/extra/exports
+++ b/extra/exports
@@ -52,6 +52,7 @@ tt_uuid_is_equal
tt_uuid_is_nil
tt_uuid_bswap
tt_uuid_from_string
+log_initialized
log_level
log_format
uri_parse
@@ -73,6 +74,7 @@ log_type
say_set_log_level
say_logrotate
say_set_log_format
+say_logger_init
tarantool_uptime
tarantool_exit
log_pid
diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index d402468ab..175191a8a 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -6,6 +6,10 @@ local private = require('box.internal')
local urilib = require('uri')
local math = require('math')
local fiber = require('fiber')
+local ffi = require('ffi')
+ffi.cdef[[
+ extern bool log_initialized;
+]]
-- Function decorator that is used to prevent box.cfg() from
-- being called concurrently by different fibers.
@@ -45,10 +49,6 @@ local default_cfg = {
vinyl_range_size = nil, -- set automatically
vinyl_page_size = 8 * 1024,
vinyl_bloom_fpr = 0.05,
- log = nil,
- log_nonblock = nil,
- log_level = 5,
- log_format = "plain",
io_collect_interval = nil,
readahead = 16320,
snap_io_rate_limit = nil, -- no limit
@@ -84,6 +84,13 @@ local default_cfg = {
net_msg_max = 768,
}
+local default_log_cfg = {
+ log = nil,
+ log_nonblock = nil,
+ log_level = 5,
+ log_format = "plain",
+}
+
-- types of available options
-- could be comma separated lua types or 'any' if any type is allowed
local template_cfg = {
@@ -389,6 +396,17 @@ local function apply_default_cfg(cfg, default_cfg)
end
end
+local function apply_default_log_cfg(cfg, default_cfg)
+ if not ffi.C.log_initialized then
+ apply_default_cfg(cfg, default_cfg)
+ else
+ cfg.log = log.cfg.init_str
+ cfg.log_level = log.level()
+ cfg.log_format = log.log_format()
+ cfg.log_nonblock = log.cfg.nonblock
+ end
+end
+
-- Return true if two configurations are equivalent.
local function compare_cfg(cfg1, cfg2)
if type(cfg1) ~= type(cfg2) then
@@ -469,7 +487,9 @@ setmetatable(box, {
local function load_cfg(cfg)
cfg = upgrade_cfg(cfg, translate_cfg)
cfg = prepare_cfg(cfg, default_cfg, template_cfg, modify_cfg)
- apply_default_cfg(cfg, default_cfg);
+ apply_default_cfg(cfg, default_cfg)
+ apply_default_log_cfg(cfg, default_log_cfg)
+
-- Save new box.cfg
box.cfg = cfg
if not pcall(private.cfg_check) then
diff --git a/src/lib/core/say.c b/src/lib/core/say.c
index 64a637c58..fe8592761 100644
--- a/src/lib/core/say.c
+++ b/src/lib/core/say.c
@@ -50,6 +50,8 @@
pid_t log_pid = 0;
int log_level = S_INFO;
+bool log_initialized = false;
+
enum say_format log_format = SF_PLAIN;
enum { SAY_SYSLOG_DEFAULT_PORT = 512 };
@@ -701,6 +703,7 @@ say_logger_init(const char *init_str, int level, int nonblock,
dup2(log_default->fd, STDOUT_FILENO);
}
}
+ log_initialized = true;
return;
fail:
diag_log();
diff --git a/src/lib/core/say.h b/src/lib/core/say.h
index d26c3ddef..16e3bc0b6 100644
--- a/src/lib/core/say.h
+++ b/src/lib/core/say.h
@@ -69,6 +69,7 @@ enum say_format {
};
extern int log_level;
+extern bool log_initialized;
static inline bool
say_log_level_is_enabled(int level)
diff --git a/src/lua/log.lua b/src/lua/log.lua
index 312c14d5e..d419119d7 100644
--- a/src/lua/log.lua
+++ b/src/lua/log.lua
@@ -22,6 +22,9 @@ ffi.cdef[[
void
say_set_log_format(enum say_format format);
+ void
+ say_logger_init(const char *init_str, int level, int nonblock,
+ const char *format, int background);
extern sayfunc_t _say;
extern struct ev_loop;
@@ -64,6 +67,12 @@ json.cfg{
encode_invalid_as_nil = true,
}
+local cfg = setmetatable({}, {
+ __newindex = function()
+ error('Attempt to modify a read-only table')
+ end,
+})
+
local special_fields = {
"file",
"level",
@@ -124,10 +133,25 @@ local function log_rotate()
end
local function log_level(level)
+ if level == nil then
+ return ffi.C.log_level
+ end
+ rawset(cfg, 'level', level)
+
return ffi.C.say_set_log_level(level)
end
local function log_format(format_name)
+ if format_name == nil then
+ if ffi.C.log_format == ffi.C.SF_PLAIN then
+ return 'plain'
+ elseif ffi.C.log_format == ffi.C.SF_JSON then
+ return 'json'
+ else
+ return
+ end
+ end
+
if format_name == "json" then
if ffi.C.log_type() == ffi.C.SAY_LOGGER_SYSLOG then
error("log_format: 'json' can't be used with syslog logger")
@@ -138,6 +162,8 @@ local function log_format(format_name)
else
error("log_format: expected 'json' or 'plain'")
end
+
+ rawset(cfg, 'format', format_name)
end
local function log_pid()
@@ -155,6 +181,38 @@ local compat_v16 = {
end;
}
+local function init(args)
+ args = args or {}
+ assert(type(args) == 'table', "init(args): expected 'args' to be a 'table'")
+
+ assert(type(args.init_str) == 'nil' or type(args.init_str) == 'string',
+ "init(args): expected 'args.init_str' to be either 'nil' or 'string'")
+
+ args.format = args.format or "plain"
+ assert(type(args.format) == 'string',
+ "init(args): expected 'args.format' to be a 'string'")
+
+ args.level = args.level or 5
+ assert(type(args.level) == 'number',
+ "init(args): expected 'args.level' to be a 'number'")
+
+ args.background = args.background or false
+ assert(type(args.background) == 'boolean',
+ "init(args): expected 'args.background' to be a 'boolean'")
+
+ args.nonblock = args.nonblock or false
+ assert(type(args.nonblock) == 'boolean',
+ "init(args): expected 'args.nonblock' to be a 'boolean'")
+
+ ffi.C.say_logger_init(args.init_str, args.level, args.nonblock, args.format, args.background)
+
+ rawset(cfg, 'init_str', args.init_str)
+ rawset(cfg, 'format', args.format)
+ rawset(cfg, 'level', args.level)
+ rawset(cfg, 'background', args.background)
+ rawset(cfg, 'nonblock', args.nonblock)
+end
+
return setmetatable({
warn = say_closure(S_WARN);
info = say_closure(S_INFO);
@@ -165,6 +223,8 @@ return setmetatable({
pid = log_pid;
level = log_level;
log_format = log_format;
+ init = init;
+ cfg = cfg;
}, {
__index = compat_v16;
})
diff --git a/test/app-tap/logger_init.test.lua b/test/app-tap/logger_init.test.lua
new file mode 100755
index 000000000..742dbdf04
--- /dev/null
+++ b/test/app-tap/logger_init.test.lua
@@ -0,0 +1,42 @@
+#!/usr/bin/env tarantool
+
+local test = require('tap').test('log')
+test:plan(4)
+
+local filename = "1.log"
+local message = "Hello, World!"
+
+local log = require('log')
+log.init({init_str = filename})
+
+local file = io.open(filename)
+
+while file:read() do
+end
+
+log.info(message)
+test:is(file:read():match('I>%s+(.*)'), message, 'logging works without box.cfg{}')
+
+log.verbose(message)
+test:isnil(file:read(), 'Default log level is 5 (INFO)')
+
+log.level(6)
+
+message = 'updates log level works'
+log.verbose(message)
+test:is(file:read():match('V>%s+(.*)'), message, 'verbose logging')
+
+box.cfg{
+ memtx_memory=107374182
+}
+
+while file:read() do
+end
+
+message = 'calling box.cfg does not reset logging level'
+log.verbose(message)
+test:is(file:read():match('V>%s+(.*)'), message, 'verbose logging after box.cfg')
+
+file:close()
+test:check()
+os.exit()
--
2.20.1 (Apple Git-117)
More information about the Tarantool-patches
mailing list