v0.2.5-pre.009

This commit is contained in:
2026-08-20 09:24:10 +02:00
parent 1125ade4c1
commit e91bf36e9e
83 changed files with 2467 additions and 1801 deletions

View File

@@ -1,34 +1,10 @@
// file: crates/ksp-logging-lib/src/domain.rs
// version: 1
// version: 2
std::thread_local! {
static CURRENT_DOMAIN: std::cell::RefCell<std::option::Option<std::string::String>> = const { std::cell::RefCell::new(std::option::Option::None) };
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
struct SpanDomain {
value: std::option::Option<std::string::String>,
}
#[derive(Default)]
struct DomainVisitor {
value: std::option::Option<std::string::String>,
}
impl tracing::field::Visit for DomainVisitor {
fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
if field.name() == "domain" {
self.value = std::option::Option::Some(value.to_string());
}
}
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
if field.name() == "domain" {
self.value = std::option::Option::Some(format!("{value:?}"));
}
}
}
pub(crate) struct DomainContextLayer;
impl DomainContextLayer {
@@ -99,6 +75,30 @@ where
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
struct SpanDomain {
value: std::option::Option<std::string::String>,
}
#[derive(Default)]
struct DomainVisitor {
value: std::option::Option<std::string::String>,
}
impl tracing::field::Visit for DomainVisitor {
fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
if field.name() == "domain" {
self.value = std::option::Option::Some(value.to_string());
}
}
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
if field.name() == "domain" {
self.value = std::option::Option::Some(format!("{value:?}"));
}
}
}
pub(crate) fn current_domain_matches(selectors: &[std::string::String]) -> bool {
if let [selector] = selectors
&& selector == "*"

View File

@@ -1,13 +1,13 @@
// file: crates/ksp-logging-lib/src/error.rs
// version: 4
// version: 5
/// Error code used when runtime logging settings are invalid.
pub const ERROR_CODE_INVALID_SETTINGS: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "invalid_settings");
/// Error code used when a global logging subscriber is already installed.
pub const ERROR_CODE_ALREADY_INITIALIZED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "already_initialized");
/// Error code used when a hot reload cannot replace the active runtime layers.
pub const ERROR_CODE_RELOAD_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "reload_failed");
/// Error code used when the rolling file output cannot be initialized.
pub const ERROR_CODE_FILE_OUTPUT_INITIALIZATION_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "file_output_initialization_failed");
/// Error code used when an application Logging runtime identity is invalid.
pub const ERROR_CODE_INVALID_RUNTIME_IDENTITY: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "invalid_runtime_identity");
/// Error code used when runtime logging settings are invalid.
pub const ERROR_CODE_INVALID_SETTINGS: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "invalid_settings");
/// Error code used when a hot reload cannot replace the active runtime layers.
pub const ERROR_CODE_RELOAD_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("logging", "reload_failed");

View File

