Explorar o código

fix: telemetry & topic metrics support i18n

DDDHuang %!s(int64=3) %!d(string=hai) anos
pai
achega
de7c15dd19

+ 121 - 0
apps/emqx_modules/i18n/emqx_telemetry_api_i18n.conf

@@ -0,0 +1,121 @@
+emqx_telemetry_api {
+
+  get_telemetry_status_api {
+    desc {
+      en: """Get telemetry status"""
+      zh: """获取遥测状态"""
+    }
+  }
+
+  update_telemetry_status_api {
+    desc {
+      en: """Enable or disable telemetry"""
+      zh: """更新遥测状态"""
+    }
+  }
+
+  get_telemetry_data_api {
+    desc {
+      en: """Get telemetry data"""
+      zh: """获取遥测数据"""
+    }
+  }
+
+  enable {
+    desc {
+      en: """Enable telemetry"""
+      zh: """启用遥测"""
+    }
+  }
+
+  emqx_version {
+    desc {
+      en: """Get emqx version"""
+      zh: """获取 emqx 版本"""
+    }
+  }
+
+  license {
+    desc {
+      en: """Get license information"""
+      zh: """获取 license 信息"""
+    }
+  }
+
+  os_name {
+    desc {
+      en: """Get OS name"""
+      zh: """获取操作系统名称"""
+    }
+  }
+
+    os_version {
+        desc {
+        en: """Get OS version"""
+        zh: """获取操作系统版本"""
+        }
+    }
+
+    otp_version {
+        desc {
+        en: """Get Erlang OTP version"""
+        zh: """获取 OTP 版本"""
+        }
+    }
+
+    up_time {
+        desc {
+        en: """Get uptime"""
+        zh: """获取运行时间"""
+        }
+    }
+
+    uuid {
+        desc {
+        en: """Get UUID"""
+        zh: """获取 UUID"""
+        }
+    }
+
+    nodes_uuid {
+        desc {
+        en: """Get nodes UUID"""
+        zh: """获取节点 UUID"""
+        }
+    }
+
+    active_plugins {
+        desc {
+        en: """Get active plugins"""
+        zh: """获取活跃插件"""
+        }
+    }
+
+    active_modules {
+        desc {
+        en: """Get active modules"""
+        zh: """获取活跃模块"""
+        }
+    }
+
+    num_clients {
+        desc {
+        en: """Get number of clients"""
+        zh: """获取客户端数量"""
+        }
+    }
+
+    messages_received {
+        desc {
+        en: """Get number of messages received"""
+        zh: """获取接收到的消息数量"""
+        }
+    }
+
+    messages_sent {
+        desc {
+        en: """Get number of messages sent"""
+        zh: """获取发送的消息数量"""
+        }
+    }
+}

+ 238 - 0
apps/emqx_modules/i18n/emqx_topic_metrics_api_i18n.conf

