diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src index 1ba47a70f..77610eb8a 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src @@ -2,13 +2,15 @@ %% Unless you know what you are doing, DO NOT edit manually!! {VSN, [{"4.3.8", - [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_metrics,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_funcs,brutal_purge,soft_purge,[]}]}, {"4.3.7", - [{load_module,emqx_rule_funcs,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_metrics,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_funcs,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, @@ -85,13 +87,15 @@ {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {<<".*">>,[]}], [{"4.3.8", - [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_metrics,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_funcs,brutal_purge,soft_purge,[]}]}, {"4.3.7", - [{load_module,emqx_rule_funcs,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_metrics,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_funcs,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, 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 313591ff3..b2766e0e0 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl @@ -58,6 +58,13 @@ descr => "Delete a rule" }). +-rest_api(#{name => reset_metrics, + method => 'PUT', + path => "/rules/:bin:id/reset_metrics", + func => reset_metrics, + descr => "reset a rule metrics" + }). + -rest_api(#{name => list_actions, method => 'GET', path => "/actions/", @@ -154,6 +161,7 @@ , list_rules/2 , show_rule/2 , delete_rule/2 + , reset_metrics/2 ]). -export([ list_actions/2 @@ -252,6 +260,10 @@ delete_rule(#{id := Id}, _Params) -> ok = emqx_rule_engine:delete_rule(Id), return(ok). +reset_metrics(#{id := Id}, _Params) -> + ok = emqx_rule_metrics:reset_metrics(Id), + return(ok). + %%------------------------------------------------------------------------------ %% Actions API %%------------------------------------------------------------------------------ diff --git a/apps/emqx_rule_engine/src/emqx_rule_metrics.erl b/apps/emqx_rule_engine/src/emqx_rule_metrics.erl index c7c38e145..9c6bfe905 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_metrics.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_metrics.erl @@ -63,6 +63,7 @@ , create_metrics/1 , clear_rule_metrics/1 , clear_metrics/1 + , reset_metrics/1 ]). -export([ get_rule_metrics/1 @@ -127,6 +128,45 @@ clear_rule_metrics(Id) -> clear_metrics(Id) -> gen_server:call(?MODULE, {delete_metrics, Id}). +-spec(reset_metrics(rule_id()) -> ok). +reset_metrics(Id) -> + reset_speeds(Id), + reset_metrics(Id, rule_metrics()), + case emqx_rule_registry:get_rule(Id) of + not_found -> ok; + {ok, #rule{actions = Actions}} -> + [ reset_metrics(ActionId, action_metrics()) + || #action_instance{ id = ActionId} <- Actions], + ok + end. + +reset_metrics(Id, Metrics) -> + case couters_ref(Id) of + not_found -> ok; + Ref -> [counters:put(Ref, metrics_idx(Idx), 0) + || Idx <- Metrics], + ok + end. + +reset_speeds(Id) -> + gen_server:call(?MODULE, {reset_speeds, Id}). + +rule_metrics() -> + [ 'rules.matched' + , 'rules.failed' + , 'rules.passed' + , 'rules.exception' + , 'rules.no_result' + ]. + +action_metrics() -> + [ 'actions.success' + , 'actions.error' + , 'actions.taken' + , 'actions.exception' + , 'actions.retry' + ]. + -spec(get(rule_id(), atom()) -> number()). get(Id, Metric) -> case couters_ref(Id) of @@ -288,6 +328,9 @@ handle_call({create_rule_metrics, Id}, _From, _ -> RuleSpeeds#{Id => #rule_speed{}} end}}; +handle_call({reset_speeds, Id}, _From, State = #state{rule_speeds = RuleSpeedMap}) -> + {reply, ok, State#state{rule_speeds = maps:put(Id, #rule_speed{}, RuleSpeedMap)}}; + handle_call({delete_metrics, Id}, _From, State = #state{metric_ids = MIDs, rule_speeds = undefined}) -> {reply, delete_counters(Id), State#state{metric_ids = sets:del_element(Id, MIDs)}}; @@ -325,7 +368,7 @@ handle_info(_Info, State) -> {noreply, State}. code_change({down, _Vsn}, State = #state{metric_ids = MIDs}, [Vsn]) -> - case string:tokens(Vsn, ".") of + case string:tokens(Vsn, ".") of ["4", "3", SVal] -> {Val, []} = string:to_integer(SVal), case Val =< 6 of diff --git a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl index 02e0f607c..1c11d756f 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl @@ -49,6 +49,7 @@ groups() -> [t_register_provider, t_unregister_provider, t_create_rule, + t_reset_metrics, t_create_resource ]}, {actions, [], @@ -351,6 +352,39 @@ t_inspect_action(_Config) -> emqx_rule_registry:remove_resource(ResId), ok. +t_reset_metrics(_Config) -> + ok = emqx_rule_engine:load_providers(), + {ok, #resource{id = ResId}} = emqx_rule_engine:create_resource( + #{type => built_in, + config => #{}, + description => <<"debug resource">>}), + {ok, #rule{id = Id}} = emqx_rule_engine:create_rule( + #{rawsql => "select clientid as c, username as u " + "from \"t1\" ", + actions => [#{name => 'inspect', + args => #{'$resource' => ResId, a=>1, b=>2}}], + type => built_in, + description => <<"Inspect rule">> + }), + {ok, Client} = emqtt:start_link([{username, <<"emqx">>}]), + {ok, _} = emqtt:connect(Client), + [ begin + emqtt:publish(Client, <<"t1">>, <<"{\"id\": 1, \"name\": \"ha\"}">>, 0), + timer:sleep(100) + end + || _ <- lists:seq(1,10)], + emqx_rule_metrics:reset_metrics(Id), + ?assertEqual(#{exception => 0,failed => 0, + matched => 0,no_result => 0,passed => 0, + speed => 0.0,speed_last5m => 0.0,speed_max => 0}, + emqx_rule_metrics:get_rule_metrics(Id)), + ?assertEqual(#{failed => 0,success => 0,taken => 0}, + emqx_rule_metrics:get_action_metrics(ResId)), + emqtt:stop(Client), + emqx_rule_registry:remove_rule(Id), + emqx_rule_registry:remove_resource(ResId), + ok. + t_republish_action(_Config) -> Qos0Received = emqx_metrics:val('messages.qos0.received'), Received = emqx_metrics:val('messages.received'),