@@ -1,5 +1,6 @@
// file: crates/ksp-logging-lib/src/lib.rs
// version: 8
// version: 9
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
@@ -69,6 +70,10 @@ pub use self::span::Span;
/// Instruments an asynchronous future with a KSP span.
pub use self::span::instrument;
pub(crate) use self::domain::current_domain_matches;
pub(crate) use self::writer::RoutedWriter;
pub(crate) use self::writer::StripAnsiWriter;
#[doc(hidden)]
/// Internal macro bridge. KSP consumers must not use this reexport directly.
pub extern crate tracing as __private_tracing;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-logging-lib/src/runtime.rs
// version: 13
// version: 14
use tracing_subscriber::Layer; // rust-rules: trait-import
use tracing_subscriber::layer::SubscriberExt; // rust-rules: trait-import
@@ -228,31 +228,6 @@ pub fn initialize_with_identity(settings: &crate::LoggingSettings, identity: &cr
return initialize_runtime(settings, std::option::Option::Some(identity.clone()));
}
fn initialize_runtime(
settings: &crate::LoggingSettings,
runtime_identity: std::option::Option<crate::LoggingRuntimeIdentity>,
) -> ksp_core_lib::Result<crate::LoggingGuard> {
return prepare_runtime_with_identity(settings, runtime_identity.as_ref()).and_then(|prepared| -> ksp_core_lib::Result<crate::LoggingGuard> {
let PreparedRuntime { layers, outputs } = prepared;
let (reload_layer, reload_handle) = tracing_subscriber::reload::Layer::new(layers);
let subscriber = tracing_subscriber::registry().with(reload_layer);
let install_result = tracing::subscriber::set_global_default(subscriber);
return match install_result {
std::result::Result::Ok(()) => std::result::Result::Ok(crate::LoggingGuard {
reload_handle,
settings: settings.clone(),
runtime_identity,
outputs,
retired_dropped_lines: crate::DroppedLines::zero(),
retired_file_dropped_lines: std::collections::HashMap::new(),
}),
std::result::Result::Err(error) => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_ALREADY_INITIALIZED, "the global KSP tracing subscriber is already installed").with_source(error),
),
};
});
}
/// Replaces the active KSP logging settings and non-blocking outputs without reinstalling the global subscriber.
///
/// New runtime layers, writers and guards are fully prepared before the reload is attempted. If validation or preparation fails, the currently active
@@ -282,6 +257,31 @@ pub fn reinitialize(guard: &mut crate::LoggingGuard, settings: &crate::LoggingSe
});
}
fn initialize_runtime(
settings: &crate::LoggingSettings,
runtime_identity: std::option::Option<crate::LoggingRuntimeIdentity>,
) -> ksp_core_lib::Result<crate::LoggingGuard> {
return prepare_runtime_with_identity(settings, runtime_identity.as_ref()).and_then(|prepared| -> ksp_core_lib::Result<crate::LoggingGuard> {
let PreparedRuntime { layers, outputs } = prepared;
let (reload_layer, reload_handle) = tracing_subscriber::reload::Layer::new(layers);
let subscriber = tracing_subscriber::registry().with(reload_layer);
let install_result = tracing::subscriber::set_global_default(subscriber);
return match install_result {
std::result::Result::Ok(()) => std::result::Result::Ok(crate::LoggingGuard {
reload_handle,
settings: settings.clone(),
runtime_identity,
outputs,
retired_dropped_lines: crate::DroppedLines::zero(),
retired_file_dropped_lines: std::collections::HashMap::new(),
}),
std::result::Result::Err(error) => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_ALREADY_INITIALIZED, "the global KSP tracing subscriber is already installed").with_source(error),
),
};
});
}
fn prepare_runtime_with_identity(
settings: &crate::LoggingSettings,
runtime_identity: std::option::Option<&crate::LoggingRuntimeIdentity>,
@@ -368,7 +368,7 @@ fn build_file_output(
);
},
};
let stripped_writer = crate::writer::StripAnsiWriter::new(appender);
let stripped_writer = crate::StripAnsiWriter::new(appender);
let thread_name = format!("ksp-logging-{}", file.output_id());
let prepared = build_non_blocking_output(stripped_writer, thread_name.as_str(), settings.span_events(), false, false, file.format(), file.filter());
let metadata = crate::RuntimeFileMetadata {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-logging-lib/src/writer.rs
// version: 3
// version: 4
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum StripAnsiState {
@@ -117,7 +117,7 @@ pub(crate) enum RoutedWriter<W> {
Disabled,
}
impl<W> std::io::Write for RoutedWriter<W>
impl<W> std::io::Write for crate::RoutedWriter<W>
where
W: std::io::Write,
{
@@ -140,17 +140,17 @@ impl<'writer, W> tracing_subscriber::fmt::MakeWriter<'writer> for RouteMakeWrite
where
W: tracing_subscriber::fmt::MakeWriter<'writer>,
{
type Writer = RoutedWriter<W::Writer>;
type Writer = crate::RoutedWriter<W::Writer>;
fn make_writer(&'writer self) -> Self::Writer {
return RoutedWriter::Enabled(tracing_subscriber::fmt::MakeWriter::make_writer(&self.inner));
return crate::RoutedWriter::Enabled(tracing_subscriber::fmt::MakeWriter::make_writer(&self.inner));
}
fn make_writer_for(&'writer self, metadata: &tracing::Metadata<'_>) -> Self::Writer {
if metadata_matches_filter(metadata, &self.filter) {
return RoutedWriter::Enabled(tracing_subscriber::fmt::MakeWriter::make_writer_for(&self.inner, metadata));
return crate::RoutedWriter::Enabled(tracing_subscriber::fmt::MakeWriter::make_writer_for(&self.inner, metadata));
}
return RoutedWriter::Disabled;
return crate::RoutedWriter::Disabled;
}
}
@@ -163,7 +163,7 @@ fn metadata_matches_filter(metadata: &tracing::Metadata<'_>, filter: &crate::Out
}) {
return false;
}
return crate::domain::current_domain_matches(filter.domains());
return crate::current_domain_matches(filter.domains());
}
fn level_is_enabled(level: &tracing::Level, filter: crate::LogFilterLevel) -> bool {