欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Windows下sentry接入C/C++程序的詳細(xì)過程

 更新時(shí)間:2022年09月29日 09:40:06   作者:小?琛  
sentry作為一個(gè)開源的軟件,發(fā)展至今,已經(jīng)非常成熟。它支持的平臺(tái)眾多,甚至于針對(duì)不同的工作者(后臺(tái)、前端、客戶端)都有相應(yīng)的內(nèi)容,這篇文章主要介紹了Windows下sentry接入C/C++程序,需要的朋友可以參考下

sentry簡(jiǎn)介

首先,如果你是為工作而做,公司一定有自己的sentry賬號(hào),去找他們申請(qǐng)權(quán)限吧;如果是學(xué)習(xí)或自己用,先去這里申請(qǐng)一個(gè)賬號(hào)sentry.io。記得,綁定的郵箱很關(guān)鍵,之后的所有崩潰、消息、異常sentry都會(huì)發(fā)送郵件給你

sentry的作用

為大家通俗的總結(jié):針對(duì)開發(fā)中的項(xiàng)目,即使我們做足了一切的排查,可仍然有出現(xiàn)crash(崩潰)的可能,這是我們必須承認(rèn)的;或者,有些時(shí)候我們使用try catch,對(duì)于某些catch我們很希望知道它的觸發(fā)率是什么。因此,sentry的本質(zhì)就是做這樣的工作:為我們的工程上一層保險(xiǎn),讓我們開發(fā)人員能隨時(shí)知道自己維護(hù)的項(xiàng)目是怎樣的狀態(tài)

舉個(gè)例子:讓大家感受一下

例如:這里的項(xiàng)目,我們可以清楚的看到,崩潰觸發(fā)率等很多我們關(guān)心的內(nèi)容

下方的圖片,我們甚至可以清楚的定位到,本次crash發(fā)生在線程29428,SentryTest.exe中main函數(shù)的71行

這里只舉了兩個(gè)最最基本的例子,但已經(jīng)能看到sentry的強(qiáng)大。

sentry-native是什么

sentry作為一個(gè)開源的軟件,發(fā)展至今,已經(jīng)非常成熟。它支持的平臺(tái)眾多,甚至于針對(duì)不同的工作者(后臺(tái)、前端、客戶端)都有相應(yīng)的內(nèi)容。而我們本次討論的是針對(duì)C/C++的版本
sentry官方GitHub鏈接

基于C/C++的native版,SDK編譯

有一點(diǎn)我在這里吐槽一下:sentry的官方只給了源碼和編譯方法,為什么不送佛送到西,給咱們把SDK編譯好?。?!(如果你熟悉vckpg,其實(shí)vckpg可以直接集成sentry)

sentry-native C/C++版本源碼

1.截至到我寫這篇博客,更新到0.5版本,使用可以將其對(duì)于的zip下載即可

2.開始編譯工作
我只能說,這里的編譯應(yīng)該是他們的疏忽,官方給的流程中有一些問題,我將整個(gè)流程進(jìn)行匯總,并將有問題的地方在后面標(biāo)注(希望在你使用的時(shí)候,這些問題已經(jīng)被修復(fù))

  • sentry的SDK構(gòu)建借助的是CMake,在你下載的工程目錄下,打開cmd

如果你的開發(fā)環(huán)境是 macOS ,流程如下

# Configure the CMake build into the `build` directory with crashpad (the default
# backend on macOS, thus optional to specify). Specifying `RelWithDebInfo` as the 
# `CMAKE_BUILD_TYPE` is also optional because it is the default in sentry-native
# for all generators supporting it.
cmake -B build -D SENTRY_BACKEND=crashpad -D CMAKE_BUILD_TYPE=RelWithDebInfo
# build the project
cmake --build build --parallel
# install the resulting artifacts into a specific prefix
cmake --install build --prefix install
# which will result in the following (on macOS):
exa --tree install --level 2
install
├── bin
│  └── crashpad_handler
├── include
│  └── sentry.h
└── lib
   ├── cmake
   ├── libsentry.dylib
   └── libsentry.dylib.dSYM

