Repository: robustmq/robustmq (language: rust)

Issue:
[RBIP][Feat][Subtask] Integrate the metrics required for connection jitter and use the official library
### Have you checked the documentation for submitting an Issue?

- [x] Yes.

### Search before asking

- [x] I have searched in the [issues](https://github.com/robustmq/robustmq/issues) and found no similar issues.


### Describe the subtask

1. Implement the client_connect metric.
2. Test if the metric works correctly.
3. Expose the metric content

### Parent issue

#775 

### Are you willing to submit PR?

- [ ] Yes. I would be willing to submit a PR with guidance from the RobustMQ community to improve.
- [x] No. I cannot submit a PR at this time.


Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 3b7edbe25..3678dab9f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1074,6 +1074,12 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
 
+[[package]]
+name = "dtoa"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653"
+
 [[package]]
 name = "dunce"
 version = "1.0.4"
@@ -2294,6 +2300,7 @@ dependencies = [
  "paho-mqtt",
  "placement-center",
  "prometheus",
+ "prometheus-client",
  "protocol",
  "regex",
  "rustls-pemfile",
@@ -2917,6 +2924,29 @@ dependencies = [
  "thiserror",
 ]
 
+[[package]]
+name = "prometheus-client"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf41c1a7c32ed72abe5082fb19505b969095c12da9f5732a4bc9878757fd087c"
+dependencies = [
+ "dtoa",
+ "itoa",
+ "parking_lot",
+ "prometheus-client-derive-encode",
+]
+
+[[package]]
+name = "prometheus-client-derive-encode"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.90",
+]
+
 [[package]]
 name = "prost"
 version = "0.12.3"
diff --git a/Cargo.toml b/Cargo.toml
index d6bb7e14d..fb0168f74 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -73,10 +73,12 @@ mockall = "0.13.1"
 ## text handle lib
 regex = "1.10.4"
 grep = "0.3.2"
-## other
-signal-hook = "0.3.17"
+## observability
 prometheus = "0.13.3"
 prometheus_exporter = "0.8"
+prometheus-client = "0.23.1"
+## other
+signal-hook = "0.3.17"
 lazy_static = "^1.4"
 thiserror = "1"
 bytes = { version = "1", features = ["serde"] }
diff --git a/docs/.design/observability/metrics.md b/docs/.design/observability/metrics.md
index a012f70d7..ddec5ff84 100644
--- a/docs/.design/observability/metrics.md
+++ b/docs/.design/observability/metrics.md
@@ -71,10 +71,10 @@
 
 # 消息分发指标
 
-| ｜ Metric Name                  | Description                |
-|--------------------------------|----------------------------|
-| ｜`delivery_dropped_too_large`  | 发送时由于长度超过限制而丢弃的消息数量        |
-| ｜`delivery_dropped_queue_full` | 发送时由于消息队列满而被丢弃的QoS不为0的消息数量 |
+| Metric Name                   | Description                |
+|-------------------------------|----------------------------|
+| `delivery_dropped_too_large`  | 发送时由于长度超过限制而丢弃的消息数量        |
+| `delivery_dropped_queue_full` | 发送时由于消息队列满而被丢弃的QoS不为0的消息数量 |
 
 
 # 统计指标
diff --git a/src/mqtt-broker/Cargo.toml b/src/mqtt-broker/Cargo.toml
index 589dae631..6d086708f 100644
--- a/src/mqtt-broker/Cargo.toml
+++ b/src/mqtt-broker/Cargo.toml
@@ -32,7 +32,6 @@ tonic.workspace = true
 dashmap.workspace = true
 serde.workspace = true
 lazy_static.workspace = true
-prometheus.workspace = true
 storage-adapter.workspace = true
 grpc-clients.workspace = true
 metadata-struct.workspace = true
@@ -51,3 +50,6 @@ ipnet.workspace = true
 os_info.workspace = true
 bincode.workspace = true
 grep.workspace = true
+# observability
+prometheus.workspace = true
+prometheus-client.workspace = true
diff --git a/src/mqtt-broker/src/observability/metrics/event_metrics.rs b/src/mqtt-broker/src/observability/metrics/event_metrics.rs
new file mode 100644
index 000000000..47e64d25c
--- /dev/null
+++ b/src/mqtt-broker/src/observability/metrics/event_metrics.rs
@@ -0,0 +1,91 @@
+// Copyright 2023 RobustMQ Team
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::observability::metrics::load_global_registry;
+use prometheus_client::encoding::EncodeLabelSet;
+use prometheus_client::metrics::counter::Counter;
+use prometheus_client::metrics::family::Family;
+use std::sync::LazyLock;
+
+/**
+For metrics related to counters,
+we typically name them in the format *xxx_counter* to indicate that they are of the counter type.
+If its type is *Family<>*, then we usually define labels as *xxxLabels*.
+For example, for *client_connection_counter*, its labels would be *ClientConnectionLabels*.
+*/
+static EVENT_METRICS: LazyLock<EventMetrics> = LazyLock::new(EventMetrics::init);
+
+#[derive(Eq, Hash, Clone, EncodeLabelSet, Debug, PartialEq)]
+struct ClientConnectionLabels {
+    client_id: String,
+}
+
+struct EventMetrics {
+    client_connection_counter: Family<ClientConnectionLabels, Counter>,
+}
+
+impl EventMetrics {
+    fn init() -> Self {
+        // init event_metrics
+        let event_metrics = Self {
+            client_connection_counter: Family::default(),
+        };
+
+        // get global registry
+        let mut global_registry = load_global_registry();
+
+        // register event_metrics
+        global_registry.register(
+            "client_connections",
+            "The number of client connections, regardless of success or failure.",
+            event_metrics.client_connection_counter.clone(),
+        );
+
+        // return event_metrics
+        event_metrics
+    }
+}
+
+pub fn incr_client_connection_counter(client_id: String) {
+    let labels = ClientConnectionLabels { client_id };
+
+    EVENT_METRICS
+        .client_connection_counter
+        .get_or_create(&labels)
+        .inc();
+}
+
+pub fn get_client_connection_counter(client_id: String) -> u64 {
+    let labels = ClientConnectionLabels { client_id };
+
+    EVENT_METRICS
+        .client_connection_counter
+        .get_or_create(&labels)
+        .get()
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::observability::metrics::event_metrics;
+
+    #[test]
+    fn test_incr_client_connection_counter() {
+        event_metrics::incr_client_connection_counter("test_client_1".to_string());
+
+        assert_eq!(
+            event_metrics::get_client_connection_counter("test_client_1".to_string()),
+            1
+        );
+    }
+}
diff --git a/src/mqtt-broker/src/observability/metrics/events.rs b/src/mqtt-broker/src/observability/metrics/events.rs
deleted file mode 100644
index 88041165f..000000000
--- a/src/mqtt-broker/src/observability/metrics/events.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2023 RobustMQ Team
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
diff --git a/src/mqtt-broker/src/observability/metrics/mod.rs b/src/mqtt-broker/src/observability/metrics/mod.rs
index 0aaf7c5a7..afed7eea2 100644
--- a/src/mqtt-broker/src/observability/metrics/mod.rs
+++ b/src/mqtt-broker/src/observability/metrics/mod.rs
@@ -12,9 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use prometheus_client::registry::Registry;
+use std::sync::{LazyLock, Mutex, MutexGuard};
+
 pub mod auth;
-pub mod events;
+pub mod event_metrics;
 pub mod packets;
 pub mod publish;
 pub mod server;
 pub mod session;
+
+pub static REGISTRY: LazyLock<Mutex<Registry>> = LazyLock::new(|| Mutex::new(Registry::default()));
+
+pub fn load_global_registry() -> MutexGuard<'static, Registry> {
+    REGISTRY.lock().unwrap()
+}


Test patch: