inklog

Crates.ioinklog
lib.rsinklog
version0.1.0
created_at2026-01-18 06:12:44.580292+00
updated_at2026-01-18 06:12:44.580292+00
descriptionEnterprise-grade Rust logging infrastructure
homepage
repositoryhttps://github.com/Kirky-X/inklog
max_upload_size
id2051880
size1,034,347
Kirky (Kirky-X)

documentation

README

Inklog Logo

CI Status Version Documentation Downloads License Rust 1.75+

Enterprise-grade Rust Logging Infrastructure

โœจ Features โ€ข ๐Ÿš€ Quick Start โ€ข ๐Ÿ“š Documentation โ€ข ๐Ÿ’ป Examples โ€ข ๐Ÿค Contributing


๐ŸŽฏ A high-performance, secure, and feature-rich logging infrastructure built on Tokio

Inklog provides a comprehensive logging solution for enterprise applications:

โšก High Performance ๐Ÿ”’ Security First ๐ŸŒ Multi-Target ๐Ÿ“Š Observability
Async I/O with Tokio AES-256-GCM encryption Console, File, DB, S3 Health monitoring
Batch writes & compression Zeroized secret memory Automatic rotation Metrics & tracing
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

๐Ÿ“‘ Table of Contents (Click to expand)

โœจ Features

๐ŸŽฏ Core Features โšก Enterprise Features
Always Available Optional

๐ŸŽฏ Core Features (Always Available)

Status Feature Description
โœ… Async I/O Tokio-powered non-blocking logging
โœ… Multi-Target Output Console, file, database, custom sinks
โœ… Structured Logging tracing ecosystem integration
โœ… 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

โšก Enterprise Features

Status Feature Description
๐Ÿ” Compression ZSTD, GZIP, Brotli, LZ4 support (zstd, flate2, etc.)
๐Ÿ”’ Encryption AES-256-GCM file encryption (aes-gcm)
๐Ÿ—„๏ธ Database Sink PostgreSQL, MySQL, SQLite via Sea-ORM
โ˜๏ธ S3 Archive Cloud log archival with AWS SDK S3 (aws feature)
๐Ÿ“Š Parquet Export Analytics-ready log format (parquet feature)
๐ŸŒ HTTP Endpoint Axum-based health check server (http feature)
๐Ÿ“… Scheduled Tasks Cron-based archive scheduling
๐Ÿ”ง CLI Tools Utility commands for log management (cli feature)
๐Ÿ“ TOML Config External configuration support (confers feature)

๐Ÿ“ฆ Feature Presets

Preset Features Use Case
minimal No optional features Core logging only
standard http, cli Standard development setup
full All default features Production-ready logging

๐Ÿš€ Quick Start

๐Ÿ“ฆ Installation

Add this to your Cargo.toml:

[dependencies]
inklog = "0.1"

For full feature set:

[dependencies]
inklog = { version = "0.1", features = ["default"] }

๐Ÿ’ก Basic Usage

๐ŸŽฌ 5-Minute Quick Start

Step 1: Initialize Logger

use inklog::LoggerManager;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let _logger = LoggerManager::new().await?;

    log::info!("Logger initialized");
    Ok(())
}

Step 2: Log Messages

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(())
}

Step 3: File Logging

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?;

Step 4: Database Logging

use inklog::{DatabaseSinkConfig, InklogConfig, config::DatabaseDriver};

