start handling reloads with profiling

This commit is contained in:
Tamo 2024-01-30 16:31:42 +01:00 committed by Louis Dureuil
parent 3c3a258a22
commit abaa72e2bf
No known key found for this signature in database
3 changed files with 32 additions and 43 deletions

View File

@ -39,6 +39,7 @@ use meilisearch_types::versioning::{check_version_file, create_version_file};
use meilisearch_types::{compression, milli, VERSION_FILE_NAME};
pub use option::Opt;
use option::ScheduleSnapshot;
use tracing_subscriber::filter::Targets;
use crate::error::MeilisearchHttpError;
@ -89,9 +90,10 @@ fn is_empty_db(db_path: impl AsRef<Path>) -> bool {
/// The handle used to update the logs at runtime. Must be accessible from the `main.rs` and the `route/logs.rs`.
pub type LogRouteHandle =
tracing_subscriber::reload::Handle<LogRouteType, tracing_subscriber::Registry>;
pub type LogRouteType = tracing_subscriber::filter::Filtered<
Option<Box<dyn tracing_subscriber::Layer<tracing_subscriber::Registry> + Send + Sync>>,
tracing_subscriber::filter::LevelFilter,
Targets,
tracing_subscriber::Registry,
>;

View File

@ -12,7 +12,9 @@ use anyhow::Context;
use index_scheduler::IndexScheduler;
use is_terminal::IsTerminal;
use meilisearch::analytics::Analytics;
use meilisearch::{analytics, create_app, prototype_name, setup_meilisearch, LogRouteHandle, Opt};
use meilisearch::{
analytics, create_app, prototype_name, setup_meilisearch, LogRouteHandle, LogRouteType, Opt,
};
use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE};
use mimalloc::MiMalloc;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
@ -28,9 +30,8 @@ static ALLOC: MiMalloc = MiMalloc;
#[global_allocator]
static ALLOC: stats_alloc::StatsAlloc<MiMalloc> = stats_alloc::StatsAlloc::new(MiMalloc);
fn default_layer<S: tracing::Subscriber>(
) -> tracing_subscriber::filter::Filtered<Option<Box<dyn Layer<S> + Send + Sync>>, LevelFilter, S> {
None.with_filter(tracing_subscriber::filter::LevelFilter::OFF)
fn default_layer() -> LogRouteType {
None.with_filter(tracing_subscriber::filter::Targets::new().with_target("", LevelFilter::OFF))
}
/// does all the setup before meilisearch is launched

View File

@ -2,6 +2,7 @@ use std::fmt;
use std::io::Write;
use std::ops::ControlFlow;
use std::str::FromStr;
use std::sync::Arc;
use actix_web::web::{Bytes, Data};
use actix_web::{web, HttpRequest, HttpResponse};
@ -13,6 +14,7 @@ use meilisearch_types::error::deserr_codes::*;
use meilisearch_types::error::ResponseError;
use tokio::sync::mpsc::{self, UnboundedSender};
use tracing::instrument::WithSubscriber;
use tracing_subscriber::filter::Targets;
use tracing_subscriber::Layer;
use crate::error::MeilisearchHttpError;
@ -48,7 +50,7 @@ pub enum LogMode {
#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)]
pub struct GetLogs {
#[deserr(default, error = DeserrJsonError<BadRequest>)]
pub level: LogLevel,
pub target: String,
#[deserr(default, error = DeserrJsonError<BadRequest>)]
pub mode: LogMode,
@ -70,6 +72,12 @@ struct LogWriter {
sender: mpsc::UnboundedSender<Vec<u8>>,
}
impl Drop for LogWriter {
fn drop(&mut self) {
println!("hello");
}
}
impl Write for LogWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.sender.send(buf.to_vec()).map_err(std::io::Error::other)?;
@ -83,6 +91,17 @@ impl Write for LogWriter {
struct LogStreamer {
receiver: mpsc::UnboundedReceiver<Vec<u8>>,
/// We need to keep an handle on the logs to make it available again when the streamer is dropped
logs: Arc<LogRouteHandle>,
}
impl Drop for LogStreamer {
fn drop(&mut self) {
println!("log streamer being dropped");
if let Err(e) = self.logs.modify(|layer| *layer.inner_mut() = None) {
tracing::error!("Could not free the logs route: {e}");
}
}
}
impl LogStreamer {
@ -142,50 +161,16 @@ pub async fn get_logs(
_req: HttpRequest,
) -> Result<HttpResponse, ResponseError> {
let opt = body.into_inner();
// #[cfg(not(feature = "stats_alloc"))]
// let (mut trace, layer) = tracing_trace::Trace::new(file);
// #[cfg(feature = "stats_alloc")]
// let (mut trace, layer) = tracing_trace::Trace::with_stats_alloc(file, &ALLOC);
let (sender, receiver) = tokio::sync::mpsc::unbounded_channel();
// let fmt_layer = tracing_subscriber::fmt::layer()
// .with_line_number(true)
// .with_writer(move || LogWriter { sender: sender.clone() })
// .with_span_events(tracing_subscriber::fmt::format::FmtSpan::ACTIVE)
// .with_filter(
// tracing_subscriber::filter::LevelFilter::from_str(&opt.level.to_string()).unwrap(),
// );
// let subscriber = tracing_subscriber::registry().with(fmt_layer);
// let subscriber = Box::new(subscriber) as Box<dyn Layer<S> + Send + Sync>;
let mut was_available = false;
logs.modify(|layer| match layer.inner_mut() {
None => {
// there is no one getting logs
was_available = true;
match opt.mode {
LogMode::Fmt => {
*layer.filter_mut() =
tracing_subscriber::filter::LevelFilter::from_str(&opt.level.to_string())
.unwrap();
}
LogMode::Profile => {
*layer.filter_mut() =
tracing_subscriber::filter::LevelFilter::from_str(&opt.level.to_string())
.unwrap();
// *layer.filter_mut() = tracing_subscriber::filter::Targets::new()
// .with_target("indexing::", tracing::Level::TRACE)
// .with_filter(
// tracing_subscriber::filter::LevelFilter::from_str(
// &opt.level.to_string(),
// )
// .unwrap(),
// )
}
}
*layer.filter_mut() =
tracing_subscriber::filter::Targets::from_str(&opt.target).unwrap();
let new_layer = make_layer(&opt, sender);
*layer.inner_mut() = Some(new_layer)
@ -198,7 +183,8 @@ pub async fn get_logs(
.unwrap();
if was_available {
Ok(HttpResponse::Ok().streaming(LogStreamer { receiver }.into_stream()))
Ok(HttpResponse::Ok()
.streaming(LogStreamer { receiver, logs: logs.into_inner() }.into_stream()))
} else {
Err(MeilisearchHttpError::AlreadyUsedLogRoute.into())
}