Skip to content

Commit

Permalink
CURA-11364 Add Sentry Support (#1985)
Browse files Browse the repository at this point in the history
  • Loading branch information
jellespijker authored Dec 5, 2023
2 parents 9d65925 + 686df6a commit faece8f
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 5 deletions.
15 changes: 13 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ option(ENABLE_BENCHMARKS "Build with Benchmarks" OFF)
option(EXTENSIVE_WARNINGS "Build with all warnings" ON)
option(ENABLE_PLUGINS "Build with plugins" ON)
option(ENABLE_REMOTE_PLUGINS "Build with all warnings" OFF)
option(ENABLE_SENTRY "Send crash data via Sentry" OFF)
option(ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS "Enable more optimization flags" ON)
option(USE_SYSTEM_LIBS "Use the system libraries if available" OFF)
option(OLDER_APPLE_CLANG "Apple Clang <= 13 used" OFF)
Expand Down Expand Up @@ -201,6 +202,10 @@ find_package(range-v3 REQUIRED)
find_package(scripta REQUIRED)
find_package(semver REQUIRED)

if (ENABLE_SENTRY)
find_package(sentry REQUIRED)
endif ()

if (ENABLE_TESTING)
find_package(GTest REQUIRED)
endif ()
Expand Down Expand Up @@ -238,8 +243,14 @@ else ()
endif (NOT WIN32)

use_threads(CuraEngine)
target_link_libraries(CuraEngine PRIVATE _CuraEngine)
target_compile_definitions(CuraEngine PRIVATE VERSION=\"${CURA_ENGINE_VERSION}\")
target_link_libraries(CuraEngine PRIVATE
_CuraEngine
$<$<BOOL:${ENABLE_SENTRY}>:sentry::sentry>
)
target_compile_definitions(CuraEngine PRIVATE
$<$<BOOL:${ENABLE_SENTRY}>:SENTRY_URL=\"${SENTRY_URL}\">
VERSION=\"${CURA_ENGINE_VERSION}\"
)

# Compiling the test environment.
if (ENABLE_TESTING OR ENABLE_BENCHMARKS)
Expand Down
15 changes: 13 additions & 2 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from conan.tools.files import copy, mkdir
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake, cmake_layout
from conan.tools.build import check_min_cppstd
from conan.tools.scm import Version
from conan.tools.scm import Version, Git


required_conan_version = ">=1.58.0 <2.0.0"

Expand All @@ -28,19 +29,22 @@ class CuraEngineConan(ConanFile):
"enable_benchmarks": [True, False],
"enable_extensive_warnings": [True, False],
"enable_plugins": [True, False],
"enable_sentry": [True, False],
"enable_remote_plugins": [True, False],
}
default_options = {
"enable_arcus": True,
"enable_benchmarks": False,
"enable_extensive_warnings": False,
"enable_plugins": True,
"enable_sentry": False,
"enable_remote_plugins": False,
}

def set_version(self):
if not self.version:
self.version = "5.7.0-alpha"
git = Git(self)
self.version = f"5.7.0-alpha+{git.get_commit()[:6]}"

def export_sources(self):
copy(self, "CMakeLists.txt", self.recipe_folder, self.export_sources_folder)
Expand All @@ -57,6 +61,8 @@ def export_sources(self):
def config_options(self):
if not self.options.enable_plugins:
del self.options.enable_remote_plugins
if self.conf.get("user.curaengine:sentry_url", "", check_type=str) == "":
del self.options.enable_sentry

def configure(self):
self.options["boost"].header_only = True
Expand Down Expand Up @@ -85,6 +91,8 @@ def build_requirements(self):
def requirements(self):
if self.options.enable_arcus:
self.requires("arcus/5.3.0")
if self.options.get_safe("enable_sentry", False):
self.requires("sentry-native/0.6.5")
self.requires("asio-grpc/2.6.0")
self.requires("grpc/1.50.1")
self.requires("curaengine_grpc_definitions/(latest)@ultimaker/testing")
Expand Down Expand Up @@ -112,6 +120,9 @@ def generate(self):
tc.variables["ENABLE_BENCHMARKS"] = self.options.enable_benchmarks
tc.variables["EXTENSIVE_WARNINGS"] = self.options.enable_extensive_warnings
tc.variables["OLDER_APPLE_CLANG"] = self.settings.compiler == "apple-clang" and Version(self.settings.compiler.version) < "14"
if self.options.get_safe("enable_sentry", False):
tc.variables["ENABLE_SENTRY"] = True
tc.variables["SENTRY_URL"] = self.conf.get("user.curaengine:sentry_url", "", check_type=str)
if self.options.enable_plugins:
tc.variables["ENABLE_PLUGINS"] = True
tc.variables["ENABLE_REMOTE_PLUGINS"] = self.options.enable_remote_plugins
Expand Down
47 changes: 47 additions & 0 deletions include/utils/format/filesystem_path.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2023 UltiMaker
// CuraEngine is released under the terms of the AGPLv3 or higher

#ifndef CURAENGINE_INCLUDE_UTILS_FORMAT_FILESYSTEM_PATH_H
#define CURAENGINE_INCLUDE_UTILS_FORMAT_FILESYSTEM_PATH_H

#include <cstdlib>
#include <filesystem>

#include <fmt/core.h>

namespace fmt
{
template<>
struct formatter<std::filesystem::path> : formatter<string_view>
{
static std::string USERNAME;
static constexpr std::string_view OBFUSCATED_STRING = "*******";

[[nodiscard]] static std::string anonymizePath(const std::string& path)
{
std::string anonymized_path = path;
size_t pos = anonymized_path.find(USERNAME);
while (pos != std::string::npos)
{
anonymized_path.replace(pos, USERNAME.size(), OBFUSCATED_STRING);
pos = anonymized_path.find(USERNAME, pos + OBFUSCATED_STRING.size());
}
return anonymized_path;
}

template<typename FormatContext>
auto format(const std::filesystem::path& path, FormatContext& ctx)
{
return formatter<string_view>::format(anonymizePath(path.generic_string()), ctx);
}
};

#ifdef _WIN32
std::string fmt::formatter<std::filesystem::path>::USERNAME = std::getenv("USERNAME") != nullptr ? std::getenv("USERNAME") : "";
#else
std::string fmt::formatter<std::filesystem::path>::USERNAME = std::getenv("USER") != nullptr ? std::getenv("USER") : "";
#endif

} // namespace fmt

#endif // CURAENGINE_INCLUDE_UTILS_FORMAT_FILESYSTEM_PATH_H
76 changes: 75 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022 Ultimaker B.V.
// Copyright (c) 2023 UltiMaker
// CuraEngine is released under the terms of the AGPLv3 or higher

#include <iostream> //To change the formatting of std::cerr.
Expand All @@ -7,6 +7,19 @@
#include <sys/resource.h> //For setpriority.
#endif

#ifdef SENTRY_URL
#include <filesystem>
#include <semver.hpp>
#include <sentry.h>
#include <string>

#include <range/v3/algorithm/contains.hpp>
#include <range/v3/range/conversion.hpp>

#include "utils/format/filesystem_path.h"
#endif
#include <cstdlib>

#include <spdlog/spdlog.h>

#include "Application.h"
Expand Down Expand Up @@ -37,7 +50,68 @@ int main(int argc, char** argv)
#endif
std::cerr << std::boolalpha;


// Want to set the sentry URL? Use '-c user.curaengine:sentry_url=<url> -o curaengine:enable_sentry=True' with conan install
#ifdef SENTRY_URL
bool use_sentry = true;
if (const char* use_sentry_env = std::getenv("use_sentry"))
{
if (std::strcmp(use_sentry_env, "0") == 0)
{
use_sentry = false;
}
}
if (use_sentry)
{
// Setup sentry error handling.
sentry_options_t* options = sentry_options_new();
sentry_options_set_dsn(options, std::string(SENTRY_URL).c_str());
spdlog::info("Sentry url: {}", std::string(SENTRY_URL).c_str());
// This is also the default-path. For further information and recommendations:
// https://docs.sentry.io/platforms/native/configuration/options/#database-path
#if defined(__linux__)
const auto config_path = std::filesystem::path(fmt::format("{}/.local/share/cura/.sentry-native", std::getenv("HOME")));
#elif defined(__APPLE__) && defined(__MACH__)
const auto config_path = std::filesystem::path(fmt::format("{}/Library/Application Support/cura/.sentry-native", std::getenv("HOME")));
#elif defined(_WIN64)
const auto config_path = std::filesystem::path(fmt::format("{}\\cura\\.sentry-native", std::getenv("APPDATA")));
#endif
spdlog::info("Sentry config path: {}", config_path);
sentry_options_set_database_path(options, std::filesystem::absolute(config_path).generic_string().c_str());
constexpr std::string_view cura_engine_version{ CURA_ENGINE_VERSION };
const auto version = semver::from_string(cura_engine_version.substr(0, cura_engine_version.find_first_of('+')));
if (ranges::contains(cura_engine_version, '+') || version.prerelease_type == semver::prerelease::alpha)
{
// Not a production build
sentry_options_set_environment(options, "development");
sentry_options_set_release(
options,
fmt::format(
"curaengine@{}.{}.{}-{}.{}",
version.major,
version.minor,
version.patch,
version.prerelease_type == semver::prerelease::alpha ? "alpha" : "beta",
version.prerelease_number)
.c_str());
}
else
{
sentry_options_set_environment(options, "production");
sentry_options_set_release(options, fmt::format("curaengine@{}", version.to_string()).c_str());
}
sentry_init(options);
}
#endif

cura::Application::getInstance().run(argc, argv);

#ifdef SENTRY_URL
if (use_sentry)
{
sentry_close();
}
#endif

return 0;
}

0 comments on commit faece8f

Please sign in to comment.