From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id E48D226EC9 for ; Tue, 27 Aug 2019 11:47:39 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rvkjvAj5JD0s for ; Tue, 27 Aug 2019 11:47:39 -0400 (EDT) Received: from mail-lj1-f194.google.com (mail-lj1-f194.google.com [209.85.208.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 92C5F26EC3 for ; Tue, 27 Aug 2019 11:47:39 -0400 (EDT) Received: by mail-lj1-f194.google.com with SMTP id h15so18922262ljg.10 for ; Tue, 27 Aug 2019 08:47:39 -0700 (PDT) From: Ilya Konyukhov Subject: [tarantool-patches] [PATCH] Expose log.init function from log module Date: Tue, 27 Aug 2019 18:46:42 +0300 Message-Id: <20190827154640.48315-1-runsfor@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org Cc: Ilya Konyukhov 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)