/src/fluent-bit/plugins/in_opentelemetry/opentelemetry_prot.c
Line | Count | Source |
1 | | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* Fluent Bit |
4 | | * ========== |
5 | | * Copyright (C) 2015-2026 The Fluent Bit Authors |
6 | | * |
7 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | * you may not use this file except in compliance with the License. |
9 | | * You may obtain a copy of the License at |
10 | | * |
11 | | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | * |
13 | | * Unless required by applicable law or agreed to in writing, software |
14 | | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | | * See the License for the specific language governing permissions and |
17 | | * limitations under the License. |
18 | | */ |
19 | | |
20 | | #include <fluent-bit/flb_input_plugin.h> |
21 | | #include <fluent-bit/flb_version.h> |
22 | | #include <fluent-bit/flb_error.h> |
23 | | #include <fluent-bit/flb_pack.h> |
24 | | #include <fluent-bit/flb_time.h> |
25 | | #include <fluent-bit/flb_gzip.h> |
26 | | #include <fluent-bit/flb_snappy.h> |
27 | | #include <fluent-bit/flb_zstd.h> |
28 | | #include <fluent-bit/flb_mp.h> |
29 | | #include <fluent-bit/flb_log_event_encoder.h> |
30 | | #include <fluent-bit/flb_opentelemetry.h> |
31 | | |
32 | | #include <fluent-bit/http_server/flb_http_server.h> |
33 | | |
34 | | #include <cmetrics/cmt_decode_opentelemetry.h> |
35 | | #include <cprofiles/cprof_decode_opentelemetry.h> |
36 | | #include <cprofiles/cprof_encode_text.h> |
37 | | |
38 | | #include <fluent-otel-proto/fluent-otel.h> |
39 | | |
40 | | |
41 | | #include "opentelemetry.h" |
42 | | #include "opentelemetry_utils.h" |
43 | | #include "opentelemetry_logs.h" |
44 | | #include "opentelemetry_traces.h" |
45 | | #include "opentelemetry_prot.h" |
46 | | |
47 | | #define HTTP_CONTENT_JSON 0 |
48 | | |
49 | | flb_sds_t opentelemetry_prot_create_request_tag(struct flb_opentelemetry *context, |
50 | | flb_sds_t uri_tag) |
51 | 0 | { |
52 | 0 | if (context->ins->tag_default == FLB_FALSE) { |
53 | 0 | return flb_sds_create(context->ins->tag); |
54 | 0 | } |
55 | | |
56 | 0 | if (context->tag_from_uri == FLB_TRUE) { |
57 | 0 | return flb_sds_create(uri_tag); |
58 | 0 | } |
59 | | |
60 | 0 | return flb_sds_create(context->ins->tag); |
61 | 0 | } |
62 | | |
63 | | static int is_profiles_export_path(const char *path) |
64 | 0 | { |
65 | 0 | if (path == NULL) { |
66 | 0 | return FLB_FALSE; |
67 | 0 | } |
68 | | |
69 | 0 | if (strcmp(path, "/opentelemetry.proto.collector.profiles.v1experimental.ProfilesService/Export") == 0 || |
70 | 0 | strcmp(path, "/opentelemetry.proto.collector.profiles.v1development.ProfilesService/Export") == 0) { |
71 | 0 | return FLB_TRUE; |
72 | 0 | } |
73 | | |
74 | 0 | return FLB_FALSE; |
75 | 0 | } |
76 | | |
77 | | static \ |
78 | | int uncompress_zlib(struct flb_opentelemetry *ctx, |
79 | | char **output_buffer, |
80 | | size_t *output_size, |
81 | | char *input_buffer, |
82 | | size_t input_size) |
83 | 0 | { |
84 | 0 | flb_plg_warn(ctx->ins, "zlib decompression is not supported"); |
85 | 0 | return -1; |
86 | 0 | } |
87 | | |
88 | | static \ |
89 | | int uncompress_zstd(struct flb_opentelemetry *ctx, |
90 | | char **output_buffer, |
91 | | size_t *output_size, |
92 | | char *input_buffer, |
93 | | size_t input_size) |
94 | 0 | { |
95 | 0 | int ret; |
96 | |
|
97 | 0 | ret = flb_zstd_uncompress(input_buffer, |
98 | 0 | input_size, |
99 | 0 | (void *) output_buffer, |
100 | 0 | output_size); |
101 | |
|
102 | 0 | if (ret != 0) { |
103 | 0 | flb_plg_error(ctx->ins, "zstd decompression failed"); |
104 | 0 | return -1; |
105 | 0 | } |
106 | | |
107 | 0 | return 1; |
108 | 0 | } |
109 | | |
110 | | static \ |
111 | | int uncompress_deflate(struct flb_opentelemetry *ctx, |
112 | | char **output_buffer, |
113 | | size_t *output_size, |
114 | | char *input_buffer, |
115 | | size_t input_size) |
116 | 0 | { |
117 | 0 | flb_plg_warn(ctx->ins, "deflate decompression is not supported"); |
118 | 0 | return -1; |
119 | 0 | } |
120 | | |
121 | | static \ |
122 | | int uncompress_snappy(struct flb_opentelemetry *ctx, |
123 | | char **output_buffer, |
124 | | size_t *output_size, |
125 | | char *input_buffer, |
126 | | size_t input_size) |
127 | 0 | { |
128 | 0 | int ret; |
129 | |
|
130 | 0 | ret = flb_snappy_uncompress_framed_data(input_buffer, |
131 | 0 | input_size, |
132 | 0 | output_buffer, |
133 | 0 | output_size); |
134 | |
|
135 | 0 | if (ret != 0) { |
136 | 0 | flb_plg_error(ctx->ins, "snappy decompression failed"); |
137 | 0 | return -1; |
138 | 0 | } |
139 | | |
140 | 0 | return 1; |
141 | 0 | } |
142 | | |
143 | | static \ |
144 | | int uncompress_gzip(struct flb_opentelemetry *ctx, |
145 | | char **output_buffer, |
146 | | size_t *output_size, |
147 | | char *input_buffer, |
148 | | size_t input_size) |
149 | 0 | { |
150 | 0 | int ret; |
151 | |
|
152 | 0 | ret = flb_gzip_uncompress(input_buffer, |
153 | 0 | input_size, |
154 | 0 | (void *) output_buffer, |
155 | 0 | output_size); |
156 | |
|
157 | 0 | if (ret == -1) { |
158 | 0 | flb_error("[opentelemetry] gzip decompression failed"); |
159 | |
|
160 | 0 | return -1; |
161 | 0 | } |
162 | | |
163 | 0 | return 1; |
164 | 0 | } |
165 | | |
166 | | /* |
167 | | * We use two backends for HTTP parsing and it depends on the version of the |
168 | | * protocol: |
169 | | * |
170 | | * http/1.x: we use Monkey HTTP parser: struct mk_http_session.parser |
171 | | * http/2.x: we use nghttp2: struct flb_http_request |
172 | | * |
173 | | * based on the protocol version we need to handle the header lookup differently. |
174 | | */ |
175 | | static int http_header_lookup(int version, void *ptr, char *key, |
176 | | char **val, size_t *val_len) |
177 | 0 | { |
178 | 0 | int key_len; |
179 | | |
180 | | /* HTTP/1.1 */ |
181 | 0 | struct mk_list *head; |
182 | 0 | struct mk_http_session *session; |
183 | 0 | struct mk_http_request *request_11; |
184 | 0 | struct mk_http_header *header; |
185 | | |
186 | | /* HTTP/2.0 */ |
187 | 0 | char *value; |
188 | 0 | struct flb_http_request *request_20; |
189 | |
|
190 | 0 | if (!key) { |
191 | 0 | return -1; |
192 | 0 | } |
193 | | |
194 | 0 | key_len = strlen(key); |
195 | 0 | if (key_len <= 0) { |
196 | 0 | return -1; |
197 | 0 | } |
198 | | |
199 | 0 | if (version <= HTTP_PROTOCOL_VERSION_11) { |
200 | 0 | if (!ptr) { |
201 | 0 | return -1; |
202 | 0 | } |
203 | | |
204 | 0 | request_11 = (struct mk_http_request *) ptr; |
205 | 0 | session = request_11->session; |
206 | 0 | mk_list_foreach(head, &session->parser.header_list) { |
207 | 0 | header = mk_list_entry(head, struct mk_http_header, _head); |
208 | 0 | if (header->key.len == key_len && |
209 | 0 | strncasecmp(header->key.data, key, key_len) == 0) { |
210 | 0 | *val = header->val.data; |
211 | 0 | *val_len = header->val.len; |
212 | 0 | return 0; |
213 | 0 | } |
214 | 0 | } |
215 | 0 | return -1; |
216 | 0 | } |
217 | 0 | else if (version == HTTP_PROTOCOL_VERSION_20) { |
218 | 0 | request_20 = ptr; |
219 | 0 | if (!request_20) { |
220 | 0 | return -1; |
221 | 0 | } |
222 | | |
223 | 0 | value = flb_http_request_get_header(request_20, key); |
224 | 0 | if (!value) { |
225 | 0 | return -1; |
226 | 0 | } |
227 | | |
228 | 0 | *val = value; |
229 | 0 | *val_len = strlen(value); |
230 | 0 | return 0; |
231 | 0 | } |
232 | | |
233 | 0 | return -1; |
234 | 0 | } |
235 | | |
236 | | /* New gen HTTP server */ |
237 | | static int send_response_ng(struct flb_http_response *response, |
238 | | int http_status, |
239 | | char *message) |
240 | 0 | { |
241 | 0 | flb_http_response_set_status(response, http_status); |
242 | |
|
243 | 0 | if (http_status == 201) { |
244 | 0 | flb_http_response_set_message(response, "Created"); |
245 | 0 | } |
246 | 0 | else if (http_status == 200) { |
247 | 0 | flb_http_response_set_message(response, "OK"); |
248 | 0 | } |
249 | 0 | else if (http_status == 204) { |
250 | 0 | flb_http_response_set_message(response, "No Content"); |
251 | 0 | } |
252 | 0 | else if (http_status == 400) { |
253 | 0 | flb_http_response_set_message(response, "Bad Request"); |
254 | 0 | } |
255 | 0 | else if (http_status == 404) { |
256 | 0 | flb_http_response_set_message(response, "Not Found"); |
257 | 0 | } |
258 | |
|
259 | 0 | if (message != NULL) { |
260 | 0 | flb_http_response_set_body(response, |
261 | 0 | (unsigned char *) message, |
262 | 0 | strlen(message)); |
263 | 0 | } |
264 | |
|
265 | 0 | flb_http_response_commit(response); |
266 | |
|
267 | 0 | return 0; |
268 | 0 | } |
269 | | |
270 | | static int send_grpc_response_ng(struct flb_http_response *response, |
271 | | uint8_t *message_buffer, |
272 | | size_t message_length, |
273 | | int grpc_status, |
274 | | char *grpc_message) |
275 | 0 | { |
276 | 0 | char grpc_status_as_string[16]; |
277 | 0 | uint32_t wire_message_length; |
278 | 0 | size_t body_buffer_size; |
279 | 0 | cfl_sds_t body_buffer; |
280 | |
|
281 | 0 | body_buffer_size = 5 + message_length; |
282 | |
|
283 | 0 | if (body_buffer_size < 65) { |
284 | 0 | body_buffer_size = 65; |
285 | 0 | } |
286 | |
|
287 | 0 | body_buffer = cfl_sds_create_size(body_buffer_size); |
288 | |
|
289 | 0 | if (body_buffer == NULL) { |
290 | 0 | return -1; |
291 | 0 | } |
292 | | |
293 | 0 | sprintf(grpc_status_as_string, "%u", grpc_status); |
294 | |
|
295 | 0 | wire_message_length = (uint32_t) message_length; |
296 | |
|
297 | 0 | cfl_sds_cat_safe(&body_buffer, "\x00----", 5); |
298 | |
|
299 | 0 | ((uint8_t *) body_buffer)[1] = (wire_message_length & 0xFF000000) >> 24; |
300 | 0 | ((uint8_t *) body_buffer)[2] = (wire_message_length & 0x00FF0000) >> 16; |
301 | 0 | ((uint8_t *) body_buffer)[3] = (wire_message_length & 0x0000FF00) >> 8; |
302 | 0 | ((uint8_t *) body_buffer)[4] = (wire_message_length & 0x000000FF) >> 0; |
303 | |
|
304 | 0 | if (message_buffer != NULL) { |
305 | 0 | cfl_sds_cat_safe(&body_buffer, (char *) message_buffer, message_length); |
306 | 0 | } |
307 | |
|
308 | 0 | flb_http_response_set_status(response, 200); |
309 | |
|
310 | 0 | flb_http_response_set_body(response, |
311 | 0 | (unsigned char *) body_buffer, |
312 | 0 | 5 + message_length); |
313 | |
|
314 | 0 | flb_http_response_set_header(response, |
315 | 0 | "content-type", 0, |
316 | 0 | "application/grpc", 0); |
317 | |
|
318 | 0 | flb_http_response_set_trailer_header(response, |
319 | 0 | "grpc-status", 0, |
320 | 0 | grpc_status_as_string, 0); |
321 | |
|
322 | 0 | flb_http_response_set_trailer_header(response, |
323 | 0 | "grpc-message", 0, |
324 | 0 | grpc_message, 0); |
325 | |
|
326 | 0 | flb_http_response_commit(response); |
327 | |
|
328 | 0 | cfl_sds_destroy(body_buffer); |
329 | |
|
330 | 0 | return 0; |
331 | 0 | } |
332 | | |
333 | | static int send_grpc_error_response_ng(struct flb_http_response *response, |
334 | | int grpc_status, |
335 | | const char *grpc_message) |
336 | 0 | { |
337 | 0 | const char *message; |
338 | |
|
339 | 0 | message = grpc_message != NULL ? grpc_message : ""; |
340 | |
|
341 | 0 | return send_grpc_response_ng(response, NULL, 0, grpc_status, (char *) message); |
342 | 0 | } |
343 | | |
344 | | static int send_export_logs_service_response_ng(struct flb_http_response *response, |
345 | | int status) |
346 | 0 | { |
347 | 0 | uint8_t *message_buffer; |
348 | 0 | size_t message_length; |
349 | 0 | const char *grpc_message; |
350 | 0 | int grpc_status; |
351 | 0 | Opentelemetry__Proto__Collector__Logs__V1__ExportLogsServiceResponse message; |
352 | |
|
353 | 0 | if (status == 0) { |
354 | 0 | opentelemetry__proto__collector__logs__v1__export_logs_service_response__init(&message); |
355 | |
|
356 | 0 | message_length = opentelemetry__proto__collector__logs__v1__export_logs_service_response__get_packed_size(&message); |
357 | |
|
358 | 0 | message_buffer = flb_calloc(message_length, sizeof(uint8_t)); |
359 | 0 | if (message_buffer == NULL) { |
360 | 0 | return -1; |
361 | 0 | } |
362 | | |
363 | 0 | opentelemetry__proto__collector__logs__v1__export_logs_service_response__pack(&message, message_buffer); |
364 | |
|
365 | 0 | grpc_status = 0; |
366 | 0 | grpc_message = ""; |
367 | 0 | } |
368 | 0 | else { |
369 | 0 | grpc_status = 2; /* gRPC UNKNOWN */ |
370 | 0 | grpc_message = "Serialization error."; |
371 | 0 | message_buffer = NULL; |
372 | 0 | message_length = 0; |
373 | 0 | } |
374 | | |
375 | 0 | send_grpc_response_ng(response, message_buffer, message_length, grpc_status, (char *) grpc_message); |
376 | |
|
377 | 0 | if (message_buffer != NULL) { |
378 | 0 | flb_free(message_buffer); |
379 | 0 | } |
380 | |
|
381 | 0 | return 0; |
382 | 0 | } |
383 | | |
384 | | static int send_export_metrics_service_response_ng(struct flb_http_response *response, |
385 | | int status) |
386 | 0 | { |
387 | 0 | uint8_t *message_buffer; |
388 | 0 | size_t message_length; |
389 | 0 | const char *grpc_message; |
390 | 0 | int grpc_status; |
391 | 0 | Opentelemetry__Proto__Collector__Metrics__V1__ExportMetricsServiceResponse message; |
392 | |
|
393 | 0 | if (status == 0) { |
394 | 0 | opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__init(&message); |
395 | |
|
396 | 0 | message_length = opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__get_packed_size(&message); |
397 | |
|
398 | 0 | message_buffer = flb_calloc(message_length, sizeof(uint8_t)); |
399 | |
|
400 | 0 | if (message_buffer == NULL) { |
401 | 0 | return -1; |
402 | 0 | } |
403 | | |
404 | 0 | opentelemetry__proto__collector__metrics__v1__export_metrics_service_response__pack(&message, message_buffer); |
405 | |
|
406 | 0 | grpc_status = 0; |
407 | 0 | grpc_message = "-"; |
408 | 0 | } |
409 | 0 | else { |
410 | 0 | grpc_status = 2; /* gRPC UNKNOWN */ |
411 | 0 | grpc_message = "Serialization error."; |
412 | 0 | message_buffer = NULL; |
413 | 0 | message_length = 0; |
414 | 0 | } |
415 | | |
416 | 0 | send_grpc_response_ng(response, message_buffer, message_length, grpc_status, (char *) grpc_message); |
417 | |
|
418 | 0 | if (message_buffer != NULL) { |
419 | 0 | flb_free(message_buffer); |
420 | 0 | } |
421 | |
|
422 | 0 | return 0; |
423 | 0 | } |
424 | | |
425 | | static int send_export_traces_service_response_ng(struct flb_http_response *response, |
426 | | int status) |
427 | 0 | { |
428 | 0 | uint8_t *message_buffer; |
429 | 0 | size_t message_length; |
430 | 0 | const char *grpc_message; |
431 | 0 | int grpc_status; |
432 | 0 | Opentelemetry__Proto__Collector__Trace__V1__ExportTraceServiceResponse message; |
433 | |
|
434 | 0 | if (status == 0) { |
435 | 0 | opentelemetry__proto__collector__trace__v1__export_trace_service_response__init(&message); |
436 | |
|
437 | 0 | message_length = opentelemetry__proto__collector__trace__v1__export_trace_service_response__get_packed_size(&message); |
438 | |
|
439 | 0 | message_buffer = flb_calloc(message_length, sizeof(uint8_t)); |
440 | |
|
441 | 0 | if (message_buffer == NULL) { |
442 | 0 | return -1; |
443 | 0 | } |
444 | | |
445 | 0 | opentelemetry__proto__collector__trace__v1__export_trace_service_response__pack(&message, message_buffer); |
446 | |
|
447 | 0 | grpc_status = 0; |
448 | 0 | grpc_message = "-"; |
449 | 0 | } |
450 | 0 | else { |
451 | 0 | grpc_status = 2; /* gRPC UNKNOWN */ |
452 | 0 | grpc_message = "Serialization error."; |
453 | 0 | message_buffer = NULL; |
454 | 0 | message_length = 0; |
455 | 0 | } |
456 | | |
457 | 0 | send_grpc_response_ng(response, message_buffer, message_length, grpc_status, (char *) grpc_message); |
458 | |
|
459 | 0 | if (message_buffer != NULL) { |
460 | 0 | flb_free(message_buffer); |
461 | 0 | } |
462 | |
|
463 | 0 | return 0; |
464 | 0 | } |
465 | | |
466 | | static int send_export_profiles_service_response_ng(struct flb_http_response *response, |
467 | | int status) |
468 | 0 | { |
469 | 0 | uint8_t *message_buffer; |
470 | 0 | size_t message_length; |
471 | 0 | const char *grpc_message; |
472 | 0 | int grpc_status; |
473 | 0 | Opentelemetry__Proto__Collector__Profiles__V1development__ExportProfilesServiceResponse message; |
474 | |
|
475 | 0 | if (status == 0) { |
476 | 0 | opentelemetry__proto__collector__profiles__v1development__export_profiles_service_response__init(&message); |
477 | |
|
478 | 0 | message_length = opentelemetry__proto__collector__profiles__v1development__export_profiles_service_response__get_packed_size(&message); |
479 | |
|
480 | 0 | message_buffer = flb_calloc(message_length, sizeof(uint8_t)); |
481 | 0 | if (message_buffer == NULL) { |
482 | 0 | return -1; |
483 | 0 | } |
484 | | |
485 | 0 | opentelemetry__proto__collector__profiles__v1development__export_profiles_service_response__pack(&message, message_buffer); |
486 | |
|
487 | 0 | grpc_status = 0; |
488 | 0 | grpc_message = "-"; |
489 | 0 | } |
490 | 0 | else { |
491 | 0 | grpc_status = 2; /* gRPC UNKNOWN */ |
492 | 0 | grpc_message = "Serialization error."; |
493 | 0 | message_buffer = NULL; |
494 | 0 | message_length = 0; |
495 | 0 | } |
496 | | |
497 | 0 | send_grpc_response_ng(response, message_buffer, message_length, grpc_status, (char *) grpc_message); |
498 | |
|
499 | 0 | if (message_buffer != NULL) { |
500 | 0 | flb_free(message_buffer); |
501 | 0 | } |
502 | |
|
503 | 0 | return 0; |
504 | 0 | } |
505 | | |
506 | | static int process_payload_metrics_ng(struct flb_opentelemetry *ctx, |
507 | | flb_sds_t tag, |
508 | | struct flb_http_request *request, |
509 | | char *payload, size_t payload_size) |
510 | | |
511 | 0 | { |
512 | 0 | struct cfl_list decoded_contexts; |
513 | 0 | struct cfl_list *iterator; |
514 | 0 | struct cfl_list *tmp; |
515 | 0 | struct cmt *context; |
516 | 0 | size_t offset; |
517 | 0 | int result = -1; |
518 | |
|
519 | 0 | offset = 0; |
520 | | |
521 | | /* note: if the content type is gRPC, it was already decoded */ |
522 | 0 | if (opentelemetry_is_json_content_type(request->content_type) == FLB_TRUE) { |
523 | 0 | result = flb_opentelemetry_metrics_json_to_cmt(&decoded_contexts, |
524 | 0 | payload, |
525 | 0 | payload_size); |
526 | 0 | } |
527 | 0 | else if (opentelemetry_is_protobuf_content_type(request->content_type) == |
528 | 0 | FLB_TRUE) { |
529 | 0 | result = cmt_decode_opentelemetry_create(&decoded_contexts, |
530 | 0 | payload, |
531 | 0 | payload_size, |
532 | 0 | &offset); |
533 | 0 | } |
534 | 0 | else { |
535 | 0 | flb_plg_error(ctx->ins, "Unsupported content type %s", request->content_type); |
536 | 0 | return -1; |
537 | 0 | } |
538 | | |
539 | 0 | if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) { |
540 | 0 | if (opentelemetry_uses_worker_ingress_queue(ctx)) { |
541 | 0 | result = flb_input_ingress_queue_metrics_list(ctx->ins, |
542 | 0 | tag, |
543 | 0 | cfl_sds_len(tag), |
544 | 0 | &decoded_contexts, |
545 | 0 | payload_size); |
546 | 0 | if (result == FLB_INPUT_INGRESS_BUSY) { |
547 | 0 | return FLB_INPUT_INGRESS_BUSY; |
548 | 0 | } |
549 | 0 | else if (result != 0) { |
550 | 0 | flb_plg_debug(ctx->ins, |
551 | 0 | "could not queue metrics contexts : %d", result); |
552 | 0 | return -1; |
553 | 0 | } |
554 | | |
555 | 0 | return 0; |
556 | 0 | } |
557 | | |
558 | 0 | cfl_list_foreach_safe(iterator, tmp, &decoded_contexts) { |
559 | 0 | context = cfl_list_entry(iterator, struct cmt, _head); |
560 | |
|
561 | 0 | result = opentelemetry_ingest_metrics(ctx, |
562 | 0 | tag, |
563 | 0 | cfl_sds_len(tag), |
564 | 0 | context, |
565 | 0 | payload_size); |
566 | |
|
567 | 0 | if (result == FLB_INPUT_INGRESS_BUSY) { |
568 | 0 | cmt_decode_opentelemetry_destroy(&decoded_contexts); |
569 | 0 | return FLB_INPUT_INGRESS_BUSY; |
570 | 0 | } |
571 | 0 | else if (result != 0) { |
572 | 0 | flb_plg_debug(ctx->ins, "could not ingest metrics context : %d", result); |
573 | 0 | } |
574 | 0 | } |
575 | | |
576 | 0 | cmt_decode_opentelemetry_destroy(&decoded_contexts); |
577 | 0 | } |
578 | 0 | else { |
579 | 0 | flb_plg_warn(ctx->ins, "non-success cmetrics opentelemetry decode result %d", result); |
580 | 0 | return -1; |
581 | 0 | } |
582 | | |
583 | 0 | return 0; |
584 | 0 | } |
585 | | |
586 | | static int ingest_profiles_context_as_log_entry(struct flb_opentelemetry *ctx, |
587 | | flb_sds_t tag, |
588 | | struct cprof *profiles_context) |
589 | 0 | { |
590 | 0 | cfl_sds_t text_encoded_profiles_context; |
591 | 0 | struct flb_log_event_encoder *encoder; |
592 | 0 | int ret; |
593 | |
|
594 | 0 | encoder = flb_log_event_encoder_create(FLB_LOG_EVENT_FORMAT_FLUENT_BIT_V2); |
595 | |
|
596 | 0 | if (encoder == NULL) { |
597 | 0 | return -1; |
598 | 0 | } |
599 | | |
600 | 0 | ret = cprof_encode_text_create(&text_encoded_profiles_context, |
601 | 0 | profiles_context, |
602 | 0 | CPROF_ENCODE_TEXT_RENDER_DICTIONARIES_AND_INDEXES); |
603 | |
|
604 | 0 | if (ret != CPROF_ENCODE_TEXT_SUCCESS) { |
605 | 0 | flb_log_event_encoder_destroy(encoder); |
606 | |
|
607 | 0 | return -2; |
608 | 0 | } |
609 | | |
610 | 0 | flb_log_event_encoder_begin_record(encoder); |
611 | |
|
612 | 0 | flb_log_event_encoder_set_current_timestamp(encoder); |
613 | |
|
614 | 0 | ret = flb_log_event_encoder_append_body_values( |
615 | 0 | encoder, |
616 | 0 | FLB_LOG_EVENT_CSTRING_VALUE("Profile"), |
617 | 0 | FLB_LOG_EVENT_STRING_VALUE(text_encoded_profiles_context, |
618 | 0 | cfl_sds_len(text_encoded_profiles_context))); |
619 | |
|
620 | 0 | cprof_encode_text_destroy(text_encoded_profiles_context); |
621 | |
|
622 | 0 | if (ret != FLB_EVENT_ENCODER_SUCCESS) { |
623 | 0 | flb_log_event_encoder_destroy(encoder); |
624 | |
|
625 | 0 | return -3; |
626 | 0 | } |
627 | | |
628 | 0 | ret = flb_log_event_encoder_commit_record(encoder); |
629 | |
|
630 | 0 | if (ret != FLB_EVENT_ENCODER_SUCCESS) { |
631 | 0 | flb_log_event_encoder_destroy(encoder); |
632 | |
|
633 | 0 | return -4; |
634 | 0 | } |
635 | | |
636 | 0 | if (opentelemetry_uses_worker_ingress_queue(ctx)) { |
637 | 0 | size_t allocation_size; |
638 | 0 | void *resized_buffer; |
639 | |
|
640 | 0 | allocation_size = encoder->buffer.alloc; |
641 | |
|
642 | 0 | if (allocation_size > encoder->output_length) { |
643 | 0 | resized_buffer = flb_realloc(encoder->output_buffer, |
644 | 0 | encoder->output_length); |
645 | 0 | if (resized_buffer != NULL) { |
646 | 0 | encoder->buffer.data = resized_buffer; |
647 | 0 | encoder->output_buffer = resized_buffer; |
648 | 0 | encoder->buffer.alloc = encoder->output_length; |
649 | 0 | allocation_size = encoder->output_length; |
650 | 0 | } |
651 | 0 | } |
652 | |
|
653 | 0 | ret = opentelemetry_ingest_logs_take(ctx, |
654 | 0 | 0, |
655 | 0 | tag, |
656 | 0 | flb_sds_len(tag), |
657 | 0 | encoder->output_buffer, |
658 | 0 | encoder->output_length, |
659 | 0 | allocation_size); |
660 | 0 | flb_log_event_encoder_claim_internal_buffer_ownership(encoder); |
661 | 0 | } |
662 | 0 | else { |
663 | 0 | ret = opentelemetry_ingest_logs(ctx, |
664 | 0 | tag, |
665 | 0 | flb_sds_len(tag), |
666 | 0 | encoder->output_buffer, |
667 | 0 | encoder->output_length); |
668 | 0 | } |
669 | |
|
670 | 0 | flb_log_event_encoder_destroy(encoder); |
671 | |
|
672 | 0 | if (ret == FLB_INPUT_INGRESS_BUSY) { |
673 | 0 | return FLB_INPUT_INGRESS_BUSY; |
674 | 0 | } |
675 | | |
676 | 0 | if (ret != FLB_EVENT_ENCODER_SUCCESS) { |
677 | 0 | return -5; |
678 | 0 | } |
679 | | |
680 | 0 | return 0; |
681 | 0 | } |
682 | | |
683 | | static int process_payload_profiles_ng(struct flb_opentelemetry *ctx, |
684 | | flb_sds_t tag, |
685 | | struct flb_http_request *request, |
686 | | char *payload, |
687 | | size_t payload_size) |
688 | 0 | { |
689 | 0 | struct cprof *profiles_context; |
690 | 0 | size_t offset; |
691 | 0 | int ret; |
692 | |
|
693 | 0 | if (request->content_type == NULL) { |
694 | 0 | flb_error("[otel] content type missing"); |
695 | 0 | return -1; |
696 | 0 | } |
697 | 0 | else if (opentelemetry_is_json_content_type(request->content_type) == FLB_TRUE) { |
698 | 0 | flb_error("[otel] unsuported profiles encoding type : %s", |
699 | 0 | request->content_type); |
700 | |
|
701 | 0 | return -1; |
702 | 0 | } |
703 | 0 | else if (opentelemetry_is_protobuf_content_type(request->content_type) == |
704 | 0 | FLB_TRUE) { |
705 | 0 | profiles_context = NULL; |
706 | 0 | offset = 0; |
707 | |
|
708 | 0 | ret = cprof_decode_opentelemetry_create(&profiles_context, |
709 | 0 | (uint8_t *) payload, |
710 | 0 | payload_size, |
711 | 0 | &offset); |
712 | |
|
713 | 0 | if (ret != CPROF_DECODE_OPENTELEMETRY_SUCCESS) { |
714 | 0 | flb_error("[otel] profile decoding error : %d", |
715 | 0 | ret); |
716 | |
|
717 | 0 | return -1; |
718 | 0 | } |
719 | | |
720 | 0 | if (ctx->encode_profiles_as_log) { |
721 | 0 | ret = ingest_profiles_context_as_log_entry(ctx, |
722 | 0 | tag, |
723 | 0 | profiles_context); |
724 | |
|
725 | 0 | cprof_decode_opentelemetry_destroy(profiles_context); |
726 | 0 | } |
727 | 0 | else { |
728 | 0 | ret = opentelemetry_ingest_profiles(ctx, |
729 | 0 | tag, |
730 | 0 | flb_sds_len(tag), |
731 | 0 | profiles_context, |
732 | 0 | payload_size); |
733 | |
|
734 | 0 | if (!opentelemetry_uses_worker_ingress_queue(ctx)) { |
735 | 0 | cprof_decode_opentelemetry_destroy(profiles_context); |
736 | 0 | } |
737 | 0 | } |
738 | |
|
739 | 0 | if (ret == FLB_INPUT_INGRESS_BUSY) { |
740 | 0 | return ret; |
741 | 0 | } |
742 | | |
743 | 0 | if (ret != 0) { |
744 | 0 | flb_error("[otel] profile ingestion error : %d", |
745 | 0 | ret); |
746 | |
|
747 | 0 | return -1; |
748 | 0 | } |
749 | | |
750 | 0 | ret = 0; |
751 | 0 | } |
752 | 0 | else { |
753 | 0 | flb_plg_error(ctx->ins, "Unsupported content type %s", request->content_type); |
754 | |
|
755 | 0 | ret = -1; |
756 | 0 | } |
757 | | |
758 | 0 | return ret; |
759 | 0 | } |
760 | | |
761 | | static int send_export_service_response_ng(struct flb_http_response *response, |
762 | | int result, |
763 | | char payload_type) |
764 | 0 | { |
765 | 0 | switch (payload_type) { |
766 | 0 | case 'M': |
767 | 0 | return send_export_metrics_service_response_ng(response, result); |
768 | 0 | case 'T': |
769 | 0 | return send_export_traces_service_response_ng(response, result); |
770 | 0 | case 'L': |
771 | 0 | return send_export_logs_service_response_ng(response, result); |
772 | 0 | case 'P': |
773 | 0 | return send_export_profiles_service_response_ng(response, result); |
774 | 0 | default: |
775 | 0 | return -1; |
776 | 0 | } |
777 | 0 | } |
778 | | |
779 | | static int send_ingress_busy_response_ng(struct flb_http_response *response, |
780 | | int grpc_request) |
781 | 0 | { |
782 | 0 | if (grpc_request == FLB_TRUE) { |
783 | 0 | return send_grpc_error_response_ng(response, 14, "server overloaded"); |
784 | 0 | } |
785 | | |
786 | 0 | return send_response_ng(response, |
787 | 0 | 503, |
788 | 0 | "server overloaded: deferred ingress queue is full\n"); |
789 | 0 | } |
790 | | |
791 | | /* |
792 | | * Protocol handle for requests coming from HTTP/2 server backend. Note that |
793 | | * if the payload is compressed (Content-Encoding) it will be decompressed |
794 | | * before this function is called. |
795 | | * |
796 | | * For gRPC payloads where the gRPC message is compressed (do not confuse with |
797 | | * Content-Encoding), each message will be decompressed within this callback. |
798 | | */ |
799 | | int opentelemetry_prot_handle_ng(struct flb_http_request *request, |
800 | | struct flb_http_response *response) |
801 | 0 | { |
802 | 0 | int ret = -1; |
803 | 0 | size_t auth_len = 0; |
804 | 0 | int grpc_request = FLB_FALSE; |
805 | 0 | int grpc_uncompressed = FLB_FALSE; |
806 | 0 | size_t grpc_offset = 0; |
807 | 0 | uint64_t grpc_size = 0; |
808 | 0 | flb_sds_t tag = NULL; |
809 | 0 | char *auth_header = NULL; |
810 | 0 | char payload_type; |
811 | 0 | char *encoding = NULL; |
812 | 0 | size_t encoding_size = 0; |
813 | 0 | char *buf = (char *) request->body; |
814 | 0 | size_t request_body_size = 0; |
815 | 0 | char *payload = NULL; |
816 | 0 | size_t payload_size = 0; |
817 | 0 | size_t max_grpc_size = 16 * 1024 * 1024; /* 16M limit per message */ |
818 | 0 | struct flb_opentelemetry *context; |
819 | |
|
820 | 0 | context = (struct flb_opentelemetry *) response->stream->user_data; |
821 | |
|
822 | 0 | if (request->path[0] != '/') { |
823 | 0 | send_response_ng(response, 400, "error: invalid request\n"); |
824 | 0 | return -1; |
825 | 0 | } |
826 | | |
827 | 0 | if (strcmp(request->path, "/v1/metrics") == 0 || |
828 | 0 | strcmp(request->path, "/v1/traces") == 0 || |
829 | 0 | strcmp(request->path, "/v1/logs") == 0) { |
830 | 0 | grpc_request = FLB_FALSE; |
831 | 0 | } |
832 | 0 | else if(strcmp(request->path, "/opentelemetry.proto.collector.metrics.v1.MetricsService/Export") == 0 || |
833 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.traces.v1.TracesService/Export") == 0 || |
834 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.logs.v1.LogsService/Export") == 0 || |
835 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.metric.v1.MetricService/Export") == 0 || |
836 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.trace.v1.TraceService/Export") == 0 || |
837 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.log.v1.LogService/Export") == 0) { |
838 | 0 | grpc_request = FLB_TRUE; |
839 | 0 | } |
840 | 0 | else if (context->profile_support_enabled && |
841 | 0 | is_profiles_export_path(request->path) == FLB_TRUE) { |
842 | 0 | grpc_request = FLB_TRUE; |
843 | 0 | } |
844 | 0 | else { |
845 | 0 | send_response_ng(response, 404, "error: invalid endpoint\n"); |
846 | 0 | return -1; |
847 | 0 | } |
848 | | |
849 | | /* ToDo: Fix me */ |
850 | | /* HTTP/1.1 needs Host header */ |
851 | 0 | if (request->protocol_version == HTTP_PROTOCOL_VERSION_11 && |
852 | 0 | request->host == NULL) { |
853 | 0 | if (grpc_request) { |
854 | 0 | send_grpc_error_response_ng(response, 3, "missing host header"); |
855 | 0 | return -1; |
856 | 0 | } |
857 | 0 | return -1; |
858 | 0 | } |
859 | | |
860 | 0 | if (context->oauth2_ctx) { |
861 | 0 | auth_header = flb_http_request_get_header(request, "authorization"); |
862 | 0 | if (auth_header != NULL) { |
863 | 0 | auth_len = strlen(auth_header); |
864 | 0 | } |
865 | |
|
866 | 0 | ret = flb_oauth2_jwt_validate(context->oauth2_ctx, auth_header, auth_len); |
867 | 0 | if (ret != FLB_OAUTH2_JWT_OK) { |
868 | 0 | flb_plg_error(context->ins, |
869 | 0 | "OAuth2 validation failed: %s (rejecting request with 401)", |
870 | 0 | flb_oauth2_jwt_status_message(ret)); |
871 | |
|
872 | 0 | if (grpc_request) { |
873 | 0 | send_grpc_error_response_ng(response, 16, "unauthorized"); |
874 | 0 | } |
875 | 0 | else { |
876 | 0 | send_response_ng(response, 401, NULL); |
877 | 0 | } |
878 | |
|
879 | 0 | return -1; |
880 | 0 | } |
881 | 0 | } |
882 | | |
883 | 0 | if (request->method != HTTP_METHOD_POST) { |
884 | 0 | if (grpc_request) { |
885 | 0 | send_grpc_error_response_ng(response, 3, "invalid HTTP method"); |
886 | 0 | } |
887 | 0 | else { |
888 | 0 | send_response_ng(response, 400, "error: invalid HTTP method\n"); |
889 | 0 | } |
890 | 0 | return -1; |
891 | 0 | } |
892 | | |
893 | | /* check content-length */ |
894 | 0 | if (request->content_length <= 0) { |
895 | 0 | if (grpc_request) { |
896 | 0 | send_grpc_error_response_ng(response, 3, "invalid content-length"); |
897 | 0 | } |
898 | 0 | else { |
899 | 0 | send_response_ng(response, 400, "error: invalid content-length\n"); |
900 | 0 | } |
901 | 0 | return -1; |
902 | 0 | } |
903 | | |
904 | 0 | if (request->body == NULL) { |
905 | 0 | if (grpc_request) { |
906 | 0 | send_grpc_error_response_ng(response, 3, "invalid payload"); |
907 | 0 | } |
908 | 0 | else { |
909 | 0 | send_response_ng(response, 400, "error: invalid payload\n"); |
910 | 0 | } |
911 | 0 | return -1; |
912 | 0 | } |
913 | 0 | request_body_size = cfl_sds_len(request->body); |
914 | | |
915 | | /* If this is a gRPC request validate the content-type */ |
916 | 0 | if (grpc_request && request->content_type == NULL) { |
917 | 0 | send_grpc_error_response_ng(response, 3, "missing content-type"); |
918 | 0 | return -1; |
919 | 0 | } |
920 | | |
921 | | /* Check if the payload is gRPC compressed */ |
922 | 0 | if (grpc_request && |
923 | 0 | opentelemetry_is_grpc_content_type(request->content_type) == FLB_TRUE) { |
924 | |
|
925 | 0 | next_grpc_message: |
926 | |
|
927 | 0 | if (grpc_offset > request_body_size || |
928 | 0 | request_body_size - grpc_offset < 5) { |
929 | 0 | send_grpc_error_response_ng(response, 3, "invalid gRPC packet"); |
930 | 0 | return -1; |
931 | 0 | } |
932 | | |
933 | | /* gRPC message size */ |
934 | 0 | grpc_size = ((uint64_t) (uint8_t) buf[1] << 24) | |
935 | 0 | ((uint64_t) (uint8_t) buf[2] << 16) | |
936 | 0 | ((uint64_t) (uint8_t) buf[3] << 8) | |
937 | 0 | ((uint64_t) (uint8_t) buf[4]); |
938 | |
|
939 | 0 | if (grpc_size == 0 || grpc_size > max_grpc_size) { |
940 | 0 | send_grpc_error_response_ng(response, 3, "gRPC message size out of valid range"); |
941 | 0 | return -1; |
942 | 0 | } |
943 | | |
944 | 0 | if (request_body_size - grpc_offset < grpc_size + 5) { |
945 | 0 | send_grpc_error_response_ng(response, 3, "invalid gRPC packet"); |
946 | 0 | return -1; |
947 | 0 | } |
948 | | |
949 | | /* check if the message is compressed */ |
950 | 0 | if (buf[0] == 0x1) { |
951 | | /* get compression type */ |
952 | 0 | ret = http_header_lookup(HTTP_PROTOCOL_VERSION_20, request, |
953 | 0 | "grpc-encoding", &encoding, &encoding_size); |
954 | | |
955 | | /* malformed gRPC message */ |
956 | 0 | if (ret == -1) { |
957 | 0 | send_grpc_error_response_ng(response, 3, "missing gRPC encoding"); |
958 | 0 | return -1; |
959 | 0 | } |
960 | | |
961 | | /* buf: skip header */ |
962 | 0 | buf += 5; |
963 | |
|
964 | 0 | if (strncasecmp(encoding, "gzip", 4) == 0 && encoding_size == 4) { |
965 | 0 | ret = uncompress_gzip(context, |
966 | 0 | &payload, &payload_size, |
967 | 0 | buf, grpc_size); |
968 | 0 | } |
969 | 0 | else if (strncasecmp(encoding, "zlib", 4) == 0 && encoding_size == 4) { |
970 | 0 | ret = uncompress_zlib(context, |
971 | 0 | &payload, &payload_size, |
972 | 0 | buf, grpc_size); |
973 | 0 | } |
974 | 0 | else if (strncasecmp(encoding, "zstd", 4) == 0 && encoding_size == 4) { |
975 | 0 | ret = uncompress_zstd(context, |
976 | 0 | &payload, &payload_size, |
977 | 0 | buf, grpc_size); |
978 | 0 | } |
979 | 0 | else if (strncasecmp(encoding, "snappy", 6) == 0 && encoding_size == 6) { |
980 | 0 | ret = uncompress_snappy(context, |
981 | 0 | &payload, &payload_size, |
982 | 0 | buf, grpc_size); |
983 | 0 | } |
984 | 0 | else if (strncasecmp(encoding, "deflate", 7) == 0 && encoding_size == 7) { |
985 | 0 | ret = uncompress_deflate(context, |
986 | 0 | &payload, &payload_size, |
987 | 0 | buf, grpc_size); |
988 | 0 | } |
989 | 0 | else { |
990 | 0 | send_grpc_error_response_ng(response, 12, "unsupported gRPC encoding"); |
991 | 0 | return -1; |
992 | 0 | } |
993 | | |
994 | 0 | if (ret <= 0) { |
995 | 0 | send_grpc_error_response_ng(response, 13, "decompression error"); |
996 | 0 | return -1; |
997 | 0 | } |
998 | | |
999 | 0 | grpc_uncompressed = FLB_TRUE; |
1000 | 0 | } |
1001 | 0 | else { |
1002 | | /* uncompressed payload */ |
1003 | 0 | payload = buf + 5; |
1004 | 0 | payload_size = grpc_size; |
1005 | 0 | grpc_uncompressed = FLB_FALSE; |
1006 | 0 | } |
1007 | | |
1008 | | /* mark the end of this gRPC message */ |
1009 | 0 | grpc_offset += grpc_size + 5; |
1010 | 0 | } |
1011 | 0 | else { |
1012 | 0 | grpc_request = FLB_FALSE; |
1013 | 0 | payload = request->body; |
1014 | 0 | payload_size = cfl_sds_len(request->body); |
1015 | 0 | } |
1016 | | |
1017 | 0 | if (strcmp(request->path, "/v1/metrics") == 0 || |
1018 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.metric.v1.MetricService/Export") == 0 || |
1019 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.metrics.v1.MetricsService/Export") == 0) { |
1020 | 0 | payload_type = 'M'; |
1021 | 0 | tag = opentelemetry_prot_create_request_tag(context, "v1_metrics"); |
1022 | 0 | if (tag == NULL) { |
1023 | 0 | ret = -1; |
1024 | 0 | if (grpc_request == FLB_TRUE) { |
1025 | 0 | send_grpc_error_response_ng(response, 13, "internal error"); |
1026 | 0 | } |
1027 | 0 | else { |
1028 | 0 | send_response_ng(response, 500, "internal error: cannot allocate request tag\n"); |
1029 | 0 | } |
1030 | 0 | goto cleanup; |
1031 | 0 | } |
1032 | | |
1033 | 0 | ret = process_payload_metrics_ng(context, tag, request, |
1034 | 0 | payload, payload_size); |
1035 | 0 | } |
1036 | 0 | else if (strcmp(request->path, "/v1/traces") == 0 || |
1037 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.trace.v1.TraceService/Export") == 0 || |
1038 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.traces.v1.TracesService/Export") == 0) { |
1039 | 0 | payload_type = 'T'; |
1040 | 0 | tag = opentelemetry_prot_create_request_tag(context, "v1_traces"); |
1041 | 0 | if (tag == NULL) { |
1042 | 0 | ret = -1; |
1043 | 0 | if (grpc_request == FLB_TRUE) { |
1044 | 0 | send_grpc_error_response_ng(response, 13, "internal error"); |
1045 | 0 | } |
1046 | 0 | else { |
1047 | 0 | send_response_ng(response, 500, "internal error: cannot allocate request tag\n"); |
1048 | 0 | } |
1049 | 0 | goto cleanup; |
1050 | 0 | } |
1051 | | |
1052 | 0 | ret = opentelemetry_process_traces(context, request->content_type, |
1053 | 0 | tag, flb_sds_len(tag), |
1054 | 0 | payload, payload_size); |
1055 | 0 | } |
1056 | 0 | else if (strcmp(request->path, "/v1/logs") == 0 || |
1057 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.log.v1.LogService/Export") == 0 || |
1058 | 0 | strcmp(request->path, "/opentelemetry.proto.collector.logs.v1.LogsService/Export") == 0) { |
1059 | 0 | payload_type = 'L'; |
1060 | 0 | tag = opentelemetry_prot_create_request_tag(context, "v1_logs"); |
1061 | 0 | if (tag == NULL) { |
1062 | 0 | ret = -1; |
1063 | 0 | if (grpc_request == FLB_TRUE) { |
1064 | 0 | send_grpc_error_response_ng(response, 13, "internal error"); |
1065 | 0 | } |
1066 | 0 | else { |
1067 | 0 | send_response_ng(response, 500, "internal error: cannot allocate request tag\n"); |
1068 | 0 | } |
1069 | 0 | goto cleanup; |
1070 | 0 | } |
1071 | | |
1072 | 0 | ret = opentelemetry_process_logs(context, request->content_type, tag, flb_sds_len(tag), |
1073 | 0 | payload, payload_size); |
1074 | 0 | } |
1075 | 0 | else if (context->profile_support_enabled && |
1076 | 0 | is_profiles_export_path(request->path) == FLB_TRUE) { |
1077 | 0 | payload_type = 'P'; |
1078 | 0 | tag = opentelemetry_prot_create_request_tag(context, "v1development_profiles"); |
1079 | 0 | if (tag == NULL) { |
1080 | 0 | ret = -1; |
1081 | 0 | if (grpc_request == FLB_TRUE) { |
1082 | 0 | send_grpc_error_response_ng(response, 13, "internal error"); |
1083 | 0 | } |
1084 | 0 | else { |
1085 | 0 | send_response_ng(response, 500, "internal error: cannot allocate request tag\n"); |
1086 | 0 | } |
1087 | 0 | goto cleanup; |
1088 | 0 | } |
1089 | 0 | ret = process_payload_profiles_ng(context, tag, request, payload, payload_size); |
1090 | 0 | } |
1091 | | |
1092 | 0 | cleanup: |
1093 | 0 | if (grpc_request) { |
1094 | | /* check if we have uncompressed a gRPC message, if so, release it */ |
1095 | 0 | if (grpc_uncompressed == FLB_TRUE) { |
1096 | 0 | flb_free(payload); |
1097 | 0 | grpc_uncompressed = FLB_FALSE; |
1098 | 0 | } |
1099 | | |
1100 | | /* check if we have more gRPC messages to process */ |
1101 | 0 | if (grpc_offset < request_body_size) { |
1102 | 0 | buf = (char *) request->body + grpc_offset; |
1103 | 0 | goto next_grpc_message; |
1104 | 0 | } |
1105 | | |
1106 | 0 | if (ret == FLB_INPUT_INGRESS_BUSY) { |
1107 | 0 | send_ingress_busy_response_ng(response, grpc_request); |
1108 | 0 | } |
1109 | 0 | else { |
1110 | 0 | send_export_service_response_ng(response, ret, payload_type); |
1111 | 0 | } |
1112 | 0 | } |
1113 | 0 | else { |
1114 | 0 | if (ret == 0) { |
1115 | 0 | send_response_ng(response, context->successful_response_code, NULL); |
1116 | 0 | } |
1117 | 0 | else if (ret == FLB_INPUT_INGRESS_BUSY) { |
1118 | 0 | send_ingress_busy_response_ng(response, grpc_request); |
1119 | 0 | } |
1120 | 0 | else { |
1121 | 0 | send_response_ng(response, 400, "invalid request: deserialisation error\n"); |
1122 | 0 | } |
1123 | 0 | } |
1124 | | |
1125 | 0 | flb_sds_destroy(tag); |
1126 | |
|
1127 | 0 | return ret; |
1128 | 0 | } |