Mercurial > prosody-modules
diff mod_sentry/mod_sentry.lua @ 4283:2ae71126e379
mod_sentry: New module to forward errors to a Sentry server
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Tue, 08 Dec 2020 15:34:53 +0000 |
parents | |
children | 2c73544e33ea |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_sentry/mod_sentry.lua Tue Dec 08 15:34:53 2020 +0000 @@ -0,0 +1,80 @@ +module:set_global(); + +local sentry_lib = module:require "sentry"; + +local hostname; +local have_pposix, pposix = pcall(require, "util.pposix"); +if have_pposix and pposix.uname then + hostname = pposix.uname().nodename; +end + +local loggingmanager = require "core.loggingmanager"; +local format = require "util.format".format; + +local default_config = assert(module:get_option("sentry"), "Please provide a 'sentry' configuration option"); +default_config.server_name = default_config.server_name or hostname or "prosody"; + +local sentry = assert(sentry_lib.new(default_config)); + +local log_filters = { + source = function (filter_source, name) + local source = name:match(":(.+)$") or name; + if filter_source == source then + return true; + end + end; + message_pattern = function (pattern, _, _, message) + return not not message:match(pattern); + end; +}; + +local function sentry_error_handler(e) + module:log("error", "Failed to submit event to sentry: %s", e); +end + +local function sentry_log_sink_maker(sink_config) + local filters = sink_config.ignore or {}; + local n_filters = #filters; + + local submitting; + return function (name, level, message, ...) + -- Ignore any log messages that occur during sentry submission + -- to avoid loops + if submitting then return; end + for i = 1, n_filters do + local filter = filters[i]; + local matched; + for filter_name, filter_value in pairs(filter) do + local f = log_filters[filter_name]; + if f and f(filter_value, name, level, message) then + matched = true; + else + matched = nil; + break; + end + end + if matched then + return; + end + end + if level == "warn" then + level = "warning"; + end + + submitting = true; + sentry:event(level, name):message(format(message, ...)):send():catch(sentry_error_handler); + submitting = false; + end; +end + +loggingmanager.register_sink_type("sentry", sentry_log_sink_maker); + +function new(conf) --luacheck: ignore 131/new + conf = conf or {}; + for k, v in pairs(default_config) do + if conf[k] == nil then + conf[k] = v; + end + end + return sentry_lib.new(conf); +end