forked from editor-code-assistant/eca-nvim
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogger.lua
More file actions
185 lines (156 loc) · 4.27 KB
/
Copy pathlogger.lua
File metadata and controls
185 lines (156 loc) · 4.27 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
local uv = vim.uv or vim.loop
---@class eca.Logger
local M = {}
---@type eca.LogConfig
M.config = nil
local LEVEL_NAMES = {
[vim.log.levels.TRACE] = "TRACE",
[vim.log.levels.DEBUG] = "DEBUG",
[vim.log.levels.INFO] = "INFO",
[vim.log.levels.WARN] = "WARN",
[vim.log.levels.ERROR] = "ERROR",
}
---Get XDG-compliant default log path
---@return string
local function get_default_log_path()
return vim.fn.stdpath("state") .. "/eca.log"
end
---@type eca.LogConfig
local DEFAULT_CONFIG = {
level = vim.log.levels.INFO,
file = get_default_log_path(),
display = "split",
max_file_size_mb = 10,
}
---Get log level name
---@param level integer
---@return string
local function get_level_name(level)
return LEVEL_NAMES[level] or "UNKNOWN"
end
---Check if log file is over size limit and notify if needed
---@param log_path string
---@param max_size_mb number
local function check_log_size_and_notify(log_path, max_size_mb)
uv.fs_stat(log_path, function(err, stat)
if err or not stat then
return
end
local max_size = max_size_mb * 1024 * 1024 -- Convert MB to bytes
if stat.size > max_size then
local size_mb = math.floor(stat.size / 1024 / 1024 * 100) / 100
vim.notify(
string.format("ECA log file is large (%.1fMB). Consider clearing it with :EcaLogs clear", size_mb),
vim.log.levels.WARN,
{ title = "ECA" }
)
end
end)
end
--- Initialize logger with configuration
---@param config eca.LogConfig
function M.setup(config)
config = config or {}
local strings = require("eca.strings")
M.config = {
level = config.level or DEFAULT_CONFIG.level,
file = strings.is_nil_or_empty(config.file) and DEFAULT_CONFIG.file or config.file,
display = config.display or DEFAULT_CONFIG.display,
max_file_size_mb = config.max_file_size_mb or DEFAULT_CONFIG.max_file_size_mb,
}
local log_path = M.get_log_path()
check_log_size_and_notify(log_path, M.config.max_file_size_mb)
end
---@return string
function M.get_display()
return M.config and M.config.display or "split"
end
--- Get current log file path
---@return string
function M.get_log_path()
assert(M.config and M.config.file ~= "", "Logger must be configured with a non-empty file path")
return vim.fn.expand(M.config.file)
end
--- Log a message to the log file
---@param message string
---@param level integer
function M.log(message, level)
if not M.config then
return
end
if level < M.config.level then
return
end
local log_path = M.get_log_path()
vim.fn.mkdir(vim.fn.fnamemodify(log_path, ":h"), "p")
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
local level_name = get_level_name(level)
local formatted = string.format("[%s] %-5s %s\n", timestamp, level_name, message)
uv.fs_open(log_path, "a", 420, function(err, fd)
if err or not fd then
return
end
uv.fs_write(fd, formatted, -1, function()
uv.fs_close(fd)
end)
end)
end
--- Log debug message
---@param message string
function M.debug(message)
M.log(message, vim.log.levels.DEBUG)
end
--- Log info message
---@param message string
function M.info(message)
M.log(message, vim.log.levels.INFO)
end
--- Log warn message
---@param message string
function M.warn(message)
M.log(message, vim.log.levels.WARN)
end
--- Log error message
---@param message string
function M.error(message)
M.log(message, vim.log.levels.ERROR)
end
--- Send notification to user via vim.notify
---@param message string
---@param level? integer vim.log.levels (default: INFO)
---@param opts? {title?: string}
function M.notify(message, level, opts)
level = level or vim.log.levels.INFO
opts = opts or {}
M.log(message, level)
vim.notify(message, level, {
title = opts.title or "ECA",
})
end
--- Get log file statistics
---@return table|nil
function M.get_log_stats()
local log_path = M.get_log_path()
local stat = uv.fs_stat(log_path)
if not stat then
return nil
end
return {
path = log_path,
size = stat.size,
size_mb = math.floor(stat.size / 1024 / 1024 * 100) / 100,
modified = os.date("%Y-%m-%d %H:%M:%S", stat.mtime.sec),
}
end
--- Clear log file
---@return boolean
function M.clear_log()
local log_path = M.get_log_path()
local file = io.open(log_path, "w")
if file then
file:close()
return true
end
return false
end
return M