1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
use axum::{Json, extract::State, http::StatusCode};
use serde::Deserialize;
use tracing::warn;
use utoipa::ToSchema;
use crate::state::AppState;
#[derive(Deserialize, Debug, Clone, ToSchema)]
/// Log level
#[serde(rename_all = "camelCase")]
pub struct LogLevel {
#[schema(examples("info", "trace", "warden=debug,tower_http=debug,axum::rejection=trace"))]
log_level: String,
}
/// Update log level
#[utoipa::path(
patch,
responses(
(
status = 200,
description = "Server's log level has been updated",
headers(
("x-request-id", description = "Request identifier")
)
),
(
status = 400,
description = "Invalid log level",
headers(
("x-request-id", description = "Request identifier")
)
),
),
operation_id = "log_update", // https://github.com/juhaku/utoipa/issues/1170
path = "/logging",
tag = super::CONFIG,
request_body(
content = LogLevel
)
)]
pub async fn reload(State(state): State<AppState>, Json(body): Json<LogLevel>) -> StatusCode {
if let Ok(value) = body.log_level.parse::<tracing_subscriber::EnvFilter>() {
match state.log_handle.reload(value) {
Ok(_) => StatusCode::OK,
Err(e) => {
warn!("{e:?}");
StatusCode::INTERNAL_SERVER_ERROR
}
}
} else {
StatusCode::BAD_REQUEST
}
}
#[cfg(test)]
mod tests {
use axum::{
Router,
body::Body,
http::{Request, StatusCode, header},
};
use anyhow::Result;
use tower::ServiceExt;
use crate::server::{self};
async fn check(
app: Router,
method: &str,
body: String,
expected_result: StatusCode,
) -> Result<()> {
let response = app
.oneshot(
Request::builder()
.method(method)
.header(header::CONTENT_TYPE, "application/json")
.uri("/api/logging")
.body(Body::from(body))?,
)
.await?;
let actual_result = response.status();
assert_eq!(expected_result, actual_result);
Ok(())
}
#[tokio::test]
async fn log_update() -> Result<()> {
let app = server::boostrap::test_app().await;
let info = serde_json::json!({
"logLevel": "info",
});
check(
app.clone(),
"GET",
info.to_string(),
StatusCode::METHOD_NOT_ALLOWED,
)
.await?;
check(app.clone(), "PATCH", info.to_string(), StatusCode::OK).await?;
Ok(())
}
}
|