|
|
@@ -16,22 +16,30 @@
|
|
|
%%
|
|
|
-module(emqx_gateway_api).
|
|
|
|
|
|
+-include("emqx_gateway_http.hrl").
|
|
|
+-include_lib("typerefl/include/types.hrl").
|
|
|
+-include_lib("hocon/include/hoconsc.hrl").
|
|
|
-include_lib("emqx/include/emqx_placeholder.hrl").
|
|
|
-include_lib("emqx/include/emqx_authentication.hrl").
|
|
|
|
|
|
-behaviour(minirest_api).
|
|
|
|
|
|
+-import(hoconsc, [mk/2, ref/1, ref/2]).
|
|
|
+
|
|
|
-import(emqx_gateway_http,
|
|
|
[ return_http_error/2
|
|
|
, with_gateway/2
|
|
|
- , schema_bad_request/0
|
|
|
- , schema_not_found/0
|
|
|
- , schema_internal_error/0
|
|
|
- , schema_no_content/0
|
|
|
]).
|
|
|
|
|
|
-%% minirest behaviour callbacks
|
|
|
--export([api_spec/0]).
|
|
|
+%% minirest/dashbaord_swagger behaviour callbacks
|
|
|
+-export([ api_spec/0
|
|
|
+ , paths/0
|
|
|
+ , schema/1
|
|
|
+ ]).
|
|
|
+
|
|
|
+-export([ roots/0
|
|
|
+ , fields/1
|
|
|
+ ]).
|
|
|
|
|
|
%% http handlers
|
|
|
-export([ gateway/2
|
|
|
@@ -44,12 +52,12 @@
|
|
|
%%--------------------------------------------------------------------
|
|
|
|
|
|
api_spec() ->
|
|
|
- {metadata(apis()), []}.
|
|
|
+ emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
|
|
|
|
|
|
-apis() ->
|
|
|
- [ {"/gateway", gateway}
|
|
|
- , {"/gateway/:name", gateway_insta}
|
|
|
- , {"/gateway/:name/stats", gateway_insta_stats}
|
|
|
+paths() ->
|
|
|
+ [ "/gateway"
|
|
|
+ , "/gateway/:name"
|
|
|
+ , "/gateway/:name/stats"
|
|
|
].
|
|
|
|
|
|
%%--------------------------------------------------------------------
|
|
|
@@ -137,270 +145,195 @@ gateway_insta_stats(get, _Req) ->
|
|
|
%% Swagger defines
|
|
|
%%--------------------------------------------------------------------
|
|
|
|
|
|
-metadata(APIs) ->
|
|
|
- metadata(APIs, []).
|
|
|
-metadata([], APIAcc) ->
|
|
|
- lists:reverse(APIAcc);
|
|
|
-metadata([{Path, Fun}|More], APIAcc) ->
|
|
|
- Methods = [get, post, put, delete, patch],
|
|
|
- Mds = lists:foldl(fun(M, Acc) ->
|
|
|
- try
|
|
|
- Acc#{M => swagger(Path, M)}
|
|
|
- catch
|
|
|
- error : function_clause ->
|
|
|
- Acc
|
|
|
- end
|
|
|
- end, #{}, Methods),
|
|
|
- metadata(More, [{Path, Mds, Fun} | APIAcc]).
|
|
|
-
|
|
|
-swagger("/gateway", get) ->
|
|
|
- #{ description => <<"Get gateway list">>
|
|
|
- , parameters => params_gateway_status_in_qs()
|
|
|
- , responses =>
|
|
|
- #{ <<"200">> => schema_gateway_overview_list() }
|
|
|
+schema("/gateway") ->
|
|
|
+ #{ 'operationId' => gateway,
|
|
|
+ get =>
|
|
|
+ #{ description => <<"Get gateway list">>
|
|
|
+ , parameters => params_gateway_status_in_qs()
|
|
|
+ , responses =>
|
|
|
+ ?STANDARD_RESP(#{200 => ref(gateway_overview)})
|
|
|
+ },
|
|
|
+ post =>
|
|
|
+ #{ description => <<"Load a gateway">>
|
|
|
+ , 'requestBody' => schema_gateways_conf()
|
|
|
+ , responses =>
|
|
|
+ ?STANDARD_RESP(#{201 => schema_gateways_conf()})
|
|
|
+ }
|
|
|
};
|
|
|
-swagger("/gateway", post) ->
|
|
|
- #{ description => <<"Load a gateway">>
|
|
|
- , requestBody => schema_gateway_conf()
|
|
|
- , responses =>
|
|
|
- #{ <<"400">> => schema_bad_request()
|
|
|
- , <<"404">> => schema_not_found()
|
|
|
- , <<"500">> => schema_internal_error()
|
|
|
- , <<"204">> => schema_no_content()
|
|
|
- }
|
|
|
- };
|
|
|
-swagger("/gateway/:name", get) ->
|
|
|
- #{ description => <<"Get the gateway configurations">>
|
|
|
- , parameters => params_gateway_name_in_path()
|
|
|
- , responses =>
|
|
|
- #{ <<"400">> => schema_bad_request()
|
|
|
- , <<"404">> => schema_not_found()
|
|
|
- , <<"500">> => schema_internal_error()
|
|
|
- , <<"200">> => schema_gateway_conf()
|
|
|
- }
|
|
|
- };
|
|
|
-swagger("/gateway/:name", delete) ->
|
|
|
- #{ description => <<"Delete/Unload the gateway">>
|
|
|
- , parameters => params_gateway_name_in_path()
|
|
|
- , responses =>
|
|
|
- #{ <<"400">> => schema_bad_request()
|
|
|
- , <<"404">> => schema_not_found()
|
|
|
- , <<"500">> => schema_internal_error()
|
|
|
- , <<"204">> => schema_no_content()
|
|
|
- }
|
|
|
- };
|
|
|
-swagger("/gateway/:name", put) ->
|
|
|
- #{ description => <<"Update the gateway configurations/status">>
|
|
|
- , parameters => params_gateway_name_in_path()
|
|
|
- , requestBody => schema_gateway_conf()
|
|
|
- , responses =>
|
|
|
- #{ <<"400">> => schema_bad_request()
|
|
|
- , <<"404">> => schema_not_found()
|
|
|
- , <<"500">> => schema_internal_error()
|
|
|
- , <<"200">> => schema_no_content()
|
|
|
- }
|
|
|
+schema("/gateway/:name") ->
|
|
|
+ #{ 'operationId' => gateway_insta,
|
|
|
+ get =>
|
|
|
+ #{ description => <<"Get the gateway configurations">>
|
|
|
+ , parameters => params_gateway_name_in_path()
|
|
|
+ , responses =>
|
|
|
+ ?STANDARD_RESP(#{200 => schema_gateways_conf()})
|
|
|
+ },
|
|
|
+ delete =>
|
|
|
+ #{ description => <<"Delete/Unload the gateway">>
|
|
|
+ , parameters => params_gateway_name_in_path()
|
|
|
+ , responses =>
|
|
|
+ ?STANDARD_RESP(#{204 => <<"Deleted">>})
|
|
|
+ },
|
|
|
+ put =>
|
|
|
+ #{ description => <<"Update the gateway configurations/status">>
|
|
|
+ , parameters => params_gateway_name_in_path()
|
|
|
+ , 'requestBody' => schema_gateways_conf()
|
|
|
+ , responses =>
|
|
|
+ ?STANDARD_RESP(#{200 => schema_gateways_conf()})
|
|
|
+ }
|
|
|
};
|
|
|
-swagger("/gateway/:name/stats", get) ->
|
|
|
- #{ description => <<"Get gateway Statistic">>
|
|
|
- , parameters => params_gateway_name_in_path()
|
|
|
- , responses =>
|
|
|
- #{ <<"400">> => schema_bad_request()
|
|
|
- , <<"404">> => schema_not_found()
|
|
|
- , <<"500">> => schema_internal_error()
|
|
|
- , <<"200">> => schema_gateway_stats()
|
|
|
- }
|
|
|
+schema("/gateway/:name/stats") ->
|
|
|
+ #{ 'operationId' => gateway_insta_stats,
|
|
|
+ get =>
|
|
|
+ #{ description => <<"Get gateway Statistic">>
|
|
|
+ , parameters => params_gateway_name_in_path()
|
|
|
+ , responses =>
|
|
|
+ ?STANDARD_RESP(
|
|
|
+ #{200 => emqx_dashboard_swagger:schema_with_examples(
|
|
|
+ ref(gateway_stats),
|
|
|
+ examples_gateway_stats())
|
|
|
+ })
|
|
|
+ }
|
|
|
}.
|
|
|
|
|
|
%%--------------------------------------------------------------------
|
|
|
%% params defines
|
|
|
|
|
|
params_gateway_name_in_path() ->
|
|
|
- [#{ name => name
|
|
|
- , in => path
|
|
|
- , schema => #{type => string}
|
|
|
- , required => true
|
|
|
- }].
|
|
|
+ [{name,
|
|
|
+ mk(binary(),
|
|
|
+ #{ in => path
|
|
|
+ , desc => <<"Gateway Name">>
|
|
|
+ })}
|
|
|
+ ].
|
|
|
|
|
|
params_gateway_status_in_qs() ->
|
|
|
- [#{ name => status
|
|
|
- , in => query
|
|
|
- , schema => #{type => string}
|
|
|
- , required => false
|
|
|
- }].
|
|
|
+ [{status,
|
|
|
+ mk(binary(),
|
|
|
+ #{ in => query
|
|
|
+ , nullable => true
|
|
|
+ , desc => <<"Gateway Status">>
|
|
|
+ })}
|
|
|
+ ].
|
|
|
|
|
|
%%--------------------------------------------------------------------
|
|
|
%% schemas
|
|
|
|
|
|
-schema_gateway_overview_list() ->
|
|
|
- emqx_mgmt_util:array_schema(
|
|
|
- #{ type => object
|
|
|
- , properties => properties_gateway_overview()
|
|
|
- },
|
|
|
- <<"Gateway list">>
|
|
|
- ).
|
|
|
-
|
|
|
-%% XXX: This is whole confs for all type gateways. It is used to fill the
|
|
|
-%% default configurations and generate the swagger-schema
|
|
|
-%%
|
|
|
-%% NOTE: It is a temporary measure to generate swagger-schema
|
|
|
--define(COAP_GATEWAY_CONFS,
|
|
|
-#{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_BINARY =>
|
|
|
- #{<<"mechanism">> => <<"password-based">>,
|
|
|
- <<"name">> => <<"authenticator1">>,
|
|
|
- <<"server_type">> => <<"built-in-database">>,
|
|
|
- <<"user_id_type">> => <<"clientid">>},
|
|
|
- <<"name">> => <<"coap">>,
|
|
|
- <<"enable">> => true,
|
|
|
- <<"enable_stats">> => true,<<"heartbeat">> => <<"30s">>,
|
|
|
- <<"idle_timeout">> => <<"30s">>,
|
|
|
- <<"listeners">> => [
|
|
|
- #{<<"id">> => <<"coap:udp:default">>,
|
|
|
- <<"type">> => <<"udp">>,
|
|
|
- <<"running">> => true,
|
|
|
- <<"acceptors">> => 8,<<"bind">> => 5683,
|
|
|
- <<"max_conn_rate">> => 1000,
|
|
|
- <<"max_connections">> => 10240}],
|
|
|
- <<"mountpoint">> => <<>>,<<"notify_type">> => <<"qos">>,
|
|
|
- <<"publish_qos">> => <<"qos1">>,
|
|
|
- <<"subscribe_qos">> => <<"qos0">>}
|
|
|
-).
|
|
|
-
|
|
|
--define(EXPROTO_GATEWAY_CONFS,
|
|
|
-#{<<"enable">> => true,
|
|
|
- <<"name">> => <<"exproto">>,
|
|
|
- <<"enable_stats">> => true,
|
|
|
- <<"handler">> =>
|
|
|
- #{<<"address">> => <<"http://127.0.0.1:9001">>},
|
|
|
- <<"idle_timeout">> => <<"30s">>,
|
|
|
- <<"listeners">> => [
|
|
|
- #{<<"id">> => <<"exproto:tcp:default">>,
|
|
|
- <<"type">> => <<"tcp">>,
|
|
|
- <<"running">> => true,
|
|
|
- <<"acceptors">> => 8,<<"bind">> => 7993,
|
|
|
- <<"max_conn_rate">> => 1000,
|
|
|
- <<"max_connections">> => 10240}],
|
|
|
- <<"mountpoint">> => <<>>,
|
|
|
- <<"server">> => #{<<"bind">> => 9100}}
|
|
|
-).
|
|
|
+roots() ->
|
|
|
+ [ gateway_overview
|
|
|
+ , gateway_stats
|
|
|
+ ].
|
|
|
|
|
|
--define(LWM2M_GATEWAY_CONFS,
|
|
|
-#{<<"auto_observe">> => false,
|
|
|
- <<"name">> => <<"lwm2m">>,
|
|
|
- <<"enable">> => true,
|
|
|
- <<"enable_stats">> => true,
|
|
|
- <<"idle_timeout">> => <<"30s">>,
|
|
|
- <<"lifetime_max">> => <<"86400s">>,
|
|
|
- <<"lifetime_min">> => <<"1s">>,
|
|
|
- <<"listeners">> => [
|
|
|
- #{<<"id">> => <<"lwm2m:udp:default">>,
|
|
|
- <<"type">> => <<"udp">>,
|
|
|
- <<"running">> => true,
|
|
|
- <<"bind">> => 5783}],
|
|
|
- <<"mountpoint">> => <<"lwm2m/", ?PH_S_ENDPOINT_NAME, "/">>,
|
|
|
- <<"qmode_time_windonw">> => 22,
|
|
|
- <<"translators">> =>
|
|
|
- #{<<"command">> => <<"dn/#">>,<<"notify">> => <<"up/notify">>,
|
|
|
- <<"register">> => <<"up/resp">>,
|
|
|
- <<"response">> => <<"up/resp">>,
|
|
|
- <<"update">> => <<"up/resp">>},
|
|
|
- <<"update_msg_publish_condition">> =>
|
|
|
- <<"contains_object_list">>,
|
|
|
- <<"xml_dir">> => <<"etc/lwm2m_xml">>}
|
|
|
-).
|
|
|
+fields(gateway_overview) ->
|
|
|
+ [ {name,
|
|
|
+ mk(string(),
|
|
|
+ #{ desc => <<"Gateway Name">>})}
|
|
|
+ , {status,
|
|
|
+ mk(hoconsc:enum([running, stopped, unloaded]),
|
|
|
+ #{ desc => <<"The Gateway status">>})}
|
|
|
+ , {created_at,
|
|
|
+ mk(string(),
|
|
|
+ #{desc => <<"The Gateway created datetime">>})}
|
|
|
+ , {started_at,
|
|
|
+ mk(string(),
|
|
|
+ #{ nullable => true
|
|
|
+ , desc => <<"The Gateway started datetime">>})}
|
|
|
+ , {stopped_at,
|
|
|
+ mk(string(),
|
|
|
+ #{ nullable => true
|
|
|
+ , desc => <<"The Gateway stopped datetime">>})}
|
|
|
+ , {max_connections,
|
|
|
+ mk(integer(),
|
|
|
+ #{ desc => <<"The Gateway allowed maximum connections/clients">>})}
|
|
|
+ , {current_connections,
|
|
|
+ mk(integer(),
|
|
|
+ #{ desc => <<"The Gateway current connected connections/clients">>
|
|
|
+ })}
|
|
|
+ , {listeners,
|
|
|
+ mk(hoconsc:array(ref(gateway_listener_overview)),
|
|
|
+ #{ nullable => {true, recursively}
|
|
|
+ , desc => <<"The Gateway listeners overview">>})}
|
|
|
+ ];
|
|
|
+fields(gateway_listener_overview) ->
|
|
|
+ [ {id,
|
|
|
+ mk(string(),
|
|
|
+ #{ desc => <<"Listener ID">>})}
|
|
|
+ , {running,
|
|
|
+ mk(boolean(),
|
|
|
+ #{ desc => <<"Listener Running status">>})}
|
|
|
+ , {type,
|
|
|
+ mk(hoconsc:enum([tcp, ssl, udp, dtls]),
|
|
|
+ #{ desc => <<"Listener Type">>})}
|
|
|
+ ];
|
|
|
|
|
|
--define(MQTTSN_GATEWAY_CONFS,
|
|
|
-#{<<"broadcast">> => true,
|
|
|
- <<"clientinfo_override">> =>
|
|
|
- #{<<"password">> => <<"abc">>,
|
|
|
- <<"username">> => <<"mqtt_sn_user">>},
|
|
|
- <<"enable">> => true,
|
|
|
- <<"name">> => <<"mqtt-sn">>,
|
|
|
- <<"enable_qos3">> => true,<<"enable_stats">> => true,
|
|
|
- <<"gateway_id">> => 1,<<"idle_timeout">> => <<"30s">>,
|
|
|
- <<"listeners">> => [
|
|
|
- #{<<"id">> => <<"mqttsn:udp:default">>,
|
|
|
- <<"type">> => <<"udp">>,
|
|
|
- <<"running">> => true,
|
|
|
- <<"bind">> => 1884,<<"max_conn_rate">> => 1000,
|
|
|
- <<"max_connections">> => 10240000}],
|
|
|
- <<"mountpoint">> => <<>>,
|
|
|
- <<"predefined">> =>
|
|
|
- [#{<<"id">> => 1,
|
|
|
- <<"topic">> => <<"/predefined/topic/name/hello">>},
|
|
|
- #{<<"id">> => 2,
|
|
|
- <<"topic">> => <<"/predefined/topic/name/nice">>}]}
|
|
|
-).
|
|
|
+fields(Gw) when Gw == stomp; Gw == mqttsn;
|
|
|
+ Gw == coap; Gw == lwm2m;
|
|
|
+ Gw == exproto ->
|
|
|
+ convert_listener_struct(emqx_gateway_schema:fields(Gw));
|
|
|
+fields(Listener) when Listener == tcp_listener;
|
|
|
+ Listener == ssl_listener;
|
|
|
+ Listener == udp_listener;
|
|
|
+ Listener == dtls_listener ->
|
|
|
+ [ {type,
|
|
|
+ mk(hoconsc:union([tcp, ssl, udp, dtls]),
|
|
|
+ #{ desc => <<"Listener type">>})}
|
|
|
+ , {name,
|
|
|
+ mk(string(),
|
|
|
+ #{ desc => <<"Listener Name">>})}
|
|
|
+ , {running,
|
|
|
+ mk(boolean(),
|
|
|
+ #{ desc => <<"Listener running status">>})}
|
|
|
+ ] ++ emqx_gateway_schema:fields(Listener);
|
|
|
|
|
|
--define(STOMP_GATEWAY_CONFS,
|
|
|
-#{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_BINARY =>
|
|
|
- #{<<"mechanism">> => <<"password-based">>,
|
|
|
- <<"name">> => <<"authenticator1">>,
|
|
|
- <<"server_type">> => <<"built-in-database">>,
|
|
|
- <<"user_id_type">> => <<"clientid">>},
|
|
|
- <<"clientinfo_override">> =>
|
|
|
- #{<<"password">> => <<"${Packet.headers.passcode}">>,
|
|
|
- <<"username">> => <<"${Packet.headers.login}">>},
|
|
|
- <<"enable">> => true,
|
|
|
- <<"name">> => <<"stomp">>,
|
|
|
- <<"enable_stats">> => true,
|
|
|
- <<"frame">> =>
|
|
|
- #{<<"max_body_length">> => 8192,<<"max_headers">> => 10,
|
|
|
- <<"max_headers_length">> => 1024},
|
|
|
- <<"idle_timeout">> => <<"30s">>,
|
|
|
- <<"listeners">> => [
|
|
|
- #{<<"id">> => <<"stomp:tcp:default">>,
|
|
|
- <<"type">> => <<"tcp">>,
|
|
|
- <<"running">> => true,
|
|
|
- <<"acceptors">> => 16,<<"active_n">> => 100,
|
|
|
- <<"bind">> => 61613,<<"max_conn_rate">> => 1000,
|
|
|
- <<"max_connections">> => 1024000}],
|
|
|
- <<"mountpoint">> => <<>>}
|
|
|
-).
|
|
|
+fields(gateway_stats) ->
|
|
|
+ [{key, mk(string(), #{})}].
|
|
|
|
|
|
-%% --- END
|
|
|
+schema_gateways_conf() ->
|
|
|
+ %% XXX: We need convert the emqx_gateway_schema's listener map
|
|
|
+ %% structure to array
|
|
|
+ emqx_dashboard_swagger:schema_with_examples(
|
|
|
+ hoconsc:union([ref(stomp), ref(mqttsn),
|
|
|
+ ref(coap), ref(lwm2m), ref(exproto)]),
|
|
|
+ examples_gateway_confs()
|
|
|
+ ).
|
|
|
|
|
|
-schema_gateway_conf() ->
|
|
|
- emqx_mgmt_util:schema(
|
|
|
- #{oneOf =>
|
|
|
- [ emqx_mgmt_api_configs:gen_schema(?STOMP_GATEWAY_CONFS)
|
|
|
- , emqx_mgmt_api_configs:gen_schema(?MQTTSN_GATEWAY_CONFS)
|
|
|
- , emqx_mgmt_api_configs:gen_schema(?COAP_GATEWAY_CONFS)
|
|
|
- , emqx_mgmt_api_configs:gen_schema(?LWM2M_GATEWAY_CONFS)
|
|
|
- , emqx_mgmt_api_configs:gen_schema(?EXPROTO_GATEWAY_CONFS)
|
|
|
- ]}).
|
|
|
+convert_listener_struct(Schema) ->
|
|
|
+ {value, {listeners,
|
|
|
+ #{type := Type}}, Schema1} = lists:keytake(listeners, 1, Schema),
|
|
|
+ ListenerSchema = hoconsc:mk(listeners_schema(Type),
|
|
|
+ #{ nullable => {true, recursively}
|
|
|
+ , desc => <<"The gateway listeners">>
|
|
|
+ }),
|
|
|
+ lists:keystore(listeners, 1, Schema1, {listeners, ListenerSchema}).
|
|
|
|
|
|
-schema_gateway_stats() ->
|
|
|
- emqx_mgmt_util:schema(
|
|
|
- #{ type => object
|
|
|
- , properties =>
|
|
|
- #{ a_key => #{type => string}
|
|
|
- }}).
|
|
|
+listeners_schema(?R_REF(_Mod, tcp_listeners)) ->
|
|
|
+ hoconsc:array(hoconsc:union([ref(tcp_listener), ref(ssl_listener)]));
|
|
|
+listeners_schema(?R_REF(_Mod, udp_listeners)) ->
|
|
|
+ hoconsc:array(hoconsc:union([ref(udp_listener), ref(dtls_listener)]));
|
|
|
+listeners_schema(?R_REF(_Mod, udp_tcp_listeners)) ->
|
|
|
+ hoconsc:array(hoconsc:union([ref(tcp_listener), ref(ssl_listener),
|
|
|
+ ref(udp_listener), ref(dtls_listener)])).
|
|
|
|
|
|
%%--------------------------------------------------------------------
|
|
|
-%% properties
|
|
|
+%% examples
|
|
|
+
|
|
|
+examples_gateway_confs() ->
|
|
|
+ #{ a_stomp_gateway =>
|
|
|
+ #{ enable => true
|
|
|
+ , enable_stats => true
|
|
|
+ , idle_timeout => <<"30s">>
|
|
|
+ , mountpoint => <<"stomp/">>
|
|
|
+ , frame =>
|
|
|
+ #{ max_header => 10
|
|
|
+ , make_header_length => 1024
|
|
|
+ , max_body_length => 65535
|
|
|
+ }
|
|
|
+ }
|
|
|
+ , a_mqttsn_gateway =>
|
|
|
+ #{ enable => true
|
|
|
+ , enable_stats => true
|
|
|
+ }
|
|
|
+ }.
|
|
|
|
|
|
-properties_gateway_overview() ->
|
|
|
- ListenerProps =
|
|
|
- [ {id, string,
|
|
|
- <<"Listener ID">>}
|
|
|
- , {running, boolean,
|
|
|
- <<"Listener Running status">>}
|
|
|
- , {type, string,
|
|
|
- <<"Listener Type">>, [<<"tcp">>, <<"ssl">>, <<"udp">>, <<"dtls">>]}
|
|
|
- ],
|
|
|
- emqx_mgmt_util:properties(
|
|
|
- [ {name, string,
|
|
|
- <<"Gateway Name">>}
|
|
|
- , {status, string,
|
|
|
- <<"Gateway Status">>,
|
|
|
- [<<"running">>, <<"stopped">>, <<"unloaded">>]}
|
|
|
- , {created_at, string,
|
|
|
- <<>>}
|
|
|
- , {started_at, string,
|
|
|
- <<>>}
|
|
|
- , {stopped_at, string,
|
|
|
- <<>>}
|
|
|
- , {max_connections, integer, <<>>}
|
|
|
- , {current_connections, integer, <<>>}
|
|
|
- , {listeners, {array, object}, ListenerProps}
|
|
|
- ]).
|
|
|
+examples_gateway_stats() ->
|
|
|
+ #{}.
|