Skip to content

Commit

Permalink
server: update traffic pages
Browse files Browse the repository at this point in the history
  • Loading branch information
Gitea committed Mar 30, 2024
1 parent ea5d3c8 commit 2c8e65a
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 33 deletions.
40 changes: 31 additions & 9 deletions crates/kernel/src/prom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,51 @@ pub struct QueryResponseDataItem {
pub values: Vec<(i64, String)>,
}

/// LineSeries is a series of line chart
#[derive(Debug, Serialize, Deserialize)]
pub struct LineSeries {
pub total: i64,
pub values: Vec<(i64, i64)>,
}

pub type MultiLineSeries = HashMap<String, LineSeries>;

impl LineSeries {
pub fn from(res: &QueryResponse, sequence: Vec<i64>) -> Self {
let mut times_data = HashMap::<i64, i64>::new();
pub fn from(res: &QueryResponse, sequence: Vec<i64>) -> MultiLineSeries {
let mut all_times_data = HashMap::<String, HashMap<i64, i64>>::new();
for item in res.data.result.iter() {
let mut times_data = HashMap::<i64, i64>::new();
// convert metric map to vec and sorted, join by "-" as key
let mut keys: Vec<String> = item
.metric
.iter()
.map(|(k, v)| format!("{}-{}", k, v))
.collect();
keys.sort();
let mut key = keys.join("-");
if key.is_empty() {
key = "metric".to_string();
}
for (t, v) in &item.values {
let value = v.parse::<f64>().unwrap_or(0.0) as i64;
times_data.insert(*t, value);
}
all_times_data.insert(key, times_data);
}
let mut values = vec![];
let mut total: i64 = 0;
for t in sequence.iter() {
let value = times_data.get(t).unwrap_or(&0);
values.push((*t * 1000, *value)); // js use milliseconds, t*1000
total += *value;

let mut res = MultiLineSeries::new();
for (k, times_data) in all_times_data.iter() {
let mut values = vec![];
let mut total: i64 = 0;
for t in sequence.iter() {
let value = times_data.get(t).unwrap_or(&0);
values.push((*t * 1000, *value)); // js use milliseconds, t*1000
total += *value;
}
let ls = LineSeries { total, values };
res.insert(k.clone(), ls);
}
LineSeries { total, values }
res
}
}

Expand Down
3 changes: 3 additions & 0 deletions land-server/src/server/dash/overview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use tracing::info;

#[derive(Debug, Serialize)]
pub struct ProjectVar {
pub id: i32,
pub name: String,
pub domain: String,
pub domain_full: String,
Expand All @@ -32,6 +33,7 @@ impl ProjectVar {
Ok(projects
.into_iter()
.map(|p| ProjectVar {
id: p.id,
name: p.name.clone(),
domain: p.domain.clone(),
domain_full: format!("{}.{}", p.domain, domain),
Expand All @@ -52,6 +54,7 @@ impl ProjectVar {
) -> anyhow::Result<Self> {
let (domain, protocol) = settings::get_domain_settings().await?;
let mut var = ProjectVar {
id: project.id,
name: project.name.clone(),
domain: project.domain.clone(),
domain_full: format!("{}.{}", project.domain, domain),
Expand Down
76 changes: 61 additions & 15 deletions land-server/src/server/dash/traffic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,34 @@ pub async fn flows(
Extension(user): Extension<SessionUser>,
Query(q): Query<RequestsQuery>,
) -> Result<impl IntoResponse, ServerError> {
Ok("flows".to_string())
let now = tokio::time::Instant::now();
let period = q.get_period();
let acc = q.account.unwrap_or_default();
if acc != user.id.to_string() {
return Err(ServerError::forbidden("user id does not match"));
}
let query = get_flow_query(acc, q.project, period.step_word);
debug!(
"query: {}, start:{}, end:{}, step:{}",
query, period.start, period.end, period.step
);
let params = land_kernel::prom::QueryRangeParams {
query: query.clone(),
step: period.step,
start: period.start,
end: period.end,
};
let res = land_kernel::prom::query_range(params).await?;
let values = land_kernel::prom::LineSeries::from(&res, period.sequence);
info!(
"query: {}, start:{}, end:{}, step:{}, cost:{}",
query,
period.start,
period.end,
period.step,
now.elapsed().as_millis(),
);
Ok(Json(values))
}

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -68,23 +95,13 @@ pub async fn requests(
Extension(user): Extension<SessionUser>,
Query(q): Query<RequestsQuery>,
) -> Result<impl IntoResponse, ServerError> {
let now = tokio::time::Instant::now();
let period = q.get_period();
let acc = q.account.unwrap_or_default();
if acc != user.id.to_string() {
return Err(ServerError::forbidden("user id does not match"));
}
let query = if let Some(pid) = q.project {
format!(
"increase(req_fn_total{{project_id=\"{}\"}}[{}])",
pid, period.step_word
)
} else {
format!(
"sum(increase(req_fn_total{{user_id=\"{}\"}}[{}]))",
acc, period.step_word
)
};
let now = tokio::time::Instant::now();
let query = get_request_query(acc, q.project, period.step_word);
// end time is now ts with latest 10 decade
debug!(
"query: {}, start:{}, end:{}, step:{}",
Expand All @@ -99,13 +116,42 @@ pub async fn requests(
let res = land_kernel::prom::query_range(params).await?;
let values = land_kernel::prom::LineSeries::from(&res, period.sequence);
info!(
"query: {}, start:{}, end:{}, step:{}, values:{}, cost:{}",
"query: {}, start:{}, end:{}, step:{}, cost:{}",
query,
period.start,
period.end,
period.step,
values.values.len(),
now.elapsed().as_millis(),
);
Ok(Json(values))
}

fn get_flow_query(acc: String, project: Option<String>, step: String) -> String {
let query = if let Some(pid) = project {
format!(
"sum by (project_id,flowtype) (increase(req_fn_bytes_total{{project_id=\"{}\"}}[{}]))",
pid, step,
)
} else {
format!(
"sum by (user_id,flowtype) (increase(req_fn_bytes_total{{user_id=\"{}\"}}[{}]))",
acc, step,
)
};
query
}

fn get_request_query(acc: String, project: Option<String>, step: String) -> String {
let query = if let Some(pid) = project {
format!(
"sum(increase(req_fn_total{{project_id=\"{}\",status=\"all\"}}[{}]))",
pid, step,
)
} else {
format!(
"sum(increase(req_fn_total{{user_id=\"{}\",status=\"all\"}}[{}]))",
acc, step,
)
};
query
}
25 changes: 25 additions & 0 deletions land-server/tpls/partials/project_traffic.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div class="container project-container py-3" id="traffic" data-x-account="{{user.id}}" data-x-project="{{project.id}}">
<div class="border rounded p-4 mb-4">
<div>
<p class="text-body-tertiary text-uppercase mb-2">Request counts</p>
<p class="fw-bold mb-1" id="requests-total"></p>
<div id="requests-loading-spinner" class="spinner-grow spinner-grow-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="requests-chart" style="height: 200px;"></div>
</div>
<div class="border rounded p-4 mb-4">
<div>
<p class="text-body-tertiary text-uppercase mb-2">Transferred Bytes</p>
<p class="fw-bold mb-1" id="flows-total"></p>
<div id="flows-loading-spinner" class="spinner-grow spinner-grow-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="flows-chart" style="height: 200px;"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"
integrity="sha256-QvgynZibb2U53SsVu98NggJXYqwRL7tg3FeyfXvPOUY=" crossorigin="anonymous"></script>
<script src="/static/js/traffic.js"></script>
13 changes: 12 additions & 1 deletion land-server/tpls/partials/traffic.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@
<div id="requests-chart" style="height: 200px;"></div>
</div>
</div>
<div class="col-6">222</div>
<div class="col-6">
<div class="border rounded p-4">
<div>
<p class="text-body-tertiary text-uppercase mb-2">Transferred Bytes</p>
<p class="fw-bold mb-1" id="flows-total"></p>
<div id="flows-loading-spinner" class="spinner-grow spinner-grow-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="flows-chart" style="height: 200px;"></div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"
Expand Down
6 changes: 1 addition & 5 deletions land-server/tpls/project-traffic.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@
<a class="nav-link" href="/projects/{{project.name}}/settings">Settings</a>
</nav>
<div class="pb-4">
<div class="card m-3">
<div class="card-body">
Traffic
</div>
</div>
{{> partials/project_traffic.hbs}}
</div>
</div>
{{> partials/footer.hbs}}
Expand Down
Loading

0 comments on commit 2c8e65a

Please sign in to comment.