pax_global_header00006660000000000000000000000064143650230450014514gustar00rootroot0000000000000052 comment=465c994788f1bc18fca950934fa5ec9a909f496c lualogging-1.8.2/000077500000000000000000000000001436502304500136545ustar00rootroot00000000000000lualogging-1.8.2/.editorconfig000066400000000000000000000004521436502304500163320ustar00rootroot00000000000000root = true [*] end_of_line = lf insert_final_newline = true charset = utf-8 [*.lua] indent_style = space indent_size = 2 trim_trailing_whitespace = true [*.html] indent_style = space indent_size = 2 trim_trailing_whitespace = true [Makefile] indent_style = tab trim_trailing_whitespace = true lualogging-1.8.2/.github/000077500000000000000000000000001436502304500152145ustar00rootroot00000000000000lualogging-1.8.2/.github/workflows/000077500000000000000000000000001436502304500172515ustar00rootroot00000000000000lualogging-1.8.2/.github/workflows/deploy.yml000066400000000000000000000023331436502304500212710ustar00rootroot00000000000000name: Deploy on: [ push, workflow_dispatch ] jobs: affected: uses: lunarmodules/.github/.github/workflows/list_affected_rockspecs.yml@main build: needs: affected if: ${{ needs.affected.outputs.rockspecs }} uses: lunarmodules/.github/.github/workflows/test_build_rock.yml@main with: rockspecs: ${{ needs.affected.outputs.rockspecs }} upload: needs: [ affected, build ] # Only run upload if: # 1. We are on the canonical repository (no uploads from forks) # 2. The current commit is either tagged or on the default branch (the workflow will upload dev/scm rockspecs any # time they are touched, tagged ones whenever the edited rockspec and tag match) # 3. Some rockspecs were changed — this implies the commit changing the rockspec is the same one that gets tagged if: >- ${{ github.repository == 'lunarmodules/lualogging' && ( github.ref_name == 'master' || startsWith(github.ref, 'refs/tags/') ) && needs.affected.outputs.rockspecs }} uses: lunarmodules/.github/.github/workflows/upload_to_luarocks.yml@main with: rockspecs: ${{ needs.affected.outputs.rockspecs }} secrets: apikey: ${{ secrets.LUAROCKS_APIKEY }} lualogging-1.8.2/.github/workflows/luacheck.yml000066400000000000000000000003331436502304500215520ustar00rootroot00000000000000name: Luacheck on: [ push, pull_request ] jobs: luacheck: runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Luacheck uses: lunarmodules/luacheck@v0 lualogging-1.8.2/.github/workflows/test.yml000066400000000000000000000013771436502304500207630ustar00rootroot00000000000000name: Test on: [ push, pull_request ] jobs: test: strategy: fail-fast: false matrix: luaVersion: [ "5.4", "5.3", "5.2", "5.1", "luajit" ] # , "luajit-openresty" ] debug: ["", "_G.debug = nil"] # also run with debug lib disabled runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Setup ‘lua’ uses: leafo/gh-actions-lua@v9 with: luaVersion: ${{ matrix.luaVersion }} - name: Setup ‘luarocks’ uses: leafo/gh-actions-luarocks@v4 - name: Setup dependencies run: | luarocks install luasocket - name: Run regression tests run: make test env: LUA_INIT: ${{ matrix.debug }} lualogging-1.8.2/.gitignore000066400000000000000000000000271436502304500156430ustar00rootroot00000000000000tests/test.log* *.rock lualogging-1.8.2/.luacheckrc000066400000000000000000000007071436502304500157650ustar00rootroot00000000000000--std = "ngx_lua+busted" unused_args = false redefined = false max_line_length = false globals = { --"_KONG", --"kong", --"ngx.IS_CLI", } not_globals = { "string.len", "table.getn", } ignore = { --"6.", -- ignore whitespace warnings } exclude_files = { -- The Github Actions Lua Environment ".lua", ".luarocks", ".install", } files["src/logging/nginx.lua"] = { std = "+ngx_lua" } lualogging-1.8.2/COPYRIGHT000066400000000000000000000021311436502304500151440ustar00rootroot00000000000000Copyright (c) 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lualogging-1.8.2/Makefile000066400000000000000000000011251436502304500153130ustar00rootroot00000000000000# Default prefix PREFIX = /usr/local # System's lua directory (where Lua libraries are installed) LUA_DIR= $(PREFIX)/share/lua/5.1 LUAS= src/logging/console.lua src/logging/email.lua src/logging/file.lua src/logging/rolling_file.lua src/logging/socket.lua src/logging/sql.lua src/logging/nginx.lua src/logging/rsyslog.lua src/logging/envconfig.lua ROOT_LUAS= src/logging.lua build clean: install: mkdir -p $(LUA_DIR)/logging cp $(LUAS) $(LUA_DIR)/logging cp $(ROOT_LUAS) $(LUA_DIR) test: cd tests && ./run_tests.sh cd tests && LUA_INIT="_G.debug = nil" ./run_tests.sh lint: luacheck . lualogging-1.8.2/Makefile.win000066400000000000000000000007031436502304500161100ustar00rootroot00000000000000 LUA_DIR= c:\lua5.1\lua LUAS= src\logging\console.lua src\logging\email.lua src\logging\file.lua src\logging\rolling_file.lua src\logging\socket.lua src\logging\sql.lua src/logging/nginx.lua src/logging/rsyslog.lua src/logging/envconfig.lua ROOT_LUAS= src\logging.lua build clean: install: IF NOT EXIST $(LUA_DIR)\logging mkdir $(LUA_DIR)\logging FOR %i IN ($(LUAS)) DO copy %i $(LUA_DIR)\logging FOR %i IN ($(ROOT_LUAS)) DO copy %i $(LUA_DIR) lualogging-1.8.2/README.md000066400000000000000000000036751436502304500151460ustar00rootroot00000000000000LuaLogging ========== [![Test](https://img.shields.io/github/actions/workflow/status/lunarmodules/lualogging/test.yml?label=Test&branch=master&logo=linux)](https://github.com/lunarmodules/lualogging/actions?workflow=Test) [![Luacheck](https://img.shields.io/github/actions/workflow/status/lunarmodules/lualogging/luacheck.yml?label=Luacheck&logo=Lua&branch=master)](https://github.com/lunarmodules/lualogging/actions?workflow=Luacheck) [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/lunarmodules/lualogging?logo=semver)](https://github.com/lunarmodules/lualogging/releases) [![Luarocks](https://img.shields.io/luarocks/v/tieske/lualogging?label=Luarocks&logo=Lua)](https://luarocks.org/modules/tieske/lualogging) https://lunarmodules.github.io/lualogging/ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and sql outputs. LuaLogging is free software and uses the same license as Lua. It is part of the Kepler Project. Please see docs at https://lunarmodules.github.io/lualogging/ for more details Installation ============ With LuaRocks: ```sh luarocks install lualogging ``` Latest Git revision ------------------- With LuaRocks: ```sh luarocks install lualogging --dev ``` With make: ```sh sudo make ``` Copyright ========= See [LICENSE file](https://github.com/lunarmodules/lualogging/blob/master/COPYRIGHT) History and changelog ===================== For the changelog see the [online documentation](https://lunarmodules.github.io/lualogging/index.html#history). ### Releasing a new version - update changelog in docs (`index.html`, update `history` and `status` sections) - update version in `logging.lua` - update copyright years if needed - update rockspec - commit as `release X.Y.Z` - tag as `vX.Y.Z` - push commit and tag - upload to luarocks - test luarocks installation lualogging-1.8.2/docs/000077500000000000000000000000001436502304500146045ustar00rootroot00000000000000lualogging-1.8.2/docs/console.html000066400000000000000000000115071436502304500171400ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Console appender

Console is the simplest appender. It just writes the log messages to io.stdout or io.stderr.

function logging.console {
    [destination = "stdout"|"stderr",]

    [logPattern = string,]
    [logPatterns = {
      [logging.DEBUG = string,]
      [logging.INFO  = string,]
      [logging.WARN  = string,]
      [logging.ERROR = string,]
      [logging.FATAL = string,]
    },]
    [timestampPattern = string,]
    [logLevel = log-level-constant,]
}
  • logPatterns:
    A table with logPattern strings indexed by the log-levels. A logPattern specifies how the message is written.
    If this parameter is omitted, a patterns table will be created with the parameter logPattern as the default value for each log-level. If logPattern also is omitted then each level will fall back to the current default setting, see logging.defaultLogPatterns.
  • logPattern:
    This value will be used as the default value for each log-level that was omitted in logPatterns.
  • timestampPattern:
    This is an optional parameter that can be used to specify a date/time formatting in the log message. See logging.date for the format. The default is taken from logging.defaultTimestampPattern().
  • destination:
    The destination stream, optional. The value can be either "stdout", or "stderr". The default is stdout.
  • logLevel:
    The initial log-level to set for the created logger.

Examples

local ansicolors = require("ansicolors") -- https://github.com/kikito/ansicolors.lua
local ll = require("logging")
require "logging.console"

-- set up the default logger to stderr + colorization
ll.defaultLogger(ll.console {
  logLevel = ll.DEBUG,
  destination = "stderr",
  timestampPattern = "%y-%m-%d %H:%M:%S",
  logPatterns = {
    [ll.DEBUG] = ansicolors("%date%{cyan} %level %message %{reset}(%source)\n"),
    [ll.INFO] = ansicolors("%date %level %message\n"),
    [ll.WARN] = ansicolors("%date%{yellow} %level %message\n"),
    [ll.ERROR] = ansicolors("%date%{red bright} %level %message %{reset}(%source)\n"),
    [ll.FATAL] = ansicolors("%date%{magenta bright} %level %message %{reset}(%source)\n"),
  }
})

local log = ll.defaultLogger()

log:info("logging.console test")
log:debug("debugging...")
log:error("error!")

 

 

 

 

 

 

 

XHTML 1.0 válido!

