Distributed querying for channels and channel
channel queries now perform an additional query to get the consumer detials once the channel pids are known
This commit is contained in:
		
							parent
							
								
									7b8eddb765
								
							
						
					
					
						commit
						04a9004b8d
					
				|  | @ -233,6 +233,10 @@ handle_call({get_all_consumers, VHost}, _From, State) -> | |||
|     {reply, [augment_msg_stats(augment_consumer(C)) || | ||||
|                 C <- consumers_by_vhost(VHost)], State}; | ||||
| 
 | ||||
| handle_call({get_consumers, ChPids}, _From, State) -> | ||||
|     {reply, [augment_msg_stats(augment_consumer(C)) || | ||||
|                 C <- consumers_by_channel_pids(ChPids)], State}; | ||||
| 
 | ||||
| handle_call({get_overview, User, Ranges}, _From, | ||||
|             #state{interval = Interval} = State) -> | ||||
|     VHosts = case User of | ||||
|  | @ -490,6 +494,7 @@ detail_channel_stats(Ranges, Objs, Interval) -> | |||
| 		   {deliveries, detail_stats(channel_queue_stats_deliver_stats, | ||||
| 						 fine_stats, first(Id), Ranges, | ||||
| 						 Interval)}], | ||||
|      [{pid, Id}] ++ | ||||
|          augment_msg_stats(combine(Props, Obj)) ++ Consumers ++ Stats ++ StatsD | ||||
|      end || Obj <- Objs]. | ||||
| 
 | ||||
|  | @ -610,6 +615,17 @@ consumers_by_vhost(VHost) -> | |||
|                  [{'orelse', {'==', 'all', VHost}, {'==', VHost, '$1'}}], | ||||
|                  ['$_']}]). | ||||
| 
 | ||||
| consumers_by_channel_pids(ChPids) -> | ||||
|     lists:foldl(fun (ChPid, Agg) -> | ||||
|                         consumers_by_channel_pid(ChPid) ++ Agg | ||||
|                 end, [], ChPids). | ||||
| 
 | ||||
| consumers_by_channel_pid(ChPid) -> | ||||
|     ets:select(consumer_stats, | ||||
|                [{{{'_', '$1', '_'}, '_'}, | ||||
|                  [{'==', ChPid, '$1'}], | ||||
|                  ['$_']}]). | ||||
| 
 | ||||
| %%---------------------------------------------------------------------------- | ||||
| %% Internal, query-time augmentation | ||||
| %%---------------------------------------------------------------------------- | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ | |||
| -export([resource_exists/2]). | ||||
| -export([variances/2]). | ||||
| 
 | ||||
| -import(rabbit_misc, [pset/3]). | ||||
| 
 | ||||
| -include("rabbit_mgmt.hrl"). | ||||
| -include_lib("rabbit_common/include/rabbit.hrl"). | ||||
| 
 | ||||
|  | @ -58,5 +60,14 @@ is_authorized(ReqData, Context) -> | |||
| %%-------------------------------------------------------------------- | ||||
| 
 | ||||
| channel(ReqData) -> | ||||
|     rabbit_mgmt_db:get_channel(rabbit_mgmt_util:id(channel, ReqData), | ||||
|                                rabbit_mgmt_util:range(ReqData)). | ||||
|     MemberPids = pg2:get_members(management_db), | ||||
|     {PidResults, _} = delegate:call(MemberPids, "delegate_management_", | ||||
|                                     {get_channel, rabbit_mgmt_util:id(channel, ReqData), | ||||
|                                      rabbit_mgmt_util:range(ReqData)}), | ||||
|     ChannelPids = [rabbit_misc:pget(pid, R) || {_, [_|_] = R} <- PidResults], | ||||
|     {PidConsumers, _} = delegate:call(MemberPids, "delegate_management_", | ||||
|                                     {get_consumers, ChannelPids}), | ||||
|     Consumers = lists:append([Cs || {_, Cs} <- PidConsumers]), | ||||
|     [Channel] = [R || {_, [_|_] = R} <- PidResults], | ||||
| 
 | ||||
