This is an automated email from the ASF dual-hosted git repository.

chewbranca pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
     new ab2cf16a6 Add dbname to mango exec stats (#4990)
ab2cf16a6 is described below

commit ab2cf16a60f4cf1cdde7b3f8c2b8e9828ca46fe5
Author: Russell Branca <chewbra...@apache.org>
AuthorDate: Tue Mar 5 14:44:07 2024 -0800

    Add dbname to mango exec stats (#4990)
    
    * WIP: include dbname in mango exec stats
    
    * Don't output dbname in exec stats http response
    
    * Make sure mango nouveau logs reports
    
    * Test that mango reports get the dbname in the stats
    
    * With compliant formatting
    
    * Switch to adding exec stats dbname during create
    
    * Add stats to explain cursor
    
    * Add stats to mango cursor special
    
    * Fix mango special cursor test
---
 src/mango/src/mango_cursor.erl          |  4 +-
 src/mango/src/mango_cursor.hrl          |  2 +-
 src/mango/src/mango_cursor_nouveau.erl  |  7 ++-
 src/mango/src/mango_cursor_special.erl  | 22 ++++++++--
 src/mango/src/mango_cursor_text.erl     | 25 +++++++----
 src/mango/src/mango_cursor_view.erl     | 76 ++++++++++++++++++++++++++-------
 src/mango/src/mango_execution_stats.erl | 26 +++++++++--
 src/mango/src/mango_execution_stats.hrl |  3 +-
 8 files changed, 132 insertions(+), 33 deletions(-)

diff --git a/src/mango/src/mango_cursor.erl b/src/mango/src/mango_cursor.erl
index 3eedc7383..deb5d9144 100644
--- a/src/mango/src/mango_cursor.erl
+++ b/src/mango/src/mango_cursor.erl
@@ -424,6 +424,7 @@ create_cursor(Db, {[], Trace0}, Selector, Opts) ->
     Skip = couch_util:get_value(skip, Opts, 0),
     Fields = couch_util:get_value(fields, Opts, all_fields),
     Bookmark = couch_util:get_value(bookmark, Opts),
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
     {ok, #cursor{
         db = Db,
         index = none,
@@ -433,7 +434,8 @@ create_cursor(Db, {[], Trace0}, Selector, Opts) ->
         limit = Limit,
         skip = Skip,
         fields = Fields,
-        bookmark = Bookmark
+        bookmark = Bookmark,
+        execution_stats = Stats
     }};
 create_cursor(Db, {Indexes, Trace0}, Selector, Opts) ->
     Trace1 = maps:merge(Trace0, #{filtered_indexes => 
sets:from_list(Indexes)}),
diff --git a/src/mango/src/mango_cursor.hrl b/src/mango/src/mango_cursor.hrl
index 6e5ffd6d9..cf02492a3 100644
--- a/src/mango/src/mango_cursor.hrl
+++ b/src/mango/src/mango_cursor.hrl
@@ -25,7 +25,7 @@
     fields = undefined,
     user_fun,
     user_acc,
-    execution_stats = #execution_stats{},
+    execution_stats,
     bookmark,
     bookmark_docid,
     bookmark_key
diff --git a/src/mango/src/mango_cursor_nouveau.erl 
b/src/mango/src/mango_cursor_nouveau.erl
index 5471ea46a..71beb053f 100644
--- a/src/mango/src/mango_cursor_nouveau.erl
+++ b/src/mango/src/mango_cursor_nouveau.erl
@@ -53,6 +53,8 @@ create(Db, {Indexes, Trace}, Selector, Opts) ->
     Skip = couch_util:get_value(skip, Opts, 0),
     Fields = couch_util:get_value(fields, Opts, all_fields),
 
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
+
     {ok, #cursor{
         db = Db,
         index = Index,
@@ -62,7 +64,8 @@ create(Db, {Indexes, Trace}, Selector, Opts) ->
         opts = Opts,
         limit = Limit,
         skip = Skip,
-        fields = Fields
+        fields = Fields,
+        execution_stats = Stats
     }}.
 
 explain(Cursor) ->