lualogging-1.8.2/docs/doc.css000066400000000000000000000063131436502304500160660ustar00rootroot00000000000000body { color: #47555c; font-size: 16px; font-family: "Open Sans", sans-serif; margin: 0; padding: 0; background: #eff4ff; } a:link { color: #008fee; } a:visited { color: #008fee; } a:hover { color: #22a7ff; } h1 { font-size:26px; } h2 { font-size:24px; } h3 { font-size:18px; } h4 { font-size:16px; } hr { height: 1px; background: #c1cce4; border: 0px; margin: 20px 0; } code { font-family: "Open Sans Mono", "Andale Mono", monospace; } tt { font-family: "Open Sans Mono", "Andale Mono", monospace; } body, td, th { } textarea, pre, tt { font-family: "Open Sans Mono", "Andale Mono", monospace; } img { border-width: 0px; } .example { background-color: #323744; color: white; font-size: 16px; padding: 16px 24px; border-radius: 2px; } div.header, div.footer { } #container { } #product { background-color: white; padding: 10px; height: 130px; border-bottom: solid #d3dbec 1px; } #product big { font-size: 42px; } #product strong { font-weight: normal; } #product_logo { float: right; } #product_name { padding-top: 15px; padding-left: 30px; font-size: 42px; font-weight: normal; } #product_description { padding-left: 30px; color: #757779; } #main { background: #eff4ff; margin: 0; } #navigation { width: 100%; background-color: rgb(44,62,103); padding: 10px; margin: 0; } #navigation h1 { display: none; } #navigation a:hover { text-decoration: underline; } #navigation ul li a { color: rgb(136, 208, 255); font-weight: bold; text-decoration: none; } #navigation ul li li a { color: rgb(136, 208, 255); font-weight: normal; text-decoration: none; } #navigation ul { display: inline; color: white; padding: 0px; padding-top: 10px; padding-bottom: 10px; } #navigation li { display: inline; list-style-type: none; padding-left: 5px; padding-right: 5px; } #navigation li { padding: 10px; padding: 10px; } #navigation li li { } #navigation li:hover a { color: rgb(166, 238, 255); } #content { padding: 20px; width: 800px; margin-left: auto; margin-right: auto; } #about { display: none; } dl.reference { background-color: white; padding: 20px; border: solid #d3dbec 1px; } dl.reference dt { padding: 5px; padding-top: 25px; color: #637bbc; } dl.reference dl dt { padding-top: 5px; color: #637383; } dl.reference dd { } @media print { body { font: 10pt "Times New Roman", "TimeNR", Times, serif; } a { font-weight:bold; color: #004080; text-decoration: underline; } #main { background-color: #ffffff; border-left: 0px; } #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } #navigation { display: none; } #product_logo { display: none; } #about img { display: none; } .example { font-family: "Andale Mono", monospace; font-size: 8pt; page-break-inside: avoid; } } lualogging-1.8.2/docs/email.html000066400000000000000000000122621436502304500165640ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Email appender

This appender can be used to send log requests through email. One email message is sent for each log request.

function logging.email {
    from = string,
    rcpt = string or string-table,
    [user = string,]
    [password = string,]
    [server = string,]
    [port = number,]
    [domain = string,]
    [headers = table,]

    [logPattern = string,]
    [logPatterns = {
      [logging.DEBUG = string,]
      [logging.INFO  = string,]
      [logging.WARN  = string,]
      [logging.ERROR = string,]
      [logging.FATAL = string,]
    },]
    [timestampPattern = string,]
    [logLevel = log-level-constant,]
}
  • from:
    The sender of the email message.
  • rcpt:
    The recipient of the email message. A string or a numerically indexed Lua table with strings.
  • user:
    User for authentication.
  • password:
    Password for authentication.
  • server:
    Server to connect to. Default is "localhost".
  • port:
    Port to connect to. Default is 25.
  • domain:
    Domain name used to greet the server. Defaults to the local machine host name.
  • headers.to:
    The recipient of the message, as an extended description.
  • headers.from:
    The sender of the message, as an extended description.
  • headers.subject:
    The subject of the message sent. This can contain patterns like the logPattern parameter.
  • logPatterns:
    A table with logPattern strings indexed by the log-levels. A logPattern specifies how the message is written.
    If this parameter is omitted, a patterns table will be created with the parameter logPattern as the default value for each log-level. If logPattern also is omitted then each level will fall back to the current default setting, see logging.defaultLogPatterns.
  • logPattern:
    This value will be used as the default value for each log-level that was omitted in logPatterns.
  • timestampPattern:
    This is an optional parameter that can be used to specify a date/time formatting in the log message. The default is taken from logging.defaultTimestampPattern().
  • logLevel:
    The initial log-level to set for the created logger.

Example

require"logging.email"

local logger = logging.email {
  rcpt = "mail@host.com",
  from = "mail@host.com",
  headers = {
    subject = "[%level] logging.email test",
  },
}

logger:info("logging.email test")
logger:debug("debugging...")
logger:error("error!")

XHTML 1.0 válido!

lualogging-1.8.2/docs/file.html000066400000000000000000000114771436502304500164230ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

File appender

The file appender can be used to write log messages to a file. It uses Lua I/O routines to do its job.

function logging.file {
    [filename = string,]
    [datePattern = string,]

    [logPattern = string,]
    [logPatterns = {
      [logging.DEBUG = string,]
      [logging.INFO  = string,]
      [logging.WARN  = string,]
      [logging.ERROR = string,]
      [logging.FATAL = string,]
    },]
    [timestampPattern = string,]
    [logLevel = log-level-constant,]
}
  • filename:
    The name of the file to be written to. On each call to log a message the file is opened for appending and closed immediately.
    If the file cannot be opened for appending the logging request returns nil and an error message.
    The default value is "lualogging.log".
  • datePattern:
    This is an optional parameter that can be used to specify a date pattern that will be passed to the os.date function to compose the filename.
    This is useful to create daily or monthly log files. If the user wants to create one log file per day he specifies a "%Y-%m-%d" pattern and a filename like "temp%s.log".
  • logPatterns:
    A table with logPattern strings indexed by the log-levels. A logPattern specifies how the message is written.
    If this parameter is omitted, a patterns table will be created with the parameter logPattern as the default value for each log-level. If logPattern also is omitted then each level will fall back to the current default setting, see logging.defaultLogPatterns.
  • logPattern:
    This value will be used as the default value for each log-level that was omitted in logPatterns.
  • timestampPattern:
    This is an optional parameter that can be used to specify a date/time formatting in the log message. See logging.date for the format. The default is taken from logging.defaultTimestampPattern().
  • logLevel:
    The initial log-level to set for the created logger.

Example

require"logging.file"

local logger = logging.file {
    filename = "test%s.log",
    datePattern = "%Y-%m-%d",
}

logger:info("logging.file test")
logger:debug("debugging...")
logger:error("error!")

 

 

XHTML 1.0 válido!

lualogging-1.8.2/docs/images/000077500000000000000000000000001436502304500160515ustar00rootroot00000000000000lualogging-1.8.2/docs/images/lualogging-128.png000066400000000000000000000274531436502304500212320ustar00rootroot00000000000000PNG  IHDRL\.IDATx}wxUE;3tB RH!@("A@ADl++gXXTbATA`!BB i733?&x-7!!;gμAsuzC^?e 9_/Dׂ ځsH #ܴMn`0FeٮA){RJ)e1Ɣ/w2Jū'On9c !$>#fƍ򼼼|}}KJJRSSÕGe#~EBREtB0W9pBRceʀė Amڴ`ɒ%׿󋊊}rJbh4<``a333;@y0B=!2䊊f B_ۂ~ 'PCauuuϟOJJ",\0<v yjj#ZZZrss DFlN./o>IQJ9Cc-ڵkuJ- =%* Re˖:0a`%T|s :mڴs qᠠupo `Ńj)1=rO)O_rclw<`Z[w߽>7T|ercLFgO#l˧}^ټZ6m:tNkhh;vmpp-˘1cdY޴iS~~޽{ !3g|-l.,,;v1c8{ ӧOO2(gA{ 619`Ho"6Ys(gAb&>>>!++O> طo8::111}etC JƍWXXO?1x///Ik M˗010Gjjږ.%In"&)r BÅ//l߾}ƍ3fرcGjjjTTTrrreeellNOI&EEEO4^m4ȑ҆F 3\ɩ6,1ahn`AvZ>\t)!!WeجY+4~}~wzp-kk4 &p,3?YLUiϞ9S 0GT;p׷T"^[[+>o޼x2yg6?2eƘc,IX!N$ cV<3%%_Bq]gAjR^^m۶{7 `ذaqqq,c}cFEE J@V$65^mmmmZ,Zb0h yg0hjg>/=Lrm<:~ g!ԩSyyyk֬YdɠARRRg}_~p…#G޽[aGK/B!tjˑ#%Ǐז7Qj]$@"D8jTqƌݮ9T ޚ"?5j̙VzꩧkMKKceee=CC ٽ{wqqq\\ۡvKoqqּM.=Z@CHs}7--|Ĺs"#b@TTu.QQ uA777[>|8d2}տm0F_SSrʥK )@h#Yfɟ~*00c"Y*W c1 ``:ԩ,1kVVKB,qdJ$ ]0cƧ, lIy:>>HL :tRzz/(dI,ʕ+x annnihhOxbBDR6kz;rB)! TR3Ņ/_>Gn*cnF+**"]Cƈ1sZGtuZ36Cāht:ݹsΞ=++V8pѣG 2o<v(Isn6=HMM+zau+:@ho?}|))eYA r//MQQc}-Ƙso~3yGsPvb7Wx7/(--}z=rرrT^^ /ח)N`eed?άKI6 B1 [ngNJQ 0FuÇjnN8Ƙ1AN=u1nkk+..f-\^rb4r=_tO>C QnU&??ʺL7BZJ > 8!3g'MZt--BڷdVSjZ_f3 9 c,{{{ϝ;7!!/ 4qqq>,o<0h YTFC-]hŋxq.#vPn yL X{w'4?z8BH˷픶]'8ukjjɓ'?1##c߾}wq̙3ʄ lRTTςʭ$jձ˷RQ:{L!;_xa,LQE ۶$_l]PJ[zjvN@x7mTUUtRuwܹk.Z(55Μ9s̙%KYqj'$9Ņ/Pd#)m}qkEH?R s+{}w?GH' 5,sF;~+ݻLM|XiF)xgAsI7p<8S1$"1JA|>|x˖-/R߾}K۷ԩS/ZWN|R`4С#7 ,f6xyI&j4k}a!I²ܜ6hE}z* %EEJ`֠A'F͟WhNU.G}TSSxb%ދ;( bMM3efH,mhhS͛8jTXxR`ϯ۷w#$!e$Yn5*zGb"UBV+mk//KZM(@ֶaÆİlBȲeDzV+=;}Ϟ\I2…#IAQ=x3V`„]fn$Q(|I8( ԺLoܬȩS5eN^7c,>[0o^p (>]KI Zp.'lf933au\6,|ȐBw};s̘1ctr iPRR;=zTx&zO6ܦͶ$ኊK7 ;kB^Xa !co=c8JD4 =b$a7ӧWVVfeeAGn.)))?sVV!$$$DꫯRRR ڈW-$p}1c)S1C+)ڵ8qpÄwUsd#([nIII1;~8_՞>}ԩS>^W^H\_ӟ~"ċ |U+PyHB)呑gV]PFHm AÇQʝ'U2Ď78y{)H鮶V@~Ǐ?BidC:` YϞ]t,8CI13m|9"ԩeAA^qts=G:U` Vd wjj֭[kjj&Nn,(w9tr!}xɓ5XЏ7ou`@cTl9!ҫoulqvv!N^Sm7TTT : UFWR0 AYsũ"kPNZ'Ǐ]ԩe9n;NQ Z-p+V6' Wk  {,V8CmذAA8Z035_pYY矟YN"/:04׮$L}噢I¶ I҉'JKK<LiwNuz"< L&a%}7Xٮv,Ib_~y@XyD0„KpYY#;hc϶YEσ `6ϧ+υW"/'OV\O@Q[ZPP@f9`tz~`V. p?ЮfCco"˳'Q/3ܬM#GJjkK}os\爈˗gGx\rWqj#Iɼ{?GHs\W lgm"w|vϞ6qB`*ZEFFMpeuiz$bL~L3}<7sXj8rlN7=+سkD8ku`B:3Ic!֭|-MDn&7OPzKnIv e999Y+qՋ@zffaK "ve˶j4jjglطZ$7\ E`剬!O pC*.^j?I늸w ª,4͙^\l4P"MeQʵZzvalp,ܚ#6lؐ yºWp{dY1fź c.^7COFXj‰1z=˖mX+OnᆆZp}Dhhhuu5bH.vw:8JZ"F401ƽC32 {nAYqҤ5O=5n j˻O,T<s#J׌7D ryuMƈ13Vѐ:GN{i8+W 7/q`0ƛ-/7_W:رB pU1K{yy8bFDD%5+*j$Ĉ_tWK(qnj2IO?xm0Hs}}3`.PYYGG,HtϞ=^^^+^WYz!KR{ !QJ0!^"s޶$qt6x@TV6ƜH%9Wݲz2!79Xn6P Ei_&9`WAכhTv ojZ7mlOeCJM?cw'XPKE$xp,KKKc N;`[=w2x4wqm3 sNE>R"2=^RjeqWxRo pSA=s$BeV%Y3֬ֆLes^  7[esک@ AV)믿6vr'>DC4 }4EY}}ʕ!έÆEw_,Ə?>jDvkhhWwaD@AAݮ]>,cCʸSNM>=:PĹV!cDNի;gEaÂ_{68s㏏0LK>>ZI|'Non}Mc{õVK:8^^^J__۔78a 7SUDNO;zIXI[[EE M XoA=EOTIpNbpձ:P|-{~ ~Vɘ528sNjl4skjZ):쳣,aPm] X` `Efn:Z RMz>>6!t߮\SEE,2mi1=WD%0bD-, p?NK.h+t` 5,. %%4\޹3Gl&D?O~~:-;v'lASQQ]ScIDk) $X/  ;0U/^<\`ۥp[RRy/뤜7 >wnСU`uu1bĀ_jiе`0H?x…*(jn_2sڴ&r˖M}Ja5:ٳ`И%K|^ƴ!b+31̜m5!`, 3<PK"OE]W-ei4.^ B:{"lʔiQylW[.\($\If9--ɧV8U!lР>̘1֯?;mZLh6{^*(k+=:orZ2hPܹgtR}}^/H~zii&\8ƘRg LX!l߾`0LKȑVlbI?>?-Ҟ>]9|jf1FfurȢXQJNɓ?.<,c4s;V/. 9$&?yr 9Wlmm}7ǻ"ձk97VK~ |8jm%D#rBzUp9-(@]/X $$:Aׯ__]]+O9urYロ⋛Tʮg~ $ض-8(ooLPiqW_`W )VRôiӪ]E^7{PYu1Fv)"B=_>@sNqS/zo E7V.C~ɼ($!wZBCw+3t3CnӧO\م8D曞P!ҋv48e{]455)Q:4*wgyF\S9)&D]{YA{(#O>{Q}}l^jɓ'`N J9$,o_MoB$ Q曳Ĉ;~է6INd+D~XnG-eR7W~&**è]!rcsٰaCiiR $ [tƌA'N<5jT,771l9%e3'^cw[/ZJ=n ؃J\_4P-fj7Pp _{msύ.0NOO) pJjɳw&#c BafN΁1+oɒQ2N_";u99977w`3vh媻l+*>8k͚$ߡ Z8'G!dZn-66V}E/?LNN~衇<Xhilۖn/6@Rp乻B8 nw„G;DB{? Kt IeiTVV^:44hr$xi׮; 23KJK-`C);c?iƍ0sfAעiw Ƹaթ3gT+DB(_D6k^^mVVٳUWKK[,VX||{GD%%6,xĈ At+v׆Pa cN]wp:Jg}7{ &tYbQPkIB,",;v͛~oЭ ˃TK1l0GftbBHKKKJJڴiSkk+ؼ H)ףCr jSZmmML&Ӳe@< :ܶ!]wYfgwzvW ,9rӳf8pW]Ĭ)zÇ/]ct{|8̋vu5*--Mө&1L&N d2B4s; v333/^tR;SLU8ԏbhʪ{gwo'e  2!DѥN<秠ĝEy挌 __Ç'$$A< * ]}Lrgr5ܹs06FqeeYolllhh(--ׯ߸q&%% V ^:zA"@[[[+++ "-G d///u***>ajJ{Q YWNj"FhRSS奾.pnnN4Pط\K!5A})ZTU>oNM@/\PR{Iw;T LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Overview

LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, email, socket and sql outputs.

LuaLogging is free software and uses the same license as Lua 5.1.

Status

Current version is 1.8.2. It was developed for Lua 5.1+.

Download

LuaLogging can be downloaded from its GitHub downloads page or installed via LuaRocks.

Dependencies

LuaLogging dependencies can be separated by the used appenders:

LuaLogging Core, Console and File appenders
Socket, Rsyslog, and Email appenders
SQL appender
  • LuaSQL 2.1.x

History

1.8.2 [27/Jan/2023]
Fix: allow to work without the debug library.
1.8.1 [23/Jan/2023]
Fix: use explicit tostring, don't rely on automatic coercion.
Fix: rsyslog appender wouldn't properly clear the socket upon an error.
1.8.0 [22/Oct/2022]
Added: new module logging.envconfig to allow log configuration via environment variables.
Refactor: refactored the appenders to be more object like. They now return a module table.
Fix: add rsyslog appender to makefile install target.
Fix: errorhandler in rsyslog was omitting 'self', and also log the failed message itself to stderr.
Fix: when using Copas and rsyslog on Lua 5.1, coxpcall is required to yield.
Fix: rsyslog; upon failure remove the closed socket from the cache to prevent the retry from using the closed socket.
1.7.0 [21/Sep/2022]
Added: new function logging.date is compatible with os.date but supports second-fractions, to be represented by %q placeholder in the timestampPattern.
Added: new bundled appender; "rsyslog". This logger will log in syslog format to a remote syslog server. It supports both BSD as well as IETF formats, and supports sending over UDP and TCP, with an option to use Copas for async-sending over TCP.
1.6.0 [09/Nov/2021]
Added: the logPattern can now be specified for each log-level individually. This allows use cases like only adding "%source" on debug level, or injecting ansi-color coding in for example the error log-level.
Added: new bundled appender; "nginx". This logger has no configuration options, but will simply pass any log messages on to the nginx log. When using LuaLogging in OpenResty, configure this logger.
Added: application level defaults. New functions logging.defaultLogPatterns() , logging.defaultTimestampPattern(), logging.defaultLevel(), and logging.defaultLogger() can be used to get/set the global application level defaults.
Use carefully, this is global state, so only applications should set those, libraries should not.
Added: the included appenders now have an extra parameter to set log-level upon creation; logLevel.
Added: the logPattern can now have new placeholders:
"%file" (source file),
"%line" (source line),
"%function" (function name), and
"%source" (evaluates to "%file:%line in function '%function'").
Added: the console logger has a new optional parameter "destination", which must be either "stderr" or "stdout" (defaults to "stdout")
1.5.2 [12/Aug/2021]
Fix: rolling-file, 'seek' can occasionally fail, handle it properly.
1.5.1 [22/Mar/2021]
Reverted: Functionality to specify custom log levels.
1.5.0 [22/Mar/2021]
Added: Functionality to specify custom log levels.
Added: Provide verbose error message when formatting fails.
Fix: disable buffering on windows files
1.4.0 [12/Aug/2020]
Fix: No more global on Lua 5.3.
Fix: Reduced log noise when changing log levels.
Added: A new log-level "off" to suspend logging.
Fix: Restored the log-level constants on the logger object.
Fix: catch exceptions when formatting log messages.
Change: creating loggers now always takes a parameters table (consistent across all appenders). The old parameters are now deprecated, but still work for backward compatibility purposes.
Added: All appenders have a new property timestampPattern to specify the format of the timestamp in the log message
Added: logger:getPrint() function that returns a print-like function, but directs all output to the logger.
1.3.0 [5/Mar/2013]
1.2.0 [20/Apr/2011]
Improved performance of logging.
Added Rolling File Appender.
1.1.4 [30/Oct/2007]
Fixed bug #1719 - inefficient handling of file loggers (Patch by Jürgen Hötzel).
1.1.3 [08/Aug/2007]
New makefile for Windows (using nmake) and configure script for Unix.
1.1.2 [14/Aug/2006]
Fixed a bug found by Carlos Augusto where tostring() was being incorrectly used with numbers.
1.1.1 [31/Mar/2006]
1.1.0 [12/Nov/2004]
1.0.0 [02/Jul/2004]

Credits

LuaLogging 1.2 and 1.3 were maintained by Robert G. Jakabosky.

LuaLogging 1.1.x was designed by Danilo Tuler and Thiago Ponte and implemented by Thiago Ponte.

LuaLogging 1.0.0 was designed by Danilo Tuler (and log4j) and implemented by Danilo Tuler and André Carregal.

lualogging-1.8.2/docs/license.html000066400000000000000000000103151436502304500171140ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

License

LuaLogging is free software: it can be used for both academic and commercial purposes at absolutely no cost. There are no royalties or GNU-like "copyleft" restrictions. LuaLogging qualifies as Open Source software. Its licenses are compatible with GPL. LuaLogging is not in the public domain and the Kepler Project keep its copyright. The legal details are below.

The spirit of the license is that you are free to use LuaLogging for any purpose at no cost without having to ask us. The only requirement is that if you do use LuaLogging, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.

The LuaLogging library is designed by Danilo Tuler and implemented by Danilo Tuler, Thiago Ponte and André Carregal. The implementation is not derived from licensed software.


Copyright © 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 

 

lualogging-1.8.2/docs/manual.html000066400000000000000000000441701436502304500167550ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Introduction

LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports console, file, email, socket and sql outputs through the use of appenders.

The logging module holds a new function to create new logger objects.

This logger constructor receives a function (known as the appender function) that will be called on each call to log a message.

An appender function receives three arguments:

  • self: the logger object
  • level: the logging level
  • message: the message to be logged

The logger constructor also receives a optional second argument which should be a table with parameters

Installation

LuaLogging is installed as a regular Lua module called logging.

installation is easiest using LuaRocks; "luarocks install lualogging", or alternatively using the Makefile.

Logging module

The logging module has a number of global functions:

logging.new( function[, logLevel] )
Creates a new logger object from a custom 'appender' function. See examples below. The appender function signature is function(self, level, message). The optional logLevel argument specifies the initial log-level to set (the value must be a valid log-level constant). If omitted defaults to logging.defaultLevel.
patts = logging.buildLogPatterns([table], [string])
Creates a log-patterns table. The returned table will for each level have the logPattern set to 1. the value in the table, or alternatively 2. the string value, or 3. the pattern from the global defaults.

Returns a logPatterns table.

Example logging source info only on debug-level, and coloring error and fatal messages:
local patterns = logging.buildLogPatterns(
  {
    [logging.DEBUG] = "%date %level %message (%source)\n"
    [logging.ERROR] = "%date "..ansi_red.."%level %message"..ansi_reset.."\n"
    [logging.FATAL] = "%date "..ansi_red.."%level %message"..ansi_reset.."\n"
  }, "%date %level %message\n"
)
      
date_val = logging.date([format,[time]])
Compatible with standard Lua os.date() function, but supports second fractions. The placeholder in the format string is "%q", or "%1q" to "%6q", where the number 1-6 specifies the number of decimals. The default is 3, so "%q" is the same as "%3q". The format will always have the specified length, padded with leading and trailing 0's where necessary.
If the pattern is "*t", then the returned table will have an extra field "secf" that holds the fractional part.

Example: "%y-%m-%d %H:%M:%S.%6q"

Note: if the "time" parameter is not provided, it will try and use the LuaSocket function gettime() to get the time. If unavailable, the fractional part will be set to 0.
patts = logging.defaultLogPatterns([string | table])
Sets the default logPatterns (global!) if a parameter is given. If the parameter is a string then that string will be used as the pattern for all log-levels. If a table is given, then it must have all log-levels defined with a pattern string. See also logging.buildLogPatterns.

The default is "%date %level %message\n" for all log-levels.

Available placeholders in the pattern string are; "%date", "%level", "%message", "%file", "%line", "%function" and "%source". The "%source" placeholder evaluates to "%file:%line in function'%function'".

Returns the current defaultLogPatterns value.

NOTE: since this is a global setting, libraries should never set it, only applications should.
patt = logging.defaultTimestampPattern([string])
Sets the default timestampPattern (global!) if given. The default is nil, which results in a system specific date/time format. The pattern should be accepted by the function logging.date for formatting.

Returns the current defaultTimestampPattern value.

NOTE: since this is a global setting, libraries should never set it, only applications should.
level = logging.defaultLevel([level constant])
Sets the default log-level (global!) if given. Each new logger object created will start with the log-level as specified by this value. The level parameter must be one of the log-level constants. The default is logging.DEBUG.

Returns the current defaultLevel value.

NOTE: since this is a global setting, libraries should never set it, only applications should.
logger = logging.defaultLogger([logger object])
Sets the default logger object (global!) if given. The logger parameter must be a LuaLogging logger object. The default is to generate a new console logger (with "destination" set to "stderr") on the first call to get the default logger.

Returns the current defaultLogger value.

NOTE: since this is a global setting, libraries should never set it, only applications should. Libraries should get this logger and use it, assuming the application has set it.
-- Example: application setting the default logger
local color = require("ansicolors") -- https://github.com/kikito/ansicolors.lua
local ll = require("logging")
require "logging.console"
ll.defaultLogger(ll.console {
  destination = "stderr",
  timestampPattern = "!%y-%m-%dT%H:%M:%S.%qZ", -- ISO 8601 in UTC
  logPatterns = {
    [ll.DEBUG] = color("%{white}%date%{cyan} %level %message (%source)\n"),
    [ll.INFO] = color("%{white}%date%{white} %level %message\n"),
    [ll.WARN] = color("%{white}%date%{yellow} %level %message\n"),
    [ll.ERROR] = color("%{white}%date%{red bright} %level %message %{cyan}(%source)\n"),
    [ll.FATAL] = color("%{white}%date%{magenta bright} %level %message %{cyan}(%source)\n"),
  }
})


-- Example: library using default if available (fallback to nop)
local log do
  local ll = package.loaded.logging
  if ll and type(ll) == "table" and ll.defaultLogger and
    tostring(ll._VERSION):find("LuaLogging") then
    -- default LuaLogging logger is available
    log = ll.defaultLogger()
  else
    -- just use a stub logger with only no-op functions
    local nop = function() end
    log = setmetatable({}, {
      __index = function(self, key) self[key] = nop return nop end
    })
  end
end

log:debug("starting my library")
  

Environment variables

The submodule logging.envconfig allows to configure the default logger via environment variables. This is done based on a "prefix" for the environment variables (with default value "LL"). The variables are the logger options names with the prefix in all-caps separated by "_". So if a logger takes an option "opts.logLevel", then it can be configured using environment variable LL_LOGLEVEL=warn.

The type of logger can be set using environment variable LL_LOGGER=console (assuming the default prefix "LL").

The defaults are "LL" for the prefix, and a console logger to "stderr".

The exposed functions:

envconfig.set_default_settings(prefix)
Sets the default prefix and loads the configuration. Returns true on success, nil, "already set a default" if it was called before. Will throw an error if something during the configuration fails (bad user input in environment variables for example).
This method should be called by applications at startup, to set the default prefix.
name, opts = envconfig.get_default_settings()
returns the appender name (eg. "file", "console", etc), and the options table for configuring the appender. The table has a metatable that will dynamically lookup fields in environment variables, this ensures that any option an appender checks will be read and returned. Boolean and number values will be converted to their respective types (case insensitive).

The common logPatterns field is a special case where each level can be configured by appending the level with an "_". See example below:
# set these environment variables
export MYAPP_LOGGER="console"
export MYAPP_LOGLEVEL="info"
export MYAPP_LOGPATTERN = "%message"
export MYAPP_LOGPATTERNS_DEBUG = "%message %source"
export MYAPP_LOGPATTERNS_FATAL = "Oh my!! %message"

-- Lua code (see set_default_logger for a shorter version)
local logging = require "logging"
local logenv = require "logging.envconfig"
assert(logenv.set_default_settings("MYAPP"))
local logger_name, logger_opts = logenv.get_default_settings()
local logger = assert(require("logging."..logger_name)(logger_opts))
logging.setdefaultLogger(logger)

logger:info("configured via environment!")
    
logger = envconfig.set_default_logger(prefix)
Sets (and returns) the default logger from the environment.
# set these environment variables
export MYAPP_LOGGER="console"
export MYAPP_LOGLEVEL="info"
export MYAPP_LOGPATTERN = "%message"
export MYAPP_LOGPATTERNS_DEBUG = "%message %source"
export MYAPP_LOGPATTERNS_FATAL = "Oh my!! %message"

-- Lua code
local logenv = require "logging.envconfig"
local logger = assert(logenv.set_default_logger("MYAPP"))

logger:info("configured via environment!")
    

Logger objects

Logger objects are created by loading the 'appender' module, and calling on it. For example:

  local logger = require("logging.console") {
    -- options go here (see appenders for options)
  }

A logger object offers the following methods that write log messages.

For each of the methods below, the parameter message may be any lua value, not only strings. When necessary message is converted to a string.

The parameter level can be one of the variables enumerated below. The values are presented in descending criticality, so if the minimum level is defined as logger.WARN then logger.INFO and logger.DEBUG level messages are not logged. The default set level at startup is logger.DEBUG.

Constants

logger.DEBUG
The DEBUG level designates fine-grained informational events that are most useful to debug an application.
logger.INFO
The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
logger.WARN
The WARN level designates potentially harmful situations.
logger.ERROR
The ERROR level designates error events that might still allow the application to continue running.
logger.FATAL
The FATAL level designates very severe error events that would presumably lead the application to abort.
logger.OFF
The OFF level will stop all log messages.

Methods

logger:log (level, [message]|[table]|[format, ...]|[function, ...])
Logs a message with the specified level.
logger:setLevel (level)
This method sets a minimum level for messages to be logged.
logger:getPrint (level)
This method returns a print-like function that redirects all output to the logger instead of the console. The level parameter specifies the log-level of the output.

The following set of methods is dynamically generated from the log-levels.

logger:debug ([message]|[table]|[format, ...]|[function, ...])
Logs a message with DEBUG level.
logger:info ([message]|[table]|[format, ...]|[function, ...])
Logs a message with INFO level.
logger:warn ([message]|[table]|[format, ...]|[function, ...])
Logs a message with WARN level.
logger:error ([message]|[table]|[format, ...]|[function, ...])
Logs a message with ERROR level.
logger:fatal ([message]|[table]|[format, ...]|[function, ...])
Logs a message with FATAL level.

Examples

The example below creates a logger that prints the level and message to the standard output (or whatever the print function does).

local Logging = require "logging"

local appender = function(self, level, message)
  print(level, message)
  return true
end

local logger = Logging.new(appender)

logger:setLevel(logger.WARN)
logger:log(logger.INFO, "sending email")

logger:info("trying to contact server")
logger:warn("server did not respond yet")
logger:error("server unreachable")

-- dump a table in a log message
local tab = { a = 1, b = 2 }
logger:debug(tab)

-- use string.format() style formatting
logger:info("val1='%s', val2=%d", "string value", 1234)

-- complex log formatting.
local function log_callback(val1, val2)
  -- Do some complex pre-processing of parameters, maybe dump a table to a string.
  return string.format("val1='%s', val2=%d", val1, val2)
end

-- function 'log_callback' will only be called if the current log level is "DEBUG"
logger:debug(log_callback, "string value", 1234)

-- create a print that redirects to the logger at level "INFO"
logger:setLevel (logger.INFO)
local print = logger:getPrint(logger.INFO)
print "hello\nthere!"

Upon execution of the above example the following lines will show in the standard output. Notice that some of the INFO log requests are not handled because the minimum level is set to WARN.

WARN server did not responded yet
ERROR server unreachable
INFO hello
INFO there!

Appenders

The following appenders are included in the standard distribution.

Upgrading from 1.0.0

Upgrading from LuaLogging 1.0.0 is very easy. The logger object is fully compatible. You just need to change the code that creates the object.

The logger constructor from 1.0.0 received a single argument which was a filename. To upgrade to 1.1.0 you should create a logging.file object instead, passing the filename as argument. As simple as this.

lualogging-1.8.2/docs/nginx.html000066400000000000000000000057531436502304500166270ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Nginx/Openresty appender

This appender has no configuration options, and simply forwards whatever is being logged to the configured Nginx log. LuaLogging log-levels will be converted to the equivalent Nginx ones, and initial log-level will be set to match the Nginx system level.

It makes sense to configure this logger and set it as the default logger on Nginx/OpenResty startup. Any libraries will then be able to just grab the defaultLogger from logging.defaultLogger() and won't need any modifications to work with Nginx/OpenResty.

Examples

require("logging.nginx")
local logging = require("logging")

local logger = logging.nginx()
logging.defaultLogger(logger)

logger:info("logging.nginx test")
logger:debug("debugging...")
logger:error("error!")

 

 

 

 

 

 

 

lualogging-1.8.2/docs/rolling_file.html000066400000000000000000000120511436502304500201360ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Rolling File appender

The rolling file appender can be used to write log messages to a file. It uses Lua I/O routines to do its job. The rolling file appender rolls over the logfile once it has reached a certain size limit. It also mantains a maximum number of log files.

function logging.rolling_file {
    [filename = string,]
    maxFileSize = number,
    [maxBackupIndex = number,]

    [logPattern = string,]
    [logPatterns = {
      [logging.DEBUG = string,]
      [logging.INFO  = string,]
      [logging.WARN  = string,]
      [logging.ERROR = string,]
      [logging.FATAL = string,]
    },]
    [timestampPattern = string,]
    [logLevel = log-level-constant,]
}
  • filename:
    The name of the file to be written to.
    If the file cannot be opened for appending the logging request returns nil and an error message.
    The default value is "lualogging.log".
  • maxFileSize:
    The max size of the file in bytes. Every time the file reaches this size it will rollover, generating a new clean log file and storing the old log on a filename.n, where n goes from 1 to the configured maxBackupIndex.
    The more recent backup is the one with the lowest n on its filename.
    Eg. test.log.1 (most recent backup)
    test.log.2 (least recent backup)
  • maxBackupIndex:
    The number of backup files that will be generated. The default value is 1.
  • logPatterns:
    A table with logPattern strings indexed by the log-levels. A logPattern specifies how the message is written.
    If this parameter is omitted, a patterns table will be created with the parameter logPattern as the default value for each log-level. If logPattern also is omitted then each level will fall back to the current default setting, see logging.defaultLogPatterns.
  • logPattern:
    This value will be used as the default value for each log-level that was omitted in logPatterns.
  • timestampPattern:
    This is an optional parameter that can be used to specify a date/time formatting in the log message. See logging.date for the format. The default is taken from logging.defaultTimestampPattern().
  • logLevel:
    The initial log-level to set for the created logger.

Example

require"logging.rolling_file"

local logger = logging.rolling_file {
    filename = "test.log",
    maxFileSize = 1024,
    maxBackupIndex = 5,
}

logger:info("logging.rolling_file test")
logger:debug("debugging...")
logger:error("error!")

 

 

lualogging-1.8.2/docs/rsyslog.html000066400000000000000000000166061436502304500172050ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Remote syslog appender

This appender can be used to send syslog formatted log requests to a remote syslog server. This appender relies on LuaSocket to do its job. Optionally Copas can be used for async sending of log messages over TCP.

If you want to log to the local syslog daemon, then please use luasyslog.

The LuaLogging log-levels will be mapped to the syslog levels by their name, where logging.FATAL maps to syslog ALERT. Since LuaLogging only has 5 levels, the syslog levels EMERG, CRIT, and NOTICE remain unused.

function logging.rsyslog {
    hostname = string,
    [port = number,]
    [protocol = "udp" | "tcp",]
    [rfc = "rfc5424" | "rfc3164",]
    [maxsize = number,]
    [facility = facility-constant,]
    [ident = string,]
    [procid = string,]
    [msgid = string,]

    [logPattern = string,]
    [logPatterns = {
      [logging.DEBUG = string,]
      [logging.INFO  = string,]
      [logging.WARN  = string,]
      [logging.ERROR = string,]
      [logging.FATAL = string,]
    },]
    [logLevel = log-level-constant,]
}
  • hostname:
    Hostname can be an IP address or a host name of the server where the log message will be sent.
  • port:
    The port must be an integer number in the range [1..64K). The default is 514.
  • protocol:
    The network protocol to use, either "udp" or "tcp". The default is "tcp".

    Note: TCP sending is a blocking operation. For non-blocking use Copas is supported, see the example below.
  • rfc:
    The message format. 2 options:
    • for the old BSD style use "rfc3164" (the default)
    • for the IETF standard use "rfc5424".
  • maxsize:
    The maximum message size. Longer messages will be truncated. The minimum value is 480. The defaults are 1024 for "rfc3164", and 2048 for "rfc5424".
  • facility:
    The syslog facility to use, use one of the constants. The default value is the "user" facility.
      rsyslog.FACILITY_KERN
      rsyslog.FACILITY_USER
      rsyslog.FACILITY_MAIL
      rsyslog.FACILITY_DAEMON
      rsyslog.FACILITY_AUTH
      rsyslog.FACILITY_SYSLOG
      rsyslog.FACILITY_LPR
      rsyslog.FACILITY_NEWS
      rsyslog.FACILITY_UUCP
      rsyslog.FACILITY_CRON
      rsyslog.FACILITY_AUTHPRIV
      rsyslog.FACILITY_FTP
      rsyslog.FACILITY_NTP
      rsyslog.FACILITY_SECURITY
      rsyslog.FACILITY_CONSOLE
      rsyslog.FACILITY_NETINFO
      rsyslog.FACILITY_REMOTEAUTH
      rsyslog.FACILITY_INSTALL
      rsyslog.FACILITY_RAS
      rsyslog.FACILITY_LOCAL0
      rsyslog.FACILITY_LOCAL1
      rsyslog.FACILITY_LOCAL2
      rsyslog.FACILITY_LOCAL3
      rsyslog.FACILITY_LOCAL4
      rsyslog.FACILITY_LOCAL5
      rsyslog.FACILITY_LOCAL6
      rsyslog.FACILITY_LOCAL7
          
  • ident:
    The value for the APP-NAME field (rfc5424, called TAG field in rfc3164). Default value is "lua".
  • procid:
    The process id value (only applicable for rfc5424 format). Default value is "-" (absent).
  • msgid:
    The message id value (only applicable for rfc5424 format). Default value is "-" (absent).
  • logPattern:
    This value will be used as the default value for each log-level that was omitted in logPatterns, this defaults to "%message". The default pattern deviates from standard LuaLogging defaults since those do not make sense for syslog.
  • logPatterns:
    A table with logPattern strings indexed by the log-levels. A logPattern specifies how the message is written.
    If this parameter is omitted, a patterns table will be created with the parameter logPattern as the default value for each log-level.
  • logLevel:
    The initial log-level to set for the created logger.

Example

local rsyslog = require "logging.rsyslog"

rsyslog.copas() -- switch to using non-blocking Copas sockets

local logger = rsyslog {
  hostname = "syslog.mycompany.com",
  port = 514,
  protocol = "tcp",
  rfc = "rfc5424",
  maxsize = 8000,
  facility = rsyslog.FACILITY_LOCAL2,
  ident = "my_lua_app",
  procid = "socket_mod",
  logPattern = "%message %source",
}

copas.loop(function()
  logger:info("logging.rsyslog test")
  logger:debug("debugging...")
  logger:error("error!")

  -- destroy to ensure threads are shutdown (only for Copas)
  logger:destroy()
end)

 

 

 

 

lualogging-1.8.2/docs/socket.html000066400000000000000000000106111436502304500167610ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

Socket appender

This appender can be used to send log requests through a socket. Socket appender relies on LuaSocket to do its job.
Upon each log request a connection is opened, the message is sent and the connection is closed.
function logging.socket {
    hostname = string,
    port = number,

    [logPattern = string,]
    [logPatterns = {
      [logging.DEBUG = string,]
      [logging.INFO  = string,]
      [logging.WARN  = string,]
      [logging.ERROR = string,]
      [logging.FATAL = string,]
    },]
    [timestampPattern = string,]
    [logLevel = log-level-constant,]
}
  • hostname:
    Hostname can be an IP address or a host name of the server where the log message will be sent.
  • port:
    The port must be an integer number in the range [1..64K).
  • logPatterns:
    A table with logPattern strings indexed by the log-levels. A logPattern specifies how the message is written.
    If this parameter is omitted, a patterns table will be created with the parameter logPattern as the default value for each log-level. If logPattern also is omitted then each level will fall back to the current default setting, see logging.defaultLogPatterns.
  • logPattern:
    This value will be used as the default value for each log-level that was omitted in logPatterns.
  • timestampPattern:
    This is an optional parameter that can be used to specify a date/time formatting in the log message. See logging.date for the format. The default is taken from logging.defaultTimestampPattern().
  • logLevel:
    The initial log-level to set for the created logger.

Example

require"logging.socket"

local logger = logging.socket {
  hostname = "localhost",
  port = 5000,
}

logger:info("logging.socket test")
logger:debug("debugging...")
logger:error("error!")

 

 

 

 

lualogging-1.8.2/docs/sql.html000066400000000000000000000103731436502304500162750ustar00rootroot00000000000000 LuaLogging: A simple API to use logging features in Lua
LuaLogging
A simple API to use logging features in Lua.

SQL appender

The SQL appender can be used to write log messages to a SQL database table. It uses LuaSQL, therefore any database supported by LuaSQL can be used.

function logging.sql{
    connectionfactory = function,
    [tablename = string,]
    [logdatefield = string,]
    [loglevelfield = string,]
    [logmessagefield = string,]
    [keepalive = boolean,]

    [logLevel = log-level-constant,]
}
  • connectionfactory:
    This must be a function that creates a LuaSQL connection object. This function will be called everytime a connection needs to be created.
  • tablename:
    The name of the table to write the log requests. Default value is "LogTable".
  • logdatefield:
    The name of the field to write the date of each log request. Default value is "LogDate".
  • loglevelfield:
    The name of the field to write the level of each log request. Default value is "LogLevel".
  • logmessagefield:
    The name of the field to write the message of each log request. Default value is "LogMessage".
  • keepalive:
    In every log request a connection to the database is opened, the message is written, and the connection is closed.
    If the user wants to keep the connection opened he can specify keepalive = true.
  • logLevel:
    The initial log-level to set for the created logger.

Example

require"logging.sql"
require"luasql.jdbc"

local env, err = luasql.jdbc('com.mysql.jdbc.Driver')

local logger = logging.sql {
  connectionfactory = function()
    local con, err = env:connect('jdbc:mysql://localhost/test',
                                 'tcp', '123')
    assert(con, err)
    return con
  end,
  keepalive = true,
}

logger:info("logging.sql test")
logger:debug("debugging...")
logger:error("error!")
lualogging-1.8.2/lualogging-dev-1.rockspec000066400000000000000000000031271436502304500204540ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "dev" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "dev") and "master" or nil, tag = (package_version ~= "dev") and ("v"..package_version) or nil, } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", ['logging.rsyslog'] = "src/logging/rsyslog.lua", ['logging.envconfig'] = "src/logging/envconfig.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/000077500000000000000000000000001436502304500156505ustar00rootroot00000000000000lualogging-1.8.2/rockspecs/lualogging-1.2.0-2.rockspec000066400000000000000000000020001436502304500223160ustar00rootroot00000000000000package = "lualogging" version = "1.2.0-2" source = { url = "git://github.com/lunarmodules/lualogging.git", branch = "v1.2.0", } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/lunarmodules/lualogging", license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", } }, copy_directories = { "doc/html", }, } lualogging-1.8.2/rockspecs/lualogging-1.3.0-2.rockspec000066400000000000000000000020001436502304500223170ustar00rootroot00000000000000package = "lualogging" version = "1.3.0-2" source = { url = "git://github.com/lunarmodules/lualogging.git", branch = "v1.3.0", } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/lunarmodules/lualogging", license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", } }, copy_directories = { "doc/html", }, } lualogging-1.8.2/rockspecs/lualogging-1.4.0-1.rockspec000066400000000000000000000020721436502304500223300ustar00rootroot00000000000000package = "lualogging" version = "1.4.0-1" source = { url = "git://github.com/lunarmodules/lualogging.git", branch = "v1.4.0", } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/lunarmodules/lualogging", license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.5.0-1.rockspec000066400000000000000000000025011436502304500223260ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.5.0" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", tag = "v"..package_version } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.5.1-1.rockspec000066400000000000000000000025011436502304500223270ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.5.1" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", tag = "v"..package_version } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.5.2-1.rockspec000066400000000000000000000025011436502304500223300ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.5.2" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", tag = "v"..package_version } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.6.0-1.rockspec000066400000000000000000000025611436502304500223350ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.6.0" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = "master" } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.6.0-2.rockspec000066400000000000000000000027361436502304500223420ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.6.0" local rockspec_revision = "2" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "dev") and "master" or nil, tag = (package_version ~= "dev") and ("v"..package_version) or nil, } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.7.0-1.rockspec000066400000000000000000000030331436502304500223310ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.7.0" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "dev") and "master" or nil, tag = (package_version ~= "dev") and ("v"..package_version) or nil, } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", ['logging.rsyslog'] = "src/logging/rsyslog.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.8.0-1.rockspec000066400000000000000000000031311436502304500223310ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.8.0" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "dev") and "master" or nil, tag = (package_version ~= "dev") and ("v"..package_version) or nil, } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", ['logging.rsyslog'] = "src/logging/rsyslog.lua", ['logging.envconfig'] = "src/logging/envconfig.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.8.1-1.rockspec000066400000000000000000000031311436502304500223320ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.8.1" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "dev") and "master" or nil, tag = (package_version ~= "dev") and ("v"..package_version) or nil, } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", ['logging.rsyslog'] = "src/logging/rsyslog.lua", ['logging.envconfig'] = "src/logging/envconfig.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/rockspecs/lualogging-1.8.2-1.rockspec000066400000000000000000000031311436502304500223330ustar00rootroot00000000000000local package_name = "lualogging" local package_version = "1.8.2" local rockspec_revision = "1" local github_account_name = "lunarmodules" local github_repo_name = package_name package = package_name version = package_version.."-"..rockspec_revision source = { url = "git://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "dev") and "master" or nil, tag = (package_version ~= "dev") and ("v"..package_version) or nil, } description = { summary = "A simple API to use logging features", detailed = [[ LuaLogging provides a simple API to use logging features in Lua. Its design was based on log4j. LuaLogging currently supports, through the use of appenders, console, file, rolling file, email, socket and SQL outputs. ]], homepage = "https://github.com/"..github_account_name.."/"..github_repo_name, license = "MIT/X11", } dependencies = { "luasocket" } build = { type = "none", install = { lua = { ['logging'] = "src/logging.lua", ['logging.console'] = "src/logging/console.lua", ['logging.file'] = "src/logging/file.lua", ['logging.rolling_file'] = "src/logging/rolling_file.lua", ['logging.email'] = "src/logging/email.lua", ['logging.sql'] = "src/logging/sql.lua", ['logging.socket'] = "src/logging/socket.lua", ['logging.nginx'] = "src/logging/nginx.lua", ['logging.rsyslog'] = "src/logging/rsyslog.lua", ['logging.envconfig'] = "src/logging/envconfig.lua", } }, copy_directories = { "docs", }, } lualogging-1.8.2/src/000077500000000000000000000000001436502304500144435ustar00rootroot00000000000000lualogging-1.8.2/src/logging.lua000066400000000000000000000353711436502304500166050ustar00rootroot00000000000000------------------------------------------------------------------------------- -- 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-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer ------------------------------------------------------------------------------- local type, table, string, _tostring, tonumber = type, table, string, tostring, tonumber local select = select local error = error local format = string.format local floor = math.floor local pairs = pairs local ipairs = ipairs local logging = { -- Meta information _COPYRIGHT = "Copyright (C) 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer", _DESCRIPTION = "A simple API to use logging features in Lua", _VERSION = "LuaLogging 1.8.2", } local LEVELS = { "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF" } local MAX_LEVELS = #LEVELS for i, level in ipairs(LEVELS) do LEVELS[level] = i logging[level] = level end local defaultLevel = LEVELS[1] local defaultLogPattern = "%date %level %message\n" local defaultLogPatterns = nil local defaultTimestampPattern = nil local defaultLogger = nil local function rewrite_stacktrace() -- prettify stack-trace, remove lualogging entries and reformat to 1 line local result = '' local trace = debug and debug.traceback() or '' for entry in trace:gmatch("%s*(.-)\n") do if entry:match("%:%d+%:") and not entry:find('logging.lua') then result = result .. ' | ' .. entry end end return result 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 .. rewrite_stacktrace()) 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 -- do nothing function for disabled levels. local function disable_level() end -- a generic print function that prints to the log local function print_to_log(logger, level, ...) local args = { n = select("#", ...), ... } for i = 1, args.n do args[i] = _tostring(args[i]) end args = table.concat(args, " ") .. "\n" for line in args:gmatch("(.-)\n") do logger:log(level, line) end 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. -- @param startLevel log-level to start with -- @return Table representing the new logger object. -- @return String if there was any error setting the custom levels if provided ------------------------------------------------------------------------------- function logging.new(append, startLevel) assert(type(append) == "function", "Appender must be a function, got: %s.", type(append)) startLevel = startLevel or defaultLevel assert(LEVELS[startLevel], "startLevel must be a valid log-level constant if given") local LEVEL_FUNCS = {} local logger = {} logger.append = append logger.setLevel = function (self, level) local order = LEVELS[level] assert(order, "undefined level '%s'", _tostring(level)) local old_level = self.level self.level = level self.level_order = order -- enable/disable levels for i=1, MAX_LEVELS do local name = LEVELS[i]:lower() if i >= order and i ~= MAX_LEVELS then self[name] = LEVEL_FUNCS[i] else self[name] = disable_level end end if old_level and old_level ~= level then self:log(LEVELS[1], "Logger: changing loglevel from %s to %s", old_level, level) end end -- generic log function. logger.log = function (self, level, ...) local order = LEVELS[level] assert(order, "undefined level `%s'", _tostring(level)) if order < self.level_order then return end return LOG_MSG(self, level, ...) end -- a print function generator logger.getPrint = function (self, level) local order = LEVELS[level] assert(order, "undefined level `%s'", _tostring(level)) return function(...) if order >= self.level_order then print_to_log(self, level, ...) end end end -- create the proxy functions for each log level. for i=1, MAX_LEVELS do local level = LEVELS[i] if logger[level:lower()] then return nil, "'" .. level .."' is not a proper level name since there is already a property '" .. level:lower() .. "'" end 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 -- insert log level constants for i=1, MAX_LEVELS do logger[LEVELS[i]] = LEVELS[i] end -- initialize log level. logger:setLevel(startLevel) return logger end ------------------------------------------------------------------------------- -- Prepares the log message ------------------------------------------------------------------------------- local sourceDebugLevel = 1 -- this will be set dynamically below local getDebugInfoLine = debug and "local info = debug.getinfo(%d)" or "local info = { short_src = '?', currentline = -1 }" function logging.compilePattern(pattern) pattern = string.format("%q", pattern) -- replace %source by its components first pattern = pattern:gsub("%%source", "%%file:%%line in function '%%function'") local placeholders = { ["date"] = false, ["level"] = false, ["message"] = false, -- truthy: requires debug info to be fetched first ["file"] = "info.short_src", ["line"] = "tostring(info.currentline)", ["function"] = '(info.name or "unknown function")', } local inject_info = false for placeholder, needs_info in pairs(placeholders) do local count pattern, count = pattern:gsub("%%"..placeholder, '"..'..(needs_info or placeholder)..'.."') inject_info = inject_info or (count>0 and needs_info) end -- cleanup start & end if pattern:sub(1, 4) == '""..' then pattern = pattern:sub(5, -1) end if pattern:sub(-4, -1) == '..""' then pattern = pattern:sub(1, -5) end -- build function local func = [[ return function(date, level, message) ]]..(inject_info and getDebugInfoLine:format(sourceDebugLevel) or "")..[[ return ]]..pattern..[[ end]] return (loadstring or load)(func, "lualogging_generated_formatter")() end local clearCompiledCache do local cache = setmetatable({}, { __index = function(self, pattern) -- pattern wasn't found in cache, compile now, and cache format-function self[pattern] = logging.compilePattern(pattern) return self[pattern] end }) function clearCompiledCache() for k in pairs(cache) do cache[k] = nil end end function logging.prepareLogMsg(lpattern, dpattern, level, message) return cache[lpattern](dpattern, level, message) end end ------------------------------------------------------------------------------- -- os.date replacement with milliseconds if supported -- ms placeholder = %q or %xq (where x is number of decimals) ------------------------------------------------------------------------------- do local gettime = os.time local ok, socket = pcall(require, "socket") -- load luasocket if available if ok then gettime = socket.gettime end -- use a pattern cache to know if we even need ms to format local patternCache = setmetatable({}, { __index = function(self, patt) local placeholder = patt:match("(%%%d*q)") if not placeholder then self[patt] = false return false end local size = tonumber(placeholder:sub(2,-2)) or 3 assert(size >= 1 and size <= 6, "millisecond format %q quantifier range is 1 to 6") self[patt] = ("0"):rep(size) -- a string to grab trailing "0"'s from return self[patt] end }) function logging.date(fmt, t) fmt = fmt or "%c" t = t or gettime() local pad = patternCache[fmt] local ms if pad then -- ms required ms = math.fmod(t,1) local mss = (tostring(ms) .. pad):sub(3, -1) fmt = fmt:gsub("(%%%d*q)", function(placeholder) return mss:sub(1, #pad) end) end local res, err = os.date(fmt, floor(t)) -- 5.3+ requires t to be an integer if type(res) == "table" then res.secf = ms or math.fmod(t,1) end return res, err end 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 ------------------------------------------------------------------------------- -- Application level defaults ------------------------------------------------------------------------------- function logging.defaultLogPatterns(patt) if patt then if type(patt) == "string" then patt = logging.buildLogPatterns({}, patt) end assert(type(patt) == "table", "logPatterns must be a string or a table, got: %s", type(patt)) for _, level in ipairs(LEVELS) do if level ~= "OFF" then assert(type(patt[level]) == "string", "the patterns contains a '%s' value (instead of a string) for level '%s'", type(patt[level]), level) end end defaultLogPatterns = patt end return defaultLogPatterns end function logging.defaultTimestampPattern(patt) if patt then if type(patt) ~= "string" then error("timestampPattern must be a string", 2) end defaultTimestampPattern = patt end return defaultTimestampPattern end function logging.defaultLevel(level) if level then if not LEVELS[level] then assert(LEVELS[level], "undefined level '%s'", _tostring(level)) end defaultLevel = level end return defaultLevel end function logging.defaultLogger(logger) if logger then -- check getPrint to protect against accidental call using colon-notation if type(logger) ~= "table" or type(logger.getPrint) ~= "function" then error("expected a logger object", 2) end defaultLogger = logger end if not defaultLogger then -- no default logger yet, go create it, using the current defaults defaultLogger = require("logging.console") { destination = "stderr" } end return defaultLogger end --- Returns a table of patterns, indexed by loglevel. -- @param patterns (table, optional) table containing logPattern strings per level, defaults to `{}` -- @param default (string, optional) the logPattern to be used for levels not yet present in 'patterns'. -- @return table, with a logPattern for every log-level constant function logging.buildLogPatterns(patterns, default) patterns = patterns or {} assert(type(default) == "string" or type(default) == "nil", "expected default logPattern (2nd argument) to be a string or nil, got: %s", tostring(default)) assert(type(patterns) == "table", "expected patterns (1st argument) to be a table or nil, got: %s", tostring(patterns)) local target = {} for _, level in ipairs(LEVELS) do if level ~= "OFF" then target[level] = patterns[level] or default or defaultLogPatterns[level] end end return target end defaultLogPatterns = logging.buildLogPatterns({}, defaultLogPattern) ------------------------------------------------------------------------------- -- Backward compatible parameter handling ------------------------------------------------------------------------------- function logging.getDeprecatedParams(lst, ...) -- TODO: remove in next major version local args = { n = select("#", ...), ...} if type(args[1]) == "table" then -- this is the new format of a single params-table return args[1] end local params = {} for i, param_name in ipairs(lst) do params[param_name] = args[i] end return params end ------------------------------------------------------------------------------- -- dynamically detect proper source debug level, since this can vary by Lua versions ------------------------------------------------------------------------------- if debug then local detection_logger, test_msg local function detect_func() detection_logger:debug("message") end -- This function MUST be on a single line!! local detect_func_info = debug.getinfo(detect_func) local detect_func_match = detect_func_info.short_src..":"..tostring(detect_func_info.linedefined or -999) detection_logger = logging.new( function(self, level, message) test_msg = logging.prepareLogMsg("%source", "", level, message) end) while true do if not pcall(detect_func) then -- cannot detect debug level, so set the function to fetch debug info to -- return a table that always returns "na" for each lookup getDebugInfoLine = "local info = setmetatable({}, { __index = function() return 'na' end })" break end if test_msg:find(detect_func_match, 1, true) then break -- found correct level, done end -- move to next level sourceDebugLevel = sourceDebugLevel + 1 clearCompiledCache() end end if _VERSION < 'Lua 5.2' then -- still create 'logging' global for Lua versions < 5.2 _G.logging = logging end return logging lualogging-1.8.2/src/logging/000077500000000000000000000000001436502304500160715ustar00rootroot00000000000000lualogging-1.8.2/src/logging/console.lua000066400000000000000000000027571436502304500202510ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Prints logging information to console -- -- @author Thiago Costa Ponte (thiago@ideais.com.br) -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local io = require"io" local logging = require"logging" local prepareLogMsg = logging.prepareLogMsg local destinations = setmetatable({ stdout = "stdout", stderr = "stderr", }, { __index = function(self, key) if not key then return "stdout" -- default value end error("destination parameter must be either 'stderr' or 'stdout', got: "..tostring(key), 3) end }) local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params, ...) params = logging.getDeprecatedParams({ "logPattern" }, params, ...) local startLevel = params.logLevel or logging.defaultLevel() local timestampPattern = params.timestampPattern or logging.defaultTimestampPattern() local destination = destinations[params.destination] local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern) return logging.new( function(self, level, message) io[destination]:write(prepareLogMsg(logPatterns[level], logging.date(timestampPattern), level, message)) return true end, startLevel) end logging.console = M return M lualogging-1.8.2/src/logging/email.lua000066400000000000000000000032021436502304500176600ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Emails logging information to the given recipient -- -- @author Thiago Costa Ponte (thiago@ideais.com.br) -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local logging = require"logging" local smtp = require"socket.smtp" local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params) params = params or {} params.headers = params.headers or {} if params.from == nil then return nil, "'from' parameter is required" end if params.rcpt == nil then return nil, "'rcpt' parameter is required" end local timestampPattern = params.timestampPattern or logging.defaultTimestampPattern() local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern) local startLevel = params.logLevel or logging.defaultLevel() return logging.new( function(self, level, message) local dt = logging.date(timestampPattern) local s = logging.prepareLogMsg(logPatterns[level], dt, level, message) if params.headers.subject then params.headers.subject = logging.prepareLogMsg(params.headers.subject, dt, level, message) end local msg = { headers = params.headers, body = s } params.source = smtp.message(msg) params.port = "25" local r, e = smtp.send(params) if not r then return nil, e end return true end, startLevel) end logging.email = M return M lualogging-1.8.2/src/logging/envconfig.lua000066400000000000000000000140151436502304500205530ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Configures LuaLogging from the environment -- -- @author Thijs Schreijer -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local ll = require "logging" local levels = { "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF" } local default_logger_name = "console" local default_logger_opts = { destination = "stderr" } local default_log_level = ll.defaultLevel() local default_timestamp_pattern = ll.defaultTimestampPattern() local default_prefix = "LL" -- -- Debug code to display environment variable access -- local getenv = os.getenv -- os.getenv = function(key) -- print(key.."="..tostring(getenv(key))) -- return getenv(key) -- end local M = {} local function validate_prefix(prefix) if type(prefix) ~= "string" then return nil, "expected prefix to be a string" end if prefix ~= prefix:gsub("[^0-9a-zA-Z_]", "") then return nil, "prefix can contain only A-Z, 0-9, and _" end if not prefix:match("^[a-zA-Z]") then return nil, "prefix must start with A-Z" end return true end --- table that dynamically looks up environment variables. -- Keys must be strings "A-Z0-9_", and start with "A-Z". The lookup -- is case-insensitive, the environment variable MUST be in ALL CAPS. -- Values will be converted to boolean if "true"/"false" (case-insensitive), or -- to a number if a valid number. -- @tparam string prefix for the environment variables -- @return table local function envloader(prefix) assert(validate_prefix(prefix)) prefix = prefix .. "_" -- looking up in this table will fetch from the environment with the proper prefix -- will convert bools, numbers, "logLevel" and "logPatterns" to proper format -- -- NOTE: its a meta-method; so cannot return nil+err, must throw errors! local env = setmetatable({}, { __index = function(self, key) if type(key) ~= "string" or key ~= key:gsub("[^0-9a-zA-Z_]", "") or #key == 0 then return nil end local envvar = (prefix..key):upper() -- log patterns table (special case) if key:lower() == "logpatterns" then local patt = {} for _, l in ipairs(levels) do local level = ll[l] -- the numeric constant for the level patt[level] = os.getenv(envvar.."_"..l) end if not next(patt) then return nil -- none set, so return nil instead of empty table end return patt end -- read the value local value = os.getenv(envvar) if value == nil then return value end -- logLevel constants if key:lower() == "loglevel" then for _, l in ipairs(levels) do if value:upper() == l then return ll[value:upper()] end end error(("not a proper loglevel set in env var %s: '%s' (use one of: %s"): format(envvar, value, '"DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF"')) end -- check for boolean if value:lower() == "true" or value:lower() == "false" then return value:lower() == "true" end -- check for number if value:gsub("[1-9%.%-]", "") == "" and #value - #value:gsub("[%.]", "") <= 1 and -- zero or 1 "." character (#value - #value:gsub("[%-]", "") == 0 or -- zero "-" characters #value - #value:gsub("[%-]", "") == 1 and value:match("^%-")) and -- 1 "-" character, at first pos #value - #value:gsub("[1-9]", "") >= 1 then -- at least 1 digit return tonumber(value) end -- return as string return value end }) return env end do local base_set = false local base_name local base_opts --- Collects and sets the default logger and its option (does not create the logger). -- From an application, this is the first call to make, to set the "prefix" for the -- environment variables to use. -- @tparam prefix the prefix for env vars to use. -- @return true, or nil + err on failure function M.set_default_settings(prefix) if base_set then return nil, "already set a default" end local ok, err = validate_prefix(prefix) if not ok then return ok, err end base_opts = envloader(prefix) base_name = base_opts.logger if not base_name then -- no logger specified, so load options for default, and send defaults if absent base_name = default_logger_name for k, v in pairs(default_logger_opts) do local ev = base_opts[k] if ev == nil then -- false is a valid value, so check against nil ev = v end base_opts[k] = ev end end -- load additional standard options base_opts.logLevel = base_opts.logLevel or default_log_level base_opts.timestampPattern = base_opts.timestampPattern or default_timestamp_pattern base_opts.logPatterns = ll.buildLogPatterns(base_opts.logPatterns or {}, base_opts.logPattern) base_set = true return true end -- returns the loggername, and the options table for it function M.get_default_settings() if not base_set then assert(M.set_default_settings(default_prefix)) end return base_name, base_opts end end --- Gets default logger options and then creates and sets the LuaLogging -- default logger. Should be called once, at application start. Not to be called by -- libraries, since this is an application global setting. -- @tparam[opt] string prefix if provided, then the default settings will be set -- using this prefix. If they were already set, it will return nil+err in that case. -- return default logger as set function M.set_default_logger(prefix) if prefix then local ok, err = M.set_default_settings(prefix) if not ok then return nil, err end end local name, opts = M.get_default_settings() -- create the logger local logger = assert(require("logging."..name)(opts)) -- set default and return it return ll.defaultLogger(logger) end return M lualogging-1.8.2/src/logging/file.lua000066400000000000000000000043171436502304500175200ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Saves logging information in a file -- -- @author Thiago Costa Ponte (thiago@ideais.com.br) -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local logging = require"logging" local lastFileNameDatePattern local lastFileHandler local buffer_mode do local dir_separator = _G.package.config:sub(1,1) local is_windows = dir_separator == '\\' if is_windows then -- Windows does not support "line" buffered mode, see -- https://github.com/lunarmodules/lualogging/pull/9 buffer_mode = "no" else buffer_mode = "line" end end local openFileLogger = function (filename, datePattern) local filename = string.format(filename, logging.date(datePattern)) if (lastFileNameDatePattern ~= filename) then local f = io.open(filename, "a") if (f) then f:setvbuf(buffer_mode) lastFileNameDatePattern = filename lastFileHandler = f return f else return nil, string.format("file `%s' could not be opened for writing", filename) end else return lastFileHandler end end local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params, ...) params = logging.getDeprecatedParams({ "filename", "datePattern", "logPattern" }, params, ...) local filename = params.filename local datePattern = params.datePattern local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern) local timestampPattern = params.timestampPattern or logging.defaultTimestampPattern() local startLevel = params.logLevel or logging.defaultLevel() if type(filename) ~= "string" then filename = "lualogging.log" end return logging.new( function(self, level, message) local f, msg = openFileLogger(filename, datePattern) if not f then return nil, msg end local s = logging.prepareLogMsg(logPatterns[level], logging.date(timestampPattern), level, message) f:write(s) return true end, startLevel) end logging.file = M return M lualogging-1.8.2/src/logging/nginx.lua000066400000000000000000000030351436502304500177200ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Forwards logging information to the Nginx log -- -- @author Thijs Schreijer -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local logging = require "logging" local prepareLogMsg = logging.prepareLogMsg local ngx_log = assert((ngx or {}).log, "this logger can only be used with OpenResty") local levels = { [logging.FATAL] = ngx.EMERG, [logging.ERROR] = ngx.ERR, [logging.WARN] = ngx.WARN, [logging.INFO] = ngx.INFO, [logging.DEBUG] = ngx.DEBUG, } local target_level do -- set the default lualogging level, based on the detected Nginx level local sys_log_level = require("ngx.errlog").get_sys_filter_level() for ll_level, ngx_level in pairs(levels) do if sys_log_level == ngx_level then target_level = ll_level ngx_log(ngx.DEBUG, "setting LuaLogging default level '", ll_level, "' to match Nginx level: ", ngx_level) break end end assert(target_level, "failed to map ngx log-level '"..tostring(sys_log_level).."' to a LuaLogging level") end local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params) return logging.new(function(self, level, message) return ngx_log(levels[level], prepareLogMsg("%message", "", level, message)) end, target_level) end logging.nginx = M return M lualogging-1.8.2/src/logging/rolling_file.lua000066400000000000000000000055501436502304500212460ustar00rootroot00000000000000--------------------------------------------------------------------------- -- RollingFileAppender is a FileAppender that rolls over the logfile -- once it has reached a certain size limit. It also mantains a -- maximum number of log files. -- -- @author Tiago Cesar Katcipis (tiagokatcipis@gmail.com) -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer --------------------------------------------------------------------------- local logging = require"logging" local buffer_mode do local dir_separator = _G.package.config:sub(1,1) local is_windows = dir_separator == '\\' if is_windows then -- Windows does not support "line" buffered mode, see -- https://github.com/lunarmodules/lualogging/pull/9 buffer_mode = "no" else buffer_mode = "line" end end local function openFile(self) self.file = io.open(self.filename, "a") if not self.file then return nil, string.format("file `%s' could not be opened for writing", self.filename) end self.file:setvbuf(buffer_mode) return self.file end local rollOver = function (self) for i = self.maxIndex - 1, 1, -1 do -- files may not exist yet, lets ignore the possible errors. os.rename(self.filename.."."..tostring(i), self.filename.."."..tostring(i+1)) end self.file:close() self.file = nil local _, msg = os.rename(self.filename, self.filename..".".."1") if msg then return nil, string.format("error %s on log rollover", msg) end return openFile(self) end local openRollingFileLogger = function (self) if not self.file then return openFile(self) end local filesize = self.file:seek("end", 0) if not filesize then self.file:close() self.file = nil return openFile(self) end if (filesize < self.maxSize) then return self.file end return rollOver(self) end local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params, ...) params = logging.getDeprecatedParams({ "filename", "maxFileSize", "maxBackupIndex", "logPattern" }, params, ...) local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern) local timestampPattern = params.timestampPattern or logging.defaultTimestampPattern() local startLevel = params.logLevel or logging.defaultLevel() local obj = { filename = type(params.filename) == "string" and params.filename or "lualogging.log", maxSize = params.maxFileSize, maxIndex = params.maxBackupIndex or 1 } return logging.new( function(self, level, message) local f, msg = openRollingFileLogger(obj) if not f then return nil, msg end local s = logging.prepareLogMsg(logPatterns[level], logging.date(timestampPattern), level, message) f:write(s) return true end, startLevel) end logging.rolling_file = M return M lualogging-1.8.2/src/logging/rsyslog.lua000066400000000000000000000256711436502304500203110ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Syslog for LuaLogging to a remote server using UDP/TCP -- -- @author Thijs Schreijer -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- -- This module differs from [`LuaSyslog`](https://github.com/lunarmodules/luasyslog) -- in that it will log to a remote server, where `LuaSyslog` will log to the local -- syslog daemon. local socket = require "socket" local logging = require "logging" local prepareLogMsg = logging.prepareLogMsg local pcall = pcall local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) -- set on module table to be able to override it. For example with a Copas -- socket. No need for UDP, since UDP sending is non-blocking. M.tcp = socket.tcp local NILVALUE = "-" local MONTHS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } -- determine the local machine hostname, once at startup local HOSTNAME do if _G.package.config:sub(1,1) == "\\" then -- Windows HOSTNAME = os.getenv("COMPUTERNAME") else -- Unix like local f = io.popen ("/bin/hostname") HOSTNAME = f:read("*a") f:close() end HOSTNAME = (HOSTNAME or ""):gsub("[^\33-\126]", "") if HOSTNAME == "" then local s = socket.udp() s:setpeername("1.1.1.1",80) -- ip for cloudflare dns HOSTNAME = s:getsockname() end HOSTNAME = (HOSTNAME or ""):gsub("[^\33-\126]", "") if HOSTNAME == "" then HOSTNAME = NILVALUE end end -- the syslog constants local syslog_facilities = { FACILITY_KERN = 0 * 8, FACILITY_USER = 1 * 8, FACILITY_MAIL = 2 * 8, FACILITY_DAEMON = 3 * 8, FACILITY_AUTH = 4 * 8, FACILITY_SYSLOG = 5 * 8, FACILITY_LPR = 6 * 8, FACILITY_NEWS = 7 * 8, FACILITY_UUCP = 8 * 8, FACILITY_CRON = 9 * 8, FACILITY_AUTHPRIV = 10 * 8, FACILITY_FTP = 11 * 8, FACILITY_NTP = 12 * 8, FACILITY_SECURITY = 13 * 8, FACILITY_CONSOLE = 14 * 8, FACILITY_NETINFO = 12 * 8, FACILITY_REMOTEAUTH = 13 * 8, FACILITY_INSTALL = 14 * 8, FACILITY_RAS = 15 * 8, FACILITY_LOCAL0 = 16 * 8, FACILITY_LOCAL1 = 17 * 8, FACILITY_LOCAL2 = 18 * 8, FACILITY_LOCAL3 = 19 * 8, FACILITY_LOCAL4 = 20 * 8, FACILITY_LOCAL5 = 21 * 8, FACILITY_LOCAL6 = 22 * 8, FACILITY_LOCAL7 = 23 * 8, } for k,v in pairs(syslog_facilities) do M[k] = v end local syslog_levels = { LOG_EMERG = 0, LOG_ALERT = 1, LOG_CRIT = 2, LOG_ERR = 3, LOG_WARNING = 4, LOG_NOTICE = 5, LOG_INFO = 6, LOG_DEBUG = 7, } -- lookup table: convert lualogging level constant to syslog level constant local convert = { [logging.DEBUG] = syslog_levels.LOG_DEBUG, [logging.INFO] = syslog_levels.LOG_INFO, [logging.WARN] = syslog_levels.LOG_WARNING, [logging.ERROR] = syslog_levels.LOG_ERR, [logging.FATAL] = syslog_levels.LOG_ALERT, } -- --------------------------------------------------------------------------- -- Writer functions for both RFC's -- --------------------------------------------------------------------------- M.writers = {} function M.writers.rfc3164(prio, facility, ident, _, _, msg) local d = os.date("!*t") msg = msg:gsub("\n", "\\n"):gsub("\t", " "):gsub("\0-\31", "") -- higher bytes allowed, for UTF8... not according to spec return ("<%d>%s %2d %02d:%02d:%02d %s %s %s\n"):format(facility + prio, MONTHS[d.month], d.day, d.hour, d.min, d.sec, HOSTNAME, ident, msg) end function M.writers.rfc5424(prio, facility, ident, procid, msgid, msg) local timestamp = logging.date("!%Y-%m-%dT%H:%M:%S.%qZ") return ("<%d>1 %s %s %s %s %s - %s"):format(facility + prio, timestamp, HOSTNAME, ident, procid, msgid, msg) end -- --------------------------------------------------------------------------- -- sender functions for UDP and TCP -- --------------------------------------------------------------------------- M.senders = {} -- sockets indexed by cache-key. -- NOTE: sockets should be anchored on the logger object to prevent GC -- of active ones. local socket_cache = setmetatable({}, { __mode = "v" }) local function socket_error(self, err) io.stderr:write(err.."\n") return nil, err end function M.senders.udp(self, msg, is_retry) local sock = self.socket if not sock then local cache_key = self.socket_cache_key sock = socket_cache[cache_key] if not sock then -- create a new socket local host, port = cache_key:match("^udp://(.+):(%d+)$") sock = assert(socket.udp()) assert(sock:settimeout(5)) local ok, err = sock:setpeername(host, tonumber(port)) if not ok then return socket_error(self, "failed to connect to "..cache_key..": ".. tostring(err).."\n"..tostring(msg)) end -- cache it socket_cache[cache_key] = sock end -- anchor it self.socket = sock end local ok, err = sock:send(msg) if not ok then sock:close() self.socket = nil socket_cache[self.socket_cache_key] = nil -- recurse once; will recreate the socket and retry if not is_retry then return M.senders.udp(self, msg, true) else return socket_error(self, "failed to send msg (after retry) to "..self.socket_cache_key..": ".. tostring(err).."\n"..tostring(msg)) end end return true end function M.senders.tcp(self, msg, is_retry) local sock = self.socket if not sock then local cache_key = self.socket_cache_key sock = socket_cache[cache_key] if not sock then -- create a new socket local host, port = cache_key:match("^tcp://(.+):(%d+)$") sock = assert(M.tcp()) assert(sock:settimeout(5)) local ok, err = sock:connect(host, tonumber(port)) if not ok then return socket_error(self, "failed to connect to "..cache_key..": ".. tostring(err).."\n"..tostring(msg)) end ok, err = sock:setoption("keepalive", true) if not ok then return socket_error(self, "failed to set keepalive for "..cache_key..": ".. tostring(err).."\n"..tostring(msg)) end -- cache it socket_cache[cache_key] = sock end -- anchor it self.socket = sock end local payload if self.send_msg_size then payload = ("%d %s"):format(#msg, msg) else payload = msg.."\n" -- old RFC, terminate by LF end local last_byte_send = 0 local size = #payload local err, last_send_error while last_byte_send < size do last_byte_send, err, last_send_error = sock:send(payload, last_byte_send + 1, size) if not last_byte_send then sock:close() self.socket = nil socket_cache[self.socket_cache_key] = nil -- recurse once; will recreate the socket and retry if not is_retry then return M.senders.tcp(self, msg, true) else return socket_error(self, "failed to send msg (after retry) to "..self.socket_cache_key.." ("..tostring(last_send_error).." bytes sent): ".. tostring(err).."\n"..tostring(msg)) end end end return true end function M.senders.copas(self, msg) local q = self.queue q:push(msg) if q:get_size() >= 1000 then -- queue is running full, drop an old message q:pop() end end -- --------------------------------------------------------------------------- -- instantiation -- --------------------------------------------------------------------------- local function validate_facility(f) for k, v in pairs(syslog_facilities) do if v == f then if tostring(k):find("FACILITY_") then return f end end end return nil, "bad facility; " .. tostring(f) end local function copas_tcp() local copas = require("copas") return copas.wrap(socket.tcp()) end function M.new(params, ...) params = logging.getDeprecatedParams({ "ident", "facility" }, params, ...) local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern or "%message") local startLevel = params.logLevel or logging.defaultLevel() local ident = (params.ident or "lua"):gsub("[^\33-\126]", "") assert(#ident > 0 and ident == (params.ident or "lua"), "invalid ident; invalid characters or empty") local procid = (params.procid or NILVALUE):gsub("[^\33-\126]", "") assert(#procid > 0 and procid == (params.procid or NILVALUE), "invalid procid; invalid characters or empty") local msgid = (params.msgid or NILVALUE):gsub("[^\33-\126]", "") assert(#msgid > 0 and msgid == (params.msgid or NILVALUE), "invalid msgid invalid characters or empty") local facility = assert(validate_facility(params.facility or syslog_facilities.FACILITY_USER)) local maxsize = tonumber(params.maxsize) local write = assert(M.writers[params.rfc or "rfc3164"], "unsupported format: "..tostring(params.rfc)) if not maxsize then maxsize = 2048 if params.rfc == "rfc3164" then maxsize = 1024 end end assert(maxsize > 480, "expected maxsize to be a number > 480") -- if send_msg_size is truthy then the message will be prefixed by the length. Otherwise -- an "\n" will be appended as separator. Only applies to TCP. local send_msg_size = false if params.rfc == "rfc5424" then send_msg_size = true end local port = params.port or 514 assert(type(port) == "number" and port > 0 and port < 65535, "not a valid port number: " .. tostring(params.port)) local hostname = params.hostname assert(type(hostname) == "string", "expected 'hostname' to be a string") local protocol = params.protocol local send = assert(M.senders[protocol or "tcp"], "unsupported protocol: "..tostring(protocol)) if protocol == "tcp" and M.tcp == copas_tcp then -- copas was enabled, so use copas instead of tcp send = M.senders.copas end local new_logger = logging.new(function(self, level, message) message = prepareLogMsg(logPatterns[level], "", level, message) message = write(convert[level], facility, ident, procid, msgid, message) send(self, message:sub(1, maxsize)) return true end, startLevel) -- set some logger properties new_logger.socket_cache_key = ("%s://%s:%d"):format(protocol, hostname, port) new_logger.send_msg_size = send_msg_size if protocol == "tcp" and M.tcp == copas_tcp then -- a copas sender, needs an async queue, and a worker to process the messages local queue = require("copas.queue").new { name = "lualogging-rsyslog" } local tcp_sender = M.senders.tcp queue:add_worker(function(msg) local ok, err = pcall(tcp_sender, new_logger, msg) if not ok then socket_error(new_logger, "lualogging rsyslog failed logging through Copas socket: "..tostring(err).."\n"..tostring(msg)) end end) new_logger.queue = queue function new_logger:destroy() if self.queue then self.queue:stop() self.queue = nil end end end return new_logger end function M.copas() if _VERSION=="Lua 5.1" and not jit then -- prevent yield across c-boundary pcall = require("coxpcall").pcall end M.tcp = copas_tcp end logging.rsyslog = M return M lualogging-1.8.2/src/logging/socket.lua000066400000000000000000000026611436502304500200710ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Sends the logging information through a socket using luasocket -- -- @author Thiago Costa Ponte (thiago@ideais.com.br) -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local logging = require"logging" local socket = require"socket" local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params, ...) params = logging.getDeprecatedParams({ "hostname", "port", "logPattern" }, params, ...) local hostname = params.hostname local port = params.port local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern) local timestampPattern = params.timestampPattern or logging.defaultTimestampPattern() local startLevel = params.logLevel or logging.defaultLevel() return logging.new( function(self, level, message) local s = logging.prepareLogMsg(logPatterns[level], logging.date(timestampPattern), level, message) local socket, err = socket.connect(hostname, port) if not socket then return nil, err end local cond, err = socket:send(s) if not cond then return nil, err end socket:close() return true end, startLevel) end logging.socket = M return M lualogging-1.8.2/src/logging/sql.lua000066400000000000000000000040001436502304500173650ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Saves the logging information in a table using luasql -- -- @author Thiago Costa Ponte (thiago@ideais.com.br) -- -- @copyright 2004-2010 Kepler Project, 2011-2013 Neopallium, 2020-2023 Thijs Schreijer -- ------------------------------------------------------------------------------- local logging = require"logging" local M = setmetatable({}, { __call = function(self, ...) -- calling on the module instantiates a new logger return self.new(...) end, }) function M.new(params) params = params or {} params.tablename = params.tablename or "LogTable" params.logdatefield = params.logdatefield or "LogDate" params.loglevelfield = params.loglevelfield or "LogLevel" params.logmessagefield = params.logmessagefield or "LogMessage" local startLevel = params.logLevel or logging.defaultLevel() if params.connectionfactory == nil or type(params.connectionfactory) ~= "function" then return nil, "No specified connection factory function" end local con, err if params.keepalive then con, err = params.connectionfactory() end return logging.new( function(self, level, message) if (not params.keepalive) or (con == nil) then con, err = params.connectionfactory() if not con then return nil, err end end local logDate = os.date("%Y-%m-%d %H:%M:%S") local insert = string.format("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')", params.tablename, params.logdatefield, params.loglevelfield, params.logmessagefield, logDate, level, string.gsub(message, "'", "''")) local ret = pcall(con.execute, con, insert) if not ret then con, err = params.connectionfactory() if not con then return nil, err end ret, err = con:execute(insert) if not ret then return nil, err end end if not params.keepalive then con:close() end return true end, startLevel) end logging.sql = M return M lualogging-1.8.2/tests/000077500000000000000000000000001436502304500150165ustar00rootroot00000000000000lualogging-1.8.2/tests/generic.lua000066400000000000000000000216301436502304500171370ustar00rootroot00000000000000local logging = require "logging" local call_count local last_msg local msgs function logging.test(params) local logPatterns = logging.buildLogPatterns(params.logPatterns, params.logPattern) local timestampPattern = params.timestampPattern or logging.defaultTimestampPattern() return logging.new( function(self, level, message) last_msg = logging.prepareLogMsg(logPatterns[level], os.date(timestampPattern), level, message) msgs = msgs or {} table.insert(msgs, last_msg) --print("----->",last_msg) call_count = call_count + 1 return true end) end local function reset() call_count = 0 last_msg = nil msgs = nil end local tests = {} tests.constants_for_lualogging = function() local DEFAULT_LEVELS = { "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF" } for _, level in ipairs(DEFAULT_LEVELS) do assert(logging[level], "constant logging."..level.." is not defined") end end tests.deprecated_parameter_handling = function() local list = { "param1", "next_one", "hello_world" } local params = logging.getDeprecatedParams(list, { param1 = 1, next_one = nil, hello_world = 3, }) assert(params.param1 == 1) assert(params.next_one == nil) assert(params.hello_world == 3) params = logging.getDeprecatedParams(list, 1, nil, 3) assert(params.param1 == 1) assert(params.next_one == nil) assert(params.hello_world == 3) end tests.buildLogPatterns = function() local check_patterns = function(t) assert(type(t) == "table") assert(t.DEBUG and t.INFO and t.WARN and t.ERROR and t.FATAL) local i = 0 for k,v in pairs(t) do i = i + 1 end assert(i == 5) end local t = logging.buildLogPatterns() check_patterns(t) local t = logging.buildLogPatterns(nil, "hello") check_patterns(t) assert(t.DEBUG == "hello") assert(t.FATAL == "hello") local t = logging.buildLogPatterns({}, "hello") check_patterns(t) assert(t.DEBUG == "hello") assert(t.FATAL == "hello") local t = logging.buildLogPatterns({ DEBUG = "bye" }, "hello") check_patterns(t) assert(t.DEBUG == "bye") assert(t.INFO == "hello") assert(t.FATAL == "hello") end tests.log_levels = function() local logger = logging.test { logPattern = "%message", timestampPattern = nil } logger:setLevel(logger.DEBUG) -- debug gets logged logger:debug("message 1") assert(last_msg == "message 1", "got: " .. tostring(last_msg)) assert(call_count == 1, "Got: " .. tostring(call_count)) -- fatal also gets logged at 'debug' setting logger:fatal("message 2") assert(last_msg == "message 2", "got: " .. tostring(last_msg)) assert(call_count == 2, "Got: " .. tostring(call_count)) logger:setLevel(logger.FATAL) -- debug gets logged logger:debug("message 3") -- should not change the last message assert(last_msg == "message 2", "got: " .. tostring(last_msg)) assert(call_count == 2, "Got: " .. tostring(call_count)) -- fatal also gets logged at 'debug' setting logger:fatal("message 4") -- should be logged as 3rd message assert(last_msg == "message 4", "got: " .. tostring(last_msg)) assert(call_count == 3, "Got: " .. tostring(call_count)) logger:setLevel(logger.OFF) -- debug gets logged logger:debug("message 5") -- should not change the last message assert(last_msg == "message 4", "got: " .. tostring(last_msg)) assert(call_count == 3, "Got: " .. tostring(call_count)) -- fatal also gets logged at 'debug' setting logger:fatal("message 6") -- should not change the last message assert(last_msg == "message 4", "got: " .. tostring(last_msg)) assert(call_count == 3, "Got: " .. tostring(call_count)) -- should never log "OFF", even if its set logger:fatal("message 7") -- should not change the last message assert(last_msg == "message 4", "got: " .. tostring(last_msg)) assert(call_count == 3, "Got: " .. tostring(call_count)) end tests.logPatterns = function() local logger = logging.test { logPattern = "%date", timestampPattern = nil } logger:debug("hello") assert(last_msg ~= "%date", "expected '%date' placeholder to be replaced, got: " .. tostring(last_msg)) assert(last_msg ~= "", "expected '%date' placeholder to be replaced by a value, got an empty string") local logger = logging.test { logPattern = "%level", timestampPattern = nil } logger:fatal("hello") assert(last_msg ~= "%level", "expected '%level' placeholder to be replaced, got: " .. tostring(last_msg)) assert(last_msg == "FATAL", "expected '%level' placeholder to be replaced by 'FATAL', got: " .. tostring(last_msg)) local logger = logging.test { logPattern = "%message", timestampPattern = nil } logger:debug("hello") assert(last_msg ~= "%message", "expected '%message' placeholder to be replaced, got: " .. tostring(last_msg)) assert(last_msg == "hello", "expected '%message' placeholder to be replaced by 'hello', got: " .. tostring(last_msg)) local logger = logging.test { logPattern = "%source", timestampPattern = nil } local function test_func() logger:debug("hello") end test_func() assert(last_msg ~= "%source", "expected '%source' placeholder to be replaced, got: " .. tostring(last_msg)) if debug then assert(last_msg:find("'test_func'", 1, true), "expected function name in output, got: " .. tostring(last_msg)) assert(last_msg:find(":138 ", 1, true), "expected line number in output, got: " .. tostring(last_msg)) -- update hardcoded linenumber when this fails! assert(last_msg:find("generic.lua:", 1, true), "expected filename in output, got: " .. tostring(last_msg)) else -- debug library disabled assert(last_msg:find("'unknown function'", 1, true), "expected 'unknwon function' in output, got: " .. tostring(last_msg)) assert(last_msg:find(":-1 ", 1, true), "expected line number (-1) in output, got: " .. tostring(last_msg)) -- update hardcoded linenumber when this fails! assert(last_msg:find("?:", 1, true), "expected filename ('?') in output, got: " .. tostring(last_msg)) end -- mutiple separate patterns local logger = logging.test { logPattern = "%message", logPatterns = { [logging.DEBUG] = "hello %message" }, timestampPattern = nil, } logger:debug("world") assert(last_msg == "hello world", "expected 'hello world', got: " .. tostring(last_msg)) logger:error("world") assert(last_msg == "world", "expected 'world', got: " .. tostring(last_msg)) end tests.table_serialization = function() local logger = logging.test { logPattern = "%message", timestampPattern = nil } logger:debug({1,2,3,4,5,6,7,8,9,10}) assert(last_msg == "{1, 10, 2, 3, 4, 5, 6, 7, 8, 9}", "got: " .. tostring(last_msg)) logger:debug({abc = "cde", "hello", "world", xyz = true, 1, 2, 3}) assert(last_msg == '{"hello", "world", 1, 2, 3, abc = "cde", xyz = true}', "got: " .. tostring(last_msg)) end tests.print_function = function() local logger = logging.test { logPattern = "%level %message" } local print = logger:getPrint(logger.DEBUG) print("hey", "there", "dude") assert(msgs[1] == "DEBUG hey there dude") print() assert(msgs[2] == "DEBUG ") print("hello\nthere") assert(msgs[3] == "DEBUG hello") assert(msgs[4] == "DEBUG there") print({}, true, nil, 0) assert(msgs[5]:find("table")) assert(msgs[5]:find(" true nil 0$")) end tests.format_error_stacktrace = function() local count = 0 local logger = logging.test { logPattern = "%level %message" } logger:debug("%s-%s", 'abc', '007') assert(last_msg == 'DEBUG abc-007') logger:debug("%s=%s", nil) assert(last_msg:find("bad argument #%d to '(.-)'"), "msg:'"..last_msg.."'") if debug then assert(last_msg:find("in main chunk"), "msg:'"..last_msg.."'") assert(last_msg:find("in %w+ 'func'"), "msg:'"..last_msg.."'") local _, levels = last_msg:gsub("(|)", function() count = count + 1 end) assert(levels == 3, "got : " .. tostring(levels)) end end tests.defaultLogger = function() -- returns a logger assert(logging.defaultLogger(), "expected a logger object to be returned)") local logger = logging.test {} -- setting a default one assert(logging.defaultLogger(logger), "expected a logger object to be returned)") assert(logger == logging.defaultLogger(), "expected my previously set logger to be returned)") end tests.defaultLevel = function() -- default level is 'debug' local old_level = logging.defaultLevel() assert(old_level == logging.DEBUG, "expected default to be 'debug'") -- setting level assert(logging.defaultLevel(logging.FATAL) == logging.FATAL, "expected updated log-level") -- new logger uses new default level local logger = logging.test {} logger:error("less than 'fatal', should not be logged") assert(call_count == 0) logger:fatal("should be logged") assert(call_count == 1) -- errors on unknown level assert(not pcall(logging.defaultLevel, "unknown level"), "expected an error to be thrown") -- restore old default logging.defaultLevel(old_level) end for name, func in pairs(tests) do reset() print("generic test: " .. name) func() end print("[v] all generic tests succesful") lualogging-1.8.2/tests/run_tests.sh000077500000000000000000000001341436502304500174010ustar00rootroot00000000000000#!/bin/sh set -e LUA_PATH="../src/?.lua;$LUA_PATH" lua test.lua rm -f test.db test.log* lualogging-1.8.2/tests/test.lua000066400000000000000000000004471436502304500165050ustar00rootroot00000000000000 local test = { "generic.lua", "testEnv.lua", "testConsole.lua", "testFile.lua", "testMail.lua", "testSocket.lua", "testSQL.lua", "testRollingFile.lua", } print ("Start of Logging tests") for _, filename in ipairs(test) do dofile(filename) end print ("End of Logging tests") lualogging-1.8.2/tests/testConsole.lua000066400000000000000000000004331436502304500200230ustar00rootroot00000000000000local log_console = require"logging.console" local logger = log_console() logger:info("logging.console test") logger:debug("debugging...") logger:error("error!") logger:debug("string with %4") logger:setLevel("INFO") -- test log level change warning. print("Console Logging OK") lualogging-1.8.2/tests/testEnv.lua000066400000000000000000000121011436502304500171440ustar00rootroot00000000000000local logging local logenv local env local old_getenv = os.getenv function os.getenv(key) -- luacheck: ignore assert(type(key) == "string", "expected env variable name to be a string") return env[key] end local function reset() env = {} package.loaded["logging"] = nil package.loaded["logging.envconfig"] = nil logging = require "logging" logenv = require "logging.envconfig" end local tests = {} tests.returns_defaults = function() local name, opts = logenv.get_default_settings() -- print("title: ", require("pl.pretty").write(opts)) assert(name == "console", "expected 'console' to be the default logger") assert(type(opts) == "table", "expected 'opts' to be a table") assert(opts.destination == "stderr", "expected 'destination' to be 'stderr'") assert(opts.logLevel == "DEBUG", "expected 'logLevel' to be 'DEBUG'") assert(opts.logPatterns.DEBUG == "%date %level %message\n") assert(opts.logPatterns.INFO == "%date %level %message\n") assert(opts.logPatterns.WARN == "%date %level %message\n") assert(opts.logPatterns.ERROR == "%date %level %message\n") assert(opts.logPatterns.FATAL == "%date %level %message\n") end tests.returns_defaults_if_prefix_not_found = function() assert(logenv.set_default_settings("not_a_real_prefix")) local name, opts = logenv.get_default_settings() -- print("title: ", require("pl.pretty").write(opts)) assert(name == "console", "expected 'console' to be the default logger") assert(type(opts) == "table", "expected 'opts' to be a table") assert(opts.destination == "stderr", "expected 'destination' to be 'stderr'") assert(opts.logLevel == "DEBUG", "expected 'logLevel' to be 'DEBUG'") assert(opts.logPatterns.DEBUG == "%date %level %message\n") assert(opts.logPatterns.INFO == "%date %level %message\n") assert(opts.logPatterns.WARN == "%date %level %message\n") assert(opts.logPatterns.ERROR == "%date %level %message\n") assert(opts.logPatterns.FATAL == "%date %level %message\n") end tests.fails_if_default_already_set = function() assert(logenv.set_default_settings("prefix")) local ok, err = logenv.set_default_settings("prefix") assert(err == "already set a default") assert(ok == nil) end tests.prefix_defaults_to_LL = function() env.LL_LOGLEVEL = assert(logging.ERROR) local _, opts = logenv.get_default_settings() -- print("title: ", require("pl.pretty").write(opts)) assert(opts.logLevel == "ERROR", "expected 'logLevel' to be 'ERROR'") end tests.loads_patterns_object = function() env.LL_LOGPATTERN = "not used" env.LL_LOGPATTERNS_DEBUG = "debug" env.LL_LOGPATTERNS_INFO = "info" env.LL_LOGPATTERNS_WARN = "warn" env.LL_LOGPATTERNS_ERROR = "error" env.LL_LOGPATTERNS_FATAL = "fatal" local _, opts = logenv.get_default_settings() -- print("title: ", require("pl.pretty").write(opts)) assert(opts.logPattern == "not used") assert(opts.logPatterns.DEBUG == "debug") assert(opts.logPatterns.INFO == "info") assert(opts.logPatterns.WARN == "warn") assert(opts.logPatterns.ERROR == "error") assert(opts.logPatterns.FATAL == "fatal") end tests.fills_patterns_object_from_logpattern = function() env.LL_LOGPATTERN = "this one" local _, opts = logenv.get_default_settings() -- print("title: ", require("pl.pretty").write(opts)) assert(opts.logPattern == "this one") assert(opts.logPatterns.DEBUG == "this one") assert(opts.logPatterns.INFO == "this one") assert(opts.logPatterns.WARN == "this one") assert(opts.logPatterns.ERROR == "this one") assert(opts.logPatterns.FATAL == "this one") end tests.bad_loglevel_not_accepted = function() env.LL_LOGLEVEL = "something bad" local ok, loggername, opts = pcall(logenv.get_default_settings) -- print("title: ", require("pl.pretty").write(opts)) assert(not ok) assert(opts == nil) assert(type(loggername) == "string") end tests.does_dynamic_lookups_of_vars = function() local _, opts = logenv.get_default_settings() -- "LL" is now prefix -- print("title: ", require("pl.pretty").write(opts)) env.LL_SOME_VALUE = "hello" assert(opts.some_value == "hello") end tests.converts_booleans = function() local _, opts = logenv.get_default_settings() -- "LL" is now prefix -- print("title: ", require("pl.pretty").write(opts)) env.LL_ONE = "TRUE" env.LL_TWO = "true" env.LL_THREE = "false" env.LL_FOUR = "FALSE" assert(opts.one == true) assert(opts.two == true) assert(opts.three == false) assert(opts.four == false) end tests.converts_numbers = function() local _, opts = logenv.get_default_settings() -- "LL" is now prefix env.LL_ONE = "1" env.LL_TWO = "-2" env.LL_THREE = ".2" env.LL_FOUR = "1.2" assert(opts.one == 1, "got: "..tostring(opts.one).." ("..type(opts.one)..")") assert(opts.two == -2, "got: "..tostring(opts.two).." ("..type(opts.two)..")") assert(opts.three == .2, "got: "..tostring(opts.three).." ("..type(opts.three)..")") assert(opts.four == 1.2, "got: "..tostring(opts.four).." ("..type(opts.four)..")") end for name, func in pairs(tests) do reset() print("env-config test: " .. name) func() end print("[v] all env-config tests succesful") os.getenv = old_getenv -- luacheck: ignore lualogging-1.8.2/tests/testFile.lua000066400000000000000000000044221436502304500173020ustar00rootroot00000000000000local GLOBAL_OS_DATE = os.date local GLOBAL_IO_OPEN = io.open local buffer_mode do local dir_separator = _G.package.config:sub(1,1) local is_windows = dir_separator == '\\' if is_windows then -- Windows does not support "line" buffered mode, see -- https://github.com/lunarmodules/lualogging/pull/9 buffer_mode = "no" else buffer_mode = "line" end end local mock = { date = nil, handle = {} } io.open = function (file, mode) --luacheck: ignore if (not string.find(file, "^__TEST*")) then return GLOBAL_IO_OPEN(file, mode) end mock.handle[file] = {} mock.handle[file].lines = {} mock.handle[file].mode = mode return { setvbuf = function (_, s) mock.handle[file].setvbuf = s end, write = function (_, s) table.insert(mock.handle[file].lines, s) end, } end os.date = function (...) --luacheck: ignore return mock.date end local log_file = require "logging.file" mock.date = "2008-01-01" local logger = log_file("__TEST%s.log", "%Y-%m-%d") assert(mock.handle["__TEST"..mock.date..".log"] == nil) logger:info("logging.file test") assert(mock.handle["__TEST"..mock.date..".log"].mode == "a") assert(#mock.handle["__TEST"..mock.date..".log"].lines == 1) assert(mock.handle["__TEST"..mock.date..".log"].setvbuf == buffer_mode) assert(mock.handle["__TEST"..mock.date..".log"].lines[1] == "2008-01-01 INFO logging.file test\n") mock.date = "2008-01-02" logger:debug("debugging...") logger:error("error!") assert(mock.handle["__TEST"..mock.date..".log"].mode == "a") assert(#mock.handle["__TEST"..mock.date..".log"].lines == 2) assert(mock.handle["__TEST"..mock.date..".log"].setvbuf == buffer_mode) assert(mock.handle["__TEST"..mock.date..".log"].lines[1] == "2008-01-02 DEBUG debugging...\n") assert(mock.handle["__TEST"..mock.date..".log"].lines[2] == "2008-01-02 ERROR error!\n") mock.date = "2008-01-03" logger:info({id = "1"}) assert(mock.handle["__TEST"..mock.date..".log"].mode == "a") assert(#mock.handle["__TEST"..mock.date..".log"].lines == 1) assert(mock.handle["__TEST"..mock.date..".log"].setvbuf == buffer_mode) assert(mock.handle["__TEST"..mock.date..".log"].lines[1] == '2008-01-03 INFO {id = "1"}\n') os.date = GLOBAL_OS_DATE --luacheck: ignore io.open = GLOBAL_IO_OPEN --luacheck: ignore print("File Logging OK") lualogging-1.8.2/tests/testMail.lua000066400000000000000000000004561436502304500173100ustar00rootroot00000000000000local log_email = require"logging.email" local logger = log_email { rcpt = "mail@host.com", from = "mail@host.com", { subject = "[%level] logging.email test", }, -- headers } logger:info("logging.email test") logger:debug("debugging...") logger:error("error!") print("Mail Logging OK") lualogging-1.8.2/tests/testRollingFile.lua000066400000000000000000000015771436502304500206410ustar00rootroot00000000000000local log_file = require "logging.rolling_file" local max_size = 1024 * 10 --10kb local max_index = 5 local total_log_size = max_size * max_index --more than needed because of the log pattern local log_filename = "test.log" local logger = log_file(log_filename, max_size, max_index) -- it will generate the log + max_index backup files local size = 0 while size < total_log_size do local data = string.format("Test actual size[%d]", size) logger:debug(data) size = size + #data end -- lets test if all files where created for i = 1, max_index do local file = assert(io.open(log_filename.."."..tostring(i), "r")) -- since there is an exact precision on the rolling -- (it can be a little less or a little more than the max_size) -- lets just test if the file is empty. assert(file:seek("end", 0) > 0) file:close() end print("RollingFile Logging OK") lualogging-1.8.2/tests/testSQL.lua000066400000000000000000000012011436502304500170520ustar00rootroot00000000000000local log_sql = require "logging.sql" local _, luasql = pcall(require, "luasql") local has_module = pcall(require, "luasql.sqlite3") if not has_module then print("SQLite 3 Logging SKIP (missing luasql.sqlite3)") else if not luasql or not luasql.sqlite3 then print("Missing LuaSQL SQLite 3 driver!") else local env = luasql.sqlite3() local logger = log_sql{ connectionfactory = function() return assert(env:connect("test.db")) end, keepalive = true, } logger:info("logging.sql test") logger:debug("debugging...") logger:error("error!") print("SQLite 3 Logging OK") end end lualogging-1.8.2/tests/testSocket.lua000066400000000000000000000003141436502304500176470ustar00rootroot00000000000000local log_sock = require"logging.socket" local logger = log_sock("localhost", "5000") logger:info("logging.socket test") logger:debug("debugging...") logger:error("error!") print("Socket Logging OK")