log.lua 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. local Log = {}
  2. local logfile = string.format("%s/%s.log", vim.fn.stdpath "cache", "lvim")
  3. Log.levels = {
  4. TRACE = 1,
  5. DEBUG = 2,
  6. INFO = 3,
  7. WARN = 4,
  8. ERROR = 5,
  9. }
  10. vim.tbl_add_reverse_lookup(Log.levels)
  11. function Log:init()
  12. local status_ok, structlog = pcall(require, "structlog")
  13. if not status_ok then
  14. return nil
  15. end
  16. local nvim_notify_params = {}
  17. local nvim_notify_params_injecter = function(_, entry)
  18. for key, value in pairs(nvim_notify_params) do
  19. entry[key] = value
  20. end
  21. return entry
  22. end
  23. local nvim_notify_default_namer = function(logger, entry)
  24. entry["title"] = logger.name
  25. return entry
  26. end
  27. nvim_notify_params_injecter(nil, {})
  28. local log_level = Log.levels[(lvim.log.level):upper() or "WARN"]
  29. structlog.configure {
  30. lvim = {
  31. sinks = {
  32. structlog.sinks.Console(log_level, {
  33. async = false,
  34. processors = {
  35. structlog.processors.Namer(),
  36. structlog.processors.StackWriter({ "line", "file" }, { max_parents = 0, stack_level = 2 }),
  37. structlog.processors.Timestamper "%H:%M:%S",
  38. },
  39. formatter = structlog.formatters.FormatColorizer( --
  40. "%s [%-5s] %s: %-30s",
  41. { "timestamp", "level", "logger_name", "msg" },
  42. { level = structlog.formatters.FormatColorizer.color_level() }
  43. ),
  44. }),
  45. structlog.sinks.NvimNotify(Log.levels.INFO, {
  46. processors = {
  47. nvim_notify_default_namer,
  48. nvim_notify_params_injecter,
  49. },
  50. formatter = structlog.formatters.Format( --
  51. "%s",
  52. { "msg" },
  53. { blacklist_all = true }
  54. ),
  55. params_map = {
  56. icon = "icon",
  57. keep = "keep",
  58. on_open = "on_open",
  59. on_close = "on_close",
  60. timeout = "timeout",
  61. title = "title",
  62. },
  63. }),
  64. structlog.sinks.File(Log.levels.TRACE, logfile, {
  65. processors = {
  66. structlog.processors.Namer(),
  67. structlog.processors.StackWriter({ "line", "file" }, { max_parents = 3, stack_level = 2 }),
  68. structlog.processors.Timestamper "%H:%M:%S",
  69. },
  70. formatter = structlog.formatters.Format( --
  71. "%s [%-5s] %s: %-30s",
  72. { "timestamp", "level", "logger_name", "msg" }
  73. ),
  74. }),
  75. },
  76. },
  77. }
  78. local logger = structlog.get_logger "lvim"
  79. if lvim.log.override_notify then
  80. -- Overwrite vim.notify to use the logger
  81. vim.notify = function(msg, vim_log_level, opts)
  82. nvim_notify_params = opts or {}
  83. -- https://github.com/neovim/neovim/blob/685cf398130c61c158401b992a1893c2405cd7d2/runtime/lua/vim/lsp/log.lua#L5
  84. logger:log(vim_log_level + 1, msg)
  85. end
  86. end
  87. return logger
  88. end
  89. --- Adds a log entry using Plenary.log
  90. ---@fparam msg any
  91. ---@param level string [same as vim.log.log_levels]
  92. function Log:add_entry(level, msg, event)
  93. if self.__handle then
  94. self.__handle:log(level, msg, event)
  95. return
  96. end
  97. local logger = self:init()
  98. if not logger then
  99. return
  100. end
  101. self.__handle = logger
  102. self.__handle:log(level, msg, event)
  103. end
  104. ---Retrieves the path of the logfile
  105. ---@return string path of the logfile
  106. function Log:get_path()
  107. return logfile
  108. end
  109. ---Add a log entry at TRACE level
  110. ---@param msg any
  111. ---@param event any
  112. function Log:trace(msg, event)
  113. self:add_entry(self.levels.TRACE, msg, event)
  114. end
  115. ---Add a log entry at DEBUG level
  116. ---@param msg any
  117. ---@param event any
  118. function Log:debug(msg, event)
  119. self:add_entry(self.levels.DEBUG, msg, event)
  120. end
  121. ---Add a log entry at INFO level
  122. ---@param msg any
  123. ---@param event any
  124. function Log:info(msg, event)
  125. self:add_entry(self.levels.INFO, msg, event)
  126. end
  127. ---Add a log entry at WARN level
  128. ---@param msg any
  129. ---@param event any
  130. function Log:warn(msg, event)
  131. self:add_entry(self.levels.WARN, msg, event)
  132. end
  133. ---Add a log entry at ERROR level
  134. ---@param msg any
  135. ---@param event any
  136. function Log:error(msg, event)
  137. self:add_entry(self.levels.ERROR, msg, event)
  138. end
  139. setmetatable({}, Log)
  140. return Log