Skip to content

Commit

Permalink
endpoint for async_metric_log
Browse files Browse the repository at this point in the history
  • Loading branch information
karencfv committed Nov 20, 2024
1 parent 9f59fea commit 75f8fbb
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 19 deletions.
17 changes: 16 additions & 1 deletion clickhouse-admin/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
use clickhouse_admin_types::{
ClickhouseKeeperClusterMembership, DistributedDdlQueue, KeeperConf,
KeeperConfig, KeeperConfigurableSettings, Lgif, MetricNamePath, RaftConfig,
ReplicaConfig, ServerConfigurableSettings, SystemTimeSeries, TimeSeriesSettingsQuery
ReplicaConfig, ServerConfigurableSettings, SystemTimeSeries,
TimeSeriesSettingsQuery,
};
use dropshot::{
HttpError, HttpResponseCreated, HttpResponseOk,
Expand Down Expand Up @@ -128,6 +129,18 @@ pub trait ClickhouseAdminServerApi {
path_params: Path<MetricNamePath>,
query_params: Query<TimeSeriesSettingsQuery>,
) -> Result<HttpResponseOk<Vec<SystemTimeSeries>>, HttpError>;

/// Retrieve time series from the system.asynchronous_metric_log table.
/// These are internal ClickHouse metrics.
#[endpoint {
method = GET,
path = "/timeseries/async-metric-log/{metric}"
}]
async fn system_async_metric_log_timeseries(
rqctx: RequestContext<Self::Context>,
path_params: Path<MetricNamePath>,
query_params: Query<TimeSeriesSettingsQuery>,
) -> Result<HttpResponseOk<Vec<SystemTimeSeries>>, HttpError>;
}

