mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
Sentry: implement basic exception reporting, error breadcrumbs
This commit is contained in:
parent
550c658ac5
commit
2b4fec6d11
@ -1,6 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
project(Server)
|
project(Server)
|
||||||
|
|
||||||
|
add_subdirectory("include/sentry-native")
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
|
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
|
||||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||||
@ -19,13 +21,18 @@ elseif (UNIX)
|
|||||||
endif (SANITIZE)
|
endif (SANITIZE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# this is set by the build system.
|
||||||
|
# if you're building from source, just leave this empty
|
||||||
|
if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL)
|
||||||
|
set(BEAMMP_SECRET_SENTRY_URL "")
|
||||||
|
endif()
|
||||||
|
|
||||||
# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG
|
# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG
|
||||||
include_directories("asio/asio/include")
|
include_directories("asio/asio/include")
|
||||||
include_directories("rapidjson/include")
|
include_directories("rapidjson/include")
|
||||||
include_directories("websocketpp")
|
include_directories("websocketpp")
|
||||||
add_subdirectory("socket.io-client-cpp")
|
add_subdirectory("socket.io-client-cpp")
|
||||||
add_subdirectory("include/commandline")
|
add_subdirectory("include/commandline")
|
||||||
add_subdirectory("include/sentry-native")
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
@ -59,8 +66,10 @@ target_include_directories(BeamMP-Server PUBLIC ${Boost_INCLUDE_DIRS} ${LUA_INCL
|
|||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
|
add_definitions(-DSECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}")
|
||||||
target_link_libraries(BeamMP-Server z pthread stdc++fs ${LUA_LIBRARIES} crypto ${OPENSSL_LIBRARIES} commandline sioclient_tls sentry)
|
target_link_libraries(BeamMP-Server z pthread stdc++fs ${LUA_LIBRARIES} crypto ${OPENSSL_LIBRARIES} commandline sioclient_tls sentry)
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
|
add_definitions(/DSECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}")
|
||||||
include(FindLua)
|
include(FindLua)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
find_package(RapidJSON CONFIG REQUIRED)
|
find_package(RapidJSON CONFIG REQUIRED)
|
||||||
|
@ -79,6 +79,9 @@ void RegisterThread(const std::string str);
|
|||||||
#define _line std::to_string(__LINE__)
|
#define _line std::to_string(__LINE__)
|
||||||
#define _in_lambda (std::string(__func__) == "operator()")
|
#define _in_lambda (std::string(__func__) == "operator()")
|
||||||
|
|
||||||
|
#include "Sentry.h"
|
||||||
|
extern TSentry Sentry;
|
||||||
|
|
||||||
// we would like the full function signature 'void a::foo() const'
|
// we would like the full function signature 'void a::foo() const'
|
||||||
// on windows this is __FUNCSIG__, on GCC it's __PRETTY_FUNCTION__,
|
// on windows this is __FUNCSIG__, on GCC it's __PRETTY_FUNCTION__,
|
||||||
// feel free to add more
|
// feel free to add more
|
||||||
@ -108,7 +111,7 @@ void RegisterThread(const std::string str);
|
|||||||
|
|
||||||
#define warn(x) Application::Console().Write(_this_location + std::string("[WARN] ") + (x))
|
#define warn(x) Application::Console().Write(_this_location + std::string("[WARN] ") + (x))
|
||||||
#define info(x) Application::Console().Write(_this_location + std::string("[INFO] ") + (x))
|
#define info(x) Application::Console().Write(_this_location + std::string("[INFO] ") + (x))
|
||||||
#define error(x) Application::Console().Write(_this_location + std::string("[ERROR] ") + (x))
|
#define error(x) do { Application::Console().Write(_this_location + std::string("[ERROR] ") + (x)); Sentry.AddErrorBreadcrumb((x), _file_basename, _line); } while (false)
|
||||||
#define luaprint(x) Application::Console().Write(_this_location + std::string("[LUA] ") + (x))
|
#define luaprint(x) Application::Console().Write(_this_location + std::string("[LUA] ") + (x))
|
||||||
#define debug(x) \
|
#define debug(x) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -1,14 +1,25 @@
|
|||||||
#ifndef SENTRY_H
|
#ifndef SENTRY_H
|
||||||
#define SENTRY_H
|
#define SENTRY_H
|
||||||
|
|
||||||
|
#include <sentry.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
enum class Logger {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// singleton, dont make this twice
|
// singleton, dont make this twice
|
||||||
class Sentry final {
|
class TSentry final {
|
||||||
public:
|
public:
|
||||||
Sentry(const std::string& SentryUrl);
|
TSentry(const std::string& SentryUrl);
|
||||||
~Sentry();
|
~TSentry();
|
||||||
|
|
||||||
|
void Log(sentry_level_t level, const std::string& logger, const std::string& text);
|
||||||
|
void LogException(const std::exception& e, const std::string& file, const std::string& line);
|
||||||
|
void AddErrorBreadcrumb(const std::string& msg, const std::string& file, const std::string& line);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool mValid { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SENTRY_H
|
#endif // SENTRY_H
|
||||||
|
@ -1,16 +1,35 @@
|
|||||||
#include "Sentry.h"
|
#include "Sentry.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#include "sentry.h"
|
TSentry::TSentry(const std::string& SentryUrl) {
|
||||||
|
if (SentryUrl.empty()) {
|
||||||
Sentry::Sentry(const std::string& SentryUrl) {
|
mValid = false;
|
||||||
|
} else {
|
||||||
|
mValid = true;
|
||||||
sentry_options_t* options = sentry_options_new();
|
sentry_options_t* options = sentry_options_new();
|
||||||
sentry_options_set_dsn(options, SentryUrl.c_str());
|
sentry_options_set_dsn(options, SentryUrl.c_str());
|
||||||
auto ReleaseString = "BeamMP-Server@" + Application::ServerVersion();
|
auto ReleaseString = "BeamMP-Server@" + Application::ServerVersion();
|
||||||
sentry_options_set_release(options, ReleaseString.c_str());
|
sentry_options_set_release(options, ReleaseString.c_str());
|
||||||
sentry_init(options);
|
sentry_init(options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sentry::~Sentry() {
|
TSentry::~TSentry() {
|
||||||
|
if (mValid) {
|
||||||
sentry_close();
|
sentry_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSentry::Log(sentry_level_t level, const std::string& logger, const std::string& text) {
|
||||||
|
sentry_capture_event(sentry_value_new_message_event(level, logger.c_str(), text.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSentry::LogException(const std::exception& e, const std::string& file, const std::string& line) {
|
||||||
|
Log(SENTRY_LEVEL_ERROR, "exceptions", std::string(e.what()) + " @ " + file + ":" + line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSentry::AddErrorBreadcrumb(const std::string& msg, const std::string& file, const std::string& line) {
|
||||||
|
auto crumb = sentry_value_new_breadcrumb("default", (msg + " @ " + file + ":" + line).c_str());
|
||||||
|
sentry_value_set_by_key(crumb, "level", sentry_value_new_string("error"));
|
||||||
|
sentry_add_breadcrumb(crumb);
|
||||||
}
|
}
|
||||||
|
26
src/main.cpp
26
src/main.cpp
@ -35,7 +35,11 @@ void UnixSignalHandler(int sig) {
|
|||||||
}
|
}
|
||||||
#endif // __unix
|
#endif // __unix
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
// this is provided by the build system, leave empty for source builds
|
||||||
|
// global, yes, this is ugly, no, it cant be done another way
|
||||||
|
TSentry Sentry { SECRET_SENTRY_URL };
|
||||||
|
|
||||||
|
int main(int argc, char** argv) try {
|
||||||
#ifdef __unix
|
#ifdef __unix
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
info("registering handlers for SIGINT, SIGTERM, SIGPIPE");
|
info("registering handlers for SIGINT, SIGTERM, SIGPIPE");
|
||||||
@ -46,27 +50,12 @@ int main(int argc, char** argv) {
|
|||||||
signal(SIGINT, UnixSignalHandler);
|
signal(SIGINT, UnixSignalHandler);
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
#endif // __unix
|
#endif // __unix
|
||||||
|
|
||||||
// FIXME: this is not prod ready, needs to be compile-time value
|
|
||||||
char* sentry_url = getenv("SENTRY_URL");
|
|
||||||
if (!sentry_url) {
|
|
||||||
error("no sentry url supplied in environment, this is not a fatal error");
|
|
||||||
} else {
|
|
||||||
info("sentry url has length " + std::to_string(std::string(sentry_url).size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Sentry sentry(sentry_url);
|
|
||||||
|
|
||||||
sentry_capture_event(sentry_value_new_message_event(
|
|
||||||
/* level */ SENTRY_LEVEL_INFO,
|
|
||||||
/* logger */ "custom",
|
|
||||||
/* message */ "It works!"));
|
|
||||||
|
|
||||||
setlocale(LC_ALL, "C");
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
bool Shutdown = false;
|
bool Shutdown = false;
|
||||||
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
||||||
|
|
||||||
|
|
||||||
TServer Server(argc, argv);
|
TServer Server(argc, argv);
|
||||||
TConfig Config;
|
TConfig Config;
|
||||||
|
|
||||||
@ -89,4 +78,7 @@ int main(int argc, char** argv) {
|
|||||||
while (!Shutdown) {
|
while (!Shutdown) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
error(e.what());
|
||||||
|
Sentry.LogException(e, _file_basename, _line);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user