@@ -128,6 +131,8 @@ execute(Cursor, UserFun, UserAcc) ->
             {FinalUserAcc0, Stats1} = mango_execution_stats:maybe_add_stats(
                 Opts, UserFun, Stats0, FinalUserAcc
             ),
+            %% This needs Stats1 as log_end is called in maybe_add_stats
+            mango_execution_stats:log_stats(Stats1),
             FinalUserAcc1 = mango_cursor:maybe_add_warning(UserFun, Cursor, 
Stats1, FinalUserAcc0),
             {ok, FinalUserAcc1}
     end.
diff --git a/src/mango/src/mango_cursor_special.erl 
b/src/mango/src/mango_cursor_special.erl
index 1891ba6d0..c466b5db1 100644
--- a/src/mango/src/mango_cursor_special.erl
+++ b/src/mango/src/mango_cursor_special.erl
@@ -45,6 +45,7 @@ create(Db, {Indexes, Trace0}, Selector, Opts) ->
     Skip = couch_util:get_value(skip, Opts, 0),
     Fields = couch_util:get_value(fields, Opts, all_fields),
     Bookmark = couch_util:get_value(bookmark, Opts),
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
 
     IndexRanges1 = mango_cursor:maybe_noop_range(Selector, IndexRanges),
     Trace = maps:merge(Trace0, #{sorted_index_ranges => SortedIndexRanges}),
@@ -59,7 +60,8 @@ create(Db, {Indexes, Trace0}, Selector, Opts) ->
         limit = Limit,
         skip = Skip,
         fields = Fields,
-        bookmark = Bookmark
+        bookmark = Bookmark,
+        execution_stats = Stats
     }}.
 
 explain(Cursor) ->
@@ -74,13 +76,26 @@ handle_message(Msg, Cursor) ->
 -ifdef(TEST).
 -include_lib("couch/include/couch_eunit.hrl").
 
-create_test() ->
+create_test_() ->
+    {
+        foreach,
+        fun() ->
+            meck:expect(couch_db, name, fun(A) when is_atom(A) -> 
atom_to_binary(A) end)
+        end,
+        fun(_) -> meck:unload() end,
+        [
+            ?TDEF_FE(t_create)
+        ]
+    }.
+
+t_create(_) ->
     Index = #idx{type = <<"special">>, def = all_docs},
     Indexes = [Index],
     Ranges = [{'$gt', null, '$lt', mango_json_max}],
     Trace = #{},
     Selector = {[]},
     Options = [{limit, limit}, {skip, skip}, {fields, fields}, {bookmark, 
bookmark}],
+    Stats = mango_execution_stats:stats_init(couch_db:name(db)),
     Cursor =
         #cursor{
             db = db,
@@ -92,7 +107,8 @@ create_test() ->
             skip = skip,
             fields = fields,
             bookmark = bookmark,
-            trace = #{sorted_index_ranges => [{Index, Ranges, 0}]}
+            trace = #{sorted_index_ranges => [{Index, Ranges, 0}]},
+            execution_stats = Stats
         },
     ?assertEqual({ok, Cursor}, create(db, {Indexes, Trace}, Selector, 
Options)).
 
diff --git a/src/mango/src/mango_cursor_text.erl 
b/src/mango/src/mango_cursor_text.erl
index ee1d962f7..6d2204070 100644
--- a/src/mango/src/mango_cursor_text.erl
+++ b/src/mango/src/mango_cursor_text.erl
@@ -50,7 +50,9 @@ create(Db, {Indexes, Trace}, Selector, Opts0) ->
                 ?MANGO_ERROR(multiple_text_indexes)
         end,
 
-    Opts = unpack_bookmark(couch_db:name(Db), Opts0),
+    DbName = couch_db:name(Db),
+    Opts = unpack_bookmark(DbName, Opts0),
+    Stats = mango_execution_stats:stats_init(DbName),
 
     DreyfusLimit = get_dreyfus_limit(),
     Limit = erlang:min(DreyfusLimit, couch_util:get_value(limit, Opts, 
mango_opts:default_limit())),
@@ -66,7 +68,8 @@ create(Db, {Indexes, Trace}, Selector, Opts0) ->
         opts = Opts,
         limit = Limit,
         skip = Skip,
