From 8967e13eeeaf9cd710075b67dd4e0324191bb7ee Mon Sep 17 00:00:00 2001
From: ieQu1 <99872536+ieQu1@users.noreply.github.com>
Date: Wed, 23 Mar 2022 13:42:11 +0100
Subject: [PATCH] docs(schema): Move descriptions from emqx.conf.all
---
apps/emqx/src/emqx_schema.erl | 37 ++++++++++---
apps/emqx_conf/src/emqx_conf_schema.erl | 6 ++-
.../src/emqx_dashboard_schema.erl | 5 +-
apps/emqx_exhook/src/emqx_exhook_schema.erl | 31 ++++++++---
apps/emqx_gateway/src/emqx_gateway_schema.erl | 24 ++++++++-
.../src/emqx_retainer_schema.erl | 54 ++++++++++++++-----
6 files changed, 126 insertions(+), 31 deletions(-)
diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl
index e502bd548..4219f8463 100644
--- a/apps/emqx/src/emqx_schema.erl
+++ b/apps/emqx/src/emqx_schema.erl
@@ -659,22 +659,40 @@ fields("flapping_detect") ->
{"enable",
sc(
boolean(),
- #{default => false}
+ #{
+ default => false,
+ desc =>
+ "Enable flapping connection detection feature.
\n"
+ "This config controls the allowed maximum number of `CONNECT` packets received\n"
+ "from the same clientid in a time frame defined by `window_time`.\n"
+ "After the limit is reached, successive `CONNECT` requests are forbidden\n"
+ "(banned) until the end of the time period defined by `ban_time`."
+ }
)},
{"max_count",
sc(
integer(),
- #{default => 15}
+ #{
+ default => 15,
+ desc =>
+ "The maximum number of disconnects allowed for a MQTT Client in `window_time`"
+ }
)},
{"window_time",
sc(
duration(),
- #{default => "1m"}
+ #{
+ default => "1m",
+ desc => "The time window for flapping detection."
+ }
)},
{"ban_time",
sc(
duration(),
- #{default => "5m"}
+ #{
+ default => "5m",
+ desc => "How long the flapping clientid will be banned."
+ }
)}
];
fields("force_shutdown") ->
@@ -682,18 +700,25 @@ fields("force_shutdown") ->
{"enable",
sc(
boolean(),
- #{default => true}
+ #{
+ default => true,
+ desc => "Enable `force_shutdown` feature."
+ }
)},
{"max_message_queue_len",
sc(
range(0, inf),
- #{default => 1000}
+ #{
+ default => 1000,
+ desc => "Maximum message queue length."
+ }
)},
{"max_heap_size",
sc(
wordsize(),
#{
default => "32MB",
+ desc => "Total heap size",
validator => fun ?MODULE:validate_heap_size/1
}
)}
diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl
index 826b73461..e1fdf2361 100644
--- a/apps/emqx_conf/src/emqx_conf_schema.erl
+++ b/apps/emqx_conf/src/emqx_conf_schema.erl
@@ -637,13 +637,17 @@ fields("console_handler") ->
fields("log_file_handler") ->
[ {"file",
sc(file(),
- #{})}
+ #{ desc => "Name the log file."
+ })}
, {"rotation",
sc(ref("log_rotation"),
#{})}
, {"max_size",
sc(hoconsc:union([infinity, emqx_schema:bytesize()]),
#{ default => "10MB"
+ , desc => "This parameter controls log file rotation. "
+ "The value `infinity` means the log file will grow indefinitely, "
+ "otherwise the log file will be rotated once it reaches `max_size` in bytes."
})}
] ++ log_handler_common_confs();
diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl
index a2c5b3c26..36ec75963 100644
--- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl
+++ b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl
@@ -29,14 +29,13 @@ fields("dashboard") ->
sc(hoconsc:array(hoconsc:union([hoconsc:ref(?MODULE, "http"),
hoconsc:ref(?MODULE, "https")])),
#{ desc =>
-"""HTTP(s) listeners are identified by their protocol type and are
+"HTTP(s) listeners are identified by their protocol type and are
used to serve dashboard UI and restful HTTP API.
Listeners must have a unique combination of port number and IP address.
For example, an HTTP listener can listen on all configured IP addresses
on a given port for a machine by specifying the IP address 0.0.0.0.
Alternatively, the HTTP listener can specify a unique IP address for each listener,
-but use the same port.
-""" })}
+but use the same port."})}
, {default_username, fun default_username/1}
, {default_password, fun default_password/1}
, {sample_interval, sc(emqx_schema:duration_s(), #{default => "10s"})}
diff --git a/apps/emqx_exhook/src/emqx_exhook_schema.erl b/apps/emqx_exhook/src/emqx_exhook_schema.erl
index 77ae90195..e95a46beb 100644
--- a/apps/emqx_exhook/src/emqx_exhook_schema.erl
+++ b/apps/emqx_exhook/src/emqx_exhook_schema.erl
@@ -45,19 +45,36 @@ fields(exhook) ->
];
fields(server) ->
- [ {name, sc(binary(), #{})}
- , {enable, sc(boolean(), #{default => true})}
- , {url, sc(binary(), #{})}
- , {request_timeout,
- sc(duration(), #{default => "5s"})}
+ [ {name, sc(binary(),
+ #{ desc => "Name of the exhook server."
+ })}
+ , {enable, sc(boolean(),
+ #{ default => true
+ , desc => "Enable the exhook server."
+ })}
+ , {url, sc(binary(),
+ #{ desc => "URL of the gRPC server."
+ })}
+ , {request_timeout, sc(duration(),
+ #{ default => "5s"
+ , desc => "The timeout to request gRPC server."
+ })}
, {failed_action, failed_action()}
, {ssl,
sc(ref(ssl_conf), #{})}
, {auto_reconnect,
sc(hoconsc:union([false, duration()]),
- #{default => "60s"})}
+ #{ default => "60s"
+ , desc => "Whether to automatically reconnect (initialize) the gRPC server.
"
+ "When gRPC is not available, exhook tries to request the gRPC service at "
+ "that interval and reinitialize the list of mounted hooks."
+ })}
, {pool_size,
- sc(integer(), #{default => 8, example => 8})}
+ sc(integer(),
+ #{ default => 8
+ , example => 8
+ , desc => "The process pool size for gRPC client."
+ })}
];
fields(ssl_conf) ->
diff --git a/apps/emqx_gateway/src/emqx_gateway_schema.erl b/apps/emqx_gateway/src/emqx_gateway_schema.erl
index 4440aaba8..09b0b7d1c 100644
--- a/apps/emqx_gateway/src/emqx_gateway_schema.erl
+++ b/apps/emqx_gateway/src/emqx_gateway_schema.erl
@@ -473,26 +473,48 @@ common_listener_opts() ->
[ {enable,
sc(boolean(),
#{ default => true
+ , desc => "Enable the listener."
})}
, {bind,
sc(hoconsc:union([ip_port(), integer()]),
- #{})}
+ #{ desc => "The IP address and port that the listener will bind."
+ })}
, {max_connections,
sc(integer(),
#{ default => 1024
+ , desc => "Maximum number of concurrent connections."
})}
, {max_conn_rate,
sc(integer(),
#{ default => 1000
+ , desc => "Maximum connections per second."
})}
, {?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_ATOM, authentication_schema()}
, {mountpoint,
sc(binary(),
#{ default => undefined
+ , desc =>
+ "When publishing or subscribing, prefix all topics with a mountpoint string.\n"
+ " The prefixed string will be removed from the topic name when the message\n"
+ " is delivered to the subscriber. The mountpoint is a way that users can use\n"
+ " to implement isolation of message routing between different listeners.\n"
+ " For example if a client A subscribes to `t` with `listeners.tcp..mountpoint`\n"
+ " set to `some_tenant`, then the client actually subscribes to the topic\n"
+ " `some_tenant/t`. Similarly, if another client B (connected to the same listener\n"
+ " as the client A) sends a message to topic `t`, the message is routed\n"
+ " to all the clients subscribed `some_tenant/t`, so client A will receive the\n"
+ " message, with topic name `t`.
\n"
+ " Set to `\"\"` to disable the feature.
\n"
+ "\n"
+ " Variables in mountpoint string:\n"
+ " - ${clientid}
: clientid\n"
+ " - ${username}
: username"
})}
, {access_rules,
sc(hoconsc:array(string()),
#{ default => []
+ , desc => "The access control rules for this listener.
"
+ "See: https://github.com/emqtt/esockd#allowdeny"
})}
].
diff --git a/apps/emqx_retainer/src/emqx_retainer_schema.erl b/apps/emqx_retainer/src/emqx_retainer_schema.erl
index 12189c737..306ab5642 100644
--- a/apps/emqx_retainer/src/emqx_retainer_schema.erl
+++ b/apps/emqx_retainer/src/emqx_retainer_schema.erl
@@ -11,35 +11,63 @@ namespace() -> "retainer".
roots() -> ["retainer"].
fields("retainer") ->
- [ {enable, sc(boolean(), false)}
- , {msg_expiry_interval, sc(emqx_schema:duration_ms(), "0s")}
- , {msg_clear_interval, sc(emqx_schema:duration_ms(), "0s")}
+ [ {enable, sc(boolean(), "Enable retainer feature.", false)}
+ , {msg_expiry_interval, sc(emqx_schema:duration_ms(),
+ "Message retention time. 0 means message will never be expired.",
+ "0s")}
+ , {msg_clear_interval, sc(emqx_schema:duration_ms(),
+ "Periodic interval for cleaning up expired messages. "
+ "Never clear if the value is 0.",
+ "0s")}
, {flow_control, ?TYPE(hoconsc:ref(?MODULE, flow_control))}
- , {max_payload_size, sc(emqx_schema:bytesize(), "1MB")}
- , {stop_publish_clear_msg, sc(boolean(), false)}
+ , {max_payload_size, sc(emqx_schema:bytesize(),
+ "Maximum retained message size.",
+ "1MB")}
+ , {stop_publish_clear_msg, sc(boolean(),
+ "When the retained flag of the `PUBLISH` message is set and Payload is empty, "
+ "whether to continue to publish the message.
"
+ "See: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718038",
+ false)}
, {backend, backend_config()}
];
fields(mnesia_config) ->
[ {type, ?TYPE(hoconsc:union([built_in_database]))}
- , {storage_type, sc(hoconsc:union([ram, disc]), ram)}
- , {max_retained_messages, sc(integer(), 0, fun is_pos_integer/1)}
+ , {storage_type, sc(hoconsc:union([ram, disc]),
+ "Specifies whether the messages are stored in RAM or persisted on disc.",
+ ram)}
+ , {max_retained_messages, sc(integer(),
+ "Maximum number of retained messages. 0 means no limit.",
+ 0,
+ fun is_pos_integer/1)}
];
fields(flow_control) ->
- [ {batch_read_number, sc(integer(), 0, fun is_pos_integer/1)}
- , {batch_deliver_number, sc(range(0, 1000), 0)}
- , {batch_deliver_limiter, sc(emqx_limiter_schema:bucket_name(), undefined)}
+ [ {batch_read_number, sc(integer(),
+ "Size of the batch when reading messages from storage. 0 means no limit.",
+ 0,
+ fun is_pos_integer/1)}
+ , {batch_deliver_number, sc(range(0, 1000),
+ "The number of retained messages can be delivered per batch.",
+ 0)}
+ , {batch_deliver_limiter, sc(emqx_limiter_schema:bucket_name(),
+ "The rate limiter name for retained messages' delivery.
"
+ "Limiter helps to avoid delivering too many messages to the client at once, which may cause the client "
+ "to block or crash, or drop messages due to exceeding the size of the message queue.
"
+ "The names of the available rate limiters are taken from the existing rate limiters under `limiter.batch`.
"
+ "If this field is empty, limiter is not used.",
+ undefined)}
].
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
-sc(Type, Default) ->
- hoconsc:mk(Type, #{default => Default}).
+sc(Type, Desc, Default) ->
+ hoconsc:mk(Type, #{default => Default, desc => Desc}).
-sc(Type, Default, Validator) ->
+sc(Type, Desc, Default, Validator) ->
hoconsc:mk(Type, #{default => Default,
+ desc => Desc,
validator => Validator}).
is_pos_integer(V) ->