33
33
34
34
-export ([
35
35
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 ,
36
39
track /1 ,
37
40
should_track /1
38
41
]).
39
42
40
43
-export ([
41
- active /0
44
+ active /0 ,
45
+ active_coordinators /0 ,
46
+ active_workers /0
42
47
]).
43
48
44
49
-export ([
93
98
% % TODO: overlap between this and couch btree fold invocations
94
99
% % TODO: need some way to distinguish fols on views vs find vs all_docs
95
100
-define (FRPC_CHANGES_ROW , changes_processed ).
101
+ % %-define(FRPC_CHANGES_ROW, ?ROWS_READ).
96
102
97
103
% % Module pdict markers
98
104
-define (DELTA_TA , csrt_delta_ta ).
109
115
% % TODO: switch to:
110
116
% % -record(?RCTX, {
111
117
-record (rctx , {
118
+ % % Metadata
112
119
updated_at = os :timestamp (),
113
120
exited_at ,
114
121
pid_ref ,
115
122
mfa ,
116
123
nonce ,
117
124
from ,
118
125
type = unknown , % % unknown/background/system/rpc/coordinator/fabric_rpc/etc_rpc/etc
126
+ state = alive ,
127
+ dbname ,
128
+ username ,
129
+
130
+ % % Stats counters
119
131
db_open = 0 ,
120
132
docs_read = 0 ,
121
133
rows_read = 0 ,
132
144
% % TODO: switch record definitions to be macro based, eg:
133
145
% % ?COUCH_BT_GET_KP_NODE = 0,
134
146
get_kv_node = 0 ,
135
- get_kp_node = 0 ,
136
- state = alive
147
+ get_kp_node = 0
137
148
}).
138
149
139
150
db_opened () -> inc (db_opened ).
@@ -208,7 +219,7 @@ inc(?MANGO_EVAL_MATCH, N) ->
208
219
inc(?DB_OPEN_DOC, N) ->
209
220
update_counter(#rctx.?DB_OPEN_DOC, N);
210
221
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
212
223
inc(?COUCH_BT_GET_KP_NODE, N) ->
213
224
update_counter(#rctx.?COUCH_BT_GET_KP_NODE, N);
214
225
inc(?COUCH_BT_GET_KV_NODE, N) ->
@@ -238,8 +249,8 @@ maybe_inc([couchdb, query_server, js_filter], Val) ->
238
249
inc(?COUCH_JS_FILTER, Val);
239
250
maybe_inc([couchdb, query_server, js_filtered_docs], Val) ->
240
251
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]),
243
254
0.
244
255
245
256
@@ -248,6 +259,8 @@ should_track([fabric_rpc, all_docs, spawned]) ->
248
259
true;
249
260
should_track([fabric_rpc, changes, spawned]) ->
250
261
true;
262
+ should_track([fabric_rpc, changes, processed]) ->
263
+ true;
251
264
should_track([fabric_rpc, map_view, spawned]) ->
252
265
true;
253
266
should_track([fabric_rpc, reduce_view, spawned]) ->
@@ -283,7 +296,26 @@ update_counter({_Pid,_Ref}=Key, Field, Count) ->
283
296
ets :update_counter (? MODULE , Key , {Field , Count }, # rctx {pid_ref = Key }).
284
297
285
298
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 ) ->
287
319
lists :map (fun to_json /1 , ets :tab2list (? MODULE )).
288
320
289
321
@@ -294,11 +326,17 @@ to_json(#rctx{}=Rctx) ->
294
326
mfa = MFA0 ,
295
327
nonce = Nonce0 ,
296
328
from = From0 ,
329
+ dbname = DbName ,
330
+ username = UserName ,
331
+ db_open = DbOpens ,
297
332
docs_read = DocsRead ,
298
333
rows_read = RowsRead ,
299
334
state = State0 ,
300
335
type = Type ,
301
336
btree_folds = BtFolds ,
337
+ get_kp_node = KpNodes ,
338
+ get_kv_node = KvNodes ,
339
+ ioq_calls = IoqCalls ,
302
340
changes_processed = ChangesProcessed
303
341
} = Rctx ,
304
342
% %io:format("TO_JSON_MFA: ~p~n", [MFA0]),
@@ -338,27 +376,43 @@ to_json(#rctx{}=Rctx) ->
338
376
nonce => term_to_json (Nonce ),
339
377
% %from => From,
340
378
from => term_to_json (From ),
379
+ dbname => DbName ,
380
+ username => UserName ,
381
+ db_open => DbOpens ,
341
382
docs_read => DocsRead ,
342
383
rows_read => RowsRead ,
343
384
state => State ,
344
- type => term_to_json (Type ),
385
+ type => term_to_json ({ type , Type } ),
345
386
btree_folds => BtFolds ,
387
+ kp_nodes => KpNodes ,
388
+ kv_nodes => KvNodes ,
389
+ ioq_calls => IoqCalls ,
346
390
changes_processed => ChangesProcessed
347
391
}.
348
392
349
393
term_to_json ({Pid , Ref }) when is_pid (Pid ), is_reference (Ref ) ->
350
394
[? 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 ]));
351
398
term_to_json ({A , B , C }) ->
352
399
[A , B , C ];
353
400
term_to_json (undefined ) ->
354
401
null ;
402
+ term_to_json (null ) ->
403
+ null ;
355
404
term_to_json (T ) ->
356
405
T .
357
406
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 ]));
358
410
term_to_flat_json (Tuple ) when is_tuple (Tuple ) ->
359
411
? l2b (io_lib :format (" ~w " , [Tuple ]));
360
412
term_to_flat_json (undefined ) ->
361
413
null ;
414
+ term_to_flat_json (null ) ->
415
+ null ;
362
416
term_to_flat_json (T ) ->
363
417
T .
364
418
@@ -369,11 +423,17 @@ to_flat_json(#rctx{}=Rctx) ->
369
423
mfa = MFA0 ,
370
424
nonce = Nonce0 ,
371
425
from = From0 ,
426
+ dbname = DbName ,
427
+ username = UserName ,
428
+ db_open = DbOpens ,
372
429
docs_read = DocsRead ,
373
430
rows_read = RowsRead ,
374
431
state = State0 ,
375
432
type = Type ,
376
- btree_folds = ChangesProcessed
433
+ get_kp_node = KpNodes ,
434
+ get_kv_node = KvNodes ,
435
+ btree_folds = ChangesProcessed ,
436
+ ioq_calls = IoqCalls
377
437
} = Rctx ,
378
438
io :format (" TO_JSON_MFA: ~p~n " , [MFA0 ]),
379
439
MFA = case MFA0 of
@@ -402,6 +462,7 @@ to_flat_json(#rctx{}=Rctx) ->
402
462
Nonce0 ->
403
463
list_to_binary (Nonce0 )
404
464
end ,
465
+ io :format (" NONCE IS: ~p ||~p~n " , [Nonce0 , Nonce ]),
405
466
#{
406
467
% %updated_at => ?l2b(io_lib:format("~w", [TP])),
407
468
updated_at => term_to_flat_json (TP ),
@@ -410,11 +471,17 @@ to_flat_json(#rctx{}=Rctx) ->
410
471
mfa => MFA ,
411
472
nonce => Nonce ,
412
473
from => From ,
474
+ dbname => DbName ,
475
+ username => UserName ,
476
+ db_open => DbOpens ,
413
477
docs_read => DocsRead ,
414
478
rows_read => RowsRead ,
415
479
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
418
485
}.
419
486
420
487
get_pid_ref () ->
@@ -440,22 +507,71 @@ create_context(Pid) ->
440
507
441
508
% % add type to disnguish coordinator vs rpc_worker
442
509
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
445
512
% %Rctx = make_record(self(), Ref),
446
513
% % TODO: extract user_ctx and db/shard from
447
514
Rctx = # rctx {
448
- pid_ref = { self (), Ref } ,
515
+ pid_ref = PidRef ,
449
516
from = From ,
450
517
mfa = MFA ,
451
518
type = {worker , M , F },
452
519
nonce = Nonce
453
520
},
454
521
track (Rctx ),
455
522
erlang :put (? DELTA_TZ , Rctx ),
456
- ets :insert (? MODULE , Rctx ),
523
+ true = ets :insert (? MODULE , Rctx ),
457
524
Rctx .
458
525
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~p FOO:: ~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~p FOO:: ~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
+
459
575
track (# rctx {}= Rctx ) ->
460
576
% % TODO: should this block or not? If no, what cleans up zombies?
461
577
% % gen_server:call(?MODULE, {track, PR}).
@@ -522,6 +638,10 @@ make_delta(#rctx{}=TA, #rctx{}=TB) ->
522
638
docs_read => TB # rctx .docs_read - TA # rctx .docs_read ,
523
639
rows_read => TB # rctx .rows_read - TA # rctx .rows_read ,
524
640
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 ,
525
645
dt => timer :now_diff (TB # rctx .updated_at , TA # rctx .updated_at )
526
646
},
527
647
% % TODO: reevaluate this decision
0 commit comments