Skip to content

Commit

Permalink
feat: change log level dynamically (#4653)
Browse files Browse the repository at this point in the history
* feat: add dyn_log handle

* feat: use reload handle

* chore: per review
  • Loading branch information
discord9 authored Sep 4, 2024
1 parent 8453df1 commit cd90ef9
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/common/telemetry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod panic_hook;
pub mod tracing_context;
mod tracing_sampler;

pub use logging::{init_default_ut_logging, init_global_logging};
pub use logging::{init_default_ut_logging, init_global_logging, RELOAD_HANDLE};
pub use metric::dump_metrics;
pub use panic_hook::set_panic_hook;
pub use {common_error, tracing};
pub use {common_error, tracing, tracing_subscriber};
17 changes: 14 additions & 3 deletions src/common/telemetry/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
use std::env;
use std::sync::{Arc, Mutex, Once};

use once_cell::sync::Lazy;
use once_cell::sync::{Lazy, OnceCell};
use opentelemetry::{global, KeyValue};
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::propagation::TraceContextPropagator;
Expand All @@ -26,6 +26,7 @@ use serde::{Deserialize, Serialize};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_log::LogTracer;
use tracing_subscriber::filter::Targets;
use tracing_subscriber::fmt::Layer;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::prelude::*;
Expand All @@ -35,6 +36,10 @@ use crate::tracing_sampler::{create_sampler, TracingSampleOptions};

pub const DEFAULT_OTLP_ENDPOINT: &str = "http://localhost:4317";

// Handle for reloading log level
pub static RELOAD_HANDLE: OnceCell<tracing_subscriber::reload::Handle<Targets, Registry>> =
OnceCell::new();

/// The logging options that used to initialize the logger.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(default)]
Expand Down Expand Up @@ -242,6 +247,12 @@ pub fn init_global_logging(
.parse::<filter::Targets>()
.expect("error parsing log level string");

let (dyn_filter, reload_handle) = tracing_subscriber::reload::Layer::new(filter.clone());

RELOAD_HANDLE
.set(reload_handle)
.expect("reload handle already set, maybe init_global_logging get called twice?");

// Must enable 'tokio_unstable' cfg to use this feature.
// For example: `RUSTFLAGS="--cfg tokio_unstable" cargo run -F common-telemetry/console -- standalone start`
#[cfg(feature = "tokio-console")]
Expand All @@ -263,7 +274,7 @@ pub fn init_global_logging(
};

Registry::default()
.with(filter)
.with(dyn_filter)
.with(tokio_console_layer)
.with(stdout_logging_layer)
.with(file_logging_layer)
Expand All @@ -275,7 +286,7 @@ pub fn init_global_logging(

#[cfg(not(feature = "tokio-console"))]
let subscriber = Registry::default()
.with(filter)
.with(dyn_filter)
.with(stdout_logging_layer)
.with(file_logging_layer)
.with(err_file_logging_layer);
Expand Down
10 changes: 10 additions & 0 deletions src/servers/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ use crate::query_handler::{
use crate::server::Server;

pub mod authorize;
pub mod dyn_log;
pub mod event;
pub mod handler;
pub mod header;
Expand Down Expand Up @@ -708,6 +709,15 @@ impl HttpServer {
authorize::check_http_auth,
)),
)
.nest(
"/debug",
Router::new()
// handler for changing log level dynamically
.route(
"/log_level",
routing::get(dyn_log::dyn_log_handler).post(dyn_log::dyn_log_handler),
),
)
// Handlers for debug, we don't expect a timeout.
.nest(
&format!("/{HTTP_API_VERSION}/prof"),
Expand Down
54 changes: 54 additions & 0 deletions src/servers/src/http/dyn_log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use axum::http::StatusCode;
use axum::response::IntoResponse;
use common_telemetry::tracing_subscriber::filter;
use common_telemetry::{info, RELOAD_HANDLE};
use snafu::OptionExt;

use crate::error::{InternalSnafu, InvalidParameterSnafu, Result};

#[axum_macros::debug_handler]
pub async fn dyn_log_handler(level: String) -> Result<impl IntoResponse> {
let new_filter = level.parse::<filter::Targets>().map_err(|e| {
InvalidParameterSnafu {
reason: format!("Invalid filter \"{level}\": {e:?}"),
}
.build()
})?;
let mut old_filter = None;
RELOAD_HANDLE
.get()
.context(InternalSnafu {
err_msg: "Reload handle not initialized",
})?
.modify(|filter| {
old_filter = Some(filter.clone());
*filter = new_filter.clone()
})
.map_err(|e| {
InternalSnafu {
err_msg: format!("Fail to modify filter: {e:?}"),
}
.build()
})?;
let change_note = format!(
"Log Level changed from {} to {}",
old_filter.map(|f| f.to_string()).unwrap_or_default(),
new_filter
);
info!("{}", change_note.clone());
Ok((StatusCode::OK, change_note))
}

0 comments on commit cd90ef9

Please sign in to comment.