Skip to content

Commit 54b0400

Browse files
authored
Small fixes (#17)
* Rework metrics storage * Delete old sub/info page * ff
1 parent 3ef1b3e commit 54b0400

22 files changed

Lines changed: 469 additions & 539 deletions

File tree

.zed/tasks.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
"label": "Run agent",
1111
"command": "cargo run --bin agent -- dev/config-agent.toml ",
1212
},
13+
{
14+
"label": "Run agent2",
15+
"command": "cargo run --bin agent -- dev/config-agent2.toml ",
16+
},
17+
{
18+
"label": "Run agent3",
19+
"command": "cargo run --bin agent -- dev/config-agent3.toml ",
20+
},
1321
{
1422
"label": "Run api",
1523
"command": "cargo run --bin api -- dev/config-api.toml ",

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,15 @@ Pony is a lightweight control plane and orchestration platform for modern proxy
88

99
Contains parts
1010

11-
- agent — manages Xray/Wireguard(in progress) connections/users/metrics
11+
- agent — manages Xray/Wireguard/Hysteria2 connections/users/metrics
1212
- api — manages cluster of servers, gets API calls and send commands to servers
13-
- auth — handles auth for Hysteri2 cleints
13+
- auth — handles auth for Hysteri2 cleints
1414
- utils — helper to work/debug Bin messages
1515

1616
### As dependencies the platfrom has
1717

1818
- ZeroMQ — communicating bus
1919
- PostgreSQL — user and node data storage
20-
- Clickhouse — metrics storage
21-
- Carbon — metrics relay
2220
- Xray Core
2321
- Hysteria2
2422
- MTproto

config-agent-example.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ xray_config_path = "/etc/xray/config.json"
1111
enabled = true
1212
port = 51820
1313
interface = "wg0"
14-
# privkey и address обычно лучше через env, но можно и тут
1514

1615
[h2]
1716
enabled = false

config-api-example.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
address = "0.0.0.0"
33
port = 3005
44
token = "your-super-secret-api-token"
5-
metrics_enabled = true
6-
metrics_interval = 60
75
db_sync_interval_sec = 300
86
subscription_restore_interval = 60
97
subscription_expire_interval = 60
108
max_points = 100000000
119
retention_seconds = 604800 # 7 days
1210

11+
[metrics]
12+
reciever = "tcp://0.0.0.0:3001"
13+
topic = ["metrics"]
14+
1315
[node]
1416
env = "experimental"
1517
label = "🏴‍☠️ DarkMachine"

dev/dev.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,13 @@ DROP TABLE keys;
124124

125125
DROP TYPE node_status;
126126
DROP TYPE proto;
127+
128+
129+
130+
131+
===
132+
133+
CREATE TYPE node_type AS ENUM ('common', 'premium');
134+
135+
ALTER TABLE nodes
136+
ADD COLUMN node_type node_type NOT NULL DEFAULT 'common';

src/bin/agent/core/http.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use async_trait::async_trait;
2+
use pony::memory::node::Type;
23
use reqwest::Client as HttpClient;
34
use reqwest::StatusCode;
45
use reqwest::Url;
@@ -35,6 +36,7 @@ pub struct NodeRequest {
3536
pub cores: usize,
3637
pub max_bandwidth_bps: i64,
3738
pub country: String,
39+
pub r#type: Type,
3840
}
3941

4042
#[async_trait]
@@ -150,6 +152,7 @@ where
150152
cores: node.cores,
151153
max_bandwidth_bps: node.max_bandwidth_bps,
152154
country: node.country,
155+
r#type: node.r#type,
153156
};
154157

155158
let res = HttpClient::new()

src/bin/api/core/http/filters.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ where
2222
warp::any().map(move || mem_sync.clone())
2323
}
2424

