summaryrefslogtreecommitdiff
path: root/server-beta/src/log.lua
blob: cd62df970f72fea34a9b651c543d6fb4dbf1fddd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
local fs = require 'bee.filesystem'

local log = {}

log.file = nil
log.start_time = os.time() - os.clock()
log.size = 0
log.max_size = 100 * 1024 * 1024

local function trim_src(src)
    src = src:sub(log.prefix_len + 3, -5)
    src = src:gsub('^[/\\]+', '')
    src = src:gsub('[\\/]+', '.')
    return src
end

local function init_log_file()
    if not log.file then
        log.file = io.open(log.path, 'w')
        if not log.file then
            return
        end
        log.file:write('')
        log.file:close()
        log.file = io.open(log.path, 'ab')
        if not log.file then
            return
        end
        log.file:setvbuf 'no'
    end
end

local function pushLog(level, ...)
    if not log.path then
        return
    end
    if log.size > log.max_size then
        return
    end
    local t = table.pack(...)
    for i = 1, t.n do
        t[i] = tostring(t[i])
    end
    local str = table.concat(t, '\t', 1, t.n)
    if level == 'error' then
        str = str .. '\n' .. debug.traceback(nil, 3)
        io.stderr:write(str .. '\n')
    end
    init_log_file()
    if not log.file then
        return
    end
    local sec, ms = math.modf(log.start_time + os.clock())
    local timestr = os.date('%Y-%m-%d %H:%M:%S', sec)
    local info = debug.getinfo(3, 'Sl')
    local buf
    if info and info.currentline > 0 then
        buf = ('[%s.%03.f][%s]: [%s:%s]%s\n'):format(timestr, ms * 1000, level, trim_src(info.source), info.currentline, str)
    else
        buf = ('[%s.%03.f][%s]: %s\n'):format(timestr, ms * 1000, level, str)
    end
    log.file:write(buf)
    log.size = log.size + #buf
    if log.size > log.max_size then
        log.file:write('[REACH MAX SIZE]')
    end
    return str
end

function log.info(...)
    pushLog('info', ...)
end

function log.debug(...)
    pushLog('debug', ...)
end

function log.trace(...)
    pushLog('trace', ...)
end

function log.warn(...)
    pushLog('warn', ...)
end

function log.error(...)
    pushLog('error', ...)
end

function log.init(root, path)
    local lastBuf
    if log.file then
        log.file:close()
        log.file = nil
        local file = io.open(log.path, 'rb')
        if file then
            lastBuf = file:read 'a'
            file:close()
        end
    end
    log.path = path:string()
    log.prefix_len = #root:string()
    log.size = 0
    if not fs.exists(path:parent_path()) then
        fs.create_directories(path:parent_path())
    end
    if lastBuf then
        init_log_file()
        if log.file then
            log.file:write(lastBuf)
            log.size = log.size + #lastBuf
        end
    end
end

return log