<div align="center">
<img src="docs/image/inklog.png" alt="Inklog Logo" width="200" style="margin-bottom: 16px;">
<p>
<a href="https://github.com/Kirky-X/inklog/actions/workflows/ci.yml"><img src="https://github.com/Kirky-X/inklog/actions/workflows/ci.yml/badge.svg" alt="CI Status" style="display:inline;margin:0 4px;"></a><a href="https://crates.io/crates/inklog"><img src="https://img.shields.io/crates/v/inklog.svg" alt="Version" style="display:inline;margin:0 4px;"></a><a href="https://docs.rs/inklog"><img src="https://docs.rs/inklog/badge.svg" alt="Documentation" style="display:inline;margin:0 4px;"></a><a href="https://crates.io/crates/inklog"><img src="https://img.shields.io/crates/d/inklog.svg" alt="Downloads" style="display:inline;margin:0 4px;"></a><a href="https://github.com/Kirky-X/inklog/blob/main/LICENSE"><img src="https://img.shields.io/crates/l/inklog.svg" alt="License" style="display:inline;margin:0 4px;"></a><a href="https://www.rust-lang.org/"><img src="https://img.shields.io/badge/rust-1.94+-orange.svg" alt="Rust 1.94+" style="display:inline;margin:0 4px;"></a>
</p>
[δΈζ](./README.md) | English
<p align="center">
<strong>Enterprise-grade Rust Logging Infrastructure</strong>
</p>
<p align="center">
<a href="#features" style="color:#3B82F6;">β¨ Features</a> β’
<a href="#quick-start" style="color:#3B82F6;">π Quick Start</a> β’
<a href="#documentation" style="color:#3B82F6;">π Documentation</a> β’
<a href="#examples" style="color:#3B82F6;">π» Examples</a> β’
<a href="#contributing" style="color:#3B82F6;">π€ Contributing</a>
</p>
</div>
---
### π― A high-performance, secure, feature-rich logging infrastructure built on Tokio
Inklog provides a **comprehensive** logging solution for enterprise applications:
| β‘ High Performance | π Security First | π Multi-Target Output | π Observability |
|:---------:|:----------:|:--------------:|:--------:|
| Tokio-based async I/O | AES-256-GCM encryption | Console, file, database | Health monitoring |
| Batch writes and compression | Key memory zeroing | Auto-rotation | Metrics and tracing |
```rust
use inklog::{InklogConfig, LoggerManager};
use std::path::PathBuf;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = InklogConfig {
file_sink: Some(inklog::FileSinkConfig {
enabled: true,
path: "logs/app.log".into(),
max_size: "100MB".into(),
compress: true,
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
log::info!("Application started successfully");
log::error!("Something went wrong with error details");
Ok(())
}
```
---
## π Table of Contents
<details open style="border-radius:8px; padding:16px; border:1px solid #E2E8F0;">
<summary style="cursor:pointer; font-weight:600; color:#1E293B;">π Table of Contents (Click to expand)</summary>
- [β¨ Features](#features)
- [π Quick Start](#quick-start)
- [π¦ Installation](#installation)
- [π‘ Basic Usage](#basic-usage)
- [π§ Advanced Configuration](#advanced-configuration)
- [π¨ Feature Flags](#feature-flags)
- [π Documentation](#documentation)
- [π» Examples](#examples)
- [ποΈ Architecture](#architecture)
- [π Security](#security)
- [π§ͺ Testing](#testing)
- [π€ Contributing](#contributing)
- [π Changelog](#changelog)
- [π License](#license)
- [π Acknowledgments](#acknowledgments)
</details>
---
## <span id="features">β¨ Features</span>
<div align="center" style="margin: 24px 0;">
| π― Core Features | β‘ Enterprise Features |
|:----------:|:----------:|
| Always Available | Optional |
</div>
<table style="width:100%; border-collapse: collapse;">
<tr>
<td width="50%" style="vertical-align:top; padding: 16px; border-radius:8px; border:1px solid #E2E8F0;">
### π― Core Features (Always Available)
| Status | Feature | Description |
|:----:|------|------|
| β
| **Async I/O** | Non-blocking logging based on Tokio |
| β
| **Multi-Target Output** | Console, file, database, custom Sink |
| β
| **Structured Logging** | Integrated with tracing ecosystem |
| β
| **Custom Formatting** | Template-based log format |
| β
| **File Rotation** | Size-based and time-based rotation |
| β
| **Data Masking** | Regex-based PII redaction |
| β
| **Health Monitoring** | Sink status and metrics tracking |
| β
| **CLI Tools** | decrypt, generate, validate commands (`cli` feature) |
</td>
<td width="50%" style="vertical-align:top; padding: 16px; border-radius:8px; border:1px solid #E2E8F0;">
### β‘ Enterprise Features
| Status | Feature | Description |
|:----:|------|------|
| π | **Compression** | ZSTD, GZIP support |
| π | **Encryption** | AES-256-GCM file encryption |
| ποΈ | **Database Sink** | PostgreSQL, MySQL, SQLite, DuckDB via dbnexus |
| π | **Parquet Export** | Analytics-ready log format |
| π | **HTTP Endpoint** | Axum-based health check server (`http` feature) |
| π§ | **CLI Tools** | Log management utility commands (`cli` feature) |
</td>
</tr>
</table>
### π¦ Feature Presets
| Preset | Features | Use Case |
|------|------|----------|
| <span style="color:#166534; padding:4px 8px; border-radius:4px;">minimal</span> | No optional features | Core logging only |
| <span style="color:#1E40AF; padding:4px 8px; border-radius:4px;">standard</span> | `http`, `cli` | Standard development environment |
| <span style="color:#991B1B; padding:4px 8px; border-radius:4px;">full</span> | All default features | Production-ready logging |
---
## <span id="quick-start">π Quick Start</span>
### <span id="installation">π¦ Installation</span>
Add this to your `Cargo.toml`:
```toml
[dependencies]
inklog = "0.2"
```
Full feature set:
```toml
[dependencies]
inklog = { version = "0.2", default-features = false, features = ["http", "cli", "sqlite"] }
```
### <span id="basic-usage">π‘ Basic Usage</span>
<div align="center" style="margin: 24px 0;">
#### π¬ 5-Minute Quick Start
</div>
<table style="width:100%; border-collapse: collapse;">
<tr>
<td width="50%" style="padding: 16px; vertical-align:top;">
**Step 1: Initialize Logger**
```rust
use inklog::LoggerManager;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let _logger = LoggerManager::new().await?;
log::info!("Logger initialized");
Ok(())
}
```
</td>
<td width="50%" style="padding: 16px; vertical-align:top;">
**Step 2: Record Logs**
```rust
use inklog::LoggerManager;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let _logger = LoggerManager::new().await?;
log::trace!("Trace message");
log::debug!("Debug message");
log::info!("Info message");
log::warn!("Warning message");
log::error!("Error message");
Ok(())
}
```
</td>
</tr>
<tr>
<td width="50%" style="padding: 16px; vertical-align:top;">
**Step 3: File Logging**
```rust
use inklog::{FileSinkConfig, InklogConfig, LoggerManager};
let config = InklogConfig {
file_sink: Some(FileSinkConfig {
enabled: true,
path: "logs/app.log".into(),
max_size: "10MB".into(),
rotation_time: "daily".into(),
keep_files: 7,
compress: true,
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
</td>
<td width="50%" style="padding: 16px; vertical-align:top;">
**Step 4: Database Logging**
```rust
use inklog::{DatabaseSinkConfig, InklogConfig};
let config = InklogConfig {
database_sink: Some(DatabaseSinkConfig {
enabled: true,
url: "sqlite://logs/app.db".to_string(),
pool_size: 5,
batch_size: 100,
flush_interval_ms: 1000,
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
</td>
</tr>
</table>
### <span id="advanced-configuration">π§ Advanced Configuration</span>
#### Encrypted File Logging
```rust
use inklog::{FileSinkConfig, InklogConfig};
// Set encryption key from environment
std::env::set_var("INKLOG_ENCRYPTION_KEY", "base64-encoded-32-byte-key");
let config = InklogConfig {
file_sink: Some(FileSinkConfig {
enabled: true,
path: "logs/encrypted.log.enc".into(),
max_size: "10MB".into(),
encrypt: true,
encryption_key_env: Some("INKLOG_ENCRYPTION_KEY".into()),
compress: false, // Don't compress encrypted logs
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
#### Custom Log Format
```rust
use inklog::{InklogConfig, config::GlobalConfig};
let format_string = "[{timestamp}] [{level:>5}] {target} - {message} | {file}:{line}";
let config = InklogConfig {
global: GlobalConfig {
level: "debug".into(),
format: format_string.to_string(),
masking_enabled: true,
..Default::default()
},
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
---
## <span id="feature-flags">π¨ Feature Flags</span>
### Default Features
```toml
inklog = "0.2" # default = [] (no optional features)
```
### Optional Features
```toml
# HTTP Server
inklog = { version = "0.2", features = [
"http", # Axum HTTP health endpoint
] }
# CLI Tools
inklog = { version = "0.2", features = [
"cli", # decrypt, generate, validate commands
] }
# Database Sinks (pick one or more)
inklog = { version = "0.2", features = [
"sqlite", # SQLite database sink
"postgres", # PostgreSQL database sink
"mysql", # MySQL database sink
] }
# Compression & Performance
inklog = { version = "0.2", features = [
"compression", # ZSTD compression support
"parquet", # Parquet export support
"fast-masking", # Aho-Corasick accelerated masking
] }
```
### Feature Details
| Feature | Dependencies | Description |
|---------|-------------|-------------|
| **http** | axum | HTTP health check endpoint |
| **cli** | clap, glob | CLI tools |
| **sqlite** | dbnexus, sea-orm | SQLite database sink |
| **postgres** | dbnexus, sea-orm | PostgreSQL database sink |
| **mysql** | dbnexus, sea-orm | MySQL database sink |
| **duckdb** | dbnexus, sea-orm | DuckDB database Sink |
| **compression** | zstd | ZSTD compression for rotated log files |
| **parquet** | parquet, arrow-array, arrow-schema | Parquet export support (analytics) |
| **fast-masking** | aho-corasick | Aho-Corasick accelerated multi-pattern masking |
| **kit** | trait-kit, dbnexus, oxcache | DI toolkit integration |
---
## <span id="documentation">π Documentation</span>
<div align="center" style="margin: 24px 0;">
<table style="width:100%; max-width: 800px;">
<tr>
<td align="center" width="33%" style="padding: 16px;">
<a href="https://docs.rs/inklog" style="text-decoration:none;">
<div style="padding: 24px; border-radius:12px; transition: transform 0.2s;">
<b style="color:#1E293B;">π API Reference</b>
</div>
</a>
<br><span style="color:#64748B;">Complete API documentation</span>
</td>
<td align="center" width="33%" style="padding: 16px;">
<a href="examples/" style="text-decoration:none;">
<div style="padding: 24px; border-radius:12px; transition: transform 0.2s;">
<b style="color:#1E293B;">π» Examples</b>
</div>
</a>
<br><span style="color:#64748B;">Working code examples</span>
</td>
<td align="center" width="33%" style="padding: 16px;">
<a href="docs/" style="text-decoration:none;">
<div style="padding: 24px; border-radius:12px; transition: transform 0.2s;">
<b style="color:#1E293B;">π Guides</b>
</div>
</a>
<br><span style="color:#64748B;">In-depth guides</span>
</td>
</tr>
</table>
</div>
### π Additional Resources
| Resource | Description |
|----------|-------------|
| π [API Reference](https://docs.rs/inklog) | Complete API documentation on docs.rs |
| ποΈ [Architecture](docs/ARCHITECTURE.md) | System architecture and design decisions |
| π [Security](docs/SECURITY.md) | Security best practices and features |
| π¦ [Examples](examples/) | Runnable code examples for all features |
---
## <span id="examples">π» Examples</span>
<div align="center" style="margin: 24px 0;">
### π‘ Practical Examples
</div>
<table style="width:100%; border-collapse: collapse;">
<tr>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### π Basic Logging
```rust
use inklog::LoggerManager;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let _logger = LoggerManager::new().await?;
log::info!("Application started");
log::error!("An error occurred: {}", err);
Ok(())
}
```
</td>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### π File Logging with Rotation
```rust
use inklog::{FileSinkConfig, InklogConfig, LoggerManager};
let config = InklogConfig {
file_sink: Some(FileSinkConfig {
enabled: true,
path: "logs/app.log".into(),
max_size: "10MB".into(),
rotation_time: "daily".into(),
keep_files: 7,
compress: true,
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
</td>
</tr>
<tr>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### π Encrypted Logging
```rust
use inklog::{FileSinkConfig, InklogConfig};
std::env::set_var("INKLOG_ENCRYPTION_KEY", "base64-encoded-key");
let config = InklogConfig {
file_sink: Some(FileSinkConfig {
enabled: true,
path: "logs/encrypted.log".into(),
encrypt: true,
encryption_key_env: Some("INKLOG_ENCRYPTION_KEY".into()),
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
</td>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### ποΈ Database Logging
```rust
use inklog::{DatabaseSinkConfig, InklogConfig};
let config = InklogConfig {
database_sink: Some(DatabaseSinkConfig {
enabled: true,
url: "postgresql://localhost/logs".to_string(),
pool_size: 10,
batch_size: 100,
flush_interval_ms: 1000,
..Default::default()
}),
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
</td>
</tr>
<tr>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### π₯ HTTP Health Check Endpoint
```rust
use axum::{routing::get, Json, Router};
use inklog::LoggerManager;
use std::sync::Arc;
let logger = Arc::new(LoggerManager::new().await?);
let app = Router::new().route(
"/health",
get({
let logger = logger.clone();
|| async move { Json(logger.get_health_status()) }
}),
);
// Start HTTP server...
```
</td>
</tr>
<tr>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### π¨ Custom Format
```rust
use inklog::{InklogConfig, config::GlobalConfig};
let format_string = "[{timestamp}] [{level:>5}] {target} - {message}";
let config = InklogConfig {
global: GlobalConfig {
level: "debug".into(),
format: format_string.to_string(),
masking_enabled: true,
..Default::default()
},
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
```
</td>
<td width="50%" style="padding: 16px; border-radius:8px; border:1px solid #E2E8F0; vertical-align:top;">
#### π Data Masking
```rust
use inklog::{InklogConfig, config::GlobalConfig};
let config = InklogConfig {
global: GlobalConfig {
level: "info".into(),
format: "{timestamp} {level} {message}".to_string(),
masking_enabled: true, // Enable PII masking
..Default::default()
},
..Default::default()
};
let _logger = LoggerManager::with_config(config).await?;
// Sensitive data will be automatically masked
log::info!("User email: user@example.com");
// Output: User email: ***@***.***
```
</td>
</tr>
</table>
### π¦ Runnable Examples
The `examples/` crate provides 10 specialized examples demonstrating specific features. Run them using `cargo run --example <name>` (in the `examples/` directory or with `--package inklog-examples`).
| Example | Description | Run Command |
|---------|-------------|-------------|
| `object_pool` | Object pool reuse for frequent allocation scenarios | `cargo run --example object_pool` |
| `path_validator` | Path validation ensuring file sink target safety | `cargo run --example path_validator` |
| `log_sanitizer` | Log input sanitization preventing log injection | `cargo run --example log_sanitizer` |
| `log_adapter` | Bridge between `log` and `tracing` ecosystems | `cargo run --example log_adapter` |
| `compression` | File sink compression (ZSTD/GZIP) | `cargo run --example compression` |
| `rotation` | Size-based and time-based file rotation | `cargo run --example rotation` |
| `ring_buffered_file` | Ring-buffered file sink for high-throughput scenarios | `cargo run --example ring_buffered_file` |
| `config_file` | TOML configuration file loading | `cargo run --example config_file` |
| `metrics` | Health metrics and Prometheus export | `cargo run --example metrics` |
| `circuit_breaker` | Sink circuit breaker and fault recovery | `cargo run --example circuit_breaker` |
<div align="center" style="margin: 24px 0;">
**[π View all examples β](examples/)**
</div>
> **Note**: `inklog-examples` is now part of the workspace.
---
## <span id="architecture">ποΈ Architecture</span>
<div align="center" style="margin: 24px 0;">
### ποΈ System Architecture
</div>
```mermaid
flowchart TD
App["Application Layer<br/>(Your code using log! macros)"]
API["Inklog API Layer<br/>- LoggerManager, LoggerBuilder<br/>- Configuration management<br/>- Health monitoring"]
Sink["Sink Abstraction Layer<br/>- ConsoleSink<br/>- FileSink (rotation, compression)<br/>- DatabaseSink (batch writes)<br/>- AsyncFileSink<br/>- RingBufferedFileSink"]
Core["Core Processing Layer<br/>- Log formatting & templates<br/>- Data masking (PII redaction)<br/>- Encryption (AES-256-GCM)<br/>- Compression (ZSTD, GZIP)"]
IO["Concurrency & I/O<br/>- Tokio async runtime<br/>- Crossbeam channels<br/>- Rayon parallel processing"]
Store["Storage & External Services<br/>- Filesystem<br/>- Database (PostgreSQL, MySQL, SQLite, DuckDB)<br/>- Parquet (analytics)"]
App --> API --> Sink --> Core --> IO --> Store
```
### Layer Descriptions
**Application Layer**
- Application code uses the standard `log!` macros from the `log` crate
- Compatible with existing Rust logging patterns
**Inklog API Layer**
- `LoggerManager`: Main coordinator for all log operations
- `LoggerBuilder`: Fluent builder pattern for configuration
- Health status tracking and metrics collection
**Sink Abstraction Layer**
- Multiple Sink implementations for different output targets
- Console output for development environments
- File output with rotation, compression, and encryption
- Database output with batch writes (PostgreSQL, MySQL, SQLite, DuckDB)
- Async and buffered file sinks for high-throughput scenarios
**Core Processing Layer**
- Template-based log formatting
- Regex-based PII data masking (email, SSN, credit cards)
- AES-256-GCM encryption for sensitive logs
- Multiple compression algorithms (ZSTD, GZIP)
**Concurrency & I/O Layer**
- Tokio async runtime for non-blocking I/O
- Crossbeam channels for inter-task communication
- Rayon for CPU-intensive parallel processing
**Storage & External Services Layer**
- Local filesystem access
- Database connections via Sea-ORM
- Parquet format for analytics workflows
---
## <span id="security">π Security</span>
<div align="center" style="margin: 24px 0;">
### π‘οΈ Security Features
</div>
Inklog is built with security as the highest priority:
#### π Encryption
- **AES-256-GCM**: Military-grade encryption for log files
- **Key Management**: Environment variable-based key injection
- **Memory Zeroing**: Secure key clearing via `zeroize` crate after use
- **SHA-256 Hashing**: Integrity verification for encrypted logs
#### π Data Masking
- **Regex-based Patterns**: Automated PII detection and masking
- **Email Masking**: `user@example.com` β `***@***.***`
- **SSN Masking**: Credit card and social security number masking
- **Custom Patterns**: Configurable regex patterns for sensitive data
#### π Secure Key Handling
```rust
// Set encryption key securely from environment
std::env::set_var("INKLOG_ENCRYPTION_KEY", "base64-encoded-32-byte-key");
// Key is automatically zeroized after use
// Never hardcode keys in your application
```
#### π‘οΈ Security Best Practices
- **No Hardcoded Keys**: Keys loaded from environment variables
- **Least Privilege**: Only necessary file/database access
- **Audit Logging**: Debug feature for security audit trails
- **Compliance Ready**: Supporting GDPR, HIPAA, PCI-DSS logging requirements
---
## <span id="testing">π§ͺ Testing</span>
<div align="center" style="margin: 24px 0;">
### π― Run Tests
</div>
```bash
# Run all tests with default features
cargo test --all-features
# Run tests with specific features
cargo test --features "http,cli"
# Run tests in release mode
cargo test --release
# Run benchmarks
cargo bench
```
### Test Coverage
Inklog targets **95%+ code coverage**:
```bash
# Generate coverage report
cargo tarpaulin --out Html --all-features
```
### Code Checking and Formatting
```bash
# Format code
cargo fmt --all
# Check formatting without changes
cargo fmt --all -- --check
# Run Clippy (warnings as errors)
cargo clippy --all-targets --all-features -- -D warnings
```
### Security Audit
```bash
# Run cargo deny for security checks
cargo deny check
# Check for advisories
cargo deny check advisories
# Check for banned licenses
cargo deny check bans
```
### Dependency Injection Testing
Inklog provides Mock implementations for unit testing without external dependencies:
```rust
use inklog::{LoggerManager, LoggerDependencies};
use inklog::{MockCache, MockConfig, MockDatabaseAdapter};
use std::sync::Arc;
#[tokio::test]
async fn test_with_mocks() -> Result<(), Box<dyn std::error::Error>> {
// Create Mock dependencies
let deps = LoggerDependencies {
cache: Some(Arc::new(MockCache::new())),
config: Some(Arc::new(MockConfig::new())),
#[cfg(any(feature = "sqlite", feature = "postgres", feature = "mysql"))]
database: Some(Arc::new(MockDatabaseAdapter::new())),
..Default::default()
};
// Inject dependencies to create logger
let logger = LoggerManager::with_dependencies(deps).await?;
// Test logging...
log::info!("Test message");
Ok(())
}
```
**Mock Implementations**:
- **MockCache**: In-memory cache backed by HashMap, supports latency simulation
- **MockConfig**: Runtime-modifiable configuration
- **MockDatabaseAdapter**: In-memory log storage with health status control
See [User Guide](docs/USER_GUIDE.md#using-mock-implementations-for-testing) for detailed usage.
### Integration Testing
```bash
# Run integration tests
cargo test --test '*'
# Run with Docker services (PostgreSQL, MySQL)
docker-compose up -d
cargo test --all-features
docker-compose down
```
---
## <span id="contributing">π€ Contributing</span>
<div align="center" style="margin: 24px 0;">
Contributions are welcome! See [CONTRIBUTING.md](docs/CONTRIBUTING.md)
</div>
### Development Setup
```bash
# Clone repository
git clone https://github.com/Kirky-X/inklog.git
cd inklog
# Install pre-commit hooks (if available)
./scripts/install-pre-commit.sh
# Run tests
cargo test --all-features
# Run linter
cargo clippy --all-features
# Format code
cargo fmt --all
```
### Pull Request Process
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes
4. Run tests and ensure all pass (`cargo test --all-features`)
5. Run clippy and fix warnings (`cargo clippy --all-features`)
6. Commit your changes (`git commit -m 'Add amazing feature'`)
7. Push to the branch (`git push origin feature/amazing-feature`)
8. Open a Pull Request
### Code Style
- Follow Rust naming conventions (snake_case for variables, PascalCase for types)
- Use `thiserror` for error types
- Use `anyhow` for error context
- Add doc comments for all public APIs
- Run `cargo fmt` before committing
---
## <span id="changelog">π Changelog</span>
See [CHANGELOG.md](docs/CHANGELOG.md)
---
## <span id="license">π License</span>
<div align="center" style="margin: 24px 0;">
This project is licensed under **MIT**:
[](LICENSE)
</div>
MIT License, Copyright (c) 2026 Kirky.X
---
## <span id="acknowledgments">π Acknowledgments</span>
<div align="center" style="margin: 24px 0;">
### π Built on Excellent Tools
</div>
Inklog would not be possible without these outstanding projects:
- [tracing](https://github.com/tokio-rs/tracing) - The foundation of Rust structured logging
- [tokio](https://tokio.rs/) - Rust's asynchronous runtime
- [Sea-ORM](https://www.sea-ql.org/SeaORM/) - Async ORM for database operations
- [axum](https://github.com/tokio-rs/axum) - Web framework for HTTP endpoints
- [serde](https://serde.rs/) - Serialization framework
- The entire Rust ecosystem for amazing tools and libraries
---
## π Support
<div align="center" style="margin: 24px 0;">
<table style="width:100%; max-width: 600px;">
<tr>
<td align="center" width="33%">
<a href="https://github.com/Kirky-X/inklog/issues">
<div style="padding: 16px; border-radius:8px;">
<b style="color:#991B1B;">π Issues</b>
</div>
</a>
<br><span style="color:#64748B;">Report bugs and issues</span>
</td>
<td align="center" width="33%">
<a href="https://github.com/Kirky-X/inklog/discussions">
<div style="padding: 16px; border-radius:8px;">
<b style="color:#1E40AF;">π¬ Discussions</b>
</div>
</a>
<br><span style="color:#64748B;">Ask questions and share ideas</span>
</td>
<td align="center" width="33%">
<a href="https://github.com/Kirky-X/inklog">
<div style="padding: 16px; border-radius:8px;">
<b style="color:#1E293B;">π GitHub</b>
</div>
</a>
<br><span style="color:#64748B;">View source code</span>
</td>
</tr>
</table>
</div>
---
## β Star History
<div align="center">
[](https://star-history.com/#Kirky-X/inklog&Date)
</div>
---
<div align="center" style="margin: 32px 0; padding: 24px; border-radius: 12px;">
### π Support This Project
If you find this project useful, please consider giving it a βοΈ!
**Built with β€οΈ by the Inklog Team**
---
**[β¬ Back to Top](#inklog)**
---
<sub>Β© 2026 Inklog Project. All rights reserved.</sub>
</div>