Skip to content

Commit 25a8e61

Browse files
committed
webui: add fail query count, add server security status, add error message when audit is disabled.
1 parent 34c5e71 commit 25a8e61

19 files changed

+236
-25
lines changed

plugin/smartdns-ui/Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "smartdns-ui"
3-
version = "0.1.0"
3+
version = "1.0.0"
44
edition = "2021"
55

66
[lib]
@@ -11,13 +11,13 @@ ctor = "0.4.3"
1111
bytes = "1.10.1"
1212
rusqlite = { version = "0.37.0", features = ["bundled"] }
1313
hyper = { version = "1.7.0", features = ["full"] }
14-
hyper-util = { version = "0.1.16", features = ["full"] }
14+
hyper-util = { version = "0.1.17", features = ["full"] }
1515
hyper-tungstenite = "0.18.0"
1616
tokio = { version = "1.47.1", features = ["full"] }
17-
serde = { version = "1.0.219", features = ["derive"] }
17+
serde = { version = "1.0.225", features = ["derive"] }
1818
tokio-rustls = { version = "0.26.2", optional = true}
1919
rustls-pemfile = { version = "2.2.0", optional = true}
20-
serde_json = "1.0.143"
20+
serde_json = "1.0.145"
2121
http-body-util = "0.1.3"
2222
getopts = "0.2.24"
2323
url = "2.5.7"
@@ -27,7 +27,7 @@ futures = "0.3.31"
2727
socket2 = "0.6.0"
2828
cfg-if = "1.0.3"
2929
urlencoding = "2.1.3"
30-
chrono = "0.4.41"
30+
chrono = "0.4.42"
3131
nix = "0.30.1"
3232
tokio-fd = "0.3.0"
3333
pbkdf2 = { version = "0.12.2", features = ["simple"] }
@@ -42,7 +42,7 @@ default = ["https"]
4242
reqwest = {version = "0.12.23", features = ["blocking"]}
4343
tungstenite = "0.23.0"
4444
tokio-tungstenite = "0.23.1"
45-
tempfile = "3.21.0"
45+
tempfile = "3.22.0"
4646

4747
[build-dependencies]
4848
bindgen = "0.69.5"

plugin/smartdns-ui/src/data_server.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub struct OverviewData {
6161
pub struct MetricsData {
6262
pub total_query_count: u64,
6363
pub block_query_count: u64,
64+
pub fail_query_count: u64,
6465
pub avg_query_time: f64,
6566
pub cache_hit_rate: f64,
6667
pub cache_number: u64,
@@ -179,7 +180,7 @@ impl DataServerControl {
179180
Plugin::smartdns_exit(1);
180181
}
181182

182-
dns_log!(LogLevel::INFO, "data server exit.");
183+
dns_log!(LogLevel::DEBUG, "data server exit.");
183184
});
184185