25-
pub fn with_param_string(
26-
param: String,
27-
) -> impl Filter<Extract = (String,), Error = std::convert::Infallible> + Clone {
28-
warp::any().map(move || param.clone())
29-
}
30-
3125
pub fn with_param_vec(
3226
param: Vec<u8>,
3327
) -> impl Filter<Extract = (Vec<u8>,), Error = std::convert::Infallible> + Clone {

src/bin/api/core/http/handlers/metrics.rs

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
use chrono::Utc;
2+
use futures::{SinkExt, StreamExt};
3+
use std::collections::BTreeMap;
14
use std::sync::Arc;
25

36
use pony::metrics::storage::MetricStorage;
47

58
pub async fn handle_ws_client(
69
socket: warp::ws::WebSocket,
710
node_id: uuid::Uuid,
8-
metric: String,
11+
series_hash: u64,
912
storage: Arc<MetricStorage>,
1013
) {
11-
use futures::{SinkExt, StreamExt};
1214
let (mut ws_tx, _) = socket.split();
1315
let mut ticker = tokio::time::interval(std::time::Duration::from_millis(1000));
1416

@@ -18,19 +20,71 @@ pub async fn handle_ws_client(
1820
let now_ms = chrono::Utc::now().timestamp_millis();
1921
let ten_min_ago_ms = now_ms - (10 * 60 * 1000);
2022

21-
let points = storage.get_range(&node_id, &metric, ten_min_ago_ms, now_ms);
23+
let points = storage.get_range(&node_id, series_hash, ten_min_ago_ms, now_ms);
2224

2325
if !points.is_empty() {
24-
let chart_points: Vec<serde_json::Value> = points
25-
.into_iter()
26-
.map(|p| serde_json::json!({ "x": p.timestamp, "y": p.value }))
27-
.collect();
28-
29-
if let Ok(msg) = serde_json::to_string(&chart_points) {
30-
if let Err(e) = ws_tx.send(warp::ws::Message::text(msg)).await {
31-
log::error!("WS send error: {}", e);
32-
break;
33-
}
26+
let msg = serde_json::json!({
27+
"type": "update",
28+
"node_id": node_id,
29+
"hash": series_hash,
30+
"data": points.iter().map(|p| (p.timestamp, p.value)).collect::<Vec<_>>()
31+
});
32+
33+
if ws_tx
34+
.send(warp::ws::Message::text(msg.to_string()))
35+
.await
36+
.is_err()
37+
{
38+
break;
39+
}
40+
}
41+
}
42+
}
43+
44+
pub async fn handle_aggregated_ws(
45+
socket: warp::ws::WebSocket,
46+
tag_key: String,
47+
tag_value: String,
48+
metric_name: String,
49+
storage: Arc<MetricStorage>,
50+
) {
51+
let (mut ws_tx, _) = socket.split();
52+
let mut ticker = tokio::time::interval(std::time::Duration::from_millis(1000));
53+
54+
loop {
55+
ticker.tick().await;
56+
57+
let now = Utc::now().timestamp_millis();
58+
let aggregated_data =
59+
storage.get_aggregated_range(&tag_key, &tag_value, &metric_name, now - 600_000, now);
60+
61+
if !aggregated_data.is_empty() {
62+
let response = aggregated_data
63+
.iter()
64+
.map(|(id, points)| {
65+
(
66+
id,
67+
points
68+
.iter()
69+
.map(|p| (p.timestamp, p.value))
70+
.collect::<Vec<_>>(),
71+
)
72+
})
73+
.collect::<BTreeMap<_, _>>();
74+
75+
let msg = serde_json::json!({
76+
"type": "aggregated_update",
77+
"tag": format!("{}:{}", tag_key, tag_value),
78+
"metric": metric_name,
79+
"data": response
80+
});
81+
82+
if ws_tx
83+
.send(warp::ws::Message::text(msg.to_string()))
84+
.await
85+
.is_err()
86+
{
87+
break;
3488
}
3589
}
3690
}

src/bin/api/core/http/handlers/node.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,33 +136,24 @@ where
136136
node_metrics_map
137137
.iter()
138138
.filter_map(|entry| {
139-
let series_key = entry.key();
139+
let series_hash = entry.key();
140140
let points = entry.value();
141141

142142
if points.is_empty() {
143143
return None;
144144
}
145145

146-
if !(series_key.starts_with("sys.")
147-
|| series_key.starts_with("net."))
148-
{
146+
let (name, tags) = metrics.metadata.get(series_hash).map(|m| {
147+
let val = m.value();
148+
(val.0.clone(), val.1.clone())
149+
})?;
150+
151+
if !(name.starts_with("sys.") || name.starts_with("net.")) {
149152
return None;
150153
}
151154

152-
let tags = metrics
153-
.metadata
154-
.get(series_key)
155-
.map(|m| m.value().clone())
156-
.unwrap_or_default();
157-
158-
let name = series_key
159-
.split(':')
160-
.next()
161-
.unwrap_or(series_key)
162-
.to_string();
163-
164155
Some(NodeMetricInfo {
165-
key: series_key.clone(),
156+
key: series_hash.to_string(),
166157
name,
167158
tags,
168159
})
@@ -189,9 +180,12 @@ where
189180
None => {
190181
let response = ResponseMessage::<Option<Vec<NodeResponse>>> {
191182
status: StatusCode::NOT_FOUND.as_u16(),
183+
192184
message: "List of nodes".to_string(),
185+
193186
response: vec![].into(),
194187
};
188+
195189
Ok(warp::reply::with_status(
196190
warp::reply::json(&response),
197191
StatusCode::NOT_FOUND,

0 commit comments

Comments
 (0)