inklog 0.1.0

Enterprise-grade Rust logging infrastructure
Documentation
// Copyright (c) 2026 Kirky.X
//
// Licensed under the MIT License
// See LICENSE file in the project root for full license information.

use anyhow::{Context, Result};
use std::fs::File;
use std::io::Write;
use std::path::Path;

pub fn generate_config(output_path: &Path, config_type: &str) -> Result<()> {
    let config_content = match config_type {
        "minimal" => generate_minimal_config(),
        "full" => generate_full_config(),
        "database" => generate_database_config(),
        "file" => generate_file_config(),
        _ => return Err(anyhow::anyhow!("Unknown config type: {}", config_type)),
    };

    let output_file = if output_path.is_dir() {
        output_path.join("inklog_config.toml")
    } else {
        output_path.to_path_buf()
    };

    let mut file = File::create(&output_file)
        .with_context(|| format!("Failed to create config file: {}", output_file.display()))?;

    file.write_all(config_content.as_bytes())
        .with_context(|| "Failed to write config content")?;

    println!("Generated config file: {}", output_file.display());
    Ok(())
}

fn generate_minimal_config() -> String {
    r#"# inklog minimal configuration
[global]
level = "info"
format = "{timestamp} [{level}] {target} - {message}"

[console_sink]
enabled = true
colored = true
"#
    .to_string()
}

fn generate_full_config() -> String {
    r#"# inklog configuration
# Generated by inklog-cli generate full

[global]
level = "info"
format = "{timestamp} [{level}] {target} - {message}"

[console_sink]
enabled = true
colored = true
stderr_levels = ["error", "warn"]

[file_sink]
enabled = true
path = "logs/app.log"
max_size = "100MB"
rotation_time = "daily"
keep_files = 30
compress = true
compression_level = 3
encrypt = false
encryption_key_env = "INKLOG_ENCRYPTION_KEY"
retention_days = 30
max_total_size = "1GB"
cleanup_interval_minutes = 60

[performance]
channel_capacity = 10000
worker_threads = 3

[http_server]
enabled = false
host = "127.0.0.1"
port = 9090
metrics_path = "/metrics"
health_path = "/health"

# Database sink (optional)
# [database_sink]
# enabled = false
# driver = "postgres"
# url = "postgres://localhost/logs"
# pool_size = 10
# batch_size = 100
# flush_interval_ms = 500
# table_name = "logs"

# S3 archive configuration (optional)
# [s3_archive]
# enabled = false
# bucket = "my-log-archive"
# region = "us-east-1"
# archive_interval_days = 1
# max_file_size_mb = 100
# compression = "zstd"
"#
    .to_string()
}

fn generate_database_config() -> String {
    r#"# inklog database configuration
# Generated by inklog-cli generate database

[global]
level = "info"
format = "{timestamp} [{level}] {target} - {message}"

[console_sink]
enabled = true
colored = true

[performance]
channel_capacity = 10000
worker_threads = 4

[database_sink]
enabled = true
driver = "postgres"
url = "postgres://localhost/logs"
pool_size = 10
batch_size = 100
flush_interval_ms = 500
archive_to_s3 = false
archive_after_days = 30
table_name = "logs"

# For MySQL:
# driver = "mysql"
# url = "mysql://user:password@localhost/logs"

# For SQLite:
# driver = "sqlite"
# url = "sqlite://logs.db"
# pool_size = 5

# S3 archive (optional)
# [s3_archive]
# enabled = false
# bucket = "my-log-archive"
# region = "us-east-1"
"#
    .to_string()
}

fn generate_file_config() -> String {
    r#"# inklog file configuration
# Generated by inklog-cli generate file

[global]
level = "info"
format = "{timestamp} [{level}] {target} - {message}"

[console_sink]
enabled = true
colored = true

[file_sink]
enabled = true
path = "logs/app.log"
max_size = "100MB"
rotation_time = "daily"
keep_files = 30
compress = true
compression_level = 3
encrypt = false
encryption_key_env = "INKLOG_ENCRYPTION_KEY"
retention_days = 30
max_total_size = "1GB"
cleanup_interval_minutes = 60

[performance]
channel_capacity = 10000
worker_threads = 2
"#
    .to_string()
}

pub fn generate_env_example(output_path: &Path) -> Result<()> {
    let env_content = r#"# inklog environment variables example
# Copy this file to .env and customize values

# Global settings
INKLOG_LEVEL=info
INKLOG_FORMAT={timestamp} [{level}] {target} - {message}

# Console sink
INKLOG_CONSOLE_ENABLED=true

# File sink
INKLOG_FILE_ENABLED=true
INKLOG_FILE_PATH=logs/app.log
INKLOG_FILE_MAX_SIZE=100MB
INKLOG_FILE_ROTATION_TIME=daily
INKLOG_FILE_KEEP_FILES=30
INKLOG_FILE_COMPRESS=true
INKLOG_FILE_ENCRYPT=false
INKLOG_FILE_ENCRYPTION_KEY=your-encryption-key-here

# Database sink
INKLOG_DB_ENABLED=false
INKLOG_DB_DRIVER=postgres
INKLOG_DB_URL=postgres://localhost/logs
INKLOG_DB_POOL_SIZE=10
INKLOG_DB_TABLE_NAME=logs
INKLOG_DB_BATCH_SIZE=100
INKLOG_DB_FLUSH_INTERVAL_MS=500

# Performance
INKLOG_CHANNEL_CAPACITY=10000
INKLOG_WORKER_THREADS=3

# HTTP server
INKLOG_HTTP_ENABLED=false
INKLOG_HTTP_PORT=9090

# Decryption
INKLOG_DECRYPT_KEY=your-decryption-key-here
"#
    .to_string();

    let output_file = if output_path.is_dir() {
        output_path.join(".env.example")
    } else {
        output_path.to_path_buf()
    };

    let mut file = File::create(&output_file).with_context(|| {
        format!(
            "Failed to create env example file: {}",
            output_file.display()
        )
    })?;

    file.write_all(env_content.as_bytes())
        .with_context(|| "Failed to write env example content")?;

    println!("Generated env example file: {}", output_file.display());
    Ok(())
}