metrics_basic/
metrics_basic.rs1use autometrics::autometrics;
2use log::info;
3use rs_infras::logger::Logger;
4use rs_infras::metrics::{API_SLO, prometheus_init};
5use std::net::SocketAddr;
6use std::process;
7use std::time::Duration;
8use axum::{Json, Router, http::StatusCode, response::IntoResponse, routing::get};
10use rs_infras::shutdown::graceful_shutdown;
11use serde::{Deserialize, Serialize};
12use tokio::net::TcpListener;
13
14#[tokio::main]
19async fn main() {
20 Logger::new().init();
21 info!("current process pid:{}", process::id());
22 info!("service start...");
23
24 let metrics_port = 8090;
26 let metrics_server = prometheus_init(metrics_port);
27 let metrics_handler = tokio::spawn(metrics_server);
28
29 let app_port = 8080;
30 let http_handler = tokio::spawn(async move {
32 let address: SocketAddr = format!("0.0.0.0:{}", app_port).parse().unwrap();
33
34 info!("http server run on:{}", address.to_string());
35
36 let router = api_router();
38
39 let listener = TcpListener::bind(address).await.unwrap();
41
42 let graceful_wait_time = 5;
44 axum::serve(listener, router)
45 .with_graceful_shutdown(graceful_shutdown(Duration::from_secs(graceful_wait_time)))
46 .await
47 .expect("failed to start gateway service");
48 });
49
50 let _ = tokio::try_join!(http_handler, metrics_handler)
52 .expect("failed to start http gateway and metrics service");
53}
54
55pub fn api_router() -> Router {
57 let api_routers = Router::new()
59 .route("/", get(root))
60 .route("/home", get(home))
61 .fallback(api_not_found);
62
63 let router = Router::new()
64 .nest("/api", api_routers)
65 .route("/", get(root))
66 .fallback(not_found_handler);
67
68 router
69}
70
71#[autometrics]
72pub async fn root() -> &'static str {
73 "Hello, World!"
74}
75
76#[autometrics(objective = API_SLO)]
77pub async fn home() -> &'static str {
80 "Hello, home!"
81}
82
83#[derive(Deserialize, Serialize, Debug)]
84pub struct Reply<T> {
85 pub code: i32,
86 pub message: String,
87 pub data: Option<T>,
88}
89
90#[derive(Deserialize, Serialize, Debug)]
92pub struct EmptyObject {}
93
94async fn api_not_found() -> impl IntoResponse {
96 (
97 StatusCode::NOT_FOUND,
98 Json(Reply {
99 code: 404,
100 message: "api not found".to_string(),
101 data: Some(EmptyObject {}),
102 }),
103 )
104}
105
106async fn not_found_handler() -> impl IntoResponse {
108 (StatusCode::NOT_FOUND, "this page not found")
109}