emqx/apps/emqx_opentelemetry/test/emqx_otel_api_SUITE.erl

296 lines
10 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_otel_api_SUITE).
-compile(export_all).
-compile(nowarn_export_all).
-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-define(OTEL_API_PATH, emqx_mgmt_api_test_util:api_path(["opentelemetry"])).
-define(CONF_PATH, [opentelemetry]).
-define(CACERT, <<
"-----BEGIN CERTIFICATE-----\n"
"MIIDUTCCAjmgAwIBAgIJAPPYCjTmxdt/MA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV\n"
"BAYTAkNOMREwDwYDVQQIDAhoYW5nemhvdTEMMAoGA1UECgwDRU1RMQ8wDQYDVQQD\n"
"DAZSb290Q0EwHhcNMjAwNTA4MDgwNjUyWhcNMzAwNTA2MDgwNjUyWjA/MQswCQYD\n"
"VQQGEwJDTjERMA8GA1UECAwIaGFuZ3pob3UxDDAKBgNVBAoMA0VNUTEPMA0GA1UE\n"
"AwwGUm9vdENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcgVLex1\n"
"EZ9ON64EX8v+wcSjzOZpiEOsAOuSXOEN3wb8FKUxCdsGrsJYB7a5VM/Jot25Mod2\n"
"juS3OBMg6r85k2TWjdxUoUs+HiUB/pP/ARaaW6VntpAEokpij/przWMPgJnBF3Ur\n"
"MjtbLayH9hGmpQrI5c2vmHQ2reRZnSFbY+2b8SXZ+3lZZgz9+BaQYWdQWfaUWEHZ\n"
"uDaNiViVO0OT8DRjCuiDp3yYDj3iLWbTA/gDL6Tf5XuHuEwcOQUrd+h0hyIphO8D\n"
"tsrsHZ14j4AWYLk1CPA6pq1HIUvEl2rANx2lVUNv+nt64K/Mr3RnVQd9s8bK+TXQ\n"
"KGHd2Lv/PALYuwIDAQABo1AwTjAdBgNVHQ4EFgQUGBmW+iDzxctWAWxmhgdlE8Pj\n"
"EbQwHwYDVR0jBBgwFoAUGBmW+iDzxctWAWxmhgdlE8PjEbQwDAYDVR0TBAUwAwEB\n"
"/zANBgkqhkiG9w0BAQsFAAOCAQEAGbhRUjpIred4cFAFJ7bbYD9hKu/yzWPWkMRa\n"
"ErlCKHmuYsYk+5d16JQhJaFy6MGXfLgo3KV2itl0d+OWNH0U9ULXcglTxy6+njo5\n"
"CFqdUBPwN1jxhzo9yteDMKF4+AHIxbvCAJa17qcwUKR5MKNvv09C6pvQDJLzid7y\n"
"E2dkgSuggik3oa0427KvctFf8uhOV94RvEDyqvT5+pgNYZ2Yfga9pD/jjpoHEUlo\n"
"88IGU8/wJCx3Ds2yc8+oBg/ynxG8f/HmCC1ET6EHHoe2jlo8FpU/SgGtghS1YL30\n"
"IWxNsPrUP+XsZpBJy/mvOhE5QXo6Y35zDqqj8tI7AGmAWu22jg==\n"
"-----END CERTIFICATE-----"
>>).
all() ->
emqx_common_test_helpers:all(?MODULE).
init_per_suite(Config) ->
%% This is called by emqx_machine in EMQX release
emqx_otel_app:configure_otel_deps(),
Apps = emqx_cth_suite:start(
[
emqx_conf,
emqx_management,
{emqx_dashboard, "dashboard.listeners.http { enable = true, bind = 18083 }"},
emqx_opentelemetry
],
#{work_dir => emqx_cth_suite:work_dir(Config)}
),
Auth = auth_header(),
[{suite_apps, Apps}, {auth, Auth} | Config].
end_per_suite(Config) ->
emqx_cth_suite:stop(?config(suite_apps, Config)),
emqx_config:delete_override_conf_files(),
ok.
init_per_testcase(_TC, Config) ->
emqx_conf:update(
?CONF_PATH,
#{
<<"traces">> => #{<<"enable">> => false},
<<"metrics">> => #{<<"enable">> => false},
<<"logs">> => #{<<"enable">> => false}
},
#{}
),
Config.
end_per_testcase(_TC, _Config) ->
ok.
auth_header() ->
{ok, API} = emqx_common_test_http:create_default_app(),
emqx_common_test_http:auth_header(API).
t_get(Config) ->
Auth = ?config(auth, Config),
Path = ?OTEL_API_PATH,
{ok, Resp} = emqx_mgmt_api_test_util:request_api(get, Path, Auth),
?assertMatch(
#{
<<"traces">> := #{<<"enable">> := false},
<<"metrics">> := #{<<"enable">> := false},
<<"logs">> := #{<<"enable">> := false}
},
emqx_utils_json:decode(Resp)
).
t_put_enable_disable(Config) ->
Auth = ?config(auth, Config),
Path = ?OTEL_API_PATH,
EnableAllReq = #{
<<"traces">> => #{<<"enable">> => true},
<<"metrics">> => #{<<"enable">> => true},
<<"logs">> => #{<<"enable">> => true}
},
?assertMatch({ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, EnableAllReq)),
?assertMatch(
#{
traces := #{enable := true},
metrics := #{enable := true},
logs := #{enable := true}
},
emqx:get_config(?CONF_PATH)
),
DisableAllReq = #{
<<"traces">> => #{<<"enable">> => false},
<<"metrics">> => #{<<"enable">> => false},
<<"logs">> => #{<<"enable">> => false}
},
?assertMatch({ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, DisableAllReq)),
?assertMatch(
#{
traces := #{enable := false},
metrics := #{enable := false},
logs := #{enable := false}
},
emqx:get_config(?CONF_PATH)
).
t_put_invalid(Config) ->
Auth = ?config(auth, Config),
Path = ?OTEL_API_PATH,
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"endpoint">> => <<>>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"endpoint">> => <<"unknown://somehost.org">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"endpoint">> => <<"https://somehost.org:99999">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"endpoint">> => <<"https://somehost.org:99999">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"unknown_field">> => <<"foo">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"protocol">> => <<"unknown">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"traces">> => #{<<"filter">> => #{<<"unknown_filter">> => <<"foo">>}}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"logs">> => #{<<"level">> => <<"foo">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"metrics">> => #{<<"interval">> => <<"foo">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"logs">> => #{<<"unknown_field">> => <<"foo">>}
})
),
?assertMatch(
{error, {_, 400, _}},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{<<"unknown_field">> => <<"foo">>})
).
t_put_valid(Config) ->
Auth = ?config(auth, Config),
Path = ?OTEL_API_PATH,
?assertMatch(
{ok, _},
emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{
<<"exporter">> => #{<<"endpoint">> => <<"nohost.com">>}
})
),
?assertEqual(<<"http://nohost.com/">>, emqx:get_config(?CONF_PATH ++ [exporter, endpoint])),
?assertMatch(
{ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{<<"exporter">> => #{}})
),
?assertMatch({ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{})),
?assertMatch(
{ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{<<"traces">> => #{}})
),
?assertMatch(
{ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{<<"logs">> => #{}})
),
?assertMatch(
{ok, _}, emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, #{<<"metrics">> => #{}})
),
?assertMatch(
{ok, _},
emqx_mgmt_api_test_util:request_api(
put,
Path,
"",
Auth,
#{<<"exporter">> => #{}, <<"traces">> => #{}, <<"logs">> => #{}, <<"metrics">> => #{}}
)
),
?assertMatch(
{ok, _},
emqx_mgmt_api_test_util:request_api(
put,
Path,
"",
Auth,
#{
<<"exporter">> => #{
<<"endpoint">> => <<"https://localhost:4317">>, <<"protocol">> => <<"grpc">>
},
<<"traces">> => #{
<<"enable">> => true,
<<"max_queue_size">> => 10,
<<"exporting_timeout">> => <<"10s">>,
<<"scheduled_delay">> => <<"20s">>,
<<"filter">> => #{<<"trace_all">> => true}
},
<<"logs">> => #{
<<"level">> => <<"warning">>,
<<"max_queue_size">> => 100,
<<"exporting_timeout">> => <<"10s">>,
<<"scheduled_delay">> => <<"1s">>
},
<<"metrics">> => #{
%% alias for "interval"
<<"scheduled_delay">> => <<"15321ms">>
}
}
),
%% alias check
?assertEqual(15_321, emqx:get_config(?CONF_PATH ++ [metrics, interval]))
).
t_put_cert(Config) ->
Auth = ?config(auth, Config),
Path = ?OTEL_API_PATH,
SSL = #{<<"enable">> => true, <<"cacertfile">> => ?CACERT},
SSLDisabled = #{<<"enable">> => false, <<"cacertfile">> => ?CACERT},
Conf = #{<<"exporter">> => #{<<"ssl_options">> => SSL}},
Conf1 = #{<<"exporter">> => #{<<"ssl_options">> => SSLDisabled}},
{ok, Body} = emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, Conf),
#{<<"exporter">> := #{<<"ssl_options">> := #{<<"cacertfile">> := CaFile}}} = emqx_utils_json:decode(
Body
),
ct:pal("CA certfile: ~p", [CaFile]),
?assert(filelib:is_file(CaFile)),
{ok, Body1} = emqx_mgmt_api_test_util:request_api(put, Path, "", Auth, Conf1),
#{<<"exporter">> := #{<<"ssl_options">> := #{<<"cacertfile">> := CaFile1}}} = emqx_utils_json:decode(
Body1
),
ct:pal("CA certfile1: ~p", [CaFile1]),
?assertNot(filelib:is_file(CaFile1)).