Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/cmetrics/.github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true

Expand Down Expand Up @@ -136,7 +136,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true

Expand Down Expand Up @@ -170,7 +170,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true

Expand Down Expand Up @@ -200,7 +200,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out the repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true

Expand Down
4 changes: 2 additions & 2 deletions lib/cmetrics/.github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: ludeeus/action-shellcheck@master

actionlint:
Expand All @@ -19,7 +19,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- run: |
echo "::add-matcher::.github/actionlint-matcher.json"
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
Expand Down
8 changes: 4 additions & 4 deletions lib/cmetrics/.github/workflows/packages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
matrix:
format: [ rpm, deb ]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true

Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:

runs-on: [ ubuntu-latest ]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true

Expand All @@ -81,7 +81,7 @@ jobs:
ext: pkg
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true

Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:
contents: write
steps:
- name: Download all artefacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
with:
path: artifacts/

Expand Down
13 changes: 7 additions & 6 deletions lib/cmetrics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ else()
endif()

# Configuration options
option(CMT_DEV "Enable development mode" No)
option(CMT_DEBUG "Enable debug mode" No)
option(CMT_TESTS "Enable unit testing" No)
option(CMT_DEV "Enable development mode" No)
option(CMT_DEBUG "Enable debug mode" No)
option(CMT_TESTS "Enable unit testing" No)
option(CMT_INSTALL_TARGETS "Enable subdirectory library installations" Yes)
option(CMT_ENABLE_PROMETHEUS_DECODER "Enable prometheus decoder" Yes)
option(CMT_PROMETHEUS_TEXT_DECODER "Enable prometheus text format decoder (requires Flex/Bison)" Yes)

if(CMT_DEV)
set(CMT_TESTS Yes)
Expand Down Expand Up @@ -155,7 +155,7 @@ check_c_source_compiles("
return 0;
}" CMT_HAVE_MSGPACK)

if(CMT_ENABLE_PROMETHEUS_DECODER)
if(CMT_PROMETHEUS_TEXT_DECODER)
# Flex and Bison: check if the variables has not been defined before by
# a parent project to avoid conflicts.
if(NOT FLEX_FOUND)
Expand All @@ -167,7 +167,8 @@ if(CMT_ENABLE_PROMETHEUS_DECODER)
endif()

if(FLEX_FOUND AND BISON_FOUND)
set(CMT_BUILD_PROMETHEUS_DECODER 1)
set(CMT_BUILD_PROMETHEUS_TEXT_DECODER 1)
CMT_DEFINITION(CMT_HAVE_PROMETHEUS_TEXT_DECODER)
endif()
endif()

Expand Down
25 changes: 21 additions & 4 deletions lib/cmetrics/include/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
# Install headers conditionally based on Prometheus text decoder availability
file(GLOB cmetricsHeaders "cmetrics/*.h")
install(FILES ${cmetricsHeaders}
DESTINATION ${CMT_INSTALL_INCLUDEDIR}/cmetrics
COMPONENT headers
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

if(CMT_BUILD_PROMETHEUS_TEXT_DECODER)
# Install all headers when Prometheus text decoder is enabled
install(FILES ${cmetricsHeaders}
DESTINATION ${CMT_INSTALL_INCLUDEDIR}/cmetrics
COMPONENT headers
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
else()
# Install headers except Prometheus text decoder header when disabled
# (remote write decoder header is always installed)
foreach(header ${cmetricsHeaders})
get_filename_component(header_name ${header} NAME)
if(NOT header_name STREQUAL "cmt_decode_prometheus.h")
install(FILES ${header}
DESTINATION ${CMT_INSTALL_INCLUDEDIR}/cmetrics
COMPONENT headers
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
endif()
endforeach()
endif()

file(GLOB promHeaders "prometheus_remote_write/*.h")
install(FILES ${promHeaders}
Expand Down
6 changes: 6 additions & 0 deletions lib/cmetrics/include/cmetrics/cmt_decode_prometheus.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#ifndef CMT_DECODE_PROMETHEUS_H
#define CMT_DECODE_PROMETHEUS_H

#include <cmetrics/cmt_info.h>

#ifdef CMT_HAVE_PROMETHEUS_TEXT_DECODER

#include <stdbool.h>

#include <cmetrics/cmetrics.h>
Expand Down Expand Up @@ -110,4 +114,6 @@ int cmt_decode_prometheus_create(
struct cmt_decode_prometheus_parse_opts *opts);
void cmt_decode_prometheus_destroy(struct cmt *cmt);

#endif /* CMT_HAVE_PROMETHEUS_TEXT_DECODER */

#endif
17 changes: 10 additions & 7 deletions lib/cmetrics/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if (CMT_BUILD_PROMETHEUS_DECODER)
if (CMT_BUILD_PROMETHEUS_TEXT_DECODER)
flex_target(cmt_decode_prometheus_lexer cmt_decode_prometheus.l
"${FLEX_BISON_GENERATED_DIR}/cmt_decode_prometheus_lexer.c"
DEFINES_FILE "${FLEX_BISON_GENERATED_DIR}/cmt_decode_prometheus_lexer.h"
Expand Down Expand Up @@ -28,7 +28,6 @@ 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
Expand All @@ -37,12 +36,16 @@ set(src
cmt_decode_msgpack.c
cmt_decode_statsd.c
cmt_mpack_utils.c

# Prometheus related protobuf files
external/remote.pb-c.c
external/types.pb-c.c
)

# Add Prometheus remote write decoder (always available, only needs protobuf)
set(src ${src}
cmt_decode_prometheus_remote_write.c
# Prometheus related protobuf files
external/remote.pb-c.c
external/types.pb-c.c
)

Comment on lines +41 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Always-on remote write: ensure protobuf-c is linked and propagate it; also prefer list(APPEND).

Compiling external/*.pb-c.c introduces a hard link-time dependency on protobuf-c. cmetrics-static currently doesn’t declare/propagate that, which can break final linkage with static libs due to order/transitivity.

  • Within this hunk, switch to list(APPEND) for clarity:
- set(src ${src}
-     cmt_decode_prometheus_remote_write.c
-     # Prometheus related protobuf files
-     external/remote.pb-c.c
-     external/types.pb-c.c
-     )
+ list(APPEND src
+   cmt_decode_prometheus_remote_write.c
+   # Prometheus remote write protobufs
+   external/remote.pb-c.c
+   external/types.pb-c.c
+ )
  • Ensure cmetrics-static links protobuf-c and propagates it (adjust the exact target name to match your build, e.g., protobuf-c or protobuf-c::protobuf-c):
# Replace the existing line with a keyworded form and add protobuf-c
target_link_libraries(cmetrics-static
  PUBLIC mpack-static cfl-static fluent-otel-proto protobuf-c)
  • If protobuf-c discovery isn’t guaranteed earlier, fail fast with a clear message (optional):
if (NOT TARGET protobuf-c AND NOT PROTOBUF_C_FOUND)
  message(FATAL_ERROR "protobuf-c is required when building Prometheus remote write decoder")
endif()

Verification script to confirm discovery/links:


🏁 Script executed:

#!/bin/bash
# Check old var usages
rg -n --hidden -C2 '\bCMT_BUILD_PROMETHEUS_DECODER\b'

# Check protobuf-c discovery/targets
rg -n -C2 'find_package\((ProtobufC|protobuf-c)\b|pkg_check_modules\((PROTOBUF_C|protobuf-c)\b|target_link_libraries\([^)]+protobuf-?c' cmake CMakeLists.txt lib -g '!**/build/**'

Length of output: 0


🏁 Script executed:

#!/bin/bash
set -e

# Search for any find_package(ProtobufC) or find_package(protobuf-c) in CMake files
rg -n --type cmake 'find_package\([^)]*(ProtobufC|protobuf-c)' -C2 .

# Search for pkg_check_modules(PROTOBUF_C) in CMake files
rg -n --type cmake 'pkg_check_modules\([^)]*PROTOBUF_C' -C2 .

# Search for target_link_libraries references to protobuf libraries
rg -n 'target_link_libraries\([^)]+protobuf' -C2 .

# Check for the custom build flag CMT_BUILD_PROMETHEUS_DECODER
rg -n 'CMT_BUILD_PROMETHEUS_DECODER' -C2 .

Length of output: 0


🏁 Script executed:

#!/bin/bash
set -e
sed -n '1,200p' lib/cmetrics/src/CMakeLists.txt

Length of output: 2668


Always-on remote write: link protobuf-c and switch to list(APPEND)

  • In lib/cmetrics/src/CMakeLists.txt (around the block that adds external/*.pb-c.c), replace
    set(src ${src}
        cmt_decode_prometheus_remote_write.c
        external/remote.pb-c.c
        external/types.pb-c.c
    )
    with
    list(APPEND src
        cmt_decode_prometheus_remote_write.c
        external/remote.pb-c.c
        external/types.pb-c.c
    )
  • Add a find_package(ProtobufC REQUIRED) (or your preferred discovery) before appending the .pb-c.c files.
  • Update the static target to propagate protobuf-c:
    target_link_libraries(cmetrics-static
      PUBLIC mpack-static cfl-static fluent-otel-proto protobuf-c
    )
  • (Optional) Fail fast if protobuf-c isn’t available:
    if (NOT TARGET protobuf-c AND NOT PROTOBUF_C_FOUND)
      message(FATAL_ERROR "protobuf-c is required for the Prometheus remote-write decoder")
    endif()
🤖 Prompt for AI Agents
In lib/cmetrics/src/CMakeLists.txt around lines 41 to 48, replace the set(...)
that adds cmt_decode_prometheus_remote_write.c and the generated
external/*.pb-c.c files with list(APPEND src ...) so the files are appended
instead of resetting the variable; add a find_package(ProtobufC REQUIRED) (or
equivalent discovery) before appending the .pb-c.c files; update the
cmetrics-static target to link against protobuf-c by adding protobuf-c to
target_link_libraries(cmetrics-static PUBLIC ...); and (optionally) add a short
check that fails fast with message(FATAL_ERROR ...) if protobuf-c isn’t found
(i.e., if neither TARGET protobuf-c nor PROTOBUF_C_FOUND).


if (MSVC)
set(PLATFORM_SPECIFIC_ATOMIC_MODULE cmt_atomic_msvc.c)
Expand All @@ -63,7 +66,7 @@ set(src
${PLATFORM_SPECIFIC_ATOMIC_MODULE}
)

if (CMT_BUILD_PROMETHEUS_DECODER)
if (CMT_BUILD_PROMETHEUS_TEXT_DECODER)
set(src ${src}
${FLEX_cmt_decode_prometheus_lexer_OUTPUTS}
${BISON_cmt_decode_prometheus_parser_OUTPUTS}
Expand Down
2 changes: 1 addition & 1 deletion lib/cmetrics/src/cmt_cat.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static inline int cat_histogram_values(struct cmt_metric *metric_dst, struct cmt
}
}

for (i = 0; i <= histogram->buckets->count; i++) {
for (i = 0; i < histogram->buckets->count; i++) {
/* histogram buckets are always integers, no need to convert them */
metric_dst->hist_buckets[i] += metric_src->hist_buckets[i];
}
Comment on lines +111 to 114
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Histogram concatenation drops the +Inf bucket.

hist_buckets has length count + 1; iterating with < count excludes the +Inf bucket at index count, producing incorrect merged histograms.

Apply:

-    for (i = 0; i < histogram->buckets->count; i++) {
+    for (i = 0; i <= histogram->buckets->count; i++) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (i = 0; i < histogram->buckets->count; i++) {
/* histogram buckets are always integers, no need to convert them */
metric_dst->hist_buckets[i] += metric_src->hist_buckets[i];
}
for (i = 0; i <= histogram->buckets->count; i++) {
/* histogram buckets are always integers, no need to convert them */
metric_dst->hist_buckets[i] += metric_src->hist_buckets[i];
}
🤖 Prompt for AI Agents
In lib/cmetrics/src/cmt_cat.c around lines 111 to 114, the loop iterates only up
to histogram->buckets->count - 1 and thus omits the +Inf bucket at index count;
update the iteration to include the final bucket (either change the loop
condition to iterate up to and including count, or compute bucket_len =
histogram->buckets->count + 1 and loop i < bucket_len) so
metric_dst->hist_buckets accumulates the +Inf bucket as well.

Expand Down
1 change: 1 addition & 0 deletions lib/cmetrics/src/cmt_decode_prometheus.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ static int split_metric_name(struct cmt_decode_prometheus_context *context,
*subsystem = strchr(*ns, '_');
if (!(*subsystem)) {
*name = *ns;
*subsystem = "";
*ns = "";
}
else {
Expand Down
2 changes: 1 addition & 1 deletion lib/cmetrics/src/cmt_histogram.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct cmt_histogram_buckets *cmt_histogram_buckets_create_size(double *bkts, si
}

/* besides buckets set by the user, we add an implicit bucket for +inf */
upper_bounds = calloc(1, sizeof(double) * (count + 1));
upper_bounds = calloc(1, sizeof(double) * count + 1);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix calloc under-allocation (parentheses bug).

Allocates sizeof(double) * count + 1 bytes instead of (count + 1) * sizeof(double) (or just count * sizeof(double)). This can corrupt memory when writing bucket bounds.

Apply one of the safe patterns (consistent with the rest of this file, upper_bounds has length = count):

-    upper_bounds = calloc(1, sizeof(double) * count + 1);
+    upper_bounds = calloc(count, sizeof(double));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
upper_bounds = calloc(1, sizeof(double) * count + 1);
upper_bounds = calloc(count, sizeof(double));
🤖 Prompt for AI Agents
In lib/cmetrics/src/cmt_histogram.c around line 39, the calloc call is
under-allocating due to missing parentheses (it does sizeof(double) * count +
1); replace it with a correct allocation matching the intended length: use
calloc(count, sizeof(double)) if upper_bounds length == count (or calloc(count +
1, sizeof(double)) if an extra slot is needed), ensuring the multiplication is
done before addition; keep the allocation pattern consistent with the rest of
the file and check for NULL return as done elsewhere.

if (!upper_bounds) {
cmt_errno();
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion lib/cmetrics/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ set(UNIT_TESTS_FILES
filter.c
)

if (CMT_BUILD_PROMETHEUS_DECODER)
if (CMT_BUILD_PROMETHEUS_TEXT_DECODER)
set(UNIT_TESTS_FILES
${UNIT_TESTS_FILES}
prometheus_lexer.c
Expand Down
35 changes: 35 additions & 0 deletions lib/cmetrics/tests/issues.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <cmetrics/cmt_encode_msgpack.h>
#include <cmetrics/cmt_decode_msgpack.h>
#include <cmetrics/cmt_encode_text.h>
#include <cmetrics/cmt_decode_prometheus.h>
#include <cmetrics/cmt_encode_prometheus.h>

#include "cmt_tests.h"

Expand Down Expand Up @@ -89,7 +91,40 @@ void test_issue_54()
cmt_destroy(cmt1);
}

#ifdef CMT_HAVE_PROMETHEUS_TEXT_DECODER

/* issue: https://github.com/fluent/fluent-bit/issues/10761 */
void test_prometheus_metric_no_subsystem()
{
const char text[] =
"# HELP up A simple example metric no subsystem\n"
"# TYPE up gauge\n"
"up{job=\"42\"} 1\n";
struct cmt *cmt;
cfl_sds_t result;
int ret;

cmt_initialize();

ret = cmt_decode_prometheus_create(&cmt, text, strlen(text), NULL);
TEST_CHECK(ret == CMT_DECODE_PROMETHEUS_SUCCESS);
if (ret == CMT_DECODE_PROMETHEUS_SUCCESS) {
result = cmt_encode_prometheus_create(cmt, CMT_TRUE);
TEST_CHECK(result != NULL);
if (result) {
TEST_CHECK(strstr(result, "up{job=\"42\"} 1") != NULL);
cmt_encode_prometheus_destroy(result);
}
cmt_decode_prometheus_destroy(cmt);
}
}

#endif

TEST_LIST = {
{"issue_54", test_issue_54},
#ifdef CMT_HAVE_PROMETHEUS_TEXT_DECODER
{"prometheus_metric_no_subsystem", test_prometheus_metric_no_subsystem},
#endif
{ 0 }
};
2 changes: 1 addition & 1 deletion lib/monkey/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ endif()
# Monkey Version
set(MK_VERSION_MAJOR 1)
set(MK_VERSION_MINOR 8)
set(MK_VERSION_PATCH 4)
set(MK_VERSION_PATCH 5)
set(MK_VERSION_STR "${MK_VERSION_MAJOR}.${MK_VERSION_MINOR}.${MK_VERSION_PATCH}")

# Output paths
Expand Down
18 changes: 10 additions & 8 deletions lib/monkey/mk_server/mk_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ void mk_http_request_init(struct mk_http_session *session,
session->channel,
NULL,
NULL, NULL, NULL);

/* Initialize headers input stream */
request->in_headers.type = MK_STREAM_IOV;
request->in_headers.dynamic = MK_FALSE;
request->in_headers.cb_consumed = NULL;
request->in_headers.cb_finished = NULL;
request->in_headers.buffer = NULL;
request->in_headers.bytes_total = 0;
request->in_headers.stream = &request->stream;
mk_list_add(&request->in_headers._head, &request->stream.inputs);
}

static inline int mk_http_point_header(mk_ptr_t *h,
Expand Down Expand Up @@ -722,14 +732,6 @@ int mk_http_init(struct mk_http_session *cs, struct mk_http_request *sr,

ret_file = mk_file_get_info(sr->real_path.data, &sr->file_info, MK_FILE_READ);

/* Manually set the headers input streams */
sr->in_headers.type = MK_STREAM_IOV;
sr->in_headers.dynamic = MK_FALSE;
sr->in_headers.cb_consumed = NULL;
sr->in_headers.cb_finished = NULL;
sr->in_headers.stream = &sr->stream;
mk_list_add(&sr->in_headers._head, &sr->stream.inputs);

/* Plugin Stage 30: look for handlers for this request */
if (sr->stage30_blocked == MK_FALSE) {
sr->uri_processed.data[sr->uri_processed.len] = '\0';
Expand Down
Loading