@@ -0,0 +1,238 @@
+emqx_topic_metrics_api {
+  get_topic_metrics_api {
+    desc {
+      en: """List Topic metrics"""
+      zh: """获取主题监控数据"""
+    }
+  }
+
+  reset_topic_metrics_api{
+    desc {
+      en: """Reset telemetry status"""
+      zh: """重置主题监控状态"""
+    }
+  }
+
+  post_topic_metrics_api {
+    desc {
+      en: """Create Topic metrics"""
+      zh: """创建主题监控数据"""
+    }
+  }
+
+  gat_topic_metrics_data_api {
+    desc {
+      en: """Get Topic metrics"""
+      zh: """获取主题监控数据"""
+    }
+  }
+
+  delete_topic_metrics_data_api {
+    desc {
+      en: """Delete Topic metrics"""
+      zh: """删除主题监控数据"""
+    }
+  }
+
+  topic_metrics_api_response409 {
+    desc {
+      en: """Conflict. Topic metrics exceeded max limit 512"""
+      zh: """冲突。主题监控数据超过最大限制512"""
+    }
+  }
+
+  topic_metrics_api_response400 {
+    desc {
+      en: """Bad Request. Already exists or bad topic name"""
+      zh: """错误请求。已存在或错误的主题名称"""
+    }
+  }
+
+   topic_metrics_api_response404 {
+    desc {
+      en: """Not Found. Topic metrics not found"""
+      zh: """未找到。主题监控数据未找到"""
+    }
+   }
+
+  reset_topic_desc {
+      en: """Topic Name. If this parameter is not present,all created topic metrics will be reset."""
+      zh: """主题名称。如果此参数不存在,则所有创建的主题监控数据都将重置。"""
+    }
+
+  topic {
+      desc {
+        en: """Topic"""
+        zh: """主题"""
+      }
+  }
+
+  topic_in_body {
+    desc {
+      en: """Raw topic string"""
+      zh: """主题字符串"""
+    }
+  }
+
+  topic_in_path {
+    desc {
+      en: """Topic string. Notice: Topic string in url path must be encoded"""
+      zh: """主题字符串。注意:主题字符串在url路径中必须编码"""
+    }
+  }
+
+  action {
+      desc {
+        en: """Action. Only support reset"""
+        zh: """操作,仅支持 reset"""
+      }
+  }
+
+  create_time {
+      desc {
+        en: """Create time"""
+        zh: """创建时间。标准 rfc3339 时间格式,例如:2018-01-01T12:00:00Z"""
+      }
+  }
+
+  reset_time {
+      desc {
+        en: """Reset time. In rfc3339. Nullable if never reset"""
+        zh: """重置时间。标准 rfc3339 时间格式,例如:2018-01-01T12:00:00Z。如果从未重置则为空"""
+      }
+  }
+
+  metrics {
+      desc {
+        en: """Metrics"""
+        zh: """监控数据"""
+      }
+  }
+
+  message_dropped_count {
+      desc {
+          en: """Dropped messages count"""
+          zh: """丢弃消息数量"""
+      }
+    }
+
+  message_dropped_rate {
+      desc {
+          en: """Dropped messages rate"""
+          zh: """丢弃消息速率"""
+      }
+    }
+
+  message_in_count {
+      desc {
+          en: """In messages count"""
+          zh: """接收消息数量"""
+      }
+    }
+
+    message_in_rate {
+        desc {
+            en: """In messages rate"""
+            zh: """接收消息速率"""
+        }
+    }
+
+    message_out_count {
+        desc {
+            en: """Out messages count"""
+            zh: """发送消息数量"""
+        }
+    }
+
+    message_out_rate {
+        desc {
+            en: """Out messages rate"""
+            zh: """发送消息速率"""
+        }
+    }
+
+    message_qos0_in_count {
+        desc {
+            en: """QoS0 in messages count"""
+            zh: """QoS0 接收消息数量"""
+        }
+    }
+
+    message_qos0_in_rate {
+        desc {
+            en: """QoS0 in messages rate"""
+            zh: """QoS0 接收消息速率"""
+        }
+    }
+
+    message_qos0_out_count {
+        desc {
+            en: """QoS0 out messages count"""
+            zh: """QoS0 发送消息数量"""
+        }
+    }
+
+    message_qos0_out_rate {
+        desc {
+            en: """QoS0 out messages rate"""
+            zh: """QoS0 发送消息速率"""
+        }
+    }
+
+    message_qos1_in_count {
+        desc {
+            en: """QoS1 in messages count"""
+            zh: """QoS1 接收消息数量"""
+        }
+    }
+
+    message_qos1_in_rate {
+        desc {
+            en: """QoS1 in messages rate"""
+            zh: """QoS1 接收消息速率"""
+        }
+    }
+
+    message_qos1_out_count {
+        desc {
+            en: """QoS1 out messages count"""
+            zh: """QoS1 发送消息数量"""
+        }
+    }
+
+    message_qos1_out_rate {
+        desc {
+            en: """QoS1 out messages rate"""
+            zh: """QoS1 发送消息速率"""
+        }
+    }
+
+    message_qos2_in_count {
+        desc {
+            en: """QoS2 in messages count"""
+            zh: """QoS2 接收消息数量"""
+        }
+    }
+
+    message_qos2_in_rate {
+        desc {
+            en: """QoS2 in messages rate"""
+            zh: """QoS2 接收消息速率"""
+        }
+    }
+
+    message_qos2_out_count {
+        desc {
+            en: """QoS2 out messages count"""
+            zh: """QoS2 发送消息数量"""
+        }
+    }
+
+    message_qos2_out_rate {
+        desc {
+            en: """QoS2 out messages rate"""
+            zh: """QoS2 发送消息速率"""
+        }
+    }
+
+}

