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