log.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. local Log = {}
  2. local logfile = string.format("%s/%s.log", get_cache_dir(), "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 notify_handler = require "lvim.core.notify"
  17. ---Check if notify is available
  18. ---@return boolean
  19. local is_notify_available = function()
  20. local in_headless = #vim.api.nvim_list_uis() == 0
  21. --We can't rely on lvim.builtin.notify.active since this can be used before the config loader
  22. local has_notify_plugin = pcall(require, "notify")
  23. if not in_headless and has_notify_plugin then
  24. return true
  25. end
  26. return false
  27. end
  28. local log_level = Log.levels[(lvim.log.level):upper() or "WARN"]
  29. local lvim_log = {
  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.File(Log.levels.TRACE, logfile, {
  46. processors = {
  47. structlog.processors.Namer(),
  48. structlog.processors.StackWriter({ "line", "file" }, { max_parents = 3, stack_level = 2 }),
  49. structlog.processors.Timestamper "%H:%M:%S",
  50. },
  51. formatter = structlog.formatters.Format( --
  52. "%s [%-5s] %s: %-30s",
  53. { "timestamp", "level", "logger_name", "msg" }
  54. ),
  55. }),
  56. },
  57. },
  58. }
  59. if is_notify_available() then
  60. table.insert(
  61. lvim_log.lvim.sinks,
  62. structlog.sinks.NvimNotify(Log.levels.INFO, {
  63. processors = {
  64. notify_handler.default_namer,
  65. notify_handler.params_injecter,
  66. },
  67. formatter = structlog.formatters.Format( --
  68. "%s",
  69. { "msg" },
  70. { blacklist_all = true }
  71. ),
  72. params_map = {
  73. icon = "icon",
  74. keep = "keep",
  75. on_open = "on_open",
  76. on_close = "on_close",
  77. timeout = "timeout",
  78. title = "title",
  79. },
  80. })
  81. )
  82. end
  83. structlog.configure(lvim_log)
  84. local logger = structlog.get_logger "lvim"
  85. if lvim.log.override_notify then
  86. logger:log(Log.levels.INFO, "Ignoring request to override vim.notify with structlog due to instabilities")
  87. end
  88. return logger
  89. end
  90. --- Adds a log entry using Plenary.log
  91. ---@fparam msg any
  92. ---@param level string [same as vim.log.log_levels]
  93. function Log:add_entry(level, msg, event)
  94. if self.__handle then
  95. self.__handle:log(level, vim.inspect(msg), event)
  96. return
  97. end
  98. local logger = self:init()
  99. if not logger then
  100. return
  101. end
  102. self.__handle = logger
  103. self.__handle:log(level, vim.inspect(msg), event)
  104. end
  105. ---Retrieves the path of the logfile
  106. ---@return string path of the logfile
  107. function Log:get_path()
  108. return logfile
  109. end
  110. ---Add a log entry at TRACE level
  111. ---@param msg any
  112. ---@param event any
  113. function Log:trace(msg, event)
  114. self:add_entry(self.levels.TRACE, msg, event)
  115. end
  116. ---Add a log entry at DEBUG level
  117. ---@param msg any
  118. ---@param event any
  119. function Log:debug(msg, event)
  120. self:add_entry(self.levels.DEBUG, msg, event)
  121. end
  122. ---Add a log entry at INFO level
  123. ---@param msg any
  124. ---@param event any
  125. function Log:info(msg, event)
  126. self:add_entry(self.levels.INFO, msg, event)
  127. end
  128. ---Add a log entry at WARN level
  129. ---@param msg any
  130. ---@param event any
  131. function Log:warn(msg, event)
  132. self:add_entry(self.levels.WARN, msg, event)
  133. end
  134. ---Add a log entry at ERROR level
  135. ---@param msg any
  136. ---@param event any
  137. function Log:error(msg, event)
  138. self:add_entry(self.levels.ERROR, msg, event)
  139. end
  140. setmetatable({}, Log)
  141. return Log