lazylog_framework/lib.rs
1//! # lazylog-framework
2//!
3//! A powerful, extensible framework for building terminal-based log viewers with vim-like
4//! navigation and real-time monitoring capabilities.
5//!
6//! ## Overview
7//!
8//! lazylog-framework provides a provider-based architecture that separates log acquisition
9//! from display. You implement the [`LogProvider`] and [`LogParser`] traits to define your
10//! log source and formatting, and the framework handles all the TUI rendering, navigation,
11//! filtering, and user interaction.
12//!
13//! ## Core Concepts
14//!
15//! ### Provider Pattern
16//!
17//! The framework uses a two-trait system:
18//!
19//! - **[`LogProvider`]**: Acquires raw log data from any source (files, sockets, APIs, etc.)
20//! - **[`LogParser`]**: Parses raw strings into [`LogItem`]s and formats them for display
21//!
22//! This separation allows you to:
23//! - Reuse providers with different parsers
24//! - Reuse parsers with different providers
25//! - Easily test parsing logic independently
26//!
27//! ### Ring Buffer
28//!
29//! Logs flow through a lock-free ring buffer with configurable capacity (default: 16K items).
30//! When full, old logs are automatically discarded to prevent unbounded memory growth.
31//!
32//! ### Non-blocking Architecture
33//!
34//! The provider runs in a background thread, polling at configurable intervals (default: 100ms).
35//! The main thread handles UI rendering and user input, keeping the interface responsive.
36//!
37//! ## Quick Start
38//!
39//! ```rust,no_run
40//! use lazylog_framework::{LogProvider, LogParser, LogItem, start_with_provider};
41//! use anyhow::Result;
42//! use std::sync::Arc;
43//!
44//! // 1. implement LogProvider for your log source
45//! struct MyLogProvider {
46//! // your state here (file handle, socket, etc.)
47//! }
48//!
49//! impl LogProvider for MyLogProvider {
50//! fn start(&mut self) -> Result<()> {
51//! // setup resources (open files, connect to streams, etc.)
52//! Ok(())
53//! }
54//!
55//! fn stop(&mut self) -> Result<()> {
56//! // cleanup resources
57//! Ok(())
58//! }
59//!
60//! fn poll_logs(&mut self) -> Result<Vec<String>> {
61//! // return raw log strings since last poll (non-blocking)
62//! Ok(vec!["2025-01-15 10:30:00 INFO Application started".to_string()])
63//! }
64//! }
65//!
66//! // 2. implement LogParser for your log format
67//! struct MyLogParser;
68//!
69//! impl LogParser for MyLogParser {
70//! fn parse(&self, raw_log: &str) -> Option<LogItem> {
71//! // parse raw string into LogItem
72//! // return None to filter out unwanted logs
73//! Some(LogItem::new(
74//! raw_log.to_string(), // parsed content
75//! raw_log.to_string(), // original raw string
76//! ))
77//! }
78//!
79//! fn format_preview(&self, item: &LogItem, detail_level: u8) -> String {
80//! // format log for display at given detail level (0-4)
81//! match detail_level {
82//! 0 => item.content.clone(),
83//! _ => format!("[{}] {}", item.time, item.content),
84//! }
85//! }
86//!
87//! fn get_searchable_text(&self, item: &LogItem, _detail_level: u8) -> String {
88//! // return text that should be searchable at this detail level
89//! item.content.clone()
90//! }
91//! }
92//!
93//! // 3. run the application
94//! fn main() -> Result<()> {
95//! use ratatui::{Terminal, backend::CrosstermBackend};
96//! use std::io;
97//!
98//! let mut terminal = Terminal::new(CrosstermBackend::new(io::stdout()))?;
99//! let provider = MyLogProvider { /* ... */ };
100//! let parser = Arc::new(MyLogParser);
101//!
102//! lazylog_framework::start_with_provider(&mut terminal, provider, parser)?;
103//! Ok(())
104//! }
105//! ```
106//!
107//! ## Advanced Configuration
108//!
109//! Use [`AppDesc`] to customize behavior:
110//!
111//! ```rust,no_run
112//! use lazylog_framework::{AppDesc, start_with_desc};
113//! use std::time::Duration;
114//! use std::sync::Arc;
115//! # use lazylog_framework::{LogProvider, LogParser, LogItem};
116//! # use anyhow::Result;
117//! # struct MyProvider;
118//! # impl LogProvider for MyProvider {
119//! # fn start(&mut self) -> Result<()> { Ok(()) }
120//! # fn stop(&mut self) -> Result<()> { Ok(()) }
121//! # fn poll_logs(&mut self) -> Result<Vec<String>> { Ok(vec![]) }
122//! # }
123//! # struct MyParser;
124//! # impl LogParser for MyParser {
125//! # fn parse(&self, _: &str) -> Option<LogItem> { None }
126//! # fn format_preview(&self, _: &LogItem, _: u8) -> String { String::new() }
127//! # fn get_searchable_text(&self, _: &LogItem, _: u8) -> String { String::new() }
128//! # }
129//! # fn main() -> Result<()> {
130//! # use ratatui::{Terminal, backend::CrosstermBackend};
131//! # use std::io;
132//! # let mut terminal = Terminal::new(CrosstermBackend::new(io::stdout()))?;
133//!
134//! let parser = Arc::new(MyParser);
135//! let mut desc = AppDesc::new(parser.clone());
136//! desc.poll_interval = Duration::from_millis(50); // poll every 50ms
137//! desc.ring_buffer_size = 32768; // 32K log capacity
138//! desc.show_debug_logs = true; // show debug panel
139//!
140//! let provider = MyProvider;
141//! start_with_desc(&mut terminal, provider, desc)?;
142//! # Ok(())
143//! # }
144//! ```
145//!
146//! ## Built-in Features
147//!
148//! The framework provides a full-featured TUI out of the box:
149//!
150//! ### Vim-like Navigation
151//! - `j`/`k`, `↓`/`↑`: move up/down
152//! - `gg`: jump to top, `G`: jump to bottom
153//! - `Ctrl+d`/`Ctrl+u`: page down/up
154//! - `a`: toggle autoscroll (like `tail -f`)
155//!
156//! ### Filtering
157//! - `/`: enter filter mode
158//! - Type regex pattern to filter logs in real-time
159//! - `Esc`: clear filter
160//!
161//! ### Detail Levels
162//! - `+`/`-`: increase/decrease detail level (0-4)
163//! - Allows progressive disclosure of information
164//! - Parser controls what each level shows
165//!
166//! ### Other Features
167//! - `y`: yank (copy) selected log to clipboard
168//! - `w`: toggle line wrapping
169//! - `?`: show help popup
170//! - Mouse support: click and scroll
171//!
172//! ## Performance
173//!
174//! - **Memory-efficient**: Ring buffer prevents unbounded growth
175//! - **Lock-free**: Uses ringbuf crate for zero-allocation producer/consumer
176//! - **Lazy rendering**: Only visible logs are formatted and drawn
177//! - **Parallel filtering**: Uses rayon for fast regex filtering on large log sets
178//!
179//! ## Use Cases
180//!
181//! - **File tailing**: Monitor local log files in real-time
182//! - **Container logs**: Stream from Docker/Kubernetes
183//! - **Network logs**: Receive syslog over UDP/TCP
184//! - **Database logs**: Query and stream from databases
185//! - **API logs**: Fetch from logging services (e.g., Elasticsearch)
186//! - **Device logs**: Monitor mobile devices (iOS, Android)
187//! - **Multi-source aggregation**: Combine multiple log sources
188//!
189//! ## Examples
190//!
191//! See the `examples/` directory for complete implementations:
192//! - `simple.rs`: Minimal provider that generates dummy logs
193//! - `file.rs`: File-based provider with real-time tailing
194//! - `structured.rs`: JSON log parsing with detail levels
195
196pub mod provider;
197
198// re-export commonly used types
199pub use provider::{
200 LogDetailLevel, LogItem, LogParser, LogProvider, decrement_detail_level,
201 increment_detail_level, spawn_provider_thread,
202};
203
204// internal modules (not part of public API but needed for app)
205pub(crate) mod app;
206pub(crate) mod app_block;
207pub(crate) mod content_line_maker;
208pub(crate) mod filter;
209pub(crate) mod log_list;
210pub(crate) mod log_parser;
211pub(crate) mod status_bar;
212pub(crate) mod theme;
213pub(crate) mod ui_logger;
214
215// public API for running the application
216pub use app::{AppDesc, start_with_desc, start_with_provider};