Merge pull request #10032 from keynslug/fix/EMQX-9019/no-metrics-disconnected
fix(bridgeapi): anticipate node responses w/o metrics
This commit is contained in:
commit
7dce152ffd
|
@ -743,8 +743,9 @@ collect_metrics(Bridges) ->
|
||||||
|
|
||||||
aggregate_metrics(AllMetrics) ->
|
aggregate_metrics(AllMetrics) ->
|
||||||
InitMetrics = ?EMPTY_METRICS,
|
InitMetrics = ?EMPTY_METRICS,
|
||||||
lists:foldl(
|
lists:foldl(fun aggregate_metrics/2, InitMetrics, AllMetrics).
|
||||||
fun(
|
|
||||||
|
aggregate_metrics(
|
||||||
#{
|
#{
|
||||||
metrics := ?metrics(
|
metrics := ?metrics(
|
||||||
M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15, M16, M17
|
M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15, M16, M17
|
||||||
|
@ -772,11 +773,9 @@ aggregate_metrics(AllMetrics) ->
|
||||||
M15 + N15,
|
M15 + N15,
|
||||||
M16 + N16,
|
M16 + N16,
|
||||||
M17 + N17
|
M17 + N17
|
||||||
)
|
);
|
||||||
end,
|
aggregate_metrics(#{}, Metrics) ->
|
||||||
InitMetrics,
|
Metrics.
|
||||||
AllMetrics
|
|
||||||
).
|
|
||||||
|
|
||||||
format_resp(Data) ->
|
format_resp(Data) ->
|
||||||
format_resp(Data, node()).
|
format_resp(Data, node()).
|
||||||
|
@ -786,18 +785,26 @@ format_resp(
|
||||||
type := Type,
|
type := Type,
|
||||||
name := BridgeName,
|
name := BridgeName,
|
||||||
raw_config := RawConf,
|
raw_config := RawConf,
|
||||||
resource_data := #{status := Status, metrics := Metrics}
|
resource_data := ResourceData
|
||||||
},
|
},
|
||||||
Node
|
Node
|
||||||
) ->
|
) ->
|
||||||
RawConfFull = fill_defaults(Type, RawConf),
|
RawConfFull = fill_defaults(Type, RawConf),
|
||||||
redact(RawConfFull#{
|
redact(
|
||||||
|
maps:merge(
|
||||||
|
RawConfFull#{
|
||||||
type => Type,
|
type => Type,
|
||||||
name => maps:get(<<"name">>, RawConf, BridgeName),
|
name => maps:get(<<"name">>, RawConf, BridgeName),
|
||||||
node => Node,
|
node => Node
|
||||||
status => Status,
|
},
|
||||||
metrics => format_metrics(Metrics)
|
format_resource_data(ResourceData)
|
||||||
}).
|
)
|
||||||
|
).
|
||||||
|
|
||||||
|
format_resource_data(#{status := Status, metrics := Metrics}) ->
|
||||||
|
#{status => Status, metrics => format_metrics(Metrics)};
|
||||||
|
format_resource_data(#{status := Status}) ->
|
||||||
|
#{status => Status}.
|
||||||
|
|
||||||
format_metrics(#{
|
format_metrics(#{
|
||||||
counters := #{
|
counters := #{
|
||||||
|
|
|
@ -140,17 +140,13 @@ stop_http_server(Sock, Acceptor) ->
|
||||||
gen_tcp:close(Sock).
|
gen_tcp:close(Sock).
|
||||||
|
|
||||||
listen_on_random_port() ->
|
listen_on_random_port() ->
|
||||||
Min = 1024,
|
SockOpts = [binary, {active, false}, {packet, raw}, {reuseaddr, true}, {backlog, 1000}],
|
||||||
Max = 65000,
|
case gen_tcp:listen(0, SockOpts) of
|
||||||
rand:seed(exsplus, erlang:timestamp()),
|
{ok, Sock} ->
|
||||||
Port = rand:uniform(Max - Min) + Min,
|
{ok, Port} = inet:port(Sock),
|
||||||
case
|
{Port, Sock};
|
||||||
gen_tcp:listen(Port, [
|
{error, Reason} when Reason /= eaddrinuse ->
|
||||||
binary, {active, false}, {packet, raw}, {reuseaddr, true}, {backlog, 1000}
|
{error, Reason}
|
||||||
])
|
|
||||||
of
|
|
||||||
{ok, Sock} -> {Port, Sock};
|
|
||||||
{error, eaddrinuse} -> listen_on_random_port()
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
accept_loop(Sock, HandleFun, Parent) ->
|
accept_loop(Sock, HandleFun, Parent) ->
|
||||||
|
@ -543,7 +539,9 @@ do_start_stop_bridges(Type, Config) ->
|
||||||
{ok, 200, <<"[]">>} = request(get, uri(["bridges"]), []),
|
{ok, 200, <<"[]">>} = request(get, uri(["bridges"]), []),
|
||||||
|
|
||||||
%% Create broken bridge
|
%% Create broken bridge
|
||||||
BadServer = <<"nohost">>,
|
{ListenPort, Sock} = listen_on_random_port(),
|
||||||
|
%% Connecting to this endpoint should always timeout
|
||||||
|
BadServer = iolist_to_binary(io_lib:format("localhost:~B", [ListenPort])),
|
||||||
BadName = <<"bad_", (atom_to_binary(Type))/binary>>,
|
BadName = <<"bad_", (atom_to_binary(Type))/binary>>,
|
||||||
{ok, 201, BadBridge1} = request(
|
{ok, 201, BadBridge1} = request(
|
||||||
post,
|
post,
|
||||||
|
@ -555,11 +553,15 @@ do_start_stop_bridges(Type, Config) ->
|
||||||
<<"name">> := BadName,
|
<<"name">> := BadName,
|
||||||
<<"enable">> := true,
|
<<"enable">> := true,
|
||||||
<<"server">> := BadServer,
|
<<"server">> := BadServer,
|
||||||
<<"status">> := <<"disconnected">>,
|
<<"status">> := <<"connecting">>,
|
||||||
<<"node_status">> := [_ | _]
|
<<"node_status">> := [_ | _]
|
||||||
} = jsx:decode(BadBridge1),
|
} = jsx:decode(BadBridge1),
|
||||||
BadBridgeID = emqx_bridge_resource:bridge_id(?BRIDGE_TYPE_MQTT, BadName),
|
BadBridgeID = emqx_bridge_resource:bridge_id(?BRIDGE_TYPE_MQTT, BadName),
|
||||||
{ok, 500, _} = request(post, operation_path(Type, start, BadBridgeID), <<"">>),
|
?assertMatch(
|
||||||
|
{ok, SC, _} when SC == 500 orelse SC == 503,
|
||||||
|
request(post, operation_path(Type, start, BadBridgeID), <<"">>)
|
||||||
|
),
|
||||||
|
ok = gen_tcp:close(Sock),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_enable_disable_bridges(Config) ->
|
t_enable_disable_bridges(Config) ->
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
When the resource manager is busy trying to establish a connection with the remote, the resource might yet lack any metrics information. Prior to this fix, the `bridges/` API handler crashed in such circumstances.
|
|
@ -0,0 +1 @@
|
||||||
|
当资源管理器忙于尝试与远程建立连接时,资源可能还缺少任何度量信息。 在此修复之前,`bridges/' API 处理程序在这种情况下崩溃。
|
Loading…
Reference in New Issue