185186
*self.is_run.lock().unwrap() = true;
@@ -474,6 +475,7 @@ impl DataServer {
474475
let metrics = MetricsData {
475476
total_query_count: self.stat.get_total_request(),
476477
block_query_count: self.stat.get_total_blocked_request(),
478+
fail_query_count: self.stat.get_total_failed_request(),
477479
avg_query_time: smartdns::Stats::get_avg_process_time(),
478480
cache_hit_rate: smartdns::Stats::get_cache_hit_rate(),
479481
cache_number: smartdns::Plugin::dns_cache_total_num() as u64,
@@ -522,6 +524,10 @@ impl DataServer {
522524
self.stat.add_total_blocked_request(1);
523525
}
524526

527+
if data.reply_code != 0 {
528+
self.stat.add_total_failed_request(1);
529+
}
530+
525531
self.db.insert_domain(&list)
526532
}
527533

@@ -532,6 +538,7 @@ impl DataServer {
532538
let mut domain_data_list = Vec::new();
533539
let mut client_data_list = Vec::new();
534540
let mut blocked_num = 0;
541+
let mut failed_num = 0;
535542
let timestamp_now = get_utc_time_ms();
536543

537544
for req in req_list {
@@ -547,6 +554,10 @@ impl DataServer {
547554
blocked_num += 1;
548555
}
549556

557+
if req.get_rcode() != 0 {
558+
failed_num += 1;
559+
}
560+
550561
let domain_data = DomainData {
551562
id: 0,
552563
domain: req.get_domain(),
@@ -589,6 +600,7 @@ impl DataServer {
589600

590601
this.stat.add_total_request(domain_data_list.len() as u64);
591602
this.stat.add_total_blocked_request(blocked_num as u64);
603+
this.stat.add_total_failed_request(failed_num as u64);
592604

593605
dns_log!(
594606
LogLevel::DEBUG,
@@ -695,7 +707,7 @@ impl DataServer {
695707
let mut check_timer = tokio::time::interval(Duration::from_secs(60));
696708
let is_check_timer_running = Arc::new(AtomicBool::new(false));
697709

698-
dns_log!(LogLevel::INFO, "data server start.");
710+
dns_log!(LogLevel::DEBUG, "data server start.");
699711

700712
loop {
701713
tokio::select! {

plugin/smartdns-ui/src/data_stats.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use tokio::time::{interval_at, Instant};
3939
struct DataStatsItem {
4040
total_request: AtomicU64,
4141
total_blocked_request: AtomicU64,
42+
total_failed_request: AtomicU64,
4243
qps: AtomicU32,
4344
qps_count: AtomicU32,
4445
request_dropped: AtomicU64,
@@ -48,6 +49,7 @@ struct DataStatsItem {
4849
struct DataStatsItem {
4950
total_request: Arc<Mutex<u64>>,
5051
total_blocked_request: Arc<Mutex<u64>>,
52+
total_failed_request: Arc<Mutex<u64>>,
5153
qps: AtomicU32,
5254
qps_count: AtomicU32,
5355
request_dropped: Arc<Mutex<u64>>,
@@ -59,6 +61,7 @@ impl DataStatsItem {
5961
let ret = DataStatsItem {
6062
total_request: 0.into(),
6163
total_blocked_request: 0.into(),
64+
total_failed_request: 0.into(),
6265
qps: 0.into(),
6366
qps_count: 0.into(),
6467
request_dropped: 0.into(),
@@ -67,6 +70,7 @@ impl DataStatsItem {
6770
let ret = DataStatsItem {
6871
total_request: Arc::new(Mutex::new(0)),
6972
total_blocked_request: Arc::new(Mutex::new(0)),
73+
total_failed_request: Arc::new(Mutex::new(0)),
7074
qps: 0.into(),
7175
qps_count: 0.into(),
7276
request_dropped: Arc::new(Mutex::new(0)),
@@ -154,6 +158,33 @@ impl DataStatsItem {
154158
}
155159
}
156160

161+
pub fn add_total_failed_request(&self, total: u64) {
162+
#[cfg(target_has_atomic = "64")]
163+
{
164+
self.total_failed_request
165+
.fetch_add(total, Ordering::Relaxed);
166+
}
167+
168+
#[cfg(not(target_has_atomic = "64"))]
169+
{
170+
let mut total_failed_request = self.total_failed_request.lock().unwrap();
171+
*total_failed_request += total;
172+
}
173+
}
174+
175+
pub fn get_total_failed_request(&self) -> u64 {
176+
#[cfg(target_has_atomic = "64")]
177+
{
178+
return self.total_failed_request.load(Ordering::Relaxed);
179+
}
180+
181+
#[cfg(not(target_has_atomic = "64"))]
182+
{
183+
let total = self.total_failed_request.lock().unwrap();
184+
return *total;
185+
}
186+
}
187+
157188
#[allow(dead_code)]
158189
pub fn get_current_hour_total(&self) -> u64 {
159190
return Stats::get_request_total();
@@ -211,6 +242,14 @@ impl DataStats {
211242
self.data.add_total_blocked_request(total);
212243
}
213244

245+
pub fn get_total_failed_request(&self) -> u64 {
246+
return self.data.get_total_failed_request();
247+
}
248+
249+
pub fn add_total_failed_request(&self, total: u64) {
250+
self.data.add_total_failed_request(total);
251+
}
252+
214253
pub fn get_total_request(&self) -> u64 {
215254
return self.data.get_total_request();
216255
}
@@ -291,11 +330,24 @@ impl DataStats {
291330
if total_blocked_count == 0 {
292331
let mut parm = DomainListGetParam::new();
293332
parm.is_blocked = Some(true);
294-
333+
295334
let count = self.db.get_domain_list_count(Some(&parm));
296335
total_blocked_count = count;
297336
}
298337
self.data.add_total_blocked_request(total_blocked_count);
338+
339+
// load total failed request
340+
let mut total_failed_count = 0 as u64;
341+
let status_data_total_failed_count = status_data.get("total_failed_request");
342+
if status_data_total_failed_count.is_some() {
343+
let count = status_data_total_failed_count.unwrap().parse::<u64>();
344+
if let Ok(count) = count {
345+
total_failed_count = count;
346+
} else {
347+
total_failed_count = 0;
348+
}
349+
}
350+
self.data.add_total_failed_request(total_failed_count);
299351
Ok(())
300352
}
301353

@@ -308,6 +360,10 @@ impl DataStats {
308360
"total_blocked_request",
309361
self.get_total_blocked_request().to_string().as_str(),
310362
)?;
363+
self.db.set_status_data(
364+
"total_failed_request",
365+
self.get_total_failed_request().to_string().as_str(),
366+
)?;
311367

312368
Ok(())
313369
}
@@ -331,7 +387,7 @@ impl DataStats {
331387
.delete_domain_before_timestamp(now - self.conf.read().unwrap().max_log_age_ms as u64);
332388
if let Err(e) = ret {
333389
if e.to_string() == "Query returned no rows" {
334-
return
390+
return;
335391
}
336392

337393
dns_log!(

plugin/smartdns-ui/src/data_upstream_server.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct UpstreamServerInfo {
3030
pub query_success_rate: f64,
3131
pub avg_time: f64,
3232
pub status: String,
33+
pub security: String,
3334
}
3435

3536
impl UpstreamServerInfo {
@@ -48,6 +49,8 @@ impl UpstreamServerInfo {
4849
"Abnormal"
4950
};
5051

52+
let security_status = server.get_server_security_status();
53+
5154
servers.push(UpstreamServerInfo {
5255
host: server.get_host(),
5356
ip: server.get_ip(),
@@ -59,6 +62,7 @@ impl UpstreamServerInfo {
5962
query_success_rate: stats.get_success_rate(),
6063
avg_time: stats.get_query_avg_time(),
6164
status: status.to_string(),
65+
security: security_status.to_string(),
6266
});
6367
});
6468
Ok(servers)

plugin/smartdns-ui/src/http_api_msg.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ pub fn api_msg_gen_upstream_server_list(upstream_server_list: &Vec<UpstreamServe
440440
"query_success_rate": x.query_success_rate,
441441
"avg_time": x.avg_time,
442442
"status": x.status,
443+
"security": x.security,
443444
});
444445
s
445446
})
@@ -510,6 +511,11 @@ pub fn api_msg_parse_upstream_server_list(
510511
return Err("status not found".into());
511512
}
512513

514+
let security = item["security"].as_str();
515+
if security.is_none() {
516+
return Err("security not found".into());
517+
}
518+
513519
upstream_server_list.push(UpstreamServerInfo {
514520
host: host.unwrap().to_string(),
515521
ip: ip.unwrap().to_string(),
@@ -521,6 +527,7 @@ pub fn api_msg_parse_upstream_server_list(
521527
query_success_rate: query_success_rate.unwrap(),
522528
avg_time: avg_time.unwrap(),
523529
status: status.unwrap().to_string(),
530+
security: security.unwrap().to_string(),
524531
});
525532
}
526533

@@ -690,6 +697,7 @@ pub fn api_msg_gen_metrics_data(data: &MetricsData) -> String {
690697
let json_str = json!({
691698
"total_query_count": data.total_query_count,
692699
"block_query_count": data.block_query_count,
700+
"fail_query_count": data.fail_query_count,
693701
"avg_query_time": data.avg_query_time,
694702
"cache_hit_rate": data.cache_hit_rate,
695703
"cache_number": data.cache_number,
@@ -714,6 +722,11 @@ pub fn api_msg_parse_metrics_data(data: &str) -> Result<MetricsData, Box<dyn Err
714722
return Err("block_query_count not found".into());
715723
}
716724

725+
let fail_query_count = v["fail_query_count"].as_u64();
726+
if fail_query_count.is_none() {
727+
return Err("fail_query_count not found".into());
728+
}
729+
717730
let avg_query_time = v["avg_query_time"].as_f64();
718731
if avg_query_time.is_none() {
719732
return Err("avg_query_time not found".into());
@@ -749,6 +762,7 @@ pub fn api_msg_parse_metrics_data(data: &str) -> Result<MetricsData, Box<dyn Err
749762
Ok(MetricsData {
750763
total_query_count: total_query_count.unwrap() as u64,
751764
block_query_count: block_query_count.unwrap() as u64,
765+
fail_query_count: fail_query_count.unwrap() as u64,
752766
avg_query_time: avg_query_time.unwrap(),
753767
cache_hit_rate: cache_hit_rate.unwrap(),
754768
cache_number: cache_number.unwrap() as u64,

plugin/smartdns-ui/src/http_server.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl HttpServerConfig {
123123
}
124124
}
125125

126-
if let Some(username) = data_server.get_server_config("smartdns-ui.username") {
126+
if let Some(username) = data_server.get_server_config("smartdns-ui.user") {
127127
self.username = username;
128128
}
129129

@@ -187,8 +187,6 @@ impl HttpServerControl {
187187
}
188188

189189
pub fn start_http_server(&self, conf: &HttpServerConfig) -> Result<(), Box<dyn Error>> {
190-
dns_log!(LogLevel::INFO, "start smartdns-ui server.");
191-
192190
let inner_clone = Arc::clone(&self.http_server);
193191
let ret = inner_clone.set_conf(conf);
194192
if let Err(e) = ret {
@@ -207,7 +205,7 @@ impl HttpServerControl {
207205
dns_log!(LogLevel::ERROR, "http server error: {}", e);
208206
Plugin::smartdns_exit(1);
209207
}
210-
dns_log!(LogLevel::INFO, "http server exit.");
208+
dns_log!(LogLevel::DEBUG, "http server exit.");
211209
});
212210

213211
tokio::task::block_in_place(|| {
@@ -225,8 +223,6 @@ impl HttpServerControl {
225223
return;
226224
}
227225

228-
dns_log!(LogLevel::INFO, "stop smartdns-ui server.");
229-
230226
self.http_server.stop_http_server();
231227

232228
if let Some(server_thread) = server_thread.take() {
@@ -881,7 +877,7 @@ impl HttpServer {
881877
let addr = listner.local_addr()?;
882878

883879
*this.local_addr.lock().unwrap() = Some(addr);
884-
dns_log!(LogLevel::INFO, "http server listen at {}", url);
880+
dns_log!(LogLevel::INFO, "http server listen at {}", addr);
885881

886882
let _ = kickoff_tx.send(0);
887883
loop {

plugin/smartdns-ui/src/http_server_stream.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
use futures::sink::SinkExt;
2020
use futures::stream::StreamExt;
21+
use hyper_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
22+
use hyper_tungstenite::tungstenite::protocol::CloseFrame;
2123
use std::os::fd::AsRawFd;
2224
use std::sync::Arc;
2325
use std::time::Duration;
@@ -182,6 +184,18 @@ pub async fn serve_audit_log_stream(
182184
let data_server = http_server.get_data_server();
183185
let mut log_stream = data_server.get_audit_log_stream().await;
184186

187+
if dns_audit_log_enabled() == false {
188+
let reason =
189+
"Audit log is not enabled, please set `audit-enable` to `yes` in smartdns config file.";
190+
191+
let close_msg = CloseFrame {
192+
code: CloseCode::Bad(4003),
193+
reason: reason.into(),
194+
};
195+
websocket.send(Message::Close(Some(close_msg))).await?;
196+
return Ok(());
197+
}
198+
185199
loop {
186200
tokio::select! {
187201
msg = log_stream.recv() => {

0 commit comments

Comments
 (0)