refactor(exhook): load only the necessary hooks

This commit is contained in:
JianBo He 2021-02-25 19:55:54 +08:00 committed by JianBo He
parent 4585306774
commit 0d8c137cb5
3 changed files with 68 additions and 12 deletions

View File

@ -22,6 +22,8 @@
-emqx_plugin(extension).
-define(REGISTRAY, emqx_exhook_registray).
-export([ start/2
, stop/1
, prep_stop/1
@ -30,8 +32,8 @@
%% Internal export
-export([ load_server/2
, unload_server/1
, load_exhooks/0
, unload_exhooks/0
, init_hook_registray/0
]).
%%--------------------------------------------------------------------
@ -41,12 +43,12 @@
start(_StartType, _StartArgs) ->
{ok, Sup} = emqx_exhook_sup:start_link(),
%% Collect all available hooks
_ = init_hook_registray(),
%% Load all dirvers
load_all_servers(),
%% Register all hooks
_ = load_exhooks(),
%% Register CLI
emqx_ctl:register_command(exhook, {emqx_exhook_cli, cli}, []),
{ok, Sup}.
@ -81,11 +83,14 @@ unload_server(Name) ->
%%--------------------------------------------------------------------
%% Exhooks
load_exhooks() ->
[emqx:hook(Name, {M, F, A}) || {Name, {M, F, A}} <- search_exhooks()].
init_hook_registray() ->
_ = ets:new(?REGISTRAY, [public, named_table]),
[ets:insert(?REGISTRAY, {Name, {M, F, A}, 0})
|| {Name, {M, F, A}} <- search_exhooks()].
unload_exhooks() ->
[emqx:unhook(Name, {M, F}) || {Name, {M, F, _A}} <- search_exhooks()].
[emqx:unhook(Name, {M, F}) ||
{Name, {M, F, _A}, _} <- ets:tab2list(?REGISTRAY)].
search_exhooks() ->
search_exhooks(ignore_lib_apps(application:loaded_applications())).

View File

@ -307,8 +307,26 @@ stringfy(Term) when is_atom(Term) ->
stringfy(Term) ->
unicode:characters_to_binary((io_lib:format("~0p", [Term]))).
hexstr(B) ->
iolist_to_binary([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(B)]).
hexstr(<<>>) -> [];
hexstr(<<H:4, L:4, B/binary>>) ->
iolist_to_binary([hexchar(H), hexchar(L)] ++ hexstr(B)).
hexchar(0) -> $0;
hexchar(1) -> $1;
hexchar(2) -> $2;
hexchar(3) -> $3;
hexchar(4) -> $4;
hexchar(5) -> $5;
hexchar(6) -> $6;
hexchar(7) -> $7;
hexchar(8) -> $8;
hexchar(9) -> $9;
hexchar(10) -> $A;
hexchar(11) -> $B;
hexchar(12) -> $C;
hexchar(13) -> $D;
hexchar(14) -> $E;
hexchar(15) -> $F.
%%--------------------------------------------------------------------
%% Acc funcs

View File

@ -20,6 +20,7 @@
-logger_header("[ExHook Svr]").
-define(REGISTRAY, emqx_exhook_registray).
-define(PB_CLIENT_MOD, emqx_exhook_v_1_hook_provider_client).
%% Load/Unload
@ -83,13 +84,19 @@
load(Name0, Opts0) ->
Name = prefix(Name0),
{SvrAddr, ClientOpts} = channel_opts(Opts0),
case emqx_exhook_sup:start_grpc_client_channel(Name, SvrAddr, ClientOpts) of
case emqx_exhook_sup:start_grpc_client_channel(
Name,
SvrAddr,
ClientOpts) of
{ok, _ChannPoolPid} ->
case do_init(Name) of
{ok, HookSpecs} ->
%% Reigster metrics
Prefix = lists:flatten(io_lib:format("exhook.~s.", [Name])),
Prefix = lists:flatten(
io_lib:format("exhook.~s.", [Name])),
ensure_metrics(Prefix, HookSpecs),
%% Ensure hooks
ensure_hooks(HookSpecs),
{ok, #server{name = Name,
options = Opts0,
channel = _ChannPoolPid,
@ -126,8 +133,9 @@ channel_opts(Opts) ->
{SvrAddr, ClientOpts}.
-spec unload(server()) -> ok.
unload(#server{name = Name}) ->
unload(#server{name = Name, hookspec = HookSpecs}) ->
_ = do_deinit(Name),
_ = may_unload_hooks(HookSpecs),
_ = emqx_exhook_sup:stop_grpc_client_channel(Name),
ok.
@ -177,6 +185,31 @@ ensure_metrics(Prefix, HookSpecs) ->
|| Hookpoint <- maps:keys(HookSpecs)],
lists:foreach(fun emqx_metrics:ensure/1, Keys).
ensure_hooks(HookSpecs) ->
lists:foreach(fun(Hookpoint) ->
case ets:lookup(?REGISTRAY, Hookpoint) of
[] ->
?LOG(warning, "Hoook ~s not found in registray", [Hookpoint]);
[{Hookpoint, {M, F, A}, _}] ->
emqx_hooks:put(Hookpoint, {M, F, A}),
ets:update_counter(?REGISTRAY, Hookpoint, {3, 1})
end
end, maps:keys(HookSpecs)).
may_unload_hooks(HookSpecs) ->
lists:foreach(fun(Hookpoint) ->
case ets:update_counter(?REGISTRAY, Hookpoint, {3, -1}) of
Cnt when Cnt =< 0 ->
case ets:lookup(?REGISTRAY, Hookpoint) of
[{Hookpoint, {M, F, _A}, _}] ->
emqx_hooks:del(Hookpoint, {M, F});
_ -> ok
end,
ets:delete(?REGISTRAY, Hookpoint);
_ -> ok
end
end, maps:keys(HookSpecs)).
format(#server{name = Name, hookspec = Hooks}) ->
io_lib:format("name=~p, hooks=~0p", [Name, Hooks]).