let config = InklogConfig {
    database_sink: Some(DatabaseSinkConfig {
        enabled: true,
        driver: DatabaseDriver::SQLite,
        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?;

๐Ÿ”ง Advanced Configuration

Encrypted File Logging

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?;

S3 Cloud Archiving

use inklog::{InklogConfig, S3ArchiveConfig};

let config = InklogConfig {
    s3_archive: Some(S3ArchiveConfig {
        enabled: true,
        bucket: "my-log-bucket".to_string(),
        region: "us-west-2".to_string(),
        archive_interval_days: 7,
        local_retention_days: 30,
        prefix: "logs/".to_string(),
        compression: inklog::archive::CompressionType::Zstd,
        ..Default::default()
    }),
    ..Default::default()
};

let manager = LoggerManager::with_config(config).await?;
manager.start_archive_service().await?;

Custom Log Format

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?;

๐ŸŽจ Feature Flags

Default Features

inklog = "0.1"  # Includes: aws, http, cli

Optional Features

# Cloud & Storage
inklog = { version = "0.1", features = [
    "aws",        # AWS S3 archive support
] }

# HTTP Server
inklog = { version = "0.1", features = [
    "http",       # Axum HTTP health endpoint
] }

# CLI Tools
inklog = { version = "0.1", features = [
    "cli",        # decrypt, generate, validate commands
] }

# Configuration
inklog = { version = "0.1", features = [
    "confers",    # TOML configuration support
] }

# Development
inklog = { version = "0.1", features = [
    "test-local", # Local testing mode
    "debug",     # Additional security audit logging
] }

Feature Details

Feature Dependencies Description
aws aws-sdk-s3, aws-config, aws-types AWS S3 cloud archive
http axum HTTP health check endpoint
cli clap, glob, toml Command-line utilities
confers confers, toml External TOML configuration support
test-local - Local testing mode
debug - Security audit logging

๐Ÿ“š Documentation

๐Ÿ“˜ API Reference

Complete API docs
๐Ÿ’ป Examples

Working code examples
๐Ÿ“– Guides

In-depth guides

๐Ÿ“– Additional Resources

Resource Description
๐Ÿ“˜ API Reference Complete API documentation on docs.rs
๐Ÿ—๏ธ Architecture System architecture and design decisions
๐Ÿ”’ Security Security best practices and features
๐Ÿ“ฆ Examples Working code examples for all features

๐Ÿ’ป Examples

๐Ÿ’ก Real-world Examples

๐Ÿ“ Basic Logging

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(())
}

๐Ÿ“ File Logging with Rotation

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?;

๐Ÿ”’ Encrypted Logging

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?;

๐Ÿ—„๏ธ Database Logging

use inklog::{DatabaseSinkConfig, InklogConfig, config::DatabaseDriver};

let config = InklogConfig {
    database_sink: Some(DatabaseSinkConfig {
        enabled: true,
        driver: DatabaseDriver::PostgreSQL,
        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?;

โ˜๏ธ S3 Cloud Archive

use inklog::{InklogConfig, S3ArchiveConfig};

let config = InklogConfig {
    s3_archive: Some(S3ArchiveConfig {
        enabled: true,
        bucket: "my-log-bucket".to_string(),
        region: "us-west-2".to_string(),
        archive_interval_days: 7,
        local_retention_days: 30,
        prefix: "logs/".to_string(),
        compression: inklog::archive::CompressionType::Zstd,
        ..Default::default()
    }),
    ..Default::default()
};

let manager = LoggerManager::with_config(config).await?;
manager.start_archive_service().await?;

๐Ÿฅ HTTP Health Endpoint

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...

๐ŸŽจ Custom Format

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?;

๐Ÿ” Data Masking

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: ***@***.***

๐Ÿ“‚ View all examples โ†’


๐Ÿ—๏ธ Architecture

๐Ÿ—๏ธ System Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚           Application Layer                    โ”‚
โ”‚  (Your code using log! macros)             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                 โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Inklog API Layer                  โ”‚
โ”‚  - LoggerManager, LoggerBuilder          โ”‚
โ”‚  - Configuration management               โ”‚
โ”‚  - Health monitoring                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                 โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Sink Abstraction Layer             โ”‚
โ”‚  - ConsoleSink                          โ”‚
โ”‚  - FileSink (rotation, compression)     โ”‚
โ”‚  - DatabaseSink (batch writes)           โ”‚
โ”‚  - AsyncFileSink                        โ”‚
โ”‚  - RingBufferedFileSink                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                 โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Core Processing Layer              โ”‚
โ”‚  - Log formatting & templates            โ”‚
โ”‚  - Data masking (PII redaction)         โ”‚
โ”‚  - Encryption (AES-256-GCM)             โ”‚
โ”‚  - Compression (ZSTD, GZIP, Brotli)    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                 โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Concurrency & I/O                 โ”‚
โ”‚  - Tokio async runtime                  โ”‚
โ”‚  - Crossbeam channels                  โ”‚
โ”‚  - Rayon parallel processing            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                 โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚         Storage & External Services        โ”‚
โ”‚  - Filesystem                          โ”‚
โ”‚  - Database (PostgreSQL, MySQL, SQLite)  โ”‚
โ”‚  - AWS S3 (cloud archive)              โ”‚
โ”‚  - Parquet (analytics)                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Layer-by-Layer Explanation

Application Layer

  • Application code uses standard log! macros from the log crate
  • Compatible with existing Rust logging patterns

Inklog API Layer

  • LoggerManager: Main orchestrator for all logging 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
  • File output with rotation, compression, and encryption
  • Database output with batch writes (PostgreSQL, MySQL, SQLite)
  • Async and buffered file sinks for high-throughput scenarios

Core Processing Layer

  • Template-based log formatting
  • Regex-based PII data masking (emails, SSNs, credit cards)
  • AES-256-GCM encryption for sensitive logs
  • Multiple compression algorithms (ZSTD, GZIP, Brotli, LZ4)

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 connectivity via Sea-ORM
  • AWS S3 integration for cloud archival
  • Parquet format for analytics workflows

๐Ÿ”’ Security

๐Ÿ›ก๏ธ Security Features

Inklog is built with security as a top priority:

๐Ÿ”’ Encryption

  • AES-256-GCM: Military-grade encryption for log files
  • Key Management: Environment variable-based key injection
  • Zeroized Memory: Secrets are securely cleared after use via zeroize crate
  • SHA-256 Hashing: Integrity verification for encrypted logs

๐ŸŽญ Data Masking

  • Regex-Based Patterns: Automatic PII detection and redaction
  • Email Masking: user@example.com โ†’ ***@***.***
  • SSN Masking: Credit card and social security number redaction
  • Custom Patterns: Configurable regex patterns for sensitive data

๐Ÿ” Secure Key Handling

// 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 secrets: Keys loaded from environment variables
  • Minimal privileged operations: Only necessary file/database access
  • Audit logging: Debug feature for security audit trails
  • Compliance-ready: Supports GDPR, HIPAA, PCI-DSS logging requirements

๐Ÿงช Testing

๐ŸŽฏ Run Tests

# Run all tests with default features
cargo test --all-features

# Run tests with specific features
cargo test --features "aws,http,cli"

# Run tests in release mode
cargo test --release

# Run benchmarks
cargo bench

Test Coverage

Inklog targets 95%+ code coverage:

# Generate coverage report
cargo tarpaulin --out Html --all-features

Linting and Formatting

# 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

# Run cargo deny for security checks
cargo deny check

# Check for advisories
cargo deny check advisories

# Check for banned licenses
cargo deny check bans

Integration Tests

# Run integration tests
cargo test --test '*'

# Run with Docker services (PostgreSQL, MySQL)
docker-compose up -d
cargo test --all-features
docker-compose down

๐Ÿค Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Development Setup

# 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 contexts
  • Add doc comments to all public APIs
  • Run cargo fmt before committing

๐Ÿ“„ License

This project is dual-licensed under MIT / Apache-2.0:

License: MIT License: Apache-2.0


๐Ÿ™ Acknowledgments

๐ŸŒŸ Built on Excellent Tools

Inklog wouldn't be possible without these amazing projects:

  • tracing - The foundation of Rust structured logging
  • tokio - Async runtime for Rust
  • Sea-ORM - Async ORM for database operations
  • AWS SDK for Rust - AWS S3 integration
  • axum - Web framework for HTTP endpoints
  • serde - Serialization framework
  • The entire Rust ecosystem for amazing tools and libraries

๐Ÿ“ž Support

๐Ÿ“‹ Issues

Report bugs and issues
๐Ÿ’ฌ Discussions

Ask questions and share ideas
๐Ÿ™ GitHub

View source code

โญ Star History

Star History Chart


๐Ÿ’ Support This Project

If you find this project useful, please consider giving it a โญ๏ธ!

Built with โค๏ธ by Inklog Team


โฌ† Back to Top


ยฉ 2026 Inklog Project. All rights reserved.

Commit count: 48

cargo fmt