如果你是在Windows下,流程如下

# The msbuild generator ignores the CMAKE_BUILD_TYPE because it contains all 
# build-types. Here we leave out the backend specification and rely on CMake
# selecting crashpad as Windows' default backend.
cmake -B build 
# The actual build step then requires we specify which build-type we want 
# to apply via the `--config` parameter. Please be aware that in msbuild 
# projects, the `--parallel` option has no effect. 
cmake --build build --config RelWithDebInfo
# install the resulting artifacts (again requiring build-type!)
cmake --install build --prefix install --config RelWithDebInfo
# which will result in the following output (ignoring non-essential lines):
tree /f install
├───bin
│       crashpad_handler.exe
│       crashpad_handler.pdb
│       sentry.dll
│       sentry.pdb
│
├───include
│       sentry.h
│
└───lib
    │   sentry.lib

接下來,進(jìn)行問題的解決(如果沒有問題,忽略這些內(nèi)容):

0.5版本整個(gè)工程編譯都會(huì)報(bào)警告:提示修改文件為Unicode。這是因?yàn)檫@些文件是他們?cè)贚inux下做的,所以文件都是UTF-8無簽名,而Windows下需要UTF-8帶簽名。但文件這么多,如果一個(gè)個(gè)在visual stdio下改不現(xiàn)實(shí),因此,打開CmakeList,將警告忽略,添加一句代碼:add_definitions(-w)

一定要注意

一定要注意,上圖的例子是我在Windows下做所以寫在這里,如果你是Mac下,就要寫在外面

工程里面給的example部分,竟然有語法錯(cuò)誤。。。這我真沒想到。解決辦法:自己打開visual stdio解決一下,或者另一個(gè)方式,忽略即可,只要正常編譯出來了dll、lib、exe即可。

或者打開build目錄,cmake成功后,會(huì)生成解決方案,用visual stdio打開,這里一定要將編譯方法選為下圖這個(gè)

接著,對(duì)每一個(gè)項(xiàng)目(有問題的RUN_TASK略過)進(jìn)行生成

如果你要編譯x86版本,除了在vs下將所以相關(guān)x64的設(shè)置都改成x86或win32,也許還會(huì)遇到這個(gè)錯(cuò)誤:模塊對(duì)于 SAFESEH 映像是不安全的錯(cuò)誤。解決方法是,對(duì)于出問題的模塊,屬性->鏈接器->命令行->添加:/SAFESEH:NO

暫時(shí)就這么多錯(cuò)誤,如果你還有其它的錯(cuò)誤,百度搜一搜,或問問大佬,別放棄,想想我當(dāng)時(shí)也很難的?。?!

sentry-SDK接入本地工程

接入我們自己的工程

接下來,我們將編譯好的SDK接入工程,注意:我所有的操作都是以Windows下例子,如果你是后端,去看對(duì)應(yīng)的官方文檔吧 sentry入口
ps:SDK,就是我們編譯出來的sentry.dll、sentry.lib、crashpad_handler.exe,sentry.h通俗來講就是可以直接集成到我們工程里的內(nèi)容。

接下來的操作,熟悉代碼編譯原理和程序運(yùn)行原理的朋友一定覺得我啰嗦

1.熟悉代碼編譯原理和程序運(yùn)行原理的朋友一定不陌生,一個(gè)接入的SDK想要成功編譯,需要將頭文件引入

2.lib庫是頭文件中那些函數(shù)的具體實(shí)現(xiàn),你需要在你的工程中將其鏈接進(jìn)來,可以使用 #pragma comment(lib, “sentry.lib”)手動(dòng)鏈接,亦可以在鏈接器中添加(一定要鏈接成功,否則編譯的時(shí)候會(huì)報(bào)錯(cuò))

