diff --git a/apps/emqx_conf/i18n/emqx_conf_schema.conf b/apps/emqx_conf/i18n/emqx_conf_schema.conf index 851b33062..282191ece 100644 --- a/apps/emqx_conf/i18n/emqx_conf_schema.conf +++ b/apps/emqx_conf/i18n/emqx_conf_schema.conf @@ -1,470 +1,553 @@ emqx_conf_schema { - cluster_name { - desc { - en: """Human-friendly name of the EMQX cluster.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_name { + desc { + en: """Human-friendly name of the EMQX cluster.""" + zh: """EMQX集群名称。每个集群都有一个唯一的名称。服务发现时会用于做路径的一部分。""" + } + label { + en: "Cluster Name" + zh: "集群名称" + } + } - cluster_discovery_strategy { - desc { - en: """Service discovery method for the cluster nodes.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_discovery_strategy { + desc { + en: """Service discovery method for the cluster nodes.""" + zh: """集群节点发现方式。可选值为: +- manual: 手动加入集群<\br> +- static: 配置静态节点。配置几个固定的节点,新节点通过连接固定节点中的某一个来加入集群。<\br> +- mcast: 使用 UDP 多播的方式发现节点。<\br> +- dns: 使用 DNS A 记录的方式发现节点。<\br> +- etcd: 使用 etcd 发现节点。<\br> +- k8s: 使用 Kubernetes 发现节点。<\br> + """ + } + label { + en: "Cluster Discovery Strategy" + zh: "集群服务发现策略" + } + } - cluster_autoclean { - desc { - en: """Remove disconnected nodes from the cluster after this interval.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_autoclean { + desc { + en: """Remove disconnected nodes from the cluster after this interval.""" + zh: """指定多久之后从集群中删除离线节点。""" + } + label { + en: "Cluster Auto Clean" + zh: "自动删除离线节点时间" + } + } - cluster_autoheal { - desc { - en: """If true, the node will try to heal network partitions - automatically.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_autoheal { + desc { + en: """If true, the node will try to heal network partitions automatically.""" + zh: """集群脑裂自动恢复机制开关。""" + } + label { + en: "Cluster Auto Heal" + zh: "节点脑裂自动修复机制" + } + } - cluster_proto_dist { - desc { - en: """The Erlang distribution protocol for the cluster.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_proto_dist { + desc { + en: """The Erlang distribution protocol for the cluster.""" + zh: """分布式 Erlang 集群协议类型。可选值为: +- inet_tcp: 使用 IPv4 <\br> +- inet6_tcp 使用 IPv6 <\br> +- inet_tls: 使用 TLS,需要与 node.ssl_dist_optfile 配置一起使用。<\br> + """ + } + label { + en: "Cluster Protocol Distribution" + zh: "集群内部通信协议" + } + } - cluster_static_seeds { - desc { - en: """List EMQX node names in the static cluster. See node.name.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_static_seeds { + desc { + en: """List EMQX node names in the static cluster. See node.name.""" + zh: """集群中的EMQX节点名称列表, +指定固定的节点列表,多个节点间使用逗号 , 分隔。 +当 cluster.discovery_strategy 为 static 时,此配置项才有效。 +适合于节点数量较少且固定的集群。 + """ + } + label { + en: "Cluster Static Seeds" + zh: "集群静态节点" + } + } - cluster_mcast_addr { - desc { - en: """Multicast IPv4 address.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_addr { + desc { + en: """Multicast IPv4 address.""" + zh: """指定多播 IPv4 地址。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Multicast Address" + zh: "多播地址" + } + } - cluster_mcast_ports { - desc { - en: """List of UDP ports used for service discovery.
-Note: probe messages are broadcast to all the specified ports.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_ports { + desc { + en: """List of UDP ports used for service discovery.
+Note: probe messages are broadcast to all the specified ports. + """ + zh: """指定多播端口。如有多个端口使用逗号 , 分隔。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Multicast Ports" + zh: "多播端口" + } + } - cluster_mcast_iface { - desc { - en: """Local IP address the node discovery service needs to bind to.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_iface { + desc { + en: """Local IP address the node discovery service needs to bind to.""" + zh: """指定节点发现服务需要绑定到本地 IP 地址。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Multicast Interface" + zh: "多播绑定地址" + } + } - cluster_mcast_ttl { - desc { - en: """Time-to-live (TTL) for the outgoing UDP datagrams.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_ttl { + desc { + en: """Time-to-live (TTL) for the outgoing UDP datagrams.""" + zh: """指定多播的 Time-To-Live 值。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Multicast TTL" + zh: "多播TTL" + } + } - cluster_mcast_loop { - desc { - en: """If true, loop UDP datagrams back to the local socket.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_loop { + desc { + en: """If true, loop UDP datagrams back to the local socket.""" + zh: """设置多播的报文是否投递到本地回环地址。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Multicast Loop" + zh: "多播回环开关" + } + } - cluster_mcast_sndbuf { - desc { - en: """Size of the kernel-level buffer for outgoing datagrams.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_sndbuf { + desc { + en: """Size of the kernel-level buffer for outgoing datagrams.""" + zh: """外发数据报的内核级缓冲区的大小。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Muticast Sendbuf" + zh: "多播发送缓存区" + } + } - cluster_mcast_recbuf { - desc { - en: """Size of the kernel-level buffer for incoming datagrams.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_recbuf { + desc { + en: """Size of the kernel-level buffer for incoming datagrams.""" + zh: """接收数据报的内核级缓冲区的大小。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Muticast Sendbuf" + zh: "多播接收数据缓冲区" + } + } - cluster_mcast_buffer { - desc { - en: """Size of the user-level buffer.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_mcast_buffer { + desc { + en: """Size of the user-level buffer.""" + zh: """用户级缓冲区的大小。 +当 cluster.discovery_strategy 为 mcast 时,此配置项才有效。 + """ + } + label { + en: "Cluster Muticast Buffer" + zh: "多播用户级缓冲区" + } + } - cluster_dns_name { - desc { - en: """The domain name of the EMQX cluster.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_dns_name { + desc { + en: """The domain name of the EMQX cluster.""" + zh: """指定 DNS A 记录的名字。emqx 会通过访问这个 DNS A 记录来获取 IP 地址列表, +然后拼接 cluster.dns.app 里指定的 APP 名得到集群中所有节点的列表。 +当 cluster.discovery_strategy 为 dns 时,此配置项才有效。 + """ + } + label { + en: "Cluster Dns Name" + zh: "DNS名称" + } + } - cluster_dns_app { - desc { - en: """The symbolic name of the EMQX service.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_dns_app { + desc { + en: """The symbolic name of the EMQX service.""" + zh: """用来与从 cluster.dns.name 获取的 IP 列表拼接得到节点名列表。 +当 cluster.discovery_strategy 为 dns 时,此配置项才有效。 + """ + } + label { + en: "Cluster DNS App" + zh: "DNS前缀标识" + } + } - cluster_etcd_server { - desc { - en: """List of endpoint URLs of the etcd cluster""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_etcd_server { + desc { + en: """List of endpoint URLs of the etcd cluster""" + zh: """指定 etcd 服务的地址。如有多个服务使用逗号 , 分隔。 +当 cluster.discovery_strategy 为 etcd 时,此配置项才有效。 + """ + } + label { + en: "Cluster Etcd Server" + zh: "Etcd 服务器地址" + } + } - cluster_etcd_prefix { - desc { - en: """Key prefix used for EMQX service discovery.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_etcd_prefix { + desc { + en: """Key prefix used for EMQX service discovery.""" + zh: """指定 etcd 路径的前缀。每个节点在 etcd 中都会创建一个路径: +v2/keys/// <\br> +当 cluster.discovery_strategy 为 etcd 时,此配置项才有效。 + """ + } + label { + en: "Cluster Etcd Prefix" + zh: "Etcd 路径前缀" + } + } - cluster_etcd_node_ttl { - desc { - en: """Expiration time of the etcd key associated with the node. -It is refreshed automatically, as long as the node is alive.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_etcd_node_ttl { + desc { + en: """Expiration time of the etcd key associated with the node. +It is refreshed automatically, as long as the node is alive. + """ + zh: """指定 etcd 中节点信息的过期时间。 +当 cluster.discovery_strategy 为 etcd 时,此配置项才有效。 + """ + } + label { + en: "Cluster Etcd Node TTL" + zh: "Etcd 节点过期时间" + } + } - cluster_etcd_ssl { - desc { - en: """Options for the TLS connection to the etcd cluster.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_etcd_ssl { + desc { + en: """Options for the TLS connection to the etcd cluster.""" + zh: """当使用 TLS 连接 etcd 时的配置选项。 +当 cluster.discovery_strategy 为 etcd 时,此配置项才有效。 + """ + } + label { + en: "Cluster Etcd SSL Option" + zh: "Etcd SSL 选项" + } + } - cluster_k8s_apiserver { - desc { - en: """Kubernetes API endpoint URL.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_k8s_apiserver { + desc { + en: """Kubernetes API endpoint URL.""" + zh: """指定 Kubernetes API Server。如有多个 Server 使用逗号 , 分隔。 +当 cluster.discovery_strategy 为 k8s 时,此配置项才有效。 + """ + } + label { + en: "Cluster k8s ApiServer" + zh: "K8s 服务地址" + } + } - cluster_k8s_service_name { - desc { - en: """EMQX broker service name.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_k8s_service_name { + desc { + en: """EMQX broker service name.""" + zh: """指定 Kubernetes 中 EMQX 的服务名。 +当 cluster.discovery_strategy 为 k8s 时,此配置项才有效。 + """ + } + label { + en: "K8s Service Name" + zh: "K8s 服务别名" + } + } - cluster_k8s_address_type { - desc { - en: """Address type used for connecting to the discovered nodes.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_k8s_address_type { + desc { + en: """Address type used for connecting to the discovered nodes.""" + zh: """当使用 k8s 方式集群时,address_type 用来从 Kubernetes 接口的应答里获取什么形式的 Host 列表。 +指定 cluster.k8s.address_type 为 ip,则将从 Kubernetes 接口中获取 emqx 服务的 IP 地址列表: +- 172.16.122.31 <\br> +- 172.16.122.32 <\br> +- 172.16.122.33 <\br> +然后与 cluster.k8s.app_name 配置指定的 app name 拼接,得到 emqx 节点列表: <\br> +- emqx@172.16.122.31 +- emqx@172.16.122.32 +- emqx@172.16.122.33 + """ + } + label { + en: "K8s Address Type" + zh: "K8s 地址类型" + } + } - cluster_k8s_app_name { - desc { - en: """This parameter should be set to the part of the node.name + cluster_k8s_app_name { + desc { + en: """This parameter should be set to the part of the node.name before the '@'.
For example, if the node.name is emqx@127.0.0.1, then this parameter should be set to emqx.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """app_name 用来跟获取的 Host 列表拼接,得到节点列表。<\br> +当 cluster.discovery_strategy 为 k8s 时,此配置项才有效。 + """ + } + label { + en: "K8s App Name" + zh: "K8s 节点名前缀" + } + } - cluster_k8s_namespace { - desc { - en: """Kubernetes namespace.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_k8s_namespace { + desc { + en: """Kubernetes namespace.""" + zh: """当使用 k8s 方式并且 cluster.k8s.address_type 指定为 dns 类型时, +可设置 emqx 节点名的命名空间。与 cluster.k8s.suffix 一起使用用以拼接得到节点名列表。 + """ + } + label { + en: "K8s Namespace" + zh: "K8s 命名空间" + } + } - cluster_k8s_suffix { - desc { - en: """Node name suffix.
+ cluster_k8s_suffix { + desc { + en: """Node name suffix.
Note: this parameter is only relevant when address_type is dns or hostname.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """当使用 k8s 方式并且 cluster.k8s.address_type 指定为 dns 类型时,可设置 emqx 节点名的后缀。 +与 cluster.k8s.namespace 一起使用用以拼接得到节点名列表。 + """ + } + label { + en: "K8s Suffix" + zh: "K8s 前缀" + } + } - node_name { - desc { - en: """Unique name of the EMQX node. It must follow %name%@FQDN or - %name%@IPv4 format.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_name { + desc { + en: """Unique name of the EMQX node. It must follow %name%@FQDN or +%name%@IPv4 format. + """ + zh: """节点名。格式为 @。其中 可以是 IP 地址,也可以是 FQDN。 +详见 http://erlang.org/doc/reference_manual/distributed.html。 + """ + } + label { + en: "Node Name" + zh: "节点名" + } + } - node_cookie { - desc { - en: """Secret cookie is a random string that should be the same on all nodes in - the given EMQX cluster, but unique per EMQX cluster. It is used to prevent EMQX nodes that - belong to different clusters from accidentally connecting to each other.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_cookie { + desc { + en: """Secret cookie is a random string that should be the same on all nodes in +the given EMQX cluster, but unique per EMQX cluster. It is used to prevent EMQX nodes that +belong to different clusters from accidentally connecting to each other.""" + zh: """分布式 Erlang 集群使用的 cookie 值。集群间保持一致""" + } + label { + en: "Node Cookie" + zh: "节点 Cookie" + } + } - node_data_dir { - desc { - en: """ -Path to the persistent data directory. -Possible auto-created subdirectories are: - - `mnesia/`: EMQX's built-in database directory. - For example, `mnesia/emqx@127.0.0.1`. - There should be only one such subdirectory. - Meaning, in case the node is to be renamed (to e.g. `emqx@10.0.1.1`), - the old dir should be deleted first. - - `configs`: Generated configs at boot time, and cluster/local override configs. - - `patches`: Hot-patch beam files are to be placed here. - - `trace`: Trace log files. + node_data_dir { + desc { + en: """ +Path to the persistent data directory.<\br> +Possible auto-created subdirectories are:<\br> +- `mnesia/`: EMQX's built-in database directory.<\br> +For example, `mnesia/emqx@127.0.0.1`.<\br> +There should be only one such subdirectory.<\br> +Meaning, in case the node is to be renamed (to e.g. `emqx@10.0.1.1`),<\br> +the old dir should be deleted first.<\br> +- `configs`: Generated configs at boot time, and cluster/local override configs.<\br> +- `patches`: Hot-patch beam files are to be placed here.<\br> +- `trace`: Trace log files.<\br> **NOTE**: One data dir cannot be shared by two or more EMQX nodes. """ - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """ +节点数据存放目录,可能会自动创建的子目录如下:<\br> +- `mnesia/`。EMQX的内置数据库目录。例如,`mnesia/emqx@127.0.0.1`。<\br> +如果节点要被重新命名(例如,`emqx@10.0.1.1`)。旧目录应该首先被删除。<\br> +- `configs`。在启动时生成的配置,以及集群/本地覆盖的配置。<\br> +- `patches`: 热补丁文件将被放在这里。<\br> +- `trace`: 日志跟踪文件。<\br> - node_config_files { - desc { - en: """List of configuration files that are read during startup. The order is - significant: later configuration files override the previous ones.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } +**注意**: 一个数据dir不能被两个或更多的EMQX节点同时使用。 + """ + } + label { + en: "Node Data Dir" + zh: "节点数据目录" + } + } - node_global_gc_interval { - desc { - en: """Periodic garbage collection interval.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_config_files { + desc { + en: """List of configuration files that are read during startup. The order is +significant: later configuration files override the previous ones. + """ + zh: """启动时读取的配置文件列表。后面的配置文件项覆盖前面的文件。""" + } + label { + en: "Config Files" + zh: "配置文件" + } + } - node_crash_dump_file { - desc { - en: """Location of the crash dump file""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_global_gc_interval { + desc { + en: """Periodic garbage collection interval.""" + zh: """系统调优参数,设置节点运行多久强制进行一次全局垃圾回收。""" + } + label { + en: "Global GC Interval" + zh: "全局垃圾回收" + } + } - node_crash_dump_seconds { - desc { - en: """The number of seconds that the broker is allowed to spend writing -a crash dump""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_crash_dump_file { + desc { + en: """Location of the crash dump file.""" + zh: """设置 Erlang crash_dump 文件的存储路径和文件名。""" + } + label { + en: "Crash Dump File" + zh: "节点崩溃时的Dump文件" + } + } - node_crash_dump_bytes { - desc { - en: """The maximum size of a crash dump file in bytes.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_crash_dump_seconds { + desc { + en: """The number of seconds that the broker is allowed to spend writing a crash dump.""" + zh: """保存崩溃文件最大允许时间,如果文件太大,在规则时间内没有保存完成,则会直接结束。""" + } + label { + en: "Crash Dump Seconds" + zh: "保存崩溃文件最长时间" + } + } - node_dist_net_ticktime { - desc { - en: """This is the approximate time an EMQX node may be unresponsive until it is considered down and thereby disconnected.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_crash_dump_bytes { + desc { + en: """The maximum size of a crash dump file in bytes.""" + zh: """限制崩溃文件的大小,当崩溃时节点内存太大, +如果为了保存现场,需要全部存到崩溃文件中,此处限制最多能保存多大的文件。 + """ + } + label { + en: "Crash Dump Bytes" + zh: "崩溃文件最大容量" + } + } - node_backtrace_depth { - desc { - en: """Maximum depth of the call stack printed in error messages and - process_info.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_dist_net_ticktime { + desc { + en: """This is the approximate time an EMQX node may be unresponsive until it is considered down and thereby disconnected.""" + zh: """系统调优参数,此配置将覆盖 vm.args 文件里的 -kernel net_ticktime 参数。当一个节点持续无响应多久之后,认为其已经宕机并断开连接。 + """ + } + label { + en: "Dist Net TickTime" + zh: "节点间心跳间隔" + } + } - node_applications { - desc { - en: """List of Erlang applications that shall be rebooted when the EMQX broker joins - the cluster.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_backtrace_depth { + desc { + en: """Maximum depth of the call stack printed in error messages and +process_info. + """ + zh: """错误信息中打印的最大堆栈层数""" + } + label { + en: "BackTrace Depth" + zh: "最大堆栈导数" + } + } - node_etc_dir { - desc { - en: """etc dir for the node""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + node_applications { + desc { + en: """List of Erlang applications that shall be rebooted when the EMQX broker joins the cluster. + """ + zh: """当新EMQX 加入集群时,应重启的Erlang应用程序的列表。""" + } + label { + en: "Application" + zh: "应用" + } + } - db_backend { - desc { - en: """ + node_etc_dir { + desc { + en: """etc dir for the node""" + zh: """etc 存放目录""" + } + label { + en: "Etc Dir" + zh: "Etc 目录" + } + } + + db_backend { + desc { + en: """ Select the backend for the embedded database.
rlog is the default backend, that is suitable for very large clusters.
mnesia is a backend that offers decent performance in small clusters. """ - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """ rlog是默认的数据库,他适用于大规模的集群。 +mnesia是备选数据库,在小集群中提供了很好的性能。 + """ + } + label { + en: "DB Backend" + zh: "内置数据库" + } + } - db_role { - desc { - en: """ + db_role { + desc { + en: """ Select a node role.
core nodes provide durability of the data, and take care of writes. It is recommended to place core nodes in different racks or different availability zones.
@@ -474,17 +557,23 @@ It is recommended to have more replicant nodes than core nodes.
Note: this parameter only takes effect when the backend is set to rlog. """ - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """ +选择节点的角色。
+core 节点提供数据的持久性,并负责写入。建议将核心节点放置在不同的机架或不同的可用区。
+repliant 节点是临时工作节点。 从集群中删除它们,不影响数据库冗余
+建议复制节点多于核心节点。
+注意:该参数仅在设置backend时生效到 rlog。 + """ + } + label { + en: "DB Role" + zh: "数据库角色" + } + } - db_core_nodes { - desc { - en: """ + db_core_nodes { + desc { + en: """ List of core nodes that the replicant will connect to.
Note: this parameter only takes effect when the backend is set to rlog and the role is set to replicant.
@@ -492,713 +581,759 @@ This value needs to be defined for manual or static cluster discovery mechanisms If an automatic cluster discovery mechanism is being used (such as etcd), there is no need to set this value. """ - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """当前节点连接的核心节点列表。
+注意:该参数仅在设置backend时生效到 rlog +并且设置rolereplicant时生效。
+该值需要在手动或静态集群发现机制下设置。
+如果使用了自动集群发现机制(如etcd),则不需要设置该值。 + """ + } + label { + en: "Db Core Node" + zh: "数据库核心节点" + } + } - db_rpc_module { - desc { - en: """ -Protocol used for pushing transaction logs to the replicant nodes. -""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + db_rpc_module { + desc { + en: """Protocol used for pushing transaction logs to the replicant nodes.""" + zh: """集群间推送事务日志到复制节点使用的协议。""" + } + label { + en: "RPC Module" + zh: "RPC协议" + } + } - db_tlog_push_mode { - desc { - en: """ + db_tlog_push_mode { + desc { + en: """ In sync mode the core node waits for an ack from the replicant nodes before sending the next transaction log entry. """ - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """同步模式下,核心节点等待复制节点的确认信息,然后再发送下一条事务日志。""" + } + label { + en: "Tlog Push Mode" + zh: "Tlog推送模式" + } + } - db_default_shard_transport { - desc { - en: """Defines the default transport for pushing transaction logs.
This may be overridden on a per-shard basis in db.shard_transports.gen_rpc uses the gen_rpc library, distr uses the Erlang distribution.
""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + db_default_shard_transport { + desc { + en: """Defines the default transport for pushing transaction logs.
+This may be overridden on a per-shard basis in db.shard_transports. +gen_rpc uses the gen_rpc library, +distr uses the Erlang distribution.
""" + zh: """ +定义用于推送事务日志的默认传输。
+这可以在 db.shard_transports 中基于每个分片被覆盖。 +gen_rpc 使用 gen_rpc 库, +distr 使用 Erlang 发行版。
+ """ + } + label { + en: "Default Shard Transport" + zh: "日志传输默认协议" + } + } - db_shard_transports { - desc { - en: """Allows to tune the transport method used for transaction log replication, on a per-shard basis.
gen_rpc uses the gen_rpc library, distr uses the Erlang distribution.
If not specified, the default is to use the value set in db.default_shard_transport.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + db_shard_transports { + desc { + en: """Allows to tune the transport method used for transaction log replication, on a per-shard basis.
+gen_rpc uses the gen_rpc library, +distr uses the Erlang distribution.
If not specified, +the default is to use the value set in db.default_shard_transport.""" + zh: """ +把事务日志复制到每个分片时的传输方法。
+gen_rpc 使用 gen_rpc 库, +distr 使用 Erlang 发行版。
如果未指定, +默认是使用 db.default_shard_transport 中设置的值。 + """ + } + label { + en: "Shard Transports" + zh: "事务日志复制模式" + } + } - cluster_call_retry_interval { - desc { - en: """Time interval to retry after a failed call.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_call_retry_interval { + desc { + en: """Time interval to retry after a failed call.""" + zh: """当集群间调用出错时,多长时间重试一次。""" + } + label { + en: "Cluster Call Retry Interval" + zh: "重试时间间隔" + } + } - cluster_call_max_history { - desc { - en: """Retain the maximum number of completed transactions (for queries).""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + cluster_call_max_history { + desc { + en: """Retain the maximum number of completed transactions (for queries).""" + zh: """集群间调用最多保留的历史记录数。只用于排错时查看。""" + } + label { + en: "Cluster Call Max History" + zh: "最大历史记录" + } + } - cluster_call_cleanup_interval { - desc { - en: """Time interval to clear completed but stale transactions. + cluster_call_cleanup_interval { + desc { + en: """Time interval to clear completed but stale transactions. Ensure that the number of completed transactions is less than the max_history.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """清理过期事务的时间间隔""" + } + label { + en: "Clean Up Interval" + zh: "清理间隔" + } + } - rpc_mode { - desc { - en: """In sync mode the sending side waits for the ack from the receiving side.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_mode { + desc { + en: """In sync mode the sending side waits for the ack from the receiving side.""" + zh: """在 sync 模式下,发送端等待接收端的 ack信号。""" + } + label { + en: "RPC Mode" + zh: "RPC 模式" + } + } - rpc_driver { - desc { - en: """Transport protocol used for inter-broker communication""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_driver { + desc { + en: """Transport protocol used for inter-broker communication""" + zh: """集群间通信使用的传输协议。""" + } + label { + en: "RPC dirver" + zh: "RPC 驱动" + } + } - rpc_async_batch_size { - desc { - en: """The maximum number of batch messages sent in asynchronous mode. Note that this configuration does not work in synchronous mode.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_async_batch_size { + desc { + en: """The maximum number of batch messages sent in asynchronous mode. + Note that this configuration does not work in synchronous mode. + """ + zh: """异步模式下,发送的批量消息的最大数量。""" + } + label { + en: "Async Batch Size" + zh: "异步模式下的批量消息数量" + } + } - rpc_port_discovery { - desc { - en: """manual: discover ports by tcp_server_port.
stateless: discover ports in a stateless manner, using the following algorithm. If node name is emqxN@127.0.0.1, where the N is an integer, then the listening port will be 5370 + N.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_port_discovery { + desc { + en: """manual: discover ports by tcp_server_port.
+stateless: discover ports in a stateless manner, using the following algorithm. +If node name is emqxN@127.0.0.1, where the N is an integer, +then the listening port will be 5370 + N.""" + zh: """manual: 通过 tcp_server_port 来发现端口。 +
stateless: 使用无状态的方式来发现端口,使用如下算法。如果节点名称是 +emqxN@127.0.0.1, N 是一个数字,那么监听端口就是 5370 + N。 + """ + } + label { + en: "RRC Port Discovery" + zh: "RPC 端口发现策略" + } + } - rpc_tcp_server_port { - desc { - en: """Listening port used by RPC local service.
Note that this config only takes effect when rpc.port_discovery is set to manual.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_tcp_server_port { + desc { + en: """Listening port used by RPC local service.
+Note that this config only takes effect when rpc.port_discovery is set to manual.""" + zh: """RPC 本地服务使用的 TCP 端口。
+只有当 rpc.port_discovery 设置为 manual 时,此配置才会生效。 + """ + } + label { + en: "RPC TCP Server Port" + zh: "RPC TCP 服务监听端口" + } + } - rpc_ssl_server_port { - desc { - en: """Listening port used by RPC local service.
Note that this config only takes effect when rpc.port_discovery is set to manual and driver is set to ssl.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_ssl_server_port { + desc { + en: """Listening port used by RPC local service.
+Note that this config only takes effect when rpc.port_discovery is set to manual +and driver is set to ssl.""" + zh: """RPC 本地服务使用的监听SSL端口。
+只有当 rpc.port_discovery 设置为 manual 且 dirver 设置为 ssl, +此配置才会生效。 + """ + } + label { + en: "RPC SSL Server Port" + zh: "RPC SSL 服务监听端口" + } + } - rpc_tcp_client_num { - desc { - en: """Set the maximum number of RPC communication channels initiated by this node to each remote node.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_tcp_client_num { + desc { + en: """Set the maximum number of RPC communication channels initiated by this node to each remote node.""" + zh: """设置本节点与远程节点之间的 RPC 通信通道的最大数量。""" + } + label { + en: "RPC TCP Client Num" + zh: "RPC TCP 客户端数量" + } + } - rpc_connect_timeout { - desc { - en: """Timeout for establishing an RPC connection.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_connect_timeout { + desc { + en: """Timeout for establishing an RPC connection.""" + zh: """建立 RPC 连接的超时时间。""" + } + label { + en: "RPC Connect Timeout" + zh: "RPC 连接超时时间" + } + } - rpc_certfile { - desc { - en: """Path to TLS certificate file used to validate identity of the cluster nodes. Note that this config only takes effect when rpc.driver is set to ssl.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_certfile { + desc { + en: """Path to TLS certificate file used to validate identity of the cluster nodes. +Note that this config only takes effect when rpc.driver is set to ssl. + """ + zh: """TLS 证书文件的路径,用于验证集群节点的身份。 +只有当 rpc.driver 设置为 ssl 时,此配置才会生效。 + """ + } + label { + en: "RPC Certfile" + zh: "RPC 证书文件" + } + } - rpc_keyfile { - desc { - en: """Path to the private key file for the rpc.certfile.
Note: contents of this file are secret, so it's necessary to set permissions to 600.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_keyfile { + desc { + en: """Path to the private key file for the rpc.certfile.
+Note: contents of this file are secret, so it's necessary to set permissions to 600.""" + zh: """rpc.certfile 的私钥文件的路径。
+注意:此文件内容是私钥,所以需要设置权限为 600。 + """ + } + label { + en: "RPC Keyfile" + zh: "RPC 私钥文件" + } + } - rpc_cacertfile { - desc { - en: """Path to certification authority TLS certificate file used to validate rpc.certfile.
Note: certificates of all nodes in the cluster must be signed by the same CA.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_cacertfile { + desc { + en: """Path to certification authority TLS certificate file used to validate rpc.certfile.
+Note: certificates of all nodes in the cluster must be signed by the same CA.""" + zh: """验证 rpc.certfile 的 CA 证书文件的路径。
+注意:集群中所有节点的证书必须使用同一个 CA 签发。 + """ + } + label { + en: "RPC Cacertfile" + zh: "RPC CA 证书文件" + } + } - rpc_send_timeout { - desc { - en: """Timeout for sending the RPC request.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_send_timeout { + desc { + en: """Timeout for sending the RPC request.""" + zh: """发送 RPC 请求的超时时间。""" + } + label { + en: "RPC Send Timeout" + zh: "RPC 发送超时时间" + } + } - rpc_authentication_timeout { - desc { - en: """Timeout for the remote node authentication.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_authentication_timeout { + desc { + en: """Timeout for the remote node authentication.""" + zh: """远程节点认证的超时时间。""" + } + label { + en: "RPC Authentication Timeout" + zh: "RPC 认证超时时间" + } + } - rpc_call_receive_timeout { - desc { - en: """Timeout for the reply to a synchronous RPC.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_call_receive_timeout { + desc { + en: """Timeout for the reply to a synchronous RPC.""" + zh: """同步 RPC 的回复超时时间。""" + } + label { + en: "RPC Call Receive Timeout" + zh: "RPC 调用接收超时时间" + } + } - rpc_socket_keepalive_idle { - desc { - en: """How long the connections between the brokers should remain open after the last message is sent.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_socket_keepalive_idle { + desc { + en: """How long the connections between the brokers should remain open after the last message is sent.""" + zh: """broker 之间的连接在最后一条消息发送后保持打开的时间。""" + } + label { + en: "RPC Socket Keepalive Idle" + zh: "RPC Socket Keepalive Idle" + } + } - rpc_socket_keepalive_interval { - desc { - en: """The interval between keepalive messages.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_socket_keepalive_interval { + desc { + en: """The interval between keepalive messages.""" + zh: """keepalive 消息的间隔。""" + } + label { + en: "RPC Socket Keepalive Interval" + zh: "RPC Socket Keepalive 间隔" + } + } - rpc_socket_keepalive_count { - desc { - en: """How many times the keepalive probe message can fail to receive a reply until the RPC connection is considered lost.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_socket_keepalive_count { + desc { + en: """How many times the keepalive probe message can fail to receive a reply +until the RPC connection is considered lost.""" + zh: """keepalive 探测消息发送失败的次数,直到 RPC 连接被认为已经断开。""" + } + label { + en: "RPC Socket Keepalive Count" + zh: "RPC Socket Keepalive 次数" + } + } - rpc_socket_sndbuf { - desc { - en: """TCP tuning parameters. TCP sending buffer size.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_socket_sndbuf { + desc { + en: """TCP tuning parameters. TCP sending buffer size.""" + zh: """TCP 调节参数。TCP 发送缓冲区大小。""" + } + label { + en: "RPC Socket Sndbuf" + zh: "RPC 套接字发送缓冲区大小" + } + } - rpc_socket_recbuf { - desc { - en: """TCP tuning parameters. TCP receiving buffer size.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_socket_recbuf { + desc { + en: """TCP tuning parameters. TCP receiving buffer size.""" + zh: """TCP 调节参数。TCP 接收缓冲区大小。""" + } + label { + en: "RPC Socket Recbuf" + zh: "RPC 套接字接收缓冲区大小" + } + } - rpc_socket_buffer { - desc { - en: """TCP tuning parameters. Socket buffer size in user mode.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + rpc_socket_buffer { + desc { + en: """TCP tuning parameters. Socket buffer size in user mode.""" + zh: """TCP 调节参数。用户模式套接字缓冲区大小。""" + } + label { + en: "RPC Socket Buffer" + zh: "RPC 套接字缓冲区大小" + } + } - log_file_handlers { - desc { - en: """Key-value list of file-based log handlers.""" - zh: """基于文件的日志处理进程的键值列表。""" - } - label: { - en: "Log Handlers Key Val List" - zh: "日志处理进程键值列表" - } - } + log_file_handlers { + desc { + en: """Key-value list of file-based log handlers.""" + zh: """基于文件的日志处理进程的键值列表。""" + } + label { + en: "Log Handlers Key Val List" + zh: "日志处理进程键值列表" + } + } - log_error_logger { - desc { - en: """Deprecated.""" - zh: """该配置已弃用。""" - } - label: { - en: "Deprecate" - zh: "配置已弃用" - } - } + log_error_logger { + desc { + en: """Deprecated.""" + zh: """该配置已弃用。""" + } + label { + en: "Deprecate" + zh: "配置已弃用" + } + } - console_handler_enable { - desc { - en: """Enable this log handler.""" - zh: """启用此日志处理进程。""" - } - label: { - en: "Enable Log Handler" - zh: "启用日志处理进程" - } - } + console_handler_enable { + desc { + en: """Enable this log handler.""" + zh: """启用此日志处理进程。""" + } + label { + en: "Enable Log Handler" + zh: "启用日志处理进程" + } + } - console_handler_level { - desc { - en: """Global log level. This includes the primary log level and all log handlers.""" - zh: """全局日志级别。 这包括主日志级别和所有日志处理进程。""" - } - label: { - en: "Global Log Level" - zh: "全局日志级别" - } - } + console_handler_level { + desc { + en: """Global log level. This includes the primary log level and all log handlers.""" + zh: """全局日志级别。 这包括主日志级别和所有日志处理进程。""" + } + label { + en: "Global Log Level" + zh: "全局日志级别" + } + } - console_handler_time_offset { - desc { - en: """The time offset to be used when formatting the timestamp.""" - zh: """格式化时间戳时,使用的时间偏移量。""" - } - label: { - en: "Time Offset" - zh: "时间偏移量" - } - } + console_handler_time_offset { + desc { + en: """The time offset to be used when formatting the timestamp.""" + zh: """格式化时间戳时,使用的时间偏移量。""" + } + label { + en: "Time Offset" + zh: "时间偏移量" + } + } - console_handler_chars_limit { - desc { - en: """Set the maximum length of a single log message. If this length is exceeded, the log message will be truncated.""" - zh: """设置单个日志消息的最大长度。 如果超过此长度,则日志消息将被截断。""" - } - label: { - en: "Single Log Max Length" - zh: "单个日志最大长度" - } - } + console_handler_chars_limit { + desc { + en: """Set the maximum length of a single log message. If this length is exceeded, the log message will be truncated.""" + zh: """设置单个日志消息的最大长度。 如果超过此长度,则日志消息将被截断。""" + } + label { + en: "Single Log Max Length" + zh: "单个日志最大长度" + } + } - console_handler_formatter { - desc { - en: """Choose log format. text for free text, and json for structured logging.""" - zh: """选择日志格式。 text 用于自由文本,json 用于结构化日志记录。""" - } - label: { - en: "Log Format" - zh: "日志格式" - } - } + console_handler_formatter { + desc { + en: """Choose log format. text for free text, and json for structured logging.""" + zh: """选择日志格式。 text 用于自由文本,json 用于结构化日志记录。""" + } + label { + en: "Log Format" + zh: "日志格式" + } + } - console_handler_single_line { - desc { - en: """Print logs in a single line if set to true. Otherwise, log messages may span multiple lines.""" - zh: """如果设置为 true,则在一行中打印日志。 否则,日志消息可能跨越多行。""" - } - label: { - en: "Single Line Mode" - zh: "单行模式" - } - } + console_handler_single_line { + desc { + en: """Print logs in a single line if set to true. Otherwise, log messages may span multiple lines.""" + zh: """如果设置为 true,则在一行中打印日志。 否则,日志消息可能跨越多行。""" + } + label { + en: "Single Line Mode" + zh: "单行模式" + } + } - console_handler_sync_mode_qlen { - desc { - en: """As long as the number of buffered log events is lower than this value, all log events are handled asynchronously.""" - zh: """只要缓冲的日志事件的数量低于这个值,所有的日志事件都会被异步处理。""" - } - label: { - en: "Sync Mode Max Log Events" - zh: "异步模式最大事件数" - } - } + console_handler_sync_mode_qlen { + desc { + en: """As long as the number of buffered log events is lower than this value, all log events are handled asynchronously.""" + zh: """只要缓冲的日志事件的数量低于这个值,所有的日志事件都会被异步处理。""" + } + label { + en: "Sync Mode Max Log Events" + zh: "异步模式最大事件数" + } + } - console_handler_drop_mode_qlen { - desc { - en: """When the number of buffered log events is larger than this value, the new log events are dropped.
When drop mode is activated or deactivated, a message is printed in the logs.""" - zh: """当缓冲的日志事件数大于此值时,新的日志事件将被丢弃。
启用或停用丢弃模式时,会在日志中打印一条消息。""" - } - label: { - en: "Drop Mode Max Log Events" - zh: "缓存最大日志事件数" - } - } + console_handler_drop_mode_qlen { + desc { + en: """When the number of buffered log events is larger than this value, the new log events are dropped.
When drop mode is activated or deactivated, a message is printed in the logs.""" + zh: """当缓冲的日志事件数大于此值时,新的日志事件将被丢弃。
启用或停用丢弃模式时,会在日志中打印一条消息。""" + } + label { + en: "Drop Mode Max Log Events" + zh: "缓存最大日志事件数" + } + } - console_handler_flush_qlen { - desc { - en: """If the number of buffered log events grows larger than this threshold, a flush (delete) operation takes place. To flush events, the handler discards the buffered log messages without logging.""" - zh: """如果缓冲日志事件的数量增长大于此阈值,则会发生刷新(删除)操作。 为了完成刷新事件,处理进程丢弃缓冲的日志消息。""" - } - label: { - en: "Flush Threshold" - zh: "刷新阈值" - } - } + console_handler_flush_qlen { + desc { + en: """If the number of buffered log events grows larger than this threshold, a flush (delete) operation takes place. To flush events, the handler discards the buffered log messages without logging.""" + zh: """如果缓冲日志事件的数量增长大于此阈值,则会发生刷新(删除)操作。 为了完成刷新事件,处理进程丢弃缓冲的日志消息。""" + } + label { + en: "Flush Threshold" + zh: "刷新阈值" + } + } - console_handler_supervisor_reports { - desc { - en: """Type of supervisor reports that are logged. + console_handler_supervisor_reports { + desc { + en: """Type of supervisor reports that are logged. - `error`: only log errors in the Erlang processes. - `progress`: log process startup.""" - zh: """ supervisor 报告的类型。 + zh: """ supervisor 报告的类型。 - `error`:仅记录 Erlang 进程中的错误。 - `progress`:记录进程启动。""" - } - label: { - en: "Report Type" - zh: "报告类型" - } - } + } + label { + en: "Report Type" + zh: "报告类型" + } + } - console_handler_max_depth { - desc { - en: """Maximum depth for Erlang term log formatting and Erlang process message queue inspection.""" - zh: """Erlang 内部格式日志格式化和 Erlang 进程消息队列检查的最大深度。""" - } - label: { - en: "Max Depth" - zh: "最大深度" - } - } + console_handler_max_depth { + desc { + en: """Maximum depth for Erlang term log formatting and Erlang process message queue inspection.""" + zh: """Erlang 内部格式日志格式化和 Erlang 进程消息队列检查的最大深度。""" + } + label { + en: "Max Depth" + zh: "最大深度" + } + } - log_file_handler_file { - desc { - en: """Name the log file.""" - zh: """日志文件名字。""" - } - label: { - en: "Log File Name" - zh: "日志文件名字" - } - } + log_file_handler_file { + desc { + en: """Name the log file.""" + zh: """日志文件名字。""" + } + label { + en: "Log File Name" + zh: "日志文件名字" + } + } - log_file_handler_max_size { - desc { - en: """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.""" - zh: """此参数控制日志文件轮换。 `infinity` 意味着日志文件将无限增长,否则日志文件将在达到 `max_size`(以字节为单位)时进行轮换。""" - } - label: { - en: "Rotation Size" - zh: "日志文件轮换大小" - } - } + log_file_handler_max_size { + desc { + en: """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.""" + zh: """此参数控制日志文件轮换。 `infinity` 意味着日志文件将无限增长,否则日志文件将在达到 `max_size`(以字节为单位)时进行轮换。""" + } + label { + en: "Rotation Size" + zh: "日志文件轮换大小" + } + } - log_file_handler_enable { - desc { - en: """Enable this log handler.""" - zh: """启用此日志处理进程。""" - } - label: { - en: "Enable Log Handler" - zh: "启用此日志处理进程" - } - } + log_file_handler_enable { + desc { + en: """Enable this log handler.""" + zh: """启用此日志处理进程。""" + } + label { + en: "Enable Log Handler" + zh: "启用此日志处理进程" + } + } - log_file_handler_level { - desc { - en: """Global log level. This includes the primary log level and all log handlers.""" - zh: """全局日志级别。 这包括主日志级别和所有日志处理进程。""" - } - label: { - en: "Global Level" - zh: "全局日志级别" - } - } + log_file_handler_level { + desc { + en: """Global log level. This includes the primary log level and all log handlers.""" + zh: """全局日志级别。 这包括主日志级别和所有日志处理进程。""" + } + label { + en: "Global Level" + zh: "全局日志级别" + } + } - log_file_handler_time_offset { - desc { - en: """The time offset to be used when formatting the timestamp.""" - zh: """格式化时间戳时要使用的时间偏移量。""" - } - label: { - en: "Time Offset" - zh: "时间偏移" - } - } + log_file_handler_time_offset { + desc { + en: """The time offset to be used when formatting the timestamp.""" + zh: """格式化时间戳时要使用的时间偏移量。""" + } + label { + en: "Time Offset" + zh: "时间偏移" + } + } - log_file_handler_chars_limit { - desc { - en: """Set the maximum length of a single log message. If this length is exceeded, the log message will be truncated.""" - zh: """设置单个日志消息的最大长度。 如果超过此长度,则日志消息将被截断。""" - } - label: { - en: "Single Log Max Length" - zh: "单个日志消息最大长度" - } - } + log_file_handler_chars_limit { + desc { + en: """Set the maximum length of a single log message. If this length is exceeded, the log message will be truncated.""" + zh: """设置单个日志消息的最大长度。 如果超过此长度,则日志消息将被截断。""" + } + label { + en: "Single Log Max Length" + zh: "单个日志消息最大长度" + } + } - log_file_handler_formatter { - desc { - en: """Choose log format. text for free text, and json for structured logging.""" - zh: """选择日志格式。 text 用于自由文本,json 用于结构化日志记录。""" - } - label: { - en: "Log Format" - zh: "日志格式" - } - } + log_file_handler_formatter { + desc { + en: """Choose log format. text for free text, and json for structured logging.""" + zh: """选择日志格式。 text 用于自由文本,json 用于结构化日志记录。""" + } + label { + en: "Log Format" + zh: "日志格式" + } + } - log_file_handler_single_line { - desc { - en: """Print logs in a single line if set to true. Otherwise, log messages may span multiple lines.""" - zh: """如果设置为 true,则在一行中打印日志。 否则,日志消息可能跨越多行。""" - } - label: { - en: "Single Line Mode" - zh: "单行模式" - } - } + log_file_handler_single_line { + desc { + en: """Print logs in a single line if set to true. Otherwise, log messages may span multiple lines.""" + zh: """如果设置为 true,则在一行中打印日志。 否则,日志消息可能跨越多行。""" + } + label { + en: "Single Line Mode" + zh: "单行模式" + } + } - log_file_handler_sync_mode_qlen { - desc { - en: """As long as the number of buffered log events is lower than this value, all log events are handled asynchronously.""" - zh: """只要缓冲的日志事件的数量低于这个值,所有的日志事件都会被异步处理。""" - } - label: { - en: "Sync Mode Max Log Events" - zh: "异步模式最大事件数" - } - } + log_file_handler_sync_mode_qlen { + desc { + en: """As long as the number of buffered log events is lower than this value, all log events are handled asynchronously.""" + zh: """只要缓冲的日志事件的数量低于这个值,所有的日志事件都会被异步处理。""" + } + label { + en: "Sync Mode Max Log Events" + zh: "异步模式最大事件数" + } + } - log_file_handler_drop_mode_qlen { - desc { - en: """When the number of buffered log events is larger than this value, the new log events are dropped.
When drop mode is activated or deactivated, a message is printed in the logs.""" - zh: """当缓冲的日志事件数大于此值时,新的日志事件将被丢弃。
启用或停用丢弃模式时,会在日志中打印一条消息。""" - } - label: { - en: "Drop Mode Max Log Events" - zh: "缓存最大日志事件数" - } - } + log_file_handler_drop_mode_qlen { + desc { + en: """When the number of buffered log events is larger than this value, the new log events are dropped.
When drop mode is activated or deactivated, a message is printed in the logs.""" + zh: """当缓冲的日志事件数大于此值时,新的日志事件将被丢弃。
启用或停用丢弃模式时,会在日志中打印一条消息。""" + } + label { + en: "Drop Mode Max Log Events" + zh: "缓存最大日志事件数" + } + } - log_file_handler_flush_qlen { - desc { - en: """If the number of buffered log events grows larger than this threshold, a flush (delete) operation takes place. To flush events, the handler discards the buffered log messages without logging.""" - zh: """如果缓冲日志事件的数量增长大于此阈值,则会发生刷新(删除)操作。 为了完成刷新事件,处理进程丢弃缓冲的日志消息。""" - } - label: { - en: "Flush Threshold" - zh: "刷新阈值" - } - } + log_file_handler_flush_qlen { + desc { + en: """If the number of buffered log events grows larger than this threshold, a flush (delete) operation takes place. To flush events, the handler discards the buffered log messages without logging.""" + zh: """如果缓冲日志事件的数量增长大于此阈值,则会发生刷新(删除)操作。 为了完成刷新事件,处理进程丢弃缓冲的日志消息。""" + } + label { + en: "Flush Threshold" + zh: "刷新阈值" + } + } - log_file_handler_supervisor_reports { - desc { - en: """Type of supervisor reports that are logged. + log_file_handler_supervisor_reports { + desc { + en: """Type of supervisor reports that are logged. - `error`: only log errors in the Erlang processes. - `progress`: log process startup.""" - zh: """ supervisor 报告的类型。 + zh: """ supervisor 报告的类型。 - `error`:仅记录 Erlang 进程中的错误。 - `progress`:记录进程启动。""" - } - label: { - en: "Report Type" - zh: "报告类型" - } - } + } + label { + en: "Report Type" + zh: "报告类型" + } + } - log_file_handler_max_depth { - desc { - en: """Maximum depth for Erlang term log formatting and Erlang process message queue inspection.""" - zh: """Erlang 内部格式日志格式化和 Erlang 进程消息队列检查的最大深度。""" - } - label: { - en: "Max Depth" - zh: "最大深度" - } - } + log_file_handler_max_depth { + desc { + en: """Maximum depth for Erlang term log formatting and Erlang process message queue inspection.""" + zh: """Erlang 内部格式日志格式化和 Erlang 进程消息队列检查的最大深度。""" + } + label { + en: "Max Depth" + zh: "最大深度" + } + } - log_rotation_enable { - desc { - en: """Enable log rotation feature.""" - zh: """启用日志轮换功能。""" - } - label: { - en: "Rotation Enable" - zh: "日志轮换" - } - } + log_rotation_enable { + desc { + en: """Enable log rotation feature.""" + zh: """启用日志轮换功能。""" + } + label { + en: "Rotation Enable" + zh: "日志轮换" + } + } - log_rotation_count { - desc { - en: """Maximum number of log files.""" - zh: """最大日志文件数。""" - } - label: { - en: "Max Log Files Number" - zh: "最大日志文件数" - } - } + log_rotation_count { + desc { + en: """Maximum number of log files.""" + zh: """最大日志文件数。""" + } + label { + en: "Max Log Files Number" + zh: "最大日志文件数" + } + } - log_overload_kill_enable { - desc { - en: """Enable log handler overload kill feature.""" - zh: """启用日志处理进程过载终止功能。""" - } - label: { - en: "Log Handler Overload Kill" - zh: "日志处理进程过载终止" - } - } + log_overload_kill_enable { + desc { + en: """Enable log handler overload kill feature.""" + zh: """启用日志处理进程过载终止功能。""" + } + label { + en: "Log Handler Overload Kill" + zh: "日志处理进程过载终止" + } + } - log_overload_kill_mem_size { - desc { - en: """Maximum memory size that the handler process is allowed to use.""" - zh: """处理进程进程允许使用的最大内存。""" - } - label: { - en: "Handler Allowed Max Memory Size" - zh: "理进程进程允许使用的最大内存" - } - } + log_overload_kill_mem_size { + desc { + en: """Maximum memory size that the handler process is allowed to use.""" + zh: """处理进程进程允许使用的最大内存。""" + } + label { + en: "Handler Allowed Max Memory Size" + zh: "理进程进程允许使用的最大内存" + } + } - log_overload_kill_qlen { - desc { - en: """Maximum allowed queue length.""" - zh: """允许的最大队列长度。""" - } - label: { - en: "Max Queue Length" - zh: "最大队列长度" - } - } + log_overload_kill_qlen { + desc { + en: """Maximum allowed queue length.""" + zh: """允许的最大队列长度。""" + } + label { + en: "Max Queue Length" + zh: "最大队列长度" + } + } - log_overload_kill_restart_after { - desc { - en: """If the handler is terminated, it restarts automatically after a delay specified in milliseconds. The value `infinity` prevents restarts.""" - zh: """如果处理进程终止,它会在以毫秒为单位指定的延迟后自动重新启动。 `infinity` 防止重新启动。""" - } - label: { - en: "Handler Restart Delay" - zh: "处理进程重启延迟" - } - } + log_overload_kill_restart_after { + desc { + en: """If the handler is terminated, it restarts automatically after a delay specified in milliseconds. The value `infinity` prevents restarts.""" + zh: """如果处理进程终止,它会在以毫秒为单位指定的延迟后自动重新启动。 `infinity` 防止重新启动。""" + } + label { + en: "Handler Restart Delay" + zh: "处理进程重启延迟" + } + } - log_burst_limit_enable { - desc { - en: """Enable log burst control feature.""" - zh: """启用日志突发控制功能。""" - } - label: { - en: "Enable Burst" - zh: "启用日志突发控制" - } - } + log_burst_limit_enable { + desc { + en: """Enable log burst control feature.""" + zh: """启用日志突发控制功能。""" + } + label { + en: "Enable Burst" + zh: "启用日志突发控制" + } + } - log_burst_limit_max_count { - desc { - en: """Maximum number of log events to handle within a `window_time` interval. After the limit is reached, successive events are dropped until the end of the `window_time`.""" - zh: """在 `window_time` 间隔内处理的最大日志事件数。 达到限制后,将丢弃连续事件,直到 `window_time` 结束。""" - } - label: { - en: "Events Number" - zh: "日志事件数" - } - } + log_burst_limit_max_count { + desc { + en: """Maximum number of log events to handle within a `window_time` interval. After the limit is reached, successive events are dropped until the end of the `window_time`.""" + zh: """在 `window_time` 间隔内处理的最大日志事件数。 达到限制后,将丢弃连续事件,直到 `window_time` 结束。""" + } + label { + en: "Events Number" + zh: "日志事件数" + } + } - log_burst_limit_window_time { - desc { - en: """See `max_count`.""" - zh: """参考 `max_count`。""" - } - label: { - en: "Window Time" - zh: "Window Time" - } - } + log_burst_limit_window_time { + desc { + en: """See `max_count`.""" + zh: """参考 `max_count`。""" + } + label { + en: "Window Time" + zh: "Window Time" + } + } - authorization { - desc { - en: """ + authorization { + desc { + en: """ Authorization a.k.a. ACL.
In EMQX, MQTT client access control is extremely flexible.
An out-of-the-box set of authorization data sources are supported. @@ -1209,209 +1344,216 @@ natively in the EMQX node;
'http' source to make EMQX call an external HTTP API to make the decision;
'PostgreSQL' etc. to look up clients or rules from external databases;
""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + zh: """ 授权(ACL)。EMQX 支持完整的客户端访问控制(ACL)。
""" + } + label { + en: "Authorization" + zh: "授权" + } + } - desc_cluster { - desc { - en: """EMQX nodes can form a cluster to scale up the total capacity.
Here holds the configs to instruct how individual nodes can discover each other.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster { + desc { + en: """EMQX nodes can form a cluster to scale up the total capacity.
+ Here holds the configs to instruct how individual nodes can discover each other.""" + zh: """EMQX 节点可以组成一个集群,以提高总容量。
这里指定了节点之间如何连接。""" + } + label { + en: "Cluster" + zh: "集群" + } + } - desc_cluster_static { - desc { - en: """Service discovery via static nodes. The new node joins the cluster by connecting to one of the bootstrap nodes.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster_static { + desc { + en: """Service discovery via static nodes. +The new node joins the cluster by connecting to one of the bootstrap nodes.""" + zh: """静态节点服务发现。新节点通过连接一个节点来加入集群。""" + } + label { + en: "Cluster Static" + zh: "静态节点服务发现" + } + } - desc_cluster_mcast { - desc { - en: """Service discovery via UDP multicast.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster_mcast { + desc { + en: """Service discovery via UDP multicast.""" + zh: """UDP 组播服务发现。""" + } + label { + en: "Cluster Multicast" + zh: "UDP 组播服务发现" + } + } - desc_cluster_dns { - desc { - en: """Service discovery via DNS SRV records.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster_dns { + desc { + en: """Service discovery via DNS SRV records.""" + zh: """DNS SRV 记录服务发现。""" + } + label { + en: "Cluster DNS" + zh: "DNS SRV 记录服务发现" + } + } - desc_cluster_etcd { - desc { - en: """Service discovery using 'etcd' service.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster_etcd { + desc { + en: """Service discovery using 'etcd' service.""" + zh: """使用 'etcd' 服务的服务发现。""" + } + label { + en: "Cluster Etcd" + zh: "'etcd' 服务的服务发现" + } + } - desc_cluster_k8s { - desc { - en: """Service discovery via Kubernetes API server.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster_k8s { + desc { + en: """Service discovery via Kubernetes API server.""" + zh: """Kubernetes 服务发现。""" + } + label { + en: "Cluster Kubernetes" + zh: "Kubernetes 服务发现" + } + } - desc_node { - desc { - en: """Node name, cookie, config & data directories and the Erlang virtual machine (BEAM) boot parameters.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_node { + desc { + en: """Node name, cookie, config & data directories and the Erlang virtual machine (BEAM) boot parameters.""" + zh: """节点名称、Cookie、配置文件、数据目录和 Erlang 虚拟机(BEAM)启动参数。""" + } + label { + en: "Node" + zh: "节点" + } + } - desc_db { - desc { - en: """Settings for the embedded database.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_db { + desc { + en: """Settings for the embedded database.""" + zh: """内置数据库的配置。""" + } + label { + en: "Database" + zh: "数据库" + } + } - desc_cluster_call { - desc { - en: """Options for the 'cluster call' feature that allows to execute a callback on all nodes in the cluster.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_cluster_call { + desc { + en: """Options for the 'cluster call' feature that allows to execute a callback on all nodes in the cluster.""" + zh: """集群调用功能的选项。""" + } + label { + en: "Cluster Call" + zh: "集群调用" + } + } - desc_rpc { - desc { - en: """EMQX uses a library called gen_rpc for inter-broker communication.
Most of the time the default config should work, but in case you need to do performance fine-tuning or experiment a bit, this is where to look.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_rpc { + desc { + en: """EMQX uses a library called gen_rpc for inter-broker communication.
+Most of the time the default config should work, +but in case you need to do performance fine-tuning or experiment a bit, +this is where to look.""" + zh: """EMQX 使用 gen_rpc 库来实现跨节点通信。
+大多数情况下,默认的配置应该可以工作,但如果你需要做一些性能优化或者实验,可以尝试调整这些参数。""" + } + label { + en: "RPC" + zh: "RPC" + } + } - desc_log { - desc { - en: """EMQX logging supports multiple sinks for the log events. Each sink is represented by a _log handler_, which can be configured independently.""" - zh: """EMQX 日志记录支持日志事件的多个接收器。 每个接收器由一个_log handler_表示,可以独立配置。""" - } - label: { - en: "Log" - zh: "日志" - } - } + desc_log { + desc { + en: """EMQX logging supports multiple sinks for the log events. +Each sink is represented by a _log handler_, which can be configured independently.""" + zh: """EMQX 日志记录支持日志事件的多个接收器。 每个接收器由一个_log handler_表示,可以独立配置。""" + } + label { + en: "Log" + zh: "日志" + } + } - desc_console_handler { - desc { - en: """Log handler that prints log events to the EMQX console.""" - zh: """日志处理进程将日志事件打印到 EMQX 控制台。""" - } - label: { - en: "Console Log Handler" - zh: "控制台日志处理进程" - } - } + desc_console_handler { + desc { + en: """Log handler that prints log events to the EMQX console.""" + zh: """日志处理进程将日志事件打印到 EMQX 控制台。""" + } + label { + en: "Console Log Handler" + zh: "控制台日志处理进程" + } + } - desc_log_file_handler { - desc { - en: """Log handler that prints log events to files.""" - zh: """日志处理进程将日志事件打印到文件。""" - } - label: { - en: "Files Log Handler" - zh: "文件日志处理进程" - } - } + desc_log_file_handler { + desc { + en: """Log handler that prints log events to files.""" + zh: """日志处理进程将日志事件打印到文件。""" + } + label { + en: "Files Log Handler" + zh: "文件日志处理进程" + } + } - desc_log_rotation { - desc { - en: """By default, the logs are stored in `./log` directory (for installation from zip file) or in `/var/log/emqx` (for binary installation).
This section of the configuration controls the number of files kept for each log handler.""" - zh: """默认情况下,日志存储在 `./log` 目录(用于从 zip 文件安装)或 `/var/log/emqx`(用于二进制安装)。
这部分配置,控制每个日志处理进程保留的文件数量。""" - } - label: { - en: "Log Rotation" - zh: "日志轮换" - } - } + desc_log_rotation { + desc { + en: """By default, the logs are stored in `./log` directory (for installation from zip file) or in `/var/log/emqx` (for binary installation).
This section of the configuration controls the number of files kept for each log handler.""" + zh: """默认情况下,日志存储在 `./log` 目录(用于从 zip 文件安装)或 `/var/log/emqx`(用于二进制安装)。
这部分配置,控制每个日志处理进程保留的文件数量。""" + } + label { + en: "Log Rotation" + zh: "日志轮换" + } + } - desc_log_overload_kill { - desc { - en: """Log overload kill features an overload protection that activates when the log handlers use too much memory or have too many buffered log messages.
When the overload is detected, the log handler is terminated and restarted after a cooldown period.""" - zh: """日志过载终止,具有过载保护功能。当日志处理进程使用过多内存,或者缓存的日志消息过多时该功能被激活。
检测到过载时,日志处理进程将终止,并在冷却期后重新启动。""" - } - label: { - en: "Log Overload Kill" - zh: "日志过载保护" - } - } + desc_log_overload_kill { + desc { + en: """Log overload kill features an overload protection that activates when the log handlers use too much memory or have too many buffered log messages.
When the overload is detected, the log handler is terminated and restarted after a cooldown period.""" + zh: """日志过载终止,具有过载保护功能。当日志处理进程使用过多内存,或者缓存的日志消息过多时该功能被激活。
检测到过载时,日志处理进程将终止,并在冷却期后重新启动。""" + } + label { + en: "Log Overload Kill" + zh: "日志过载保护" + } + } - desc_log_burst_limit { - desc { - en: """Large bursts of log events produced in a short time can potentially cause problems, such as: + desc_log_burst_limit { + desc { + en: """Large bursts of log events produced in a short time can potentially cause problems, such as: - Log files grow very large - Log files are rotated too quickly, and useful information gets overwritten - Overall performance impact on the system Log burst limit feature can temporarily disable logging to avoid these issues.""" - zh: """短时间内产生的大量日志事件可能会导致问题,例如: + zh: """短时间内产生的大量日志事件可能会导致问题,例如: - 日志文件变得非常大 - 日志文件轮换过快,有用信息被覆盖 - 对系统的整体性能影响 日志突发限制功能可以暂时禁用日志记录以避免这些问题。""" - } - label: { - en: "Log Burst Limit" - zh: "日志突发限制" - } - } + } + label { + en: "Log Burst Limit" + zh: "日志突发限制" + } + } - desc_authorization { - desc { - en: """Settings that control client authorization.""" - zh: """""" - } - label: { - en: "" - zh: "" - } - } + desc_authorization { + desc { + en: """Settings that control client authorization.""" + zh: """授权相关""" + } + label { + en: "Authorization" + zh: "授权" + } + } } diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl index 8a854aca2..a4e13ec27 100644 --- a/apps/emqx_conf/src/emqx_conf_schema.erl +++ b/apps/emqx_conf/src/emqx_conf_schema.erl @@ -105,28 +105,27 @@ fields("cluster") -> sc(atom(), #{ mapping => "ekka.cluster_name" , default => emqxcl - , desc => "Human-friendly name of the EMQX cluster." + , desc => ?DESC(cluster_name) , 'readOnly' => true })} , {"discovery_strategy", sc(hoconsc:enum([manual, static, mcast, dns, etcd, k8s]), #{ default => manual - , desc => "Service discovery method for the cluster nodes." + , desc => ?DESC(cluster_discovery_strategy) , 'readOnly' => true })} , {"autoclean", sc(emqx_schema:duration(), #{ mapping => "ekka.cluster_autoclean" , default => "5m" - , desc => "Remove disconnected nodes from the cluster after this interval." + , desc => ?DESC(cluster_autoclean) , 'readOnly' => true })} , {"autoheal", sc(boolean(), #{ mapping => "ekka.cluster_autoheal" , default => true - , desc => "If true, the node will try to heal network partitions - automatically." + , desc => ?DESC(cluster_autoheal) , 'readOnly' => true })} , {"proto_dist", @@ -134,7 +133,7 @@ fields("cluster") -> #{ mapping => "ekka.proto_dist" , default => inet_tcp , 'readOnly' => true - , desc => "The Erlang distribution protocol for the cluster." + , desc => ?DESC(cluster_proto_dist) })} , {"static", sc(ref(cluster_static), @@ -162,7 +161,7 @@ fields(cluster_static) -> [ {"seeds", sc(hoconsc:array(atom()), #{ default => [] - , desc => "List EMQX node names in the static cluster. See node.name." + , desc => ?DESC(cluster_static_seeds) , 'readOnly' => true })} ]; @@ -171,50 +170,49 @@ fields(cluster_mcast) -> [ {"addr", sc(string(), #{ default => "239.192.0.1" - , desc => "Multicast IPv4 address." + , desc => ?DESC(cluster_mcast_addr) , 'readOnly' => true })} , {"ports", sc(hoconsc:array(integer()), #{ default => [4369, 4370] , 'readOnly' => true - , desc => "List of UDP ports used for service discovery.
-Note: probe messages are broadcast to all the specified ports." + , desc => ?DESC(cluster_mcast_ports) })} , {"iface", sc(string(), #{ default => "0.0.0.0" - , desc => "Local IP address the node discovery service needs to bind to." + , desc => ?DESC(cluster_mcast_iface) , 'readOnly' => true })} , {"ttl", sc(range(0, 255), #{ default => 255 - , desc => "Time-to-live (TTL) for the outgoing UDP datagrams." + , desc => ?DESC(cluster_mcast_ttl) , 'readOnly' => true })} , {"loop", sc(boolean(), #{ default => true - , desc => "If true, loop UDP datagrams back to the local socket." + , desc => ?DESC(cluster_mcast_loop) , 'readOnly' => true })} , {"sndbuf", sc(emqx_schema:bytesize(), #{ default => "16KB" - , desc => "Size of the kernel-level buffer for outgoing datagrams." + , desc => ?DESC(cluster_mcast_sndbuf) , 'readOnly' => true })} , {"recbuf", sc(emqx_schema:bytesize(), #{ default => "16KB" - , desc => "Size of the kernel-level buffer for incoming datagrams." + , desc => ?DESC(cluster_mcast_recbuf) , 'readOnly' => true })} , {"buffer", sc(emqx_schema:bytesize(), #{ default =>"32KB" - , desc => "Size of the user-level buffer." + , desc => ?DESC(cluster_mcast_buffer) , 'readOnly' => true })} ]; @@ -223,13 +221,13 @@ fields(cluster_dns) -> [ {"name", sc(string(), #{ default => "localhost" - , desc => "The domain name of the EMQX cluster." + , desc => ?DESC(cluster_dns_name) , 'readOnly' => true })} , {"app", sc(string(), #{ default => "emqx" - , desc => "The symbolic name of the EMQX service." + , desc => ?DESC(cluster_dns_app) , 'readOnly' => true })} ]; @@ -237,25 +235,24 @@ fields(cluster_dns) -> fields(cluster_etcd) -> [ {"server", sc(emqx_schema:comma_separated_list(), - #{ desc => "List of endpoint URLs of the etcd cluster" + #{ desc => ?DESC(cluster_etcd_server) , 'readOnly' => true })} , {"prefix", sc(string(), #{ default => "emqxcl" - , desc => "Key prefix used for EMQX service discovery." + , desc => ?DESC(cluster_etcd_prefix) , 'readOnly' => true })} , {"node_ttl", sc(emqx_schema:duration(), #{ default => "1m" , 'readOnly' => true - , desc => "Expiration time of the etcd key associated with the node. -It is refreshed automatically, as long as the node is alive." + , desc => ?DESC(cluster_etcd_node_ttl) })} , {"ssl", sc(hoconsc:ref(emqx_schema, ssl_client_opts), - #{ desc => "Options for the TLS connection to the etcd cluster." + #{ desc => ?DESC(cluster_etcd_ssl) , 'readOnly' => true })} ]; @@ -263,42 +260,37 @@ It is refreshed automatically, as long as the node is alive." fields(cluster_k8s) -> [ {"apiserver", sc(string(), - #{ desc => "Kubernetes API endpoint URL." + #{ desc => ?DESC(cluster_k8s_apiserver) , 'readOnly' => true })} , {"service_name", sc(string(), #{ default => "emqx" - , desc => "EMQX broker service name." + , desc => ?DESC(cluster_k8s_service_name) , 'readOnly' => true })} , {"address_type", sc(hoconsc:enum([ip, dns, hostname]), - #{ desc => "Address type used for connecting to the discovered nodes." + #{ desc => ?DESC(cluster_k8s_address_type) , 'readOnly' => true })} , {"app_name", sc(string(), #{ default => "emqx" , 'readOnly' => true - , desc => "This parameter should be set to the part of the node.name -before the '@'.
-For example, if the node.name is emqx@127.0.0.1, then this parameter -should be set to emqx." + , desc => ?DESC(cluster_k8s_app_name) })} , {"namespace", sc(string(), #{ default => "default" - , desc => "Kubernetes namespace." + , desc => ?DESC(cluster_k8s_namespace) , 'readOnly' => true })} , {"suffix", sc(string(), #{ default => "pod.local" , 'readOnly' => true - , desc => "Node name suffix.
-Note: this parameter is only relevant when address_type is dns -or hostname." + , desc => ?DESC(cluster_k8s_suffix) })} ]; @@ -307,8 +299,7 @@ fields("node") -> sc(string(), #{ default => "emqx@127.0.0.1" , 'readOnly' => true - , desc => "Unique name of the EMQX node. It must follow %name%@FQDN or - %name%@IPv4 format." + , desc => ?DESC(node_name) })} , {"cookie", sc(string(), @@ -316,65 +307,47 @@ fields("node") -> default => "emqxsecretcookie", 'readOnly' => true, sensitive => true, - desc => "Secret cookie is a random string that should be the same on all nodes in - the given EMQX cluster, but unique per EMQX cluster. It is used to prevent EMQX nodes that - belong to different clusters from accidentally connecting to each other." + desc => ?DESC(node_cookie) })} , {"data_dir", sc(string(), #{ required => true, 'readOnly' => true, mapping => "emqx.data_dir", - desc => -""" -Path to the persistent data directory. -Possible auto-created subdirectories are: - - `mnesia/\`: EMQX's built-in database directory. - For example, `mnesia/emqx@127.0.0.1`. - There should be only one such subdirectory. - Meaning, in case the node is to be renamed (to e.g. `emqx@10.0.1.1`), - the old dir should be deleted first. - - `configs`: Generated configs at boot time, and cluster/local override configs. - - `patches`: Hot-patch beam files are to be placed here. - - `trace`: Trace log files. - -**NOTE**: One data dir cannot be shared by two or more EMQX nodes. -""" + desc => ?DESC(node_data_dir) })} , {"config_files", sc(list(string()), #{ mapping => "emqx.config_files" , default => undefined , 'readOnly' => true - , desc => "List of configuration files that are read during startup. The order is - significant: later configuration files override the previous ones." + , desc => ?DESC(node_config_files) })} , {"global_gc_interval", sc(emqx_schema:duration(), #{ mapping => "emqx_machine.global_gc_interval" , default => "15m" - , desc => "Periodic garbage collection interval." + , desc => ?DESC(node_global_gc_interval) , 'readOnly' => true })} , {"crash_dump_file", sc(file(), #{ mapping => "vm_args.-env ERL_CRASH_DUMP" - , desc => "Location of the crash dump file" + , desc => ?DESC(node_crash_dump_file) , 'readOnly' => true })} , {"crash_dump_seconds", sc(emqx_schema:duration_s(), #{ mapping => "vm_args.-env ERL_CRASH_DUMP_SECONDS" , default => "30s" - , desc => "The number of seconds that the broker is allowed to spend writing -a crash dump" + , desc => ?DESC(node_crash_dump_seconds) , 'readOnly' => true })} , {"crash_dump_bytes", sc(emqx_schema:bytesize(), #{ mapping => "vm_args.-env ERL_CRASH_DUMP_BYTES" , default => "100MB" - , desc => "The maximum size of a crash dump file in bytes." + , desc => ?DESC(node_crash_dump_bytes) , 'readOnly' => true })} , {"dist_net_ticktime", @@ -382,28 +355,25 @@ a crash dump" #{ mapping => "vm_args.-kernel net_ticktime" , default => "2m" , 'readOnly' => true - , desc => "This is the approximate time an EMQX node may be unresponsive " - "until it is considered down and thereby disconnected." + , desc => ?DESC(node_dist_net_ticktime) })} , {"backtrace_depth", sc(integer(), #{ mapping => "emqx_machine.backtrace_depth" , default => 23 , 'readOnly' => true - , desc => "Maximum depth of the call stack printed in error messages and - process_info." + , desc => ?DESC(node_backtrace_depth) })} , {"applications", sc(emqx_schema:comma_separated_atoms(), #{ mapping => "emqx_machine.applications" , default => [] , 'readOnly' => true - , desc => "List of Erlang applications that shall be rebooted when the EMQX broker joins - the cluster." + , desc => ?DESC(node_applications) })} , {"etc_dir", sc(string(), - #{ desc => "etc dir for the node" + #{ desc => ?DESC(node_etc_dir) , 'readOnly' => true } )} @@ -420,81 +390,45 @@ fields("db") -> #{ mapping => "mria.db_backend" , default => rlog , 'readOnly' => true - , desc => """ -Select the backend for the embedded database.
-rlog is the default backend, -that is suitable for very large clusters.
-mnesia is a backend that offers decent performance in small clusters. -""" + , desc => ?DESC(db_backend) })} , {"role", sc(hoconsc:enum([core, replicant]), #{ mapping => "mria.node_role" , default => core , 'readOnly' => true - , desc => """ -Select a node role.
-core nodes provide durability of the data, and take care of writes. -It is recommended to place core nodes in different racks or different availability zones.
-replicant nodes are ephemeral worker nodes. Removing them from the cluster -doesn't affect database redundancy
-It is recommended to have more replicant nodes than core nodes.
-Note: this parameter only takes effect when the backend is set -to rlog. -""" + , desc => ?DESC(db_role) })} , {"core_nodes", sc(emqx_schema:comma_separated_atoms(), #{ mapping => "mria.core_nodes" , default => [] , 'readOnly' => true - , desc => """ -List of core nodes that the replicant will connect to.
-Note: this parameter only takes effect when the backend is set -to rlog and the role is set to replicant.
-This value needs to be defined for manual or static cluster discovery mechanisms.
-If an automatic cluster discovery mechanism is being used (such as etcd), -there is no need to set this value. -""" + , desc => ?DESC(db_core_nodes) })} , {"rpc_module", sc(hoconsc:enum([gen_rpc, rpc]), #{ mapping => "mria.rlog_rpc_module" , default => gen_rpc , 'readOnly' => true - , desc => """ -Protocol used for pushing transaction logs to the replicant nodes. -""" + , desc => ?DESC(db_rpc_module) })} , {"tlog_push_mode", sc(hoconsc:enum([sync, async]), #{ mapping => "mria.tlog_push_mode" , default => async , 'readOnly' => true - , desc => """ -In sync mode the core node waits for an ack from the replicant nodes before sending the next -transaction log entry. -""" + , desc => ?DESC(db_tlog_push_mode) })} , {"default_shard_transport", sc(hoconsc:enum([gen_rpc, distr]), #{ mapping => "mria.shard_transport" , default => gen_rpc - , desc => - "Defines the default transport for pushing transaction logs.
" - "This may be overridden on a per-shard basis in db.shard_transports." - "gen_rpc uses the gen_rpc library, " - "distr uses the Erlang distribution.
" + , desc => ?DESC(db_default_shard_transport) })} , {"shard_transports", sc(map(shard, hoconsc:enum([gen_rpc, distr])), - #{ desc => - "Allows to tune the transport method used for transaction log replication, " - "on a per-shard basis.
" - "gen_rpc uses the gen_rpc library, " - "distr uses the Erlang distribution.
" - "If not specified, the default is to use the value " - "set in db.default_shard_transport." + #{ desc => ?DESC(db_shard_transports) , mapping => "emqx_machine.custom_shard_transports" , default => #{} })} @@ -503,19 +437,17 @@ transaction log entry. fields("cluster_call") -> [ {"retry_interval", sc(emqx_schema:duration(), - #{ desc => "Time interval to retry after a failed call." + #{ desc => ?DESC(cluster_call_retry_interval) , default => "1s" })} , {"max_history", sc(range(1, 500), - #{ desc => "Retain the maximum number of completed transactions (for queries)." + #{ desc => ?DESC(cluster_call_max_history) , default => 100 })} , {"cleanup_interval", sc(emqx_schema:duration(), - #{ desc => -"Time interval to clear completed but stale transactions. -Ensure that the number of completed transactions is less than the max_history." + #{ desc => ?DESC(cluster_call_cleanup_interval) , default => "5m" })} ]; @@ -524,136 +456,118 @@ fields("rpc") -> [ {"mode", sc(hoconsc:enum([sync, async]), #{ default => async - , desc => "In sync mode the sending side waits for the ack from the " - "receiving side." + , desc => ?DESC(rpc_mode) })} , {"driver", sc(hoconsc:enum([tcp, ssl]), #{ mapping => "gen_rpc.driver" , default => tcp - , desc => "Transport protocol used for inter-broker communication" + , desc => ?DESC(rpc_driver) })} , {"async_batch_size", sc(integer(), #{ mapping => "gen_rpc.max_batch_size" , default => 256 - , desc => "The maximum number of batch messages sent in asynchronous mode. " - "Note that this configuration does not work in synchronous mode." + , desc => ?DESC(rpc_async_batch_size) })} , {"port_discovery", sc(hoconsc:enum([manual, stateless]), #{ mapping => "gen_rpc.port_discovery" , default => stateless - , desc => "manual: discover ports by tcp_server_port.
" - "stateless: discover ports in a stateless manner, " - "using the following algorithm. " - "If node name is emqxN@127.0.0.1, where the N is an integer, " - "then the listening port will be 5370 + N." + , desc => ?DESC(rpc_port_discovery) })} , {"tcp_server_port", sc(integer(), #{ mapping => "gen_rpc.tcp_server_port" , default => 5369 - , desc => "Listening port used by RPC local service.
" - "Note that this config only takes effect when rpc.port_discovery " - "is set to manual." + , desc => ?DESC(rpc_tcp_server_port) })} , {"ssl_server_port", sc(integer(), #{ mapping => "gen_rpc.ssl_server_port" , default => 5369 - , desc => "Listening port used by RPC local service.
" - "Note that this config only takes effect when rpc.port_discovery " - "is set to manual and driver is set to ssl." + , desc => ?DESC(rpc_ssl_server_port) })} , {"tcp_client_num", sc(range(1, 256), #{ default => 10 - , desc => "Set the maximum number of RPC communication channels initiated by this node " - "to each remote node." + , desc => ?DESC(rpc_tcp_client_num) })} , {"connect_timeout", sc(emqx_schema:duration(), #{ mapping => "gen_rpc.connect_timeout" , default => "5s" - , desc => "Timeout for establishing an RPC connection." + , desc => ?DESC(rpc_connect_timeout) })} , {"certfile", sc(file(), #{ mapping => "gen_rpc.certfile" - , desc => "Path to TLS certificate file used to validate identity of the cluster nodes. " - "Note that this config only takes effect when rpc.driver " - "is set to ssl." + , desc => ?DESC(rpc_certfile) })} , {"keyfile", sc(file(), #{ mapping => "gen_rpc.keyfile" - , desc => "Path to the private key file for the rpc.certfile.
" - "Note: contents of this file are secret, so " - "it's necessary to set permissions to 600." + , desc => ?DESC(rpc_keyfile) })} , {"cacertfile", sc(file(), #{ mapping => "gen_rpc.cacertfile" - , desc => "Path to certification authority TLS certificate file used to validate " - "rpc.certfile.
" - "Note: certificates of all nodes in the cluster must be signed by the same CA." + , desc => ?DESC(rpc_cacertfile) })} , {"send_timeout", sc(emqx_schema:duration(), #{ mapping => "gen_rpc.send_timeout" , default => "5s" - , desc => "Timeout for sending the RPC request." + , desc => ?DESC(rpc_send_timeout) })} , {"authentication_timeout", sc(emqx_schema:duration(), #{ mapping=> "gen_rpc.authentication_timeout" , default => "5s" - , desc => "Timeout for the remote node authentication." + , desc => ?DESC(rpc_authentication_timeout) })} , {"call_receive_timeout", sc(emqx_schema:duration(), #{ mapping => "gen_rpc.call_receive_timeout" , default => "15s" - , desc => "Timeout for the reply to a synchronous RPC." + , desc => ?DESC(rpc_call_receive_timeout) })} , {"socket_keepalive_idle", sc(emqx_schema:duration_s(), #{ mapping => "gen_rpc.socket_keepalive_idle" , default => "7200s" - , desc => "How long the connections between the brokers " - "should remain open after the last message is sent." + , desc => ?DESC(rpc_socket_keepalive_idle) + })} , {"socket_keepalive_interval", sc(emqx_schema:duration_s(), #{ mapping => "gen_rpc.socket_keepalive_interval" , default => "75s" - , desc => "The interval between keepalive messages." + , desc => ?DESC(rpc_socket_keepalive_interval) })} , {"socket_keepalive_count", sc(integer(), #{ mapping => "gen_rpc.socket_keepalive_count" , default => 9 - , desc => "How many times the keepalive probe message can fail to receive a reply " - "until the RPC connection is considered lost." + , desc => ?DESC(rpc_socket_keepalive_count) })} , {"socket_sndbuf", sc(emqx_schema:bytesize(), #{ mapping => "gen_rpc.socket_sndbuf" , default => "1MB" - , desc => "TCP tuning parameters. TCP sending buffer size." + , desc => ?DESC(rpc_socket_sndbuf) })} , {"socket_recbuf", sc(emqx_schema:bytesize(), #{ mapping => "gen_rpc.socket_recbuf" , default => "1MB" - , desc => "TCP tuning parameters. TCP receiving buffer size." + , desc => ?DESC(rpc_socket_recbuf) })} , {"socket_buffer", sc(emqx_schema:bytesize(), #{ mapping => "gen_rpc.socket_buffer" , default => "1MB" - , desc => "TCP tuning parameters. Socket buffer size in user mode." + , desc => ?DESC(rpc_socket_buffer) })} ]; @@ -1094,15 +1008,5 @@ emqx_schema_high_prio_roots() -> Roots = emqx_schema:roots(high), Authz = {"authorization", sc(hoconsc:ref(?MODULE, "authorization"), - #{ desc => """ -Authorization a.k.a. ACL.
-In EMQX, MQTT client access control is extremely flexible.
-An out-of-the-box set of authorization data sources are supported. -For example,
-'file' source is to support concise and yet generic ACL rules in a file;
-'built_in_database' source can be used to store per-client customizable rule sets, -natively in the EMQX node;
-'http' source to make EMQX call an external HTTP API to make the decision;
-'PostgreSQL' etc. to look up clients or rules from external databases;
-""" })}, + #{ desc => ?DESC(authorization)})}, lists:keyreplace("authorization", 1, Roots, Authz). diff --git a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf b/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf deleted file mode 100644 index 2a588b752..000000000 --- a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf +++ /dev/null @@ -1,12 +0,0 @@ -emqx_dashboard_schema { - protocol { - desc { - en: "Protocol Name" - zh: "协议名" - } - label: { - en: "Protocol" - zh: "协议" - } - } -} diff --git a/apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf b/apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf new file mode 100644 index 000000000..d7b2055bb --- /dev/null +++ b/apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf @@ -0,0 +1,190 @@ +emqx_dashboard_schema { + listeners { + desc { + en: """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.""" + zh: """仪表盘监听器设置。""" + } + label { + en: "Listeners" + zh: "监听器" + } + } + sample_interval { + desc { + en: """How often to update metrics displayed in the dashboard.
" +Note: `sample_interval` should be a divisor of 60.""" + zh: """更新仪表板中显示的指标的时间间隔。""" + } + } + token_expired_time { + desc { + en: "JWT token expiration time." + zh: "JWT token 过期时间" + } + label { + en: "Token expired time" + zh: "JWT 过期时间" + } + } + num_acceptors { + desc { + en: "Socket acceptor pool size for TCP protocols." + zh: "TCP协议的Socket acceptor池大小" + } + label { + en: "Number of acceptors" + zh: "Acceptor 数量" + } + } + max_connections { + desc { + en: "Maximum number of simultaneous connections." + zh: "同时处理的最大连接数" + } + label { + en: "Maximum connections" + zh: "最大连接数" + } + } + backlog { + desc { + en: "Defines the maximum length that the queue of pending connections can grow to." + zh: "排队等待连接的队列的最大长度" + } + label { + en: "Backlog" + zh: "排队长度" + } + } + send_timeout { + desc { + en: "Send timeout for the socket." + zh: "Socket发送超时时间" + } + label { + en: "Send timeout" + zh: "发送超时时间" + } + } + inet6 { + desc { + en: "Enable IPv6 support." + zh: "启用IPv6" + } + label { + en: "IPv6" + zh: "IPv6" + } + } + ipv6_v6only { + desc { + en: "Disable IPv4-to-IPv6 mapping for the listener." + zh: "禁用IPv4-to-IPv6映射" + } + label { + en: "IPv6 only" + zh: "IPv6 only" + } + } + desc_dashboard { + desc { + en: "Configuration for EMQX dashboard." + zh: "EMQX仪表板配置" + } + label { + en: "Dashboard" + zh: "仪表板" + } + } + desc_listeners { + desc { + en: "Configuration for the dashboard listener." + zh: "仪表板监听器配置" + } + label { + en: "Listeners" + zh: "监听器" + } + } + desc_http { + desc { + en: "Configuration for the dashboard listener (plaintext)." + zh: "仪表板监听器(HTTP)配置" + } + label { + en: "HTTP" + zh: "HTTP" + } + } + desc_https { + desc { + en: "Configuration for the dashboard listener (TLS)." + zh: "仪表板监听器(HTTPS)配置" + } + label { + en: "HTTPS" + zh: "HTTPS" + } + } + bind { + desc { + en: "Port without IP(18083) or port with specified IP(127.0.0.1:18083)." + zh: "监听的地址与端口" + } + label { + en: "Bind" + zh: "绑定端口" + } + } + default_username { + desc { + en: "The default username of the automatically created dashboard user." + zh: "默认的仪表板用户名" + } + label { + en: "Default username" + zh: "默认用户名" + } + } + default_password { + desc { + en: """The initial default password for dashboard 'admin' user.
" +For safety, it should be changed as soon as possible.""" + zh: """默认的仪表板用户密码
+为了安全,应该尽快修改密码。""" + } + label { + en: "Default password" + zh: "默认密码" + } + } + cors { + desc { + en: """Support Cross-Origin Resource Sharing (CORS).
+Allows a server to indicate any origins (domain, scheme, or port) other than
+允许服务器指示任何来源(域名、协议或端口),除了本服务器之外的任何浏览器应允许加载资源。""" + } + label { + en: "CORS" + zh: "跨域资源共享" + } + } + i18n_lang { + desc { + en: "Internationalization language support." + zh: "多语言支持" + } + label { + en: "I18n language" + zh: "多语言支持" + } + } +} diff --git a/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl b/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl index fbb294601..549c59184 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl @@ -313,7 +313,7 @@ next_interval() -> sample(Time) -> Fun = fun(Key, Res) -> - maps:put(Key, value(Key), Res) + maps:put(Key, getstats(Key), Res) end, Data = lists:foldl(Fun, #{}, ?SAMPLER_LIST), #emqx_monit{time = Time, data = Data}. @@ -362,11 +362,17 @@ count_map(M1, M2) -> end, lists:foldl(Fun, #{}, ?SAMPLER_LIST). -value(connections) -> emqx_stats:getstat('connections.count'); -value(topics) -> emqx_stats:getstat('topics.count'); -value(subscriptions) -> emqx_stats:getstat('subscriptions.count'); -value(received) -> emqx_metrics:val('messages.received'); -value(received_bytes) -> emqx_metrics:val('bytes.received'); -value(sent) -> emqx_metrics:val('messages.sent'); -value(sent_bytes) -> emqx_metrics:val('bytes.sent'); -value(dropped) -> emqx_metrics:val('messages.dropped'). +getstats(Key) -> + %% Stats ets maybe not exist when ekka join. + try stats(Key) + catch _: _ -> 0 + end. + +stats(connections) -> emqx_stats:getstat('connections.count'); +stats(topics) -> emqx_stats:getstat('topics.count'); +stats(subscriptions) -> emqx_stats:getstat('subscriptions.count'); +stats(received) -> emqx_metrics:val('messages.received'); +stats(received_bytes) -> emqx_metrics:val('bytes.received'); +stats(sent) -> emqx_metrics:val('messages.sent'); +stats(sent_bytes) -> emqx_metrics:val('bytes.sent'); +stats(dropped) -> emqx_metrics:val('messages.dropped'). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl index 6f187a694..4fb7b2abc 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl @@ -32,16 +32,7 @@ fields("dashboard") -> {listeners, sc( ref("listeners"), - #{ - desc => - "HTTP(s) listeners are identified by their protocol type and are\n" - "used to serve dashboard UI and restful HTTP API.
\n" - "Listeners must have a unique combination of port number and IP address.
\n" - "For example, an HTTP listener can listen on all configured IP addresses\n" - "on a given port for a machine by specifying the IP address 0.0.0.0.
\n" - "Alternatively, the HTTP listener can specify a unique IP address for each listener,\n" - "but use the same port." - } + #{ desc => ?DESC(listeners)} )}, {default_username, fun default_username/1}, {default_password, fun default_password/1}, @@ -50,9 +41,8 @@ fields("dashboard") -> emqx_schema:duration_s(), #{ default => "10s", - desc => - "How often to update metrics displayed in the dashboard.
" - "Note: `sample_interval` should be a divisor of 60." + desc => ?DESC(sample_interval), + validator => fun validate_sample_interval/1 } )}, {token_expired_time, @@ -60,7 +50,7 @@ fields("dashboard") -> emqx_schema:duration(), #{ default => "30m", - desc => "JWT token expiration time." + desc => ?DESC(token_expired_time) } )}, {cors, fun cors/1}, @@ -93,7 +83,7 @@ fields("http") -> integer(), #{ default => 4, - desc => "Socket acceptor pool size for TCP protocols." + desc => ?DESC(num_acceptors) } )}, {"max_connections", @@ -101,7 +91,7 @@ fields("http") -> integer(), #{ default => 512, - desc => "Maximum number of simultaneous connections." + desc => ?DESC(max_connections) } )}, {"backlog", @@ -109,8 +99,7 @@ fields("http") -> integer(), #{ default => 1024, - desc => - "Defines the maximum length that the queue of pending connections can grow to." + desc => ?DESC(backlog) } )}, {"send_timeout", @@ -118,7 +107,7 @@ fields("http") -> emqx_schema:duration(), #{ default => "5s", - desc => "Send timeout for the socket." + desc => ?DESC(send_timeout) } )}, {"inet6", @@ -126,7 +115,7 @@ fields("http") -> boolean(), #{ default => false, - desc => "Sets up the listener for IPv6." + desc => ?DESC(inet6) } )}, {"ipv6_v6only", @@ -134,7 +123,7 @@ fields("http") -> boolean(), #{ default => false, - desc => "Disable IPv4-to-IPv6 mapping for the listener." + desc => ?DESC(ipv6_v6only) } )} ]; @@ -145,27 +134,22 @@ fields("https") -> emqx_schema:server_ssl_opts_schema(#{}, true) ). -desc("dashboard") -> - "Configuration for EMQX dashboard."; -desc("listeners") -> - "Configuration for the dashboard listener."; -desc("http") -> - "Configuration for the dashboard listener (plaintext)."; -desc("https") -> - "Configuration for the dashboard listener (TLS)."; -desc(_) -> - undefined. +desc("dashboard") -> ?DESC(desc_dashboard); +desc("listeners") -> ?DESC(desc_listeners); +desc("http") -> ?DESC(desc_http); +desc("https") -> ?DESC(desc_https); +desc(_) -> undefined. bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]); bind(default) -> 18083; bind(required) -> true; -bind(desc) -> "Port without IP(18083) or port with specified IP(127.0.0.1:18083)."; +bind(desc) -> ?DESC(bind); bind(_) -> undefined. default_username(type) -> string(); default_username(default) -> "admin"; default_username(required) -> true; -default_username(desc) -> "The default username of the automatically created dashboard user."; +default_username(desc) -> ?DESC(default_username); default_username('readOnly') -> true; default_username(_) -> undefined. @@ -180,11 +164,7 @@ default_password('readOnly') -> default_password(sensitive) -> true; default_password(desc) -> - "" - "\n" - "The initial default password for dashboard 'admin' user.\n" - "For safety, it should be changed as soon as possible." - ""; + ?DESC(default_password); default_password(_) -> undefined. @@ -195,18 +175,22 @@ cors(default) -> cors(required) -> false; cors(desc) -> - "Support Cross-Origin Resource Sharing (CORS).\n" - "Allows a server to indicate any origins (domain, scheme, or port) other than\n" - "its own from which a browser should permit loading resources."; + ?DESC(cors); cors(_) -> undefined. i18n_lang(type) -> ?ENUM([en, zh]); i18n_lang(default) -> en; i18n_lang('readOnly') -> true; -i18n_lang(desc) -> "Internationalization language support."; +i18n_lang(desc) -> ?DESC(i18n_lang); i18n_lang(_) -> undefined. +validate_sample_interval(Second) -> + case Second >= 1 andalso Second =< 60 andalso (60 rem Second =:= 0) of + true -> ok; + false -> error({"Sample interval must be between 1 and 60 and be a divisor of 60.", Second}) + end. + sc(Type, Meta) -> hoconsc:mk(Type, Meta). ref(Field) -> hoconsc:ref(?MODULE, Field). diff --git a/apps/emqx_plugins/i18n/emqx_plugins_schema.conf b/apps/emqx_plugins/i18n/emqx_plugins_schema.conf new file mode 100644 index 000000000..2b88bbc6d --- /dev/null +++ b/apps/emqx_plugins/i18n/emqx_plugins_schema.conf @@ -0,0 +1,93 @@ +emqx_plugins_schema { + plugins { + desc { + en: """ +Manage EMQX plugins.
+Plugins can be pre-built as a part of EMQX package, +or installed as a standalone package in a location specified by +install_dir config key
+The standalone-installed plugins are referred to as 'external' plugins. +""" + zh: """管理EMQX插件。
+插件可以是EMQX安装包中的一部分,也可以是一个独立的安装包。
+独立安装的插件称为“外部插件”。 + """ + } + label { + en: "Plugins" + zh: "插件" + } + } + state { + desc { + en: "A per-plugin config to describe the desired state of the plugin." + zh: "描述插件的状态" + } + label { + en: "State" + zh: "插件状态" + } + } + name_vsn { + desc { + en: """The {name}-{version} of the plugin.
+It should match the plugin application name-version as the for the plugin release package name
+For example: my_plugin-0.1.0. +""" + zh: """插件的名称{name}-{version}。
+它应该与插件的发布包名称一致,如my_plugin-0.1.0。""" + } + label { + en: "Name-Version" + zh: "名称-版本" + } + } + enable { + desc { + en: "Set to 'true' to enable this plugin" + zh: "设置为“true”以启用此插件" + } + label { + en: "Enable" + zh: "启用" + } + } + states { + desc { + en: """An array of plugins in the desired states.
+The plugins are started in the defined order""" + zh: """一组插件的状态。插件将按照定义的顺序启动""" + } + label { + en: "States" + zh: "插件启动顺序及状态" + } + } + install_dir { + desc { + en: """ +The installation directory for the external plugins. +The plugin beam files and configuration files should reside in +the subdirectory named as emqx_foo_bar-0.1.0. +
+NOTE: For security reasons, this directory should **NOT** be writable +by anyone except emqx (or any user which runs EMQX). +""" + zh: "插件安装包的目录, 不要自己创建, 只能由emqx用户创建与修改" + } + label { + en: "Install Directory" + zh: "安装目录" + } + } + check_interval { + desc { + en: """Check interval: check if the status of the plugins in the cluster is consistent,
+if the results of 3 consecutive checks are not consistent, then alarm. +""" + zh: """检查间隔:检查集群中插件的状态是否一致,
+如果连续3次检查结果不一致,则报警。 +""" + } + } +} diff --git a/apps/emqx_plugins/src/emqx_plugins_schema.erl b/apps/emqx_plugins/src/emqx_plugins_schema.erl index b7498d2ee..eed85558c 100644 --- a/apps/emqx_plugins/src/emqx_plugins_schema.erl +++ b/apps/emqx_plugins/src/emqx_plugins_schema.erl @@ -23,7 +23,7 @@ , namespace/0 ]). --include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include("emqx_plugins.hrl"). namespace() -> "plugin". @@ -32,33 +32,22 @@ roots() -> [?CONF_ROOT]. fields(?CONF_ROOT) -> #{fields => root_fields(), - desc => """ -Manage EMQX plugins. -
-Plugins can be pre-built as a part of EMQX package, -or installed as a standalone package in a location specified by -install_dir config key -
-The standalone-installed plugins are referred to as 'external' plugins. -""" + desc => ?DESC(?CONF_ROOT) }; fields(state) -> #{ fields => state_fields(), - desc => "A per-plugin config to describe the desired state of the plugin." + desc => ?DESC(state) }. state_fields() -> [ {name_vsn, hoconsc:mk(string(), - #{ desc => "The {name}-{version} of the plugin.
" - "It should match the plugin application name-version as the " - "for the plugin release package name
" - "For example: my_plugin-0.1.0." + #{ desc => ?DESC(name_vsn) , required => true })} , {enable, hoconsc:mk(boolean(), - #{ desc => "Set to 'true' to enable this plugin" + #{ desc => ?DESC(enable) , required => true })} ]. @@ -72,27 +61,16 @@ root_fields() -> states(type) -> hoconsc:array(hoconsc:ref(?MODULE, state)); states(required) -> false; states(default) -> []; -states(desc) -> "An array of plugins in the desired states.
" - "The plugins are started in the defined order"; +states(desc) -> ?DESC(states); states(_) -> undefined. install_dir(type) -> string(); install_dir(required) -> false; install_dir(default) -> "plugins"; %% runner's root dir install_dir(T) when T =/= desc -> undefined; -install_dir(desc) -> """ -The installation directory for the external plugins. -The plugin beam files and configuration files should reside in -the subdirectory named as emqx_foo_bar-0.1.0. -
-NOTE: For security reasons, this directory should **NOT** be writable -by anyone except emqx (or any user which runs EMQX). -""". +install_dir(desc) -> ?DESC(install_dir). check_interval(type) -> emqx_schema:duration(); check_interval(default) -> "5s"; check_interval(T) when T =/= desc -> undefined; -check_interval(desc) -> """ -Check interval: check if the status of the plugins in the cluster is consistent,
-if the results of 3 consecutive checks are not consistent, then alarm. -""". +check_interval(desc) -> ?DESC(check_interval). diff --git a/scripts/merge-i18n.escript b/scripts/merge-i18n.escript index 13a7df27b..8a42cffe4 100755 --- a/scripts/merge-i18n.escript +++ b/scripts/merge-i18n.escript @@ -3,7 +3,7 @@ -mode(compile). main(_) -> - {ok, BaseConf} = file:read_file("apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf"), + {ok, BaseConf} = file:read_file("apps/emqx_dashboard/i18n/emqx_dashboard_schema.conf"), Cfgs = get_all_cfgs("apps/"), Conf = [merge(BaseConf, Cfgs),