-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #556 from AndyTWF/send-exception-info-to-api
feat: log fatal exceptions to the api
- Loading branch information
Showing
12 changed files
with
260 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#include "ApiLogger.h" | ||
#include "api/ApiRequestFactory.h" | ||
#include "api/ApiRequestException.h" | ||
#include "update/PluginVersion.h" | ||
|
||
namespace UKControllerPluginUtils::Log { | ||
|
||
struct ApiLogger::Impl | ||
{ | ||
[[nodiscard]] auto CreatePayloadNoMetadata(const std::string& type, const std::string& message) const | ||
-> nlohmann::json | ||
{ | ||
return {{"type", type}, {"message", message}, {"metadata", PluginVersionMetadata().dump()}}; | ||
} | ||
|
||
[[nodiscard]] auto | ||
CreatePayload(const std::string& type, const std::string& message, const nlohmann::json& metadata) const | ||
-> nlohmann::json | ||
{ | ||
auto metadataWithVersion = PluginVersionMetadata(); | ||
metadataWithVersion.update(metadata); | ||
return {{"type", type}, {"message", message}, {"metadata", metadataWithVersion.dump()}}; | ||
} | ||
|
||
[[nodiscard]] auto PluginVersionMetadata() const -> nlohmann::json | ||
{ | ||
return {{"plugin_version", UKControllerPlugin::Plugin::PluginVersion::version}}; | ||
} | ||
|
||
void WriteLog(const nlohmann::json& data) | ||
{ | ||
ApiRequest() | ||
.Post("plugin/logs", data) | ||
.Then([](const UKControllerPluginUtils::Api::Response& response) { | ||
const auto data = response.Data(); | ||
if (!data.is_object() || !data.contains("id") || !data["id"].is_string()) { | ||
LogError("Failed to send log to API, response was not as expected"); | ||
return; | ||
} | ||
|
||
LogInfo("Log sent to API with ID " + data["id"].get<std::string>()); | ||
}) | ||
.Catch([](const Api::ApiRequestException& exception) { | ||
LogError( | ||
"Failed to send log to API, status code was " + | ||
std::to_string(static_cast<uint64_t>(exception.StatusCode()))); | ||
}) | ||
.Await(); | ||
} | ||
|
||
void WriteLogAsync(const nlohmann::json& data) | ||
{ | ||
ApiRequest().Post("plugin/logs", data).Catch([](const Api::ApiRequestException& exception) { | ||
LogError( | ||
"Failed to send log to API, status code was " + | ||
std::to_string(static_cast<uint64_t>(exception.StatusCode()))); | ||
}); | ||
} | ||
}; | ||
|
||
ApiLogger::ApiLogger() : impl(std::make_unique<Impl>()) | ||
{ | ||
} | ||
|
||
ApiLogger::~ApiLogger() = default; | ||
|
||
void ApiLogger::Log(const std::string& type, const std::string& message) const | ||
{ | ||
impl->WriteLog(impl->CreatePayloadNoMetadata(type, message)); | ||
} | ||
|
||
void ApiLogger::Log(const std::string& type, const std::string& message, const nlohmann::json& metadata) const | ||
{ | ||
impl->WriteLog(impl->CreatePayload(type, message, metadata)); | ||
} | ||
|
||
void ApiLogger::LogAsync(const std::string& type, const std::string& message) const | ||
{ | ||
impl->WriteLogAsync(impl->CreatePayloadNoMetadata(type, message)); | ||
} | ||
|
||
void ApiLogger::LogAsync(const std::string& type, const std::string& message, const nlohmann::json& metadata) const | ||
{ | ||
impl->WriteLogAsync(impl->CreatePayload(type, message, metadata)); | ||
} | ||
} // namespace UKControllerPluginUtils::Log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#pragma once | ||
#include "ApiLoggerInterface.h" | ||
|
||
namespace UKControllerPluginUtils::Log { | ||
class ApiLogger : public ApiLoggerInterface | ||
{ | ||
public: | ||
ApiLogger(); | ||
~ApiLogger() override; | ||
void Log(const std::string& type, const std::string& message) const override; | ||
void Log(const std::string& type, const std::string& message, const nlohmann::json& metadata) const override; | ||
void LogAsync(const std::string& type, const std::string& message) const override; | ||
void | ||
LogAsync(const std::string& type, const std::string& message, const nlohmann::json& metadata) const override; | ||
|
||
private: | ||
struct Impl; | ||
std::unique_ptr<Impl> impl; | ||
}; | ||
} // namespace UKControllerPluginUtils::Log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
namespace UKControllerPluginUtils::Log { | ||
/** | ||
* An interface for logging things to the API where we need more information | ||
* or just want to know what's going on. | ||
*/ | ||
class ApiLoggerInterface | ||
{ | ||
public: | ||
virtual ~ApiLoggerInterface() = default; | ||
virtual void Log(const std::string& type, const std::string& message) const = 0; | ||
virtual void Log(const std::string& type, const std::string& message, const nlohmann::json& metadata) const = 0; | ||
virtual void LogAsync(const std::string& type, const std::string& message) const = 0; | ||
virtual void | ||
LogAsync(const std::string& type, const std::string& message, const nlohmann::json& metadata) const = 0; | ||
}; | ||
} // namespace UKControllerPluginUtils::Log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#include "log/ApiLogger.h" | ||
#include "test/ApiTestCase.h" | ||
#include "update/PluginVersion.h" | ||
|
||
namespace UKControllerPluginUtilsTest::Api { | ||
class ApiLoggerTest : public UKControllerPluginTest::ApiTestCase | ||
{ | ||
public: | ||
ApiLoggerTest() : ApiTestCase() | ||
{ | ||
} | ||
|
||
const nlohmann::json expectedPluginVersionMetadata = { | ||
{"plugin_version", UKControllerPlugin::Plugin::PluginVersion::version}}; | ||
|
||
UKControllerPluginUtils::Log::ApiLogger logger; | ||
}; | ||
|
||
TEST_F(ApiLoggerTest, ItLogsSync) | ||
{ | ||
const nlohmann::json expectedPayload = { | ||
{"type", "type"}, {"message", "message"}, {"metadata", expectedPluginVersionMetadata.dump()}}; | ||
|
||
this->ExpectApiRequest()->Post().To("plugin/logs").WithBody(expectedPayload).WillReturnCreated(); | ||
logger.Log("type", "message"); | ||
} | ||
|
||
TEST_F(ApiLoggerTest, ItLogsSyncWithMetadata) | ||
{ | ||
nlohmann::json metadata = {{"key", "value"}}; | ||
metadata.update(expectedPluginVersionMetadata); | ||
const nlohmann::json expectedPayload = { | ||
{"type", "type"}, {"message", "message"}, {"metadata", metadata.dump()}}; | ||
|
||
this->ExpectApiRequest()->Post().To("plugin/logs").WithBody(expectedPayload).WillReturnCreated(); | ||
logger.Log("type", "message", metadata); | ||
} | ||
|
||
TEST_F(ApiLoggerTest, ItLogsAsync) | ||
{ | ||
const nlohmann::json expectedPayload = { | ||
{"type", "type"}, {"message", "message"}, {"metadata", expectedPluginVersionMetadata.dump()}}; | ||
|
||
this->ExpectApiRequest()->Post().To("plugin/logs").WithBody(expectedPayload).WillReturnCreated(); | ||
logger.LogAsync("type", "message"); | ||
} | ||
|
||
TEST_F(ApiLoggerTest, ItLogsAsyncWithMetadata) | ||
{ | ||
nlohmann::json metadata = {{"key", "value"}}; | ||
metadata.update(expectedPluginVersionMetadata); | ||
const nlohmann::json expectedPayload = { | ||
{"type", "type"}, {"message", "message"}, {"metadata", metadata.dump()}}; | ||
|
||
this->ExpectApiRequest()->Post().To("plugin/logs").WithBody(expectedPayload).WillReturnCreated(); | ||
logger.LogAsync("type", "message", metadata); | ||
} | ||
} // namespace UKControllerPluginUtilsTest::Api |