diff options
author | Will Holley <willholley@gmail.com> | 2020-01-06 11:49:41 +0000 |
---|---|---|
committer | Will Holley <willholley@gmail.com> | 2020-01-17 13:54:34 +0000 |
commit | 1cacc76ef1166fdb9e60fae173fd310ffb09139b (patch) | |
tree | d2e7d70ee38914e8d81d4c79a02311421ddb4ec4 /src/mango | |
parent | 5d55e289760959eb2fc228acb2ed00d57ddd4dee (diff) | |
download | couchdb-1cacc76ef1166fdb9e60fae173fd310ffb09139b.tar.gz |
Instrument Mango execution stats
Adds metrics for mango execution statistics:
* total docs examined (counter). Note that for non-quorum doc
reads this needs to be counted at the shard level and not be the
mango query coordinator
* total results returned (counter)
* query time (histogram)
* mango:selector evaluations (may be queries or _changes feeds)
For mrview-based queries which don't use quorum reads (the default),
total docs examined should equal mango:selector evaluations. However,
there are cases where mango selectors are evaluated outside of query
time e.g. partial indexing, selector-based _changes which make it
useful to maintain a distinct counter.
Diffstat (limited to 'src/mango')
-rw-r--r-- | src/mango/src/mango_cursor_text.erl | 1 | ||||
-rw-r--r-- | src/mango/src/mango_cursor_view.erl | 2 | ||||
-rw-r--r-- | src/mango/src/mango_execution_stats.erl | 9 | ||||
-rw-r--r-- | src/mango/src/mango_selector.erl | 18 |
4 files changed, 20 insertions, 10 deletions
diff --git a/src/mango/src/mango_cursor_text.erl b/src/mango/src/mango_cursor_text.erl index 6b202daab..2b42c3995 100644 --- a/src/mango/src/mango_cursor_text.erl +++ b/src/mango/src/mango_cursor_text.erl @@ -184,6 +184,7 @@ handle_hit(CAcc0, Sort, Doc) -> } = CAcc0, CAcc1 = update_bookmark(CAcc0, Sort), Stats1 = mango_execution_stats:incr_docs_examined(Stats), + couch_stats:increment_counter([mango, docs_examined]), CAcc2 = CAcc1#cacc{execution_stats = Stats1}, case mango_selector:match(CAcc2#cacc.selector, Doc) of true when Skip > 0 -> diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl index 256946900..240ef501d 100644 --- a/src/mango/src/mango_cursor_view.erl +++ b/src/mango/src/mango_cursor_view.erl @@ -249,6 +249,7 @@ view_cb({row, Row}, #mrargs{extra = Options} = Acc) -> Doc -> put(mango_docs_examined, get(mango_docs_examined) + 1), Selector = couch_util:get_value(selector, Options), + couch_stats:increment_counter([mango, docs_examined]), case mango_selector:match(Selector, Doc) of true -> ok = rexi:stream2(ViewRow), @@ -433,6 +434,7 @@ doc_member(Cursor, RowProps) -> % an undefined doc was returned, indicating we should % perform a quorum fetch ExecutionStats1 = mango_execution_stats:incr_quorum_docs_examined(ExecutionStats), + couch_stats:increment_counter([mango, quorum_docs_examined]), Id = couch_util:get_value(id, RowProps), case mango_util:defer(fabric, open_doc, [Db, Id, Opts]) of {ok, #doc{}=DocProps} -> diff --git a/src/mango/src/mango_execution_stats.erl b/src/mango/src/mango_execution_stats.erl index 7e8afd782..5878a3190 100644 --- a/src/mango/src/mango_execution_stats.erl +++ b/src/mango/src/mango_execution_stats.erl @@ -62,6 +62,7 @@ incr_quorum_docs_examined(Stats) -> incr_results_returned(Stats) -> + couch_stats:increment_counter([mango, results_returned]), Stats#execution_stats { resultsReturned = Stats#execution_stats.resultsReturned + 1 }. @@ -81,11 +82,13 @@ log_end(Stats) -> }. -maybe_add_stats(Opts, UserFun, Stats, UserAcc) -> +maybe_add_stats(Opts, UserFun, Stats0, UserAcc) -> + Stats1 = log_end(Stats0), + couch_stats:update_histogram([mango, query_time], Stats1#execution_stats.executionTimeMs), + case couch_util:get_value(execution_stats, Opts) of true -> - Stats0 = log_end(Stats), - JSONValue = to_json(Stats0), + JSONValue = to_json(Stats1), Arg = {add_key, execution_stats, JSONValue}, {_Go, FinalUserAcc} = UserFun(Arg, UserAcc), FinalUserAcc; diff --git a/src/mango/src/mango_selector.erl b/src/mango/src/mango_selector.erl index 005a6afb3..3ea83c220 100644 --- a/src/mango/src/mango_selector.erl +++ b/src/mango/src/mango_selector.erl @@ -52,15 +52,19 @@ normalize(Selector) -> % Match a selector against a #doc{} or EJSON value. % This assumes that the Selector has been normalized. % Returns true or false. +match(Selector, D) -> + couch_stats:increment_counter([mango, evaluate_selector]), + match_int(Selector, D). + % An empty selector matches any value. -match({[]}, _) -> +match_int({[]}, _) -> true; -match(Selector, #doc{body=Body}) -> +match_int(Selector, #doc{body=Body}) -> match(Selector, Body, fun mango_json:cmp/2); -match(Selector, {Props}) -> +match_int(Selector, {Props}) -> match(Selector, {Props}, fun mango_json:cmp/2). % Convert each operator into a normalized version as well @@ -582,7 +586,7 @@ match({[_, _ | _] = _Props} = Sel, _Value, _Cmp) -> erlang:error({unnormalized_selector, Sel}). -% Returns true if Selector requires all +% Returns true if Selector requires all % fields in RequiredFields to exist in any matching documents. % For each condition in the selector, check @@ -612,13 +616,13 @@ has_required_fields_int(Selector, RequiredFields) when not is_list(Selector) -> % We can "see" through $and operator. Iterate % through the list of child operators. -has_required_fields_int([{[{<<"$and">>, Args}]}], RequiredFields) +has_required_fields_int([{[{<<"$and">>, Args}]}], RequiredFields) when is_list(Args) -> has_required_fields_int(Args, RequiredFields); % We can "see" through $or operator. Required fields % must be covered by all children. -has_required_fields_int([{[{<<"$or">>, Args}]} | Rest], RequiredFields) +has_required_fields_int([{[{<<"$or">>, Args}]} | Rest], RequiredFields) when is_list(Args) -> Remainder0 = lists:foldl(fun(Arg, Acc) -> % for each child test coverage against the full @@ -635,7 +639,7 @@ has_required_fields_int([{[{<<"$or">>, Args}]} | Rest], RequiredFields) % Handle $and operator where it has peers. Required fields % can be covered by any child. -has_required_fields_int([{[{<<"$and">>, Args}]} | Rest], RequiredFields) +has_required_fields_int([{[{<<"$and">>, Args}]} | Rest], RequiredFields) when is_list(Args) -> Remainder = has_required_fields_int(Args, RequiredFields), has_required_fields_int(Rest, Remainder); |