chore: add loadtest observability setup
This commit is contained in:
@@ -75,6 +75,7 @@ mod square_hole_agent_turn;
|
||||
mod state;
|
||||
mod story_battles;
|
||||
mod story_sessions;
|
||||
mod telemetry;
|
||||
mod tracking;
|
||||
mod vector_engine_audio_generation;
|
||||
mod visual_novel;
|
||||
@@ -85,8 +86,15 @@ mod wechat_provider;
|
||||
mod work_author;
|
||||
mod work_play_tracking;
|
||||
|
||||
use shared_logging::init_tracing;
|
||||
use std::{collections::HashSet, env, fs, io, panic, thread, time::Duration};
|
||||
use shared_logging::{OtelConfig, init_tracing};
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
env, fs, io,
|
||||
net::{SocketAddr, TcpListener as StdTcpListener},
|
||||
panic, thread,
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::runtime::Builder as TokioRuntimeBuilder;
|
||||
use tokio::time::timeout;
|
||||
@@ -103,12 +111,18 @@ fn main() -> Result<(), io::Error> {
|
||||
.name("api-server-bootstrap".to_string())
|
||||
.stack_size(API_SERVER_STARTUP_STACK_SIZE_BYTES)
|
||||
.spawn(|| {
|
||||
TokioRuntimeBuilder::new_multi_thread()
|
||||
load_local_env_files();
|
||||
let config = AppConfig::from_env();
|
||||
let mut runtime_builder = TokioRuntimeBuilder::new_multi_thread();
|
||||
runtime_builder
|
||||
.enable_all()
|
||||
.thread_name("api-server-worker")
|
||||
.thread_stack_size(API_SERVER_STARTUP_STACK_SIZE_BYTES)
|
||||
.build()?
|
||||
.block_on(run_server())
|
||||
.thread_stack_size(API_SERVER_STARTUP_STACK_SIZE_BYTES);
|
||||
if let Some(worker_threads) = config.worker_threads {
|
||||
runtime_builder.worker_threads(worker_threads);
|
||||
}
|
||||
|
||||
runtime_builder.build()?.block_on(run_server(config))
|
||||
})?;
|
||||
|
||||
match server_thread.join() {
|
||||
@@ -117,28 +131,49 @@ fn main() -> Result<(), io::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_server() -> Result<(), io::Error> {
|
||||
// 运行本地开发与联调时,优先从仓库根目录加载本地变量。
|
||||
// 只尊重外层 shell 先注入的变量;后续本地文件需要能覆盖前序本地文件。
|
||||
load_local_env_files();
|
||||
|
||||
// 统一先从配置对象读取监听地址,避免后续把环境变量读取散落到入口和路由层。
|
||||
let config = AppConfig::from_env();
|
||||
init_tracing(&config.log_filter)?;
|
||||
async fn run_server(config: AppConfig) -> Result<(), io::Error> {
|
||||
init_tracing(
|
||||
&config.log_filter,
|
||||
OtelConfig {
|
||||
enabled: config.otel_enabled,
|
||||
},
|
||||
)?;
|
||||
|
||||
let bind_address = config.bind_socket_addr();
|
||||
let listener = TcpListener::bind(bind_address).await?;
|
||||
let listen_backlog = config.listen_backlog;
|
||||
let worker_threads = config.worker_threads;
|
||||
let otel_enabled = config.otel_enabled;
|
||||
let listener = build_tcp_listener(bind_address, listen_backlog)?;
|
||||
|
||||
let state = restore_app_state_for_startup(config)
|
||||
.await
|
||||
.map_err(|error| std::io::Error::other(format!("初始化应用状态失败:{error}")))?;
|
||||
let router = build_router(state);
|
||||
|
||||
info!(%bind_address, "api-server 已完成 tracing 初始化并开始监听");
|
||||
info!(
|
||||
%bind_address,
|
||||
listen_backlog,
|
||||
worker_threads = worker_threads.unwrap_or(0),
|
||||
otel_enabled,
|
||||
"api-server 已完成 tracing 初始化并开始监听"
|
||||
);
|
||||
|
||||
axum::serve(listener, router).await
|
||||
}
|
||||
|
||||
fn build_tcp_listener(
|
||||
bind_address: SocketAddr,
|
||||
listen_backlog: i32,
|
||||
) -> Result<TcpListener, io::Error> {
|
||||
let domain = Domain::for_address(bind_address);
|
||||
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
|
||||
socket.set_reuse_address(true)?;
|
||||
socket.set_nonblocking(true)?;
|
||||
socket.bind(&bind_address.into())?;
|
||||
socket.listen(listen_backlog)?;
|
||||
TcpListener::from_std(StdTcpListener::from(socket))
|
||||
}
|
||||
|
||||
async fn restore_app_state_for_startup(
|
||||
config: AppConfig,
|
||||
) -> Result<AppState, state::AppStateInitError> {
|
||||
|
||||
Reference in New Issue
Block a user