-        fields = Fields
+        fields = Fields,
+        execution_stats = Stats
     }}.
 
 explain(Cursor) ->
@@ -389,8 +392,10 @@ t_create_regular(_) ->
     Limit = 10,
     Options = [{limit, Limit}, {skip, skip}, {fields, fields}, {bookmark, 
bookmark}],
     Options1 = [{limit, Limit}, {skip, skip}, {fields, fields}, {bookmark, 
unpacked_bookmark}],
+    Db = db,
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
     Cursor = #cursor{
-        db = db,
+        db = Db,
         index = Index,
         ranges = null,
         trace = Trace,
@@ -398,17 +403,20 @@ t_create_regular(_) ->
         opts = Options1,
         limit = Limit,
         skip = skip,
-        fields = fields
+        fields = fields,
+        execution_stats = Stats
     },
     meck:expect(dreyfus_bookmark, unpack, [db_name, bookmark], 
meck:val(unpacked_bookmark)),
-    ?assertEqual({ok, Cursor}, create(db, {Indexes, Trace}, selector, 
Options)).
+    ?assertEqual({ok, Cursor}, create(Db, {Indexes, Trace}, selector, 
Options)).
 
 t_create_no_bookmark(_) ->
     Limit = 99,
     Options = [{limit, Limit}, {skip, skip}, {fields, fields}, {bookmark, 
nil}],
     Options1 = [{limit, Limit}, {skip, skip}, {fields, fields}, {bookmark, 
[]}],
+    Db = db,
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
     Cursor = #cursor{
-        db = db,
+        db = Db,
         index = index,
         ranges = null,
         trace = trace,
@@ -416,9 +424,10 @@ t_create_no_bookmark(_) ->
         opts = Options1,
         limit = Limit,
         skip = skip,
-        fields = fields
+        fields = fields,
+        execution_stats = Stats
     },
-    ?assertEqual({ok, Cursor}, create(db, {[index], trace}, selector, 
Options)).
+    ?assertEqual({ok, Cursor}, create(Db, {[index], trace}, selector, 
Options)).
 
 t_create_invalid_bookmark(_) ->
     Options = [{bookmark, invalid}],
diff --git a/src/mango/src/mango_cursor_view.erl 
b/src/mango/src/mango_cursor_view.erl
index b103d869d..ac8714aa7 100644
--- a/src/mango/src/mango_cursor_view.erl
+++ b/src/mango/src/mango_cursor_view.erl
@@ -105,6 +105,8 @@ create(Db, {Indexes, Trace0}, Selector, Opts) ->
     IndexRanges1 = mango_cursor:maybe_noop_range(Selector, IndexRanges),
     Trace = maps:merge(Trace0, #{sorted_index_ranges => SortedIndexRanges}),
 
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
+
     {ok, #cursor{
         db = Db,
         index = Index,
@@ -115,7 +117,8 @@ create(Db, {Indexes, Trace0}, Selector, Opts) ->
         limit = Limit,
         skip = Skip,
         fields = Fields,
-        bookmark = Bookmark
+        bookmark = Bookmark,
+        execution_stats = Stats
     }}.
 
 -spec required_fields(#cursor{}) -> fields().
@@ -906,16 +909,30 @@ composite_indexes_test() ->
     ],
     ?assertEqual(Result, composite_indexes(Indexes, Ranges)).
 
-create_test() ->
+create_test_() ->
+    {
+        foreach,
+        fun() ->
+            meck:expect(couch_db, name, fun(A) when is_atom(A) -> 
atom_to_binary(A) end)
+        end,
+        fun(_) -> meck:unload() end,
+        [
+            ?TDEF_FE(t_create_ok)
+        ]
+    }.
+
+t_create_ok(_) ->
     Index = #idx{type = <<"json">>, def = {[{<<"fields">>, {[]}}]}},
     Indexes = [Index],
     Trace = #{},
     Ranges = [],
     Selector = {[]},
     Options = [{limit, limit}, {skip, skip}, {fields, fields}, {bookmark, 
bookmark}],
+    Db = db,
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
     Cursor =
         #cursor{
