-- gitano.log -- -- Statement logging depending on log level etc. -- -- Copyright 2012 Daniel Silverstone local luxio = require "luxio" local sio = require "luxio.simple" local os = require "os" local concat = table.concat local prefix = "[gitano] " local transactionid = nil local stream = sio.stderr local is_buffered = false local ERRS = 0 local WARN = 1 local CHAT = 2 local INFO = 3 local DEBUG = 4 local DEEPDEBUG = 5 local level = ERRS local LogBuf = {} LogBuf.__index = LogBuf function LogBuf:new() return setmetatable({strings = {}}, self) end function LogBuf:write(s) table.insert(self.strings, s) end function LogBuf:get() return table.concat(self.strings) end local function is_buffered_output() return is_buffered end local function buffer_output() if not is_buffered_output() then stream = LogBuf:new() is_buffered = true end end local function get_buffered_output() if is_buffered_output() then return stream:get() else return nil end end local function syslog_write(priority, ...) local strs = {...} for i = 1, #strs do strs[i] = tostring(strs[i]) or "?" end luxio.syslog(priority, transactionid .. ": " .. concat(strs, " ") .. "\n") end local function syslog_open() local ident = "gitano" transactionid = luxio.getenv("GITANO_TRANSACTION_ID") if not transactionid then transactionid = tostring(luxio.getpid()) .. "." .. os.date("%H%M%S") end luxio.openlog(ident, 0, luxio.LOG_DAEMON) return transactionid end local function syslog_close() luxio.closelog() end local function syslog_error(...) syslog_write(luxio.LOG_ERR, ...) end local function syslog_warning(...) syslog_write(luxio.LOG_WARNING, ...) end local function syslog_notice(...) syslog_write(luxio.LOG_NOTICE, ...) end local function syslog_info(...) syslog_write(luxio.LOG_INFO, ...) end local function syslog_debug(...) syslog_write(luxio.LOG_DEBUG, ...) end local function set_prefix(new_prefix) if not new_prefix then prefix = "" else if new_prefix == "true" then new_prefix = "Gitano" end prefix = "[" .. tostring(new_prefix) .. "] " end end local function AT(LVL, ...) if level >= LVL then local strs = {...} for i = 1, #strs do strs[i] = tostring(strs[i]) or "?" end stream:write(prefix .. concat(strs, " ") .. "\n") end end local function state(...) return AT(-1, ...) end local function stdout(...) local savedstream, savedprefix = stream, prefix prefix = "" if not is_buffered_output() then stream = sio.stdout end state(...) stream, prefix = savedstream, savedprefix end local function fatal(...) syslog_write(luxio.LOG_CRIT, ...) AT(ERRS, "FATAL:", ...) if is_buffered_output() then sio.stderr:write(get_buffered_output()) else stream:close() end luxio._exit(1) end local function critical(...) syslog_write(luxio.LOG_CRIT, ...) return AT(ERRS, "CRIT:", ...) end local function error(...) return AT(ERRS, "ERROR:", ...) end local function warning(...) return AT(WARN, "WARNING:", ...) end local warn = warning local function chat(...) return AT(CHAT, ...) end local function info(...) return AT(INFO, "INFO:", ...) end local function debug(...) return AT(DEBUG, "DEBUG:", ...) end local function deepdebug(...) return AT(DEEPDEBUG, "DEEPDEBUG:", ...) end local function set_level(l) if type(l) ~= "number" or l < ERRS or l > DEEPDEBUG then level = WARN warn("Attempted to set level to", tostring(l), "- defaulted to warnings") end level = l end local function bump_level(l) if type(l) ~= "number" or l < ERRS or l > DEEPDEBUG then warn("Attempted to bump level to", tostring(l), "- left alone") end if level < l then level = l end end local function cap_level(l) if type(l) ~= "number" or l < ERRS or l > DEEPDEBUG then warn("Attempted to cap level to", tostring(l), "- left alone") end if level > l then level = l end end local function get_level() return level end -- Check for default log level based on environment do local loglevel = luxio.getenv("LC_GITANO_LOG_LEVEL") or luxio.getenv("GITANO_LOG_LEVEL") if loglevel then if tonumber(loglevel) then set_level(tonumber(loglevel)) else loglevel = loglevel:lower() if (loglevel == "warn" or loglevel == "warning" or loglevel == "warnings") then level = WARN elseif loglevel == "chat" then level = CHAT elseif loglevel == "info" then level = INFO elseif loglevel == "debug" then level = DEBUG elseif (loglevel == "deepdebug" or loglevel == "ddebug" or loglevel == "all") then level = DEEPDEBUG end end if level == nil then level = WARN end end local do_debug = luxio.getenv("LC_GITANO_DEBUG") or luxio.getenv("GITANO_DEBUG") if do_debug and do_debug ~= "" then level = DEBUG end end return { level = { ALL = ERRS, ERRS = ERRS, WARN = WARN, CHAT = CHAT, INFO = INFO, DEBUG = DEBUG, DDEBUG = DEEPDEBUG, DEEPDEBUG = DEEPDEBUG, }, set_level = set_level, get_level = get_level, bump_level = bump_level, cap_level = cap_level, state = state, crit = critical, critical = critical, err = error, error = error, warn = warning, warning = warning, chat = chat, info = info, debug = debug, ddebug = deepdebug, deepdebug = deepdebug, fatal = fatal, stdout = stdout, set_prefix = set_prefix, syslog = { open = syslog_open, err = syslog_error, error = syslog_error, warn = syslog_warning, warning = syslog_warning, notice = syslog_notice, info = syslog_info, debug = syslog_debug, close = syslog_close, }, buffer_output = buffer_output, is_buffered_output = is_buffered_output, get_buffered_output = get_buffered_output }