|     pset(consumer_details, Consumers, Channel). | ||||
|  |  | |||
|  | @ -51,6 +51,9 @@ is_authorized(ReqData, Context) -> | |||
|     rabbit_mgmt_util:is_authorized(ReqData, Context). | ||||
| 
 | ||||
| augmented(ReqData, Context) -> | ||||
|     MemberPids = pg2:get_members(management_db), | ||||
|     {PidResults, _} = delegate:call(MemberPids, "delegate_management_", | ||||
|                                     {get_all_channels, rabbit_mgmt_util:range(ReqData)}), | ||||
| 
 | ||||
|     rabbit_mgmt_util:filter_conn_ch_list( | ||||
|       rabbit_mgmt_db:get_all_channels( | ||||
|         rabbit_mgmt_util:range(ReqData)), ReqData, Context). | ||||
|       lists:append([R || {_, R} <- PidResults]), ReqData, Context). | ||||
|  |  | |||
|  | @ -44,7 +44,13 @@ groups() -> | |||
|                                queue_consumer_channel_closed, | ||||
|                                queues_single, | ||||
|                                queues_multiple, | ||||
|                                queues_removed | ||||
|                                queues_removed, | ||||
|                                channels_multiple_on_different_nodes, | ||||
|                                channels_cancelled, | ||||
|                                channel, | ||||
|                                channel_other_node, | ||||
|                                channel_with_consumer_on_other_node, | ||||
|                                channel_with_consumer_on_same_node | ||||
|                               ]} | ||||
|     ]. | ||||
| 
 | ||||
|  | @ -125,11 +131,11 @@ multi_node_case1_test(Config) -> | |||
|     restart_node(Config, 1), | ||||
| 
 | ||||
|     Q2 = wait_for(Config, "/queues/%2f/ha-queue"), | ||||
|     http_delete(Config, "/queues/%2f/ha-queue", ?NO_CONTENT), | ||||
|     http_delete(Config, "/policies/%2f/HA", ?NO_CONTENT), | ||||
|     assert_node(Nodename1, pget(node, Q2)), | ||||
|     assert_single_node(Nodename2, pget(slave_nodes, Q2)), | ||||
|     assert_single_node(Nodename2, pget(synchronised_slave_nodes, Q2)), | ||||
|     http_delete(Config, "/queues/%2f/ha-queue", ?NO_CONTENT), | ||||
|     http_delete(Config, "/policies/%2f/HA", ?NO_CONTENT), | ||||
| 
 | ||||
|     passed. | ||||
| 
 | ||||
