From e57e19c9f1575bbb14ad08f8ddc2a905a717b882 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Wed, 31 Jan 2024 15:52:46 +0800 Subject: [PATCH 1/7] build: i18n file download time with millisecond precision --- scripts/pre-compile.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/pre-compile.sh b/scripts/pre-compile.sh index 12506162c..cd340338f 100755 --- a/scripts/pre-compile.sh +++ b/scripts/pre-compile.sh @@ -29,17 +29,20 @@ I18N_REPO_BRANCH="v$(./pkg-vsn.sh "${PROFILE_STR}" | tr -d '.' | cut -c 1-2)" DOWNLOAD_I18N_TRANSLATIONS=${DOWNLOAD_I18N_TRANSLATIONS:-true} # download desc (i18n) translations +beginfmt='\033[1m' +endfmt='\033[0m' if [ "$DOWNLOAD_I18N_TRANSLATIONS" = "true" ]; then - echo "downloading i18n translation from emqx/emqx-i18n" - start=$(date +%s) + echo "Downloading i18n translation from emqx/emqx-i18n..." + start=$(date +%s%N) curl -L --fail --silent --show-error \ --output "apps/emqx_dashboard/priv/desc.zh.hocon" \ "https://raw.githubusercontent.com/emqx/emqx-i18n/${I18N_REPO_BRANCH}/desc.zh.hocon" - end=$(date +%s) - duration=$(echo "$end $start" | awk '{print $1 - $2}') - echo "downloaded i18n translation in $duration seconds, set DOWNLOAD_I18N_TRANSLATIONS=false to skip" + end=$(date +%s%N) + duration=$(echo "$end $start" | awk '{printf "%.f\n", (($1 - $2)/ 1000000)}') + if [ "$duration" -gt 1000 ]; then beginfmt='\033[1;33m'; fi + echo -e "Downloaded i18n translation in $duration milliseconds.\nSet ${beginfmt}DOWNLOAD_I18N_TRANSLATIONS=false${endfmt} to skip" else - echo "skipping to download i18n translation from emqx/emqx-i18n, set DOWNLOAD_I18N_TRANSLATIONS=true to update" + echo -e "Skipping to download i18n translation from emqx/emqx-i18n.\nSet ${beginfmt}DOWNLOAD_I18N_TRANSLATIONS=true${endfmt} to update" fi # TODO From 9e16f33c315a33d540e53bebc277a548ffaa3847 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Tue, 30 Jan 2024 18:15:29 +0800 Subject: [PATCH 2/7] test: `/prometheus/stats` endpoint format in json --- .../test/emqx_prometheus_SUITE.erl | 32 ++++++++++--------- .../test/emqx_prometheus_api_SUITE.erl | 15 +++++---- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl index 2d85f2a05..0e5e9c31e 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl @@ -22,21 +22,23 @@ -compile(nowarn_export_all). -compile(export_all). --define(LEGACY_CONF_DEFAULT, << - "prometheus {\n" - " push_gateway_server = \"http://127.0.0.1:9091\"\n" - " interval = \"1s\"\n" - " headers = { Authorization = \"some-authz-tokens\"}\n" - " job_name = \"${name}~${host}\"\n" - " enable = true\n" - " vm_dist_collector = disabled\n" - " mnesia_collector = disabled\n" - " vm_statistics_collector = disabled\n" - " vm_system_info_collector = disabled\n" - " vm_memory_collector = disabled\n" - " vm_msacc_collector = disabled\n" - "}\n" ->>). +-define(CLUSTER_RPC_SHARD, emqx_cluster_rpc_shard). +%% erlfmt-ignore +-define(LEGACY_CONF_DEFAULT, <<" +prometheus { + push_gateway_server = \"http://127.0.0.1:9091\" + interval = \"1s\" + headers = { Authorization = \"some-authz-tokens\"} + job_name = \"${name}~${host}\" + enable = true + vm_dist_collector = disabled + mnesia_collector = disabled + vm_statistics_collector = disabled + vm_system_info_collector = disabled + vm_memory_collector = disabled + vm_msacc_collector = disabled +} +">>). -define(CONF_DEFAULT, #{ <<"prometheus">> => diff --git a/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl index 79fd0ef91..134aa82a6 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_api_SUITE.erl @@ -279,20 +279,23 @@ t_stats_no_auth_api(_) -> ok end, emqx_dashboard_listener:regenerate_minirest_dispatch(), - Json = [{"accept", "application/json"}], - request_stats(Json, []). + Headers = accept_josn_header(), + request_stats(Headers, []). t_stats_auth_api(_) -> {ok, _} = emqx:update_config([prometheus, enable_basic_auth], true), emqx_dashboard_listener:regenerate_minirest_dispatch(), Auth = emqx_mgmt_api_test_util:auth_header_(), - JsonAuth = [{"accept", "application/json"}, Auth], - request_stats(JsonAuth, Auth), + Headers = [Auth | accept_josn_header()], + request_stats(Headers, Auth), ok. -request_stats(JsonAuth, Auth) -> +accept_josn_header() -> + [{"accept", "application/json"}]. + +request_stats(Headers, Auth) -> Path = emqx_mgmt_api_test_util:api_path(["prometheus", "stats"]), - {ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path, "", JsonAuth), + {ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path, "", Headers), Data = emqx_utils_json:decode(Response, [return_maps]), ?assertMatch(#{<<"client">> := _, <<"delivery">> := _}, Data), {ok, _} = emqx_mgmt_api_test_util:request_api(get, Path, "", Auth), From d45d925529f25f45457e63125c420630dd11ee49 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Fri, 26 Jan 2024 17:12:54 +0800 Subject: [PATCH 3/7] test(prom_api): `/prometheus/stats` in prom/json format --- .../src/emqx_prometheus_api.erl | 5 + .../test/emqx_prometheus_data_SUITE.erl | 522 ++++++++++++++++++ 2 files changed, 527 insertions(+) create mode 100644 apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl diff --git a/apps/emqx_prometheus/src/emqx_prometheus_api.erl b/apps/emqx_prometheus/src/emqx_prometheus_api.erl index 432142775..f92d0ff58 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus_api.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus_api.erl @@ -22,6 +22,11 @@ -include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/logger.hrl"). +-ifdef(TEST). +-compile(export_all). +-compile(nowarn_export_all). +-endif. + -import( hoconsc, [ diff --git a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl new file mode 100644 index 000000000..22a888f28 --- /dev/null +++ b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl @@ -0,0 +1,522 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2023 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_prometheus_data_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include("emqx_prometheus.hrl"). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + +-define(LOGT(Format, Args), ct:pal("TEST_SUITE: " ++ Format, Args)). + +all() -> + [ + {group, stats}, + {group, auth}, + {group, data_integration} + ]. + +groups() -> + TCs = emqx_common_test_helpers:all(?MODULE), + AcceptGroups = [ + {group, 'text/plain'}, + {group, 'application/json'} + ], + ModeGroups = [ + {group, ?PROM_DATA_MODE__NODE}, + {group, ?PROM_DATA_MODE__ALL_NODES_AGGREGATED}, + {group, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED} + ], + [ + {stats, ModeGroups}, + {auth, ModeGroups}, + {data_integration, ModeGroups}, + {?PROM_DATA_MODE__NODE, AcceptGroups}, + {?PROM_DATA_MODE__ALL_NODES_AGGREGATED, AcceptGroups}, + {?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED, AcceptGroups}, + {'text/plain', TCs}, + {'application/json', TCs} + ]. + +init_per_suite(Config) -> + meck:new(emqx_retainer, [non_strict, passthrough, no_history, no_link]), + meck:expect(emqx_retainer, retained_count, fun() -> 0 end), + emqx_prometheus_SUITE:init_group(), + ok = emqx_common_test_helpers:start_apps( + [emqx, emqx_conf, emqx_auth, emqx_rule_engine, emqx_prometheus], + fun set_special_configs/1 + ), + Config. +end_per_suite(Config) -> + meck:unload([emqx_retainer]), + emqx_prometheus_SUITE:end_group(), + emqx_common_test_helpers:stop_apps( + [emqx, emqx_conf, emqx_auth, emqx_rule_engine, emqx_prometheus] + ), + + Config. + +init_per_group(stats, Config) -> + [{module, emqx_prometheus} | Config]; +init_per_group(auth, Config) -> + [{module, emqx_prometheus_auth} | Config]; +init_per_group(data_integration, Config) -> + [{module, emqx_prometheus_data_integration} | Config]; +init_per_group(?PROM_DATA_MODE__NODE, Config) -> + [{mode, ?PROM_DATA_MODE__NODE} | Config]; +init_per_group(?PROM_DATA_MODE__ALL_NODES_AGGREGATED, Config) -> + [{mode, ?PROM_DATA_MODE__ALL_NODES_AGGREGATED} | Config]; +init_per_group(?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED, Config) -> + [{mode, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED} | Config]; +init_per_group('text/plain', Config) -> + [{accept, 'text/plain'} | Config]; +init_per_group('application/json', Config) -> + [{accept, 'application/json'} | Config]; +init_per_group(_Group, Config) -> + Config. + +end_per_group(_Group, _Config) -> + ok. + +set_special_configs(emqx_dashboard) -> + emqx_dashboard_api_test_helpers:set_default_config(); +set_special_configs(emqx_auth) -> + {ok, _} = emqx:update_config([authorization, cache, enable], true), + {ok, _} = emqx:update_config([authorization, no_match], deny), + {ok, _} = emqx:update_config([authorization, sources], []), + ok; +set_special_configs(emqx_prometheus) -> + emqx_prometheus_SUITE:load_config(), + ok; +set_special_configs(_App) -> + ok. + +%%-------------------------------------------------------------------- +%% Cases +%%-------------------------------------------------------------------- + +t_collect_prom_data(Config) -> + CollectOpts = collect_opts(Config), + Module = ?config(module, Config), + Response = emqx_prometheus_api:collect(Module, CollectOpts), + assert_data(Module, Response, CollectOpts). + +%%-------------------------------------------------------------------- +%% Helper fns +%%-------------------------------------------------------------------- + +assert_data(_Module, {Code, Header, RawDataBinary}, #{type := <<"prometheus">>, mode := Mode}) -> + ?assertEqual(Code, 200), + ?assertMatch(#{<<"content-type">> := <<"text/plain">>}, Header), + DataL = lists:filter( + fun(B) -> + case re:run(B, <<"^[^#]">>, [global]) of + {match, _} -> + true; + nomatch -> + false + end + end, + binary:split(RawDataBinary, [<<"\n">>], [global]) + ), + assert_prom_data(DataL, Mode); +assert_data(Module, {Code, JsonData}, #{type := <<"json">>, mode := Mode}) -> + ?assertEqual(Code, 200), + ?assert(is_map(JsonData), true), + assert_json_data(Module, JsonData, Mode). + +%%%%%%%%%%%%%%%%%%%% +%% assert text/plain format +assert_prom_data(DataL, Mode) -> + NDataL = lists:map( + fun(Line) -> + binary:split(Line, [<<"{">>, <<",">>, <<"} ">>, <<" ">>], [global]) + end, + DataL + ), + do_assert_prom_data_stats(NDataL, Mode). + +-define(MGU(K, MAP), maps:get(K, MAP, undefined)). + +assert_json_data(emqx_prometheus, Data, Mode) -> + lists:foreach( + fun(FunSeed) -> + erlang:apply(?MODULE, fun_name(FunSeed), [?MGU(FunSeed, Data), Mode]), + ok + end, + maps:keys(Data) + ), + ok; +%% TOOD auth/data_integration +assert_json_data(_, _, _) -> + ok. + +fun_name(Seed) -> + binary_to_atom(<<"assert_json_data_", (atom_to_binary(Seed))/binary>>). + +%%-------------------------------------------------------------------- +%% Internal Functions +%%-------------------------------------------------------------------- + +collect_opts(Config) -> + #{ + type => accept(?config(accept, Config)), + mode => ?config(mode, Config) + }. + +accept('text/plain') -> + <<"prometheus">>; +accept('application/json') -> + <<"json">>. + +do_assert_prom_data_stats([], _Mode) -> + ok; +do_assert_prom_data_stats([Metric | RestDataL], Mode) -> + [_MetricNamme | _] = Metric, + assert_stats_metric_labels(Metric, Mode), + do_assert_prom_data_stats(RestDataL, Mode). + +assert_stats_metric_labels([MetricName | R] = _Metric, Mode) -> + case maps:get(Mode, metric_meta(MetricName), undefined) of + %% for uncatched metrics (by prometheus.erl) + undefined -> + ok; + N when is_integer(N) -> + ?assertEqual(N, length(lists:droplast(R))) + end. + +-define(meta(NODE, AGGRE, UNAGGRE), #{ + ?PROM_DATA_MODE__NODE => NODE, + ?PROM_DATA_MODE__ALL_NODES_AGGREGATED => AGGRE, + ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED => UNAGGRE +}). + +%% TODO: auth/data_integration +%% BEGIN always no label +metric_meta(<<"emqx_topics_max">>) -> ?meta(0, 0, 0); +metric_meta(<<"emqx_topics_count">>) -> ?meta(0, 0, 0); +metric_meta(<<"emqx_retained_count">>) -> ?meta(0, 0, 0); +metric_meta(<<"emqx_retained_max">>) -> ?meta(0, 0, 0); +%% END +%% BEGIN no label in mode `node` +metric_meta(<<"emqx_vm_cpu_use">>) -> ?meta(0, 1, 1); +metric_meta(<<"emqx_vm_cpu_idle">>) -> ?meta(0, 1, 1); +metric_meta(<<"emqx_vm_run_queue">>) -> ?meta(0, 1, 1); +metric_meta(<<"emqx_vm_process_messages_in_queues">>) -> ?meta(0, 1, 1); +metric_meta(<<"emqx_vm_total_memory">>) -> ?meta(0, 1, 1); +metric_meta(<<"emqx_vm_used_memory">>) -> ?meta(0, 1, 1); +%% END +metric_meta(<<"emqx_cert_expiry_at">>) -> ?meta(2, 2, 2); +metric_meta(<<"emqx_license_expiry_at">>) -> ?meta(0, 0, 0); +%% mria metric with label `shard` and `node` when not in mode `node` +metric_meta(<<"emqx_mria_", _Tail/binary>>) -> ?meta(1, 2, 2); +metric_meta(_) -> #{}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Assert Json Data Structure + +assert_json_data_messages(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_messages_received := _, + emqx_messages_sent := _, + emqx_messages_qos0_received := _, + emqx_messages_qos0_sent := _, + emqx_messages_qos1_received := _, + emqx_messages_qos1_sent := _, + emqx_messages_qos2_received := _, + emqx_messages_qos2_sent := _, + emqx_messages_publish := _, + emqx_messages_dropped := _, + emqx_messages_dropped_expired := _, + emqx_messages_dropped_no_subscribers := _, + emqx_messages_forward := _, + emqx_messages_retained := _, + emqx_messages_delayed := _, + emqx_messages_delivered := _, + emqx_messages_acked := _ + }, + M + ), + ok; +assert_json_data_messages(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_stats(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_connections_count := _, + emqx_connections_max := _, + emqx_live_connections_count := _, + emqx_live_connections_max := _, + emqx_sessions_count := _, + emqx_sessions_max := _, + emqx_channels_count := _, + emqx_channels_max := _, + emqx_topics_count := _, + emqx_topics_max := _, + emqx_suboptions_count := _, + emqx_suboptions_max := _, + emqx_subscribers_count := _, + emqx_subscribers_max := _, + emqx_subscriptions_count := _, + emqx_subscriptions_max := _, + emqx_subscriptions_shared_count := _, + emqx_subscriptions_shared_max := _, + emqx_retained_count := _, + emqx_retained_max := _, + emqx_delayed_count := _, + emqx_delayed_max := _ + }, + M + ); +assert_json_data_stats(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_olp(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch(#{}, M); +assert_json_data_olp(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> + ok. + +assert_json_data_client(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_client_connect := _, + emqx_client_connack := _, + emqx_client_connected := _, + emqx_client_authenticate := _, + emqx_client_auth_anonymous := _, + emqx_client_authorize := _, + emqx_client_subscribe := _, + emqx_client_unsubscribe := _, + emqx_client_disconnected := _ + }, + M + ); +assert_json_data_client(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_session(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_session_created := _, + emqx_session_resumed := _, + emqx_session_takenover := _, + emqx_session_discarded := _, + emqx_session_terminated := _ + }, + M + ); +assert_json_data_session(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_metrics(M, ?PROM_DATA_MODE__NODE) -> + ?assertMatch( + #{ + emqx_vm_cpu_use := _, + emqx_vm_cpu_idle := _, + emqx_vm_run_queue := _, + emqx_vm_process_messages_in_queues := _, + emqx_vm_total_memory := _, + emqx_vm_used_memory := _ + }, + M + ); +assert_json_data_metrics(Ms, Mode) when + is_list(Ms) andalso + (Mode =:= ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_delivery(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_delivery_dropped := _, + emqx_delivery_dropped_no_local := _, + emqx_delivery_dropped_too_large := _, + emqx_delivery_dropped_qos0_msg := _, + emqx_delivery_dropped_queue_full := _, + emqx_delivery_dropped_expired := _ + }, + M + ); +assert_json_data_delivery(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_cluster(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{emqx_cluster_nodes_running := _, emqx_cluster_nodes_stopped := _}, + M + ); +assert_json_data_cluster(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_acl(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_authorization_allow := _, + emqx_authorization_deny := _, + emqx_authorization_cache_hit := _, + emqx_authorization_cache_miss := _, + emqx_authorization_superuser := _, + emqx_authorization_nomatch := _, + emqx_authorization_matched_allow := _, + emqx_authorization_matched_deny := _ + }, + M + ); +assert_json_data_acl(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_authn(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_authentication_success := _, + emqx_authentication_success_anonymous := _, + emqx_authentication_failure := _ + }, + M + ); +assert_json_data_authn(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +assert_json_data_packets(M, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + ?assertMatch( + #{ + emqx_packets_publish_auth_error := _, + emqx_packets_puback_received := _, + emqx_packets_pubcomp_inuse := _, + emqx_packets_pubcomp_sent := _, + emqx_packets_suback_sent := _, + emqx_packets_pubrel_missed := _, + emqx_packets_publish_inuse := _, + emqx_packets_pingresp_sent := _, + emqx_packets_subscribe_received := _, + emqx_bytes_received := _, + emqx_packets_publish_dropped := _, + emqx_packets_publish_received := _, + emqx_packets_connack_sent := _, + emqx_packets_connack_auth_error := _, + emqx_packets_pubrec_inuse := _, + emqx_packets_sent := _, + emqx_packets_puback_sent := _, + emqx_packets_received := _, + emqx_packets_pubrec_missed := _, + emqx_packets_unsubscribe_received := _, + emqx_packets_puback_inuse := _, + emqx_packets_publish_sent := _, + emqx_packets_pubrec_sent := _, + emqx_packets_pubcomp_received := _, + emqx_packets_disconnect_sent := _, + emqx_packets_unsuback_sent := _, + emqx_bytes_sent := _, + emqx_packets_unsubscribe_error := _, + emqx_packets_auth_received := _, + emqx_packets_subscribe_auth_error := _, + emqx_packets_puback_missed := _, + emqx_packets_publish_error := _, + emqx_packets_subscribe_error := _, + emqx_packets_disconnect_received := _, + emqx_packets_pingreq_received := _, + emqx_packets_pubrel_received := _, + emqx_packets_pubcomp_missed := _, + emqx_packets_pubrec_received := _, + emqx_packets_connack_error := _, + emqx_packets_auth_sent := _, + emqx_packets_pubrel_sent := _, + emqx_packets_connect := _ + }, + M + ); +assert_json_data_packets(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + eval_foreach_assert(?FUNCTION_NAME, Ms). + +%% certs always return json list +assert_json_data_certs(Ms, _) -> + lists:foreach( + fun(M) -> + ?assertMatch( + #{ + emqx_cert_expiry_at := _, + listener_type := _, + listener_name := _ + }, + M + ) + end, + Ms + ). + +-if(?EMQX_RELEASE_EDITION == ee). +%% license always map +assert_json_data_license(M, _) -> + ?assertMatch(#{emqx_license_expiry_at := _}, M). +-else. +-endif. + +eval_foreach_assert(FunctionName, Ms) -> + Fun = fun() -> + ok = lists:foreach( + fun(M) -> erlang:apply(?MODULE, FunctionName, [M, ?PROM_DATA_MODE__NODE]) end, Ms + ), + ok = lists:foreach(fun(M) -> ?assertMatch(#{node := _}, M) end, Ms) + end, + Fun(). From 7bfabd7865d36aab72e2b8937670a0e83ccf2824 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Sun, 4 Feb 2024 18:13:39 +0800 Subject: [PATCH 4/7] refactor: meck license checker for prom cases --- .../test/emqx_prometheus_SUITE.erl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl index 0e5e9c31e..4b3cb576d 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl @@ -133,6 +133,22 @@ config(default) -> config(legacy) -> ?LEGACY_CONF_DEFAULT. +conf_default() -> + ?CONF_DEFAULT. + +legacy_conf_default() -> + ?LEGACY_CONF_DEFAULT. + +-if(?EMQX_RELEASE_EDITION == ee). +maybe_meck_license() -> + meck:new(emqx_license_checker, [non_strict, passthrough, no_link]), + meck:expect(emqx_license_checker, expiry_epoch, fun() -> 1859673600 end). +maybe_unmeck_license() -> + meck:unload(emqx_license_checker). +-else. +maybe_meck_license() -> ok. +maybe_unmeck_license() -> ok. +-endif. %%-------------------------------------------------------------------- %% Test cases %%-------------------------------------------------------------------- From ba1d24d054092d3a31fcedf7e73b60b92ee5fb8d Mon Sep 17 00:00:00 2001 From: JimMoen Date: Fri, 2 Feb 2024 16:19:26 +0800 Subject: [PATCH 5/7] test(prom_api): '/prometheus/auth' and '/prometheus/data_integration' --- .../src/emqx_authz/emqx_authz_schema.erl | 4 + .../test/emqx_authz/emqx_authz_SUITE.erl | 23 +- .../test/emqx_prometheus_data_SUITE.erl | 353 +++++++++++++++--- 3 files changed, 325 insertions(+), 55 deletions(-) diff --git a/apps/emqx_auth/src/emqx_authz/emqx_authz_schema.erl b/apps/emqx_auth/src/emqx_authz/emqx_authz_schema.erl index 5a73f5991..8e82ea061 100644 --- a/apps/emqx_auth/src/emqx_authz/emqx_authz_schema.erl +++ b/apps/emqx_auth/src/emqx_authz/emqx_authz_schema.erl @@ -42,6 +42,10 @@ authz_common_fields/1 ]). +-ifdef(TEST). +-export([source_schema_mods/0]). +-endif. + -define(AUTHZ_MODS_PT_KEY, {?MODULE, authz_schema_mods}). %%-------------------------------------------------------------------- diff --git a/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl b/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl index cee120acb..746f3daad 100644 --- a/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl +++ b/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl @@ -292,16 +292,19 @@ t_update_source(_) -> t_replace_all(_) -> RootKey = [<<"authorization">>], Conf = emqx:get_raw_config(RootKey), - emqx_authz_utils:update_config(RootKey, Conf#{ - <<"sources">> => [ - ?SOURCE_FILE1, - ?SOURCE_REDIS, - ?SOURCE_POSTGRESQL, - ?SOURCE_MYSQL, - ?SOURCE_MONGODB, - ?SOURCE_HTTP - ] - }), + ?assertMatch( + {ok, _}, + emqx_authz_utils:update_config(RootKey, Conf#{ + <<"sources">> => [ + ?SOURCE_FILE1, + ?SOURCE_REDIS, + ?SOURCE_POSTGRESQL, + ?SOURCE_MYSQL, + ?SOURCE_MONGODB, + ?SOURCE_HTTP + ] + }) + ), %% config ?assertMatch( [ diff --git a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl index 22a888f28..b0a0a2c18 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl @@ -26,11 +26,62 @@ -define(LOGT(Format, Args), ct:pal("TEST_SUITE: " ++ Format, Args)). +%% erlfmt-ignore +-define(EMQX_CONF, <<" +authentication = [ + { + backend = built_in_database + enable = true + mechanism = password_based + password_hash_algorithm {name = sha256, salt_position = suffix} + user_id_type = username + }, + { + algorithm = sha256 + backend = built_in_database + enable = true + iteration_count = 4096 + mechanism = scram + } +] +authorization { + cache { + enable = true + } + deny_action = ignore + no_match = allow + sources = [ + {path = \"${EMQX_ETC_DIR}/acl.conf\", type = file} + ] +} +connectors { + http { + test_http_connector { + ssl {enable = false, verify = verify_peer} + url = \"http://127.0.0.1:3000\" + } + } +} +rule_engine { + ignore_sys_message = true + jq_function_default_timeout = 10s + rules { + rule_xbmw { + actions = [\"mqtt:action1\"] + description = \"\" + enable = true + metadata {created_at = 1707244896918} + sql = \"SELECT * FROM \\\"t/#\\\"\" + } + } +} +">>). + all() -> [ - {group, stats}, - {group, auth}, - {group, data_integration} + {group, '/prometheus/stats'}, + {group, '/prometheus/auth'}, + {group, '/prometheus/data_integration'} ]. groups() -> @@ -45,9 +96,9 @@ groups() -> {group, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED} ], [ - {stats, ModeGroups}, - {auth, ModeGroups}, - {data_integration, ModeGroups}, + {'/prometheus/stats', ModeGroups}, + {'/prometheus/auth', ModeGroups}, + {'/prometheus/data_integration', ModeGroups}, {?PROM_DATA_MODE__NODE, AcceptGroups}, {?PROM_DATA_MODE__ALL_NODES_AGGREGATED, AcceptGroups}, {?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED, AcceptGroups}, @@ -58,26 +109,53 @@ groups() -> init_per_suite(Config) -> meck:new(emqx_retainer, [non_strict, passthrough, no_history, no_link]), meck:expect(emqx_retainer, retained_count, fun() -> 0 end), - emqx_prometheus_SUITE:init_group(), - ok = emqx_common_test_helpers:start_apps( - [emqx, emqx_conf, emqx_auth, emqx_rule_engine, emqx_prometheus], - fun set_special_configs/1 + meck:expect( + emqx_authz_file, + acl_conf_file, + fun() -> + emqx_common_test_helpers:deps_path(emqx_auth, "etc/acl.conf") + end ), - Config. + ok = emqx_prometheus_SUITE:maybe_meck_license(), + + application:load(emqx_auth), + Apps = emqx_cth_suite:start( + [ + emqx, + {emqx_conf, ?EMQX_CONF}, + emqx_auth, + emqx_auth_mnesia, + emqx_rule_engine, + emqx_bridge_http, + emqx_connector, + {emqx_prometheus, emqx_prometheus_SUITE:legacy_conf_default()} + ], + #{ + work_dir => filename:join(?config(priv_dir, Config), ?MODULE) + } + ), + + [{apps, Apps} | Config]. + end_per_suite(Config) -> meck:unload([emqx_retainer]), - emqx_prometheus_SUITE:end_group(), - emqx_common_test_helpers:stop_apps( - [emqx, emqx_conf, emqx_auth, emqx_rule_engine, emqx_prometheus] + emqx_prometheus_SUITE:maybe_unmeck_license(), + {ok, _} = emqx:update_config( + [authorization], + #{ + <<"no_match">> => <<"allow">>, + <<"cache">> => #{<<"enable">> => <<"true">>}, + <<"sources">> => [] + } ), + emqx_cth_suite:stop(?config(apps, Config)), + ok. - Config. - -init_per_group(stats, Config) -> +init_per_group('/prometheus/stats', Config) -> [{module, emqx_prometheus} | Config]; -init_per_group(auth, Config) -> +init_per_group('/prometheus/auth', Config) -> [{module, emqx_prometheus_auth} | Config]; -init_per_group(data_integration, Config) -> +init_per_group('/prometheus/data_integration', Config) -> [{module, emqx_prometheus_data_integration} | Config]; init_per_group(?PROM_DATA_MODE__NODE, Config) -> [{mode, ?PROM_DATA_MODE__NODE} | Config]; @@ -95,17 +173,28 @@ init_per_group(_Group, Config) -> end_per_group(_Group, _Config) -> ok. -set_special_configs(emqx_dashboard) -> - emqx_dashboard_api_test_helpers:set_default_config(); -set_special_configs(emqx_auth) -> - {ok, _} = emqx:update_config([authorization, cache, enable], true), - {ok, _} = emqx:update_config([authorization, no_match], deny), - {ok, _} = emqx:update_config([authorization, sources], []), +init_per_testcase(t_collect_prom_data, Config) -> + meck:new(emqx_utils, [non_strict, passthrough, no_history, no_link]), + meck:expect(emqx_utils, gen_id, fun() -> "fake" end), + + meck:new(emqx, [non_strict, passthrough, no_history, no_link]), + meck:expect( + emqx, + data_dir, + fun() -> + {data_dir, Data} = lists:keyfind(data_dir, 1, Config), + Data + end + ), + Config; +init_per_testcase(_, Config) -> + Config. + +end_per_testcase(t_collect_prom_data, _Config) -> + meck:unload(emqx_utils), + meck:unload(emqx), ok; -set_special_configs(emqx_prometheus) -> - emqx_prometheus_SUITE:load_config(), - ok; -set_special_configs(_App) -> +end_per_testcase(_, _Config) -> ok. %%-------------------------------------------------------------------- @@ -151,11 +240,11 @@ assert_prom_data(DataL, Mode) -> end, DataL ), - do_assert_prom_data_stats(NDataL, Mode). + do_assert_prom_data(NDataL, Mode). -define(MGU(K, MAP), maps:get(K, MAP, undefined)). -assert_json_data(emqx_prometheus, Data, Mode) -> +assert_json_data(_, Data, Mode) -> lists:foreach( fun(FunSeed) -> erlang:apply(?MODULE, fun_name(FunSeed), [?MGU(FunSeed, Data), Mode]), @@ -163,9 +252,6 @@ assert_json_data(emqx_prometheus, Data, Mode) -> end, maps:keys(Data) ), - ok; -%% TOOD auth/data_integration -assert_json_data(_, _, _) -> ok. fun_name(Seed) -> @@ -186,12 +272,12 @@ accept('text/plain') -> accept('application/json') -> <<"json">>. -do_assert_prom_data_stats([], _Mode) -> +do_assert_prom_data([], _Mode) -> ok; -do_assert_prom_data_stats([Metric | RestDataL], Mode) -> +do_assert_prom_data([Metric | RestDataL], Mode) -> [_MetricNamme | _] = Metric, assert_stats_metric_labels(Metric, Mode), - do_assert_prom_data_stats(RestDataL, Mode). + do_assert_prom_data(RestDataL, Mode). assert_stats_metric_labels([MetricName | R] = _Metric, Mode) -> case maps:get(Mode, metric_meta(MetricName), undefined) of @@ -199,6 +285,12 @@ assert_stats_metric_labels([MetricName | R] = _Metric, Mode) -> undefined -> ok; N when is_integer(N) -> + %% ct:print( + %% "====================~n" + %% "%% Metric: ~p~n" + %% "%% Expect labels count: ~p in Mode: ~p~n", + %% [_Metric, N, Mode] + %% ), ?assertEqual(N, length(lists:droplast(R))) end. @@ -208,7 +300,7 @@ assert_stats_metric_labels([MetricName | R] = _Metric, Mode) -> ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED => UNAGGRE }). -%% TODO: auth/data_integration +%% `/prometheus/stats` %% BEGIN always no label metric_meta(<<"emqx_topics_max">>) -> ?meta(0, 0, 0); metric_meta(<<"emqx_topics_count">>) -> ?meta(0, 0, 0); @@ -227,6 +319,21 @@ metric_meta(<<"emqx_cert_expiry_at">>) -> ?meta(2, 2, 2); metric_meta(<<"emqx_license_expiry_at">>) -> ?meta(0, 0, 0); %% mria metric with label `shard` and `node` when not in mode `node` metric_meta(<<"emqx_mria_", _Tail/binary>>) -> ?meta(1, 2, 2); +%% `/prometheus/auth` +metric_meta(<<"emqx_authn_users_count">>) -> ?meta(1, 1, 1); +metric_meta(<<"emqx_authn_", _Tail/binary>>) -> ?meta(1, 1, 2); +metric_meta(<<"emqx_authz_rules_count">>) -> ?meta(1, 1, 1); +metric_meta(<<"emqx_authz_", _Tail/binary>>) -> ?meta(1, 1, 2); +metric_meta(<<"emqx_banned_count">>) -> ?meta(0, 0, 0); +%% `/prometheus/data_integration` +metric_meta(<<"emqx_rules_count">>) -> ?meta(0, 0, 0); +metric_meta(<<"emqx_connectors_count">>) -> ?meta(0, 0, 0); +metric_meta(<<"emqx_schema_registrys_count">>) -> ?meta(0, 0, 0); +metric_meta(<<"emqx_rule_", _Tail/binary>>) -> ?meta(1, 1, 2); +metric_meta(<<"emqx_action_", _Tail/binary>>) -> ?meta(1, 1, 2); +metric_meta(<<"emqx_connector_", _Tail/binary>>) -> ?meta(1, 1, 2); +%% normal emqx metrics +metric_meta(<<"emqx_", _Tail/binary>>) -> ?meta(0, 0, 1); metric_meta(_) -> #{}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -505,13 +612,6 @@ assert_json_data_certs(Ms, _) -> Ms ). --if(?EMQX_RELEASE_EDITION == ee). -%% license always map -assert_json_data_license(M, _) -> - ?assertMatch(#{emqx_license_expiry_at := _}, M). --else. --endif. - eval_foreach_assert(FunctionName, Ms) -> Fun = fun() -> ok = lists:foreach( @@ -520,3 +620,166 @@ eval_foreach_assert(FunctionName, Ms) -> ok = lists:foreach(fun(M) -> ?assertMatch(#{node := _}, M) end, Ms) end, Fun(). + +-if(?EMQX_RELEASE_EDITION == ee). +%% license always map +assert_json_data_license(M, _) -> + ?assertMatch(#{emqx_license_expiry_at := _}, M). +-else. +-endif. + +-define(assert_node_foreach(Ms), lists:foreach(fun(M) -> ?assertMatch(#{node := _}, M) end, Ms)). + +assert_json_data_emqx_banned(M, _) -> + ?assertMatch(#{emqx_banned_count := _}, M). + +assert_json_data_emqx_authn(Ms, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + lists:foreach( + fun(M) -> + ?assertMatch( + #{ + id := _, + emqx_authn_enable := _, + emqx_authn_failed := _, + emqx_authn_nomatch := _, + emqx_authn_status := _, + emqx_authn_success := _, + emqx_authn_total := _, + emqx_authn_users_count := _ + }, + M + ) + end, + Ms + ); +assert_json_data_emqx_authn(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) -> + ?assert_node_foreach(Ms). + +assert_json_data_emqx_authz(Ms, _) -> + lists:foreach( + fun(M) -> + ?assertMatch( + #{ + type := _, + emqx_authz_allow := _, + emqx_authz_deny := _, + emqx_authz_enable := _, + emqx_authz_nomatch := _, + emqx_authz_rules_count := _, + emqx_authz_status := _, + emqx_authz_total := _ + }, + M + ) + end, + Ms + ); +assert_json_data_emqx_authz(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) -> + ?assert_node_foreach(Ms). + +assert_json_data_rules(Ms, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + lists:foreach( + fun(M) -> + ?assertMatch( + #{ + id := _, + emqx_rule_actions_failed := _, + emqx_rule_actions_failed_out_of_service := _, + emqx_rule_actions_failed_unknown := _, + emqx_rule_actions_success := _, + emqx_rule_actions_total := _, + emqx_rule_enable := _, + emqx_rule_failed := _, + emqx_rule_failed_exception := _, + emqx_rule_failed_no_result := _, + emqx_rule_matched := _, + emqx_rule_passed := _ + }, + M + ) + end, + Ms + ); +assert_json_data_rules(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + ?assert_node_foreach(Ms). + +assert_json_data_actions(Ms, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + lists:foreach( + fun(M) -> + ?assertMatch( + #{ + id := _, + emqx_action_dropped := _, + emqx_action_dropped_expired := _, + emqx_action_dropped_other := _, + emqx_action_dropped_queue_full := _, + emqx_action_dropped_resource_not_found := _, + emqx_action_dropped_resource_stopped := _, + emqx_action_enable := _, + emqx_action_failed := _, + emqx_action_inflight := _, + emqx_action_late_reply := _, + emqx_action_matched := _, + emqx_action_queuing := _, + emqx_action_received := _, + emqx_action_retried := _, + emqx_action_retried_failed := _, + emqx_action_retried_success := _, + emqx_action_status := _, + emqx_action_success := _ + }, + M + ) + end, + Ms + ); +assert_json_data_actions(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + ?assert_node_foreach(Ms). + +assert_json_data_connectors(Ms, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> + lists:foreach( + fun(M) -> + ?assertMatch( + #{ + id := _, + emqx_connector_enable := _, + emqx_connector_status := _ + }, + M + ) + end, + Ms + ); +assert_json_data_connectors(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when + is_list(Ms) +-> + ?assert_node_foreach(Ms). + +assert_json_data_data_integration_overview(M, _) -> + ?assertMatch( + #{ + emqx_connectors_count := _, + emqx_rules_count := _, + emqx_schema_registrys_count := _ + }, + M + ). + +stop_apps(Apps) -> + lists:foreach(fun application:stop/1, Apps). From c61b5584236f4b7a7c1465631fd05c85c7874519 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Sun, 18 Feb 2024 03:39:18 +0800 Subject: [PATCH 6/7] test(prom): start mock pushgateway --- apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl index b0a0a2c18..95f303b82 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl @@ -117,6 +117,7 @@ init_per_suite(Config) -> end ), ok = emqx_prometheus_SUITE:maybe_meck_license(), + emqx_prometheus_SUITE:start_mock_pushgateway(9091), application:load(emqx_auth), Apps = emqx_cth_suite:start( @@ -140,6 +141,7 @@ init_per_suite(Config) -> end_per_suite(Config) -> meck:unload([emqx_retainer]), emqx_prometheus_SUITE:maybe_unmeck_license(), + emqx_prometheus_SUITE:stop_mock_pushgateway(), {ok, _} = emqx:update_config( [authorization], #{ From 6aae3ba2edf0c2870870e132c9e8b6633d0e3d64 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Sun, 18 Feb 2024 10:42:40 +0800 Subject: [PATCH 7/7] refactor(prom_test): assert fun prefix --- .../test/emqx_prometheus_data_SUITE.erl | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl index 95f303b82..ccb27e245 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_data_SUITE.erl @@ -257,7 +257,7 @@ assert_json_data(_, Data, Mode) -> ok. fun_name(Seed) -> - binary_to_atom(<<"assert_json_data_", (atom_to_binary(Seed))/binary>>). + binary_to_atom(<<"assert_json_data__", (atom_to_binary(Seed))/binary>>). %%-------------------------------------------------------------------- %% Internal Functions @@ -341,7 +341,7 @@ metric_meta(_) -> #{}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Assert Json Data Structure -assert_json_data_messages(M, Mode) when +assert_json_data__messages(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -368,10 +368,10 @@ assert_json_data_messages(M, Mode) when M ), ok; -assert_json_data_messages(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> +assert_json_data__messages(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_stats(M, Mode) when +assert_json_data__stats(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -402,18 +402,18 @@ assert_json_data_stats(M, Mode) when }, M ); -assert_json_data_stats(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> +assert_json_data__stats(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_olp(M, Mode) when +assert_json_data__olp(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> ?assertMatch(#{}, M); -assert_json_data_olp(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> +assert_json_data__olp(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> ok. -assert_json_data_client(M, Mode) when +assert_json_data__client(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -431,10 +431,10 @@ assert_json_data_client(M, Mode) when }, M ); -assert_json_data_client(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> +assert_json_data__client(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_session(M, Mode) when +assert_json_data__session(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -448,10 +448,10 @@ assert_json_data_session(M, Mode) when }, M ); -assert_json_data_session(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> +assert_json_data__session(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_metrics(M, ?PROM_DATA_MODE__NODE) -> +assert_json_data__metrics(M, ?PROM_DATA_MODE__NODE) -> ?assertMatch( #{ emqx_vm_cpu_use := _, @@ -463,14 +463,14 @@ assert_json_data_metrics(M, ?PROM_DATA_MODE__NODE) -> }, M ); -assert_json_data_metrics(Ms, Mode) when +assert_json_data__metrics(Ms, Mode) when is_list(Ms) andalso (Mode =:= ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_delivery(M, Mode) when +assert_json_data__delivery(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -485,12 +485,12 @@ assert_json_data_delivery(M, Mode) when }, M ); -assert_json_data_delivery(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__delivery(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_cluster(M, Mode) when +assert_json_data__cluster(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -498,12 +498,12 @@ assert_json_data_cluster(M, Mode) when #{emqx_cluster_nodes_running := _, emqx_cluster_nodes_stopped := _}, M ); -assert_json_data_cluster(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__cluster(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_acl(M, Mode) when +assert_json_data__acl(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -520,12 +520,12 @@ assert_json_data_acl(M, Mode) when }, M ); -assert_json_data_acl(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__acl(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_authn(M, Mode) when +assert_json_data__authn(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -537,12 +537,12 @@ assert_json_data_authn(M, Mode) when }, M ); -assert_json_data_authn(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__authn(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). -assert_json_data_packets(M, Mode) when +assert_json_data__packets(M, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -593,13 +593,13 @@ assert_json_data_packets(M, Mode) when }, M ); -assert_json_data_packets(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__packets(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> eval_foreach_assert(?FUNCTION_NAME, Ms). %% certs always return json list -assert_json_data_certs(Ms, _) -> +assert_json_data__certs(Ms, _) -> lists:foreach( fun(M) -> ?assertMatch( @@ -625,17 +625,17 @@ eval_foreach_assert(FunctionName, Ms) -> -if(?EMQX_RELEASE_EDITION == ee). %% license always map -assert_json_data_license(M, _) -> +assert_json_data__license(M, _) -> ?assertMatch(#{emqx_license_expiry_at := _}, M). -else. -endif. -define(assert_node_foreach(Ms), lists:foreach(fun(M) -> ?assertMatch(#{node := _}, M) end, Ms)). -assert_json_data_emqx_banned(M, _) -> +assert_json_data__emqx_banned(M, _) -> ?assertMatch(#{emqx_banned_count := _}, M). -assert_json_data_emqx_authn(Ms, Mode) when +assert_json_data__emqx_authn(Ms, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -657,10 +657,13 @@ assert_json_data_emqx_authn(Ms, Mode) when end, Ms ); -assert_json_data_emqx_authn(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) -> +assert_json_data__emqx_authn(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) -> ?assert_node_foreach(Ms). -assert_json_data_emqx_authz(Ms, _) -> +assert_json_data__emqx_authz(Ms, Mode) when + (Mode =:= ?PROM_DATA_MODE__NODE orelse + Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) +-> lists:foreach( fun(M) -> ?assertMatch( @@ -679,10 +682,10 @@ assert_json_data_emqx_authz(Ms, _) -> end, Ms ); -assert_json_data_emqx_authz(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) -> +assert_json_data__emqx_authz(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) -> ?assert_node_foreach(Ms). -assert_json_data_rules(Ms, Mode) when +assert_json_data__rules(Ms, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -708,12 +711,12 @@ assert_json_data_rules(Ms, Mode) when end, Ms ); -assert_json_data_rules(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__rules(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> ?assert_node_foreach(Ms). -assert_json_data_actions(Ms, Mode) when +assert_json_data__actions(Ms, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -746,12 +749,12 @@ assert_json_data_actions(Ms, Mode) when end, Ms ); -assert_json_data_actions(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__actions(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> ?assert_node_foreach(Ms). -assert_json_data_connectors(Ms, Mode) when +assert_json_data__connectors(Ms, Mode) when (Mode =:= ?PROM_DATA_MODE__NODE orelse Mode =:= ?PROM_DATA_MODE__ALL_NODES_AGGREGATED) -> @@ -768,12 +771,13 @@ assert_json_data_connectors(Ms, Mode) when end, Ms ); -assert_json_data_connectors(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when +assert_json_data__connectors(Ms, ?PROM_DATA_MODE__ALL_NODES_UNAGGREGATED) when is_list(Ms) -> ?assert_node_foreach(Ms). -assert_json_data_data_integration_overview(M, _) -> +-if(?EMQX_RELEASE_EDITION == ee). +assert_json_data__data_integration_overview(M, _) -> ?assertMatch( #{ emqx_connectors_count := _, @@ -783,5 +787,16 @@ assert_json_data_data_integration_overview(M, _) -> M ). +-else. +assert_json_data__data_integration_overview(M, _) -> + ?assertMatch( + #{ + emqx_connectors_count := _, + emqx_rules_count := _ + }, + M + ). +-endif. + stop_apps(Apps) -> lists:foreach(fun application:stop/1, Apps).