Refactored Sentry configuration to use TOML config

This commit is contained in:
Jamie Kerber
2026-05-16 00:40:49 +02:00
parent 68e42f2bc1
commit 9a60d72ce2
6 changed files with 145 additions and 130 deletions
+38 -22
View File
@@ -566,24 +566,36 @@ For target Yocto builds `CMAKE_INSTALL_PREFIX` defaults to `/usr`
Sentry-native support is available for Crash Handling. This pushes a mini-dump to the cloud for triage and tracking.
To create user account and get DNS See https://sentry.io/welcome/
> To create user account and get a DSN
> see https://sentry.io/welcome/
CMake Variables
### Configuration
1. Specify your DSN via environment variable `SENTRY_DSN`
2. Add the following sections to your `config.toml` file with the following structure:
```toml
[sentry]
release = "homescreen-1.0.0"
env = "production"
attachments = [
"/path/to/crash.log",
"/path/to/config.toml"
]
[sentry.tags]
platform = "linux"
device = "ivi"
```
### CMake Variables
To enable crash handler support:
-DBUILD_CRASH_HANDLER=ON
-DCRASH_HANDLER_DSN="dsn from your account. If not defined, can be set at runtime via environment variable"
-DSENTRY_NATIVE_LIBDIR="directory where sentry native is installed, will look in CMAKE_INSTALL_PREFIX directory if not defined"
-DCRASHPAD_BINARY_DIR="directory where crashpad_handler executable is installed, will look in CMAKE_INSTALL_PREFIX directory if not defined"
-DCRASH_HANDLER_ATTACHMENTS="paths to files you'd like to attach to coredump reports, separated by commas (,)"
-DCRASH_HANDLER_TAGS="tags to accompany Sentry coredump report in the style of "TAG_NAME=tagvalue", multiple tags can be defined separated by commas (,)"
Optional Environment Variables
SENTRY_DSN -- Overrides CMake CRASH_HANDLER_DSN value
SENTRY_HOMESCREEN_ENV -- Homescreen Sentry environment (default: CMAKE_BUILD_TYPE)
SENTRY_HOMESCREEN_RELEASE -- Homescreen Sentry release identifier
SENTRY_HOMESCREEN_TAGS -- Homescreen tags in "key:value,key2:value2" format
SENTRY_ATTACHMENTS -- Additional file attachments to add to Sentry crash reports (Appended to those defined in CRASH_HANDLER_ATTACHMENTS), multiple files can be defined, separated by commas (,)
To resolve crash dump stack trace, debug binaries and symbols need to be uploaded to Sentry via sentry-cli tool: https://docs.sentry.io/cli/installation/
@@ -593,18 +605,22 @@ Required source repo: https://github.com/getsentry/sentry-native
sentry build
git clone https://github.com/getsentry/sentry-native
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_STAGING_PREFIX=`pwd`/out/usr
make install
```bash
git clone https://github.com/getsentry/sentry-native
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_STAGING_PREFIX=`pwd`/out/usr
make install
```
ivi-homescreen build
git clone https://github.com/toyota-connected/ivi-homescreen
mkdir build && cd build
cmake .. -DBUILD_CRASH_HANDLER=ON -DCRASH_HANDLER_DSN="dsn from your account"
make -j
LD_LIBRARY_PATH=<sentry staged sysroot install path>/lib homescreen --b=<your bundle folder> --f
```bash
git clone https://github.com/toyota-connected/ivi-homescreen
mkdir build && cd build
cmake .. -DBUILD_CRASH_HANDLER=ON -DSENTRY_NATIVE_LIBDIR=`pwd`/../sentry-native/build/out/usr/lib -DCRASHPAD_BINARY_DIR=`pwd`/../sentry-native/build/out/usr/bin
make -j
SENTRY_DSN=<your DSN> homescreen --b=<your bundle folder> --f
```
## Yocto recipes
+1 -5
View File
@@ -87,12 +87,8 @@
#cmakedefine01 BUILD_CRASH_HANDLER
#if BUILD_CRASH_HANDLER
static constexpr char kCrashHandlerDsn[] = "@CRASH_HANDLER_DSN@";
static constexpr char kCrashHandlerRelease[] = "@PROJECT_NAME@@@BUILD_VER@_@BUILD_NUMBER@_dev";
static constexpr char kDefaultCrashHandlerRelease[] = "homescreen-dev";
static constexpr char kSentryEnvDefault[] = "@CMAKE_BUILD_TYPE@";
static constexpr char kCrashpadBinaryPath[] = "@CRASHPAD_BINARY_DIR@/crashpad_handler";
static constexpr char kCrashpadAttachments[] = "@CRASH_HANDLER_ATTACHMENTS@";
static constexpr char kCrashpadTags[] = "@CRASH_HANDLER_TAGS@";
#endif
#cmakedefine01 DEBUG_PLATFORM_MESSAGES
+3 -7
View File
@@ -224,13 +224,9 @@ if (BUILD_CRASH_HANDLER)
set(CRASHPAD_BINARY_DIR ${CMAKE_INSTALL_PREFIX}/bin)
else ()
message(FATAL_ERROR "System crashpad_handler not found at ${CMAKE_INSTALL_PREFIX}, please set CRASHPAD_BINARY_DIR")
endif ()
endif ()
if (NOT CRASH_HANDLER_DSN)
message(STATUS "Sentry DSN not set, use environment variable SENTRY_DSN to direct coredumps")
endif ()
endif()
endif()
find_package(sentry REQUIRED)
find_package(PkgConfig)
pkg_check_modules(UNWIND REQUIRED IMPORTED_TARGET libunwind)
+77 -80
View File
@@ -3,9 +3,12 @@
#include "utils.h"
#include <config/common.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#define TOML_EXCEPTIONS 0
#include <tomlplusplus/toml.hpp>
#include "sentry.h"
@@ -15,105 +18,99 @@ void CrashHandler::trigger_crash() {
memset(invalid_mem, 1, 100);
}
const char* CrashHandler::get_dsn() {
const auto dsn_env = getenv("SENTRY_DSN");
const char* dsn;
CrashHandler::SentryConfig CrashHandler::LoadConfig(
const std::string& bundle_path) {
SentryConfig config;
if (dsn_env && *dsn_env) {
dsn = dsn_env;
} else {
dsn = kCrashHandlerDsn;
// Defaults
config.release = "";
config.env = kSentryEnvDefault;
// DSN from environment variable
const char* dsn_env = std::getenv("SENTRY_DSN");
config.dsn = dsn_env ? dsn_env : "";
std::filesystem::path toml_path;
if (bundle_path.empty()) {
spdlog::warn("Bundle path is empty, using defaults");
return config;
}
return dsn;
}
toml_path = bundle_path;
toml_path /= kViewConfigToml;
void CrashHandler::set_sentry_attachments(sentry_options_t* options) {
const auto attachment_env = getenv("SENTRY_ATTACHMENTS");
std::string attachments(kCrashpadAttachments);
if (attachment_env && *attachment_env) {
attachments.append(",");
attachments.append(attachment_env);
if (!std::filesystem::exists(toml_path)) {
spdlog::warn("Global config file not found at {}, using defaults",
toml_path.string());
return config;
}
std::stringstream ss(attachments);
std::string attachment;
while (getline(ss, attachment, ',')) {
std::filesystem::path attachment_path(attachment);
if (exists(attachment_path)) {
sentry_options_add_attachment(options, attachment_path.c_str());
// Parse TOML file
auto result = toml::parse_file(toml_path.string());
if (!result) {
spdlog::error("TOML parsing failed: {}", toml_path.string());
return config;
}
auto& tbl = result.table();
// Extract [sentry] section
if (auto* sentry_section = tbl.get("sentry")) {
if (auto* release = sentry_section->as_table()->get("release"))
config.release = release->value_or("");
if (auto* env = sentry_section->as_table()->get("env"))
config.env = env->value_or(kSentryEnvDefault);
// Extract [sentry.tags] subsection
if (auto* tags_node = sentry_section->as_table()->get("tags")) {
if (auto* tags_tbl = tags_node->as_table()) {
for (auto& [key, val] : *tags_tbl) {
if (auto str_val = val.value<std::string>())
config.tags[std::string(key)] = *str_val;
}
}
}
// Extract [sentry] attachments array
if (auto* arr_node = sentry_section->as_table()->get("attachments")) {
if (auto* arr = arr_node->as_array()) {
for (auto& val : *arr) {
if (auto str_val = val.value<std::string>())
config.attachments.push_back(*str_val);
}
}
}
}
return config;
}
void CrashHandler::set_sentry_tags() {
const auto tags_env = getenv("SENTRY_TAGS");
std::string tags(kCrashpadTags);
CrashHandler::CrashHandler(const std::string& bundle_path) {
config_ = LoadConfig(bundle_path);
if (tags_env && *tags_env) {
tags.append(",");
tags.append(tags_env);
}
std::stringstream ss(tags);
std::string tag;
while (getline(ss, tag, ',')) {
size_t del = tag.find("=", 0);
std::string tag_name = tag.substr(0, del);
size_t tag_val_size = tag.size() - tag_name.size() - 1;
std::string tag_val = tag.substr(del + 1, tag_val_size);
sentry_set_tag(tag_name.c_str(), tag_val.c_str());
}
}
const char* CrashHandler::get_sentry_env() {
const auto env = getenv("SENTRY_HOMESCREEN_ENV");
if (env && *env)
return env;
#if defined(CMAKE_BUILD_TYPE)
return CMAKE_BUILD_TYPE;
#else
return "development";
#endif
}
const char* CrashHandler::get_sentry_release() {
const auto release = getenv("SENTRY_HOMESCREEN_RELEASE");
if (release && *release)
return release;
return kCrashHandlerRelease;
}
CrashHandler::CrashHandler() {
sentry_options_t* options = sentry_options_new();
sentry_options_set_dsn(options, get_dsn());
sentry_options_set_dsn(options, config_.dsn.c_str());
auto home_path = Utils::GetConfigHomePath();
std::filesystem::path db_path = home_path;
db_path /= ".sentry";
sentry_options_set_handler_path(options, kCrashpadBinaryPath);
sentry_options_set_database_path(options, db_path.c_str());
// Use SENTRY_HOMESCREEN_RELEASE only
sentry_options_set_release(options, get_sentry_release());
sentry_options_set_release(options, config_.release.c_str());
sentry_options_set_environment(options, config_.env.c_str());
// Use SENTRY_HOMESCREEN_ENV only
sentry_options_set_environment(options, get_sentry_env());
// Use SENTRY_HOMESCREEN_TAGS only
const auto homescreen_tags_env = getenv("SENTRY_HOMESCREEN_TAGS");
if (homescreen_tags_env && *homescreen_tags_env) {
std::stringstream ss(homescreen_tags_env);
std::string tag;
while (getline(ss, tag, ',')) {
size_t del = tag.find("=", 0);
if (del != std::string::npos) {
std::string tag_name = tag.substr(0, del);
std::string tag_val = tag.substr(del + 1);
sentry_set_tag(tag_name.c_str(), tag_val.c_str());
}
}
// Apply tags
for (auto& [tag_name, tag_val] : config_.tags) {
sentry_set_tag(tag_name.c_str(), tag_val.c_str());
}
set_sentry_attachments(options);
// Apply attachments
for (auto& attachment : config_.attachments) {
std::filesystem::path attachment_path(attachment);
if (exists(attachment_path)) {
sentry_options_add_attachment(options, attachment_path.c_str());
}
}
sentry_options_set_symbolize_stacktraces(options, true);
sentry_options_set_debug(options, 0);
+16 -8
View File
@@ -1,23 +1,31 @@
#pragma once
#include <map>
#include <string>
#include <vector>
#include "sentry.h"
class CrashHandler {
public:
CrashHandler();
explicit CrashHandler(const std::string& bundle_path);
~CrashHandler();
static void trigger_crash();
static const char* get_dsn();
static void set_sentry_attachments(sentry_options_t* options);
static void set_sentry_tags();
// Homescreen-specific helpers
static const char* get_sentry_env();
static const char* get_sentry_release();
CrashHandler(const CrashHandler&) = delete;
CrashHandler& operator=(const CrashHandler&) = delete;
private:
struct SentryConfig {
std::string dsn;
std::string release;
std::string env;
std::map<std::string, std::string> tags;
std::vector<std::string> attachments;
};
static SentryConfig LoadConfig(const std::string& bundle_path);
SentryConfig config_;
};
+10 -8
View File
@@ -86,12 +86,19 @@ void InstallShutdownHandlers() {
* wayland, flutter
*/
int main(const int argc, char** argv) {
gLogger = std::make_unique<Logging>();
const auto configs = Configuration::ParseArgcArgv(argc, argv);
assert(!configs.empty());
#if BUILD_CRASH_HANDLER
auto crash_handler = std::make_unique<CrashHandler>();
std::string first_bundle_path;
if (!configs.empty()) {
first_bundle_path = configs.front().view.bundle_path;
}
auto crash_handler = std::make_unique<CrashHandler>(first_bundle_path);
#endif
#if BUILD_BACKEND_DRM_KMS_EGL || BUILD_BACKEND_DRM_KMS_VULKAN || \
BUILD_BACKEND_SOFTWARE
#if BUILD_BACKEND_DRM_KMS_EGL || BUILD_BACKEND_SOFTWARE
// Handle --drm-list-modes[=<path>] before the main config parse so the
// user doesn't need to supply a bundle path just to inspect modes. On
// software builds this lists the DRM dumb-sink's modes (the values valid
@@ -146,11 +153,6 @@ int main(const int argc, char** argv) {
}
#endif
gLogger = std::make_unique<Logging>();
const auto configs = Configuration::ParseArgcArgv(argc, argv);
assert(!configs.empty());
const App app(configs);
// Construct the waker (publishing its eventfd) before installing the