3.sentry.dll是編譯出來的程序正常運(yùn)行需要的動(dòng)態(tài)庫,你需要將它和編譯出來的內(nèi)容放到同級(jí)目錄下,否則編譯出來的exe是無法正常運(yùn)行的。

4.crashpad_handler.exe,這是sentry執(zhí)行崩潰操作的exe,也就是說,我們調(diào)用的接口,最終都是它來執(zhí)行操作。因此,想讓sentry正常工作,需要將它和編譯產(chǎn)物放到一起(和sentry.dll一樣)。

關(guān)于配置

一些必要信息的初始化

記住一句話,sentry的初始化越早越好,始終記得,你的目的是讓sentry監(jiān)控你的項(xiàng)目狀態(tài)。

這里先上一段代碼吧

#include <sentry.h>

int main(void) {
  sentry_options_t *options = sentry_options_new();
  sentry_options_set_dsn(options, "https://examplePublicKey@o0.ingest.sentry.io/0");
  sentry_options_set_release(options, "my-project-name@2.3.12");
  sentry_options_set_debug(options, 1);
  sentry_options_set_environment(options, "production");
  sentry_options_set_database_path(options, ".native");
  sentry_init(options);

  /* ... */
}

上面的代碼完成了基本的初始化,也就是說sentry已經(jīng)可以正常工作了,接下來細(xì)說

1.初始化用到的對(duì)象
sentry_options_t *options = sentry_options_new();這段代碼中options就是后面需要用的對(duì)象,或許你可以把它的定義放到類內(nèi)成員函數(shù)處dsn
2.DSN告訴 SDK 將事件發(fā)送到哪里。如果未提供此值,SDK 將嘗試從SENTRY_DSN環(huán)境變量中讀取它。如果該變量也不存在,SDK 將不會(huì)發(fā)送任何事件。
關(guān)于dsn的查看如下圖,這個(gè)dsn是獨(dú)有的,也是固定的,因此代碼中可以直接寫死,即調(diào)用sentry_options_set_dsn接口,第一個(gè)參數(shù)就是初始化的對(duì)象,第二個(gè)參數(shù)即dsn地址,是一個(gè)字符串

3.Release版本
通常你的產(chǎn)品有多個(gè)不同版本,有些時(shí)候你可能還需要對(duì)它們進(jìn)行區(qū)分,如下圖,你可以清晰的看到每個(gè)版本的表現(xiàn)

使用sentry_options_set_release(參數(shù)1,參數(shù)2);參數(shù)1為初始化對(duì)象,參數(shù)2為具體版本(一個(gè)字符串)

4.觸發(fā)環(huán)境
有些時(shí)候,你的產(chǎn)品可能面向多種用戶,例如:product、develop、test。設(shè)置環(huán)境去進(jìn)行區(qū)分
sentry_options_set_environment(參數(shù)1,參數(shù)2);參數(shù)1為初始化對(duì)象,參數(shù)2為環(huán)境(一個(gè)字符串)

5.日志目錄
sentry的運(yùn)行是會(huì)產(chǎn)生目錄的,如果不設(shè)置,就會(huì)以當(dāng)前路徑為默認(rèn)目錄,在一些面向用戶的產(chǎn)品中,這是肯定不允許的,也許你需要將它設(shè)置為temp臨時(shí)目錄下去
sentry_options_set_database_path(參數(shù)1,參數(shù)2);參數(shù)1為初始化對(duì)象,參數(shù)2為目錄路徑(字符串,絕對(duì)路徑和相對(duì)路徑均可)

自定義配置

有些時(shí)候,你可能需要一些其它信息來輔助你排查錯(cuò)誤,或者是處理后續(xù)的事宜,這里列舉幾個(gè),可以選擇性參考

添加一個(gè)自定義content字段

