187 lines
8.4 KiB
Erlang
187 lines
8.4 KiB
Erlang
-module(emqx_rule_api_schema).
|
|
|
|
-behaviour(hocon_schema).
|
|
|
|
-include_lib("typerefl/include/types.hrl").
|
|
-include_lib("emqx/include/logger.hrl").
|
|
|
|
-export([ check_params/2
|
|
]).
|
|
|
|
-export([roots/0, fields/1]).
|
|
|
|
-type tag() :: rule_creation | rule_test.
|
|
|
|
-spec check_params(map(), tag()) -> {ok, map()} | {error, term()}.
|
|
check_params(Params, Tag) ->
|
|
BTag = atom_to_binary(Tag),
|
|
try hocon_schema:check_plain(?MODULE, #{BTag => Params},
|
|
#{atom_key => true, nullable => true}, [BTag]) of
|
|
#{Tag := Checked} -> {ok, Checked}
|
|
catch
|
|
Error:Reason:ST ->
|
|
?SLOG(error, #{msg => "check_rule_params_failed",
|
|
exception => Error,
|
|
reason => Reason,
|
|
stacktrace => ST}),
|
|
{error, {Reason, ST}}
|
|
end.
|
|
|
|
%%======================================================================================
|
|
%% Hocon Schema Definitions
|
|
|
|
roots() ->
|
|
[ {"rule_creation", sc(ref("rule_creation"), #{desc => "Schema for creating rules"})}
|
|
, {"rule_info", sc(ref("rule_info"), #{desc => "Schema for rule info"})}
|
|
, {"rule_events", sc(ref("rule_events"), #{desc => "Schema for rule events"})}
|
|
, {"rule_test", sc(ref("rule_test"), #{desc => "Schema for testing rules"})}
|
|
].
|
|
|
|
fields("rule_creation") ->
|
|
[ {"id", sc(binary(),
|
|
#{ desc => "The Id of the rule", nullable => false
|
|
, example => "my_rule_id"
|
|
})}
|
|
] ++ emqx_rule_engine_schema:fields("rules");
|
|
|
|
fields("rule_info") ->
|
|
[ {"metrics", sc(ref("metrics"), #{desc => "The metrics of the rule"})}
|
|
, {"node_metrics", sc(ref("node_metrics"), #{desc => "The metrics of the rule"})}
|
|
, {"from", sc(hoconsc:array(binary()),
|
|
#{desc => "The topics of the rule", example => "t/#"})}
|
|
, {"created_at", sc(binary(),
|
|
#{ desc => "The created time of the rule"
|
|
, example => "2021-12-01T15:00:43.153+08:00"
|
|
})}
|
|
] ++ fields("rule_creation");
|
|
|
|
%% TODO: we can delete this API if the Dashboard not denpends on it
|
|
fields("rule_events") ->
|
|
ETopics = [emqx_rule_events:event_topic(E) || E <- emqx_rule_events:event_names()],
|
|
[ {"event", sc(hoconsc:enum(ETopics), #{desc => "The event topics", nullable => false})}
|
|
, {"title", sc(binary(), #{desc => "The title", example => "some title"})}
|
|
, {"description", sc(binary(), #{desc => "The description", example => "some desc"})}
|
|
, {"columns", sc(map(), #{desc => "The columns"})}
|
|
, {"test_columns", sc(map(), #{desc => "The test columns"})}
|
|
, {"sql_example", sc(binary(), #{desc => "The sql_example"})}
|
|
];
|
|
|
|
fields("rule_test") ->
|
|
[ {"context", sc(hoconsc:union([ ref("ctx_pub")
|
|
, ref("ctx_sub")
|
|
, ref("ctx_delivered")
|
|
, ref("ctx_acked")
|
|
, ref("ctx_dropped")
|
|
, ref("ctx_connected")
|
|
, ref("ctx_disconnected")
|
|
]),
|
|
#{desc => "The context of the event for testing",
|
|
default => #{}})}
|
|
, {"sql", sc(binary(), #{desc => "The SQL of the rule for testing", nullable => false})}
|
|
];
|
|
|
|
fields("metrics") ->
|
|
[ {"matched", sc(integer(), #{desc => "How much times this rule is matched"})}
|
|
, {"rate", sc(float(), #{desc => "The rate of matched, times/second"})}
|
|
, {"rate_max", sc(float(), #{desc => "The max rate of matched, times/second"})}
|
|
, {"rate_last5m", sc(float(),
|
|
#{desc => "The average rate of matched in last 5 mins, times/second"})}
|
|
];
|
|
|
|
fields("node_metrics") ->
|
|
[ {"node", sc(binary(), #{desc => "The node name", example => "emqx@127.0.0.1"})}
|
|
] ++ fields("metrics");
|
|
|
|
fields("ctx_pub") ->
|
|
[ {"event_type", sc(message_publish, #{desc => "Event Type", nullable => false})}
|
|
, {"id", sc(binary(), #{desc => "Message ID"})}
|
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
|
|
, {"peerhost", sc(binary(), #{desc => "The IP Address of the Peer Client"})}
|
|
, {"topic", sc(binary(), #{desc => "Message Topic"})}
|
|
, {"publish_received_at", sc(integer(), #{
|
|
desc => "The Time that this Message is Received"})}
|
|
] ++ [qos()];
|
|
|
|
fields("ctx_sub") ->
|
|
[ {"event_type", sc(session_subscribed, #{desc => "Event Type", nullable => false})}
|
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
|
|
, {"peerhost", sc(binary(), #{desc => "The IP Address of the Peer Client"})}
|
|
, {"topic", sc(binary(), #{desc => "Message Topic"})}
|
|
, {"publish_received_at", sc(integer(), #{
|
|
desc => "The Time that this Message is Received"})}
|
|
] ++ [qos()];
|
|
|
|
fields("ctx_unsub") ->
|
|
[{"event_type", sc(session_unsubscribed, #{desc => "Event Type", nullable => false})}] ++
|
|
proplists:delete("event_type", fields("ctx_sub"));
|
|
|
|
fields("ctx_delivered") ->
|
|
[ {"event_type", sc(message_delivered, #{desc => "Event Type", nullable => false})}
|
|
, {"id", sc(binary(), #{desc => "Message ID"})}
|
|
, {"from_clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"from_username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
|
|
, {"peerhost", sc(binary(), #{desc => "The IP Address of the Peer Client"})}
|
|
, {"topic", sc(binary(), #{desc => "Message Topic"})}
|
|
, {"publish_received_at", sc(integer(), #{
|
|
desc => "The Time that this Message is Received"})}
|
|
] ++ [qos()];
|
|
|
|
fields("ctx_acked") ->
|
|
[{"event_type", sc(message_acked, #{desc => "Event Type", nullable => false})}] ++
|
|
proplists:delete("event_type", fields("ctx_delivered"));
|
|
|
|
fields("ctx_dropped") ->
|
|
[ {"event_type", sc(message_dropped, #{desc => "Event Type", nullable => false})}
|
|
, {"id", sc(binary(), #{desc => "Message ID"})}
|
|
, {"reason", sc(binary(), #{desc => "The Reason for Dropping"})}
|
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
|
|
, {"peerhost", sc(binary(), #{desc => "The IP Address of the Peer Client"})}
|
|
, {"topic", sc(binary(), #{desc => "Message Topic"})}
|
|
, {"publish_received_at", sc(integer(), #{
|
|
desc => "The Time that this Message is Received"})}
|
|
] ++ [qos()];
|
|
|
|
fields("ctx_connected") ->
|
|
[ {"event_type", sc(client_connected, #{desc => "Event Type", nullable => false})}
|
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"mountpoint", sc(binary(), #{desc => "The Mountpoint"})}
|
|
, {"peername", sc(binary(), #{desc => "The IP Address and Port of the Peer Client"})}
|
|
, {"sockname", sc(binary(), #{desc => "The IP Address and Port of the Local Listener"})}
|
|
, {"proto_name", sc(binary(), #{desc => "Protocol Name"})}
|
|
, {"proto_ver", sc(binary(), #{desc => "Protocol Version"})}
|
|
, {"keepalive", sc(integer(), #{desc => "KeepAlive"})}
|
|
, {"clean_start", sc(boolean(), #{desc => "Clean Start", default => true})}
|
|
, {"expiry_interval", sc(integer(), #{desc => "Expiry Interval"})}
|
|
, {"is_bridge", sc(boolean(), #{desc => "Is Bridge", default => false})}
|
|
, {"connected_at", sc(integer(), #{
|
|
desc => "The Time that this Client is Connected"})}
|
|
];
|
|
|
|
fields("ctx_disconnected") ->
|
|
[ {"event_type", sc(client_disconnected, #{desc => "Event Type", nullable => false})}
|
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
|
, {"reason", sc(binary(), #{desc => "The Reason for Disconnect"})}
|
|
, {"peername", sc(binary(), #{desc => "The IP Address and Port of the Peer Client"})}
|
|
, {"sockname", sc(binary(), #{desc => "The IP Address and Port of the Local Listener"})}
|
|
, {"disconnected_at", sc(integer(), #{
|
|
desc => "The Time that this Client is Disconnected"})}
|
|
].
|
|
|
|
qos() ->
|
|
{"qos", sc(hoconsc:union([typerefl:integer(0), typerefl:integer(1), typerefl:integer(2)]),
|
|
#{desc => "The Message QoS"})}.
|
|
|
|
sc(Type, Meta) -> hoconsc:mk(Type, Meta).
|
|
ref(Field) -> hoconsc:ref(?MODULE, Field).
|