@@ -394,7 +394,7 @@ get_samples_for_stat(Kind, StatName, ForNodes, ClientTStamp, Window) ->
394394 samples = [lists :reverse (MainSamples ) | RestSamples ],
395395 extractor = StatExtractor }.
396396
397- nodes_to_try (Kind , all ) ->
397+ nodes_to_try (Kind , Atom ) when Atom =:= all ; Atom =:= aggregate ->
398398 section_nodes (Kind );
399399nodes_to_try (_Kind , Nodes ) ->
400400 Nodes .
@@ -2772,6 +2772,19 @@ do_merge_samples(Samples, [], StartTS, EndTS, Extractor) ->
27722772do_merge_samples (Samples , [{EndTS , _ } | _ ] = AccSamples , StartTS , _ , Extractor ) ->
27732773 prepare_samples (Samples , StartTS , EndTS , Extractor ) ++ AccSamples .
27742774
2775+ prepare_aggregated_samples (Samples , StartTS , EndTS , Extractor ) ->
2776+ [FirstNodeSamples | Rest ] =
2777+ [filter_samples (S , StartTS , EndTS ) || S <- Samples ],
2778+ Aggregated = merge_all_samples_normally (FirstNodeSamples , Rest ),
2779+ calculate_stats (Extractor , Aggregated ).
2780+
2781+ aggregate_and_merge (Samples , [[{EndTS , _ } | _ ]] = [AccSamples ], StartTS , _ ,
2782+ Extractor ) ->
2783+ [prepare_aggregated_samples (Samples , StartTS , EndTS , Extractor ) ++
2784+ AccSamples ];
2785+ aggregate_and_merge (Samples , _ , StartTS , EndTS , Extractor ) ->
2786+ [prepare_aggregated_samples (Samples , StartTS , EndTS , Extractor )].
2787+
27752788latest_start_timestamp (Samples , StartTS ) ->
27762789 lists :foldl (
27772790 fun ([# stat_entry {timestamp = T } | _ ], LatestT ) when T > LatestT ->
@@ -2804,7 +2817,8 @@ retrive_samples_from_archive(_Archive, _Params,
28042817 {_AccSamples , _AccNodes , _Kind , false } = Acc ) ->
28052818 Acc ;
28062819retrive_samples_from_archive (Archive , Params = # params {start_ts = StartTS ,
2807- end_ts = EndTS },
2820+ end_ts = EndTS ,
2821+ nodes = Host },
28082822 {AccSamples , AccNodes , Kind , Continue }) ->
28092823 case do_retrive_samples_from_archive (Archive , Params , Kind ) of
28102824 # gathered_stats {samples = [[]]} ->
@@ -2824,8 +2838,16 @@ retrive_samples_from_archive(Archive, Params = #params{start_ts = StartTS,
28242838 false
28252839 end ,
28262840
2827- {merge_samples (Samples , AccSamples , StartTS , EndTS , Extractor ),
2828- Nodes , NewKind , NewContinue }
2841+ MergedSamples =
2842+ case Host of
2843+ aggregate ->
2844+ aggregate_and_merge (Samples , AccSamples , StartTS ,
2845+ EndTS , Extractor );
2846+ _ ->
2847+ merge_samples (Samples , AccSamples , StartTS , EndTS ,
2848+ Extractor )
2849+ end ,
2850+ {MergedSamples , Nodes , NewKind , NewContinue }
28292851 end .
28302852
28312853do_retrive_samples_from_archive ({Period , Seconds , Count },
@@ -2865,20 +2887,24 @@ handle_ui_stats_v2(Req) ->
28652887 end_ts = proplists :get_value (endTS , Values , ? MAX_TS ),
28662888 step = proplists :get_value (step , Values , 1 ),
28672889 nodes = proplists :get_value (host , Values , all )},
2868- {Samples , Nodes } =
2869- fix_empty_response (retrive_samples_from_all_archives (Params ),
2870- Params ),
2871- output_ui_stats_v2 (Req , Params , Samples , Nodes )
2890+ {Samples , Nodes , AggregatedNodes } =
2891+ fix_response (retrive_samples_from_all_archives (Params ),
2892+ Params ),
2893+ output_ui_stats_v2 (Req , Params , Samples , Nodes , AggregatedNodes )
28722894 end , Req , qs , ui_stats_v2_validators (Req )).
28732895
2874- fix_empty_response ({undefined , undefined }, # params {nodes = all }) ->
2875- {[[]], [node ()]};
2876- fix_empty_response ({undefined , undefined }, # params {nodes = [Node ]}) ->
2877- {[[]], [Node ]};
2878- fix_empty_response ({[[]], _ }, Params ) ->
2879- fix_empty_response ({undefined , undefined }, Params );
2880- fix_empty_response (Other , _ ) ->
2881- Other .
2896+ fix_response ({undefined , undefined }, # params {nodes = aggregate }) ->
2897+ {[[]], [aggregate ], []};
2898+ fix_response ({undefined , undefined }, # params {nodes = all }) ->
2899+ {[[]], [node ()], undefined };
2900+ fix_response ({undefined , undefined }, # params {nodes = [Node ]}) ->
2901+ {[[]], [Node ], undefined };
2902+ fix_response ({[[]], _ }, Params ) ->
2903+ fix_response ({undefined , undefined }, Params );
2904+ fix_response ({Stats , Nodes }, # params {nodes = aggregate }) ->
2905+ {Stats , [aggregate ], Nodes };
2906+ fix_response ({Stats , Nodes }, _ ) ->
2907+ {Stats , Nodes , undefined }.
28822908
28832909ui_stats_v2_validators (Req ) ->
28842910 Now = os :system_time (millisecond ),
@@ -2927,7 +2953,9 @@ validate_bucket(Name, State) ->
29272953
29282954validate_host (Name , State , Req ) ->
29292955 validator :validate (
2930- fun (HostName ) ->
2956+ fun (" aggregate" ) ->
2957+ {value , aggregate };
2958+ (HostName ) ->
29312959 case menelaus_web_node :find_node_hostname (HostName , Req ) of
29322960 false ->
29332961 {error , " Unknown hostname" };
@@ -2937,21 +2965,32 @@ validate_host(Name, State, Req) ->
29372965 end , Name , State ).
29382966
29392967output_ui_stats_v2 (Req , # params {bucket = Bucket , stat = Stat , step = Step },
2940- Stats , Nodes ) ->
2968+ Stats , Nodes , AggregatedNodes ) ->
29412969 LocalAddr = menelaus_util :local_addr (Req ),
29422970 StatsJson =
29432971 lists :map (
29442972 fun ({S , N }) ->
2945- Host = menelaus_web_node :build_node_hostname (
2946- ns_config :latest (), N , LocalAddr ),
2973+ Host = case N of
2974+ aggregate ->
2975+ aggregate ;
2976+ _ ->
2977+ menelaus_web_node :build_node_hostname (
2978+ ns_config :latest (), N , LocalAddr )
2979+ end ,
29472980 {Timestamps , Samples } = lists :unzip (S ),
29482981 {Host , {[{samples , Samples }, {timestamps , Timestamps }]}}
29492982 end , lists :zip (Stats , Nodes )),
29502983 menelaus_util :reply_json (
29512984 Req , {[{bucket , list_to_binary (Bucket )},
29522985 {statName , list_to_binary (Stat )},
29532986 {step , Step },
2954- {stats , {StatsJson }}]}).
2987+ {stats , {StatsJson }}] ++
2988+ [{aggregatedNodes ,
2989+ [list_to_binary (
2990+ menelaus_web_node :build_node_hostname (ns_config :latest (),
2991+ N , LocalAddr )) ||
2992+ N <- AggregatedNodes ]} || AggregatedNodes =/= undefined ]
2993+ }).
29552994
29562995-ifdef (TEST ).
29572996join_samples_test () ->
0 commit comments