Add dynamic log level reload support to server
Introduces tracing_subscriber::reload to enable dynamic log level changes at runtime. Updates the main server initialization and ServiceRegister to accept and store a log handle. Refactors related code to support this feature and removes disabled state from developer UI log level selectors.
This commit is contained in:
1 parent
3698bcf28a
commit
55370dd87a
13 files changed
+101
-75
No files matched your search
Generated
+2
-2
@@ -362,7 +362,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "biliup-cli"
|
||||
version = "1.1.24"
|
||||
version = "1.1.25"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-trait",
|
||||
@@ -3645,7 +3645,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "stream-gears"
|
||||
version = "1.1.24"
|
||||
version = "1.1.25"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-trait",
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ members = [
|
||||
resolver = "3"
|
||||
|
||||
[workspace.package]
|
||||
version = "1.1.24"
|
||||
version = "1.1.25"
|
||||
|
||||
[workspace.dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
@@ -52,7 +52,6 @@ const Developer: React.FC = () => {
|
||||
formApi.setValue('LOGGING.root.handlers', ['console'])
|
||||
}}
|
||||
showClear={true}
|
||||
disabled
|
||||
>
|
||||
<Select.Option value="DEBUG">DEBUG</Select.Option>
|
||||
<Select.Option value="INFO">INFO</Select.Option>
|
||||
@@ -73,7 +72,6 @@ const Developer: React.FC = () => {
|
||||
formApi.setValue('LOGGING.loggers.biliup.handlers', ['file'])
|
||||
}}
|
||||
showClear={true}
|
||||
disabled
|
||||
>
|
||||
<Select.Option value="DEBUG">DEBUG</Select.Option>
|
||||
<Select.Option value="INFO">INFO</Select.Option>
|
||||
|
||||
@@ -14,8 +14,14 @@ use clap::ValueEnum;
|
||||
use error_stack::ResultExt;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use tracing_subscriber::{EnvFilter, Registry, reload};
|
||||
|
||||
pub async fn run(addr: (&str, u16), auth: bool) -> AppResult<()> {
|
||||
// 定义 Handle 的类型别名,简化代码
|
||||
// EnvFilter: 我们使用的过滤器类型
|
||||
// Registry: 基础的 Subscriber 类型
|
||||
type LogHandle = reload::Handle<EnvFilter, Registry>;
|
||||
|
||||
pub async fn run(addr: (&str, u16), auth: bool, log_handle: LogHandle) -> AppResult<()> {
|
||||
// let config = Arc::new(AppConfig::parse());
|
||||
|
||||
tracing::info!(
|
||||
@@ -31,7 +37,8 @@ pub async fn run(addr: (&str, u16), auth: bool) -> AppResult<()> {
|
||||
config.read().unwrap().pool2_size,
|
||||
conn_pool.clone(),
|
||||
);
|
||||
let service_register = ServiceRegister::new(conn_pool, config.clone(), download_manager);
|
||||
let service_register =
|
||||
ServiceRegister::new(conn_pool, config.clone(), download_manager, log_handle);
|
||||
|
||||
tracing::info!("migrations successfully ran, initializing axum server...");
|
||||
let addr = addr
|
||||
|
||||
@@ -9,6 +9,7 @@ use clap::Parser;
|
||||
|
||||
use biliup_cli::server::errors::AppResult;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::reload;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
#[tokio::main]
|
||||
@@ -33,8 +34,11 @@ async fn main() -> AppResult<()> {
|
||||
"[year]-[month]-[day] [hour]:[minute]:[second]"
|
||||
));
|
||||
|
||||
let console_filter = tracing_subscriber::EnvFilter::new(&cli.rust_log);
|
||||
// let (file_filter_layer, file_reload_handle) = reload::Layer::new(file_filter);
|
||||
let (console_filter_layer, console_reload_handle) = reload::Layer::new(console_filter);
|
||||
tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::EnvFilter::new(&cli.rust_log))
|
||||
.with(console_filter_layer)
|
||||
.with(tracing_subscriber::fmt::layer().with_timer(timer))
|
||||
.init();
|
||||
|
||||
@@ -97,7 +101,9 @@ async fn main() -> AppResult<()> {
|
||||
split_size,
|
||||
split_time,
|
||||
} => download(&url, output, split_size, split_time).await?,
|
||||
Commands::Server { bind, port, auth } => biliup_cli::run((&bind, port), auth).await?,
|
||||
Commands::Server { bind, port, auth } => {
|
||||
biliup_cli::run((&bind, port), auth, console_reload_handle).await?
|
||||
}
|
||||
Commands::List {
|
||||
is_pubing,
|
||||
pubed,
|
||||
|
||||
@@ -544,37 +544,37 @@ pub async fn post_uploads(
|
||||
(line, limit, submit_api)
|
||||
};
|
||||
info!("通过页面开始上传");
|
||||
let (bilibili, videos) = upload(
|
||||
upload_config
|
||||
.user_cookie
|
||||
.as_deref()
|
||||
.unwrap_or("cookies.json"),
|
||||
None,
|
||||
line,
|
||||
&json_data.files,
|
||||
limit as usize,
|
||||
)
|
||||
.await
|
||||
.map_err(report_to_response)?;
|
||||
if !videos.is_empty() {
|
||||
let recorder = Recorder::new(
|
||||
upload_config.title.clone(),
|
||||
StreamerInfo::new(
|
||||
&upload_config.template_name,
|
||||
"stream_title",
|
||||
tokio::spawn(async move {
|
||||
let (bilibili, videos) = upload(
|
||||
upload_config
|
||||
.user_cookie
|
||||
.as_deref()
|
||||
.unwrap_or("cookies.json"),
|
||||
None,
|
||||
line,
|
||||
&json_data.files,
|
||||
limit as usize,
|
||||
)
|
||||
.await?;
|
||||
if !videos.is_empty() {
|
||||
let recorder = Recorder::new(
|
||||
upload_config.title.clone(),
|
||||
StreamerInfo::new(
|
||||
&upload_config.template_name,
|
||||
"stream_title",
|
||||
"",
|
||||
Utc::now(),
|
||||
"",
|
||||
),
|
||||
"",
|
||||
Utc::now(),
|
||||
"",
|
||||
),
|
||||
"",
|
||||
);
|
||||
let studio = build_studio(&upload_config, &bilibili, videos, recorder)
|
||||
.await
|
||||
.map_err(report_to_response)?;
|
||||
let response_data = submit_to_bilibili(&bilibili, &studio, submit_api.as_deref())
|
||||
.await
|
||||
.map_err(report_to_response)?;
|
||||
info!("通过页面上传成功 {:?}", response_data);
|
||||
}
|
||||
);
|
||||
let studio = build_studio(&upload_config, &bilibili, videos, recorder).await?;
|
||||
let response_data =
|
||||
submit_to_bilibili(&bilibili, &studio, submit_api.as_deref()).await?;
|
||||
info!("通过页面上传成功 {:?}", response_data);
|
||||
}
|
||||
Ok::<_, Report<AppError>>(())
|
||||
});
|
||||
|
||||
Ok(Json(serde_json::json!({})))
|
||||
}
|
||||
@@ -114,12 +114,7 @@ impl SegmentEventProcessor {
|
||||
channel: None,
|
||||
uploader,
|
||||
file_validator: FileValidator::new(
|
||||
ctx.worker
|
||||
.clone()
|
||||
.get_config()
|
||||
.filtering_threshold
|
||||
* 1000
|
||||
* 1000,
|
||||
ctx.worker.clone().get_config().filtering_threshold * 1000 * 1000,
|
||||
true,
|
||||
),
|
||||
ctx,
|
||||
|
||||
@@ -239,7 +239,12 @@ pub(crate) async fn build_studio(
|
||||
.maybe_copyright(upload_config.copyright)
|
||||
.cover(upload_config.cover_path.clone().unwrap_or_default())
|
||||
.dynamic(upload_config.dynamic.clone().unwrap_or_default())
|
||||
.source(upload_config.copyright_source.clone().unwrap_or_default())
|
||||
.source(
|
||||
upload_config
|
||||
.copyright_source
|
||||
.clone()
|
||||
.unwrap_or_else(|| recorder.streamer_info.url.clone()),
|
||||
)
|
||||
.tag(upload_config.tags.join(","))
|
||||
.maybe_tid(upload_config.tid)
|
||||
.title(recorder.format_filename())
|
||||
|
||||
@@ -441,10 +441,8 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
single,
|
||||
Config::builder()
|
||||
.streamers(Default::default())
|
||||
.build(),
|
||||
Config::builder().streamers(Default::default()).build(),
|
||||
"普通Option正常包裹一层"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,9 @@ impl Monitor {
|
||||
// 没有必要检查两次失败
|
||||
let _ = self.sender.send(msg).await;
|
||||
if let Some(worker) = recv.await.expect("Actor task has been killed") {
|
||||
worker.change_status(Stage::Download, WorkerStatus::Idle).await;
|
||||
worker
|
||||
.change_status(Stage::Download, WorkerStatus::Idle)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::server::config::{Config, ConfigPatch};
|
||||
use crate::server::infrastructure::models::hook_step::HookStep;
|
||||
use ormlite::{Insert, Model};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use crate::server::config::{Config, ConfigPatch};
|
||||
|
||||
/// 直播主播模型
|
||||
/// 存储直播主播的配置信息和录制参数
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::LogHandle;
|
||||
use crate::server::config::Config;
|
||||
use crate::server::core::download_manager::DownloadManager;
|
||||
use crate::server::core::plugin::yy::YY;
|
||||
@@ -7,9 +8,9 @@ use crate::server::infrastructure::models::live_streamer::LiveStreamer;
|
||||
use crate::server::infrastructure::models::upload_streamer::UploadStreamer;
|
||||
use axum::extract::FromRef;
|
||||
use biliup::client::StatelessClient;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use error_stack::fmt::ColorMode;
|
||||
use error_stack::Report;
|
||||
use error_stack::fmt::ColorMode;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use tracing::info;
|
||||
|
||||
/// 服务注册器
|
||||
@@ -24,6 +25,8 @@ pub struct ServiceRegister {
|
||||
pub config: Arc<RwLock<Config>>,
|
||||
/// HTTP客户端
|
||||
pub client: StatelessClient,
|
||||
#[from_ref(skip)]
|
||||
log_handle: LogHandle,
|
||||
}
|
||||
|
||||
/// 简单的服务容器,负责管理API端点通过axum扩展获取的各种服务
|
||||
@@ -39,6 +42,7 @@ impl ServiceRegister {
|
||||
pool: ConnectionPool,
|
||||
config: Arc<RwLock<Config>>,
|
||||
download_manager: DownloadManager,
|
||||
log_handle: LogHandle,
|
||||
) -> Self {
|
||||
Report::set_color_mode(ColorMode::None);
|
||||
info!("initializing utility services...");
|
||||
@@ -56,6 +60,7 @@ impl ServiceRegister {
|
||||
managers: Arc::new(download_manager),
|
||||
config: config.clone(),
|
||||
client,
|
||||
log_handle,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ use std::sync::{Arc, LazyLock, RwLock};
|
||||
use time::macros::format_description;
|
||||
use tracing::{debug, info, warn};
|
||||
use tracing_appender::rolling::Rotation;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::{EnvFilter, reload};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PyPlugin {
|
||||
@@ -339,6 +339,14 @@ pub(crate) async fn _main(args: &[String]) -> AppResult<()> {
|
||||
let local_time = tracing_subscriber::fmt::time::LocalTime::new(format_description!(
|
||||
"[year]-[month]-[day] [hour]:[minute]:[second]"
|
||||
));
|
||||
|
||||
let console_layer = tracing_subscriber::fmt::layer()
|
||||
.with_target(false)
|
||||
.with_timer(local_time.clone())
|
||||
.with_file(true) // 打印文件名
|
||||
.with_line_number(true)
|
||||
.with_thread_ids(true);
|
||||
|
||||
// 按日期滚动,每天创建新文件
|
||||
let file_appender = tracing_appender::rolling::RollingFileAppender::builder()
|
||||
.rotation(Rotation::DAILY) // rotate log files once every hour
|
||||
@@ -355,27 +363,25 @@ pub(crate) async fn _main(args: &[String]) -> AppResult<()> {
|
||||
|
||||
let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
|
||||
|
||||
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||
let (filter_layer, reload_handle) = reload::Layer::new(filter);
|
||||
|
||||
let file_layer = tracing_subscriber::fmt::layer()
|
||||
.with_writer(non_blocking)
|
||||
.with_timer(local_time)
|
||||
.with_target(true)
|
||||
.with_thread_ids(true)
|
||||
.with_file(true)
|
||||
.with_line_number(true)
|
||||
.with_ansi(false);
|
||||
|
||||
let subscriber = tracing_subscriber::registry()
|
||||
.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")))
|
||||
.with(filter_layer) // 这个是“总开关”,所有 layer 都会被它过滤
|
||||
// 控制台输出
|
||||
.with(
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_target(false)
|
||||
.with_timer(local_time.clone())
|
||||
.with_file(true) // 打印文件名
|
||||
.with_line_number(true)
|
||||
.with_thread_ids(true),
|
||||
)
|
||||
.with(console_layer)
|
||||
// 文件输出
|
||||
.with(
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_writer(non_blocking)
|
||||
.with_timer(local_time)
|
||||
.with_target(true)
|
||||
.with_thread_ids(true)
|
||||
.with_file(true)
|
||||
.with_line_number(true)
|
||||
.with_ansi(false), // .json() // 可选:使用 JSON 格式便于解析
|
||||
file_layer, // .json() // 可选:使用 JSON 格式便于解析
|
||||
);
|
||||
|
||||
subscriber.init();
|
||||
@@ -461,8 +467,12 @@ pub(crate) async fn _main(args: &[String]) -> AppResult<()> {
|
||||
download_manager.add_plugin(Arc::new(v));
|
||||
}
|
||||
|
||||
let service_register =
|
||||
ServiceRegister::new(conn_pool.clone(), CONFIG.clone(), download_manager);
|
||||
let service_register = ServiceRegister::new(
|
||||
conn_pool.clone(),
|
||||
CONFIG.clone(),
|
||||
download_manager,
|
||||
reload_handle,
|
||||
);
|
||||
|
||||
let all_streamer = repositories::get_all_streamer(&conn_pool).await?;
|
||||
|
||||
|
||||
Reference in new issue
Block a user