+ 22 - 22
apps/emqx_modules/src/emqx_telemetry_api.erl

@@ -18,6 +18,7 @@
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
+-include_lib("hocon/include/hoconsc.hrl").
 -include_lib("typerefl/include/types.hrl").
 -include_lib("typerefl/include/types.hrl").
 
 
 -import(hoconsc, [mk/2, ref/1, ref/2, array/1]).
 -import(hoconsc, [mk/2, ref/1, ref/2, array/1]).
@@ -50,18 +51,17 @@ schema("/telemetry/status") ->
         'operationId' => status,
         'operationId' => status,
         get =>
         get =>
             #{
             #{
-                description => <<"Get telemetry status">>,
+                description => ?DESC(get_telemetry_status_api),
                 responses =>
                 responses =>
-                    #{200 => status_schema(<<"Get telemetry status">>)}
+                    #{200 => status_schema(?DESC(get_telemetry_status_api))}
             },
             },
         put =>
         put =>
             #{
             #{
-                description => <<"Enable or disable telemetry">>,
-                'requestBody' => status_schema(<<"Enable or disable telemetry">>),
+                description => ?DESC(update_telemetry_status_api),
+                'requestBody' => status_schema(?DESC(update_telemetry_status_api)),
                 responses =>
                 responses =>
                     #{
                     #{
-                        200 => status_schema(<<"Enable or disable telemetry successfully">>),
-                        400 => emqx_dashboard_swagger:error_codes([?BAD_REQUEST], <<"Bad Request">>)
+                        200 => status_schema(?DESC(update_telemetry_status_api))
                     }
                     }
             }
             }
     };
     };
@@ -70,9 +70,9 @@ schema("/telemetry/data") ->
         'operationId' => data,
         'operationId' => data,
         get =>
         get =>
             #{
             #{
-                description => <<"Get telemetry data">>,
+                description => ?DESC(get_telemetry_data_api),
                 responses =>
                 responses =>
-                    #{200 => mk(ref(?MODULE, telemetry), #{desc => <<"Get telemetry data">>})}
+                    #{200 => mk(ref(?MODULE, telemetry), #{desc => ?DESC(get_telemetry_data_api)})}
             }
             }
     }.
     }.
 
 
@@ -85,7 +85,7 @@ fields(status) ->
             mk(
             mk(
                 boolean(),
                 boolean(),
                 #{
                 #{
-                    desc => <<"Telemetry status">>,
+                    desc => ?DESC(enable),
                     default => true,
                     default => true,
                     example => false
                     example => false
                 }
                 }
@@ -97,7 +97,7 @@ fields(telemetry) ->
             mk(
             mk(
                 string(),
                 string(),
                 #{
                 #{
-                    desc => <<"EMQX Version">>,
+                    desc => ?DESC(emqx_version),
                     example => <<"5.0.0-beta.3-32d1547c">>
                     example => <<"5.0.0-beta.3-32d1547c">>
                 }
                 }
             )},
             )},
