Skip to content

Commit be70e78

Browse files
anuthanAliaksey Artamonau
authored andcommitted
Make KV rebalance details available in stage_info output.
Helps with, MB-30803: Collect rebalance related stats CBSE-1097: Visualize bucket movements during rebalance Part of EPIC, MB-30894: Rebalance visibility and reporting Change-Id: Ic2709fdb9196fc6d4bc6b70e592b40da1e3132f7 Reviewed-on: http://review.couchbase.org/101822 Reviewed-by: Aliaksey Artamonau <[email protected]> Well-Formed: Build Bot <[email protected]> Tested-by: Aliaksey Artamonau <[email protected]>
1 parent 2f0141c commit be70e78

File tree

2 files changed

+101
-11
lines changed

2 files changed

+101
-11
lines changed

src/ns_rebalance_observer.erl

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ get_aggregated_progress(Timeout) ->
8484
generic_get_call(get_aggregated_progress, Timeout).
8585

8686
get_stage_info() ->
87-
generic_get_call(get_stage_info).
87+
generic_get_call({get_stage_info, []}).
8888

8989
update_progress(Stage, StageProgress) ->
9090
gen_server:cast(?SERVER, {update_progress, Stage, StageProgress}).
@@ -167,9 +167,11 @@ handle_call(get_detailed_progress, _From, State) ->
167167
handle_call(get_aggregated_progress, _From,
168168
#state{stage_info = StageInfo} = State) ->
169169
{reply, dict:to_list(rebalance_stage_info:get_progress(StageInfo)), State};
170-
handle_call(get_stage_info, _From,
170+
handle_call({get_stage_info, Options}, _From,
171171
#state{stage_info = StageInfo} = State) ->
172-
{reply, rebalance_stage_info:get_stage_info(StageInfo), State};
172+
StageDetails = get_all_stage_rebalance_details(State, Options),
173+
{reply, rebalance_stage_info:get_stage_info(StageInfo, StageDetails),
174+
State};
173175
handle_call(Req, From, State) ->
174176
?log_error("Got unknown request: ~p from ~p", [Req, From]),
175177
{reply, unknown_request, State}.
@@ -660,3 +662,78 @@ update_vbucket_level_info_inner(
660662
BucketLevelInfo#bucket_level_info{
661663
vbucket_level_info = NewVBLevelInfo}
662664
end.
665+
666+
construct_bucket_level_info_json(
667+
#bucket_level_info{bucket_name = BucketName,
668+
vbucket_level_info = VBLevelInfo}, Options) ->
669+
case dict:is_empty(VBLevelInfo#vbucket_level_info.vbucket_info) of
670+
true ->
671+
undefined;
672+
false ->
673+
{BucketName, {[{vbucketLevelInfo,
674+
construct_vbucket_level_info_json(VBLevelInfo,
675+
Options)}]}}
676+
end.
677+
678+
construct_stat_info_json(#stat_info{start_time = false}) ->
679+
{[{startTime, rebalance_stage_info:binarify_timestamp(false)}]};
680+
construct_stat_info_json(#stat_info{start_time = ST,
681+
end_time = ET}) ->
682+
{[{startTime, rebalance_stage_info:binarify_timestamp(ST)},
683+
{endTime, rebalance_stage_info:binarify_timestamp(ET)},
684+
{timeTaken, rebalance_stage_info:diff_timestamp(ET, ST)}]}.
685+
686+
average(_, 0) ->
687+
0;
688+
average(Total, Count) ->
689+
Total/Count.
690+
691+
construct_total_stat_info_json(#total_stat_info{total_time = TT,
692+
completed_count = CC}) ->
693+
{[{averageTime, average(TT, CC)}]}.
694+
695+
construct_replica_building_stats_json(#replica_building_stats{node = Node,
696+
docs_total = DT,
697+
docs_left = DL}) ->
698+
{Node, {[{node, Node},
699+
{docsTotal, DT},
700+
{docsLeft, DL}]}}.
701+
702+
construct_vbucket_info_json(Id, #vbucket_info{before_chain = BC,
703+
after_chain = AC,
704+
stats = RBS,
705+
move = Move}) ->
706+
{[{id, Id},
707+
{beforeChain, BC},
708+
{afterChain, AC},
709+
{stats, {[construct_replica_building_stats_json(X) || X <- RBS]}},
710+
{move, construct_stat_info_json(Move)}]}.
711+
712+
construct_vbucket_level_info_json(
713+
#vbucket_level_info{move = Move,
714+
vbucket_info = AllVBInfo}, Options) ->
715+
VBI = case proplists:get_bool(add_vbucket_info, Options) of
716+
true ->
717+
[{vbucketInfo,
718+
dict:fold(fun (VB, Info, Acc) ->
719+
[construct_vbucket_info_json(VB, Info) | Acc]
720+
end, [], AllVBInfo)}];
721+
_ ->
722+
[]
723+
end,
724+
{[{move, construct_total_stat_info_json(Move)}]
725+
++ VBI}.
726+
727+
get_all_stage_rebalance_details(#state{bucket_info = BucketLevelInfo},
728+
Options) ->
729+
RV = dict:fold(
730+
fun (_Key, BLI, Acc) ->
731+
case construct_bucket_level_info_json(BLI, Options) of
732+
undefined -> Acc;
733+
Val -> [Val | Acc]
734+
end
735+
end, [], BucketLevelInfo),
736+
case RV of
737+
[] -> [];
738+
_ -> [{kv, {RV}}]
739+
end.

