Skip to content

Commit 20f8d15

Browse files
committed
feat: [torrust#700] add logs to Health Check API
`````` 2024-02-19T11:30:21.061293933+00:00 [HEALTH CHECK API][INFO] request; method=GET uri=/health_check request_id=78933bbf-c4cf-4897-b972-4c0fd252159a 2024-02-19T11:30:21.070329733+00:00 [HEALTH CHECK API][INFO] response; latency=9 status=200 OK request_id=78933bbf-c4cf-4897-b972-4c0fd252159a ```
1 parent db71f2a commit 20f8d15

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

src/bootstrap/jobs/health_check_api.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,18 @@ pub async fn start_job(config: &HealthCheckApi, register: ServiceRegistry) -> Jo
4747

4848
// Run the API server
4949
let join_handle = tokio::spawn(async move {
50-
info!(target: "Health Check API", "Starting on: {protocol}://{}", bind_addr);
50+
info!(target: "HEALTH CHECK API", "Starting on: {protocol}://{}", bind_addr);
5151

5252
let handle = server::start(bind_addr, tx_start, rx_halt, register);
5353

5454
if let Ok(()) = handle.await {
55-
info!(target: "Health Check API", "Stopped server running on: {protocol}://{}", bind_addr);
55+
info!(target: "HEALTH CHECK API", "Stopped server running on: {protocol}://{}", bind_addr);
5656
}
5757
});
5858

5959
// Wait until the server sends the started message
6060
match rx_start.await {
61-
Ok(msg) => info!(target: "Health Check API", "Started on: {protocol}://{}", msg.address),
61+
Ok(msg) => info!(target: "HEALTH CHECK API", "Started on: {protocol}://{}", msg.address),
6262
Err(e) => panic!("the Health Check API server was dropped: {e}"),
6363
}
6464

src/servers/health_check_api/server.rs

+56-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,24 @@
33
//! This API is intended to be used by the container infrastructure to check if
44
//! the whole application is healthy.
55
use std::net::SocketAddr;
6+
use std::time::Duration;
67

8+
use axum::http::{HeaderName, HeaderValue};
9+
use axum::response::Response;
710
use axum::routing::get;
811
use axum::{Json, Router};
912
use axum_server::Handle;
1013
use futures::Future;
14+
use hyper::Request;
1115
use log::debug;
1216
use serde_json::json;
1317
use tokio::sync::oneshot::{Receiver, Sender};
18+
use tower_http::compression::CompressionLayer;
19+
use tower_http::propagate_header::PropagateHeaderLayer;
20+
use tower_http::request_id::{MakeRequestId, RequestId, SetRequestIdLayer};
21+
use tower_http::trace::{DefaultMakeSpan, TraceLayer};
22+
use tracing::{Level, Span};
23+
use uuid::Uuid;
1424

1525
use crate::bootstrap::jobs::Started;
1626
use crate::servers::health_check_api::handlers::health_check_handler;
@@ -31,14 +41,48 @@ pub fn start(
3141
let router = Router::new()
3242
.route("/", get(|| async { Json(json!({})) }))
3343
.route("/health_check", get(health_check_handler))
34-
.with_state(register);
44+
.with_state(register)
45+
.layer(CompressionLayer::new())
46+
.layer(SetRequestIdLayer::x_request_id(RequestIdGenerator))
47+
.layer(PropagateHeaderLayer::new(HeaderName::from_static("x-request-id")))
48+
.layer(
49+
TraceLayer::new_for_http()
50+
.make_span_with(DefaultMakeSpan::new().level(Level::INFO))
51+
.on_request(|request: &Request<axum::body::Body>, _span: &Span| {
52+
let method = request.method().to_string();
53+
let uri = request.uri().to_string();
54+
let request_id = request
55+
.headers()
56+
.get("x-request-id")
57+
.map(|v| v.to_str().unwrap_or_default())
58+
.unwrap_or_default();
59+
60+
tracing::span!(
61+
target: "HEALTH CHECK API",
62+
tracing::Level::INFO, "request", method = %method, uri = %uri, request_id = %request_id);
63+
})
64+
.on_response(|response: &Response, latency: Duration, _span: &Span| {
65+
let status_code = response.status();
66+
let request_id = response
67+
.headers()
68+
.get("x-request-id")
69+
.map(|v| v.to_str().unwrap_or_default())
70+
.unwrap_or_default();
71+
let latency_ms = latency.as_millis();
72+
73+
tracing::span!(
74+
target: "HEALTH CHECK API",
75+
tracing::Level::INFO, "response", latency = %latency_ms, status = %status_code, request_id = %request_id);
76+
}),
77+
)
78+
.layer(SetRequestIdLayer::x_request_id(RequestIdGenerator));
3579

3680
let socket = std::net::TcpListener::bind(bind_to).expect("Could not bind tcp_listener to address.");
3781
let address = socket.local_addr().expect("Could not get local_addr from tcp_listener.");
3882

3983
let handle = Handle::new();
4084

41-
debug!(target: "Health Check API", "Starting service with graceful shutdown in a spawned task ...");
85+
debug!(target: "HEALTH CHECK API", "Starting service with graceful shutdown in a spawned task ...");
4286

4387
tokio::task::spawn(graceful_shutdown(
4488
handle.clone(),
@@ -55,3 +99,13 @@ pub fn start(
5599

56100
running
57101
}
102+
103+
#[derive(Clone, Default)]
104+
struct RequestIdGenerator;
105+
106+
impl MakeRequestId for RequestIdGenerator {
107+
fn make_request_id<B>(&mut self, _request: &Request<B>) -> Option<RequestId> {
108+
let id = HeaderValue::from_str(&Uuid::new_v4().to_string()).expect("UUID is a valid HTTP header value");
109+
Some(RequestId::new(id))
110+
}
111+
}

tests/servers/health_check_api/environment.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@ impl Environment<Stopped> {
5151

5252
let register = self.registar.entries();
5353

54-
debug!(target: "Health Check API", "Spawning task to launch the service ...");
54+
debug!(target: "HEALTH CHECK API", "Spawning task to launch the service ...");
5555

5656
let server = tokio::spawn(async move {
57-
debug!(target: "Health Check API", "Starting the server in a spawned task ...");
57+
debug!(target: "HEALTH CHECK API", "Starting the server in a spawned task ...");
5858

5959
server::start(self.state.bind_to, tx_start, rx_halt, register)
6060
.await
6161
.expect("it should start the health check service");
6262

63-
debug!(target: "Health Check API", "Server started. Sending the binding {} ...", self.state.bind_to);
63+
debug!(target: "HEALTH CHECK API", "Server started. Sending the binding {} ...", self.state.bind_to);
6464

6565
self.state.bind_to
6666
});
6767

68-
debug!(target: "Health Check API", "Waiting for spawning task to send the binding ...");
68+
debug!(target: "HEALTH CHECK API", "Waiting for spawning task to send the binding ...");
6969

7070
let binding = rx_start.await.expect("it should send service binding").address;
7171

0 commit comments

Comments
 (0)