/// API interface for our clickhouse-admin-single server
Expand All @@ -148,4 +161,6 @@ pub trait ClickhouseAdminSingleApi {
async fn init_db(
rqctx: RequestContext<Self::Context>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

// TODO: Retrieve time series here too
}
22 changes: 20 additions & 2 deletions clickhouse-admin/src/clickhouse_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use anyhow::Result;
use camino::Utf8PathBuf;
use clickhouse_admin_types::{
ClickhouseKeeperClusterMembership, DistributedDdlQueue, KeeperConf,
KeeperId, Lgif, SystemTimeSeriesSettings, RaftConfig, SystemTimeSeries,
KeeperId, Lgif, RaftConfig, SystemTimeSeries, SystemTimeSeriesSettings,
OXIMETER_CLUSTER,
};
use dropshot::HttpError;
Expand Down Expand Up @@ -168,12 +168,30 @@ impl ClickhouseCli {
) -> Result<Vec<SystemTimeSeries>, ClickhouseCliError> {
self.client_non_interactive(
ClickhouseClientType::Server,
settings.query().as_str(),
settings.query_metric_log().as_str(),
"Retrieve time series from the system.metric_log table",
SystemTimeSeries::parse,
self.log.clone().unwrap(),
)
.await

// TODO: log query?
}

pub async fn system_async_metric_log_timeseries(
&self,
settings: SystemTimeSeriesSettings,
) -> Result<Vec<SystemTimeSeries>, ClickhouseCliError> {
self.client_non_interactive(
ClickhouseClientType::Server,
settings.query_async_metric_log().as_str(),
"Retrieve time series from the system.asynchronous_metric_log table",
SystemTimeSeries::parse,
self.log.clone().unwrap(),
)
.await

// TODO: log query?
}

async fn client_non_interactive<F, T>(
Expand Down
22 changes: 19 additions & 3 deletions clickhouse-admin/src/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use crate::context::{ServerContext, SingleServerContext};
use clickhouse_admin_api::*;
use clickhouse_admin_types::{
ClickhouseKeeperClusterMembership, DistributedDdlQueue, KeeperConf,
KeeperConfig, KeeperConfigurableSettings, Lgif,
SystemTimeSeriesSettings, MetricNamePath, RaftConfig, ReplicaConfig,
ServerConfigurableSettings, SystemTimeSeries, TimeSeriesSettingsQuery,
KeeperConfig, KeeperConfigurableSettings, Lgif, MetricNamePath, RaftConfig,
ReplicaConfig, ServerConfigurableSettings, SystemTimeSeries,
SystemTimeSeriesSettings, TimeSeriesSettingsQuery,
};
use dropshot::{
ApiDescription, HttpError, HttpResponseCreated, HttpResponseOk,
Expand Down Expand Up @@ -79,6 +79,22 @@ impl ClickhouseAdminServerApi for ClickhouseAdminServerImpl {
ctx.clickhouse_cli().system_metric_log_timeseries(settings).await?;
Ok(HttpResponseOk(output))
}

async fn system_async_metric_log_timeseries(
rqctx: RequestContext<Self::Context>,
path_params: Path<MetricNamePath>,
query_params: Query<TimeSeriesSettingsQuery>,
) -> Result<HttpResponseOk<Vec<SystemTimeSeries>>, HttpError> {
let ctx = rqctx.context();
let settings = query_params.into_inner();
let metric = path_params.into_inner();
let settings = SystemTimeSeriesSettings { settings, metric };
let output = ctx
.clickhouse_cli()
.system_async_metric_log_timeseries(settings)
.await?;
Ok(HttpResponseOk(output))
}
}

enum ClickhouseAdminKeeperImpl {}
Expand Down
49 changes: 36 additions & 13 deletions clickhouse-admin/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,14 +1043,15 @@ fn default_time_range() -> u64 {
86400
}

// TODO: Have an enum?
#[derive(Debug, Serialize, Deserialize, Display, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MetricNamePath {
/// Name of the metric to retrieve.
pub metric: String,
}

#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct TimeSeriesSettingsQuery {
/// The interval to collect monitoring metrics in seconds.
/// Default is 60 seconds.
Expand All @@ -1063,34 +1064,55 @@ pub struct TimeSeriesSettingsQuery {
pub time_range: u64,
}

// TODO: Should I have settings for each system table?
// or should I just add an enum here?
/// Settings to specify which time series to retrieve.
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct SystemTimeSeriesSettings {
pub settings: TimeSeriesSettingsQuery,
/// Name of the metric to retrieve
pub metric: MetricNamePath,
}

impl SystemTimeSeriesSettings {
pub fn query(&self) -> String {
// TODO: Use more aggregate functions than just avg?

pub fn query_metric_log(&self) -> String {
let interval = self.settings.interval;
let time_range = self.settings.time_range;
let metric = &self.metric;
let query = format!("SELECT toStartOfInterval(event_time, INTERVAL {interval} SECOND) AS time, avg({metric}) AS value
FROM system.metric_log
WHERE event_date >= toDate(now() - {time_range}) AND event_time >= now() - {time_range}
GROUP BY time
ORDER BY time WITH FILL STEP {interval}
FORMAT JSONEachRow
SETTINGS date_time_output_format = 'iso'");
let query = format!(
"SELECT toStartOfInterval(event_time, INTERVAL {interval} SECOND) AS time, avg({metric}) AS value
FROM system.metric_log
WHERE event_date >= toDate(now() - {time_range}) AND event_time >= now() - {time_range}
GROUP BY time
ORDER BY time WITH FILL STEP {interval}
FORMAT JSONEachRow
SETTINGS date_time_output_format = 'iso'"
);
query
}
}

// TODO: Do the above for AsyncMetricLogTimeSeriesSettings
pub fn query_async_metric_log(&self) -> String {
let interval = self.settings.interval;
let time_range = self.settings.time_range;
let metric = &self.metric;
let query = format!(
"SELECT toStartOfInterval(event_time, INTERVAL {interval} SECOND) AS time, avg(value) AS value
FROM system.asynchronous_metric_log
WHERE event_date >= toDate(now() - {time_range}) AND event_time >= now() - {time_range}
AND metric = '{metric}'
GROUP BY time
ORDER BY time WITH FILL STEP {interval}
FORMAT JSONEachRow
SETTINGS date_time_output_format = 'iso'"
);
query
}
}

/// Retrieved time series from the internal `system` database.
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct SystemTimeSeries {
pub time: DateTime<Utc>,
pub value: f64,
Expand All @@ -1105,6 +1127,7 @@ impl SystemTimeSeries {
info!(
log,
"Retrieved data from `system` database";
// TODO: Log output here? feels like a lot of noise?
"output" => ?s
);

Expand Down
61 changes: 61 additions & 0 deletions openapi/clickhouse-admin-server.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,66 @@
}
}
},
"/timeseries/async-metric-log/{metric}": {
"get": {
"summary": "Retrieve time series from the system.asynchronous_metric_log table.",
"description": "These are internal ClickHouse metrics.",
"operationId": "system_async_metric_log_timeseries",
"parameters": [
{
"in": "path",
"name": "metric",
"description": "Name of the metric to retrieve.",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "interval",
"description": "The interval to collect monitoring metrics in seconds. Default is 60 seconds.",
"schema": {
"type": "integer",
"format": "uint64",
"minimum": 0
}
},
{
"in": "query",
"name": "time_range",
"description": "Range of time to collect monitoring metrics in seconds. Default is 86400 seconds (24 hrs).",
"schema": {
"type": "integer",
"format": "uint64",
"minimum": 0
}
}
],
"responses": {
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"title": "Array_of_SystemTimeSeries",
"type": "array",
"items": {
"$ref": "#/components/schemas/SystemTimeSeries"
}
}
}
}
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/timeseries/metric-log/{metric}": {
"get": {
"summary": "Retrieve time series from the system.metric_log table.",
Expand Down Expand Up @@ -595,6 +655,7 @@
]
},
"SystemTimeSeries": {
"description": "Retrieved time series from the internal `system` database.",
"type": "object",
"properties": {
"time": {
Expand Down

0 comments on commit 75f8fbb

Please sign in to comment.