kerf 0.1.2

Simple tokio-based trace event collector
Documentation
# Kerf API Reference

## Quick Start

```rust
use kerf::{Kerf, Match, Config};

// Basic setup
let kerf = Kerf::init_default()?;
kerf.set_stdout_callback()?;

// Advanced setup
let config = Config::empty()
    .with_tab("errors", Match::error().all_modules())
    .with_tab("api", Match::info().module_pattern("api_*"));
let kerf = Kerf::init(config)?;
```

## Core Types

### Kerf
Main tracer instance.

```rust
// Initialization
Kerf::init(config: Config) -> Result<Kerf>
Kerf::init_default() -> Result<Kerf>

// Callbacks
kerf.set_callback(callback: impl Fn(ArcEvent, &[&str]) + Send + Sync + 'static) -> Result<()>
kerf.set_silenced_callback(callback: impl Fn(ArcEvent, &[&str]) + Send + Sync + 'static) -> Result<()>
kerf.set_dropped_callback(callback: impl Fn(ArcEvent) + Send + Sync + 'static) -> Result<()>
kerf.set_stdout_callback() -> Result<()>

// Tab management
kerf.add_tab(name: &str, matcher_set: impl IntoMatcherSet) -> Result<()>
kerf.update_tab(name: &str, matcher_set: impl IntoMatcherSet) -> Result<()>
kerf.remove_tab(name: &str) -> Result<()>

// Statistics
kerf.get_stats() -> Result<oneshot::Receiver<Option<StatsSnapshot>>>
kerf.clear_stats() -> Result<()>
```

### KerfBuilder
Fluent API for per-tab callbacks.

```rust
let kerf = Kerf::init(config)?
    .with_tab_callback("console", |event| println!("{}", event))
    .with_tab_callback("errors", |event| eprintln!("{}", event.colored()))
    .build().await?;
```

### Config
Configuration builder.

```rust
Config::empty() -> Config
Config::default() -> Config

config.with_tab(name: &str, matcher_set: impl IntoMatcherSet) -> Config
config.with_stats(stats_config: StatsConfig) -> Config
```

### Match
Pattern matcher builder.

```rust
// Level constructors
Match::trace() -> Match
Match::debug() -> Match
Match::info() -> Match
Match::warn() -> Match
Match::error() -> Match

// Include/exclude
match.include() -> Match
match.exclude() -> Match

// Pattern methods
match.module_pattern(pattern: &str) -> Match
match.module_patterns(patterns: Vec<&str>) -> Match
match.file_pattern(pattern: &str) -> Match
match.file_patterns(patterns: Vec<&str>) -> Match
match.span_pattern(pattern: &str) -> Match
match.span_patterns(patterns: Vec<&str>) -> Match
match.target_pattern(pattern: &str) -> Match
match.target_patterns(patterns: Vec<&str>) -> Match

// Shortcuts
match.all_modules() -> Match
```

### Event
Trace event data.

```rust
event.id: u64
event.timestamp: DateTime<Local>
event.level: Level
event.target: String
event.name: String
event.module_path: Option<String>
event.file: Option<String>
event.line: Option<u32>
event.message: String
event.fields: HashMap<String, String>
event.span_name: Option<String>
event.span_hierarchy: Option<String>

// Formatting
event.format() -> String
event.format_with_file() -> String
event.format_with_fields() -> String
event.colored() -> String
```

## Pattern Matching

### Glob Patterns
- `*` - matches everything
- `prefix*` - matches strings starting with "prefix"
- `*suffix` - matches strings ending with "suffix"
- `*substring*` - matches strings containing "substring"
- `exact` - matches exactly "exact"

### Complex Patterns
- `prefix*suffix` - regex fallback for complex patterns
- `test_[0-9]+` - regex patterns supported

### Performance
- Simple patterns use fast string operations
- Complex patterns use cached regex compilation
- Patterns are precompiled when Match objects are created

## Usage Patterns

### Basic Filtering
```rust
let config = Config::empty()
    .with_tab("errors", Match::error().all_modules())
    .with_tab("debug", Match::debug().module_pattern("my_app::*"));
```

### Exclusion Filters
```rust
let config = Config::empty()
    .with_tab("main", Match::info().all_modules())
    .with_tab("silence", Match::info().exclude().module_pattern("noisy::*"));
```

### Multiple Patterns
```rust
let matcher = Match::info()
    .module_patterns(vec!["api::*", "web::*"])
    .file_pattern("*.rs")
    .span_pattern("request_*");
```

### Per-Tab Callbacks
```rust
let kerf = Kerf::init(config)?
    .with_tab_callback("console", |event| {
        println!("[{}] {}", event.level, event.message);
    })
    .with_tab_callback("file", |event| {
        write_to_file(&event);
    })
    .build().await?;
```

### Global + Per-Tab Callbacks
```rust
// Per-tab callbacks handle specific routing
let kerf = Kerf::init(config)?
    .with_tab_callback("errors", |event| write_error_log(&event))
    .build().await?;

// Global callback for cross-cutting concerns
kerf.set_callback(|event, tabs| {
    update_metrics(&event, tabs);
})?;
```

### Statistics
```rust
let config = Config::empty()
    .with_stats(StatsConfig::default());

let kerf = Kerf::init(config)?;

// Get stats
let stats_rx = kerf.get_stats()?;
let stats = stats_rx.await??;
println!("Captured: {}", stats.total_counters.get(&(EventType::Captured, Level::INFO)));
```

## Event Types

### EventType
```rust
EventType::Captured  // Matched include filters
EventType::Silenced  // Matched exclude filters  
EventType::Dropped   // No filters matched
```

### Level Hierarchy
- `ERROR` - only ERROR events
- `WARN` - ERROR + WARN events
- `INFO` - ERROR + WARN + INFO events
- `DEBUG` - ERROR + WARN + INFO + DEBUG events
- `TRACE` - all events

## Statistics

### StatsConfig
```rust
StatsConfig::default() -> StatsConfig
StatsConfig::disabled() -> StatsConfig

config.max_locations: usize     // default: 1000
config.max_modules: usize       // default: 100
config.max_raw_entries: usize   // default: 10000
```

### StatsSnapshot
```rust
snapshot.total_counters: HashMap<(EventType, Level), u64>
snapshot.location_stats: HashMap<Location, LocationStats>
snapshot.module_stats: HashMap<String, ModuleStats>
snapshot.raw_stats: Vec<StatEntry>
```

## Error Handling

All async operations return `Result<T>`. Common errors:
- Tab not found
- Invalid configuration
- Channel communication failures

## Thread Safety

- All types are `Send + Sync`
- Callbacks must be `Send + Sync + 'static`
- Statistics use atomic counters
- Event processing is lock-free