@@ -105,7 +105,7 @@ fields(telemetry) ->
             mk(
             mk(
                 map(),
                 map(),
                 #{
                 #{
-                    desc => <<"EMQX License">>,
+                    desc => ?DESC(license),
                     example => #{edition => <<"community">>}
                     example => #{edition => <<"community">>}
                 }
                 }
             )},
             )},
@@ -113,7 +113,7 @@ fields(telemetry) ->
             mk(
             mk(
                 string(),
                 string(),
                 #{
                 #{
-                    desc => <<"OS Name">>,
+                    desc => ?DESC(os_name),
                     example => <<"Linux">>
                     example => <<"Linux">>
                 }
                 }
             )},
             )},
@@ -121,7 +121,7 @@ fields(telemetry) ->
             mk(
             mk(
                 string(),
                 string(),
                 #{
                 #{
-                    desc => <<"OS Version">>,
+                    desc => ?DESC(os_version),
                     example => <<"20.04">>
                     example => <<"20.04">>
                 }
                 }
             )},
             )},
@@ -129,7 +129,7 @@ fields(telemetry) ->
             mk(
             mk(
                 string(),
                 string(),
                 #{
                 #{
-                    desc => <<"Erlang/OTP Version">>,
+                    desc => ?DESC(otp_version),
                     example => <<"24">>
                     example => <<"24">>
                 }
                 }
             )},
             )},
@@ -137,7 +137,7 @@ fields(telemetry) ->
             mk(
             mk(
                 integer(),
                 integer(),
                 #{
                 #{
-                    desc => <<"EMQX Runtime">>,
+                    desc => ?DESC(up_time),
                     example => 20220113
                     example => 20220113
                 }
                 }
             )},
             )},
@@ -145,7 +145,7 @@ fields(telemetry) ->
             mk(
             mk(
                 string(),
                 string(),
                 #{
                 #{
-                    desc => <<"EMQX UUID">>,
+                    desc => ?DESC(uuid),
                     example => <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>
                     example => <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>
                 }
                 }
             )},
             )},
@@ -153,7 +153,7 @@ fields(telemetry) ->
             mk(
             mk(
                 array(binary()),
                 array(binary()),
                 #{
                 #{
-                    desc => <<"EMQX Cluster Nodes UUID">>,
+                    desc => ?DESC(nodes_uuid),
                     example => [
                     example => [
                         <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>,
                         <<"AAAAAAAA-BBBB-CCCC-2022-DDDDEEEEFFF">>,
                         <<"ZZZZZZZZ-CCCC-BBBB-2022-DDDDEEEEFFF">>
                         <<"ZZZZZZZZ-CCCC-BBBB-2022-DDDDEEEEFFF">>
@@ -164,7 +164,7 @@ fields(telemetry) ->
             mk(
             mk(
                 array(binary()),
                 array(binary()),
                 #{
                 #{
-                    desc => <<"EMQX Active Plugins">>,
+                    desc => ?DESC(active_plugins),
                     example => [<<"Plugin A">>, <<"Plugin B">>]
                     example => [<<"Plugin A">>, <<"Plugin B">>]
                 }
                 }
             )},
             )},
@@ -172,7 +172,7 @@ fields(telemetry) ->
             mk(
             mk(
                 array(binary()),
                 array(binary()),
                 #{
                 #{
-                    desc => <<"EMQX Active Modules">>,
+                    desc => ?DESC(active_modules),
                     example => [<<"Module A">>, <<"Module B">>]
                     example => [<<"Module A">>, <<"Module B">>]
                 }
                 }
             )},
             )},
@@ -180,7 +180,7 @@ fields(telemetry) ->
             mk(
             mk(
                 integer(),
                 integer(),
                 #{
                 #{
-                    desc => <<"EMQX Current Connections">>,
+                    desc => ?DESC(num_clients),
                     example => 20220113
                     example => 20220113
                 }
                 }
             )},
             )},
