From 5687b895c5103a143beba748210d8bbd72714239 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Fri, 26 Apr 2024 23:29:41 -0500 Subject: [PATCH] lib: cmetrics: upgrade to v0.9.0 Signed-off-by: Eduardo Silva --- lib/cmetrics/CMakeLists.txt | 2 +- .../cmt_decode_prometheus_remote_write.h | 39 + .../prometheus_remote_write/remote.pb-c.h | 6 +- .../prometheus_remote_write/types.pb-c.h | 261 ++++++- lib/cmetrics/src/CMakeLists.txt | 1 + lib/cmetrics/src/cmt_decode_msgpack.c | 6 +- lib/cmetrics/src/cmt_decode_opentelemetry.c | 2 +- .../src/cmt_decode_prometheus_remote_write.c | 688 ++++++++++++++++++ lib/cmetrics/src/external/types.pb-c.c | 548 +++++++++++++- ...ite_dump_originally_from_node_exporter.bin | Bin 0 -> 293512 bytes lib/cmetrics/tests/decoding.c | 21 + 11 files changed, 1557 insertions(+), 17 deletions(-) create mode 100644 lib/cmetrics/include/cmetrics/cmt_decode_prometheus_remote_write.h create mode 100644 lib/cmetrics/src/cmt_decode_prometheus_remote_write.c create mode 100644 lib/cmetrics/tests/data/remote_write_dump_originally_from_node_exporter.bin diff --git a/lib/cmetrics/CMakeLists.txt b/lib/cmetrics/CMakeLists.txt index bfcd4492538..1041f6d295d 100644 --- a/lib/cmetrics/CMakeLists.txt +++ b/lib/cmetrics/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # CMetrics Version set(CMT_VERSION_MAJOR 0) -set(CMT_VERSION_MINOR 8) +set(CMT_VERSION_MINOR 9) set(CMT_VERSION_PATCH 0) set(CMT_VERSION_STR "${CMT_VERSION_MAJOR}.${CMT_VERSION_MINOR}.${CMT_VERSION_PATCH}") diff --git a/lib/cmetrics/include/cmetrics/cmt_decode_prometheus_remote_write.h b/lib/cmetrics/include/cmetrics/cmt_decode_prometheus_remote_write.h new file mode 100644 index 00000000000..4eef2e4c3ac --- /dev/null +++ b/lib/cmetrics/include/cmetrics/cmt_decode_prometheus_remote_write.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2024 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef CMT_DECODE_PROMETHEUS_REMOTE_WRITE_H +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_H + +#include +#include + +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS 0 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR 1 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_UNEXPECTED_ERROR 2 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_INVALID_ARGUMENT_ERROR 3 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_UNEXPECTED_METRIC_TYPE 4 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_DECODE_ERROR 5 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_UNPACK_ERROR 6 +#define CMT_DECODE_PROMETHEUS_REMOTE_WRITE_UNSUPPORTED_METRIC_TYPE 7 + +int cmt_decode_prometheus_remote_write_create(struct cmt **out_cmt, char *in_buf, size_t in_size); +void cmt_decode_prometheus_remote_write_destroy(struct cmt *cmt); + +#endif diff --git a/lib/cmetrics/include/prometheus_remote_write/remote.pb-c.h b/lib/cmetrics/include/prometheus_remote_write/remote.pb-c.h index a816a4bbded..925f65de3f4 100644 --- a/lib/cmetrics/include/prometheus_remote_write/remote.pb-c.h +++ b/lib/cmetrics/include/prometheus_remote_write/remote.pb-c.h @@ -37,8 +37,10 @@ typedef enum _Prometheus__ReadRequest__ResponseType { */ PROMETHEUS__READ_REQUEST__RESPONSE_TYPE__SAMPLES = 0, /* - * Server will stream a delimited ChunkedReadResponse message that contains XOR encoded chunks for a single series. - * Each message is following varint size and fixed size bigendian uint32 for CRC32 Castagnoli checksum. + * Server will stream a delimited ChunkedReadResponse message that + * contains XOR or HISTOGRAM(!) encoded chunks for a single series. + * Each message is following varint size and fixed size bigendian + * uint32 for CRC32 Castagnoli checksum. * Response headers: * Content-Type: "application/x-streamed-protobuf; proto=prometheus.ChunkedReadResponse" * Content-Encoding: "" diff --git a/lib/cmetrics/include/prometheus_remote_write/types.pb-c.h b/lib/cmetrics/include/prometheus_remote_write/types.pb-c.h index 25291c92efb..e17d3ba7af6 100644 --- a/lib/cmetrics/include/prometheus_remote_write/types.pb-c.h +++ b/lib/cmetrics/include/prometheus_remote_write/types.pb-c.h @@ -18,6 +18,9 @@ PROTOBUF_C__BEGIN_DECLS typedef struct _Prometheus__MetricMetadata Prometheus__MetricMetadata; typedef struct _Prometheus__Sample Prometheus__Sample; +typedef struct _Prometheus__Exemplar Prometheus__Exemplar; +typedef struct _Prometheus__Histogram Prometheus__Histogram; +typedef struct _Prometheus__BucketSpan Prometheus__BucketSpan; typedef struct _Prometheus__TimeSeries Prometheus__TimeSeries; typedef struct _Prometheus__Label Prometheus__Label; typedef struct _Prometheus__Labels Prometheus__Labels; @@ -40,6 +43,25 @@ typedef enum _Prometheus__MetricMetadata__MetricType { PROMETHEUS__METRIC_METADATA__METRIC_TYPE__STATESET = 7 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PROMETHEUS__METRIC_METADATA__METRIC_TYPE) } Prometheus__MetricMetadata__MetricType; +typedef enum _Prometheus__Histogram__ResetHint { + /* + * Need to test for a counter reset explicitly. + */ + PROMETHEUS__HISTOGRAM__RESET_HINT__UNKNOWN = 0, + /* + * This is the 1st histogram after a counter reset. + */ + PROMETHEUS__HISTOGRAM__RESET_HINT__YES = 1, + /* + * There was no counter reset between this and the previous Histogram. + */ + PROMETHEUS__HISTOGRAM__RESET_HINT__NO = 2, + /* + * This is a gauge histogram where counter resets don't happen. + */ + PROMETHEUS__HISTOGRAM__RESET_HINT__GAUGE = 3 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PROMETHEUS__HISTOGRAM__RESET_HINT) +} Prometheus__Histogram__ResetHint; typedef enum _Prometheus__LabelMatcher__Type { PROMETHEUS__LABEL_MATCHER__TYPE__EQ = 0, PROMETHEUS__LABEL_MATCHER__TYPE__NEQ = 1, @@ -52,7 +74,9 @@ typedef enum _Prometheus__LabelMatcher__Type { */ typedef enum _Prometheus__Chunk__Encoding { PROMETHEUS__CHUNK__ENCODING__UNKNOWN = 0, - PROMETHEUS__CHUNK__ENCODING__XOR = 1 + PROMETHEUS__CHUNK__ENCODING__XOR = 1, + PROMETHEUS__CHUNK__ENCODING__HISTOGRAM = 2, + PROMETHEUS__CHUNK__ENCODING__FLOAT_HISTOGRAM = 3 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PROMETHEUS__CHUNK__ENCODING) } Prometheus__Chunk__Encoding; @@ -63,7 +87,7 @@ struct _Prometheus__MetricMetadata ProtobufCMessage base; /* * Represents the metric type, these match the set from Prometheus. - * Refer to pkg/textparse/interface.go for details. + * Refer to github.com/prometheus/common/model/metadata.go for details. */ Prometheus__MetricMetadata__MetricType type; char *metric_family_name; @@ -79,6 +103,10 @@ struct _Prometheus__Sample { ProtobufCMessage base; double value; + /* + * timestamp is in ms format, see model/timestamp/timestamp.go for + * conversion from time.Time to Prometheus timestamp. + */ int64_t timestamp; }; #define PROMETHEUS__SAMPLE__INIT \ @@ -86,20 +114,177 @@ struct _Prometheus__Sample , 0, 0 } +struct _Prometheus__Exemplar +{ + ProtobufCMessage base; + /* + * Optional, can be empty. + */ + size_t n_labels; + Prometheus__Label **labels; + double value; + /* + * timestamp is in ms format, see model/timestamp/timestamp.go for + * conversion from time.Time to Prometheus timestamp. + */ + int64_t timestamp; +}; +#define PROMETHEUS__EXEMPLAR__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&prometheus__exemplar__descriptor) \ + , 0,NULL, 0, 0 } + + +typedef enum { + PROMETHEUS__HISTOGRAM__COUNT__NOT_SET = 0, + PROMETHEUS__HISTOGRAM__COUNT_COUNT_INT = 1, + PROMETHEUS__HISTOGRAM__COUNT_COUNT_FLOAT = 2 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PROMETHEUS__HISTOGRAM__COUNT) +} Prometheus__Histogram__CountCase; + +typedef enum { + PROMETHEUS__HISTOGRAM__ZERO_COUNT__NOT_SET = 0, + PROMETHEUS__HISTOGRAM__ZERO_COUNT_ZERO_COUNT_INT = 6, + PROMETHEUS__HISTOGRAM__ZERO_COUNT_ZERO_COUNT_FLOAT = 7 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PROMETHEUS__HISTOGRAM__ZERO_COUNT) +} Prometheus__Histogram__ZeroCountCase; + +/* + * A native histogram, also known as a sparse histogram. + * Original design doc: + * https://docs.google.com/document/d/1cLNv3aufPZb3fNfaJgdaRBZsInZKKIHo9E6HinJVbpM/edit + * The appendix of this design doc also explains the concept of float + * histograms. This Histogram message can represent both, the usual + * integer histogram as well as a float histogram. + */ +struct _Prometheus__Histogram +{ + ProtobufCMessage base; + /* + * Sum of observations in the histogram. + */ + double sum; + /* + * The schema defines the bucket schema. Currently, valid numbers + * are -4 <= n <= 8. They are all for base-2 bucket schemas, where 1 + * is a bucket boundary in each case, and then each power of two is + * divided into 2^n logarithmic buckets. Or in other words, each + * bucket boundary is the previous boundary times 2^(2^-n). In the + * future, more bucket schemas may be added using numbers < -4 or > + * 8. + */ + int32_t schema; + /* + * Breadth of the zero bucket. + */ + double zero_threshold; + /* + * Negative Buckets. + */ + size_t n_negative_spans; + Prometheus__BucketSpan **negative_spans; + /* + * Use either "negative_deltas" or "negative_counts", the former for + * regular histograms with integer counts, the latter for float + * histograms. + */ + /* + * Count delta of each bucket compared to previous one (or to zero for 1st bucket). + */ + size_t n_negative_deltas; + int64_t *negative_deltas; + /* + * Absolute count of each bucket. + */ + size_t n_negative_counts; + double *negative_counts; + /* + * Positive Buckets. + */ + size_t n_positive_spans; + Prometheus__BucketSpan **positive_spans; + /* + * Use either "positive_deltas" or "positive_counts", the former for + * regular histograms with integer counts, the latter for float + * histograms. + */ + /* + * Count delta of each bucket compared to previous one (or to zero for 1st bucket). + */ + size_t n_positive_deltas; + int64_t *positive_deltas; + /* + * Absolute count of each bucket. + */ + size_t n_positive_counts; + double *positive_counts; + Prometheus__Histogram__ResetHint reset_hint; + /* + * timestamp is in ms format, see model/timestamp/timestamp.go for + * conversion from time.Time to Prometheus timestamp. + */ + int64_t timestamp; + Prometheus__Histogram__CountCase count_case; + union { + uint64_t count_int; + double count_float; + }; + Prometheus__Histogram__ZeroCountCase zero_count_case; + union { + uint64_t zero_count_int; + double zero_count_float; + }; +}; +#define PROMETHEUS__HISTOGRAM__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&prometheus__histogram__descriptor) \ + , 0, 0, 0, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, PROMETHEUS__HISTOGRAM__RESET_HINT__UNKNOWN, 0, PROMETHEUS__HISTOGRAM__COUNT__NOT_SET, {0}, PROMETHEUS__HISTOGRAM__ZERO_COUNT__NOT_SET, {0} } + + +/* + * A BucketSpan defines a number of consecutive buckets with their + * offset. Logically, it would be more straightforward to include the + * bucket counts in the Span. However, the protobuf representation is + * more compact in the way the data is structured here (with all the + * buckets in a single array separate from the Spans). + */ +struct _Prometheus__BucketSpan +{ + ProtobufCMessage base; + /* + * Gap to previous span, or starting point for 1st span (which can be negative). + */ + int32_t offset; + /* + * Length of consecutive buckets. + */ + uint32_t length; +}; +#define PROMETHEUS__BUCKET_SPAN__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&prometheus__bucket_span__descriptor) \ + , 0, 0 } + + /* * TimeSeries represents samples and labels for a single time series. */ struct _Prometheus__TimeSeries { ProtobufCMessage base; + /* + * For a timeseries to be valid, and for the samples and exemplars + * to be ingested by the remote system properly, the labels field is required. + */ size_t n_labels; Prometheus__Label **labels; size_t n_samples; Prometheus__Sample **samples; + size_t n_exemplars; + Prometheus__Exemplar **exemplars; + size_t n_histograms; + Prometheus__Histogram **histograms; }; #define PROMETHEUS__TIME_SERIES__INIT \ { PROTOBUF_C_MESSAGE_INIT (&prometheus__time_series__descriptor) \ - , 0,NULL, 0,NULL } + , 0,NULL, 0,NULL, 0,NULL, 0,NULL } struct _Prometheus__Label @@ -254,6 +439,63 @@ Prometheus__Sample * void prometheus__sample__free_unpacked (Prometheus__Sample *message, ProtobufCAllocator *allocator); +/* Prometheus__Exemplar methods */ +void prometheus__exemplar__init + (Prometheus__Exemplar *message); +size_t prometheus__exemplar__get_packed_size + (const Prometheus__Exemplar *message); +size_t prometheus__exemplar__pack + (const Prometheus__Exemplar *message, + uint8_t *out); +size_t prometheus__exemplar__pack_to_buffer + (const Prometheus__Exemplar *message, + ProtobufCBuffer *buffer); +Prometheus__Exemplar * + prometheus__exemplar__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void prometheus__exemplar__free_unpacked + (Prometheus__Exemplar *message, + ProtobufCAllocator *allocator); +/* Prometheus__Histogram methods */ +void prometheus__histogram__init + (Prometheus__Histogram *message); +size_t prometheus__histogram__get_packed_size + (const Prometheus__Histogram *message); +size_t prometheus__histogram__pack + (const Prometheus__Histogram *message, + uint8_t *out); +size_t prometheus__histogram__pack_to_buffer + (const Prometheus__Histogram *message, + ProtobufCBuffer *buffer); +Prometheus__Histogram * + prometheus__histogram__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void prometheus__histogram__free_unpacked + (Prometheus__Histogram *message, + ProtobufCAllocator *allocator); +/* Prometheus__BucketSpan methods */ +void prometheus__bucket_span__init + (Prometheus__BucketSpan *message); +size_t prometheus__bucket_span__get_packed_size + (const Prometheus__BucketSpan *message); +size_t prometheus__bucket_span__pack + (const Prometheus__BucketSpan *message, + uint8_t *out); +size_t prometheus__bucket_span__pack_to_buffer + (const Prometheus__BucketSpan *message, + ProtobufCBuffer *buffer); +Prometheus__BucketSpan * + prometheus__bucket_span__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void prometheus__bucket_span__free_unpacked + (Prometheus__BucketSpan *message, + ProtobufCAllocator *allocator); /* Prometheus__TimeSeries methods */ void prometheus__time_series__init (Prometheus__TimeSeries *message); @@ -395,6 +637,15 @@ typedef void (*Prometheus__MetricMetadata_Closure) typedef void (*Prometheus__Sample_Closure) (const Prometheus__Sample *message, void *closure_data); +typedef void (*Prometheus__Exemplar_Closure) + (const Prometheus__Exemplar *message, + void *closure_data); +typedef void (*Prometheus__Histogram_Closure) + (const Prometheus__Histogram *message, + void *closure_data); +typedef void (*Prometheus__BucketSpan_Closure) + (const Prometheus__BucketSpan *message, + void *closure_data); typedef void (*Prometheus__TimeSeries_Closure) (const Prometheus__TimeSeries *message, void *closure_data); @@ -425,6 +676,10 @@ typedef void (*Prometheus__ChunkedSeries_Closure) extern const ProtobufCMessageDescriptor prometheus__metric_metadata__descriptor; extern const ProtobufCEnumDescriptor prometheus__metric_metadata__metric_type__descriptor; extern const ProtobufCMessageDescriptor prometheus__sample__descriptor; +extern const ProtobufCMessageDescriptor prometheus__exemplar__descriptor; +extern const ProtobufCMessageDescriptor prometheus__histogram__descriptor; +extern const ProtobufCEnumDescriptor prometheus__histogram__reset_hint__descriptor; +extern const ProtobufCMessageDescriptor prometheus__bucket_span__descriptor; extern const ProtobufCMessageDescriptor prometheus__time_series__descriptor; extern const ProtobufCMessageDescriptor prometheus__label__descriptor; extern const ProtobufCMessageDescriptor prometheus__labels__descriptor; diff --git a/lib/cmetrics/src/CMakeLists.txt b/lib/cmetrics/src/CMakeLists.txt index 166fa0583d6..d45de9b8334 100644 --- a/lib/cmetrics/src/CMakeLists.txt +++ b/lib/cmetrics/src/CMakeLists.txt @@ -28,6 +28,7 @@ set(src cmt_decode_opentelemetry.c cmt_encode_prometheus.c cmt_encode_prometheus_remote_write.c + cmt_decode_prometheus_remote_write.c cmt_encode_splunk_hec.c cmt_encode_cloudwatch_emf.c cmt_encode_text.c diff --git a/lib/cmetrics/src/cmt_decode_msgpack.c b/lib/cmetrics/src/cmt_decode_msgpack.c index 4ede1bdd9ed..25942b354ab 100644 --- a/lib/cmetrics/src/cmt_decode_msgpack.c +++ b/lib/cmetrics/src/cmt_decode_msgpack.c @@ -226,8 +226,10 @@ static int unpack_opts(mpack_reader_t *reader, struct cmt_opts *opts) return CMT_DECODE_MSGPACK_ALLOCATION_ERROR; } - cfl_sds_cat(opts->fqname, opts->ns, cfl_sds_len(opts->ns)); - cfl_sds_cat(opts->fqname, "_", 1); + if (cfl_sds_len(opts->ns) > 0) { + cfl_sds_cat(opts->fqname, opts->ns, cfl_sds_len(opts->ns)); + cfl_sds_cat(opts->fqname, "_", 1); + } if (cfl_sds_len(opts->subsystem) > 0) { cfl_sds_cat(opts->fqname, opts->subsystem, cfl_sds_len(opts->subsystem)); diff --git a/lib/cmetrics/src/cmt_decode_opentelemetry.c b/lib/cmetrics/src/cmt_decode_opentelemetry.c index 34cafd55a30..9f88bfc81af 100644 --- a/lib/cmetrics/src/cmt_decode_opentelemetry.c +++ b/lib/cmetrics/src/cmt_decode_opentelemetry.c @@ -452,7 +452,7 @@ static int decode_numerical_data_point(struct cmt *cmt, value = 0; } else { - value = cmt_math_uint64_to_d64((uint64_t) data_point->as_int); + value = data_point->as_int; } } else if (data_point->value_case == OPENTELEMETRY__PROTO__METRICS__V1__NUMBER_DATA_POINT__VALUE_AS_DOUBLE) { diff --git a/lib/cmetrics/src/cmt_decode_prometheus_remote_write.c b/lib/cmetrics/src/cmt_decode_prometheus_remote_write.c new file mode 100644 index 00000000000..1a01f2d08f1 --- /dev/null +++ b/lib/cmetrics/src/cmt_decode_prometheus_remote_write.c @@ -0,0 +1,688 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* CMetrics + * ======== + * Copyright 2021-2024 The CMetrics Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void *__cmt_allocator_alloc(void *data, size_t size) { + return malloc(size); +} +static void __cmt_allocator_free(void *data, void *ptr) { + free(ptr); +} + +static ProtobufCAllocator __cmt_allocator = { + .alloc = __cmt_allocator_alloc, + .free = __cmt_allocator_free, + .allocator_data = NULL +}; + +#define cmt_system_allocator __cmt_allocator + +static char *cmt_metric_name_from_labels(Prometheus__TimeSeries *ts) +{ + int i; + int count; + + count = ts->n_labels; + for (i = 0; i < count; i++) { + if (strncmp("__name__", ts->labels[i]->name, 8) == 0) { + return strdup(ts->labels[i]->value); + } + } + + return NULL; +} + +static struct cmt_map_label *create_map_label(char *caption, size_t length) +{ + struct cmt_map_label *map_label; + + map_label = calloc(1, sizeof(struct cmt_map_label)); + if (!map_label) { + return NULL; + } + + if (map_label != NULL) { + if (caption != NULL) { + if (length == 0) { + length = strlen(caption); + } + + map_label->name = cfl_sds_create_len(caption, length); + + if (map_label->name == NULL) { + cmt_errno(); + + free(map_label); + + map_label = NULL; + } + } + } + + return map_label; +} + +static int append_new_map_label_key(struct cmt_map *map, char *name) +{ + struct cmt_map_label *label; + + label = create_map_label(name, 0); + + if (label == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_add(&label->_head, &map->label_keys); + map->label_count++; + + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + +static int append_new_metric_label_value(struct cmt_metric *metric, char *name, size_t length) +{ + struct cmt_map_label *label; + + label = create_map_label(name, length); + + if (label == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_add(&label->_head, &metric->labels); + + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; +} + +static int decode_labels(struct cmt *cmt, + struct cmt_map *map, + struct cmt_metric *metric, + size_t n_labels, + Prometheus__Label **labels) +{ + void **value_index_list; + size_t prom_label_index; + size_t map_label_index; + size_t map_label_count; + struct cfl_list *label_iterator; + struct cmt_map_label *current_label; + size_t label_index; + int label_found; + Prometheus__Label *label; + int result; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + if (n_labels == 0) { + return result; + } + + if (n_labels > 127) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_INVALID_ARGUMENT_ERROR; + } + + value_index_list = calloc(128, sizeof(void *)); + + if (value_index_list == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + for (prom_label_index = 0; + result == CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && + prom_label_index < n_labels; + prom_label_index++) { + + label = labels[prom_label_index]; + + label_found = CMT_FALSE; + label_index = 0; + + cfl_list_foreach(label_iterator, &map->label_keys) { + current_label = cfl_list_entry(label_iterator, struct cmt_map_label, _head); + + if (strcmp(current_label->name, label->name) == 0) { + label_found = CMT_TRUE; + + break; + } + + label_index++; + } + + if (label_found == CMT_FALSE) { + result = append_new_map_label_key(map, label->name); + } + + if (result == CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + value_index_list[label_index] = (void *) label; + } + } + + map_label_count = cfl_list_size(&map->label_keys); + + for (map_label_index = 0 ; + result == CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS && + map_label_index < map_label_count ; + map_label_index++) { + + if (value_index_list[map_label_index] != NULL) { + label = (Prometheus__Label *) value_index_list[map_label_index]; + result = append_new_metric_label_value(metric, label->value, 0); + } + } + + free(value_index_list); + + return result; +} + +static int decode_numerical_samples(struct cmt *cmt, + struct cmt_map *map, + size_t n_samples, + Prometheus__Sample *sample, + size_t n_labels, + Prometheus__Label **labels) +{ + int static_metric_detected; + struct cmt_metric *metric; + int result; + + static_metric_detected = CMT_FALSE; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + if (n_samples == 0) { + if (map->metric_static_set == CMT_FALSE) { + static_metric_detected = CMT_TRUE; + } + } + + if (static_metric_detected == CMT_FALSE) { + metric = calloc(1, sizeof(struct cmt_metric)); + + if (metric == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_init(&metric->labels); + + result = decode_labels(cmt, + map, + metric, + n_labels, + labels); + + if (result) { + destroy_label_list(&metric->labels); + + free(metric); + } + else { + cfl_list_add(&metric->_head, &map->metrics); + } + } + else { + metric = &map->metric; + + map->metric_static_set = CMT_TRUE; + } + + if (result == CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + cmt_metric_set(metric, sample->timestamp * 1000000, sample->value); + } + + return result; +} + +static int decode_numerical_time_series(struct cmt *cmt, + struct cmt_map *map, + size_t ts_count, + Prometheus__TimeSeries *ts) +{ + size_t index; + int result; + Prometheus__Sample *sample = NULL; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + for (index = 0; index < ts->n_samples; index++) { + sample = ts->samples[index]; + result = decode_numerical_samples(cmt, map, + ts->n_samples, sample, + ts->n_labels, ts->labels); + } + + return result; +} + +static int decode_counter_entry(struct cmt *cmt, + void *instance, + Prometheus__TimeSeries *ts) +{ + struct cmt_counter *counter; + int result; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + counter = (struct cmt_counter *) instance; + + counter->map->metric_static_set = 0; + + result = decode_numerical_time_series(cmt, + counter->map, + ts->n_samples, + ts); + + return result; +} + +static int decode_gauge_entry(struct cmt *cmt, + void *instance, + Prometheus__TimeSeries *ts) +{ + struct cmt_gauge *gauge; + int result; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + gauge = (struct cmt_gauge *) instance; + + gauge->map->metric_static_set = 0; + + result = decode_numerical_time_series(cmt, + gauge->map, + ts->n_samples, + ts); + + return result; +} + +static int decode_untyped_entry(struct cmt *cmt, + void *instance, + Prometheus__TimeSeries *ts) +{ + struct cmt_untyped *untyped; + int result; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + untyped = (struct cmt_untyped *) instance; + + untyped->map->metric_static_set = 0; + + result = decode_numerical_time_series(cmt, + untyped->map, + ts->n_samples, + ts); + + return result; +} + +static int decode_histogram_points(struct cmt *cmt, + struct cmt_map *map, + size_t n_histograms, + Prometheus__Histogram *hist, + size_t n_labels, + Prometheus__Label **labels) +{ + int i; + int static_metric_detected; + struct cmt_histogram *histogram; + struct cmt_metric *metric; + int result; + double *spans; + + static_metric_detected = CMT_FALSE; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + histogram = (struct cmt_histogram *) map->parent; + + if (histogram->buckets == NULL) { + if (hist->n_negative_spans > 0) { + spans = calloc(1, sizeof(double) * hist->n_negative_spans); + + for (i = 0; i < hist->n_negative_spans; i++) { + spans[i] = (double) hist->negative_spans[i]->offset; + } + histogram->buckets = cmt_histogram_buckets_create_size(spans, + hist->n_negative_spans); + free(spans); + } + else if (hist->n_positive_spans > 0) { + spans = calloc(1, sizeof(double) * hist->n_positive_spans); + + for (i = 0; i < hist->n_positive_spans; i++) { + spans[i] = (double) hist->positive_spans[i]->offset; + } + histogram->buckets = cmt_histogram_buckets_create_size(spans, + hist->n_positive_spans); + free(spans); + } + + if (histogram->buckets == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + } + + if (n_histograms == 0) { + if (map->metric_static_set == CMT_FALSE) { + static_metric_detected = CMT_TRUE; + } + } + + if (static_metric_detected == CMT_FALSE) { + metric = calloc(1, sizeof(struct cmt_metric)); + + if (metric == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + cfl_list_init(&metric->labels); + + result = decode_labels(cmt, + map, + metric, + n_labels, + labels); + + if (result) { + destroy_label_list(&metric->labels); + + free(metric); + } + else { + cfl_list_add(&metric->_head, &map->metrics); + } + } + else { + metric = &map->metric; + + map->metric_static_set = CMT_TRUE; + } + + if (result == CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + if (hist->n_negative_spans > 0) { + for (i = 0; i < hist->n_negative_counts; i++) { + cmt_metric_hist_set(metric, hist->timestamp * 1000000, + i, hist->negative_counts[i]); + } + } + else if (hist->n_positive_spans > 0) { + for (i = 0; i < hist->n_positive_counts; i++) { + cmt_metric_hist_set(metric, hist->timestamp * 1000000, + i, hist->positive_counts[i]); + } + } + else { + free(metric); + + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_DECODE_ERROR; + } + } + + metric->hist_sum = cmt_math_d64_to_uint64(hist->sum); + if (hist->count_case == PROMETHEUS__HISTOGRAM__COUNT_COUNT_INT) { + metric->hist_count = hist->count_int; + } + else if (hist->count_case == PROMETHEUS__HISTOGRAM__COUNT_COUNT_FLOAT) { + metric->hist_count = hist->count_float; + } + else { + free(metric); + + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_DECODE_ERROR; + } + + return result; +} + +static int decode_histogram_time_series(struct cmt *cmt, + struct cmt_map *map, + size_t hist_count, + Prometheus__TimeSeries *ts) +{ + size_t index; + int result; + Prometheus__Histogram *histogram = NULL; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + for (index = 0; result == 0 && index < hist_count; index++) { + histogram = ts->histograms[index]; + result = decode_histogram_points(cmt, map, + ts->n_histograms, + histogram, + ts->n_labels, + ts->labels); + } + + return result; +} + +static int decode_histogram_entry(struct cmt *cmt, + void *instance, + Prometheus__TimeSeries *ts) +{ + struct cmt_histogram *histogram; + int result; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + histogram = (struct cmt_histogram *) instance; + + histogram->map->metric_static_set = 0; + + result = decode_histogram_time_series(cmt, + histogram->map, + ts->n_histograms, + ts); + + return result; +} + +static int decode_metrics_entry(struct cmt *cmt, + Prometheus__WriteRequest *write) +{ + int i; + char *metric_name = NULL; + char *metric_subsystem = NULL; + char *metric_namespace = NULL; + char *metric_description = NULL; + void *instance; + int result; + int ts_count = 0; + int hist_count = 0; + int meta_count = 0; + Prometheus__MetricMetadata *metadata = NULL; + Prometheus__MetricMetadata__MetricType type; + Prometheus__TimeSeries *ts = NULL; + + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS; + + ts_count = write->n_timeseries; + for (i = 0; i < ts_count; i++) { + ts = write->timeseries[i]; + meta_count = write->n_metadata; + hist_count = ts->n_histograms; + if (meta_count > 0) { + metadata = write->metadata[i]; + } + if (metadata == NULL) { + type = PROMETHEUS__METRIC_METADATA__METRIC_TYPE__GAUGE; + metric_description = "-"; + } + else if (hist_count > 0) { + type = PROMETHEUS__METRIC_METADATA__METRIC_TYPE__HISTOGRAM; + metric_description = "-"; + } + else { + type = write->metadata[i]->type; + metric_description = write->metadata[i]->help; + if (metric_description == NULL) { + metric_description = "-"; + } + } + + metric_name = cmt_metric_name_from_labels(ts); + if (metric_name == NULL) { + continue; + } + + metric_namespace = ""; + metric_subsystem = ""; + + switch (type) { + case PROMETHEUS__METRIC_METADATA__METRIC_TYPE__COUNTER: + instance = cmt_counter_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + 0, NULL); + + if (instance == NULL) { + free(metric_name); + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + result = decode_counter_entry(cmt, instance, ts); + + if (result) { + cmt_counter_destroy(instance); + } + break; + case PROMETHEUS__METRIC_METADATA__METRIC_TYPE__GAUGE: + instance = cmt_gauge_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + 0, NULL); + + if (instance == NULL) { + free(metric_name); + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + result = decode_gauge_entry(cmt, instance, ts); + + if (result) { + cmt_gauge_destroy(instance); + } + break; + case PROMETHEUS__METRIC_METADATA__METRIC_TYPE__UNKNOWN: + instance = cmt_untyped_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + 0, NULL); + + if (instance == NULL) { + free(metric_name); + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + result = decode_untyped_entry(cmt, instance, ts); + + if (result) { + cmt_untyped_destroy(instance); + } + break; + case PROMETHEUS__METRIC_METADATA__METRIC_TYPE__HISTOGRAM: + instance = cmt_histogram_create(cmt, + metric_namespace, + metric_subsystem, + metric_name, + metric_description, + (struct cmt_histogram_buckets *) cmt, + 0, NULL); + + if (instance == NULL) { + free(metric_name); + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + result = decode_histogram_entry(cmt, instance, ts); + + if (result) { + cmt_histogram_destroy(instance); + } + break; + /* case PROMETHEUS__METRIC_METADATA__METRIC_TYPE__SUMMARY: */ + + default: + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_UNSUPPORTED_METRIC_TYPE; + break; + } + + free(metric_name); + } + + return result; +} + +int cmt_decode_prometheus_remote_write_create(struct cmt **out_cmt, char *in_buf, size_t in_size) +{ + int result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_INVALID_ARGUMENT_ERROR; + Prometheus__WriteRequest *write = NULL; + struct cmt *cmt = NULL; + + cmt = cmt_create(); + + if (cmt == NULL) { + return CMT_DECODE_PROMETHEUS_REMOTE_WRITE_ALLOCATION_ERROR; + } + + write = prometheus__write_request__unpack(&cmt_system_allocator, + in_size, + (uint8_t *) in_buf); + if (write == NULL) { + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_UNPACK_ERROR; + return result; + } + + result = decode_metrics_entry(cmt, write); + if (result != CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS) { + cmt_destroy(cmt); + prometheus__write_request__free_unpacked(write, &cmt_system_allocator); + result = CMT_DECODE_PROMETHEUS_REMOTE_WRITE_DECODE_ERROR; + + return result; + } + + prometheus__write_request__free_unpacked(write, &cmt_system_allocator); + + *out_cmt = cmt; + + return result; +} + +void cmt_decode_prometheus_remote_write_destroy(struct cmt *cmt) +{ + cmt_destroy(cmt); +} diff --git a/lib/cmetrics/src/external/types.pb-c.c b/lib/cmetrics/src/external/types.pb-c.c index 782815930d8..c09a154aa2b 100644 --- a/lib/cmetrics/src/external/types.pb-c.c +++ b/lib/cmetrics/src/external/types.pb-c.c @@ -98,6 +98,141 @@ void prometheus__sample__free_unpacked assert(message->base.descriptor == &prometheus__sample__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void prometheus__exemplar__init + (Prometheus__Exemplar *message) +{ + static const Prometheus__Exemplar init_value = PROMETHEUS__EXEMPLAR__INIT; + *message = init_value; +} +size_t prometheus__exemplar__get_packed_size + (const Prometheus__Exemplar *message) +{ + assert(message->base.descriptor == &prometheus__exemplar__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__exemplar__pack + (const Prometheus__Exemplar *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__exemplar__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__exemplar__pack_to_buffer + (const Prometheus__Exemplar *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__exemplar__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Exemplar * + prometheus__exemplar__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Exemplar *) + protobuf_c_message_unpack (&prometheus__exemplar__descriptor, + allocator, len, data); +} +void prometheus__exemplar__free_unpacked + (Prometheus__Exemplar *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__exemplar__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__histogram__init + (Prometheus__Histogram *message) +{ + static const Prometheus__Histogram init_value = PROMETHEUS__HISTOGRAM__INIT; + *message = init_value; +} +size_t prometheus__histogram__get_packed_size + (const Prometheus__Histogram *message) +{ + assert(message->base.descriptor == &prometheus__histogram__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__histogram__pack + (const Prometheus__Histogram *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__histogram__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__histogram__pack_to_buffer + (const Prometheus__Histogram *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__histogram__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__Histogram * + prometheus__histogram__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__Histogram *) + protobuf_c_message_unpack (&prometheus__histogram__descriptor, + allocator, len, data); +} +void prometheus__histogram__free_unpacked + (Prometheus__Histogram *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__histogram__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void prometheus__bucket_span__init + (Prometheus__BucketSpan *message) +{ + static const Prometheus__BucketSpan init_value = PROMETHEUS__BUCKET_SPAN__INIT; + *message = init_value; +} +size_t prometheus__bucket_span__get_packed_size + (const Prometheus__BucketSpan *message) +{ + assert(message->base.descriptor == &prometheus__bucket_span__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t prometheus__bucket_span__pack + (const Prometheus__BucketSpan *message, + uint8_t *out) +{ + assert(message->base.descriptor == &prometheus__bucket_span__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t prometheus__bucket_span__pack_to_buffer + (const Prometheus__BucketSpan *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &prometheus__bucket_span__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Prometheus__BucketSpan * + prometheus__bucket_span__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Prometheus__BucketSpan *) + protobuf_c_message_unpack (&prometheus__bucket_span__descriptor, + allocator, len, data); +} +void prometheus__bucket_span__free_unpacked + (Prometheus__BucketSpan *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &prometheus__bucket_span__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void prometheus__time_series__init (Prometheus__TimeSeries *message) { @@ -582,7 +717,374 @@ const ProtobufCMessageDescriptor prometheus__sample__descriptor = (ProtobufCMessageInit) prometheus__sample__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor prometheus__time_series__field_descriptors[2] = +static const ProtobufCFieldDescriptor prometheus__exemplar__field_descriptors[3] = +{ + { + "labels", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__Exemplar, n_labels), + offsetof(Prometheus__Exemplar, labels), + &prometheus__label__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Prometheus__Exemplar, value), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "timestamp", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Exemplar, timestamp), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__exemplar__field_indices_by_name[] = { + 0, /* field[0] = labels */ + 2, /* field[2] = timestamp */ + 1, /* field[1] = value */ +}; +static const ProtobufCIntRange prometheus__exemplar__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor prometheus__exemplar__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Exemplar", + "Exemplar", + "Prometheus__Exemplar", + "prometheus", + sizeof(Prometheus__Exemplar), + 3, + prometheus__exemplar__field_descriptors, + prometheus__exemplar__field_indices_by_name, + 1, prometheus__exemplar__number_ranges, + (ProtobufCMessageInit) prometheus__exemplar__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue prometheus__histogram__reset_hint__enum_values_by_number[4] = +{ + { "UNKNOWN", "PROMETHEUS__HISTOGRAM__RESET_HINT__UNKNOWN", 0 }, + { "YES", "PROMETHEUS__HISTOGRAM__RESET_HINT__YES", 1 }, + { "NO", "PROMETHEUS__HISTOGRAM__RESET_HINT__NO", 2 }, + { "GAUGE", "PROMETHEUS__HISTOGRAM__RESET_HINT__GAUGE", 3 }, +}; +static const ProtobufCIntRange prometheus__histogram__reset_hint__value_ranges[] = { +{0, 0},{0, 4} +}; +static const ProtobufCEnumValueIndex prometheus__histogram__reset_hint__enum_values_by_name[4] = +{ + { "GAUGE", 3 }, + { "NO", 2 }, + { "UNKNOWN", 0 }, + { "YES", 1 }, +}; +const ProtobufCEnumDescriptor prometheus__histogram__reset_hint__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "prometheus.Histogram.ResetHint", + "ResetHint", + "Prometheus__Histogram__ResetHint", + "prometheus", + 4, + prometheus__histogram__reset_hint__enum_values_by_number, + 4, + prometheus__histogram__reset_hint__enum_values_by_name, + 1, + prometheus__histogram__reset_hint__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor prometheus__histogram__field_descriptors[15] = +{ + { + "count_int", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + offsetof(Prometheus__Histogram, count_case), + offsetof(Prometheus__Histogram, count_int), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "count_float", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Prometheus__Histogram, count_case), + offsetof(Prometheus__Histogram, count_float), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sum", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Prometheus__Histogram, sum), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "schema", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_SINT32, + 0, /* quantifier_offset */ + offsetof(Prometheus__Histogram, schema), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "zero_threshold", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + 0, /* quantifier_offset */ + offsetof(Prometheus__Histogram, zero_threshold), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "zero_count_int", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT64, + offsetof(Prometheus__Histogram, zero_count_case), + offsetof(Prometheus__Histogram, zero_count_int), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "zero_count_float", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Prometheus__Histogram, zero_count_case), + offsetof(Prometheus__Histogram, zero_count_float), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "negative_spans", + 8, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__Histogram, n_negative_spans), + offsetof(Prometheus__Histogram, negative_spans), + &prometheus__bucket_span__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "negative_deltas", + 9, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_SINT64, + offsetof(Prometheus__Histogram, n_negative_deltas), + offsetof(Prometheus__Histogram, negative_deltas), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "negative_counts", + 10, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Prometheus__Histogram, n_negative_counts), + offsetof(Prometheus__Histogram, negative_counts), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "positive_spans", + 11, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__Histogram, n_positive_spans), + offsetof(Prometheus__Histogram, positive_spans), + &prometheus__bucket_span__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "positive_deltas", + 12, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_SINT64, + offsetof(Prometheus__Histogram, n_positive_deltas), + offsetof(Prometheus__Histogram, positive_deltas), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "positive_counts", + 13, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(Prometheus__Histogram, n_positive_counts), + offsetof(Prometheus__Histogram, positive_counts), + NULL, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "reset_hint", + 14, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(Prometheus__Histogram, reset_hint), + &prometheus__histogram__reset_hint__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "timestamp", + 15, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT64, + 0, /* quantifier_offset */ + offsetof(Prometheus__Histogram, timestamp), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__histogram__field_indices_by_name[] = { + 1, /* field[1] = count_float */ + 0, /* field[0] = count_int */ + 9, /* field[9] = negative_counts */ + 8, /* field[8] = negative_deltas */ + 7, /* field[7] = negative_spans */ + 12, /* field[12] = positive_counts */ + 11, /* field[11] = positive_deltas */ + 10, /* field[10] = positive_spans */ + 13, /* field[13] = reset_hint */ + 3, /* field[3] = schema */ + 2, /* field[2] = sum */ + 14, /* field[14] = timestamp */ + 6, /* field[6] = zero_count_float */ + 5, /* field[5] = zero_count_int */ + 4, /* field[4] = zero_threshold */ +}; +static const ProtobufCIntRange prometheus__histogram__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 15 } +}; +const ProtobufCMessageDescriptor prometheus__histogram__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.Histogram", + "Histogram", + "Prometheus__Histogram", + "prometheus", + sizeof(Prometheus__Histogram), + 15, + prometheus__histogram__field_descriptors, + prometheus__histogram__field_indices_by_name, + 1, prometheus__histogram__number_ranges, + (ProtobufCMessageInit) prometheus__histogram__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__bucket_span__field_descriptors[2] = +{ + { + "offset", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_SINT32, + 0, /* quantifier_offset */ + offsetof(Prometheus__BucketSpan, offset), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "length", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(Prometheus__BucketSpan, length), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned prometheus__bucket_span__field_indices_by_name[] = { + 1, /* field[1] = length */ + 0, /* field[0] = offset */ +}; +static const ProtobufCIntRange prometheus__bucket_span__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor prometheus__bucket_span__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "prometheus.BucketSpan", + "BucketSpan", + "Prometheus__BucketSpan", + "prometheus", + sizeof(Prometheus__BucketSpan), + 2, + prometheus__bucket_span__field_descriptors, + prometheus__bucket_span__field_indices_by_name, + 1, prometheus__bucket_span__number_ranges, + (ProtobufCMessageInit) prometheus__bucket_span__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor prometheus__time_series__field_descriptors[4] = { { "labels", @@ -608,15 +1110,41 @@ static const ProtobufCFieldDescriptor prometheus__time_series__field_descriptors 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "exemplars", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__TimeSeries, n_exemplars), + offsetof(Prometheus__TimeSeries, exemplars), + &prometheus__exemplar__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "histograms", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Prometheus__TimeSeries, n_histograms), + offsetof(Prometheus__TimeSeries, histograms), + &prometheus__histogram__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned prometheus__time_series__field_indices_by_name[] = { + 2, /* field[2] = exemplars */ + 3, /* field[3] = histograms */ 0, /* field[0] = labels */ 1, /* field[1] = samples */ }; static const ProtobufCIntRange prometheus__time_series__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 2 } + { 0, 4 } }; const ProtobufCMessageDescriptor prometheus__time_series__descriptor = { @@ -626,7 +1154,7 @@ const ProtobufCMessageDescriptor prometheus__time_series__descriptor = "Prometheus__TimeSeries", "prometheus", sizeof(Prometheus__TimeSeries), - 2, + 4, prometheus__time_series__field_descriptors, prometheus__time_series__field_indices_by_name, 1, prometheus__time_series__number_ranges, @@ -934,16 +1462,20 @@ const ProtobufCMessageDescriptor prometheus__read_hints__descriptor = (ProtobufCMessageInit) prometheus__read_hints__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCEnumValue prometheus__chunk__encoding__enum_values_by_number[2] = +static const ProtobufCEnumValue prometheus__chunk__encoding__enum_values_by_number[4] = { { "UNKNOWN", "PROMETHEUS__CHUNK__ENCODING__UNKNOWN", 0 }, { "XOR", "PROMETHEUS__CHUNK__ENCODING__XOR", 1 }, + { "HISTOGRAM", "PROMETHEUS__CHUNK__ENCODING__HISTOGRAM", 2 }, + { "FLOAT_HISTOGRAM", "PROMETHEUS__CHUNK__ENCODING__FLOAT_HISTOGRAM", 3 }, }; static const ProtobufCIntRange prometheus__chunk__encoding__value_ranges[] = { -{0, 0},{0, 2} +{0, 0},{0, 4} }; -static const ProtobufCEnumValueIndex prometheus__chunk__encoding__enum_values_by_name[2] = +static const ProtobufCEnumValueIndex prometheus__chunk__encoding__enum_values_by_name[4] = { + { "FLOAT_HISTOGRAM", 3 }, + { "HISTOGRAM", 2 }, { "UNKNOWN", 0 }, { "XOR", 1 }, }; @@ -954,9 +1486,9 @@ const ProtobufCEnumDescriptor prometheus__chunk__encoding__descriptor = "Encoding", "Prometheus__Chunk__Encoding", "prometheus", - 2, + 4, prometheus__chunk__encoding__enum_values_by_number, - 2, + 4, prometheus__chunk__encoding__enum_values_by_name, 1, prometheus__chunk__encoding__value_ranges, diff --git a/lib/cmetrics/tests/data/remote_write_dump_originally_from_node_exporter.bin b/lib/cmetrics/tests/data/remote_write_dump_originally_from_node_exporter.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f8afe3cbb3bcd4be2fbc58765d0d60c04e0ff65 GIT binary patch literal 293512 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 literal 0 HcmV?d00001 diff --git a/lib/cmetrics/tests/decoding.c b/lib/cmetrics/tests/decoding.c index 823861bdb52..358ca531367 100644 --- a/lib/cmetrics/tests/decoding.c +++ b/lib/cmetrics/tests/decoding.c @@ -20,11 +20,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include "cmt_tests.h" @@ -178,7 +181,25 @@ void test_opentelemetry() cmt_destroy(cmt); } +void test_prometheus_remote_write() +{ + int ret; + struct cmt *decoded_context; + cfl_sds_t payload = read_file(CMT_TESTS_DATA_PATH "/remote_write_dump_originally_from_node_exporter.bin"); + + cmt_initialize(); + + ret = cmt_decode_prometheus_remote_write_create(&decoded_context, payload, cfl_sds_len(payload)); + TEST_CHECK(ret == CMT_DECODE_PROMETHEUS_REMOTE_WRITE_SUCCESS); + + cmt_decode_prometheus_remote_write_destroy(decoded_context); + + cfl_sds_destroy(payload); +} + + TEST_LIST = { {"opentelemetry", test_opentelemetry}, + {"prometheus_remote_write", test_prometheus_remote_write}, { 0 } };