Repo-Init
 
Loading...
Searching...
No Matches
Sentry.cpp
Go to the documentation of this file.
1#include "logging/Sentry.hpp"
2
3#include "Version.h"
5
6#include <array>
7
8#include <arpa/inet.h>
9#include <ifaddrs.h>
10#include <net/if.h>
11#include <netpacket/packet.h>
12#include <unistd.h>
13
14#include <sentry.h>
15#include <spdlog/spdlog.h>
16
17// MAC address length for character string
18constexpr int MAC_LEN = 18;
19
20namespace
21{
23 void setVersionContext()
24 {
25 std::string versionBuffer;
26 const sentry_value_t versionContext = sentry_value_new_object();
27 versionBuffer = "v" + std::string(PROJECT_FULL_REVISION);
28 sentry_value_set_by_key(versionContext, PROJECT_NAME, sentry_value_new_string(versionBuffer.c_str()));
29 versionBuffer = std::string(PROJECT_BUILD_DATE) + " " + PROJECT_BUILD_TIME;
30 sentry_value_set_by_key(versionContext, "Release Date", sentry_value_new_string(versionBuffer.c_str()));
31 sentry_set_context("Version", versionContext);
32 }
33
35 void setHostContext()
36 {
37 std::array<char, BUFSIZ> hostBuffer{};
38 gethostname(hostBuffer.data(), BUFSIZ);
39 const sentry_value_t hostContext = sentry_value_new_object();
40 sentry_value_set_by_key(hostContext, "Hostname", sentry_value_new_string(hostBuffer.data()));
41
42 // Parse CPU information
43 const std::string cpuInfoPath = "/proc/cpuinfo";
44 std::string word;
45
46 findFromFile(cpuInfoPath, "^siblings", word);
47 sentry_value_set_by_key(hostContext, "Thread count", sentry_value_new_string(word.c_str()));
48 findFromFile(cpuInfoPath, "^(cpu cores)", word);
49 sentry_value_set_by_key(hostContext, "Core count", sentry_value_new_string(word.c_str()));
50 findFromFile(cpuInfoPath, "^(model name)", word);
51 sentry_value_set_by_key(hostContext, "Model", sentry_value_new_string(word.c_str()));
52 findFromFile(cpuInfoPath, "^vendor_id", word);
53 sentry_value_set_by_key(hostContext, "Vendor ID", sentry_value_new_string(word.c_str()));
54
55 sentry_set_context("Host", hostContext);
56 }
57
59 void setNetworkContext()
60 {
61 ifaddrs *ifaddr = nullptr;
62 if (getifaddrs(&ifaddr) < 0)
63 {
64 return;
65 }
66
67 // Iterate interfaces
68 const sentry_value_t networkContext = sentry_value_new_object();
69 for (ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
70 {
71 if (ifa->ifa_addr == nullptr || ((ifa->ifa_flags & IFF_RUNNING) == 0) ||
72 (ifa->ifa_flags & IFF_LOOPBACK) != 0)
73 {
74 continue;
75 }
76
77 switch (ifa->ifa_addr->sa_family)
78 {
79 case AF_INET: {
80 std::array<char, INET_ADDRSTRLEN> host{};
81 inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in *>(ifa->ifa_addr))->sin_addr, host.data(),
82 INET_ADDRSTRLEN);
83 sentry_value_set_by_key(networkContext, (std::string(ifa->ifa_name) + ".ipv4").c_str(),
84 sentry_value_new_string(host.data()));
85 break;
86 }
87 case AF_INET6: {
88 std::array<char, INET6_ADDRSTRLEN> host{};
89 inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr))->sin6_addr, host.data(),
90 INET6_ADDRSTRLEN);
91 sentry_value_set_by_key(networkContext, (std::string(ifa->ifa_name) + ".ipv6").c_str(),
92 sentry_value_new_string(host.data()));
93 break;
94 }
95 case AF_PACKET: {
96 std::array<char, MAC_LEN> host{};
97 if (const auto *sock = reinterpret_cast<sockaddr_ll *>(ifa->ifa_addr);
98 snprintf(host.data(), MAC_LEN, "%02x:%02x:%02x:%02x:%02x:%02x", sock->sll_addr[0],
99 sock->sll_addr[1], sock->sll_addr[2], sock->sll_addr[3], sock->sll_addr[4],
100 sock->sll_addr[5]) > 0)
101 {
102 sentry_value_set_by_key(networkContext, (std::string(ifa->ifa_name) + ".mac").c_str(),
103 sentry_value_new_string(host.data()));
104 }
105 break;
106 }
107 default:
108 break;
109 }
110 }
111 freeifaddrs(ifaddr);
112
113 sentry_set_context("Network", networkContext);
114 }
115} // namespace
116
117namespace spdlog::sinks
118{
119 template <typename Mutex> sentry_api_sink<Mutex>::sentry_api_sink(const std::string &sentryAddress)
120 {
121 if (sentryAddress.empty())
122 {
123 return;
124 }
125 _sentryAvailable = true;
126
127 // Set options
128 sentry_options_t *sentryOptions = sentry_options_new();
129 sentry_options_set_release(sentryOptions, PROJECT_FULL_REVISION);
130 sentry_options_set_dsn(sentryOptions, sentryAddress.c_str());
131
132 // Init
133 sentry_init(sentryOptions);
134
135 // Tags
136 sentry_set_tag("compiler.name", COMPILER_NAME);
137 sentry_set_tag("compiler.version", COMPILER_VERSION);
138 sentry_set_tag("build", BUILD_TYPE);
139
140 /* ################################################################################### */
141 /* ############################# MAKE MODIFICATIONS HERE ############################# */
142 /* ################################################################################### */
143
144 /* ################################################################################### */
145 /* ################################ END MODIFICATIONS ################################ */
146 /* ################################################################################### */
147
148 setVersionContext();
149 setHostContext();
150 setNetworkContext();
151 }
152
153 template <typename Mutex> sentry_api_sink<Mutex>::~sentry_api_sink() { sentry_close(); }
154
155 template <typename Mutex> void sentry_api_sink<Mutex>::sink_it_(const details::log_msg &msg)
156 {
157 if (!_sentryAvailable)
158 {
159 return;
160 }
161 switch (msg.level)
162 {
163 case spdlog::level::warn:
164 sentry_capture_event(sentry_value_new_message_event(
165 SENTRY_LEVEL_WARNING, "main", std::string(msg.payload.data(), msg.payload.size()).c_str()));
166 break;
167 case spdlog::level::err:
168 sentry_capture_event(sentry_value_new_message_event(
169 SENTRY_LEVEL_ERROR, "main", std::string(msg.payload.data(), msg.payload.size()).c_str()));
170 break;
171 case spdlog::level::critical:
172 sentry_capture_event(sentry_value_new_message_event(
173 SENTRY_LEVEL_FATAL, "main", std::string(msg.payload.data(), msg.payload.size()).c_str()));
174 break;
175 case spdlog::level::trace:
176 case spdlog::level::debug:
177 case spdlog::level::info:
178 case spdlog::level::off:
179 // For lower levels, do nothing for now. But you can easily handle them here.
180 break;
181 default:
182 break;
183 }
184 }
185
186 template <typename Mutex> void sentry_api_sink<Mutex>::flush_()
187 {
188 // Sentry library handles all operations, so no need to flush
189 }
190
191 template class sentry_api_sink<std::mutex>;
193} // namespace spdlog::sinks
std::vector< std::string > findFromFile(const std::string &filePath, const std::string &pattern, std::string &lastWord)
constexpr int MAC_LEN
Definition Sentry.cpp:18
sentry_api_sink(const std::string &sentryAddress)
Definition Sentry.cpp:119
void sink_it_(const details::log_msg &msg) override
Definition Sentry.cpp:155