@@ -188,7 +188,7 @@ fields(telemetry) ->
             mk(
             mk(
                 integer(),
                 integer(),
                 #{
                 #{
-                    desc => <<"EMQX Current Received Message">>,
+                    desc => ?DESC(messages_received),
                     example => 2022
                     example => 2022
                 }
                 }
             )},
             )},
@@ -196,7 +196,7 @@ fields(telemetry) ->
             mk(
             mk(
                 integer(),
                 integer(),
                 #{
                 #{
-                    desc => <<"EMQX Current Sent Message">>,
+                    desc => ?DESC(messages_sent),
                     example => 2022
                     example => 2022
                 }
                 }
             )}
             )}

+ 57 - 174
apps/emqx_modules/src/emqx_topic_metrics_api.erl

@@ -18,6 +18,7 @@
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
+-include_lib("hocon/include/hoconsc.hrl").
 -include_lib("typerefl/include/types.hrl").
 -include_lib("typerefl/include/types.hrl").
 -include("emqx_modules.hrl").
 -include("emqx_modules.hrl").
 
 
@@ -68,19 +69,19 @@ schema("/mqtt/topic_metrics") ->
         'operationId' => topic_metrics,
         'operationId' => topic_metrics,
         get =>
         get =>
             #{
             #{
-                description => <<"List topic metrics">>,
+                description => ?DESC(get_topic_metrics_api),
                 tags => ?API_TAG_MQTT,
                 tags => ?API_TAG_MQTT,
                 responses =>
                 responses =>
                     #{
                     #{
                         200 =>
                         200 =>
                             mk(array(hoconsc:ref(topic_metrics)), #{
                             mk(array(hoconsc:ref(topic_metrics)), #{
-                                desc => <<"List all topic metrics">>
+                                desc => ?DESC(get_topic_metrics_api)
                             })
                             })
                     }
                     }
             },
             },
         put =>
         put =>
             #{
             #{
-                description => <<"Reset topic metrics by topic name. Or reset all Topic Metrics">>,
+                description => ?DESC(reset_topic_metrics_api),
                 tags => ?API_TAG_MQTT,
                 tags => ?API_TAG_MQTT,
                 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
                 'requestBody' => emqx_dashboard_swagger:schema_with_examples(
                     ref(reset),
                     ref(reset),
@@ -88,28 +89,28 @@ schema("/mqtt/topic_metrics") ->
                 ),
                 ),
                 responses =>
                 responses =>
                     #{
                     #{
-                        204 => <<"Reset topic metrics successfully">>,
+                        204 => ?DESC(reset_topic_metrics_api),
                         404 =>
                         404 =>
                             emqx_dashboard_swagger:error_codes(
                             emqx_dashboard_swagger:error_codes(
-                                [?TOPIC_NOT_FOUND], <<"Topic not found">>
+                                [?TOPIC_NOT_FOUND], ?DESC(topic_metrics_api_response404)
                             )
                             )
                     }
                     }
             },
             },
         post =>
         post =>
             #{
             #{
-                description => <<"Create topic metrics">>,
+                description => ?DESC(post_topic_metrics_api),
                 tags => ?API_TAG_MQTT,
                 tags => ?API_TAG_MQTT,
                 'requestBody' => [topic(body)],
                 'requestBody' => [topic(body)],
                 responses =>
                 responses =>
                     #{
                     #{
-                        204 => <<"Create topic metrics success">>,
+                        204 => ?DESC(post_topic_metrics_api),
                         409 => emqx_dashboard_swagger:error_codes(
                         409 => emqx_dashboard_swagger:error_codes(
                             [?EXCEED_LIMIT],
                             [?EXCEED_LIMIT],
-                            <<"Topic metrics exceeded max limit 512">>
+                            ?DESC(topic_metrics_api_response409)
                         ),
                         ),
                         400 => emqx_dashboard_swagger:error_codes(
                         400 => emqx_dashboard_swagger:error_codes(
                             [?BAD_REQUEST, ?BAD_TOPIC],
                             [?BAD_REQUEST, ?BAD_TOPIC],
-                            <<"Topic metrics already existed or bad topic">>
+                            ?DESC(topic_metrics_api_response400)
                         )
                         )
                     }
                     }
             }
             }
