Skip to content

Commit b2094ab

Browse files
committed
Include useful context when logging a bad reduction
1 parent a271313 commit b2094ab

6 files changed

Lines changed: 76 additions & 54 deletions

File tree

share/server/views.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ var Views = (function() {
1616

1717
var map_results = []; // holds temporary emitted values during doc map
1818

19-
function runReduce(reduceFuns, keys, values, rereduce) {
19+
function runReduce(reduceFuns, keys, values, rereduce, ctx) {
2020
var code_size = 0;
2121
for (var i in reduceFuns) {
2222
var fun_body = reduceFuns[i];
@@ -42,7 +42,8 @@ var Views = (function() {
4242
var log_message = [
4343
"Reduce output must shrink more rapidly:",
4444
"input size:", input_length,
45-
"output size:", reduce_length
45+
"output size:", reduce_length,
46+
"context:", ctx
4647
].join(" ");
4748
if (State.query_config.reduce_limit === "log") {
4849
log("reduce_overflow_error: " + log_message);
@@ -65,8 +66,8 @@ var Views = (function() {
6566
// fatal_error. But by default if they don't do error handling we
6667
// just eat the exception and carry on.
6768
//
68-
// In this case we abort map processing but don't destroy the
69-
// JavaScript process. If you need to destroy the JavaScript
69+
// In this case we abort map processing but don't destroy the
70+
// JavaScript process. If you need to destroy the JavaScript
7071
// process, throw the error form matched by the block below.
7172
throw(["error", "map_runtime_error", "function raised 'fatal_error'"]);
7273
} else if (err[0] == "fatal") {
@@ -93,17 +94,17 @@ var Views = (function() {
9394
}
9495
return rv;
9596
},
96-
reduce : function(reduceFuns, kvs) {
97+
reduce : function(reduceFuns, kvs, ctx) {
9798
var keys = new Array(kvs.length);
9899
var values = new Array(kvs.length);
99100
for(var i = 0; i < kvs.length; i++) {
100101
keys[i] = kvs[i][0];
101102
values[i] = kvs[i][1];
102103
}
103-
runReduce(reduceFuns, keys, values, false);
104+
runReduce(reduceFuns, keys, values, false, ctx);
104105
},
105-
rereduce : function(reduceFuns, values) {
106-
runReduce(reduceFuns, null, values, true);
106+
rereduce : function(reduceFuns, values, ctx) {
107+
runReduce(reduceFuns, null, values, true, ctx);
107108
},
108109
mapDoc : function(doc) {
109110
// Compute all the map functions against the document.

src/couch/src/couch_native_process.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ run(State, [<<"map_doc">>, Doc]) ->
183183
State#evstate.funs
184184
),
185185
{State, Resp};
186-
run(State, [<<"reduce">>, Funs, KVs]) ->
186+
run(State, [<<"reduce">>, Funs, KVs, _Ctx]) ->
187187
{Keys, Vals} =
188188
lists:foldl(
189189
fun([K, V], {KAcc, VAcc}) ->
@@ -195,7 +195,7 @@ run(State, [<<"reduce">>, Funs, KVs]) ->
195195
Keys2 = lists:reverse(Keys),
196196
Vals2 = lists:reverse(Vals),
197197
{State, catch reduce(State, Funs, Keys2, Vals2, false)};
198-
run(State, [<<"rereduce">>, Funs, Vals]) ->
198+
run(State, [<<"rereduce">>, Funs, Vals, _Ctx]) ->
199199
{State, catch reduce(State, Funs, null, Vals, true)};
200200
run(#evstate{ddocs = DDocs} = State, [<<"ddoc">>, <<"new">>, DDocId, DDoc]) ->
201201
DDocs2 = store_ddoc(DDocs, DDocId, DDoc),

src/couch/src/couch_query_servers.erl

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
-export([try_compile/4]).
1616
-export([start_doc_map/3, map_doc_raw/2, stop_doc_map/1, raw_to_ejson/1]).
17-
-export([reduce/3, rereduce/3, validate_doc_update/6]).
17+
-export([reduce/3, reduce/4, rereduce/3, rereduce/4, validate_doc_update/6]).
1818
-export([filter_docs/5]).
1919
-export([filter_view/4]).
2020
-export([finalize/2]).
@@ -108,35 +108,43 @@ finalize(<<"_last", _/binary>>, {_K, _Id, V}) ->
108108
finalize(_RedSrc, Reduction) ->
109109
{ok, Reduction}.
110110

111-
rereduce(_Lang, [], _ReducedValues) ->
111+
rereduce(Lang, RedSrcs, _ReducedValues) ->
112+
rereduce(Lang, RedSrcs, _ReducedValues, <<>>).
113+
114+
rereduce(_Lang, [], _ReducedValues, _Ctx) ->
112115
{ok, []};
113-
rereduce(Lang, RedSrcs, ReducedValues) ->
116+
rereduce(Lang, RedSrcs, ReducedValues, Ctx) ->
114117
Grouped = group_reductions_results(ReducedValues),
115118
Results = lists:zipwith(
116119
fun
117120
(<<"_", _/binary>> = FunSrc, Values) ->
118-
{ok, [Result]} = builtin_reduce(rereduce, [FunSrc], [[[], V] || V <- Values], []),
121+
{ok, [Result]} = builtin_reduce(
122+
rereduce, [FunSrc], [[[], V] || V <- Values], [], Ctx
123+
),
119124
Result;
120125
(FunSrc, Values) ->
121-
os_rereduce(Lang, [FunSrc], Values)
126+
os_rereduce(Lang, [FunSrc], Values, Ctx)
122127
end,
123128
RedSrcs,
124129
Grouped
125130
),
126131
{ok, Results}.
127132

128-
reduce(_Lang, [], _KVs) ->
133+
reduce(Lang, RedSrcs, _KVs) ->
134+
reduce(Lang, RedSrcs, _KVs, <<>>).
135+
136+
reduce(_Lang, [], _KVs, _Ctx) ->
129137
{ok, []};
130-
reduce(Lang, RedSrcs, KVs) ->
138+
reduce(Lang, RedSrcs, KVs, Ctx) ->
131139
{OsRedSrcs, BuiltinReds} = lists:partition(
132140
fun
133141
(<<"_", _/binary>>) -> false;
134142
(_OsFun) -> true
135143
end,
136144
RedSrcs
137145
),
138-
{ok, OsResults} = os_reduce(Lang, OsRedSrcs, KVs),
139-
{ok, BuiltinResults} = builtin_reduce(reduce, BuiltinReds, KVs, []),
146+
{ok, OsResults} = os_reduce(Lang, OsRedSrcs, KVs, Ctx),
147+
{ok, BuiltinResults} = builtin_reduce(reduce, BuiltinReds, KVs, [], Ctx),
140148
recombine_reduce_results(RedSrcs, OsResults, BuiltinResults, []).
141149

142150
recombine_reduce_results([], [], [], Acc) ->
@@ -146,12 +154,12 @@ recombine_reduce_results([<<"_", _/binary>> | RedSrcs], OsResults, [BRes | Built
146154
recombine_reduce_results([_OsFun | RedSrcs], [OsR | OsResults], BuiltinResults, Acc) ->
147155
recombine_reduce_results(RedSrcs, OsResults, BuiltinResults, [OsR | Acc]).
148156

149-
os_reduce(_Lang, [], _KVs) ->
157+
os_reduce(_Lang, [], _KVs, _Ctx) ->
150158
{ok, []};
151-
os_reduce(Lang, OsRedSrcs, KVs) ->
159+
os_reduce(Lang, OsRedSrcs, KVs, Ctx) ->
152160
Proc = get_os_process(Lang),
153161
OsResults =
154-
try proc_prompt(Proc, [<<"reduce">>, OsRedSrcs, KVs]) of
162+
try proc_prompt(Proc, [<<"reduce">>, OsRedSrcs, KVs, Ctx]) of
155163
[true, Reductions] -> Reductions
156164
catch
157165
throw:{reduce_overflow_error, Msg} ->
@@ -161,11 +169,11 @@ os_reduce(Lang, OsRedSrcs, KVs) ->
161169
end,
162170
{ok, OsResults}.
163171

164-
os_rereduce(Lang, OsRedSrcs, KVs) ->
172+
os_rereduce(Lang, OsRedSrcs, KVs, Ctx) ->
165173
case get_overflow_error(KVs) of
166174
undefined ->
167175
Proc = get_os_process(Lang),
168-
try proc_prompt(Proc, [<<"rereduce">>, OsRedSrcs, KVs]) of
176+
try proc_prompt(Proc, [<<"rereduce">>, OsRedSrcs, KVs, Ctx]) of
169177
[true, [Reduction]] -> Reduction
170178
catch
171179
throw:{reduce_overflow_error, Msg} ->
@@ -184,36 +192,36 @@ get_overflow_error([{[{reduce_overflow_error, _}]} = Error | _]) ->
184192
get_overflow_error([_ | Rest]) ->
185193
get_overflow_error(Rest).
186194

187-
builtin_reduce(_Re, [], _KVs, Acc) ->
195+
builtin_reduce(_Re, [], _KVs, Acc, _Ctx) ->
188196
{ok, lists:reverse(Acc)};
189-
builtin_reduce(Re, [<<"_sum", _/binary>> | BuiltinReds], KVs, Acc) ->
197+
builtin_reduce(Re, [<<"_sum", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
190198
Sum = builtin_sum_rows(KVs, 0),
191-
Red = check_sum_overflow(?term_size(KVs), ?term_size(Sum), Sum),
192-
builtin_reduce(Re, BuiltinReds, KVs, [Red | Acc]);
193-
builtin_reduce(reduce, [<<"_count", _/binary>> | BuiltinReds], KVs, Acc) ->
199+
Red = check_sum_overflow(?term_size(KVs), ?term_size(Sum), Sum, Ctx),
200+
builtin_reduce(Re, BuiltinReds, KVs, [Red | Acc], Ctx);
201+
builtin_reduce(reduce, [<<"_count", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
194202
Count = length(KVs),
195-
builtin_reduce(reduce, BuiltinReds, KVs, [Count | Acc]);
196-
builtin_reduce(rereduce, [<<"_count", _/binary>> | BuiltinReds], KVs, Acc) ->
203+
builtin_reduce(reduce, BuiltinReds, KVs, [Count | Acc], Ctx);
204+
builtin_reduce(rereduce, [<<"_count", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
197205
Count = builtin_sum_rows(KVs, 0),
198-
builtin_reduce(rereduce, BuiltinReds, KVs, [Count | Acc]);
199-
builtin_reduce(Re, [<<"_stats", _/binary>> | BuiltinReds], KVs, Acc) ->
206+
builtin_reduce(rereduce, BuiltinReds, KVs, [Count | Acc], Ctx);
207+
builtin_reduce(Re, [<<"_stats", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
200208
Stats = builtin_stats(Re, KVs),
201-
builtin_reduce(Re, BuiltinReds, KVs, [Stats | Acc]);
202-
builtin_reduce(Re, [<<"_approx_count_distinct", _/binary>> | BuiltinReds], KVs, Acc) ->
209+
builtin_reduce(Re, BuiltinReds, KVs, [Stats | Acc], Ctx);
210+
builtin_reduce(Re, [<<"_approx_count_distinct", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
203211
Distinct = approx_count_distinct(Re, KVs),
204-
builtin_reduce(Re, BuiltinReds, KVs, [Distinct | Acc]);
205-
builtin_reduce(Re, [<<"_top_", N/binary>> | BuiltinReds], KVs, Acc) ->
212+
builtin_reduce(Re, BuiltinReds, KVs, [Distinct | Acc], Ctx);
213+
builtin_reduce(Re, [<<"_top_", N/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
206214
Top = builtin_rank_n(Re, fun rank_fun_top/2, binary_to_integer(N), KVs),
207-
builtin_reduce(Re, BuiltinReds, KVs, [Top | Acc]);
208-
builtin_reduce(Re, [<<"_bottom_", N/binary>> | BuiltinReds], KVs, Acc) ->
215+
builtin_reduce(Re, BuiltinReds, KVs, [Top | Acc], Ctx);
216+
builtin_reduce(Re, [<<"_bottom_", N/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
209217
Bottom = builtin_rank_n(Re, fun rank_fun_bottom/2, binary_to_integer(N), KVs),
210-
builtin_reduce(Re, BuiltinReds, KVs, [Bottom | Acc]);
211-
builtin_reduce(Re, [<<"_first", _/binary>> | BuiltinReds], KVs, Acc) ->
218+
builtin_reduce(Re, BuiltinReds, KVs, [Bottom | Acc], Ctx);
219+
builtin_reduce(Re, [<<"_first", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
212220
First = builtin_first_last(Re, fun builtin_cmp_first/2, KVs),
213-
builtin_reduce(Re, BuiltinReds, KVs, [First | Acc]);
214-
builtin_reduce(Re, [<<"_last", _/binary>> | BuiltinReds], KVs, Acc) ->
221+
builtin_reduce(Re, BuiltinReds, KVs, [First | Acc], Ctx);
222+
builtin_reduce(Re, [<<"_last", _/binary>> | BuiltinReds], KVs, Acc, Ctx) ->
215223
Last = builtin_first_last(Re, fun builtin_cmp_last/2, KVs),
216-
builtin_reduce(Re, BuiltinReds, KVs, [Last | Acc]).
224+
builtin_reduce(Re, BuiltinReds, KVs, [Last | Acc], Ctx).
217225

218226
builtin_sum_rows([], Acc) ->
219227
Acc;
@@ -278,28 +286,29 @@ sum_arrays([X | Xs], [Y | Ys]) when is_number(X), is_number(Y) ->
278286
sum_arrays(Else, _) ->
279287
throw_sum_error(Else).
280288

281-
check_sum_overflow(InSize, OutSize, Sum) ->
289+
check_sum_overflow(InSize, OutSize, Sum, Ctx) ->
282290
Overflowed = OutSize > reduce_limit_threshold() andalso OutSize * reduce_limit_ratio() > InSize,
283291
case config:get("query_server_config", "reduce_limit", "true") of
284292
"true" when Overflowed ->
285-
Msg = log_sum_overflow(InSize, OutSize),
293+
Msg = log_sum_overflow(InSize, OutSize, Ctx),
286294
{[
287295
{<<"error">>, <<"builtin_reduce_error">>},
288296
{<<"reason">>, Msg}
289297
]};
290298
"log" when Overflowed ->
291-
log_sum_overflow(InSize, OutSize),
299+
log_sum_overflow(InSize, OutSize, Ctx),
292300
Sum;
293301
_ ->
294302
Sum
295303
end.
296304

297-
log_sum_overflow(InSize, OutSize) ->
305+
log_sum_overflow(InSize, OutSize, Ctx) ->
298306
Fmt =
299307
"Reduce output must shrink more rapidly: "
300308
"input size: ~b "
301-
"output size: ~b",
302-
Msg = iolist_to_binary(io_lib:format(Fmt, [InSize, OutSize])),
309+
"output size: ~b "
310+
"context: ~s",
311+
Msg = iolist_to_binary(io_lib:format(Fmt, [InSize, OutSize, Ctx])),
303312
couch_log:error(Msg, []),
304313
Msg.
305314

src/fabric/include/fabric.hrl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
-record(collector, {
1414
db_name=nil,
15+
ddoc_name=nil,
16+
view_name=nil,
1517
query_args,
1618
callback,
1719
counters,

src/fabric/src/fabric_view.erl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,14 @@ get_next_row(#collector{reducer = RedSrc} = State0) when RedSrc =/= undefined ->
285285
Records
286286
),
287287
Wrapped = [[fabric_view_row:get_value(R)] || R <- Records],
288-
{ok, [Reduced]} = couch_query_servers:rereduce(Lang, [RedSrc], Wrapped),
288+
ReduceCtx = ?l2b(
289+
io_lib:format("~s/~s/_view/~s", [
290+
State0#collector.db_name,
291+
State0#collector.ddoc_name,
292+
State0#collector.view_name
293+
])
294+
),
295+
{ok, [Reduced]} = couch_query_servers:rereduce(Lang, [RedSrc], Wrapped, ReduceCtx),
289296
{ok, Finalized} = couch_query_servers:finalize(RedSrc, Reduced),
290297
State = State0#collector{keys = RestKeys, rows = RowDict, counters = Counters},
291298
ViewRow = fabric_view_row:from_props(
@@ -852,7 +859,7 @@ t_get_next_row_reduce(_) ->
852859
Row2 = {view_row, #{key => Key, id => reduced, value => finalized}},
853860
meck:expect(rexi, stream_ack, ['_'], meck:val(ok)),
854861
meck:expect(
855-
couch_query_servers, rereduce, [Language, [reducer], Values], meck:val({ok, [reduced]})
862+
couch_query_servers, rereduce, [Language, [reducer], Values, '_'], meck:val({ok, [reduced]})
856863
),
857864
meck:expect(couch_query_servers, finalize, [reducer, reduced], meck:val({ok, finalized})),
858865
?assertEqual({Row1, State3}, get_next_row(State1)),

src/fabric/src/fabric_view_reduce.erl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
-include_lib("fabric/include/fabric.hrl").
1818
-include_lib("mem3/include/mem3.hrl").
1919
-include_lib("couch_mrview/include/couch_mrview.hrl").
20+
-include_lib("couch/include/couch_db.hrl").
2021

2122
go(DbName, GroupId, View, Args, Callback, Acc0, VInfo) when is_binary(GroupId) ->
2223
{ok, DDoc} = fabric:open_doc(DbName, <<"_design/", GroupId/binary>>, []),
@@ -50,7 +51,7 @@ go(Db, DDoc, VName, Args, Callback, Acc, VInfo) ->
5051
Callback({error, insufficient_storage}, Acc);
5152
{ok, Workers} ->
5253
try
53-
go2(DbName, Workers, VInfo, CoordArgs, Callback, Acc)
54+
go2(DbName, DDoc#doc.id, VName, Workers, VInfo, CoordArgs, Callback, Acc)
5455
after
5556
fabric_streams:cleanup(Workers)
5657
end;
@@ -64,7 +65,7 @@ go(Db, DDoc, VName, Args, Callback, Acc, VInfo) ->
6465
rexi_monitor:stop(RexiMon)
6566
end.
6667

67-
go2(DbName, Workers, {red, {_, Lang, View}, _} = VInfo, Args, Callback, Acc0) ->
68+
go2(DbName, DDocId, VName, Workers, {red, {_, Lang, View}, _} = VInfo, Args, Callback, Acc0) ->
6869
#mrargs{limit = Limit, skip = Skip, keys = Keys, update_seq = UpdateSeq} = Args,
6970
RedSrc = couch_mrview_util:extract_view_reduce(VInfo),
7071
OsProc =
@@ -74,6 +75,8 @@ go2(DbName, Workers, {red, {_, Lang, View}, _} = VInfo, Args, Callback, Acc0) ->
7475
end,
7576
State = #collector{
7677
db_name = DbName,
78+
ddoc_name = DDocId,
79+
view_name = VName,
7780
query_args = Args,
7881
callback = Callback,
7982
counters = fabric_dict:init(Workers, 0),

0 commit comments

Comments
 (0)