kwaak 0.7.0

Run a team of autonomous agents on your code, right from your terminal
Documentation
use crate::repository::Repository;
use anyhow::Result;
use tracing::level_filters::LevelFilter;
use tracing_opentelemetry::OpenTelemetryLayer;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};

pub struct Guard {
    otel: Option<TracerProvider>,
}

impl Drop for Guard {
    fn drop(&mut self) {
        tracing::debug!("shutting down tracing");
        if let Some(provider) = self.otel.take() {
            if let Err(e) = provider.shutdown() {
                eprintln!("Failed to shutdown OpenTelemetry: {e:?}");
            }
        }
    }
}
/// Configures tracing for the app
///
/// # Panics
///
/// Panics if setting up tracing fails
pub fn init(repository: &Repository) -> Result<Guard> {
    let log_dir = repository.config().log_dir();

    let file_appender = tracing_appender::rolling::daily(
        log_dir,
        format!("{}.log", repository.config().project_name),
    );

    let fmt_layer = fmt::layer().compact().with_writer(file_appender);

    // Logs the file layer will capture
    let mut env_filter_layer = EnvFilter::builder()
        .with_default_directive(LevelFilter::ERROR.into())
        .from_env_lossy();

    if cfg!(feature = "otel") && repository.config().otel_enabled {
        env_filter_layer = env_filter_layer
            .add_directive("swiftide=debug".parse().unwrap())
            .add_directive("swiftide_docker_executor=info".parse().unwrap())
            .add_directive("swiftide_indexing=debug".parse().unwrap())
            .add_directive("swiftide_integrations=debug".parse().unwrap())
            .add_directive("swiftide_query=debug".parse().unwrap())
            .add_directive("swiftide_agents=debug".parse().unwrap())
            .add_directive("swiftide_core=debug".parse().unwrap())
            .add_directive("kwaak=debug".parse().unwrap());
    }

    // The log level tui logger will capture
    let default_level = if cfg!(debug_assertions) {
        log::LevelFilter::Info
    } else {
        log::LevelFilter::Warn
    };
    let tui_layer = tui_logger::tracing_subscriber_layer();
    tui_logger::init_logger(default_level)?;

    let mut layers = vec![tui_layer.boxed(), fmt_layer.boxed()];

    let mut provider_for_guard = None;
    if cfg!(feature = "otel") && repository.config().otel_enabled {
        println!("OpenTelemetry tracing enabled");
        let provider = init_otel();
        let tracer = provider.tracer("kwaak");
        opentelemetry::global::set_tracer_provider(provider.clone());
        provider_for_guard = Some(provider);

        // Create a tracing layer with the configured tracer
        let layer = OpenTelemetryLayer::new(tracer);

        layers.push(layer.boxed());
    }

    let registry = tracing_subscriber::registry()
        .with(env_filter_layer)
        .with(layers);
    registry.try_init()?;

    Ok(Guard {
        otel: provider_for_guard,
    })
}

#[cfg(feature = "otel")]
use opentelemetry::trace::TracerProvider as _;
#[cfg(feature = "otel")]
use opentelemetry_sdk::trace::TracerProvider;

#[cfg(feature = "otel")]
fn init_otel() -> TracerProvider {
    use opentelemetry_sdk::runtime;
    use opentelemetry_sdk::trace::TracerProvider;

    let exporter = opentelemetry_otlp::SpanExporter::builder()
        .with_http()
        .build()
        .expect("failed to create otlp exporter");

    TracerProvider::builder()
        .with_batch_exporter(exporter, runtime::Tokio)
        .with_resource(opentelemetry_sdk::Resource::new(vec![
            opentelemetry::KeyValue::new("service.name", "kwaak"),
        ]))
        .build()
}