This repository has been archived by the owner on Apr 30, 2021. It is now read-only.
Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
lualogging/src/logging.lua
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
206 lines (180 sloc)
5.85 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ------------------------------------------------------------------------------- | |
| -- includes a new tostring function that handles tables recursively | |
| -- | |
| -- @author Danilo Tuler (tuler@ideais.com.br) | |
| -- @author Andre Carregal (info@keplerproject.org) | |
| -- @author Thiago Costa Ponte (thiago@ideais.com.br) | |
| -- | |
| -- @copyright 2004-2013 Kepler Project | |
| ------------------------------------------------------------------------------- | |
| local type, table, string, _tostring, tonumber = type, table, string, tostring, tonumber | |
| local select = select | |
| local error = error | |
| local format = string.format | |
| local pairs = pairs | |
| local ipairs = ipairs | |
| local logging = { | |
| -- Meta information | |
| _COPYRIGHT = "Copyright (C) 2004-2013 Kepler Project", | |
| _DESCRIPTION = "A simple API to use logging features in Lua", | |
| _VERSION = "LuaLogging 1.3.0", | |
| -- The DEBUG Level designates fine-grained instring.formational events that are most | |
| -- useful to debug an application | |
| DEBUG = "DEBUG", | |
| -- The INFO level designates instring.formational messages that highlight the | |
| -- progress of the application at coarse-grained level | |
| INFO = "INFO", | |
| -- The WARN level designates potentially harmful situations | |
| WARN = "WARN", | |
| -- The ERROR level designates error events that might still allow the | |
| -- application to continue running | |
| ERROR = "ERROR", | |
| -- The FATAL level designates very severe error events that will presumably | |
| -- lead the application to abort | |
| FATAL = "FATAL", | |
| } | |
| local LEVEL = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"} | |
| local MAX_LEVELS = #LEVEL | |
| -- make level names to order | |
| for i=1,MAX_LEVELS do | |
| LEVEL[LEVEL[i]] = i | |
| end | |
| -- private log function, with support for formating a complex log message. | |
| local function LOG_MSG(self, level, fmt, ...) | |
| local f_type = type(fmt) | |
| if f_type == 'string' then | |
| if select('#', ...) > 0 then | |
| local status, msg = pcall(format, fmt, ...) | |
| if status then | |
| return self:append(level, msg) | |
| else | |
| return self:append(level, "Error formatting log message: " .. msg) | |
| end | |
| else | |
| -- only a single string, no formating needed. | |
| return self:append(level, fmt) | |
| end | |
| elseif f_type == 'function' then | |
| -- fmt should be a callable function which returns the message to log | |
| return self:append(level, fmt(...)) | |
| end | |
| -- fmt is not a string and not a function, just call tostring() on it. | |
| return self:append(level, logging.tostring(fmt)) | |
| end | |
| -- create the proxy functions for each log level. | |
| local LEVEL_FUNCS = {} | |
| for i=1,MAX_LEVELS do | |
| local level = LEVEL[i] | |
| LEVEL_FUNCS[i] = function(self, ...) | |
| -- no level checking needed here, this function will only be called if it's level is active. | |
| return LOG_MSG(self, level, ...) | |
| end | |
| end | |
| -- do nothing function for disabled levels. | |
| local function disable_level() end | |
| -- improved assertion function. | |
| local function assert(exp, ...) | |
| -- if exp is true, we are finished so don't do any processing of the parameters | |
| if exp then return exp, ... end | |
| -- assertion failed, raise error | |
| error(format(...), 2) | |
| end | |
| ------------------------------------------------------------------------------- | |
| -- Creates a new logger object | |
| -- @param append Function used by the logger to append a message with a | |
| -- log-level to the log stream. | |
| -- @return Table representing the new logger object. | |
| ------------------------------------------------------------------------------- | |
| function logging.new(append) | |
| if type(append) ~= "function" then | |
| return nil, "Appender must be a function." | |
| end | |
| local logger = {} | |
| logger.append = append | |
| logger.setLevel = function (self, level) | |
| local order = LEVEL[level] | |
| assert(order, "undefined level `%s'", _tostring(level)) | |
| if self.level then | |
| self:log(logging.WARN, "Logger: changing loglevel from %s to %s", self.level, level) | |
| end | |
| self.level = level | |
| self.level_order = order | |
| -- enable/disable levels | |
| for i=1,MAX_LEVELS do | |
| local name = LEVEL[i]:lower() | |
| if i >= order then | |
| self[name] = LEVEL_FUNCS[i] | |
| else | |
| self[name] = disable_level | |
| end | |
| end | |
| end | |
| -- generic log function. | |
| logger.log = function (self, level, ...) | |
| local order = LEVEL[level] | |
| assert(order, "undefined level `%s'", _tostring(level)) | |
| if order < self.level_order then | |
| return | |
| end | |
| return LOG_MSG(self, level, ...) | |
| end | |
| -- initialize log level. | |
| logger:setLevel(logging.DEBUG) | |
| return logger | |
| end | |
| ------------------------------------------------------------------------------- | |
| -- Prepares the log message | |
| ------------------------------------------------------------------------------- | |
| function logging.prepareLogMsg(pattern, dt, level, message) | |
| local logMsg = pattern or "%date %level %message\n" | |
| message = string.gsub(message, "%%", "%%%%") | |
| logMsg = string.gsub(logMsg, "%%date", dt) | |
| logMsg = string.gsub(logMsg, "%%level", level) | |
| logMsg = string.gsub(logMsg, "%%message", message) | |
| return logMsg | |
| end | |
| ------------------------------------------------------------------------------- | |
| -- Converts a Lua value to a string | |
| -- | |
| -- Converts Table fields in alphabetical order | |
| ------------------------------------------------------------------------------- | |
| local function tostring(value) | |
| local str = '' | |
| if (type(value) ~= 'table') then | |
| if (type(value) == 'string') then | |
| str = string.format("%q", value) | |
| else | |
| str = _tostring(value) | |
| end | |
| else | |
| local auxTable = {} | |
| for key in pairs(value) do | |
| if (tonumber(key) ~= key) then | |
| table.insert(auxTable, key) | |
| else | |
| table.insert(auxTable, tostring(key)) | |
| end | |
| end | |
| table.sort(auxTable) | |
| str = str..'{' | |
| local separator = "" | |
| local entry = "" | |
| for _, fieldName in ipairs(auxTable) do | |
| if ((tonumber(fieldName)) and (tonumber(fieldName) > 0)) then | |
| entry = tostring(value[tonumber(fieldName)]) | |
| else | |
| entry = fieldName.." = "..tostring(value[fieldName]) | |
| end | |
| str = str..separator..entry | |
| separator = ", " | |
| end | |
| str = str..'}' | |
| end | |
| return str | |
| end | |
| logging.tostring = tostring | |
| if _VERSION ~= 'Lua 5.2' then | |
| -- still create 'logging' global for Lua versions < 5.2 | |
| _G.logging = logging | |
| end | |
| return logging |