diff --git a/apps/emqx/etc/emqx.conf b/apps/emqx/etc/emqx.conf index 68d8f359f..4c8113cd5 100644 --- a/apps/emqx/etc/emqx.conf +++ b/apps/emqx/etc/emqx.conf @@ -344,8 +344,8 @@ log { ## ## @doc log.console_handler.level ## ValueType: debug | info | notice | warning | error | critical | alert | emergency - ## Default: debug - console_handler.level = debug + ## Default: warning + console_handler.level = warning ##---------------------------------------------------------------- ## The file log handlers send log messages to files @@ -358,8 +358,8 @@ log { ## ## @doc log.file_handlers..level ## ValueType: debug | info | notice | warning | error | critical | alert | emergency - ## Default: debug - level: debug + ## Default: warning + level: warning ## The log file for specified level. ## @@ -380,18 +380,18 @@ log { ## With this enabled, new log files will be created when the current ## log file is full, max to `rotation_count` files will be created. ## - ## @doc log.file_handlers..rotation + ## @doc log.file_handlers..rotation.enable ## ValueType: Boolean ## Default: true - rotation = true + rotation.enable = true ## Maximum rotation count of log files. ## - ## @doc log.file_handlers..rotation_count + ## @doc log.file_handlers..rotation.count ## ValueType: Integer ## Range: [1, 2048] ## Default: 10 - rotation_count: 10 + rotation.count: 10 ## Maximum size of each log file. ## @@ -411,9 +411,19 @@ log { ## log level for example: file_handlers.emqx_error: { level: error - file: "{{ platform_log_dir }}/emqx.error.log" + file: "{{ platform_log_dir }}/error.log" } + ## Timezone offset to display in logs + ## + ## @doc log.time_offset + ## ValueType: system | utc | String + ## - "system" use system zone + ## - "utc" for Universal Coordinated Time (UTC) + ## - "+hh:mm" or "-hh:mm" for a specified offset + ## Default: system + time_offset = system + ## Limits the total number of characters printed for each log event. ## ## @doc log.chars_limit @@ -421,6 +431,14 @@ log { ## Default: infinity chars_limit: 8192 + ## Maximum depth for Erlang term log formatting + ## and Erlang process message queue inspection. + ## + ## @doc log.max_depth + ## ValueType: Integer | infinity + ## Default: 80 + max_depth = 80 + ## Log formatter ## @doc log.formatter ## ValueType: text | json @@ -477,10 +495,10 @@ log { ## We could kill the log handler in these cases and restart it after a ## few seconds. ## - ## @doc log.overload_kill + ## @doc log.overload_kill.enable ## ValueType: Boolean ## Default: true - overload_kill: true + overload_kill.enable: true ## The max allowed queue length before killing the log hanlder. ## @@ -488,11 +506,11 @@ log { ## length. If the message queue grows larger than this, the handler ## process is terminated. ## - ## @doc log.overload_kill_qlen + ## @doc log.overload_kill.qlen ## ValueType: Integer ## Range: [0, 1048576] ## Default: 20000 - overload_kill_qlen: 20000 + overload_kill.qlen: 20000 ## The max allowed memory size before killing the log hanlder. ## @@ -500,20 +518,20 @@ log { ## that the handler process is allowed to use. If the handler grows ## larger than this, the process is terminated. ## - ## @doc log.overload_kill_mem_size + ## @doc log.overload_kill.mem_size ## ValueType: Size ## Default: 30MB - overload_kill_mem_size: 30MB + overload_kill.mem_size: 30MB ## Restart the log hanlder after some seconds. ## ## Log overload protection parameter. If the handler is terminated, ## it restarts automatically after a delay specified in seconds. ## - ## @doc log.overload_kill_restart_after + ## @doc log.overload_kill.restart_after ## ValueType: Duration ## Default: 5s - overload_kill_restart_after: 5s + overload_kill.restart_after: 5s ## Controlling Bursts of Log Requests. ## @@ -526,26 +544,26 @@ log { ## Note that there would be no warning if any messages were ## dropped because of burst control. ## - ## @doc log.burst_limit + ## @doc log.burst_limit.enable ## ValueType: Boolean ## Default: false - burst_limit: false + burst_limit.enable: false ## This config controls the maximum number of events to handle within ## a time frame. After the limit is reached, successive events are ## dropped until the end of the time frame defined by `window_time`. ## - ## @doc log.burst_limit_max_count + ## @doc log.burst_limit.max_count ## ValueType: Integer ## Default: 10000 - burst_limit_max_count: 10000 + burst_limit.max_count: 10000 ## See the previous description of burst_limit_max_count. ## - ## @doc log.burst_limit_window_time + ## @doc log.burst_limit.window_time ## ValueType: duration ## Default: 1s - burst_limit_window_time: 1s + burst_limit.window_time: 1s } ##================================================================== @@ -577,8 +595,7 @@ rpc { ## ## @doc cluster.discovery_strategy ## ValueType: manual | stateless - ## - manual: discover ports by `tcp_server_port` and - ## `tcp_client_port`. + ## - manual: discover ports by `tcp_server_port`. ## - stateless: discover ports in a stateless manner. ## If node name is `emqx@127.0.0.1`, where the `` is ## an integer, then the listening port will be `5370 + ` @@ -596,26 +613,15 @@ rpc { ## Defaults: 5369 tcp_server_port: 5369 - ## TCP port for outgoing RPC connections. - ## - ## Only takes effect when `rpc.port_discovery` = `manual`. - ## - ## @doc rpc.tcp_client_port - ## ValueType: Integer - ## Range: [1024-65535] - ## Defaults: 5369 - tcp_client_port: 5369 - ## Number of outgoing RPC connections. ## - ## Defaults to "num_cpu_cores", that is, the number of CPU cores. ## Set this to 1 to keep the message order sent from the same ## client. ## ## @doc rpc.tcp_client_num - ## ValueType: Integer | num_cpu_cores + ## ValueType: Integer ## Range: [1, 256] - ## Defaults: num_cpu_cores + ## Defaults: 1 tcp_client_num: 1 ## RCP Client connect timeout. @@ -827,6 +833,13 @@ zone.default { ## Default: true stats.enable: true + ## Maximum number of concurrent connections. + ## + ## @doc zone..listeners..overall_max_connections + ## ValueType: Number | infinity + ## Default: infinity + overall_max_connections: infinity + mqtt { ## When publishing or subscribing, prefix all topics with a mountpoint string. ## The prefixed string will be removed from the topic name when the message @@ -870,7 +883,7 @@ zone.default { ## Maximum length of MQTT clientId allowed. ## ## @doc zone..mqtt.max_clientid_len - ## ValueType: Integer | infinity + ## ValueType: Integer ## Range: [23, 65535] ## Default: 65535 max_clientid_len: 65535 @@ -878,10 +891,10 @@ zone.default { ## Maximum topic levels allowed. ## ## @doc zone..mqtt.max_topic_levels - ## ValueType: Integer | infinity + ## ValueType: Integer ## Range: [1, 65535] - ## Default: infinity - max_topic_levels: infinity + ## Default: 65535 + max_topic_levels: 65535 ## Maximum QoS allowed. ## @@ -893,7 +906,7 @@ zone.default { ## Maximum Topic Alias, 0 means no topic alias supported. ## ## @doc zone..mqtt.max_topic_alias - ## ValueType: Integer | infinity + ## ValueType: Integer ## Range: [0, 65535] ## Default: 65535 max_topic_alias: 65535 @@ -958,11 +971,11 @@ zone.default { ## Default: 0.75 keepalive_backoff: 0.75 - ## Maximum number of subscriptions allowed, 0 means no limit. + ## Maximum number of subscriptions allowed. ## ## @doc zone..mqtt.max_subscriptions ## ValueType: Integer | infinity - ## Range: [0, ) + ## Range: [1, ) ## Default: infinity max_subscriptions: infinity @@ -976,8 +989,8 @@ zone.default { ## Maximum size of the Inflight Window storing QoS1/2 messages delivered but unacked. ## ## @doc zone..mqtt.max_inflight - ## ValueType: Integer | infinity - ## Range: [0, ) + ## ValueType: Integer + ## Range: [1, 65535] ## Default: 32 max_inflight: 32 @@ -988,11 +1001,11 @@ zone.default { ## Default: 30s retry_interval: 30s - ## Maximum QoS2 packets (Client -> Broker) awaiting PUBREL, 0 means no limit. + ## Maximum QoS2 packets (Client -> Broker) awaiting PUBREL. ## ## @doc zone..mqtt.max_awaiting_rel ## ValueType: Integer | infinity - ## Range: [0, ) + ## Range: [1, ) ## Default: 100 max_awaiting_rel: 100 @@ -1011,7 +1024,7 @@ zone.default { session_expiry_interval: 2h ## Maximum queue length. Enqueued messages when persistent client disconnected, - ## or inflight window is full. 0 means no limit. + ## or inflight window is full. ## ## @doc zone..mqtt.max_mqueue_len ## ValueType: Integer | infinity @@ -1117,61 +1130,6 @@ zone.default { cache.ttl: 1m } - rate_limit { - ## Maximum connections per second. - ## - ## @doc zone..max_conn_rate - ## ValueType: Number | infinity - ## Default: 1000 - ## Examples: - ## max_conn_rate: 1000 - max_conn_rate: 1000 - - ## Message limit for the a external MQTT connection. - ## - ## @doc zone..rate_limit.conn_messages_in - ## ValueType: String | infinity - ## Default: infinity - ## Examples: 100 messages per 10 seconds. - ## conn_messages_in: "100,10s" - conn_messages_in: "100,10s" - - ## Limit the rate of receiving packets for a MQTT connection. - ## The rate is counted by bytes of packets per second. - ## - ## The connection won't accept more messages if the messages come - ## faster than the limit. - ## - ## @doc zone..rate_limit.conn_bytes_in - ## ValueType: String | infinity - ## Default: infinity - ## Examples: 100KB incoming per 10 seconds. - ## conn_bytes_in: "100KB,10s" - ## - conn_bytes_in: "100KB,10s" - - ## Messages quota for the each of external MQTT connection. - ## This value consumed by the number of recipient on a message. - ## - ## @doc zone..rate_limit.quota.conn_messages_routing - ## ValueType: String | infinity - ## Default: infinity - ## Examples: 100 messaegs per 1s: - ## quota.conn_messages_routing: "100,1s" - quota.conn_messages_routing: "100,1s" - - ## Messages quota for the all of external MQTT connections. - ## This value consumed by the number of recipient on a message. - ## - ## @doc zone..rate_limit.quota.overall_messages_routing - ## ValueType: String | infinity - ## Default: infinity - ## Examples: 200000 messages per 1s: - ## quota.overall_messages_routing: "200000,1s" - ## - quota.overall_messages_routing: "200000,1s" - } - flapping_detect { ## Enable Flapping Detection. ## @@ -1299,11 +1257,9 @@ zone.default { ## The type of the listener. ## ## @doc zone..listeners..type - ## ValueType: tcp | ssl | ws | wss + ## ValueType: tcp | ws ## - tcp: MQTT over TCP - ## - ssl: MQTT over TLS ## - ws: MQTT over Websocket - ## - wss: MQTT over WebSocket Secure ## Required: true type: tcp @@ -1318,9 +1274,9 @@ zone.default { ## The size of the acceptor pool for this listener. ## ## @doc zone..listeners..acceptors - ## ValueType: Number | num_cpu_cores - ## Default: num_cpu_cores - acceptors: num_cpu_cores + ## ValueType: Number + ## Default: 16 + acceptors: 16 ## Maximum number of concurrent connections. ## @@ -1363,6 +1319,61 @@ zone.default { ## Default: 3s proxy_protocol_timeout: 3s + rate_limit { + ## Maximum connections per second. + ## + ## @doc zone..max_conn_rate + ## ValueType: Number | infinity + ## Default: 1000 + ## Examples: + ## max_conn_rate: 1000 + max_conn_rate: 1000 + + ## Message limit for the a external MQTT connection. + ## + ## @doc zone..rate_limit.conn_messages_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messages per 10 seconds. + ## conn_messages_in: "100,10s" + conn_messages_in: "100,10s" + + ## Limit the rate of receiving packets for a MQTT connection. + ## The rate is counted by bytes of packets per second. + ## + ## The connection won't accept more messages if the messages come + ## faster than the limit. + ## + ## @doc zone..rate_limit.conn_bytes_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100KB incoming per 10 seconds. + ## conn_bytes_in: "100KB,10s" + ## + conn_bytes_in: "100KB,10s" + + ## Messages quota for the each of external MQTT connection. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.conn_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messaegs per 1s: + ## quota.conn_messages_routing: "100,1s" + quota.conn_messages_routing: "100,1s" + + ## Messages quota for the all of external MQTT connections. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.overall_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 200000 messages per 1s: + ## quota.overall_messages_routing: "200000,1s" + ## + quota.overall_messages_routing: "200000,1s" + } + ## TCP options ## See ${example_common_tcp_options} for more information tcp.backlog: 1024 @@ -1377,13 +1388,11 @@ zone.default { ## The type of the listener. ## ## @doc zone..listeners..type - ## ValueType: tcp | ssl | ws | wss + ## ValueType: tcp | ws ## - tcp: MQTT over TCP - ## - ssl: MQTT over TLS ## - ws: MQTT over Websocket - ## - wss: MQTT over WebSocket Secure ## Required: true - type: ssl + type: tcp ## The IP address and port that the listener will bind. ## @@ -1396,9 +1405,9 @@ zone.default { ## The size of the acceptor pool for this listener. ## ## @doc zone..listeners..acceptors - ## ValueType: Number | num_cpu_cores - ## Default: num_cpu_cores - acceptors: num_cpu_cores + ## ValueType: Number + ## Default: 16 + acceptors: 16 ## Maximum number of concurrent connections. ## @@ -1441,8 +1450,64 @@ zone.default { ## Default: 3s proxy_protocol_timeout: 3s + rate_limit { + ## Maximum connections per second. + ## + ## @doc zone..max_conn_rate + ## ValueType: Number | infinity + ## Default: 1000 + ## Examples: + ## max_conn_rate: 1000 + max_conn_rate: 1000 + + ## Message limit for the a external MQTT connection. + ## + ## @doc zone..rate_limit.conn_messages_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messages per 10 seconds. + ## conn_messages_in: "100,10s" + conn_messages_in: "100,10s" + + ## Limit the rate of receiving packets for a MQTT connection. + ## The rate is counted by bytes of packets per second. + ## + ## The connection won't accept more messages if the messages come + ## faster than the limit. + ## + ## @doc zone..rate_limit.conn_bytes_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100KB incoming per 10 seconds. + ## conn_bytes_in: "100KB,10s" + ## + conn_bytes_in: "100KB,10s" + + ## Messages quota for the each of external MQTT connection. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.conn_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messaegs per 1s: + ## quota.conn_messages_routing: "100,1s" + quota.conn_messages_routing: "100,1s" + + ## Messages quota for the all of external MQTT connections. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.overall_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 200000 messages per 1s: + ## quota.overall_messages_routing: "200000,1s" + ## + quota.overall_messages_routing: "200000,1s" + } + ## SSL options ## See ${example_common_ssl_options} for more information + ssl.enable: true ssl.keyfile: "{{ platform_etc_dir }}/certs/key.pem" ssl.certfile: "{{ platform_etc_dir }}/certs/cert.pem" ssl.cacertfile: "{{ platform_etc_dir }}/certs/cacert.pem" @@ -1460,11 +1525,9 @@ zone.default { ## The type of the listener. ## ## @doc zone..listeners..type - ## ValueType: tcp | ssl | ws | wss + ## ValueType: tcp | ws ## - tcp: MQTT over TCP - ## - ssl: MQTT over TLS ## - ws: MQTT over Websocket - ## - wss: MQTT over WebSocket Secure ## Required: true type: ws @@ -1479,9 +1542,9 @@ zone.default { ## The size of the acceptor pool for this listener. ## ## @doc zone..listeners..acceptors - ## ValueType: Number | num_cpu_cores - ## Default: num_cpu_cores - acceptors: num_cpu_cores + ## ValueType: Number + ## Default: 16 + acceptors: 16 ## Maximum number of concurrent connections. ## @@ -1524,6 +1587,61 @@ zone.default { ## Default: 3s proxy_protocol_timeout: 3s + rate_limit { + ## Maximum connections per second. + ## + ## @doc zone..max_conn_rate + ## ValueType: Number | infinity + ## Default: 1000 + ## Examples: + ## max_conn_rate: 1000 + max_conn_rate: 1000 + + ## Message limit for the a external MQTT connection. + ## + ## @doc zone..rate_limit.conn_messages_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messages per 10 seconds. + ## conn_messages_in: "100,10s" + conn_messages_in: "100,10s" + + ## Limit the rate of receiving packets for a MQTT connection. + ## The rate is counted by bytes of packets per second. + ## + ## The connection won't accept more messages if the messages come + ## faster than the limit. + ## + ## @doc zone..rate_limit.conn_bytes_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100KB incoming per 10 seconds. + ## conn_bytes_in: "100KB,10s" + ## + conn_bytes_in: "100KB,10s" + + ## Messages quota for the each of external MQTT connection. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.conn_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messaegs per 1s: + ## quota.conn_messages_routing: "100,1s" + quota.conn_messages_routing: "100,1s" + + ## Messages quota for the all of external MQTT connections. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.overall_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 200000 messages per 1s: + ## quota.overall_messages_routing: "200000,1s" + ## + quota.overall_messages_routing: "200000,1s" + } + ## TCP options ## See ${example_common_tcp_options} for more information tcp.backlog: 1024 @@ -1537,23 +1655,15 @@ zone.default { listeners.mqtt_wss: #${example_common_tcp_options} ${example_common_ssl_options} ${example_common_websocket_options} # common options can be written in a separate config entry and reference it from here. { - ## The name of the listener. - ## - ## @doc zone..listeners..name - ## ValueType: String - ## Required: true - name: mqtt_over_wss ## The type of the listener. ## ## @doc zone..listeners..type - ## ValueType: tcp | ssl | ws | wss + ## ValueType: tcp | ws ## - tcp: MQTT over TCP - ## - ssl: MQTT over TLS ## - ws: MQTT over Websocket - ## - wss: MQTT over WebSocket Secure ## Required: true - type: wss + type: ws ## The IP address and port that the listener will bind. ## @@ -1566,9 +1676,9 @@ zone.default { ## The size of the acceptor pool for this listener. ## ## @doc zone..listeners..acceptors - ## ValueType: Number | num_cpu_cores - ## Default: num_cpu_cores - acceptors: num_cpu_cores + ## ValueType: Number + ## Default: 16 + acceptors: 16 ## Maximum number of concurrent connections. ## @@ -1611,8 +1721,64 @@ zone.default { ## Default: 3s proxy_protocol_timeout: 3s + rate_limit { + ## Maximum connections per second. + ## + ## @doc zone..max_conn_rate + ## ValueType: Number | infinity + ## Default: 1000 + ## Examples: + ## max_conn_rate: 1000 + max_conn_rate: 1000 + + ## Message limit for the a external MQTT connection. + ## + ## @doc zone..rate_limit.conn_messages_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messages per 10 seconds. + ## conn_messages_in: "100,10s" + conn_messages_in: "100,10s" + + ## Limit the rate of receiving packets for a MQTT connection. + ## The rate is counted by bytes of packets per second. + ## + ## The connection won't accept more messages if the messages come + ## faster than the limit. + ## + ## @doc zone..rate_limit.conn_bytes_in + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100KB incoming per 10 seconds. + ## conn_bytes_in: "100KB,10s" + ## + conn_bytes_in: "100KB,10s" + + ## Messages quota for the each of external MQTT connection. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.conn_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 100 messaegs per 1s: + ## quota.conn_messages_routing: "100,1s" + quota.conn_messages_routing: "100,1s" + + ## Messages quota for the all of external MQTT connections. + ## This value consumed by the number of recipient on a message. + ## + ## @doc zone..rate_limit.quota.overall_messages_routing + ## ValueType: String | infinity + ## Default: infinity + ## Examples: 200000 messages per 1s: + ## quota.overall_messages_routing: "200000,1s" + ## + quota.overall_messages_routing: "200000,1s" + } + ## SSL options ## See ${example_common_ssl_options} for more information + ssl.enable: true ssl.keyfile: "{{ platform_etc_dir }}/certs/key.pem" ssl.certfile: "{{ platform_etc_dir }}/certs/cert.pem" ssl.cacertfile: "{{ platform_etc_dir }}/certs/cacert.pem" diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index a2644f353..292d5569a 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -87,7 +87,7 @@ fields("cluster") -> ]; fields("static") -> - [ {"seeds", t(list(string()))}]; + [ {"seeds", t(hoconsc:array(string()))}]; fields("mcast") -> [ {"addr", t(string(), undefined, "239.192.0.1")} @@ -164,46 +164,56 @@ fields("rpc") -> ]; fields("log") -> - [ {"to", t(union([file, console, both]), undefined, file)} - , {"level", t(log_level(), undefined, warning)} + [ {"primary_level", t(log_level(), undefined, warning)} + , {"console_handler", ref("console_handler")} + , {"file_handlers", ref("file_handlers")} , {"time_offset", t(string(), undefined, "system")} - , {"primary_log_level", t(log_level(), undefined, warning)} - , {"dir", t(string(), undefined, "log")} - , {"file", t(file(), undefined, "emqx.log")} - , {"chars_limit", t(integer(), undefined, -1)} + , {"chars_limit", maybe_infinity(integer())} , {"supervisor_reports", t(union([error, progress]), undefined, error)} , {"max_depth", t(union([infinity, integer()]), "kernel.error_logger_format_depth", 80)} , {"formatter", t(union([text, json]), undefined, text)} , {"single_line", t(boolean(), undefined, true)} - , {"rotation", ref("rotation")} - , {"size", t(union(bytesize(), infinity), undefined, infinity)} , {"sync_mode_qlen", t(integer(), undefined, 100)} , {"drop_mode_qlen", t(integer(), undefined, 3000)} , {"flush_qlen", t(integer(), undefined, 8000)} - , {"overload_kill", t(flag(), undefined, true)} - , {"overload_kill_mem_size", t(bytesize(), undefined, "30MB")} - , {"overload_kill_qlen", t(integer(), undefined, 20000)} - , {"overload_kill_restart_after", t(union(duration(), infinity), undefined, "5s")} - , {"burst_limit", t(comma_separated_list(), undefined, "disabled")} + , {"overload_kill", ref("log_overload_kill")} + , {"burst_limit", ref("log_burst_limit")} , {"error_logger", t(atom(), "kernel.error_logger", silent)} - , {"debug", ref("additional_log_file")} - , {"info", ref("additional_log_file")} - , {"notice", ref("additional_log_file")} - , {"warning", ref("additional_log_file")} - , {"error", ref("additional_log_file")} - , {"critical", ref("additional_log_file")} - , {"alert", ref("additional_log_file")} - , {"emergency", ref("additional_log_file")} ]; -fields("additional_log_file") -> - [ {"file", t(string())}]; +fields("console_handler") -> + [ {"enable", t(flag(), undefined, false)} + , {"level", t(log_level(), undefined, warning)} + ]; -fields("rotation") -> +fields("file_handlers") -> + [ {"$name", ref("log_file_handler")} + ]; + +fields("log_file_handler") -> + [ {"level", t(log_level(), undefined, warning)} + , {"file", t(file(), undefined, undefined)} + , {"rotation", ref("log_rotation")} + , {"max_size", maybe_infinity(bytesize(), "10MB")} + ]; + +fields("log_rotation") -> [ {"enable", t(flag(), undefined, true)} - , {"size", t(bytesize(), undefined, "10MB")} - , {"count", t(integer(), undefined, 5)} + , {"count", t(range(1, 2048), undefined, 10)} + ]; + +fields("log_overload_kill") -> + [ {"enable", t(flag(), undefined, true)} + , {"mem_size", t(bytesize(), undefined, "30MB")} + , {"qlen", t(integer(), undefined, 20000)} + , {"restart_after", t(union(duration(), infinity), undefined, "5s")} + ]; + +fields("log_burst_limit") -> + [ {"enable", t(flag(), undefined, true)} + , {"max_count", t(integer(), undefined, 10000)} + , {"window_time", t(duration(), undefined, "1s")} ]; fields("lager") -> @@ -227,16 +237,16 @@ fields("acl") -> fields("acl_cache") -> [ {"enable", t(boolean(), undefined, true)} - , {"max_size", t(range(1, 1048576), undefined, 32)} + , {"max_size", maybe_infinity(range(1, 1048576), 32)} , {"ttl", t(duration(), undefined, "1m")} ]; fields("mqtt") -> [ {"mountpoint", t(binary(), undefined, <<"">>)} - , {"idle_timeout", t(duration(), undefined, "15s")} - , {"max_packet_size", t(bytesize(), undefined, "1MB")} + , {"idle_timeout", maybe_infinity(duration(), "15s")} + , {"max_packet_size", maybe_infinity(bytesize(), "1MB")} , {"max_clientid_len", t(integer(), undefined, 65535)} - , {"max_topic_levels", t(integer(), undefined, 0)} + , {"max_topic_levels", t(integer(), undefined, 65535)} , {"max_qos_allowed", t(range(0, 2), undefined, 2)} , {"max_topic_alias", t(integer(), undefined, 65535)} , {"retain_available", t(boolean(), undefined, true)} @@ -245,16 +255,16 @@ fields("mqtt") -> , {"ignore_loop_deliver", t(boolean())} , {"strict_mode", t(boolean(), undefined, false)} , {"response_information", t(string(), undefined, undefined)} - , {"server_keepalive", t(integer())} + , {"server_keepalive", maybe_disabled(integer())} , {"keepalive_backoff", t(float(), undefined, 0.75)} - , {"max_subscriptions", t(integer(), undefined, 0)} + , {"max_subscriptions", maybe_infinity(integer())} , {"upgrade_qos", t(flag(), undefined, false)} - , {"max_inflight", t(range(0, 65535))} + , {"max_inflight", t(range(1, 65535))} , {"retry_interval", t(duration_s(), undefined, "30s")} - , {"max_awaiting_rel", t(duration(), undefined, 0)} + , {"max_awaiting_rel", maybe_infinity(duration())} , {"await_rel_timeout", t(duration_s(), undefined, "300s")} , {"session_expiry_interval", t(duration_s(), undefined, "2h")} - , {"max_mqueue_len", t(integer(), undefined, 1000)} + , {"max_mqueue_len", maybe_infinity(integer(), 1000)} , {"mqueue_priorities", t(comma_separated_list(), undefined, "none")} , {"mqueue_default_priority", t(union(highest, lowest), undefined, lowest)} , {"mqueue_store_qos0", t(boolean(), undefined, true)} @@ -275,20 +285,20 @@ fields("zone_settings") -> , {"force_shutdown", ref("force_shutdown")} , {"conn_congestion", ref("conn_congestion")} , {"force_gc", ref("force_gc")} - , {"overall_max_connections", t(integer(), undefined, 2048000)} + , {"overall_max_connections", maybe_infinity(integer())} , {"listeners", t("listeners")} ]; fields("rate_limit") -> [ {"max_conn_rate", maybe_infinity(integer(), 1000)} - , {"conn_messages_in", t(comma_separated_list())} - , {"conn_bytes_in", t(comma_separated_list())} + , {"conn_messages_in", maybe_infinity(comma_separated_list())} + , {"conn_bytes_in", maybe_infinity(comma_separated_list())} , {"quota", ref("rate_limit_quota")} ]; fields("rate_limit_quota") -> - [ {"conn_messages_routing", t(comma_separated_list())} - , {"overall_messages_routing", t(comma_separated_list())} + [ {"conn_messages_routing", maybe_infinity(comma_separated_list())} + , {"overall_messages_routing", maybe_infinity(comma_separated_list())} ]; fields("flapping_detect") -> @@ -331,32 +341,19 @@ fields("force_gc") -> fields("listeners") -> [ {"$name", hoconsc:union( - [ ref("mqtt_tcp_listener") - , ref("mqtt_ssl_listener") - , ref("mqtt_ws_listener") - , ref("mqtt_wss_listener") + [ hoconsc:ref("mqtt_tcp_listener") + , hoconsc:ref("mqtt_ws_listener") ])} ]; fields("mqtt_tcp_listener") -> - [ {"type", t(typerefl:atom(tcp))} + [ {"type", t(tcp)} , {"tcp", ref("tcp_opts")} - ] ++ mqtt_listener(); - -fields("mqtt_ssl_listener") -> - [ {"type", t(typerefl:atom(ssl))} , {"ssl", ref("ssl_opts")} - , {"tcp", ref("tcp_opts")} ] ++ mqtt_listener(); fields("mqtt_ws_listener") -> - [ {"type", t(typerefl:atom(ws))} - , {"tcp", ref("tcp_opts")} - , {"websocket", ref("ws_opts")} - ] ++ mqtt_listener(); - -fields("mqtt_wss_listener") -> - [ {"type", t(typerefl:atom(ws))} + [ {"type", t(ws)} , {"tcp", ref("tcp_opts")} , {"ssl", ref("ssl_opts")} , {"websocket", ref("ws_opts")} @@ -366,8 +363,8 @@ fields("ws_opts") -> [ {"mqtt_path", t(string(), undefined, "/mqtt")} , {"mqtt_piggyback", t(union(single, multiple), undefined, multiple)} , {"compress", t(boolean())} - , {"idle_timeout", t(duration())} - , {"max_frame_size", t(integer())} + , {"idle_timeout", maybe_infinity(duration())} + , {"max_frame_size", maybe_infinity(integer())} , {"fail_if_no_subprotocol", t(boolean(), undefined, true)} , {"supported_subprotocols", t(string(), undefined, "mqtt, mqtt-v3, mqtt-v3.1.1, mqtt-v5")} @@ -480,7 +477,7 @@ fields("sysmon_os") -> [ {"cpu_check_interval", t(duration_s(), undefined, 60)} , {"cpu_high_watermark", t(percent(), undefined, "80%")} , {"cpu_low_watermark", t(percent(), undefined, "60%")} - , {"mem_check_interval", t(duration_s(), undefined, 60)} + , {"mem_check_interval", maybe_disabled(duration_s(), 60)} , {"sysmem_high_watermark", t(percent(), undefined, "70%")} , {"procmem_high_watermark", t(percent(), undefined, "5%")} ]; @@ -503,9 +500,10 @@ fields(ExtraField) -> mqtt_listener() -> [ {"bind", t(union(ip_port(), integer()))} - , {"acceptors", t(integer(), undefined, 8)} - , {"max_connections", t(integer(), undefined, 1024000)} - , {"access", t(list(string()))} + , {"acceptors", t(integer(), undefined, 16)} + , {"max_connections", maybe_infinity(integer(), infinity)} + , {"rate_limit", ref("rate_limit")} + , {"access_rules", t(hoconsc:array(string()))} , {"proxy_protocol", t(flag())} , {"proxy_protocol_timeout", t(duration())} ]. @@ -1050,7 +1048,8 @@ filter(Opts) -> %% ...] ssl(Defaults) -> D = fun (Field) -> maps:get(list_to_atom(Field), Defaults, undefined) end, - [ {"cacertfile", t(string(), undefined, D("cacertfile"))} + [ {"enable", t(flag(), undefined, D("enable"))} + , {"cacertfile", t(string(), undefined, D("cacertfile"))} , {"certfile", t(string(), undefined, D("certfile"))} , {"keyfile", t(string(), undefined, D("keyfile"))} , {"verify", t(union(verify_peer, verify_none), undefined, D("verify"))} @@ -1176,8 +1175,8 @@ maybe_disabled(T) -> maybe_disabled(T, Default) -> maybe_sth(disabled, T, Default). -% maybe_infinity(T) -> -% maybe_sth(infinity, T, infinity). +maybe_infinity(T) -> + maybe_sth(infinity, T, infinity). maybe_infinity(T, Default) -> maybe_sth(infinity, T, Default). @@ -1215,7 +1214,7 @@ to_bytesize(Str) -> to_wordsize(Str) -> WordSize = erlang:system_info(wordsize), case to_bytesize(Str) of - {ok, Bytes} -> Bytes div WordSize; + {ok, Bytes} -> {ok, Bytes div WordSize}; Error -> Error end. diff --git a/bin/emqx b/bin/emqx index a5f76ac72..70b878715 100755 --- a/bin/emqx +++ b/bin/emqx @@ -582,7 +582,7 @@ case "$1" in # set before generate_config if [ "${_EMQX_START_MODE:-}" = '' ]; then - export EMQX_LOG__TO="${EMQX_LOG__TO:-console}" + export EMQX_CONSOLE_HANDLER__ENABLE="${EMQX_CONSOLE_HANDLER__ENABLE:-true}" fi #generate app.config and vm.args @@ -626,7 +626,7 @@ case "$1" in # or other supervision services # set before generate_config - export EMQX_LOG__TO="${EMQX_LOG__TO:-console}" + export EMQX_CONSOLE_HANDLER__ENABLE="${EMQX_CONSOLE_HANDLER__ENABLE:-true}" #generate app.config and vm.args generate_config