@@ -119,29 +120,29 @@ schema("/mqtt/topic_metrics/:topic") ->
         'operationId' => operate_topic_metrics,
         'operationId' => operate_topic_metrics,
         get =>
         get =>
             #{
             #{
-                description => <<"Get topic metrics">>,
+                description => ?DESC(gat_topic_metrics_data_api),
                 tags => ?API_TAG_MQTT,
                 tags => ?API_TAG_MQTT,
                 parameters => [topic(path)],
                 parameters => [topic(path)],
                 responses =>
                 responses =>
                     #{
                     #{
-                        200 => mk(ref(topic_metrics), #{desc => <<"Topic metrics">>}),
+                        200 => mk(ref(topic_metrics), #{desc => ?DESC(topic)}),
                         404 => emqx_dashboard_swagger:error_codes(
                         404 => emqx_dashboard_swagger:error_codes(
                             [?TOPIC_NOT_FOUND],
                             [?TOPIC_NOT_FOUND],
-                            <<"Topic not found">>
+                            ?DESC(topic_metrics_api_response404)
                         )
                         )
                     }
                     }
             },
             },
         delete =>
         delete =>
             #{
             #{
-                description => <<"Remove the topic metrics">>,
+                description => ?DESC(delete_topic_metrics_data_api),
                 tags => ?API_TAG_MQTT,
                 tags => ?API_TAG_MQTT,
                 parameters => [topic(path)],
                 parameters => [topic(path)],
                 responses =>
                 responses =>
                     #{
                     #{
-                        204 => <<"Removed topic metrics successfully">>,
+                        204 => ?DESC(delete_topic_metrics_data_api),
                         404 => emqx_dashboard_swagger:error_codes(
                         404 => emqx_dashboard_swagger:error_codes(
                             [?TOPIC_NOT_FOUND],
                             [?TOPIC_NOT_FOUND],
-                            <<"Topic not found">>
+                            ?DESC(topic_metrics_api_response404)
                         )
                         )
                     }
                     }
             }
             }
@@ -153,11 +154,7 @@ fields(reset) ->
             mk(
             mk(
                 binary(),
                 binary(),
                 #{
                 #{
-                    desc =>
-                        <<
-                            "Topic Name. If this parameter is not present,"
-                            " all created topic metrics will be reset"
-                        >>,
+                    desc => ?DESC(reset_topic_desc),
                     example => <<"testtopic/1">>,
                     example => <<"testtopic/1">>,
                     required => false
                     required => false
                 }
                 }
@@ -166,7 +163,7 @@ fields(reset) ->
             mk(
             mk(
                 string(),
                 string(),
                 #{
                 #{
-                    desc => <<"Action Name. Only as a \"reset\"">>,
+                    desc => ?DESC(action),
                     enum => [reset],
                     enum => [reset],
                     required => true,
                     required => true,
                     example => <<"reset">>
                     example => <<"reset">>
@@ -179,7 +176,7 @@ fields(topic_metrics) ->
             mk(
             mk(
                 binary(),
                 binary(),
                 #{
                 #{
-                    desc => <<"Topic Name">>,
+                    desc => ?DESC(topic),
                     example => <<"testtopic/1">>,
                     example => <<"testtopic/1">>,
                     required => true
                     required => true
                 }
                 }
@@ -188,7 +185,7 @@ fields(topic_metrics) ->
             mk(
             mk(
                 emqx_datetime:epoch_second(),
                 emqx_datetime:epoch_second(),
                 #{
                 #{
-                    desc => <<"Topic Metrics created date time, in rfc3339">>,
+                    desc => ?DESC(create_time),
                     required => true,
                     required => true,
                     example => <<"2022-01-14T21:48:47+08:00">>
                     example => <<"2022-01-14T21:48:47+08:00">>
                 }
                 }
@@ -197,8 +194,7 @@ fields(topic_metrics) ->
             mk(
             mk(
                 emqx_datetime:epoch_second(),
                 emqx_datetime:epoch_second(),
                 #{
                 #{
-                    desc =>
-                        <<"Topic Metrics reset date time, in rfc3339. Nullable if never reset">>,
+                    desc => ?DESC(reset_time),
                     required => false,
                     required => false,
                     example => <<"2022-01-14T21:48:47+08:00">>
                     example => <<"2022-01-14T21:48:47+08:00">>
                 }
                 }
@@ -207,164 +203,51 @@ fields(topic_metrics) ->
             mk(
             mk(
                 ref(metrics),
                 ref(metrics),
                 #{
                 #{
-                    desc => <<"Topic Metrics fields">>,
+                    desc => ?DESC(metrics),
                     required => true
                     required => true
                 }
                 }
             )}
             )}
     ];
     ];
 fields(metrics) ->
 fields(metrics) ->
