diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index b5c0d87ec..7a7c9078e 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -51,6 +51,9 @@ -export([official_version/1]). +%% internal export +-export([read_raw_build_info/0]). + -ifdef(TEST). -compile(export_all). -compile(nowarn_export_all). @@ -295,7 +298,9 @@ get_telemetry(#state{uuid = UUID}) -> {active_plugins, active_plugins()}, {num_clients, num_clients()}, {messages_received, messages_received()}, - {messages_sent, messages_sent()}]. + {messages_sent, messages_sent()}, + {build_info, build_info()}, + {vm_specs, vm_specs()}]. report_telemetry(State = #state{url = URL}) -> Data = get_telemetry(State), @@ -324,6 +329,27 @@ parse_os_release(FileContent) -> end, [], string:tokens(binary:bin_to_list(FileContent), "\n")). +build_info() -> + case ?MODULE:read_raw_build_info() of + {ok, BuildInfo} -> + %% running on EMQX release + {ok, Fields} = hocon:binary(BuildInfo), + Fields; + _ -> + #{} + end. + +read_raw_build_info() -> + Filename = filename:join([code:root_dir(), "releases", + emqx_app:get_release(), "BUILD_INFO"]), + file:read_file(Filename). + +vm_specs() -> + SysMemData = memsup:get_system_memory_data(), + [ {num_cpus, erlang:system_info(logical_processors)} + , {total_memory, proplists:get_value(available_memory, SysMemData)} + ]. + bin(L) when is_list(L) -> list_to_binary(L); bin(A) when is_atom(A) -> diff --git a/apps/emqx_modules/test/emqx_telemetry_SUITE.erl b/apps/emqx_modules/test/emqx_telemetry_SUITE.erl index 43c262989..efb258853 100644 --- a/apps/emqx_modules/test/emqx_telemetry_SUITE.erl +++ b/apps/emqx_modules/test/emqx_telemetry_SUITE.erl @@ -28,14 +28,53 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - ok = mria:start(), - ok = emqx_telemetry:mnesia(boot), + snabbkaffe:fix_ct_logging(), emqx_common_test_helpers:start_apps([emqx_modules]), Config. end_per_suite(_Config) -> emqx_common_test_helpers:stop_apps([emqx_modules]). +init_per_testcase(t_get_telemetry, Config) -> + DataDir = ?config(data_dir, Config), + TestPID = self(), + ok = meck:new(httpc, [non_strict, passthrough, no_history, no_link]), + ok = meck:expect(httpc, request, fun(Method, URL, Headers, Body) -> + TestPID ! {request, Method, URL, Headers, Body} + end), + ok = meck:new(emqx_telemetry, [non_strict, passthrough, no_history, no_link]), + ok = meck:expect(emqx_telemetry, read_raw_build_info, + fun() -> + {ok, Path} = file:read_link(filename:join([DataDir, "BUILD_INFO"])), + {ok, Template} = file:read_file(Path), + Vars0 = [ {build_info_arch, "arch"} + , {build_info_wordsize, "64"} + , {build_info_os, "os"} + , {build_info_erlang, "erlang"} + , {build_info_elixir, "elixir"} + , {build_info_relform, "relform"} + ], + Vars = [{atom_to_list(K), iolist_to_binary(V)} + || {K, V} <- Vars0], + Rendered = bbmustache:render(Template, Vars), + {ok, Rendered} + end), + Config; +init_per_testcase(_Testcase, Config) -> + TestPID = self(), + ok = meck:new(httpc, [non_strict, passthrough, no_history, no_link]), + ok = meck:expect(httpc, request, fun(Method, URL, Headers, Body) -> + TestPID ! {request, Method, URL, Headers, Body} + end), + Config. + +end_per_testcase(t_get_telemetry, _Config) -> + meck:unload([httpc, emqx_telemetry]), + ok; +end_per_testcase(_Testcase, _Config) -> + meck:unload([httpc]), + ok. + t_uuid(_) -> UUID = emqx_telemetry:generate_uuid(), Parts = binary:split(UUID, <<"-">>, [global, trim]), @@ -65,13 +104,29 @@ t_official_version(_) -> true = emqx_telemetry:official_version("1.1-rc.1"), false = emqx_telemetry:official_version("1.1-alpha.a"). -t_get_telemetry(_) -> +t_get_telemetry(_Config) -> {ok, TelemetryData} = emqx_telemetry:get_telemetry(), OTPVersion = bin(erlang:system_info(otp_release)), ?assertEqual(OTPVersion, get_value(otp_version, TelemetryData)), {ok, UUID} = emqx_telemetry:get_uuid(), ?assertEqual(UUID, get_value(uuid, TelemetryData)), - ?assertEqual(0, get_value(num_clients, TelemetryData)). + ?assertEqual(0, get_value(num_clients, TelemetryData)), + BuildInfo = get_value(build_info, TelemetryData), + ?assertMatch( + #{ <<"arch">> := <<_/binary>> + , <<"elixir">> := <<_/binary>> + , <<"erlang">> := <<_/binary>> + , <<"os">> := <<_/binary>> + , <<"relform">> := <<_/binary>> + , <<"wordsize">> := Wordsize + } when is_integer(Wordsize), + BuildInfo), + VMSpecs = get_value(vm_specs, TelemetryData), + ?assert(is_integer(get_value(num_cpus, VMSpecs))), + ?assert(0 =< get_value(num_cpus, VMSpecs)), + ?assert(is_integer(get_value(total_memory, VMSpecs))), + ?assert(0 =< get_value(total_memory, VMSpecs)), + ok. t_enable(_) -> ok = meck:new(emqx_telemetry, [non_strict, passthrough, no_history, no_link]), diff --git a/apps/emqx_modules/test/emqx_telemetry_SUITE_data/BUILD_INFO b/apps/emqx_modules/test/emqx_telemetry_SUITE_data/BUILD_INFO new file mode 120000 index 000000000..adb156dee --- /dev/null +++ b/apps/emqx_modules/test/emqx_telemetry_SUITE_data/BUILD_INFO @@ -0,0 +1 @@ +../../../../rel/BUILD_INFO \ No newline at end of file