|  | @ -147,13 +153,13 @@ ha_queue_hosted_on_other_node(Config) -> | |||
|     timer:sleep(2000), % wait for metrics to be pushed :( | ||||
|     Res = http_get(Config, "/queues/%2f/ha-queue"), | ||||
|     amqp_channel:close(Chan), | ||||
|     http_delete(Config, "/queues/%2f/ha-queue", ?NO_CONTENT), | ||||
|     http_delete(Config, "/policies/%2f/HA", ?NO_CONTENT), | ||||
|     % assert some basic data is there | ||||
|     [Cons] = pget(consumer_details, Res), | ||||
|     [_|_] = pget(channel_details, Cons), % channel details proplist must not be empty | ||||
|     0 = pget(prefetch_count, Cons), % check one of the augmented properties | ||||
|     <<"ha-queue">> = pget(name, Res), | ||||
|     http_delete(Config, "/queues/%2f/ha-queue", ?NO_CONTENT), | ||||
|     http_delete(Config, "/policies/%2f/HA", ?NO_CONTENT), | ||||
|     ok. | ||||
| 
 | ||||
| ha_queue_with_multiple_consumers(Config) -> | ||||
|  | @ -171,6 +177,8 @@ ha_queue_with_multiple_consumers(Config) -> | |||
|     timer:sleep(3000), % wait for metrics to be pushed | ||||
|     Res = http_get(Config, "/queues/%2f/ha-queue"), | ||||
|     amqp_channel:close(Chan), | ||||
|     http_delete(Config, "/queues/%2f/ha-queue", ?NO_CONTENT), | ||||
|     http_delete(Config, "/policies/%2f/HA", ?NO_CONTENT), | ||||
|     % assert some basic data is there | ||||
|     [C1, C2] = pget(consumer_details, Res), | ||||
|     % channel details proplist must not be empty | ||||
|  | @ -180,8 +188,6 @@ ha_queue_with_multiple_consumers(Config) -> | |||
|     0 = pget(prefetch_count, C1), | ||||
|     0 = pget(prefetch_count, C2), | ||||
|     <<"ha-queue">> = pget(name, Res), | ||||
|     http_delete(Config, "/queues/%2f/ha-queue", ?NO_CONTENT), | ||||
|     http_delete(Config, "/policies/%2f/HA", ?NO_CONTENT), | ||||
|     ok. | ||||
| 
 | ||||
| queue_on_other_node(Config) -> | ||||
|  | @ -194,12 +200,12 @@ queue_on_other_node(Config) -> | |||
|     timer:sleep(2000), % wait for metrics to be pushed :( | ||||
|     Res = http_get(Config, "/queues/%2f/some-queue"), | ||||
|     amqp_channel:close(Chan), | ||||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     % assert some basic data is present | ||||
|     [Cons] = pget(consumer_details, Res), | ||||
|     [_|_] = pget(channel_details, Cons), % channel details proplist must not be empty | ||||
|     0 = pget(prefetch_count, Cons), % check one of the augmented properties | ||||
|     <<"some-queue">> = pget(name, Res), | ||||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     ok. | ||||
| 
 | ||||
| queue_with_multiple_consumers(Config) -> | ||||
|  | @ -296,13 +302,113 @@ queues_removed(Config) -> | |||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed :( | ||||
|     Res = http_get(Config, "/queues/%2f"), | ||||
|     ct:pal("Res: ~p~n", [Res]), | ||||
|     % assert single queue is returned | ||||
|     [] = Res, | ||||
|     ok. | ||||
| 
 | ||||
| channels_multiple_on_different_nodes(Config) -> | ||||
|     Nodename2 = get_node_config(Config, 1, nodename), | ||||
|     QArgs = [{node, list_to_binary(atom_to_list(Nodename2))}], | ||||
|     http_put(Config, "/queues/%2f/some-queue", QArgs, ?CREATED), | ||||
|     {ok, Chan} = amqp_connection:open_channel(?config(conn, Config)), | ||||
|     Conn = rabbit_ct_client_helpers:open_unmanaged_connection(Config, 1), | ||||
|     {ok, Chan2} = amqp_connection:open_channel(Conn), | ||||
|     consume(Chan, <<"some-queue">>), | ||||
| 
 | ||||
|     timer:sleep(2000), % wait for metrics to be pushed :( | ||||
|     Res = http_get(Config, "/channels"), | ||||
|     amqp_channel:close(Chan), | ||||
|     amqp_channel:close(Chan2), | ||||
|     amqp_connection:close(Conn), | ||||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     % assert two channels are present | ||||
|     [_,_] = Res, | ||||
|     ok. | ||||
| 
 | ||||
| channels_cancelled(Config) -> | ||||
|     Nodename2 = get_node_config(Config, 1, nodename), | ||||
|     QArgs = [{node, list_to_binary(atom_to_list(Nodename2))}], | ||||
|     http_put(Config, "/queues/%2f/some-queue", QArgs, ?CREATED), | ||||
|     {ok, Chan} = amqp_connection:open_channel(?config(conn, Config)), | ||||
|     Conn = rabbit_ct_client_helpers:open_unmanaged_connection(Config, 1), | ||||
|     {ok, Chan2} = amqp_connection:open_channel(Conn), | ||||
|     consume(Chan, <<"some-queue">>), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed | ||||
|     amqp_channel:close(Chan2), | ||||
|     amqp_connection:close(Conn), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed | ||||
| 
 | ||||
|     Res = http_get(Config, "/channels"), | ||||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     amqp_channel:close(Chan), | ||||
|     % assert one channel is present | ||||
|     [_] = Res, | ||||
|     ok. | ||||
| 
 | ||||
| channel(Config) -> | ||||
|     {ok, Chan} = amqp_connection:open_channel(?config(conn, Config)), | ||||
|     [{_, ChData}] = rabbit_ct_broker_helpers:rpc(Config, 0, ets, tab2list, [channel_created]), | ||||
| 
 | ||||
|     ChName = http_uri:encode(binary_to_list(pget(name, ChData))), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed :( | ||||
|     Res = http_get(Config, "/channels/" ++ ChName ), | ||||
|     amqp_channel:close(Chan), | ||||
|     % assert channel is non empty | ||||
|     [_|_] = Res, | ||||
|     ok. | ||||
| 
 | ||||
| channel_other_node(Config) -> | ||||
|     Conn = rabbit_ct_client_helpers:open_unmanaged_connection(Config, 1), | ||||
|     {ok, _} = amqp_connection:open_channel(Conn), | ||||
|     [{_, ChData}] = rabbit_ct_broker_helpers:rpc(Config, 1, ets, tab2list, | ||||
|                                                  [channel_created]), | ||||
|     ChName = http_uri:encode(binary_to_list(pget(name, ChData))), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed :( | ||||
|     Res = http_get(Config, "/channels/" ++ ChName ), | ||||
|     amqp_connection:close(Conn), | ||||
|     % assert channel is non empty | ||||
|     [_|_] = Res, | ||||
|     ok. | ||||
| 
 | ||||
| channel_with_consumer_on_other_node(Config) -> | ||||
|     Nodename2 = get_node_config(Config, 1, nodename), | ||||
|     QArgs = [{node, list_to_binary(atom_to_list(Nodename2))}], | ||||
|     http_put(Config, "/queues/%2f/some-queue", QArgs, ?CREATED), | ||||
|     {ok, Chan} = amqp_connection:open_channel(?config(conn, Config)), | ||||
|     ChName = get_channel_name(Config, 0), | ||||
|     consume(Chan, <<"some-queue">>), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed | ||||
|     Res = http_get(Config, "/channels/" ++ ChName ), | ||||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     amqp_channel:close(Chan), | ||||
|     % assert channel is non empty | ||||
|     [_|_] = Res, | ||||
|     [_] = pget(consumer_details, Res), | ||||
|     ok. | ||||
| 
 | ||||
| channel_with_consumer_on_same_node(Config) -> | ||||
|     Nodename1 = get_node_config(Config, 0, nodename), | ||||
|     QArgs = [{node, list_to_binary(atom_to_list(Nodename1))}], | ||||
|     http_put(Config, "/queues/%2f/some-queue", QArgs, ?CREATED), | ||||
|     {ok, Chan} = amqp_connection:open_channel(?config(conn, Config)), | ||||
|     ChName = get_channel_name(Config, 0), | ||||
|     consume(Chan, <<"some-queue">>), | ||||
|     timer:sleep(2000), % wait for metrics to be pushed | ||||
|     Res = http_get(Config, "/channels/" ++ ChName ), | ||||
|     amqp_channel:close(Chan), | ||||
|     http_delete(Config, "/queues/%2f/some-queue", ?NO_CONTENT), | ||||
|     % assert channel is non empty | ||||
|     [_|_] = Res, | ||||
|     [_] = pget(consumer_details, Res), | ||||
|     ok. | ||||
| 
 | ||||
| %%---------------------------------------------------------------------------- | ||||
| 
 | ||||
| get_channel_name(Config, Node) -> | ||||
|     [{_, ChData}|_] = rabbit_ct_broker_helpers:rpc(Config, Node, ets, tab2list, | ||||
|                                                  [channel_created]), | ||||
|     http_uri:encode(binary_to_list(pget(name, ChData))). | ||||
| 
 | ||||
| consume(Channel, Queue) -> | ||||
|     #'basic.consume_ok'{consumer_tag = Tag} = | ||||
|          amqp_channel:call(Channel, #'basic.consume'{queue = Queue}), | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue