This is an automated email from the ASF dual-hosted git repository. willholley pushed a commit to branch wh/fix-prometheus in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit c926e8fc4fa36048d45e412fc98b7e296d98f441 Author: Will Holley <[email protected]> AuthorDate: Fri Nov 28 16:54:40 2025 +0000 fix: prometheus metrics annotations ## Why Previously, the `_node/_local/_prometheus` endpoints would return invalid annotations for certain metrics. For example: ``` # TYPE couchdb_database_reads_total counterof times a document was read from a database couchdb_database_reads_total 2208 ``` In general this doesn't matter too much - prometheus will infer the type from the metric name - but some clients will respect it and generate errors/warnings if the annotations are incorrect. ## What This removes the carriage returns from the prometheus output. These were added as an incorrect fix to spurious newlines in the output but caused this bug with the annotations. The actual bug causing the additional newlines is that the result of `type_def/3` was additionally wrapped in a list. This commit removes the re-wrapping. removes the carriage return and adds a test for the output. This changes the output of `to_prom` slightly because the first element of the result is no longer --- .devcontainer/Dockerfile | 2 +- .devcontainer/devcontainer.json | 9 ++++---- src/couch_prometheus/src/couch_prometheus_util.erl | 25 ++++++++++++++++++---- .../test/eunit/couch_prometheus_e2e_tests.erl | 4 ++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2f4672d1b..2670d8795 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,7 +2,7 @@ ARG COUCHDB_IMAGE FROM ${COUCHDB_IMAGE} # Install SpiderMonkey 78 and tell CouchDB to use it in configure -#ENV SM_VSN= +ENV SM_VSN=78 USER root diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5befbbf48..eb0831cf5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,10 +5,11 @@ "context": "..", "args": { // Useful choices include: - // apache/couchdbci-debian:bookworm-erlang-28.2 - // apache/couchdbci-debian:bookworm-erlang-27.3.4.6 + // apache/couchdbci-debian:bullseye-erlang-26.1.2 + // apache/couchdbci-debian:bullseye-erlang-25.3.2.7 + // apache/couchdbci-debian:bookworm-erlang-24.3.4.14 // - "COUCHDB_IMAGE": "apache/couchdbci-debian:bookworm-erlang-27.3.4.6" + "COUCHDB_IMAGE": "apache/couchdbci-debian:bullseye-erlang-24.3.4.14" } }, @@ -22,7 +23,7 @@ // Your code will live inside the volume created for the container under /workspace. "workspaceMount": "target=/workspaces/couchdb,type=volume", "workspaceFolder": "/workspaces/couchdb", - "postCreateCommand": "./configure --disable-spidermonkey --with-nouveau --with-clouseau && make", + "postCreateCommand": "./configure --with-nouveau --with-clouseau && make", "customizations": { "vscode": { diff --git a/src/couch_prometheus/src/couch_prometheus_util.erl b/src/couch_prometheus/src/couch_prometheus_util.erl index 2ae927656..d010461d6 100644 --- a/src/couch_prometheus/src/couch_prometheus_util.erl +++ b/src/couch_prometheus/src/couch_prometheus_util.erl @@ -116,7 +116,7 @@ couch_to_prom(Path, Info, _All) -> type_def(Metric, Type, Desc) -> Name = to_prom_name(Metric), [ - to_bin(io_lib:format("\n# HELP ~s ~s\r", [Name, Desc])), + to_bin(io_lib:format("\n# HELP ~s ~s", [Name, Desc])), to_bin(io_lib:format("# TYPE ~s ~s", [Name, Type])) ]. @@ -126,7 +126,7 @@ to_prom(_Metric, _Type, _Desc, []) -> []; to_prom(Metric, Type, Desc, Instances) when is_list(Instances) -> TypeStr = type_def(Metric, Type, Desc), - [TypeStr] ++ lists:flatmap(fun(Inst) -> to_prom(Metric, Inst) end, Instances); + TypeStr ++ lists:flatmap(fun(Inst) -> to_prom(Metric, Inst) end, Instances); to_prom(Metric, Type, Desc, Data) -> to_prom(Metric, Type, Desc, [Data]). @@ -221,6 +221,23 @@ desc(Info) -> -ifdef(TEST). -include_lib("couch/include/couch_eunit.hrl"). +to_prom_annotations_test() -> + Out = to_prom(couchdb_bt_engine_cache_size, gauge, "number of entries in the btree cache", 9), + [ + ?assertEqual( + <<"\n# HELP couchdb_couchdb_bt_engine_cache_size number of entries in the btree cache">>, + lists:nth(1, Out) + ), + ?assertEqual( + <<"# TYPE couchdb_couchdb_bt_engine_cache_size gauge">>, + lists:nth(2, Out) + ), + ?assertEqual( + <<"couchdb_couchdb_bt_engine_cache_size 9">>, + lists:nth(3, Out) + ) + ]. + to_prom_counter_test() -> [ ?assertEqual( @@ -288,10 +305,10 @@ counter_metric_test_() -> test_to_prom_output(Metric, Type, Desc, Val) -> Out = to_prom(Metric, Type, Desc, Val), - lists:nth(2, Out). + lists:nth(3, Out). test_to_prom_summary_output(Metric, Info) -> Out = to_prom_summary(Metric, Info), - lists:nth(3, Out). + lists:nth(4, Out). -endif. diff --git a/src/couch_prometheus/test/eunit/couch_prometheus_e2e_tests.erl b/src/couch_prometheus/test/eunit/couch_prometheus_e2e_tests.erl index 383871721..dd8da5f79 100644 --- a/src/couch_prometheus/test/eunit/couch_prometheus_e2e_tests.erl +++ b/src/couch_prometheus/test/eunit/couch_prometheus_e2e_tests.erl @@ -177,12 +177,12 @@ t_survives_mem3_sync_termination(_) -> ok = supervisor:terminate_child(mem3_sup, mem3_sync), ?assertEqual(undefined, whereis(mem3_sync)), ?assertMatch( - [[_, _], <<"couchdb_internal_replication_jobs 0">>], + [_, _, <<"couchdb_internal_replication_jobs 0">>], couch_prometheus:get_internal_replication_jobs_stat() ), {ok, _} = supervisor:restart_child(mem3_sup, mem3_sync), ?assertMatch( - [[_, _], <<"couchdb_internal_replication_jobs", _/binary>>], + [_, _, <<"couchdb_internal_replication_jobs", _/binary>>], couch_prometheus:get_internal_replication_jobs_stat() ).