例如上圖,這個(gè)character字段就是我自己添加的。
下面的函數(shù)是我自己封裝的函數(shù),第一個(gè)參數(shù)為自定義的內(nèi)容,例如:character,第二個(gè)參數(shù)為一個(gè)map,輸入你希望的信息,例如:uuid:19,name:Mighty Fighter,都是調(diào)用了sentry SDK接口。在需要添加信息的地方使用即可

void addContext(const char* contextName, std::unordered_map<char*, char*> textContent)
{
    if (contextName == nullptr || textContent.empty()) {
        return;
    }
    sentry_value_t character = sentry_value_new_object();

    for (auto it = textContent.begin(); it != textContent.end(); it++) {
        sentry_value_set_by_key(character, it->first, sentry_value_new_string(it->second));
    }

    sentry_set_context(contextName, character);
}

豐富本次觸發(fā)的用戶信息
下面的函數(shù)是我自定義的,為本次在觸發(fā)添加用戶信息,這里添加了觸發(fā)的ip地址和uuid,當(dāng)然你也可以自定義其它內(nèi)容。注意:sentry可以自動(dòng)拿到ip地址,格式如下面的代碼:sentry_value_new_string(“{{auto}}”)

void addUser(const char* ipAddress, const char* uuid) 
{
    if (uuid == nullptr) {
        return;
    }
    sentry_value_t user = sentry_value_new_object();
    if (ipAddress == nullptr) {
        sentry_value_set_by_key(user, "ip_address", sentry_value_new_string("{{auto}}"));
    } else {
        sentry_value_set_by_key(user, "ip_address", sentry_value_new_string(ipAddress));
    }

    sentry_value_set_by_key(user, "uuid", sentry_value_new_string(uuid));
    LOG_INFO << "[SentryReporter::addUser]: add User: uuid: " << uuid;

    sentry_set_user(user);
}

利用sentry監(jiān)視崩潰

在完成所有的初始化工作后,sentry就可以為你的工程進(jìn)行監(jiān)控了,在出現(xiàn)crash時(shí),即可向你的客戶端發(fā)送報(bào)告。

崩潰回調(diào)

sentry提供了崩潰回調(diào)函數(shù),什么作用呢?在發(fā)送crash時(shí),sentry會(huì)執(zhí)行它的所有工作,攔截+上發(fā),但在這之前,如果你想做一些其它的事情,也是可以的,看如下代碼:

sentry_value_t SentryReporter::onCrashCallback(
    const sentry_ucontext_t* uctx, // Crashed user space context
    sentry_value_t event,
    void* closure                  // User data that provide during configuration
)
{
    const std::wstring uuid = APP->getMainWindow()->getUUID();
    addUser(nullptr, Utils::StringUtils::ws2s(uuid).c_str());

    //if you want to give up this crash,Add a judgment method and make the following if true
    if (GIVE_UP_CRASH) {
        sentry_value_decref(event);
        return sentry_value_new_null();
    }

    return event;
}

//----------------初始化時(shí)添加-------------------------
sentry_options_set_on_crash(optioning, onCrashCallback, NULL);

代碼中,實(shí)現(xiàn)了一個(gè)函數(shù)onCrashCallback,并在sentry初始化時(shí)進(jìn)行綁定,這樣做之后,就可以達(dá)到上面說的效果。

你可以在崩潰回調(diào)函數(shù)中做一些操作,例如:添加一些附加信息,又或者調(diào)用接口放棄上傳此次崩潰
一定要注意,sentry沒有做線程安全處理,因此這里的崩潰回調(diào)函數(shù)一定要輕量級(jí),不要做過重的計(jì)算操作

手動(dòng)發(fā)送異常、消息

sentry的另一種用法就是我們手動(dòng)上發(fā)事件,舉個(gè)例子:代碼中try catch,我希望得知某些catch的觸發(fā)率,就可以在對(duì)應(yīng)的catch處進(jìn)行一個(gè)手動(dòng)的數(shù)據(jù)上發(fā)。
看如下代碼:

