v0.1.3-pre.004

This commit is contained in:
2026-08-15 19:58:18 +02:00
parent 0629a48e97
commit 29660fd9f0
13 changed files with 1134 additions and 174 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-logging-lib/USAGE.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# Utilisation de ksp-logging-lib
@@ -21,20 +21,57 @@ ksp_logging_lib::trace!(
Les champs `domain`, `component`, `operation` et autres champs structurés sont ajoutés par le caller lorsqu'ils sont utiles ; ils ne remplacent pas le target propriétaire.
## Initialisation
## Contrat des outputs
`initialize` installe le subscriber global KSP une seule fois et retourne le `LoggingGuard` qui doit rester vivant pendant la durée du runtime :
`LoggingSettings` possède :
- le `default_filter` global de takeover KSP ;
- les `TargetFilter` globaux ;
- la politique `SpanEvents` ;
- une console déclarée optionnellement ;
- zéro, un ou plusieurs `FileSettings`.
Chaque output possède un `OutputFilter` indépendant. Son niveau, ses targets et ses domains s'appliquent **en plus** de la politique globale. `*` signifie « tous » dans la dimension concernée.
Les formats publics sont :
```text
Human
Compact
Pretty
Json
```
Une sortie fichier possède un `output_id` stable et unique dans `LoggingSettings`. Cet identifiant appartient au runtime Logging et ne doit pas être confondu avec les `file_id` utilisés par `ksp-config-lib` pour identifier ses documents.
Les fichiers persistants interdisent `ansi = true`.
## Compatibilité runtime de `pre.004`
`0.1.3-pre.004` étend d'abord le **contrat public**. Le runtime multi-sink/routing est livré séparément en `pre.005`.
Jusqu'à cette tranche suivante, `initialize`/`reinitialize` refusent explicitement toute capacité nouvellement représentée qu'ils ne savent pas encore appliquer : plusieurs fichiers actifs, format non `Human`, ANSI console ou filtre propre à un output. Ces valeurs ne sont donc jamais acceptées puis ignorées silencieusement.
Les helpers `ConsoleSettings::stdout()` et `ConsoleSettings::stderr()` construisent une console compatible avec le runtime actuel : activée, `Human`, sans ANSI et sans filtre supplémentaire par rapport au takeover global.
## Initialisation compatible avec le runtime actuel
```rust
let file = ksp_logging_lib::FileSettings::new(
"file.worker",
true,
"logs",
"worker.log",
ksp_logging_lib::FileRotation::Daily,
ksp_logging_lib::LogFormat::Human,
ksp_logging_lib::OutputFilter::unrestricted(),
);
let settings = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Info,
ksp_logging_lib::SpanEvents::NewAndClose,
std::option::Option::Some(ksp_logging_lib::ConsoleSettings::stderr()),
std::option::Option::Some(ksp_logging_lib::FileSettings::new(
"logs",
"worker.log",
ksp_logging_lib::FileRotation::Daily,
)),
std::vec![file],
);
let initialize_result = ksp_logging_lib::initialize(&settings);
@@ -44,18 +81,61 @@ let mut logging_guard = match initialize_result {
};
```
Une configuration sans console ni fichier est valide et installe une infrastructure initialement silencieuse qui pourra être activée plus tard par hot reload.
Une configuration sans output actif est valide et installe une infrastructure initialement silencieuse qui pourra être activée plus tard par hot reload.
## Construction d'un contrat multi-output
Le contrat public peut déjà représenter la future configuration Config complète :
```rust
let console = ksp_logging_lib::ConsoleSettings::new(
true,
ksp_logging_lib::ConsoleOutput::Stderr,
true,
ksp_logging_lib::LogFormat::Compact,
ksp_logging_lib::OutputFilter::new(
ksp_logging_lib::LogFilterLevel::Debug,
std::vec!["*".to_string()],
std::vec!["*".to_string()],
),
);
let error_file = ksp_logging_lib::FileSettings::new(
"file.config.error",
true,
"logs/config",
"error.jsonl",
ksp_logging_lib::FileRotation::Daily,
ksp_logging_lib::LogFormat::Json,
ksp_logging_lib::OutputFilter::new(
ksp_logging_lib::LogFilterLevel::Error,
std::vec!["ksp-config-lib".to_string()],
std::vec!["config".to_string()],
),
);
let settings = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Warn,
ksp_logging_lib::SpanEvents::NewAndClose,
std::option::Option::Some(console),
std::vec![error_file],
);
let validation = settings.validate();
```
`validate()` vérifie le contrat structurel. L'activation runtime de ce routage enrichi appartient à `pre.005`.
## Hot reload
Une nouvelle configuration peut être appliquée sans redémarrer le processus ou le worker :
Une configuration compatible avec les capacités runtime actives peut être appliquée sans redémarrer le processus ou le worker :
```rust
let debug_settings = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Info,
ksp_logging_lib::SpanEvents::NewAndClose,
std::option::Option::Some(ksp_logging_lib::ConsoleSettings::stderr()),
std::option::Option::None,
std::vec::Vec::new(),
)
.with_target_filter(ksp_logging_lib::TargetFilter::new(
"ksp-store-lib",
@@ -104,7 +184,7 @@ La future instrumentée entre/sort du span pendant ses polls et lors de son `Dro
## Lignes abandonnées
Les sorties utilisent des queues lossy afin de ne pas appliquer de backpressure au hot path. Les pertes restent observables :
Les sorties utilisent des queues lossy afin de ne pas appliquer de backpressure au hot path. Les compteurs restent encore agrégés console/fichier pendant `pre.004` ; leur généralisation par output appartient au runtime multi-sink :
```rust
let dropped = logging_guard.dropped_lines();
@@ -119,12 +199,4 @@ ksp_logging_lib::warn!(
## Instrumentation async et executor
`instrument(span, future)` accepte une `Future` standard et ne dépend d'aucun executor particulier :
```rust
let span = ksp_logging_lib::trace_span!(target: LOGGING_TARGET, "load_transactions");
let result = ksp_logging_lib::instrument(span, async_operation()).await;
```
La crate ne requiert pas Tokio en production. Tokio n'est présent qu'en `dev-dependency` pour valider la surface sur un executor réel, y compris après plusieurs suspensions et sur un runtime multi-thread. Un consumer peut donc utiliser l'executor adapté à son propre contexte sans que Logging lui en impose un.
`instrument(span, future)` accepte une `Future` standard et ne dépend d'aucun executor particulier. Tokio n'est présent qu'en `dev-dependency` pour valider la surface sur un executor réel, y compris après plusieurs suspensions et sur un runtime multi-thread.