salvo-logging
Implement request logging, tracing, and observability. Use for debugging, monitoring, and production observability.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Implement request logging, tracing, and observability. Use for debugging, monitoring, and production observability.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | salvo-logging |
| description | Implement request logging, tracing, and observability. Use for debugging, monitoring, and production observability. |
| version | 0.89.3 |
| tags | ["operations","logging","tracing","observability"] |
This skill helps implement logging and tracing in Salvo applications.
[dependencies]
salvo = { version = "0.89.3", features = ["logging"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
use salvo::logging::Logger;
use salvo::prelude::*;
#[handler]
async fn hello() -> &'static str {
"Hello, World!"
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let router = Router::new()
.get(hello)
.push(Router::with_path("error").get(error));
let service = Service::new(router).hoop(Logger::new());
let acceptor = TcpListener::new("0.0.0.0:8080").bind().await;
Server::new(acceptor).serve(service).await;
}
use salvo::prelude::*;
use tracing::info;
use std::time::Instant;
#[handler]
async fn request_logger(
req: &mut Request,
depot: &mut Depot,
res: &mut Response,
ctrl: &mut FlowCtrl,
) {
let start = Instant::now();
let method = req.method().clone();
let path = req.uri().path().to_string();
let remote_addr = req.remote_addr().map(|a| a.to_string());
ctrl.call_next(req, depot, res).await;
let duration = start.elapsed();
let status = res.status_code().unwrap_or(StatusCode::OK);
info!(
method = %method,
path = %path,
status = %status.as_u16(),
duration_ms = %duration.as_millis(),
remote_addr = ?remote_addr,
"Request completed"
);
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt()
.with_target(false)
.with_level(true)
.init();
let router = Router::new()
.hoop(request_logger)
.get(hello);
let acceptor = TcpListener::new("0.0.0.0:8080").bind().await;
Server::new(acceptor).serve(router).await;
}
use salvo::prelude::*;
use tracing::{info, warn, error, debug, instrument};
#[handler]
#[instrument(skip(req, res), fields(user_id))]
async fn get_user(req: &mut Request, res: &mut Response) {
let user_id: u32 = req.param("id").unwrap_or(0);
tracing::Span::current().record("user_id", user_id);
debug!("Fetching user from database");
match fetch_user(user_id).await {
Ok(user) => {
info!(user_id = %user_id, "User found");
res.render(Json(user));
}
Err(e) => {
warn!(user_id = %user_id, error = %e, "User not found");
res.status_code(StatusCode::NOT_FOUND);
}
}
}
use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
fn init_logging() {
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| {
EnvFilter::new("info")
.add_directive("salvo=debug".parse().unwrap())
.add_directive("hyper=warn".parse().unwrap())
});
tracing_subscriber::registry()
.with(filter)
.with(tracing_subscriber::fmt::layer())
.init();
}
#[tokio::main]
async fn main() {
init_logging();
// Application code...
}
use tracing_subscriber::{fmt, EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
fn init_json_logging() {
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("info"));
tracing_subscriber::registry()
.with(filter)
.with(
fmt::layer()
.json()
.with_current_span(true)
.with_span_list(true)
)
.init();
}
use salvo::prelude::*;
use uuid::Uuid;
use tracing::info;
#[handler]
async fn add_request_id(
req: &mut Request,
depot: &mut Depot,
res: &mut Response,
ctrl: &mut FlowCtrl,
) {
let request_id = req
.header::<String>("X-Request-ID")
.unwrap_or_else(|| Uuid::new_v4().to_string());
depot.insert("request_id", request_id.clone());
res.headers_mut().insert(
"X-Request-ID",
request_id.parse().unwrap(),
);
let span = tracing::info_span!(
"request",
request_id = %request_id,
method = %req.method(),
path = %req.uri().path()
);
let _enter = span.enter();
ctrl.call_next(req, depot, res).await;
}
use salvo::prelude::*;
use tracing::{error, warn};
#[handler]
async fn error_handler(
req: &mut Request,
depot: &mut Depot,
res: &mut Response,
ctrl: &mut FlowCtrl,
) {
ctrl.call_next(req, depot, res).await;
if let Some(status) = res.status_code() {
if status.is_server_error() {
error!(
status = %status.as_u16(),
path = %req.uri().path(),
"Server error occurred"
);
} else if status.is_client_error() {
warn!(
status = %status.as_u16(),
path = %req.uri().path(),
"Client error"
);
}
}
}
Guide for using RBatis v4 Rust ORM framework. Use when implementing database CRUD operations, writing dynamic SQL with py_sql or html_sql macros, configuring database connections, managing transactions, implementing interceptors, syncing table structures, or integrating RBatis into Genies microservices. Also use when the user asks about RBatis usage patterns, query building, or database operations in Rust.
Genies 前后端接口规范。Use when designing API contracts, defining field naming conventions, date/time formats, response models, pagination, error handling, or ID strategies between Genies backend and frontend (Web/Android/OHOS).
Guide for using flyway-rs database migration framework with RBatis. Use when implementing database schema migrations, managing SQL changelog files, configuring migration runners, handling multi-database migrations, or integrating database versioning into Genies microservices.
Guide for developing Rust microservices using Genies framework following Java DDD layering principles. Use when creating new microservices, designing aggregate roots, implementing domain events, organizing service layers, setting up Flyway migrations, or structuring a DDD-based Genies project.
Genies framework unified skill hub. Use when you need to find the right skill for any Genies framework task, including authentication, authorization, caching, configuration, database, DDD microservices, Dapr messaging, macros, K8s deployment, testing, API conventions, gateway proxy, or Salvo web framework features. Also use when the user asks about Genies framework capabilities, asks which skill to use, or wants a quick overview of available Genies skills.
Guide for using the Genies Rust microservice framework with DDD and Dapr. Use when developing with Genies, creating aggregates, domain events, Dapr subscriptions, Casbin field-level permissions, configuration management, or when the user asks about Genies framework usage patterns.