-            db = db,
+            db = Db,
             index = Index,
             ranges = Ranges,
             selector = Selector,
@@ -924,9 +941,10 @@ create_test() ->
             skip = skip,
             fields = fields,
             bookmark = bookmark,
-            trace = #{sorted_index_ranges => [{Index, [], 0}]}
+            trace = #{sorted_index_ranges => [{Index, [], 0}]},
+            execution_stats = Stats
         },
-    ?assertEqual({ok, Cursor}, create(db, {Indexes, Trace}, Selector, 
Options)).
+    ?assertEqual({ok, Cursor}, create(Db, {Indexes, Trace}, Selector, 
Options)).
 
 to_selector(Map) ->
     test_util:as_selector(Map).
@@ -993,7 +1011,8 @@ execute_test_() ->
         fun() ->
             meck:new(foo, [non_strict]),
             meck:new(fabric),
-            meck:new(chttpd_stats)
+            meck:new(chttpd_stats),
+            meck:expect(couch_db, name, fun(A) when is_atom(A) -> 
atom_to_binary(A) end)
         end,
         fun(_) -> meck:unload() end,
         [
@@ -1007,7 +1026,9 @@ execute_test_() ->
     }.
 
 t_execute_empty(_) ->
-    Cursor = #cursor{ranges = [empty]},
+    Db = db,
+    Stats = mango_execution_stats:stats_init(couch_db:name(Db)),
+    Cursor = #cursor{ranges = [empty], execution_stats = Stats},
     meck:expect(fabric, all_docs, ['_', '_', '_', '_', '_'], meck:val(error)),
     meck:expect(fabric, query_view, ['_', '_', '_', '_', '_', '_'], 
meck:val(error)),
     ?assertEqual({ok, accumulator}, execute(Cursor, undefined, accumulator)),
@@ -1023,6 +1044,7 @@ t_execute_ok_all_docs(_) ->
     Index = #idx{type = <<"json">>, def = all_docs},
     Selector = {[]},
     Fields = all_fields,
+    Stats = mango_execution_stats:stats_init(db),
     Cursor =
         #cursor{
             index = Index,
@@ -1031,7 +1053,8 @@ t_execute_ok_all_docs(_) ->
             fields = Fields,
             ranges = [{'$gte', start_key, '$lte', end_key}],
             opts = [{user_ctx, user_ctx}],
-            bookmark = nil
+            bookmark = nil,
+            execution_stats = Stats
         },
     Cursor1 =
         Cursor#cursor{
@@ -1050,7 +1073,8 @@ t_execute_ok_all_docs(_) ->
                 #execution_stats{
                     totalKeysExamined = TotalKeysExamined,
                     totalDocsExamined = TotalDocsExamined,
-                    executionStartTime = {0, 0, 0}
+                    executionStartTime = {0, 0, 0},
+                    dbname = db
                 }
         },
     Extra =
@@ -1089,6 +1113,7 @@ t_execute_ok_query_view(_) ->
     IndexScanWarning =
         <<"The number of documents examined is high in proportion to the 
number of results returned. Consider adding a more specific index to improve 
this.">>,
     UserFnParameters2 = [{add_key, warning, IndexScanWarning}, accumulator2],
+    Stats = mango_execution_stats:stats_init(db),
     meck:expect(
         foo,
         bar,
@@ -1114,7 +1139,8 @@ t_execute_ok_query_view(_) ->
             fields = Fields,
             ranges = [{'$gte', start_key, '$lte', end_key}],
             opts = [{user_ctx, user_ctx}],
-            bookmark = nil
+            bookmark = nil,
+            execution_stats = Stats
         },
     Cursor1 =
         Cursor#cursor{
