You've already forked ivi-homescreen
mirror of
https://github.com/toyota-connected/ivi-homescreen.git
synced 2026-06-21 07:19:30 -07:00
Refactored Sentry configuration to use TOML config
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user