aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/log.lua
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2024-02-08 09:24:47 +0000
committerLewis Russell <me@lewisr.dev>2024-02-08 11:11:46 +0000
commit1f9da3d0835af2cfe937de250c2cde3a59e1677e (patch)
tree08acc0f5ea7259e81714f833522e9b49bfe20591 /runtime/lua/vim/lsp/log.lua
parent2a7c4aca422f99f3bd3a38425b660b94b5518469 (diff)
downloadrneovim-1f9da3d0835af2cfe937de250c2cde3a59e1677e.tar.gz
rneovim-1f9da3d0835af2cfe937de250c2cde3a59e1677e.tar.bz2
rneovim-1f9da3d0835af2cfe937de250c2cde3a59e1677e.zip
refactor(lsp): tidy up logging
Diffstat (limited to 'runtime/lua/vim/lsp/log.lua')
-rw-r--r--runtime/lua/vim/lsp/log.lua206
1 files changed, 103 insertions, 103 deletions
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index 00433474fe..a9d49bc8f4 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -12,130 +12,130 @@ log.levels = vim.deepcopy(vim.log.levels)
-- Default log level is warn.
local current_log_level = log.levels.WARN
+
local log_date_format = '%F %H:%M:%S'
-local format_func = function(arg)
+
+local function format_func(arg)
return vim.inspect(arg, { newline = '' })
end
-do
- local function notify(msg, level)
- if vim.in_fast_event() then
- vim.schedule(function()
- vim.notify(msg, level)
- end)
- else
+local function notify(msg, level)
+ if vim.in_fast_event() then
+ vim.schedule(function()
vim.notify(msg, level)
- end
+ end)
+ else
+ vim.notify(msg, level)
end
+end
+
+local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'lsp.log')
+
+-- TODO: Ideally the directory should be created in open_logfile(), right
+-- before opening the log file, but open_logfile() can be called from libuv
+-- callbacks, where using fn.mkdir() is not allowed.
+vim.fn.mkdir(vim.fn.stdpath('log'), 'p')
+
+--- Returns the log filename.
+---@return string log filename
+function log.get_filename()
+ return logfilename
+end
+
+--- @type file*?, string?
+local logfile, openerr
- local path_sep = vim.uv.os_uname().version:match('Windows') and '\\' or '/'
- local function path_join(...)
- return table.concat(vim.tbl_flatten({ ... }), path_sep)
+--- Opens log file. Returns true if file is open, false on error
+local function open_logfile()
+ -- Try to open file only once
+ if logfile then
+ return true
+ end
+ if openerr then
+ return false
end
- local logfilename = path_join(vim.fn.stdpath('log'), 'lsp.log')
- -- TODO: Ideally the directory should be created in open_logfile(), right
- -- before opening the log file, but open_logfile() can be called from libuv
- -- callbacks, where using fn.mkdir() is not allowed.
- vim.fn.mkdir(vim.fn.stdpath('log'), 'p')
+ logfile, openerr = io.open(logfilename, 'a+')
+ if not logfile then
+ local err_msg = string.format('Failed to open LSP client log file: %s', openerr)
+ notify(err_msg, vim.log.levels.ERROR)
+ return false
+ end
- --- Returns the log filename.
- ---@return string log filename
- function log.get_filename()
- return logfilename
+ local log_info = vim.uv.fs_stat(logfilename)
+ if log_info and log_info.size > 1e9 then
+ local warn_msg = string.format(
+ 'LSP client log is large (%d MB): %s',
+ log_info.size / (1000 * 1000),
+ logfilename
+ )
+ notify(warn_msg)
end
- local logfile, openerr
- --- Opens log file. Returns true if file is open, false on error
- local function open_logfile()
- -- Try to open file only once
- if logfile then
+ -- Start message for logging
+ logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format)))
+ return true
+end
+
+for level, levelnr in pairs(log.levels) do
+ -- Also export the log level on the root object.
+ log[level] = levelnr
+end
+
+vim.tbl_add_reverse_lookup(log.levels)
+
+--- @param level string
+--- @param levelnr integer
+--- @return fun(...:any): boolean?
+local function create_logger(level, levelnr)
+ return function(...)
+ if levelnr < current_log_level then
+ return false
+ end
+ local argc = select('#', ...)
+ if argc == 0 then
return true
end
- if openerr then
+ if not open_logfile() then
return false
end
-
- logfile, openerr = io.open(logfilename, 'a+')
- if not logfile then
- local err_msg = string.format('Failed to open LSP client log file: %s', openerr)
- notify(err_msg, vim.log.levels.ERROR)
- return false
+ local info = debug.getinfo(2, 'Sl')
+ local header = string.format(
+ '[%s][%s] ...%s:%s',
+ level,
+ os.date(log_date_format),
+ info.short_src:sub(-16),
+ info.currentline
+ )
+ local parts = { header }
+ for i = 1, argc do
+ local arg = select(i, ...)
+ table.insert(parts, arg == nil and 'nil' or format_func(arg))
end
+ assert(logfile)
+ logfile:write(table.concat(parts, '\t'), '\n')
+ logfile:flush()
+ end
+end
- local log_info = vim.uv.fs_stat(logfilename)
- if log_info and log_info.size > 1e9 then
- local warn_msg = string.format(
- 'LSP client log is large (%d MB): %s',
- log_info.size / (1000 * 1000),
- logfilename
- )
- notify(warn_msg)
- end
+-- If called without arguments, it will check whether the log level is
+-- greater than or equal to this one. When called with arguments, it will
+-- log at that level (if applicable, it is checked either way).
- -- Start message for logging
- logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format)))
- return true
- end
+--- @nodoc
+log.debug = create_logger('DEBUG', vim.log.levels.DEBUG)
- for level, levelnr in pairs(log.levels) do
- -- Also export the log level on the root object.
- log[level] = levelnr
- -- FIXME: DOC
- -- Should be exposed in the vim docs.
- --
- -- Set the lowercase name as the main use function.
- -- If called without arguments, it will check whether the log level is
- -- greater than or equal to this one. When called with arguments, it will
- -- log at that level (if applicable, it is checked either way).
- --
- -- Recommended usage:
- -- ```
- -- if log.warn() then
- -- log.warn("123")
- -- end
- -- ```
- --
- -- This way you can avoid string allocations if the log level isn't high enough.
- if level ~= 'OFF' then
- log[level:lower()] = function(...)
- local argc = select('#', ...)
- if levelnr < current_log_level then
- return false
- end
- if argc == 0 then
- return true
- end
- if not open_logfile() then
- return false
- end
- local info = debug.getinfo(2, 'Sl')
- local header = string.format(
- '[%s][%s] ...%s:%s',
- level,
- os.date(log_date_format),
- string.sub(info.short_src, #info.short_src - 15),
- info.currentline
- )
- local parts = { header }
- for i = 1, argc do
- local arg = select(i, ...)
- if arg == nil then
- table.insert(parts, 'nil')
- else
- table.insert(parts, format_func(arg))
- end
- end
- logfile:write(table.concat(parts, '\t'), '\n')
- logfile:flush()
- end
- end
- end
-end
+--- @nodoc
+log.error = create_logger('ERROR', vim.log.levels.ERROR)
--- This is put here on purpose after the loop above so that it doesn't
--- interfere with iterating the levels
-vim.tbl_add_reverse_lookup(log.levels)
+--- @nodoc
+log.info = create_logger('INFO', vim.log.levels.INFO)
+
+--- @nodoc
+log.trace = create_logger('TRACE', vim.log.levels.TRACE)
+
+--- @nodoc
+log.warn = create_logger('WARN', vim.log.levels.WARN)
--- Sets the current log level.
---@param level (string|integer) One of `vim.lsp.log.levels`