@@ -1131,6 +1157,7 @@ t_execute_ok_query_view(_) ->
             bookmark_key = undefined,
             execution_stats =
                 #execution_stats{
+                    dbname = db,
                     totalKeysExamined = TotalKeysExamined,
                     totalDocsExamined = TotalDocsExamined,
                     executionStartTime = {0, 0, 0}
@@ -1174,18 +1201,22 @@ t_execute_ok_query_view(_) ->
 
 t_execute_ok_all_docs_with_execution_stats(_) ->
     Bookmark = bookmark,
+    DbName = db,
     TotalKeysExamined = 33,
     TotalDocsExamined = 12,
     TotalQuorumDocsExamined = 0,
     ResultsReturned = 20,
+    InitStats = mango_execution_stats:stats_init(couch_db:name(DbName)),
     ExecutionStats =
         #execution_stats{
             totalKeysExamined = TotalKeysExamined,
             totalDocsExamined = TotalDocsExamined,
             totalQuorumDocsExamined = TotalQuorumDocsExamined,
             resultsReturned = ResultsReturned,
-            executionStartTime = {0, 0, 0}
+            executionStartTime = {0, 0, 0},
+            dbname = DbName
         },
+    %% Stats doesn't include dbname as it will have already been stripped out
     Stats =
         {[
             {total_keys_examined, TotalKeysExamined},
@@ -1209,12 +1240,13 @@ t_execute_ok_all_docs_with_execution_stats(_) ->
     Cursor =
         #cursor{
             index = Index,
-            db = db,
+            db = DbName,
             selector = Selector,
             fields = Fields,
             ranges = [{'$gte', start_key, '$lte', end_key}],
             opts = [{user_ctx, user_ctx}, {execution_stats, true}],
-            bookmark = nil
+            bookmark = nil,
+            execution_stats = InitStats
         },
     Cursor1 =
         Cursor#cursor{
@@ -1253,13 +1285,24 @@ t_execute_ok_all_docs_with_execution_stats(_) ->
     Parameters = [
         db, [{user_ctx, user_ctx}], fun 
mango_cursor_view:handle_all_docs_message/2, Cursor1, Args
     ],
+    meck:new(couch_log, [passthrough]),
+    %% Pattern matching on DbName in the fun head results in a shadowed 
variable
+    %% warning. Creating a new variable and testing in the guard works around 
this.
+    meck:expect(
+        couch_log,
+        report,
+        fun("mango-stats", #{dbname := DbName1}) when DbName1 =:= DbName -> 
true end
+    ),
+    meck:expect(chttpd_stats, incr_rows, [TotalKeysExamined], meck:val(ok)),
     meck:expect(chttpd_stats, incr_rows, [TotalKeysExamined], meck:val(ok)),
     meck:expect(chttpd_stats, incr_reads, [TotalDocsExamined], meck:val(ok)),
     meck:expect(fabric, all_docs, Parameters, meck:val({ok, Cursor2})),
     ?assertEqual({ok, updated_accumulator2}, execute(Cursor, fun foo:bar/2, 
accumulator)),
+    ?assert(meck:called(couch_log, report, '_')),
     ?assert(meck:called(fabric, all_docs, '_')).
 
 t_execute_error_1(_) ->
+    Stats = mango_execution_stats:stats_init(db),
     Cursor =
         #cursor{
             index = #idx{type = <<"json">>, ddoc = <<"_design/ghibli">>, name 
= index_name},
@@ -1268,7 +1311,8 @@ t_execute_error_1(_) ->
             fields = all_fields,
             ranges = [{'$gte', start_key, '$lte', end_key}],
             opts = [{user_ctx, user_ctx}],
-            bookmark = nil
+            bookmark = nil,
+            execution_stats = Stats
         },
     Parameters = [
         db, '_', <<"ghibli">>, index_name, fun 
mango_cursor_view:handle_message/2, '_', '_'
@@ -1279,6 +1323,7 @@ t_execute_error_1(_) ->
     ?assertNot(meck:called(chttpd_stats, incr_reads, '_')).
 
 t_execute_error_2(_) ->
+    Stats = mango_execution_stats:stats_init(db),
     Cursor =
         #cursor{
             index = #idx{type = <<"json">>, ddoc = <<"_design/ghibli">>, name 
= index_name},
@@ -1287,7 +1332,8 @@ t_execute_error_2(_) ->
             fields = all_fields,
             ranges = [{'$gte', start_key, '$lte', end_key}],
             opts = [{user_ctx, user_ctx}],
