diff --git a/apps/emqx_rule_engine/i18n/emqx_rule_engine_schema.conf b/apps/emqx_rule_engine/i18n/emqx_rule_engine_schema.conf index 7f5a81a70..b6dd2d3b5 100644 --- a/apps/emqx_rule_engine/i18n/emqx_rule_engine_schema.conf +++ b/apps/emqx_rule_engine/i18n/emqx_rule_engine_schema.conf @@ -70,6 +70,17 @@ counter of the function action or the bridge channel will increase. } } + rules_metadata { + desc { + en: "Rule metadata, do not change manually" + zh: "规则的元数据,不要手动修改" + } + label: { + en: "Rule metadata" + zh: "规则的元数据" + } + } + rules_description { desc { en: "The description of the rule" diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.erl b/apps/emqx_rule_engine/src/emqx_rule_engine.erl index fe46b6867..f991c7b4f 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.erl @@ -66,6 +66,8 @@ %% exported for `emqx_telemetry' -export([get_basic_usage_info/0]). +-export([now_ms/0]). + %% gen_server Callbacks -export([ init/1, @@ -137,16 +139,22 @@ post_config_update(_, _Req, NewRules, OldRules, _AppEnvs) -> -spec load_rules() -> ok. load_rules() -> maps_foreach( - fun({Id, Rule}) -> - {ok, _} = create_rule(Rule#{id => bin(Id)}) + fun + ({Id, #{metadata := #{created_at := CreatedAt}} = Rule}) -> + create_rule(Rule#{id => bin(Id)}, CreatedAt); + ({Id, Rule}) -> + create_rule(Rule#{id => bin(Id)}) end, emqx:get_config([rule_engine, rules], #{}) ). -spec create_rule(map()) -> {ok, rule()} | {error, term()}. -create_rule(Params = #{id := RuleId}) when is_binary(RuleId) -> +create_rule(Params) -> + create_rule(Params, now_ms()). + +create_rule(Params = #{id := RuleId}, CreatedAt) when is_binary(RuleId) -> case get_rule(RuleId) of - not_found -> parse_and_insert(Params, now_ms()); + not_found -> parse_and_insert(Params, CreatedAt); {ok, _} -> {error, already_exists} end. diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl index b1dbd72d9..658781636 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl @@ -233,11 +233,6 @@ param_path_id() -> %% Rules API %%------------------------------------------------------------------------------ -%% To get around the hocon bug, we replace crlf with spaces -replace_sql_clrf(#{<<"sql">> := SQL} = Params) -> - NewSQL = re:replace(SQL, "[\r\n]", " ", [{return, binary}, global]), - Params#{<<"sql">> => NewSQL}. - '/rule_events'(get, _Params) -> {200, emqx_rule_events:event_info()}. @@ -249,7 +244,7 @@ replace_sql_clrf(#{<<"sql">> := SQL} = Params) -> <<>> -> {400, #{code => 'BAD_REQUEST', message => <<"empty rule id is not allowed">>}}; Id -> - Params = filter_out_request_body(replace_sql_clrf(Params0)), + Params = filter_out_request_body(add_metadata(Params0)), ConfPath = emqx_rule_engine:config_key_path() ++ [Id], case emqx_rule_engine:get_rule(Id) of {ok, _Rule} -> @@ -491,6 +486,13 @@ aggregate_metrics(AllMetrics) -> get_one_rule(AllRules, Id) -> [R || R = #{id := Id0} <- AllRules, Id0 == Id]. +add_metadata(Params) -> + Params#{ + <<"metadata">> => #{ + <<"created_at">> => emqx_rule_engine:now_ms() + } + }. + filter_out_request_body(Conf) -> ExtraConfs = [ <<"id">>, diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl index 2025c2186..c6e7a2bc0 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl @@ -91,7 +91,8 @@ fields("rules") -> example => "Some description", default => <<>> } - )} + )}, + {"metadata", ?HOCON(map(), #{desc => ?DESC("rules_metadata")})} ]; fields("builtin_action_republish") -> [