emqx/apps/emqx_telemetry/src/emqx_telemetry_api.erl

273 lines
7.6 KiB
Erlang

%%--------------------------------------------------------------------
%% Copyright (c) 2020-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_telemetry_api).
-behaviour(minirest_api).
-include_lib("hocon/include/hoconsc.hrl").
-include_lib("typerefl/include/types.hrl").
-import(hoconsc, [mk/2, ref/1, ref/2, array/1]).
-export([
status/2,
data/2
]).
-export([
api_spec/0,
paths/0,
schema/1,
fields/1,
namespace/0
]).
-define(BAD_REQUEST, 'BAD_REQUEST').
-define(NOT_FOUND, 'NOT_FOUND').
namespace() -> undefined.
api_spec() ->
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
paths() ->
[
"/telemetry/status",
"/telemetry/data"
].
schema("/telemetry/status") ->
#{
'operationId' => status,
get =>
#{
description => ?DESC(get_telemetry_status_api),
tags => [<<"Telemetry">>],
responses =>
#{200 => status_schema(?DESC(get_telemetry_status_api))}
},
put =>
#{
description => ?DESC(update_telemetry_status_api),
tags => [<<"Telemetry">>],
'requestBody' => status_schema(?DESC(update_telemetry_status_api)),
responses =>
#{
200 => status_schema(?DESC(update_telemetry_status_api)),
400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad Request">>)
}
}
};
schema("/telemetry/data") ->
#{
'operationId' => data,
get =>
#{
description => ?DESC(get_telemetry_data_api),
tags => [<<"Telemetry">>],
responses =>
#{
200 => mk(ref(?MODULE, telemetry), #{desc => ?DESC(get_telemetry_data_api)}),
404 => emqx_dashboard_swagger:error_codes(
[?NOT_FOUND], <<"Telemetry is not enabled">>
)
}
}
}.
status_schema(Desc) ->
mk(ref(?MODULE, status), #{in => body, desc => Desc}).
fields(status) ->
[
{enable,
mk(
boolean(),
#{
desc => ?DESC(enable),
default => true,
example => false
}
)}
];
fields(telemetry) ->
[
{emqx_version,
mk(
string(),
#{
desc => ?DESC(emqx_version),
example => <<"5.0.0-beta.3-32d1547c">>
}
)},
{license,
mk(
map(),
#{
desc => ?DESC(license),
example => #{edition => <<"opensource">>}
}
)},
{os_name,
mk(
string(),
#{
desc => ?DESC(os_name),
example => <<"Linux">>
}
)},
{os_version,
mk(
string(),
#{
desc => ?DESC(os_version),
example => <<"20.04">>
}
)},
{otp_version,
mk(
string(),
#{
desc => ?DESC(otp_version),
example => <<"24">>
}
)},
{up_time,
mk(
integer(),
#{
desc => ?DESC(up_time),
example => 20220113
}
)},
{uuid,
mk(
string(),
#{
desc => ?DESC(uuid),
example => <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>
}
)},
{nodes_uuid,
mk(
array(binary()),
#{
desc => ?DESC(nodes_uuid),
example => [
<<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>,
<<"ZZZZZZZZ-CCCC-BBBB-2022-DDDDEEEEFFF">>
]
}
)},
{active_plugins,
mk(
array(binary()),
#{
desc => ?DESC(active_plugins),
example => [<<"Plugin A">>, <<"Plugin B">>]
}
)},
{active_modules,
mk(
array(binary()),
#{
desc => ?DESC(active_modules),
example => [<<"Module A">>, <<"Module B">>]
}
)},
{num_clients,
mk(
integer(),
#{
desc => ?DESC(num_clients),
example => 20220113
}
)},
{messages_received,
mk(
integer(),
#{
desc => ?DESC(messages_received),
example => 2022
}
)},
{messages_sent,
mk(
integer(),
#{
desc => ?DESC(messages_sent),
example => 2022
}
)}
].
%%--------------------------------------------------------------------
%% HTTP API
%%--------------------------------------------------------------------
status(get, _Params) ->
{200, get_telemetry_status()};
status(put, #{body := Body}) ->
Enable = maps:get(<<"enable">>, Body),
case Enable =:= is_enabled() of
true ->
Reason =
case Enable of
true -> <<"Telemetry status is already enabled">>;
false -> <<"Telemetry status is already disabled">>
end,
{400, #{code => ?BAD_REQUEST, message => Reason}};
false ->
case enable_telemetry(Enable) of
ok ->
{200, get_telemetry_status()};
{error, Reason} ->
{400, #{
code => ?BAD_REQUEST,
message => Reason
}}
end
end.
data(get, _Request) ->
case is_enabled() of
true ->
{200, emqx_utils_json:encode(get_telemetry_data())};
false ->
{404, #{
code => ?NOT_FOUND,
message => <<"Telemetry is not enabled">>
}}
end.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
enable_telemetry(Enable) ->
emqx_telemetry_config:set_telemetry_status(Enable).
get_telemetry_status() ->
#{enable => is_enabled()}.
get_telemetry_data() ->
{ok, TelemetryData} = emqx_telemetry:get_telemetry(),
TelemetryData.
is_enabled() ->
emqx_telemetry_config:is_enabled().