-            bookmark = nil
+            bookmark = nil,
+            execution_stats = Stats
         },
     Parameters = [
         db, '_', <<"ghibli">>, index_name, fun 
mango_cursor_view:handle_message/2, '_', '_'
diff --git a/src/mango/src/mango_execution_stats.erl 
b/src/mango/src/mango_execution_stats.erl
index dce7c087b..67a1edd0a 100644
--- a/src/mango/src/mango_execution_stats.erl
+++ b/src/mango/src/mango_execution_stats.erl
@@ -13,7 +13,7 @@
 -module(mango_execution_stats).
 
 -export([
-    to_json/1,
+    to_json/1, to_json/2,
     to_map/1,
     incr_keys_examined/1,
     incr_keys_examined/2,
@@ -28,7 +28,8 @@
     shard_init/0,
     shard_incr_keys_examined/0,
     shard_incr_docs_examined/0,
-    shard_get_stats/0
+    shard_get_stats/0,
+    stats_init/0, stats_init/1
 ]).
 
 -include("mango.hrl").
@@ -36,13 +37,31 @@
 
 -define(SHARD_STATS_KEY, mango_shard_execution_stats).
 
+stats_init() ->
+    #execution_stats{}.
+
+stats_init(DbName) ->
+    Stats = stats_init(),
+    Stats#execution_stats{dbname = DbName}.
+
 to_json(Stats) ->
+    to_json(Stats, true).
+
+to_json(Stats, IncludeDbName) ->
+    Base =
+        case IncludeDbName of
+            true ->
+                [{dbname, Stats#execution_stats.dbname}];
+            false ->
+                []
+        end,
     {[
         {total_keys_examined, Stats#execution_stats.totalKeysExamined},
         {total_docs_examined, Stats#execution_stats.totalDocsExamined},
         {total_quorum_docs_examined, 
Stats#execution_stats.totalQuorumDocsExamined},
         {results_returned, Stats#execution_stats.resultsReturned},
         {execution_time_ms, Stats#execution_stats.executionTimeMs}
+        | Base
     ]}.
 
 to_map(Stats) ->
@@ -51,6 +70,7 @@ to_map(Stats) ->
         total_docs_examined => Stats#execution_stats.totalDocsExamined,
         total_quorum_docs_examined => 
Stats#execution_stats.totalQuorumDocsExamined,
         results_returned => Stats#execution_stats.resultsReturned,
+        dbname => Stats#execution_stats.dbname,
         execution_time_ms => Stats#execution_stats.executionTimeMs
     }.
 
@@ -103,7 +123,7 @@ maybe_add_stats(Opts, UserFun, Stats0, UserAcc) ->
     FinalAcc =
         case couch_util:get_value(execution_stats, Opts) of
             true ->
-                JSONValue = to_json(Stats1),
+                JSONValue = to_json(Stats1, false),
                 Arg = {add_key, execution_stats, JSONValue},
                 {_Go, FinalUserAcc} = UserFun(Arg, UserAcc),
                 FinalUserAcc;
diff --git a/src/mango/src/mango_execution_stats.hrl 
b/src/mango/src/mango_execution_stats.hrl
index ea5ed5ee8..302460c26 100644
--- a/src/mango/src/mango_execution_stats.hrl
+++ b/src/mango/src/mango_execution_stats.hrl
@@ -16,5 +16,6 @@
     totalQuorumDocsExamined = 0,
     resultsReturned = 0,
     executionStartTime,
-    executionTimeMs
+    executionTimeMs,
+    dbname
 }).

Reply via email to