Explorar el Código

feat: add build info and vm specs to telemetry

Thales Macedo Garitezi hace 3 años
padre
commit
e8682a1107

+ 27 - 1
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) ->

+ 59 - 4
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]),

+ 1 - 0
apps/emqx_modules/test/emqx_telemetry_SUITE_data/BUILD_INFO

@@ -0,0 +1 @@
+../../../../rel/BUILD_INFO