Repo-Init
 
Loading...
Searching...
No Matches
Loki.cpp
Go to the documentation of this file.
1#include "logging/Loki.hpp"
2
3#include "Version.h"
5
6#include <array>
7#include <filesystem>
8#include <sstream>
9
10#include <arpa/inet.h>
11#include <ifaddrs.h>
12#include <net/if.h>
13#include <netpacket/packet.h>
14#include <unistd.h>
15
16#include <spdlog/spdlog.h>
17
19{
20 template <typename Mutex> loki_api_sink<Mutex>::loki_api_sink(const std::string &lokiAddress)
21 {
22 if (lokiAddress.empty())
23 {
24 return;
25 }
26
27 _connHandler = std::make_unique<HTTP>(lokiAddress);
28
29 // Pre-allocate buffers
30 _internalLogBuffer.push_back({"debug", std::vector<std::pair<std::string, std::string>>()});
31 _internalLogBuffer.push_back({"info", std::vector<std::pair<std::string, std::string>>()});
32 _internalLogBuffer.push_back({"warn", std::vector<std::pair<std::string, std::string>>()});
33 _internalLogBuffer.push_back({"error", std::vector<std::pair<std::string, std::string>>()});
34 _internalLogBuffer.push_back({"critical", std::vector<std::pair<std::string, std::string>>()});
35
36 // Prepare information (Loki limits maximum number of labels with 15)
37 _basicInformation = "";
38 _basicInformation += std::string(R"("release_version":"v)") + PROJECT_FULL_REVISION + "\",";
39 _basicInformation += std::string(R"("release_date":")") + PROJECT_BUILD_DATE + " " + PROJECT_BUILD_TIME + "\",";
40 _basicInformation += std::string(R"("compiler_name":")") + COMPILER_NAME + "\",";
41 _basicInformation += std::string(R"("compiler_version":")") + COMPILER_VERSION + "\",";
42 _basicInformation += std::string(R"("build":")") + BUILD_TYPE + "\",";
43
44 // Parse hostname
45 std::array<char, BUFSIZ> hostBuffer{};
46 gethostname(hostBuffer.data(), BUFSIZ);
47 _basicInformation += std::string(R"("hostname":")") + hostBuffer.data() + "\",";
48
49 // Parse CPU information
50 const std::filesystem::path cpuInfoPath = "/proc/cpuinfo";
51 std::string word;
52
53 findFromFile(cpuInfoPath, "^siblings", word);
54 _basicInformation += std::string(R"("cpu_threadcount":")") + word + "\",";
55 findFromFile(cpuInfoPath, "^(cpu cores)", word);
56 _basicInformation += std::string(R"("cpu_corecount":")") + word + "\",";
57 findFromFile(cpuInfoPath, "^(model name)", word);
58 _basicInformation += std::string(R"("cpu_model":")") + word + "\",";
59 findFromFile(cpuInfoPath, "^vendor_id", word);
60 _basicInformation += std::string(R"("cpu_vendorid":")") + word + "\",";
61
62 _lokiAvailable = true;
63 }
64
65 template <typename Mutex> loki_api_sink<Mutex>::~loki_api_sink() = default;
66
67 template <typename Mutex> void loki_api_sink<Mutex>::sink_it_(const details::log_msg &msg)
68 {
69 if (!_lokiAvailable)
70 {
71 return;
72 }
73
74 if (msg.level >= spdlog::level::debug && msg.level <= spdlog::level::critical)
75 {
76 _internalLogBuffer[static_cast<size_t>(msg.level) - 1].logs.push_back(
77 {std::to_string(msg.time.time_since_epoch().count()),
78 std::string(msg.payload.data(), msg.payload.size())});
79 }
80 }
81
82 template <typename Mutex> void loki_api_sink<Mutex>::flush_()
83 {
84 bool flag = false;
85
86 // Prepare JSON
87 std::ostringstream sStream;
88
89 sStream << "{\"streams\":[";
90 for (auto &entry : _internalLogBuffer)
91 {
92 if (entry.logs.empty())
93 {
94 continue;
95 }
96
97 if (flag)
98 {
99 sStream << ",";
100 }
101 flag = true;
102 sStream << "{\"stream\":{" << _basicInformation + R"("level":")" << entry.level << R"("},"values":[)";
103
104 bool subflag = false;
105 for (const auto &subentry : entry.logs)
106 {
107 if (subflag)
108 {
109 sStream << ",";
110 }
111 subflag = true;
112 sStream << "[\"" << subentry.first << "\",\"" << subentry.second << "\"]";
113 }
114 sStream << "]}";
115
116 entry.logs.clear();
117 }
118 sStream << "]}";
119
120 if (flag)
121 {
122 // Send request
123 std::string recvData;
124 HttpStatus::Code replyCode = HttpStatus::Code::xxx_max;
125 _connHandler->sendPOSTRequest("/loki/api/v1/push", sStream.str(), recvData, replyCode);
126 }
127 }
128
129 template class loki_api_sink<std::mutex>;
131} // namespace spdlog::sinks
std::vector< std::string > findFromFile(const std::filesystem::path &filePath, const std::string &pattern, std::string &lastWord)
std::unique_ptr< HTTP > _connHandler
Definition Loki.hpp:59
void flush_() override
Definition Loki.cpp:82
std::vector< struct logInfo_t > _internalLogBuffer
Definition Loki.hpp:66
void sink_it_(const details::log_msg &msg) override
Definition Loki.cpp:67
loki_api_sink(const std::string &lokiAddress)
Definition Loki.cpp:20