void capturingErrorsWithStacktrace(const char* errorMessage) 
{
    sentry_value_t event = sentry_value_new_event();

    sentry_value_t exc = sentry_value_new_exception("Exception", errorMessage);
    sentry_value_set_stacktrace(exc, NULL, 0);
    sentry_event_add_exception(event, exc);
    LOG_INFO << "[SentryReporter::capturingErrorsWithStacktrace]:sentry sent error,message: " << errorMessage;

    sentry_capture_event(event);
}

void capturingMessages(sentry_level_t level, const char* logger, const char* message) 
{
    if (logger == nullptr || message == nullptr) {
        return;
    }

    sentry_value_t event = sentry_value_new_message_event(level, logger, message);
    LOG_INFO << "[SentryReporter::capturingMessages]:sentry  sent message,level: " 
        << level << "logger: " << logger << "message: " << message;

    sentry_capture_event(event);
}

上面的兩個(gè)函數(shù),一個(gè)可以手動(dòng)發(fā)送錯(cuò)誤、一個(gè)可以手動(dòng)發(fā)送一個(gè)自定義消息,這里就不講述了,自己看代碼理解一下。

消息回調(diào)

與crash回調(diào)一樣,手動(dòng)發(fā)送的消息也可以有回調(diào)函數(shù),這里直接給出實(shí)現(xiàn),原理請(qǐng)看上文:

/*
* This function sends an error or message manually to make a callback
* You can do some operations, such as adding information
*/
sentry_value_t SentryReporter::beforeSendCallback(sentry_value_t event, void* hint, void* closure)
{
    //do something before send
    return event;
}


//---------------------設(shè)置發(fā)送消息回調(diào)--------------------------
sentry_options_set_before_send(m_pOptions.get(), beforeSendCallback, NULL);

上傳PDB,直接定位崩潰發(fā)生的位置

sentry的另一個(gè)強(qiáng)大之處,在于當(dāng)發(fā)生崩潰時(shí),它不僅可以及時(shí)捕捉并上報(bào),還可以配合正確的PDB(Windows下的調(diào)試文件),精確的定位到發(fā)生crash的exe或dll,甚至可以定位到具體哪一行代碼

  • 適用于 iOS、iPadOS、tvOS、watchOS 和 macOS 的dSYM 文件
  • 適用于 Linux 和 Android (NDK) 的ELF 符號(hào)
  • 適用于 Windows 的PDB 文件
  • 適用于所有平臺(tái)的Breakpad 符號(hào)
  • WebAssembly 的WASM 文件
  • 適用于 Java 和 Android 的ProGuard 映射

崩潰發(fā)生在線程29428,SentryTest.exe中main函數(shù)71行


崩潰發(fā)生在線程29428,SentryTest.exe中main函數(shù)71行

流程如下:

1.最直接的方式是借助第三方的工具sentry-cli.exe,下載鏈接,下載下來的內(nèi)容僅僅一個(gè)sentry-cli.exe,在cmd下利用該exe進(jìn)行操作即可

2.首先,你可能需要先對(duì)身份進(jìn)行配置,cmd下該命令,其中如果你是使用的自己項(xiàng)目組或公司的sentry,需要將https://myserver.invalid/換為自己項(xiàng)目的url,這里放置的url是sentry io的官方環(huán)境

sentry-cli --url https://myserver.invalid/ login

3.上傳調(diào)試文件,這里以Windows下的pdb為例子

#首先對(duì)調(diào)試文件進(jìn)行檢查,是否格式正確
sentry-cli difutil check SentryTest.pdb

如果出現(xiàn)了類似以下內(nèi)容,即為格式正確

Debug Info File Check
  Type: elf debug companion
  Contained debug identifiers:
    > 924e148f-3bb7-06a0-74c1-36f42f08b40e (x86_64)
  Contained debug information:
    > symtab, debug
  Usable: yes

