Skip to content

Commit ecda8f3

Browse files
committed
Add more usage tracking and core functionality
1 parent e5e4820 commit ecda8f3

File tree

6 files changed

+158
-19
lines changed

6 files changed

+158
-19
lines changed

src/chttpd/src/chttpd.erl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ handle_request_int(MochiReq) ->
323323
% Save client socket so that it can be monitored for disconnects
324324
chttpd_util:mochiweb_client_req_set(MochiReq),
325325

326+
%% This is probably better in before_request, but having Path is nice
327+
couch_stats_resource_tracker:create_coordinator_context(HttpReq0, Path),
326328
{HttpReq2, Response} =
327329
case before_request(HttpReq0) of
328330
{ok, HttpReq1} ->
@@ -353,6 +355,8 @@ handle_request_int(MochiReq) ->
353355

354356
before_request(HttpReq) ->
355357
try
358+
%% TODO: re-enable this here once we have Path
359+
%% couch_stats_resource_tracker:create_coordinator_context(HttpReq),
356360
chttpd_stats:init(),
357361
chttpd_plugin:before_request(HttpReq)
358362
catch

src/chttpd/src/chttpd_db.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383

8484
% Database request handlers
8585
handle_request(#httpd{path_parts = [DbName | RestParts], method = Method} = Req) ->
86+
couch_stats_resource_tracker:set_context_dbname(DbName),
8687
case {Method, RestParts} of
8788
{'PUT', []} ->
8889
create_db_req(Req, DbName);

src/couch_stats/src/couch_stats_resource_tracker.erl

Lines changed: 135 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,17 @@
3333

3434
-export([
3535
create_context/0, create_context/1, create_context/3,
36+
create_coordinator_context/1, create_coordinator_context/2,
37+
set_context_dbname/1,
38+
set_context_username/1,
3639
track/1,
3740
should_track/1
3841
]).
3942

4043
-export([
41-
active/0
44+
active/0,
45+
active_coordinators/0,
46+
active_workers/0
4247
]).
4348

4449
-export([
@@ -93,6 +98,7 @@
9398
%% TODO: overlap between this and couch btree fold invocations
9499
%% TODO: need some way to distinguish fols on views vs find vs all_docs
95100
-define(FRPC_CHANGES_ROW, changes_processed).
101+
%%-define(FRPC_CHANGES_ROW, ?ROWS_READ).
96102

97103
%% Module pdict markers
98104
-define(DELTA_TA, csrt_delta_ta).
@@ -109,13 +115,19 @@
109115
%% TODO: switch to:
110116
%% -record(?RCTX, {
111117
-record(rctx, {
118+
%% Metadata
112119
updated_at = os:timestamp(),
113120
exited_at,
114121
pid_ref,
115122
mfa,
116123
nonce,
117124
from,
118125
type = unknown, %% unknown/background/system/rpc/coordinator/fabric_rpc/etc_rpc/etc
126+
state = alive,
127+
dbname,
128+
username,
129+
130+
%% Stats counters
119131
db_open = 0,
120132
docs_read = 0,
121133
rows_read = 0,
@@ -132,8 +144,7 @@
132144
%% TODO: switch record definitions to be macro based, eg:
133145
%% ?COUCH_BT_GET_KP_NODE = 0,
134146
get_kv_node = 0,
135-
get_kp_node = 0,
136-
state = alive
147+
get_kp_node = 0
137148
}).
138149

139150
db_opened() -> inc(db_opened).
@@ -208,7 +219,7 @@ inc(?MANGO_EVAL_MATCH, N) ->
208219
inc(?DB_OPEN_DOC, N) ->
209220
update_counter(#rctx.?DB_OPEN_DOC, N);
210221
inc(?FRPC_CHANGES_ROW, N) ->
211-
update_counter(#rctx.?FRPC_CHANGES_ROW, N);
222+
update_counter(#rctx.?ROWS_READ, N); %% TODO: rework double use of rows_read
212223
inc(?COUCH_BT_GET_KP_NODE, N) ->
213224
update_counter(#rctx.?COUCH_BT_GET_KP_NODE, N);
214225
inc(?COUCH_BT_GET_KV_NODE, N) ->
@@ -238,8 +249,8 @@ maybe_inc([couchdb, query_server, js_filter], Val) ->
238249
inc(?COUCH_JS_FILTER, Val);
239250
maybe_inc([couchdb, query_server, js_filtered_docs], Val) ->
240251
inc(?COUCH_JS_FILTERED_DOCS, Val);
241-
maybe_inc(Metric, Val) ->
242-
io:format("SKIPPING MAYBE_INC METRIC[~p]: ~p~n", [Val, Metric]),
252+
maybe_inc(_Metric, _Val) ->
253+
%%io:format("SKIPPING MAYBE_INC METRIC[~p]: ~p~n", [Val, Metric]),
243254
0.
244255

245256

@@ -248,6 +259,8 @@ should_track([fabric_rpc, all_docs, spawned]) ->
248259
true;
249260
should_track([fabric_rpc, changes, spawned]) ->
250261
true;
262+
should_track([fabric_rpc, changes, processed]) ->
263+
true;
251264
should_track([fabric_rpc, map_view, spawned]) ->
252265
true;
253266
should_track([fabric_rpc, reduce_view, spawned]) ->
@@ -283,7 +296,26 @@ update_counter({_Pid,_Ref}=Key, Field, Count) ->
283296
ets:update_counter(?MODULE, Key, {Field, Count}, #rctx{pid_ref=Key}).
284297

285298

286-
active() ->
299+
active() -> active_int(all).
300+
active_coordinators() -> active_int(coordinators).
301+
active_workers() -> active_int(workers).
302+
303+
304+
active_int(coordinators) ->
305+
select_by_type(coordinators);
306+
active_int(workers) ->
307+
select_by_type(workers);
308+
active_int(all) ->
309+
lists:map(fun to_json/1, ets:tab2list(?MODULE)).
310+
311+
312+
select_by_type(coordinators) ->
313+
ets:select(couch_stats_resource_tracker,
314+
[{#rctx{type = {coordinator,'_','_'}, _ = '_'}, [], ['$_']}]);
315+
select_by_type(workers) ->
316+
ets:select(couch_stats_resource_tracker,
317+
[{#rctx{type = {worker,'_','_'}, _ = '_'}, [], ['$_']}]);
318+
select_by_type(all) ->
287319
lists:map(fun to_json/1, ets:tab2list(?MODULE)).
288320

289321

@@ -294,11 +326,17 @@ to_json(#rctx{}=Rctx) ->
294326
mfa = MFA0,
295327
nonce = Nonce0,
296328
from = From0,
329+
dbname = DbName,
330+
username = UserName,
331+
db_open = DbOpens,
297332
docs_read = DocsRead,
298333
rows_read = RowsRead,
299334
state = State0,
300335
type = Type,
301336
btree_folds = BtFolds,
337+
get_kp_node = KpNodes,
338+
get_kv_node = KvNodes,
339+
ioq_calls = IoqCalls,
302340
changes_processed = ChangesProcessed
303341
} = Rctx,
304342
%%io:format("TO_JSON_MFA: ~p~n", [MFA0]),
@@ -338,27 +376,43 @@ to_json(#rctx{}=Rctx) ->
338376
nonce => term_to_json(Nonce),
339377
%%from => From,
340378
from => term_to_json(From),
379+
dbname => DbName,
380+
username => UserName,
381+
db_open => DbOpens,
341382
docs_read => DocsRead,
342383
rows_read => RowsRead,
343384
state => State,
344-
type => term_to_json(Type),
385+
type => term_to_json({type, Type}),
345386
btree_folds => BtFolds,
387+
kp_nodes => KpNodes,
388+
kv_nodes => KvNodes,
389+
ioq_calls => IoqCalls,
346390
changes_processed => ChangesProcessed
347391
}.
348392

349393
term_to_json({Pid, Ref}) when is_pid(Pid), is_reference(Ref) ->
350394
[?l2b(pid_to_list(Pid)), ?l2b(ref_to_list(Ref))];
395+
term_to_json({type, {coordinator, _, _} = Type}) ->
396+
%%io:format("SETTING JSON TYPE: ~p~n", [Type]),
397+
?l2b(io_lib:format("~p", [Type]));
351398
term_to_json({A, B, C}) ->
352399
[A, B, C];
353400
term_to_json(undefined) ->
354401
null;
402+
term_to_json(null) ->
403+
null;
355404
term_to_json(T) ->
356405
T.
357406

407+
term_to_flat_json({type, {coordinator, _, _} = Type}) ->
408+
%%io:format("SETTING FLAT JSON TYPE: ~p~n", [Type]),
409+
?l2b(io_lib:format("~p", [Type]));
358410
term_to_flat_json(Tuple) when is_tuple(Tuple) ->
359411
?l2b(io_lib:format("~w", [Tuple]));
360412
term_to_flat_json(undefined) ->
361413
null;
414+
term_to_flat_json(null) ->
415+
null;
362416
term_to_flat_json(T) ->
363417
T.
364418

@@ -369,11 +423,17 @@ to_flat_json(#rctx{}=Rctx) ->
369423
mfa = MFA0,
370424
nonce = Nonce0,
371425
from = From0,
426+
dbname = DbName,
427+
username = UserName,
428+
db_open = DbOpens,
372429
docs_read = DocsRead,
373430
rows_read = RowsRead,
374431
state = State0,
375432
type = Type,
376-
btree_folds = ChangesProcessed
433+
get_kp_node = KpNodes,
434+
get_kv_node = KvNodes,
435+
btree_folds = ChangesProcessed,
436+
ioq_calls = IoqCalls
377437
} = Rctx,
378438
io:format("TO_JSON_MFA: ~p~n", [MFA0]),
379439
MFA = case MFA0 of
@@ -402,6 +462,7 @@ to_flat_json(#rctx{}=Rctx) ->
402462
Nonce0 ->
403463
list_to_binary(Nonce0)
404464
end,
465+
io:format("NONCE IS: ~p||~p~n", [Nonce0, Nonce]),
405466
#{
406467
%%updated_at => ?l2b(io_lib:format("~w", [TP])),
407468
updated_at => term_to_flat_json(TP),
@@ -410,11 +471,17 @@ to_flat_json(#rctx{}=Rctx) ->
410471
mfa => MFA,
411472
nonce => Nonce,
412473
from => From,
474+
dbname => DbName,
475+
username => UserName,
476+
db_open => DbOpens,
413477
docs_read => DocsRead,
414478
rows_read => RowsRead,
415479
state => State,
416-
type => term_to_flat_json(Type),
417-
btree_folds => ChangesProcessed
480+
type => term_to_flat_json({type, Type}),
481+
kp_nodes => KpNodes,
482+
kv_nodes => KvNodes,
483+
btree_folds => ChangesProcessed,
484+
ioq_calls => IoqCalls
418485
}.
419486

420487
get_pid_ref() ->
@@ -440,22 +507,71 @@ create_context(Pid) ->
440507

441508
%% add type to disnguish coordinator vs rpc_worker
442509
create_context(From, {M,F,_A} = MFA, Nonce) ->
443-
io:format("CREAT_CONTEXT MFA[~p]: {~p}: ~p~n", [From, MFA, Nonce]),
444-
Ref = make_ref(),
510+
io:format("[~p] CREAT_CONTEXT MFA[~p]: {~p}: ~p~n", [self(), From, MFA, Nonce]),
511+
PidRef = get_pid_ref(), %% this will instantiate a new PidRef
445512
%%Rctx = make_record(self(), Ref),
446513
%% TODO: extract user_ctx and db/shard from
447514
Rctx = #rctx{
448-
pid_ref = {self(), Ref},
515+
pid_ref = PidRef,
449516
from = From,
450517
mfa = MFA,
451518
type = {worker, M, F},
452519
nonce = Nonce
453520
},
454521
track(Rctx),
455522
erlang:put(?DELTA_TZ, Rctx),
456-
ets:insert(?MODULE, Rctx),
523+
true = ets:insert(?MODULE, Rctx),
457524
Rctx.
458525

526+
create_coordinator_context(#httpd{path_parts=Parts} = Req) ->
527+
create_coordinator_context(Req, io_lib:format("~p", [Parts])).
528+
529+
create_coordinator_context(#httpd{} = Req, Path) ->
530+
io:format("CREATING COORDINATOR CONTEXT ON {~p}~n", [Path]),
531+
#httpd{
532+
method = Verb,
533+
%%path_parts = Parts,
534+
nonce = Nonce
535+
} = Req,
536+
PidRef = get_pid_ref(), %% this will instantiate a new PidRef
537+
%%Rctx = make_record(self(), Ref),
538+
%% TODO: extract user_ctx and db/shard from Req
539+
Rctx = #rctx{
540+
pid_ref = PidRef,
541+
%%type = {cooridantor, Verb, Parts},
542+
type = {coordinator, Verb, [$/ | Path]},
543+
nonce = Nonce
544+
},
545+
track(Rctx),
546+
erlang:put(?DELTA_TZ, Rctx),
547+
true = ets:insert(?MODULE, Rctx),
548+
Rctx.
549+
550+
set_context_dbname(DbName) ->
551+
case ets:update_element(?MODULE, get_pid_ref(), [{#rctx.dbname, DbName}]) of
552+
false ->
553+
Stk = try throw(42) catch _:_:Stk0 -> Stk0 end,
554+
io:format("UPDATING DBNAME[~p] FAILURE WITH CONTEXT: ~p AND STACK:~n~pFOO:: ~p~n~n", [DbName, get_resource(), Stk, process_info(self(), current_stacktrace)]),
555+
timer:sleep(1000),
556+
erlang:halt(kaboomz);
557+
true ->
558+
true
559+
end.
560+
561+
set_context_username(null) ->
562+
ok;
563+
set_context_username(UserName) ->
564+
io:format("CSRT SETTING USERNAME CONTEXT: ~p~n", [UserName]),
565+
case ets:update_element(?MODULE, get_pid_ref(), [{#rctx.username, UserName}]) of
566+
false ->
567+
Stk = try throw(42) catch _:_:Stk0 -> Stk0 end,
568+
io:format("UPDATING DBNAME[~p] FAILURE WITH CONTEXT: ~p AND STACK:~n~pFOO:: ~p~n~n", [UserName, get_resource(), Stk, process_info(self(), current_stacktrace)]),
569+
timer:sleep(1000),
570+
erlang:halt(kaboomz);
571+
true ->
572+
true
573+
end.
574+
459575
track(#rctx{}=Rctx) ->
460576
%% TODO: should this block or not? If no, what cleans up zombies?
461577
%% gen_server:call(?MODULE, {track, PR}).
@@ -522,6 +638,10 @@ make_delta(#rctx{}=TA, #rctx{}=TB) ->
522638
docs_read => TB#rctx.docs_read - TA#rctx.docs_read,
523639
rows_read => TB#rctx.rows_read - TA#rctx.rows_read,
524640
btree_folds => TB#rctx.btree_folds - TA#rctx.btree_folds,
641+
get_kp_node => TB#rctx.get_kp_node - TA#rctx.get_kp_node,
642+
get_kv_node => TB#rctx.get_kv_node - TA#rctx.get_kv_node,
643+
db_open => TB#rctx.db_open - TA#rctx.db_open,
644+
ioq_calls => TB#rctx.ioq_calls - TA#rctx.ioq_calls,
525645
dt => timer:now_diff(TB#rctx.updated_at, TA#rctx.updated_at)
526646
},
527647
%% TODO: reevaluate this decision

src/fabric/src/fabric_rpc.erl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ set_purge_infos_limit(DbName, Limit, Options) ->
262262
with_db(DbName, Options, {couch_db, set_purge_infos_limit, [Limit]}).
263263

264264
open_doc(DbName, DocId, Options) ->
265+
io:format("frpc:open_doc(~p, ~p, ~p)~n", [DbName, DocId, Options]),
265266
with_db(DbName, Options, {couch_db, open_doc, [DocId, Options]}).
266267

267268
open_revs(DbName, IdRevsOpts, Options) ->
@@ -352,6 +353,14 @@ get_uuid(DbName) ->
352353

353354
with_db(DbName, Options, {M, F, A}) ->
354355
set_io_priority(DbName, Options),
356+
couch_stats_resource_tracker:set_context_dbname(DbName),
357+
%% TODO: better approach here than using proplists?
358+
case proplists:get_value(user_ctx, Options) of
359+
undefined ->
360+
ok;
361+
#user_ctx{name = UserName} ->
362+
couch_stats_resource_tracker:set_context_username(UserName)
363+
end,
355364
case get_or_create_db(DbName, Options) of
356365
{ok, Db} ->
357366
rexi:reply(

src/rexi/src/rexi.erl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ async_server_call(Server, Caller, Request) ->
129129
-spec reply(any()) -> any().
130130
reply(Reply) ->
131131
{Caller, Ref} = get(rexi_from),
132-
Delta = couch_stats_resource_tracker:make_delta(),
133-
erlang:send(Caller, {Ref, Reply, {delta, Delta}}).
132+
erlang:send(Caller, {Ref, Reply, get_delta()}).
134133

135134
%% @equiv sync_reply(Reply, 300000)
136135
sync_reply(Reply) ->
@@ -215,8 +214,7 @@ stream(Msg, Limit, Timeout) ->
215214
{ok, Count} ->
216215
put(rexi_unacked, Count + 1),
217216
{Caller, Ref} = get(rexi_from),
218-
Delta = couch_stats_resource_tracker:make_delta(),
219-
erlang:send(Caller, {Ref, self(), Msg, {delta, Delta}}),
217+
erlang:send(Caller, {Ref, self(), Msg, get_delta()}),
220218
ok
221219
catch
222220
throw:timeout ->
@@ -330,3 +328,6 @@ drain_acks(Count) ->
330328
after 0 ->
331329
{ok, Count}
332330
end.
331+
332+
get_delta() ->
333+
{delta, couch_stats_resource_tracker:make_delta()}.

0 commit comments

Comments
 (0)