-    [
-        {'messages.dropped.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message dropped count">>,
-                    example => 0
-                }
-            )},
-        {'messages.dropped.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message dropped rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.in.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message received count">>,
-                    example => 0
-                }
-            )},
-        {'messages.in.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message received rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.out.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message sent count">>,
-                    example => 0
-                }
-            )},
-        {'messages.out.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message sent rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos0.in.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message with QoS 0 received count">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos0.in.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message with QoS 0 received rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos0.out.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message with QoS 0 sent count">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos0.out.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message with QoS 0 sent rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos1.in.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message with QoS 1 received count">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos1.in.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message with QoS 1 received rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos1.out.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message with QoS 1 sent count">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos1.out.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message with QoS 1 sent rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos2.in.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message with QoS 2 sent count">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos2.in.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message with QoS 2 received rate in 5s">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos2.out.count',
-            mk(
-                integer(),
-                #{
-                    desc => <<"Message with QoS 2 sent count">>,
-                    example => 0
-                }
-            )},
-        {'messages.qos2.out.rate',
-            mk(
-                number(),
-                #{
-                    desc => <<"Message with QoS 2 sent rate in 5s">>,
-                    example => 0
-                }
-            )}
-    ].
+    Integers = [
+        'message.dropped.count',
+        'message.in.count',
+        'message.out.count',
+        'message.qos0.in.count',
+        'message.qos0.out.count',
+        'message.qos1.in.count',
+        'message.qos1.out.count',
+        'message.qos2.in.count',
+        'message.qos2.out.count'
+    ],
+    Numbers = [
+        'message.dropped.rate',
+        'message.in.rate',
+        'message.out.rate',
+        'message.qos0.in.rate',
+        'message.qos0.out.rate',
+        'message.qos1.in.rate',
+        'message.qos1.out.rate',
+        'message.qos2.in.rate',
+        'message.qos2.out.rate'
+    ],
+    ToDesc =
+        fun(Key) ->
+            %% message.dropped.rate -> message_dropped_rate
+            Str = string:replace(atom_to_binary(Key, utf8), ".", "_", all),
+            NKey = binary_to_atom(list_to_binary(Str), utf8),
+            ?DESC(NKey)
+        end,
+    [{Key, mk(integer(), #{desc => ToDesc(Key), example => 0})} || Key <- Integers]
+    ++
+    [{Key, mk(number(), #{desc => ToDesc(Key), example => 0})} || Key <- Numbers].
+
 
 
 topic(In) ->
 topic(In) ->
     Desc =
     Desc =
         case In of
         case In of
-            body -> <<"Raw topic string">>;
-            path -> <<"Notice: Topic string in url path must be encoded">>
+            body -> ?DESC(topic_in_body);
+            path -> ?DESC(topic_in_path)
         end,
         end,
     {topic,
     {topic,
         mk(
         mk(