接下來,將該文件上傳,其中 < org >要換你的項(xiàng)目所在組織;< project > 要換位你的項(xiàng)目名稱;后面的files則為具體文件,支持絕對(duì)路徑和相對(duì)路徑,且支持上傳多個(gè)文件

sentry-cli upload-dif -o <org> -p <project> files...

出現(xiàn)類似如下內(nèi)容,則上傳成功

> Found 2 debug information files
> Prepared debug information files for upload
> Uploaded 2 missing debug information files
> File processing complete:

  PENDING 1ddb3423-950a-3646-b17b-d4360e6acfc9 (MyApp; x86_64 executable)
  PENDING 1ddb3423-950a-3646-b17b-d4360e6acfc9 (MyApp; x86_64 debug companion)

又或者,你可以去sentry項(xiàng)目處查看:

博主自己封裝的sentry類

注意:這里的代碼是不能直接用的,因?yàn)樯婕暗搅艘恍┬畔⒌奶崛。枰鶕?jù)自身項(xiàng)目進(jìn)行適配,在對(duì)sentry有一定了解后,再來看

SentryReporter.h

#pragma once
#include "sentry.h"
#include "stdafx.h"
#include <iostream>
#include <string>
#include <unordered_map>

#ifdef ANDROID_SIX
const std::string SENTRY_DSN = "https://b2a9969e03944fae81a12cf84afa6bd2@sentry.netease.com/81";
#else
const std::string SENTRY_DSN = "https://ca88798ea2404243a3dc5a5e2ebdb670@sentry.netease.com/82";
#endif // ANDROID_SIX

const std::string DATABASE_NAME = ".sentry-native";
const std::string ENVIRONMENT = "production";

const bool GIVE_UP_CRASH = false;

struct SentryInitInfo
{
    std::string dsn;
    std::string databasePath;
    std::string releaseVersion;
    std::string environment;
    std::string nemuDownloadLog;
    float sampleRate;//Range must be within :0-1
    int maxBreadcrumbs;//default:100
    bool attachStacktrace;//default:false
};

class SentryReporter {

public:
    SentryReporter();
    ~SentryReporter();
    void setup();
    static void addContext(const char* contextName, std::unordered_map<char*, char*> textContent);
    static void addUser(const char* ipAddress, const char* uuid);//if ipAddress = nullptr,get from system
    static void capturingErrorsWithStacktrace(const char* errorMessage);
    static void capturingMessages(sentry_level_t level, const char* logger, const char* message);

private:
    void fetchInitInfomation();
    static sentry_value_t onCrashCallback(const sentry_ucontext_t* uctx, sentry_value_t event, void* closure);
    static sentry_value_t beforeSendCallback(sentry_value_t event, void* hint, void* closure);

private:
    shared_ptr<sentry_options_t> m_pOptions;
    SentryInitInfo m_sentryInitInfo;
};

SentryReporter.cpp

#include "SentryReport.h"
#include "utils.h"
#include "VersionNo.h"
#include "MainWindow.h"

sentry_value_t SentryReporter::onCrashCallback(
    const sentry_ucontext_t* uctx, // Crashed user space context
    sentry_value_t event,
    void* closure                  // User data that provide during configuration
)
{
    const std::wstring uuid = APP->getMainWindow()->getUUID();
    addUser(nullptr, Utils::StringUtils::ws2s(uuid).c_str());

    //if you want to give up this crash,Add a judgment method and make the following if true
    if (GIVE_UP_CRASH) {
        sentry_value_decref(event);
        return sentry_value_new_null();
    }

    return event;
}

/*
* This function sends an error or message manually to make a callback
* You can do some operations, such as adding information
*/
sentry_value_t SentryReporter::beforeSendCallback(sentry_value_t event, void* hint, void* closure)
{
    //do something before send
    return event;
}

