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 b295acab3f0630b3ca87a49d7964d7d68d4c01c6
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
---
 src/couch_prometheus/src/couch_prometheus_util.erl | 25 ++++++++++++++++++----
 .../test/eunit/couch_prometheus_e2e_tests.erl      |  4 ++--
 2 files changed, 23 insertions(+), 6 deletions(-)

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()
     ).
 

Reply via email to