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_PROMISC) != 0) || ((ifa->ifa_flags & IFF_UP) != 0))
72 {
73 continue;
74 }
75
76 switch (ifa->ifa_addr->sa_family)
77 {
78 case AF_INET: {
79 std::array<char, INET_ADDRSTRLEN> host{};
80 inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in *>(ifa->ifa_addr))->sin_addr, host.data(),
81 INET_ADDRSTRLEN);
82 sentry_value_set_by_key(networkContext, (std::string(ifa->ifa_name) + ".ipv4").c_str(),
83 sentry_value_new_string(host.data()));
84 break;
85 }
86 case AF_INET6: {
87 std::array<char, INET6_ADDRSTRLEN> host{};
88 inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr))->sin6_addr, host.data(),
89 INET6_ADDRSTRLEN);
90 sentry_value_set_by_key(networkContext, (std::string(ifa->ifa_name) + ".ipv6").c_str(),
91 sentry_value_new_string(host.data()));
92 break;
93 }
94 case AF_PACKET: {
95 std::array<char, MAC_LEN> host{};
96 if (const auto *sock = reinterpret_cast<sockaddr_ll *>(ifa->ifa_addr);
97 snprintf(host.data(), MAC_LEN, "%02x:%02x:%02x:%02x:%02x:%02x", sock->sll_addr[0],
98 sock->sll_addr[1], sock->sll_addr[2], sock->sll_addr[3], sock->sll_addr[4],
99 sock->sll_addr[5]) > 0)
100 {
101 sentry_value_set_by_key(networkContext, (std::string(ifa->ifa_name) + ".mac").c_str(),
102 sentry_value_new_string(host.data()));
103 }
104 break;
105 }
106 default:
107 break;
108 }
109 }
110 freeifaddrs(ifaddr);
111
112 sentry_set_context("Network", networkContext);
113 }
114} // namespace
115
116namespace spdlog::sinks
117{
118 template <typename Mutex> sentry_api_sink<Mutex>::sentry_api_sink(const std::string &sentryAddress)
119 {
120 if (sentryAddress.empty())
121 {
122 return;
123 }
124 _sentryAvailable = true;
125
126 // Set options
127 sentry_options_t *sentryOptions = sentry_options_new();
128 sentry_options_set_release(sentryOptions, PROJECT_FULL_REVISION);
129 sentry_options_set_dsn(sentryOptions, sentryAddress.c_str());
130
131 // Init
132 sentry_init(sentryOptions);
133
134 // Tags
135 sentry_set_tag("compiler.name", COMPILER_NAME);
136 sentry_set_tag("compiler.version", COMPILER_VERSION);
137 sentry_set_tag("build", BUILD_TYPE);
138
139 /* ################################################################################### */
140 /* ############################# MAKE MODIFICATIONS HERE ############################# */
141 /* ################################################################################### */
142
143 /* ################################################################################### */
144 /* ################################ END MODIFICATIONS ################################ */
145 /* ################################################################################### */
146
147 setVersionContext();
148 setHostContext();
149 setNetworkContext();
150 }
151
152 template <typename Mutex> sentry_api_sink<Mutex>::~sentry_api_sink() { sentry_close(); }
153
154 template <typename Mutex> void sentry_api_sink<Mutex>::sink_it_(const details::log_msg &msg)
155 {
156 if (!_sentryAvailable)
157 {
158 return;
159 }
160 switch (msg.level)
161 {
162 case spdlog::level::warn:
163 sentry_capture_event(sentry_value_new_message_event(
164 SENTRY_LEVEL_WARNING, "main", std::string(msg.payload.data(), msg.payload.size()).c_str()));
165 break;
166 case spdlog::level::err:
167 sentry_capture_event(sentry_value_new_message_event(
168 SENTRY_LEVEL_ERROR, "main", std::string(msg.payload.data(), msg.payload.size()).c_str()));
169 break;
170 case spdlog::level::critical:
171 sentry_capture_event(sentry_value_new_message_event(
172 SENTRY_LEVEL_FATAL, "main", std::string(msg.payload.data(), msg.payload.size()).c_str()));
173 break;
174 case spdlog::level::trace:
175 case spdlog::level::debug:
176 case spdlog::level::info:
177 case spdlog::level::off:
178 // For lower levels, do nothing for now. But you can easily handle them here.
179 break;
180 default:
181 break;
182 }
183 }
184
185 template <typename Mutex> void sentry_api_sink<Mutex>::flush_()
186 {
187 // Sentry library handles all operations, so no need to flush
188 }
189
190 template class sentry_api_sink<std::mutex>;
192} // 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:118
void sink_it_(const details::log_msg &msg) override
Definition Sentry.cpp:154