mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-14 17:13:13 +00:00
Refactor telemetry initialization for non-production environments (#789)
* add dep `scopeguard` * improve for tracing * fix * fix * improve code for import * add logger trace id * fix * fix * fix * fix * fix
This commit is contained in:
+2
-1
@@ -79,7 +79,7 @@ tokio-stream.workspace = true
|
||||
tokio-util.workspace = true
|
||||
tonic = { workspace = true }
|
||||
tower.workspace = true
|
||||
tower-http = { workspace = true, features = ["trace", "compression-deflate", "compression-gzip", "cors", "catch-panic", "timeout", "limit"] }
|
||||
tower-http = { workspace = true, features = ["trace", "compression-full", "cors", "catch-panic", "timeout", "limit", "request-id"] }
|
||||
|
||||
# Serialization and Data Formats
|
||||
bytes = { workspace = true }
|
||||
@@ -112,6 +112,7 @@ mime_guess = { workspace = true }
|
||||
pin-project-lite.workspace = true
|
||||
rust-embed = { workspace = true, features = ["interpolate-folder-path"] }
|
||||
s3s.workspace = true
|
||||
scopeguard.workspace = true
|
||||
shadow-rs = { workspace = true, features = ["build", "metadata"] }
|
||||
sysinfo = { workspace = true, features = ["multithread"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
+18
-12
@@ -14,26 +14,31 @@
|
||||
|
||||
use crate::config::build;
|
||||
use crate::license::get_license;
|
||||
use axum::Json;
|
||||
use axum::body::Body;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::{Router, extract::Request, middleware, routing::get};
|
||||
use axum::{
|
||||
Json, Router,
|
||||
body::Body,
|
||||
extract::Request,
|
||||
middleware,
|
||||
response::{IntoResponse, Response},
|
||||
routing::get,
|
||||
};
|
||||
use axum_extra::extract::Host;
|
||||
use axum_server::tls_rustls::RustlsConfig;
|
||||
use http::{HeaderMap, HeaderName, StatusCode, Uri};
|
||||
use http::{HeaderValue, Method};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, Uri};
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::RustEmbed;
|
||||
use rustfs_config::{RUSTFS_TLS_CERT, RUSTFS_TLS_KEY};
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use std::io::Result;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
io::Result,
|
||||
net::{IpAddr, SocketAddr},
|
||||
sync::{Arc, OnceLock},
|
||||
time::Duration,
|
||||
};
|
||||
use tokio_rustls::rustls::ServerConfig;
|
||||
use tower_http::catch_panic::CatchPanicLayer;
|
||||
use tower_http::compression::CompressionLayer;
|
||||
use tower_http::cors::{AllowOrigin, Any, CorsLayer};
|
||||
use tower_http::limit::RequestBodyLimitLayer;
|
||||
use tower_http::timeout::TimeoutLayer;
|
||||
@@ -274,7 +279,6 @@ async fn console_logging_middleware(req: Request, next: axum::middleware::Next)
|
||||
let method = req.method().clone();
|
||||
let uri = req.uri().clone();
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
let response = next.run(req).await;
|
||||
let duration = start.elapsed();
|
||||
|
||||
@@ -409,6 +413,8 @@ fn setup_console_middleware_stack(
|
||||
app = app
|
||||
.layer(CatchPanicLayer::new())
|
||||
.layer(TraceLayer::new_for_http())
|
||||
// Compress responses
|
||||
.layer(CompressionLayer::new())
|
||||
.layer(middleware::from_fn(console_logging_middleware))
|
||||
.layer(cors_layer)
|
||||
// Add timeout layer - convert auth_timeout from seconds to Duration
|
||||
|
||||
@@ -28,7 +28,7 @@ use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use tokio::net::lookup_host;
|
||||
use tokio::time::{Duration, sleep};
|
||||
use tracing::{debug, error, info, warn};
|
||||
use tracing::{Span, debug, error, info, warn};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -121,6 +121,8 @@ pub struct NotificationTarget {}
|
||||
#[async_trait::async_trait]
|
||||
impl Operation for NotificationTarget {
|
||||
async fn call(&self, req: S3Request<Body>, params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
let span = Span::current();
|
||||
let _enter = span.enter();
|
||||
// 1. Analyze query parameters
|
||||
let (target_type, target_name) = extract_target_params(¶ms)?;
|
||||
|
||||
@@ -274,6 +276,9 @@ impl Operation for NotificationTarget {
|
||||
let mut header = HeaderMap::new();
|
||||
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
|
||||
header.insert(CONTENT_LENGTH, "0".parse().unwrap());
|
||||
if let Some(v) = req.headers.get("x-request-id") {
|
||||
header.insert("x-request-id", v.clone());
|
||||
}
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
|
||||
}
|
||||
}
|
||||
@@ -283,6 +288,8 @@ pub struct ListNotificationTargets {}
|
||||
#[async_trait::async_trait]
|
||||
impl Operation for ListNotificationTargets {
|
||||
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
let span = Span::current();
|
||||
let _enter = span.enter();
|
||||
debug!("ListNotificationTargets call start request params: {:?}", req.uri.query());
|
||||
|
||||
// 1. Permission verification
|
||||
@@ -320,6 +327,9 @@ impl Operation for ListNotificationTargets {
|
||||
debug!("ListNotificationTargets call end, response data length: {}", data.len(),);
|
||||
let mut header = HeaderMap::new();
|
||||
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
|
||||
if let Some(v) = req.headers.get("x-request-id") {
|
||||
header.insert("x-request-id", v.clone());
|
||||
}
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::from(data)), header))
|
||||
}
|
||||
}
|
||||
@@ -329,6 +339,8 @@ pub struct ListTargetsArns {}
|
||||
#[async_trait::async_trait]
|
||||
impl Operation for ListTargetsArns {
|
||||
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
let span = Span::current();
|
||||
let _enter = span.enter();
|
||||
debug!("ListTargetsArns call start request params: {:?}", req.uri.query());
|
||||
|
||||
// 1. Permission verification
|
||||
@@ -364,6 +376,9 @@ impl Operation for ListTargetsArns {
|
||||
debug!("ListTargetsArns call end, response data length: {}", data.len(),);
|
||||
let mut header = HeaderMap::new();
|
||||
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
|
||||
if let Some(v) = req.headers.get("x-request-id") {
|
||||
header.insert("x-request-id", v.clone());
|
||||
}
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::from(data)), header))
|
||||
}
|
||||
}
|
||||
@@ -373,6 +388,8 @@ pub struct RemoveNotificationTarget {}
|
||||
#[async_trait::async_trait]
|
||||
impl Operation for RemoveNotificationTarget {
|
||||
async fn call(&self, req: S3Request<Body>, params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
let span = Span::current();
|
||||
let _enter = span.enter();
|
||||
// 1. Analyze query parameters
|
||||
let (target_type, target_name) = extract_target_params(¶ms)?;
|
||||
|
||||
@@ -398,6 +415,9 @@ impl Operation for RemoveNotificationTarget {
|
||||
let mut header = HeaderMap::new();
|
||||
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
|
||||
header.insert(CONTENT_LENGTH, "0".parse().unwrap());
|
||||
if let Some(v) = req.headers.get("x-request-id") {
|
||||
header.insert("x-request-id", v.clone());
|
||||
}
|
||||
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
);
|
||||
|
||||
if eps.drives_per_set > 1 {
|
||||
warn!("WARNING: Host local has more than 0 drives of set. A host failure will result in data becoming unavailable.");
|
||||
warn!(target: "rustfs::main::run","WARNING: Host local has more than 0 drives of set. A host failure will result in data becoming unavailable.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ use tokio_rustls::TlsAcceptor;
|
||||
use tonic::{Request, Status, metadata::MetadataValue};
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::catch_panic::CatchPanicLayer;
|
||||
use tower_http::compression::CompressionLayer;
|
||||
use tower_http::cors::{AllowOrigin, Any, CorsLayer};
|
||||
use tower_http::request_id::{MakeRequestUuid, PropagateRequestIdLayer, SetRequestIdLayer};
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tracing::{Span, debug, error, info, instrument, warn};
|
||||
|
||||
@@ -448,11 +450,18 @@ fn process_connection(
|
||||
let service = hybrid(s3_service, rpc_service);
|
||||
|
||||
let hybrid_service = ServiceBuilder::new()
|
||||
.layer(SetRequestIdLayer::x_request_id(MakeRequestUuid))
|
||||
.layer(CatchPanicLayer::new())
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
.make_span_with(|request: &HttpRequest<_>| {
|
||||
let trace_id = request
|
||||
.headers()
|
||||
.get(http::header::HeaderName::from_static("x-request-id"))
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("unknown");
|
||||
let span = tracing::info_span!("http-request",
|
||||
trace_id = %trace_id,
|
||||
status_code = tracing::field::Empty,
|
||||
method = %request.method(),
|
||||
uri = %request.uri(),
|
||||
@@ -466,7 +475,8 @@ fn process_connection(
|
||||
|
||||
span
|
||||
})
|
||||
.on_request(|request: &HttpRequest<_>, _span: &Span| {
|
||||
.on_request(|request: &HttpRequest<_>, span: &Span| {
|
||||
let _enter = span.enter();
|
||||
debug!("http started method: {}, url path: {}", request.method(), request.uri().path());
|
||||
let labels = [
|
||||
("key_request_method", format!("{}", request.method())),
|
||||
@@ -474,23 +484,31 @@ fn process_connection(
|
||||
];
|
||||
counter!("rustfs_api_requests_total", &labels).increment(1);
|
||||
})
|
||||
.on_response(|response: &Response<_>, latency: Duration, _span: &Span| {
|
||||
_span.record("http response status_code", tracing::field::display(response.status()));
|
||||
.on_response(|response: &Response<_>, latency: Duration, span: &Span| {
|
||||
span.record("status_code", tracing::field::display(response.status()));
|
||||
let _enter = span.enter();
|
||||
histogram!("request.latency.ms").record(latency.as_millis() as f64);
|
||||
debug!("http response generated in {:?}", latency)
|
||||
})
|
||||
.on_body_chunk(|chunk: &Bytes, latency: Duration, _span: &Span| {
|
||||
.on_body_chunk(|chunk: &Bytes, latency: Duration, span: &Span| {
|
||||
let _enter = span.enter();
|
||||
histogram!("request.body.len").record(chunk.len() as f64);
|
||||
debug!("http body sending {} bytes in {:?}", chunk.len(), latency);
|
||||
})
|
||||
.on_eos(|_trailers: Option<&HeaderMap>, stream_duration: Duration, _span: &Span| {
|
||||
.on_eos(|_trailers: Option<&HeaderMap>, stream_duration: Duration, span: &Span| {
|
||||
let _enter = span.enter();
|
||||
debug!("http stream closed after {:?}", stream_duration)
|
||||
})
|
||||
.on_failure(|_error, latency: Duration, _span: &Span| {
|
||||
.on_failure(|_error, latency: Duration, span: &Span| {
|
||||
let _enter = span.enter();
|
||||
counter!("rustfs_api_requests_failure_total").increment(1);
|
||||
debug!("http request failure error: {:?} in {:?}", _error, latency)
|
||||
}),
|
||||
)
|
||||
.layer(PropagateRequestIdLayer::x_request_id())
|
||||
.layer(cors_layer)
|
||||
// Compress responses
|
||||
.layer(CompressionLayer::new())
|
||||
.option_layer(if is_console { Some(RedirectLayer) } else { None })
|
||||
.service(service);
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ where
|
||||
{
|
||||
type Response = Response<HybridBody<RestBody, GrpcBody>>;
|
||||
type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||
type Future = Pin<Box<dyn Future<Output = std::result::Result<Self::Response, Self::Error>> + Send>>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<std::result::Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.inner.poll_ready(cx).map_err(Into::into)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ use rustfs_ecstore::{
|
||||
},
|
||||
};
|
||||
use rustfs_filemeta::REPLICATE_INCOMING_DELETE;
|
||||
use rustfs_filemeta::fileinfo::{ObjectPartInfo, RestoreStatusOps};
|
||||
use rustfs_filemeta::{ObjectPartInfo, RestoreStatusOps};
|
||||
use rustfs_filemeta::{ReplicationStatusType, ReplicationType, VersionPurgeStatusType};
|
||||
use rustfs_kms::{
|
||||
DataKey,
|
||||
|
||||
Reference in New Issue
Block a user