src/rebalance_stage_info.erl

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
-module(rebalance_stage_info).
1717

1818
-export([init/1,
19-
get_stage_info/1,
19+
get_stage_info/2,
2020
get_progress/1,
2121
update_progress/3,
2222
update_stage_info/3,
@@ -104,8 +104,8 @@ aggregate(PerStage) ->
104104
Sum / Count
105105
end, TmpAggr).
106106

107-
get_stage_info(StageInfo) ->
108-
{get_per_stage_info(StageInfo)}.
107+
get_stage_info(StageInfo, AllStageDetails) ->
108+
{get_per_stage_info(StageInfo, AllStageDetails)}.
109109

110110
diff_timestamp(false, false) ->
111111
false;
@@ -121,17 +121,19 @@ binarify_timestamp(Time) ->
121121

122122
get_per_stage_info(#stage_info{
123123
per_stage_progress = PerStageProgress,
124-
per_stage_info = PerStageInfo}) ->
124+
per_stage_info = PerStageInfo}, AllStageDetails) ->
125125
AllStageProgress = get_per_stage_progress(PerStageProgress),
126126
lists:map(
127127
fun ({Stage, StageInfo}) ->
128128
construct_per_stage_json(AllStageProgress,
129+
AllStageDetails,
129130
Stage,
130131
StageInfo)
131132
end, PerStageInfo).
132133

133-
construct_per_stage_json(AllStageProgress, Stage, StageInfo) ->
134+
construct_per_stage_json(AllStageProgress, AllStageDetails, Stage, StageInfo) ->
134135
{ok, PerNodeProgress} = dict:find(Stage, AllStageProgress),
136+
StageDetails = construct_per_stage_details_json(Stage, AllStageDetails),
135137
TotalStageProgress = case lists:foldl(fun ({_, P}, {Total, Count}) ->
136138
{Total + P, Count + 1}
137139
end, {0, 0}, PerNodeProgress) of
@@ -143,8 +145,10 @@ construct_per_stage_json(AllStageProgress, Stage, StageInfo) ->
143145
ProgressInfoJson = construct_per_stage_progress_json(TotalStageProgress,
144146
PerNodeProgress,
145147
StageInfo),
146-
StageInfoJson = construct_per_stage_info_json(StageInfo, AllStageProgress),
147-
{get_stage_name(Stage), {ProgressInfoJson ++ StageInfoJson}}.
148+
StageInfoJson = construct_per_stage_info_json(StageInfo, AllStageProgress,
149+
AllStageDetails),
150+
{get_stage_name(Stage), {ProgressInfoJson ++ StageInfoJson ++
151+
StageDetails}}.
148152

149153
get_stage_name(Stage) ->
150154
Stages = [{kv, data},
@@ -159,6 +163,14 @@ get_stage_name(Stage) ->
159163
false -> Stage
160164
end.
161165

166+
construct_per_stage_details_json(Stage, AllStageDetails) ->
167+
case lists:keyfind(Stage, 1, AllStageDetails) of
168+
{Stage, StageDetails} ->
169+
[{details, StageDetails}];
170+
false ->
171+
[]
172+
end.
173+
162174
construct_per_stage_progress_json(
163175
TSP, _, #stage_details{complete_time = false}) when TSP == 0 ->
164176
[];
@@ -176,11 +188,12 @@ construct_per_stage_info_json(#stage_details{
176188
complete_time = EndTime,
177189
sub_stages = SubStages,
178190
notable_events = NotableEvents},
179-
AllStageProgress) ->
191+
AllStageProgress, AllStageDetails) ->
180192
SubStagesInfo = case SubStages of
181193
[] -> [];
182194
_ -> [{subStages,
183195
{[construct_per_stage_json(AllStageProgress,
196+
AllStageDetails,
184197
SubStage,
185198
SubStageInfo) ||
186199
{SubStage, SubStageInfo} <- SubStages]}}]

0 commit comments

Comments
 (0)