Свой Sentry для крашей Qt-приложения: сервер, sentry-native и символы
Sentry — открытая платформа для сбора ошибок и крашей. Облачная версия удобна, но у неё два минуса: данные уходят из вашей инфраструктуры, а цена растёт вместе с числом событий.
Собственный Sentry снимает оба. Вы сами управляете данными, не платите за каждое событие и подключаете внутренние инструменты, не открывая их наружу.
Ниже — весь путь от пустого сервера до первого краша в дашборде:
- Поднимите Sentry на Ubuntu за Nginx с сертификатом Let’s Encrypt.
- Соберите клиент sentry-native в Visual Studio 2022.
- Подключите его к Qt/CMake-проекту.
- Загрузите отладочные символы, чтобы стеки читались.
Часть 1. Sentry на своём сервере
1. Установите Sentry
Подготовьте сервер на Ubuntu: добавьте пользователя и установите Docker.
Минимальные требования Sentry:
- 4 ядра процессора;
- 16 ГБ RAM и 16 ГБ swap;
- 20 ГБ свободного места на диске.
1.1 Скачайте Sentry из репозитория и установите
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/getsentry/self-hosted/releases/latest)
VERSION=${VERSION##*/}
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
git checkout ${VERSION}
./install.sh
1.2 Настройте sentry/config.yml
Укажите адрес сервера:
system.url-prefix: 'https://sentry.example.com'
Настройте отправку почты. В примере — SMTP2GO:
###############
# Mail Server #
###############
mail.backend: 'smtp'
mail.host: 'mail.smtp2go.com'
mail.port: 587
mail.username: '<USERNAME>'
mail.password: '<PWD>'
1.3 Настройте sentry/sentry.conf.py
Добавьте адрес сервера в доверенные источники CSRF:
CSRF_TRUSTED_ORIGINS = ["https://sentry.example.com"]
Включите SSL/TLS:
###########
# SSL/TLS #
###########
# If you're using a reverse SSL proxy, you should enable the X-Forwarded-Proto
# header and enable the settings below
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
1.4 Перезапустите Docker
docker compose down
docker compose up -d
2. Установите Nginx
2.1 Установите пакеты
sudo apt install nginx certbot python3-certbot-nginx
2.2 Создайте начальную конфигурацию
Откройте файл:
sudo nano /etc/nginx/sites-available/sentry
Вставьте минимальную конфигурацию. Она нужна, чтобы Let’s Encrypt проверил домен:
server {
listen 80;
listen [::]:80;
server_name sentry.example.com;
root /var/www/html;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 404;
}
}
Включите конфигурацию:
sudo ln -s /etc/nginx/sites-available/sentry /etc/nginx/sites-enabled/sentry
2.3 Проверьте конфигурацию и перезагрузите Nginx
sudo nginx -t
sudo systemctl reload nginx
2.4 Запросите сертификат
sudo mkdir -p /var/www/html
sudo certbot certonly --webroot -w /var/www/html -d sentry.example.com --email support@example.com --agree-tos --no-eff-email
2.5 Скачайте параметры Диффи — Хеллмана (dhparam)
sudo ls /etc/letsencrypt/ffdhe2048.txt || sudo curl -o /etc/letsencrypt/ffdhe2048.txt https://ssl-config.mozilla.org/ffdhe2048.txt
2.6 Замените конфигурацию на полную
Откройте файл:
sudo nano /etc/nginx/sites-available/sentry
Вставьте:
error_log /var/log/nginx/error.log warn;
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sentry.example.com;
ssl_certificate /etc/letsencrypt/live/sentry.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sentry.example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_dhparam /etc/letsencrypt/ffdhe2048.txt;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
client_max_body_size 100m;
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
location ~ ^/api/[0-9]+/(envelope|minidump|security|store|unreal)/ {
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Credentials false always;
add_header Access-Control-Allow-Methods GET,POST,PUT always;
add_header Access-Control-Allow-Headers sentry-trace,baggage always;
add_header Access-Control-Expose-Headers sentry-trace,baggage always;
include proxy_params;
proxy_pass http://127.0.0.1:9000;
}
location / {
include proxy_params;
proxy_pass http://127.0.0.1:9000;
}
}
server {
listen 80;
listen [::]:80;
server_name sentry.example.com;
root /var/www/html;
location /.well-known/ {
try_files $uri =404;
}
location / {
return 301 https://$host$request_uri;
}
}
Что делает эта конфигурация:
- Блок
location ~ ^/api/...принимает события от SDK и отдаёт CORS-заголовки. Они нужны браузерным SDK. client_max_body_size 100mподнимает лимит запроса до 100 МБ: минидампы и вложения бывают большими.- Блок на порту 80 оставляет доступным
/.well-known/для продления сертификата, а остальной трафик перенаправляет на HTTPS. ssl_protocols TLSv1.2 TLSv1.3оставляет TLS 1.2 для клиентов на Windows 10. Системный TLS-стек (Schannel) в ней не поддерживает TLS 1.3, а sentry-native с транспортомwinhttpиспользует именно его (в части 2 клиент собран так). Если все ваши клиенты на Windows 11 или Linux, можно оставить толькоTLSv1.3.
2.7 Проверьте конфигурацию и перезагрузите Nginx
sudo nginx -t
sudo systemctl reload nginx
curl -I https://sentry.example.com
2.8 Перезапустите Sentry
docker compose down
docker compose up -d
Часть 2. Qt-приложение
Sentry Native SDK — клиент для сбора крашей и ошибок в приложениях на C и C++. Он поддерживает теги, breadcrumbs и произвольный контекст. Эти данные помогают воспроизвести и исправить проблему, которая случилась у пользователя.
Сервер из части 1 уже работает. Теперь подключите к нему приложение.
3. Соберите sentry-native в VS 2022 Community x64
Клонируйте исходники вместе с подмодулями:
git clone --recurse-submodules git@github.com:getsentry/sentry-native.git
cd sentry-native
Подготовьте окружение Visual Studio:
"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
Настройте проект:
cmake -G "Visual Studio 17 2022" -A x64 -B build-x64-release -DSENTRY_BUILD_RUNTIMESTATIC=OFF -DSENTRY_BUILD_SHARED_LIBS=ON -DSENTRY_BACKEND=crashpad -DSENTRY_TRANSPORT=winhttp -DCMAKE_BUILD_TYPE=release -DSENTRY_BUILD_TESTS=OFF -DSENTRY_BUILD_EXAMPLES=OFF
Что означают ключевые параметры:
| Параметр | Что делает |
|---|---|
SENTRY_BACKEND=crashpad |
Ловит краши отдельным процессом crashpad_handler |
SENTRY_TRANSPORT=winhttp |
Отправляет события через WinHTTP |
SENTRY_BUILD_SHARED_LIBS=ON |
Собирает sentry.dll вместо статической библиотеки |
SENTRY_BUILD_RUNTIMESTATIC=OFF |
Использует динамическую CRT (/MD), как стандартные сборки Qt |
Соберите проект:
cmake --build build-x64-release --config release --parallel
Установите:
cmake --install build-x64-release --config release --prefix C:/sentry-install/x64/release
4. Подключите Sentry в Qt-проекте
Пример проекта на Qt и CMake: https://github.com/danilevsky/sentry-native-qt-demo
Создайте проект в своём Sentry, если ещё не создали. Затем скопируйте DSN: Settings → Project → [ваш проект] → Client Keys (DSN) → DSN.
#include "mainview.h"
#include <QApplication>
#include <QScopeGuard>
#include <sentry.h>
int main(int argc, char *argv[])
{
const std::string sDSN = "<SENTRY_DSN_VALUE>";
sentry_options_t *options = sentry_options_new();
sentry_options_set_dsn(options, sDSN.c_str());
sentry_options_set_database_path(options, ".sentry-native");
sentry_options_set_release(options, "test-app@1.0.1");
sentry_options_set_debug(options, 1);
sentry_init(options);
auto sentryClose = qScopeGuard([] { sentry_close(); });
QApplication a(argc, argv);
MainView w;
w.show();
sentry_capture_event(sentry_value_new_message_event(
/* level */ SENTRY_LEVEL_INFO,
/* logger */ "custom",
/* message */ "It works!"
));
return QCoreApplication::exec();
}
Что здесь важно:
sentry_options_set_releaseзадаёт версию в форматеимя@версия. По ней Sentry группирует краши по релизам.sentry_options_set_debugвключает отладочный вывод SDK. В релизной сборке выключайте.qScopeGuardиsentry_close()отправляют накопленные события при выходе из программы. Без этого вызова часть событий может не уйти.
Положите crashpad_handler.exe рядом с приложением. SDK запускает его при инициализации и по умолчанию ищет в каталоге исполняемого файла. После cmake --install он лежит в каталоге bin установки рядом с sentry.dll. Копируйте оба файла в каталог приложения. Документация Sentry советует задавать пути явно:
sentry_options_set_handler_path(options, "path/to/crashpad_handler.exe");
sentry_options_set_database_path(options, "sentry-db-directory");
5. Загрузите отладочные символы
Чтобы стек в Sentry показывал функции и строки, загрузите файлы .pdb и .exe утилитой sentry-cli.
sentry-cli нужен токен организации, иначе файлы отладочной информации не загрузятся:
- Откройте Settings → Integrations → Create New Integration → Internal Integration.
- В разделе Token создайте токен для
SENTRY_AUTH_TOKEN.
Задайте переменные и загрузите файлы:
SET SENTRY_END_POINT=<your_sentry_url>
SET SENTRY_AUTH_TOKEN=<token>
SET SENTRY_ORG=<org>
SET SENTRY_LOG_LEVEL=warn
SET SENTRY_PROJECT_NAME=<project_name>
sentry-cli --url %SENTRY_END_POINT% --auth-token %SENTRY_AUTH_TOKEN% debug-files upload -o %SENTRY_ORG% -p %SENTRY_PROJECT_NAME% "test_app.pdb" --log-level %SENTRY_LOG_LEVEL% --include-sources
sentry-cli --url %SENTRY_END_POINT% --auth-token %SENTRY_AUTH_TOKEN% debug-files upload -o %SENTRY_ORG% -p %SENTRY_PROJECT_NAME% "test_app.exe" --log-level %SENTRY_LOG_LEVEL%
6. Вызовите тестовый краш
Добавьте в приложение обработчик с обращением к нулевому указателю:
void MainView::OnClick()
{
int *p = nullptr;
*p = 42;
}
Запустите приложение, нажмите кнопку и откройте дашборд проекта. Вы увидите две записи:
- сообщение «It works!»;
- исключение со стеком вызовов и минидампом во вложениях (Attachments).
Ссылки
- Документация Sentry self-hosted
- Установка Docker на Ubuntu (DigitalOcean)
- Начальная настройка сервера Ubuntu (DigitalOcean)
- Пароли приложений Google, если отправляете почту через Gmail
- Какие версии TLS поддерживает Schannel в Windows (Microsoft)
- Пример проекта на Qt и CMake
- Скрипт сборки sentry-native для всех конфигураций
- Sentry Native SDK: документация
- Бэкенд Crashpad: документация
- sentry-cli: загрузка файлов отладочной информации
- sentry-native на GitHub