emqx_trace_handler_SUITE.erl 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2019-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_trace_handler_SUITE).
  17. -compile(export_all).
  18. -compile(nowarn_export_all).
  19. -include_lib("eunit/include/eunit.hrl").
  20. -include_lib("common_test/include/ct.hrl").
  21. -define(CLIENT, [{host, "localhost"},
  22. {clientid, <<"client">>},
  23. {username, <<"testuser">>},
  24. {password, <<"pass">>}
  25. ]).
  26. all() -> [t_trace_clientid, t_trace_topic, t_trace_ip_address, t_trace_clientid_utf8].
  27. init_per_suite(Config) ->
  28. emqx_common_test_helpers:boot_modules(all),
  29. emqx_common_test_helpers:start_apps([]),
  30. Config.
  31. end_per_suite(_Config) ->
  32. emqx_common_test_helpers:stop_apps([]).
  33. init_per_testcase(t_trace_clientid, Config) ->
  34. init(),
  35. Config;
  36. init_per_testcase(_Case, Config) ->
  37. _ = [logger:remove_handler(Id) ||#{id := Id} <- emqx_trace_handler:running()],
  38. init(),
  39. Config.
  40. end_per_testcase(_Case, _Config) ->
  41. terminate(),
  42. ok.
  43. t_trace_clientid(_Config) ->
  44. %% Start tracing
  45. %% add list clientid
  46. ok = emqx_trace_handler:install("CLI-client1", clientid, "client", debug, "tmp/client.log"),
  47. ok = emqx_trace_handler:install("CLI-client2", clientid, <<"client2">>, all, "tmp/client2.log"),
  48. ok = emqx_trace_handler:install("CLI-client3", clientid, <<"client3">>, all, "tmp/client3.log"),
  49. {error, {handler_not_added, {file_error, ".", eisdir}}} =
  50. emqx_trace_handler:install(clientid, <<"client5">>, debug, "."),
  51. emqx_trace:check(),
  52. ok = filesync(<<"CLI-client1">>, clientid),
  53. ok = filesync(<<"CLI-client2">>, clientid),
  54. ok = filesync(<<"CLI-client3">>, clientid),
  55. %% Verify the tracing file exits
  56. ?assert(filelib:is_regular("tmp/client.log")),
  57. ?assert(filelib:is_regular("tmp/client2.log")),
  58. ?assert(filelib:is_regular("tmp/client3.log")),
  59. %% Get current traces
  60. ?assertMatch([#{type := clientid, filter := <<"client">>, name := <<"CLI-client1">>,
  61. level := debug, dst := "tmp/client.log"},
  62. #{type := clientid, filter := <<"client2">>, name := <<"CLI-client2">>
  63. , level := debug, dst := "tmp/client2.log"},
  64. #{type := clientid, filter := <<"client3">>, name := <<"CLI-client3">>,
  65. level := debug, dst := "tmp/client3.log"}
  66. ], emqx_trace_handler:running()),
  67. %% Client with clientid = "client" publishes a "hi" message to "a/b/c".
  68. {ok, T} = emqtt:start_link(?CLIENT),
  69. emqtt:connect(T),
  70. emqtt:publish(T, <<"a/b/c">>, <<"hi">>),
  71. emqtt:ping(T),
  72. ok = filesync(<<"CLI-client1">>, clientid),
  73. ok = filesync(<<"CLI-client2">>, clientid),
  74. ok = filesync(<<"CLI-client3">>, clientid),
  75. %% Verify messages are logged to "tmp/client.log" but not "tmp/client2.log".
  76. {ok, Bin} = file:read_file("tmp/client.log"),
  77. ?assertNotEqual(nomatch, binary:match(Bin, [<<"CONNECT">>])),
  78. ?assertNotEqual(nomatch, binary:match(Bin, [<<"CONNACK">>])),
  79. ?assertNotEqual(nomatch, binary:match(Bin, [<<"PUBLISH">>])),
  80. ?assertNotEqual(nomatch, binary:match(Bin, [<<"PINGREQ">>])),
  81. ?assert(filelib:file_size("tmp/client2.log") == 0),
  82. %% Stop tracing
  83. ok = emqx_trace_handler:uninstall(clientid, <<"CLI-client1">>),
  84. ok = emqx_trace_handler:uninstall(clientid, <<"CLI-client2">>),
  85. ok = emqx_trace_handler:uninstall(clientid, <<"CLI-client3">>),
  86. emqtt:disconnect(T),
  87. ?assertEqual([], emqx_trace_handler:running()).
  88. t_trace_clientid_utf8(_) ->
  89. Utf8Id = <<"client 漢字編碼"/utf8>>,
  90. ok = emqx_trace_handler:install("CLI-UTF8", clientid, Utf8Id, debug, "tmp/client-utf8.log"),
  91. emqx_trace:check(),
  92. {ok, T} = emqtt:start_link([{clientid, Utf8Id}]),
  93. emqtt:connect(T),
  94. [begin emqtt:publish(T, <<"a/b/c">>, <<"hi">>) end|| _ <- lists:seq(1, 10)],
  95. emqtt:ping(T),
  96. ok = filesync("CLI-UTF8", clientid),
  97. ok = emqx_trace_handler:uninstall(clientid, "CLI-UTF8"),
  98. emqtt:disconnect(T),
  99. ?assertEqual([], emqx_trace_handler:running()),
  100. ok.
  101. t_trace_topic(_Config) ->
  102. {ok, T} = emqtt:start_link(?CLIENT),
  103. emqtt:connect(T),
  104. %% Start tracing
  105. ok = emqx_trace_handler:install("CLI-TOPIC-1", topic, <<"x/#">>, all, "tmp/topic_trace_x.log"),
  106. ok = emqx_trace_handler:install("CLI-TOPIC-2", topic, <<"y/#">>, all, "tmp/topic_trace_y.log"),
  107. emqx_trace:check(),
  108. ok = filesync("CLI-TOPIC-1", topic),
  109. ok = filesync("CLI-TOPIC-2", topic),
  110. %% Verify the tracing file exits
  111. ?assert(filelib:is_regular("tmp/topic_trace_x.log")),
  112. ?assert(filelib:is_regular("tmp/topic_trace_y.log")),
  113. %% Get current traces
  114. ?assertMatch([#{type := topic, filter := <<"x/#">>,
  115. level := debug, dst := "tmp/topic_trace_x.log", name := <<"CLI-TOPIC-1">>},
  116. #{type := topic, filter := <<"y/#">>,
  117. name := <<"CLI-TOPIC-2">>, level := debug, dst := "tmp/topic_trace_y.log"}
  118. ],
  119. emqx_trace_handler:running()),
  120. %% Client with clientid = "client" publishes a "hi" message to "x/y/z".
  121. emqtt:publish(T, <<"x/y/z">>, <<"hi1">>),
  122. emqtt:publish(T, <<"x/y/z">>, <<"hi2">>),
  123. emqtt:subscribe(T, <<"x/y/z">>),
  124. emqtt:unsubscribe(T, <<"x/y/z">>),
  125. ok = filesync("CLI-TOPIC-1", topic),
  126. ok = filesync("CLI-TOPIC-2", topic),
  127. {ok, Bin} = file:read_file("tmp/topic_trace_x.log"),
  128. ?assertNotEqual(nomatch, binary:match(Bin, [<<"hi1">>])),
  129. ?assertNotEqual(nomatch, binary:match(Bin, [<<"hi2">>])),
  130. ?assertNotEqual(nomatch, binary:match(Bin, [<<"PUBLISH">>])),
  131. ?assertNotEqual(nomatch, binary:match(Bin, [<<"SUBSCRIBE">>])),
  132. ?assertNotEqual(nomatch, binary:match(Bin, [<<"UNSUBSCRIBE">>])),
  133. ?assert(filelib:file_size("tmp/topic_trace_y.log") =:= 0),
  134. %% Stop tracing
  135. ok = emqx_trace_handler:uninstall(topic, <<"CLI-TOPIC-1">>),
  136. ok = emqx_trace_handler:uninstall(topic, <<"CLI-TOPIC-2">>),
  137. {error, _Reason} = emqx_trace_handler:uninstall(topic, <<"z/#">>),
  138. ?assertEqual([], emqx_trace_handler:running()),
  139. emqtt:disconnect(T).
  140. t_trace_ip_address(_Config) ->
  141. {ok, T} = emqtt:start_link(?CLIENT),
  142. emqtt:connect(T),
  143. %% Start tracing
  144. ok = emqx_trace_handler:install("CLI-IP-1", ip_address, "127.0.0.1", all, "tmp/ip_trace_x.log"),
  145. ok = emqx_trace_handler:install("CLI-IP-2", ip_address,
  146. "192.168.1.1", all, "tmp/ip_trace_y.log"),
  147. emqx_trace:check(),
  148. ok = filesync(<<"CLI-IP-1">>, ip_address),
  149. ok = filesync(<<"CLI-IP-2">>, ip_address),
  150. %% Verify the tracing file exits
  151. ?assert(filelib:is_regular("tmp/ip_trace_x.log")),
  152. ?assert(filelib:is_regular("tmp/ip_trace_y.log")),
  153. %% Get current traces
  154. ?assertMatch([#{type := ip_address, filter := "127.0.0.1",
  155. name := <<"CLI-IP-1">>,
  156. level := debug, dst := "tmp/ip_trace_x.log"},
  157. #{type := ip_address, filter := "192.168.1.1",
  158. name := <<"CLI-IP-2">>,
  159. level := debug, dst := "tmp/ip_trace_y.log"}
  160. ],
  161. emqx_trace_handler:running()),
  162. %% Client with clientid = "client" publishes a "hi" message to "x/y/z".
  163. emqtt:publish(T, <<"x/y/z">>, <<"hi1">>),
  164. emqtt:publish(T, <<"x/y/z">>, <<"hi2">>),
  165. emqtt:subscribe(T, <<"x/y/z">>),
  166. emqtt:unsubscribe(T, <<"x/y/z">>),
  167. ok = filesync(<<"CLI-IP-1">>, ip_address),
  168. ok = filesync(<<"CLI-IP-2">>, ip_address),
  169. {ok, Bin} = file:read_file("tmp/ip_trace_x.log"),
  170. ?assertNotEqual(nomatch, binary:match(Bin, [<<"hi1">>])),
  171. ?assertNotEqual(nomatch, binary:match(Bin, [<<"hi2">>])),
  172. ?assertNotEqual(nomatch, binary:match(Bin, [<<"PUBLISH">>])),
  173. ?assertNotEqual(nomatch, binary:match(Bin, [<<"SUBSCRIBE">>])),
  174. ?assertNotEqual(nomatch, binary:match(Bin, [<<"UNSUBSCRIBE">>])),
  175. ?assert(filelib:file_size("tmp/ip_trace_y.log") =:= 0),
  176. %% Stop tracing
  177. ok = emqx_trace_handler:uninstall(ip_address, <<"CLI-IP-1">>),
  178. ok = emqx_trace_handler:uninstall(ip_address, <<"CLI-IP-2">>),
  179. {error, _Reason} = emqx_trace_handler:uninstall(ip_address, <<"127.0.0.2">>),
  180. emqtt:disconnect(T),
  181. ?assertEqual([], emqx_trace_handler:running()).
  182. filesync(Name, Type) ->
  183. ct:sleep(50),
  184. filesync(Name, Type, 3).
  185. %% sometime the handler process is not started yet.
  186. filesync(_Name, _Type, 0) -> ok;
  187. filesync(Name0, Type, Retry) ->
  188. Name =
  189. case is_binary(Name0) of
  190. true -> Name0;
  191. false -> list_to_binary(Name0)
  192. end,
  193. try
  194. Handler = binary_to_atom(<<"trace_",
  195. (atom_to_binary(Type))/binary, "_", Name/binary>>),
  196. ok = logger_disk_log_h:filesync(Handler)
  197. catch E:R ->
  198. ct:pal("Filesync error:~p ~p~n", [{Name, Type, Retry}, {E, R}]),
  199. ct:sleep(100),
  200. filesync(Name, Type, Retry - 1)
  201. end.
  202. init() ->
  203. emqx_trace:start_link().
  204. terminate() ->
  205. catch ok = gen_server:stop(emqx_trace, normal, 5000).