From 72152d78072357e69abeff6a0bd7ecfc3ed98011 Mon Sep 17 00:00:00 2001 From: Jasper Spaans Date: Tue, 5 Nov 2024 22:42:31 +0100 Subject: [PATCH 1/2] split out a call to resolve open alerts --- notifiers.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/notifiers.cc b/notifiers.cc index 83e9411..4e7b259 100644 --- a/notifiers.cc +++ b/notifiers.cc @@ -226,15 +226,19 @@ void Notifier::bulkDone() // fmt::print("There are {} results that used to be old enough & are gone now\n", // diff.size()); for(const auto& str : diff) { - string desc = getAgeDesc(deltime[str]); - this->alert(fmt::format("🎉 after {}, the following alert is over: {}", - desc, - str)); + this->resolve(str, deltime[str]); } d_prevOldEnough = d_oldEnough; } +void Notifier::resolve(const std::string& message, const time_t ts) +{ + string desc = getAgeDesc(ts); + this->alert(fmt::format("🎉 after {}, the following alert is over: {}", + message, + desc)); +} TelegramNotifier::TelegramNotifier(sol::table data) : Notifier(data) { From a4440700922947269bf66465dd132a2493092d66 Mon Sep 17 00:00:00 2001 From: Jasper Spaans Date: Tue, 5 Nov 2024 22:43:13 +0100 Subject: [PATCH 2/2] add a notifier for Opsgenie --- luabridge.cc | 8 +++++++ notifiers.cc | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ notifiers.hh | 12 ++++++++++ 3 files changed, 84 insertions(+) diff --git a/luabridge.cc b/luabridge.cc index 2514f77..94c3b41 100644 --- a/luabridge.cc +++ b/luabridge.cc @@ -193,4 +193,12 @@ void initLua() return make_shared(data); }); + // Opsgenie notifier + g_lua.set_function("addOpsgenieNotifier", [&](sol::table data) { + g_notifiers.emplace_back(make_shared(data)); + return *g_notifiers.rbegin(); + }); + g_lua.set_function("createOpsgenieNotifier", [&](sol::table data) { + return make_shared(data); + }); } diff --git a/notifiers.cc b/notifiers.cc index 4e7b259..2ca8f74 100644 --- a/notifiers.cc +++ b/notifiers.cc @@ -272,3 +272,67 @@ void TelegramNotifier::alert(const std::string& message) // fmt::print("{}\n", res->body); } + +OpsgenieNotifier::OpsgenieNotifier(sol::table data) : Notifier(data) +{ + checkLuaTable(data, {"apikey"}); + d_apikey = data.get("apikey"); +} + +void OpsgenieNotifier::alert(const std::string& message) +{ + httplib::Client cli("https://api.opsgenie.com"); + auto field = "GenieKey " + d_apikey; + httplib::Headers headers = { + {"Authorization", std::move(field)} + }; + nlohmann::json jsonRequest = { + { "message", message }, + }; + std::string path; + path = "/v2/alerts"; + auto response = cli.Post(path, headers, jsonRequest.dump(), "application/json"); + if(!response) { + auto err = response.error(); + throw std::runtime_error(fmt::format("\nCould not send post: {}", httplib::to_string(err))); + } + if(response->status != 202) + throw std::runtime_error(fmt::format("\nUnexpected response from Opsgenie, response = {}\n{}", response->status, response->body)); + auto jsonResponse = nlohmann::json::parse(response->body); + const std::string requestId = jsonResponse["requestId"]; + + // now get the actual alert id + path = "/v2/alerts/requests/" + requestId; + response = cli.Get(path, headers); + + // need to pull the request-id out of here! + if(!response) { + auto err = response.error(); + throw std::runtime_error(fmt::format("\nCould not send post: {}", httplib::to_string(err))); + } + if(response->status != 200) + throw std::runtime_error(fmt::format("\nUnexpected response from Opsgenie, res = {}\n{}", response->status, response->body)); + jsonResponse = nlohmann::json::parse(response->body); + const std::string alertId = jsonResponse["data"]["alertId"]; + d_msg_to_alertid.insert({ message, alertId }); +} + +void OpsgenieNotifier::resolve(const std::string& message, const time_t ts) +{ + auto alertIdIter = d_msg_to_alertid.find(message); + if (alertIdIter == d_msg_to_alertid.end()) { + throw std::runtime_error(fmt::format("\nCould not find alertId for message {} !?", message)); + } + const std::string alertId = alertIdIter->second; + + httplib::Client cli("https://api.opsgenie.com"); + auto field = "GenieKey " + d_apikey; + httplib::Headers headers = { + {"Authorization", std::move(field)} + }; + std::string path; + path = "/v2/alerts/" + alertId + "/close"; + const std::string empty_body("{}"); + // need post an empty json-object to this url, empty string is not accepted + cli.Post(path, headers, "{}", "application/json"); +} diff --git a/notifiers.hh b/notifiers.hh index 911d805..f540c5a 100644 --- a/notifiers.hh +++ b/notifiers.hh @@ -19,6 +19,7 @@ public: } virtual ~Notifier() = default; virtual void alert(const std::string& message) = 0; + virtual void resolve(const std::string& message, const time_t ts); std::string getNotifierName() { return d_notifierName; } void bulkAlert(const std::string& textBody); void bulkDone(); @@ -96,3 +97,14 @@ public: private: std::string d_botid, d_apikey, d_chatid; }; + +class OpsgenieNotifier : public Notifier +{ +public: + OpsgenieNotifier(sol::table data); + void alert(const std::string& message) override; + void resolve(const std::string& message, const time_t ts) override; +private: + std::string d_apikey; + std::unordered_map d_msg_to_alertid; +};