SentryReporter::SentryReporter()
    :m_pOptions(sentry_options_new())
{
    fetchInitInfomation();
}

SentryReporter::~SentryReporter()
{
    sentry_close();
    m_pOptions = nullptr;
}

void SentryReporter::fetchInitInfomation()
{
    m_sentryInitInfo.dsn = SENTRY_DSN;

    std::wstring databasePath = Utils::pathCombine(DCommon::DSystemUtils::getTempPath(), Utils::StringUtils::s2ws(DATABASE_NAME));
    m_sentryInitInfo.databasePath = Utils::StringUtils::ws2s(databasePath);

    m_sentryInitInfo.releaseVersion = Utils::StringUtils::ws2s(STRVERSION);
    m_sentryInitInfo.environment = ENVIRONMENT;

    std::wstring logFilePath = Utils::getLogFile();
    m_sentryInitInfo.nemuDownloadLog = Utils::StringUtils::ws2s(logFilePath);

    sentry_options_set_auto_session_tracking(m_pOptions.get(), false);
    sentry_options_set_symbolize_stacktraces(m_pOptions.get(), true);

    //use default value
    m_sentryInitInfo.sampleRate = 1;
    m_sentryInitInfo.maxBreadcrumbs = 100;
    m_sentryInitInfo.attachStacktrace = false;
}

void SentryReporter::setup()
{
    sentry_options_set_dsn(m_pOptions.get(), m_sentryInitInfo.dsn.c_str());
    sentry_options_set_database_path(m_pOptions.get(), m_sentryInitInfo.databasePath.c_str());
    sentry_options_set_release(m_pOptions.get(), m_sentryInitInfo.releaseVersion.c_str());
    sentry_options_set_environment(m_pOptions.get(), m_sentryInitInfo.environment.c_str());
    sentry_options_set_traces_sample_rate(m_pOptions.get(), m_sentryInitInfo.sampleRate);
    sentry_options_add_attachment(m_pOptions.get(), m_sentryInitInfo.nemuDownloadLog.c_str());

    sentry_options_set_on_crash(m_pOptions.get(), onCrashCallback, NULL);
    sentry_options_set_before_send(m_pOptions.get(), beforeSendCallback, NULL);

    int ret = sentry_init(m_pOptions.get());
    if (ret != 0) {
        LOG_INFO << "[SentryReporter::setup]: sentry init error";
    }
}

void SentryReporter::addContext(const char* contextName, std::unordered_map<char*, char*> textContent)
{
    if (contextName == nullptr || textContent.empty()) {
        LOG_INFO << "[SentryReporter::addContext]: contextName==nullptr or textContent==nullptr";
        return;
    }
    sentry_value_t character = sentry_value_new_object();

    for (auto it = textContent.begin(); it != textContent.end(); it++) {
        sentry_value_set_by_key(character, it->first, sentry_value_new_string(it->second));
    }

    sentry_set_context(contextName, character);
}

void SentryReporter::addUser(const char* ipAddress, const char* uuid) 
{
    if (uuid == nullptr) {
        LOG_INFO << "[SentryReporter::addUser]: uuid==nullptr";
        return;
    }
    sentry_value_t user = sentry_value_new_object();
    if (ipAddress == nullptr) {
        sentry_value_set_by_key(user, "ip_address", sentry_value_new_string("{{auto}}"));
    } else {
        sentry_value_set_by_key(user, "ip_address", sentry_value_new_string(ipAddress));
    }

    sentry_value_set_by_key(user, "uuid", sentry_value_new_string(uuid));
    LOG_INFO << "[SentryReporter::addUser]: add User: uuid: " << uuid;

    sentry_set_user(user);
}

void SentryReporter::capturingErrorsWithStacktrace(const char* errorMessage) 
{
    sentry_value_t event = sentry_value_new_event();

    sentry_value_t exc = sentry_value_new_exception("Exception", errorMessage);
    sentry_value_set_stacktrace(exc, NULL, 0);
    sentry_event_add_exception(event, exc);
    LOG_INFO << "[SentryReporter::capturingErrorsWithStacktrace]:sentry sent error,message: " << errorMessage;

    sentry_capture_event(event);
}

