master
cc 258 lines 7.36 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include <snappy.h>
4 #include "src/exporting/prometheus/remote_write/remote_write.pb.h"
5 #include "remote_write_request.h"
6
7 using namespace prometheus;
8
9 google::protobuf::Arena arena;
10
11 /**
12 * Initialize a write request
13 *
14 * @return Returns a new write request
15 */
16 void *init_write_request()
17 {
18 GOOGLE_PROTOBUF_VERIFY_VERSION;
19 WriteRequest *write_request = google::protobuf::Arena::Create<WriteRequest>(&arena);
20 return (void *)write_request;
21 }
22
23 /**
24 * Adds information about a host to a write request
25 *
26 * @param write_request_p the write request
27 * @param name the name of a metric which is used for providing the host information
28 * @param instance the name of the host itself
29 * @param application the name of a program which sends the information
30 * @param version the version of the program
31 * @param timestamp the timestamp for the metric in milliseconds
32 */
33 void add_host_info(
34 void *write_request_p,
35 const char *name, const char *instance, const char *application, const char *version, const int64_t timestamp)
36 {
37 WriteRequest *write_request = (WriteRequest *)write_request_p;
38 TimeSeries *timeseries;
39 Sample *sample;
40 Label *label;
41
42 timeseries = write_request->add_timeseries();
43
44 label = timeseries->add_labels();
45 label->set_name("__name__");
46 label->set_value(name);
47
48 if (application) {
49 label = timeseries->add_labels();
50 label->set_name("application");
51 label->set_value(application);
52 }
53
54 label = timeseries->add_labels();
55 label->set_name("instance");
56 label->set_value(instance);
57
58 if (version) {
59 label = timeseries->add_labels();
60 label->set_name("version");
61 label->set_value(version);
62 }
63
64 sample = timeseries->add_samples();
65 sample->set_value(1);
66 sample->set_timestamp(timestamp);
67 }
68
69 /**
70 * Adds a label to the last created timeseries
71 *
72 * @param write_request_p the write request with the timeseries
73 * @param key the key of the label
74 * @param value the value of the label
75 */
76 void add_label(void *write_request_p, char *key, char *value)
77 {
78 WriteRequest *write_request = (WriteRequest *)write_request_p;
79 TimeSeries *timeseries;
80 Label *label;
81
82 timeseries = write_request->mutable_timeseries(write_request->timeseries_size() - 1);
83
84 label = timeseries->add_labels();
85 label->set_name(key);
86 label->set_value(value);
87 }
88
89 /**
90 * Adds a metric to a write request
91 *
92 * @param write_request_p the write request
93 * @param name the name of the metric
94 * @param chart the chart, the metric belongs to
95 * @param family the family, the metric belongs to
96 * @param dimension the dimension, the metric belongs to
97 * @param instance the name of the host, the metric belongs to
98 * @param value the value of the metric
99 * @param timestamp the timestamp for the metric in milliseconds
100 */
101 void add_metric(
102 void *write_request_p,
103 const char *name, const char *chart, const char *family, const char *dimension, const char *instance,
104 const double value, const int64_t timestamp)
105 {
106 WriteRequest *write_request = (WriteRequest *)write_request_p;
107 TimeSeries *timeseries;
108 Sample *sample;
109 Label *label;
110
111 timeseries = write_request->add_timeseries();
112
113 label = timeseries->add_labels();
114 label->set_name("__name__");
115 label->set_value(name);
116
117 label = timeseries->add_labels();
118 label->set_name("chart");
119 label->set_value(chart);
120
121 if (dimension) {
122 label = timeseries->add_labels();
123 label->set_name("dimension");
124 label->set_value(dimension);
125 }
126
127 label = timeseries->add_labels();
128 label->set_name("family");
129 label->set_value(family);
130
131 label = timeseries->add_labels();
132 label->set_name("instance");
133 label->set_value(instance);
134
135 sample = timeseries->add_samples();
136 sample->set_value(value);
137 sample->set_timestamp(timestamp);
138 }
139
140 /**
141 * Adds a metric to a write request
142 *
143 * @param write_request_p the write request
144 * @param name the name of the metric
145 * @param instance the name of the host, the metric belongs to
146 * @param value the value of the metric
147 * @param timestamp the timestamp for the metric in milliseconds
148 */
149 void add_variable(
150 void *write_request_p, const char *name, const char *instance, const double value, const int64_t timestamp)
151 {
152 WriteRequest *write_request = (WriteRequest *)write_request_p;
153 TimeSeries *timeseries;
154 Sample *sample;
155 Label *label;
156
157 timeseries = write_request->add_timeseries();
158
159 label = timeseries->add_labels();
160 label->set_name("__name__");
161 label->set_value(name);
162
163 label = timeseries->add_labels();
164 label->set_name("instance");
165 label->set_value(instance);
166
167 sample = timeseries->add_samples();
168 sample->set_value(value);
169 sample->set_timestamp(timestamp);
170 }
171
172 /**
173 * Gets the size of a write request
174 *
175 * @param write_request_p the write request
176 * @return Returns the size of the write request
177 */
178 size_t get_write_request_size(void *write_request_p)
179 {
180 WriteRequest *write_request = (WriteRequest *)write_request_p;
181
182 #if GOOGLE_PROTOBUF_VERSION < 3001000
183 size_t size = (size_t)snappy::MaxCompressedLength(write_request->ByteSize());
184 #else
185 size_t size = (size_t)snappy::MaxCompressedLength(write_request->ByteSizeLong());
186 #endif
187
188 return (size < INT_MAX) ? size : 0;
189 }
190
191 /**
192 * Packs a write request into a buffer and clears the request
193 *
194 * @param write_request_p the write request
195 * @param buffer a buffer, where compressed data is written
196 * @param size gets the size of the write request, returns the size of the compressed data
197 * @return Returns 0 on success, 1 on failure
198 */
199 int pack_and_clear_write_request(void *write_request_p, char *buffer, size_t *size)
200 {
201 WriteRequest *write_request = (WriteRequest *)write_request_p;
202 std::string uncompressed_write_request;
203
204 if (write_request->SerializeToString(&uncompressed_write_request) == false)
205 return 1;
206 write_request->clear_timeseries();
207 snappy::RawCompress(uncompressed_write_request.data(), uncompressed_write_request.size(), buffer, size);
208
209 return 0;
210 }
211
212 /**
213 * Writes an unpacked write request into a text buffer
214 *
215 * @param write_request_p the write request
216 * @param buffer a buffer, where text is written
217 * @param size the size of the buffer
218 * @return Returns 0 on success, 1 on failure
219 */
220 int convert_write_request_to_string(
221 const char *compressed_write_request,
222 size_t compressed_size,
223 char *buffer,
224 size_t size)
225 {
226 size_t uncompressed_size = 0;
227
228 snappy::GetUncompressedLength(compressed_write_request, compressed_size, &uncompressed_size);
229 if (size < uncompressed_size)
230 return 1;
231 char *uncompressed_write_request = (char *)malloc(size);
232
233 if (snappy::RawUncompress(compressed_write_request, compressed_size, uncompressed_write_request) == false) {
234 free(uncompressed_write_request);
235 return 1;
236 }
237
238 WriteRequest *write_request = google::protobuf::Arena::Create<WriteRequest>(&arena);
239 if (write_request->ParseFromString(std::string(uncompressed_write_request, uncompressed_size)) == false) {
240 free(uncompressed_write_request);
241 return 1;
242 }
243
244 std::string text_write_request(write_request->DebugString());
245 text_write_request.copy(buffer, size);
246
247 free(uncompressed_write_request);
248
249 return 0;
250 }
251
252 /**
253 * Shuts down the Protobuf library
254 */
255 void protocol_buffers_shutdown()
256 {
257 google::protobuf::ShutdownProtobufLibrary();
258 }