emqx_telemetry_api.erl 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2020-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_telemetry_api).
  17. -behaviour(minirest_api).
  18. -include_lib("typerefl/include/types.hrl").
  19. -import(hoconsc, [mk/2, ref/1, ref/2, array/1]).
  20. % -export([cli/1]).
  21. -export([ status/2
  22. , data/2
  23. ]).
  24. -export([enable_telemetry/2]).
  25. -export([ api_spec/0
  26. , paths/0
  27. , schema/1
  28. , fields/1
  29. ]).
  30. -define(BAD_REQUEST, 'BAD_REQUEST').
  31. api_spec() ->
  32. emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
  33. paths() ->
  34. [ "/telemetry/status"
  35. , "/telemetry/data"
  36. ].
  37. schema("/telemetry/status") ->
  38. #{ 'operationId' => status,
  39. get =>
  40. #{ description => <<"Get telemetry status">>
  41. , responses =>
  42. #{ 200 => status_schema(<<"Get telemetry status">>)}
  43. },
  44. put =>
  45. #{ description => <<"Enable or disable telemetry">>
  46. , 'requestBody' => status_schema(<<"Enable or disable telemetry">>)
  47. , responses =>
  48. #{ 200 => status_schema(<<"Enable or disable telemetry successfully">>)
  49. , 400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad Request">>)
  50. }
  51. }
  52. };
  53. schema("/telemetry/data") ->
  54. #{ 'operationId' => data,
  55. get =>
  56. #{ description => <<"Get telemetry data">>
  57. , responses =>
  58. #{ 200 => mk(ref(?MODULE, telemetry), #{ desc => <<"Get telemetry data">>})}}
  59. }.
  60. status_schema(Desc) ->
  61. mk(ref(?MODULE, status), #{desc => Desc}).
  62. fields(status) ->
  63. [ { enable
  64. , mk( boolean()
  65. , #{ desc => <<"Telemetry status">>
  66. , default => false
  67. , example => false
  68. })
  69. }
  70. ];
  71. fields(telemetry) ->
  72. [ { emqx_version
  73. , mk( string()
  74. , #{ desc => <<"EMQ X Version">>
  75. , example => <<"5.0.0-beta.3-32d1547c">>
  76. })
  77. }
  78. , { license
  79. , mk( map()
  80. , #{ desc => <<"EMQ X License">>
  81. , example => #{edition => <<"community">>}
  82. })
  83. }
  84. , { os_name
  85. , mk( string()
  86. , #{ desc => <<"OS Name">>
  87. , example => <<"Linux">>
  88. })
  89. }
  90. , { os_version
  91. , mk( string()
  92. , #{ desc => <<"OS Version">>
  93. , example => <<"20.04">>
  94. })
  95. }
  96. , { otp_version
  97. , mk( string()
  98. , #{ desc => <<"Erlang/OTP Version">>
  99. , example => <<"24">>
  100. })
  101. }
  102. , { up_time
  103. , mk( integer()
  104. , #{ desc => <<"EMQ X Runtime">>
  105. , example => 20220113
  106. })
  107. }
  108. , { uuid
  109. , mk( string()
  110. , #{ desc => <<"EMQ X UUID">>
  111. , example => <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>
  112. })
  113. }
  114. , { nodes_uuid
  115. , mk( array(binary())
  116. , #{ desc => <<"EMQ X Cluster Nodes UUID">>
  117. , example => [ <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>
  118. , <<"ZZZZZZZZ-CCCC-BBBB-2022-DDDDEEEEFFF">>]
  119. })
  120. }
  121. , { active_plugins
  122. , mk( array(binary())
  123. , #{ desc => <<"EMQ X Active Plugins">>
  124. , example => [<<"Plugin A">>, <<"Plugin B">>]
  125. })
  126. }
  127. , { active_modules
  128. , mk( array(binary())
  129. , #{ desc => <<"EMQ X Active Modules">>
  130. , example => [<<"Module A">>, <<"Module B">>]
  131. })
  132. }
  133. , { num_clients
  134. , mk( integer()
  135. , #{ desc => <<"EMQ X Current Connections">>
  136. , example => 20220113
  137. })
  138. }
  139. , { messages_received
  140. , mk( integer()
  141. , #{ desc => <<"EMQ X Current Received Message">>
  142. , example => 2022
  143. })
  144. }
  145. , { messages_sent
  146. , mk( integer()
  147. , #{ desc => <<"EMQ X Current Sent Message">>
  148. , example => 2022
  149. })
  150. }
  151. ].
  152. %%--------------------------------------------------------------------
  153. %% HTTP API
  154. %%--------------------------------------------------------------------
  155. status(get, _Params) ->
  156. {200, get_telemetry_status()};
  157. status(put, #{body := Body}) ->
  158. Enable = maps:get(<<"enable">>, Body),
  159. case Enable =:= emqx_telemetry:get_status() of
  160. true ->
  161. Reason = case Enable of
  162. true -> <<"Telemetry status is already enabled">>;
  163. false -> <<"Telemetry status is already disable">>
  164. end,
  165. {400, #{code => 'BAD_REQUEST', message => Reason}};
  166. false ->
  167. enable_telemetry(Enable),
  168. {200, #{<<"enable">> => emqx_telemetry:get_status()}}
  169. end.
  170. data(get, _Request) ->
  171. {200, emqx_json:encode(get_telemetry_data())}.
  172. %%--------------------------------------------------------------------
  173. %% CLI
  174. %%--------------------------------------------------------------------
  175. % cli(["enable", Enable0]) ->
  176. % Enable = list_to_atom(Enable0),
  177. % case Enable =:= emqx_telemetry:is_enabled() of
  178. % true ->
  179. % case Enable of
  180. % true -> emqx_ctl:print("Telemetry status is already enabled~n");
  181. % false -> emqx_ctl:print("Telemetry status is already disable~n")
  182. % end;
  183. % false ->
  184. % enable_telemetry(Enable),
  185. % case Enable of
  186. % true -> emqx_ctl:print("Enable telemetry successfully~n");
  187. % false -> emqx_ctl:print("Disable telemetry successfully~n")
  188. % end
  189. % end;
  190. % cli(["get", "status"]) ->
  191. % case get_telemetry_status() of
  192. % [{enabled, true}] ->
  193. % emqx_ctl:print("Telemetry is enabled~n");
  194. % [{enabled, false}] ->
  195. % emqx_ctl:print("Telemetry is disabled~n")
  196. % end;
  197. % cli(["get", "data"]) ->
  198. % TelemetryData = get_telemetry_data(),
  199. % case emqx_json:safe_encode(TelemetryData, [pretty]) of
  200. % {ok, Bin} ->
  201. % emqx_ctl:print("~ts~n", [Bin]);
  202. % {error, _Reason} ->
  203. % emqx_ctl:print("Failed to get telemetry data")
  204. % end;
  205. % cli(_) ->
  206. % emqx_ctl:usage([{"telemetry enable", "Enable telemetry"},
  207. % {"telemetry disable", "Disable telemetry"},
  208. % {"telemetry get data", "Get reported telemetry data"}]).
  209. %%--------------------------------------------------------------------
  210. %% internal function
  211. %%--------------------------------------------------------------------
  212. enable_telemetry(Enable) ->
  213. lists:foreach(fun(Node) ->
  214. enable_telemetry(Node, Enable)
  215. end, mria_mnesia:running_nodes()).
  216. enable_telemetry(Node, true) ->
  217. is_ok(emqx_telemetry_proto_v1:enable_telemetry(Node));
  218. enable_telemetry(Node, false) ->
  219. is_ok(emqx_telemetry_proto_v1:disable_telemetry(Node)).
  220. get_telemetry_status() ->
  221. #{enabled => emqx_telemetry:get_status()}.
  222. get_telemetry_data() ->
  223. {ok, TelemetryData} = emqx_telemetry:get_telemetry(),
  224. TelemetryData.
  225. is_ok(Result) ->
  226. case Result of
  227. {badrpc, Reason} -> {error, Reason};
  228. Result -> Result
  229. end.