void SentryReporter::capturingMessages(sentry_level_t level, const char* logger, const char* message) 
{
    if (logger == nullptr || message == nullptr) {
        return;
    }

    sentry_value_t event = sentry_value_new_message_event(level, logger, message);
    LOG_INFO << "[SentryReporter::capturingMessages]:sentry  sent message,level: " 
        << level << "logger: " << logger << "message: " << message;

    sentry_capture_event(event);
}

到此這篇關(guān)于Windows——sentry接入C/C++程序的文章就介紹到這了,更多相關(guān)Windows C++程序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言宏定義使用分析

    C語言宏定義使用分析

    在宏定義中,“宏名稱”和“宏字符串”是通過“空格”來區(qū)分的,某些朋友不要混淆了,接下來請(qǐng)祥看本文
    2012-12-12
  • C++精要分析lambda表達(dá)式的使用

    C++精要分析lambda表達(dá)式的使用

    Lambda表達(dá)式是現(xiàn)代C++在C ++ 11和更高版本中的一個(gè)新的語法糖 ,在C++11、C++14、C++17和C++20中Lambda表達(dá)的內(nèi)容還在不斷更新。 lambda表達(dá)式(也稱為lambda函數(shù))是在調(diào)用或作為函數(shù)參數(shù)傳遞的位置處定義匿名函數(shù)對(duì)象的便捷方法
    2022-05-05
  • C語言超詳細(xì)講解遞歸算法漢諾塔

    C語言超詳細(xì)講解遞歸算法漢諾塔

    漢諾塔問題是一個(gè)經(jīng)典的問題。漢諾塔(Hanoi Tower),又稱河內(nèi)塔,源于印度一個(gè)古老傳說。本文將用Java求解這一問題,感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • C++中雙冒號(hào)::用法案例詳解

    C++中雙冒號(hào)::用法案例詳解

    這篇文章主要介紹了C++中雙冒號(hào)::用法案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • c語言中main函數(shù)用法及知識(shí)點(diǎn)總結(jié)

    c語言中main函數(shù)用法及知識(shí)點(diǎn)總結(jié)

    在本篇文章里小編給大家分享的是一篇關(guān)于c語言中main函數(shù)用法及知識(shí)點(diǎn)總結(jié)內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)參考下。
    2021-10-10
  • C++中using的三種用法舉例詳解

    C++中using的三種用法舉例詳解

    最近在使用中,發(fā)現(xiàn)了一種以前沒學(xué)過的using用法,于是在這里,將using的幾種用法總結(jié)一下,下面這篇文章主要給大家介紹了關(guān)于C++中using的三種用法,需要的朋友可以參考下
    2023-02-02
  • win32使用openfilename瀏覽文件窗口示例

    win32使用openfilename瀏覽文件窗口示例

    這篇文章主要介紹了使用win32 API打開瀏覽文件窗口,使用OPENFILENAME結(jié)構(gòu)體來實(shí)現(xiàn)這個(gè)功能,需要的朋友可以參考下
    2014-02-02
  • C++中函數(shù)重載詳解

    C++中函數(shù)重載詳解

    大家好,本篇文章主要講的是C++中函數(shù)重載詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • 詳解C++基礎(chǔ)——類繼承中方法重載

    詳解C++基礎(chǔ)——類繼承中方法重載

    這篇文章主要介紹了C++基礎(chǔ)——類繼承中方法重載,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • c語言 樹的基礎(chǔ)知識(shí)(必看篇)

    c語言 樹的基礎(chǔ)知識(shí)(必看篇)

    下面小編就為大家?guī)硪黄猚語言 樹的基礎(chǔ)知識(shí)(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05

最新評(píng)論