{"id":29128125,"url":"https://github.com/ditzdev/cappie","last_synced_at":"2025-09-05T02:14:12.109Z","repository":{"id":300479566,"uuid":"1006279565","full_name":"DitzDev/Cappie","owner":"DitzDev","description":"A fast JSON logger for Rust.","archived":false,"fork":false,"pushed_at":"2025-06-21T23:17:40.000Z","size":0,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-21T23:33:26.491Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DitzDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-21T22:34:28.000Z","updated_at":"2025-06-21T23:17:43.000Z","dependencies_parsed_at":"2025-06-21T23:33:28.053Z","dependency_job_id":"9f727b1a-91b8-4aff-afee-8dca8069baf9","html_url":"https://github.com/DitzDev/Cappie","commit_stats":null,"previous_names":["ditzdev/cappie"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DitzDev/Cappie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DitzDev%2FCappie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DitzDev%2FCappie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DitzDev%2FCappie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DitzDev%2FCappie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DitzDev","download_url":"https://codeload.github.com/DitzDev/Cappie/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DitzDev%2FCappie/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262690485,"owners_count":23349168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-30T01:05:06.777Z","updated_at":"2025-06-30T01:05:12.267Z","avatar_url":"https://github.com/DitzDev.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cappie\n\n[![Latest Version]][crates.io]\n\n[Latest Version]: https://img.shields.io/crates/v/cappie.svg\n[crates.io]: https://crates.io/crates/cappie\n\nA fast, flexible JSON logger for Rust, inspired by Pino from Node.js.\n\n## Features\n\n- 🚀 **Fast \u0026 Simple** - High-performance logger with minimal overhead\n- 📝 **JSON Logging** - Structured JSON output by default\n- 🎨 **Pretty Printing** - Human-readable colorized output\n- 🔧 **Highly Configurable** - Customize colors, formats, and outputs\n- ✨ **Flexible Formatting** - Complete control over log output format and positioning\n- 📊 **Structured Logging** - Add custom fields to log entries\n- 👶 **Child Loggers** - Create contextual child loggers\n- 📁 **Multiple Outputs** - Log to console, files, or multiple destinations\n- 🌈 **Custom Colors** - Full control over ANSI color codes for any component\n\n## Installation\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\ncappie = \"0.1.0\"\n```\n\nOr install with `cargo` for new version:\n```bash\ncargo add cappie\n```\n\n## Quick Start\n\n### JSON Logging (Default)\n\n```rust\nuse cappie::{Logger, Level};\n\nfn main() {\n    let logger = Logger::new(\"my-app\")\n        .with_level(Level::Debug);\n    \n    logger.info(\"Application started\");\n    logger.error(\"Something went wrong\");\n    \n    // With additional fields\n    logger.info_with(\"User logged in\", |log| {\n        log.string(\"user_id\", \"12345\")\n           .string(\"ip\", \"192.168.1.1\")\n           .bool(\"first_time\", true);\n    });\n}\n```\n\n**Output:**\n```json\n{\"level\":30,\"time\":\"2024-01-15T10:30:45.123Z\",\"name\":\"my-app\",\"msg\":\"Application started\"}\n{\"level\":50,\"time\":\"2024-01-15T10:30:45.124Z\",\"name\":\"my-app\",\"msg\":\"Something went wrong\"}\n{\"level\":30,\"time\":\"2024-01-15T10:30:45.125Z\",\"name\":\"my-app\",\"msg\":\"User logged in\",\"user_id\":\"12345\",\"ip\":\"192.168.1.1\",\"first_time\":true}\n```\n\n### Pretty Logging\n\n```rust\nuse cappie::{Logger, PrettyFormatter};\n\nfn main() {\n    let logger = Logger::new(\"my-app\")\n        .with_formatter(Box::new(PrettyFormatter::new()));\n    \n    logger.info(\"Server started\");\n    logger.warn(\"Memory usage high\");\n    logger.error(\"Database connection failed\");\n}\n```\n\n**Output:**\n```\n[10:30:45] (my-app) INFO: Server started\n[10:30:45] (my-app) WARN: Memory usage high  \n[10:30:45] (my-app) ERROR: Database connection failed\n```\n\n## 🌟 Flexible Formatting (NEW!)\n\nThe `FlexibleFormatter` gives you complete control over log output format. You can position any component anywhere, add custom colors, prefixes, suffixes, and even custom text.\n\n### Basic Flexible Usage\n\n```rust\nuse cappie::{Logger, FlexibleFormatter, ComponentType, ComponentPosition};\n\n// Default format: [HH:mm:SS] (logger) LEVEL: message fields\nlet logger = Logger::new(\"app\")\n    .with_formatter(Box::new(FlexibleFormatter::new()));\n```\n\n### Custom Positioning Examples\n\n#### 1. Message First Format\n```rust\n// Output: message LEVEL [HH:mm:SS]: fields\nlet logger = Logger::new(\"api\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_message(ComponentPosition::Start, None, None, None)\n            .add_level(ComponentPosition::AfterMessage, Some(\"\\x1b[31m\".to_string()), Some(\" \".to_string()), None)\n            .add_timestamp(ComponentPosition::AfterLevel, None, Some(\" [\".to_string()), Some(\"]\".to_string()))\n            .add_custom_text(\": \", ComponentPosition::AfterTime, None)\n            .add_fields(ComponentPosition::End, None, None, None)\n    ));\n\nlogger.error(\"Database connection failed\");\n// Output: Database connection failed ERROR [10:30:45]: \n```\n\n#### 2. Minimal Format\n```rust\n// Output: [LEVEL] message\nlet logger = Logger::new(\"minimal\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_level(ComponentPosition::Start, Some(\"\\x1b[33m\".to_string()), Some(\"[\".to_string()), Some(\"]\".to_string()))\n            .add_message(ComponentPosition::AfterLevel, None, Some(\" \".to_string()), None)\n    ));\n\nlogger.warn(\"This is a warning\");\n// Output: [WARN] This is a warning\n```\n\n#### 3. Time at the End\n```rust\n// Output: [logger] LEVEL: message | fields (at HH:mm:SS)\nlet logger = Logger::new(\"backend\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_logger_name(ComponentPosition::Start, Some(\"\\x1b[36m\".to_string()), Some(\"[\".to_string()), Some(\"]\".to_string()))\n            .add_level(ComponentPosition::AfterName, Some(\"\\x1b[32m\".to_string()), Some(\" \".to_string()), None)\n            .add_custom_text(\": \", ComponentPosition::AfterLevel, None)\n            .add_message(ComponentPosition::AfterLevel, None, None, None)\n            .add_fields(ComponentPosition::AfterMessage, None, Some(\" | \".to_string()), None)\n            .add_timestamp(ComponentPosition::End, Some(\"\\x1b[90m\".to_string()), Some(\" (at \".to_string()), Some(\")\".to_string()))\n    ));\n\nlogger.info_with(\"Server started\", |log| { log.number(\"port\", 8080); });\n// Output: [backend] INFO: Server started | port=8080 (at 10:30:45)\n```\n\n#### 4. Highly Colorful Format\n```rust\n// Output: 🚀 [HH:mm:SS] {logger} \u003cLEVEL\u003e → message 📊 fields\nlet logger = Logger::new(\"colorful\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_custom_text(\"🚀 \", ComponentPosition::Start, Some(\"\\x1b[95m\".to_string()))\n            .add_timestamp(ComponentPosition::Start, Some(\"\\x1b[94m\".to_string()), Some(\"[\".to_string()), Some(\"]\".to_string()))\n            .add_logger_name(ComponentPosition::AfterTime, Some(\"\\x1b[96m\".to_string()), Some(\" {\".to_string()), Some(\"}\".to_string()))\n            .add_level(ComponentPosition::AfterName, Some(\"\\x1b[93m\".to_string()), Some(\" \u003c\".to_string()), Some(\"\u003e\".to_string()))\n            .add_custom_text(\" → \", ComponentPosition::AfterLevel, Some(\"\\x1b[97m\".to_string()))\n            .add_message(ComponentPosition::AfterLevel, Some(\"\\x1b[92m\".to_string()), None, None)\n            .add_fields(ComponentPosition::End, Some(\"\\x1b[91m\".to_string()), Some(\" 📊 \".to_string()), None)\n    ));\n\nlogger.info_with(\"App started\", |log| { log.string(\"version\", \"1.0.0\"); });\n// Output: 🚀 [10:30:45] {colorful} \u003cINFO\u003e → App started 📊 version=1.0.0\n```\n\n### Component Types\n\nThe `FlexibleFormatter` supports these component types:\n\n- **`ComponentType::Timestamp`** - The log timestamp\n- **`ComponentType::LoggerName`** - The logger name  \n- **`ComponentType::Level`** - The log level (INFO, ERROR, etc.)\n- **`ComponentType::Message`** - The log message\n- **`ComponentType::Fields`** - Additional structured fields\n- **`ComponentType::CustomText(String)`** - Custom static text\n\n### Component Positions\n\nYou can position components at these locations:\n\n- **`ComponentPosition::Start`** - At the very beginning\n- **`ComponentPosition::AfterTime`** - After the timestamp\n- **`ComponentPosition::AfterName`** - After the logger name\n- **`ComponentPosition::AfterLevel`** - After the log level\n- **`ComponentPosition::AfterMessage`** - After the message\n- **`ComponentPosition::End`** - At the very end\n\n### FlexibleFormatter Methods\n\n```rust\nFlexibleFormatter::new()\n    // Clear all default components\n    .clear_components()\n    \n    // Add components with full control\n    .add_component(ComponentType::Timestamp, ComponentPosition::Start, color, prefix, suffix)\n    \n    // Convenience methods for common components\n    .add_timestamp(position, color, prefix, suffix)\n    .add_logger_name(position, color, prefix, suffix)\n    .add_level(position, color, prefix, suffix)\n    .add_message(position, color, prefix, suffix)\n    .add_fields(position, color, prefix, suffix)\n    .add_custom_text(\"text\", position, color)\n    \n    // Configuration\n    .with_time_format(\"%H:%M:%S\")\n    .with_no_colors()\n```\n\n## Custom Colors \u0026 Traditional Pretty Format\n\n```rust\nuse cappie::{Logger, PrettyFormatter, Level};\n\nfn main() {\n    let logger = Logger::new(\"my-app\")\n        .with_formatter(Box::new(\n            PrettyFormatter::new()\n                .with_color(Level::Error, \"\\x1b[91m\") // Bright red\n                .with_color(Level::Warn, \"\\x1b[93m\")  // Bright yellow\n                .with_time_format(\"%Y-%m-%d %H:%M:%S\")\n        ));\n    \n    logger.warn(\"Custom colored warning\");\n    logger.error(\"Custom colored error\");\n}\n```\n\n## Log Levels\n\n| Level | Value | Description |\n|-------|-------|-------------|\n| `TRACE` | 10 | Very detailed information |\n| `DEBUG` | 20 | Debug information |\n| `INFO` | 30 | General information |\n| `WARN` | 40 | Warning messages |\n| `ERROR` | 50 | Error messages |\n| `FATAL` | 60 | Fatal errors |\n\n## Advanced Usage\n\n### Child Loggers\n\nCreate contextual loggers that inherit parent configuration:\n\n```rust\nlet parent = Logger::new(\"app\");\nlet auth_logger = parent.child(\"auth\");\nlet db_logger = parent.child(\"database\");\n\nauth_logger.info(\"User authenticated\");  // Outputs: app.auth\ndb_logger.error(\"Connection timeout\");   // Outputs: app.database\n```\n\n### Multiple Outputs\n\nLog to console and file simultaneously:\n\n```rust\nuse cappie::{Logger, FileOutput, MultiOutput, StdoutOutput};\n\nlet logger = Logger::new(\"my-app\")\n    .with_output(Box::new(\n        MultiOutput::new()\n            .add_output(Box::new(StdoutOutput))\n            .add_output(Box::new(FileOutput::new(\"app.log\")))\n    ));\n\nlogger.info(\"This goes to both console and file\");\n```\n\n### Base Fields\n\nAdd fields that appear in every log entry:\n\n```rust\nlet logger = Logger::new(\"my-app\")\n    .with_field(\"version\", \"1.0.0\")\n    .with_field(\"env\", \"production\")\n    .with_field(\"service\", \"api-server\");\n\nlogger.info(\"App started\"); // Includes version, env, and service fields\n```\n\n### Structured Logging\n\nAdd contextual information to specific log entries:\n\n```rust\nlogger.error_with(\"Database query failed\", |log| {\n    log.string(\"query\", \"SELECT * FROM users\")\n       .number(\"duration_ms\", 1500)\n       .string(\"table\", \"users\")\n       .bool(\"timeout\", true);\n});\n```\n\n## ANSI Color Codes\n\nCappie supports full ANSI color customization:\n\n```rust\nuse cappie::{Logger, FlexibleFormatter, ComponentPosition, ComponentType};\n\nlet logger = Logger::new(\"colorful-app\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_timestamp(ComponentPosition::Start, Some(\"\\x1b[32m\".to_string()), Some(\"[\".to_string()), Some(\"]\".to_string()))    // Green\n            .add_level(ComponentPosition::AfterTime, Some(\"\\x1b[33m\".to_string()), Some(\" \".to_string()), None)    // Yellow\n            .add_message(ComponentPosition::AfterLevel, Some(\"\\x1b[31m\".to_string()), Some(\": \".to_string()), None)   // Red\n    ));\n```\n\n### Common ANSI Colors\n\n| Color | Code | Color | Code |\n|-------|------|-------|------|\n| Black | `\\x1b[30m` | Bright Black | `\\x1b[90m` |\n| Red | `\\x1b[31m` | Bright Red | `\\x1b[91m` |\n| Green | `\\x1b[32m` | Bright Green | `\\x1b[92m` |\n| Yellow | `\\x1b[33m` | Bright Yellow | `\\x1b[93m` |\n| Blue | `\\x1b[34m` | Bright Blue | `\\x1b[94m` |\n| Magenta | `\\x1b[35m` | Bright Magenta | `\\x1b[95m` |\n| Cyan | `\\x1b[36m` | Bright Cyan | `\\x1b[96m` |\n| White | `\\x1b[37m` | Bright White | `\\x1b[97m` |\n\n## Examples\n\nRun the included examples:\n\n```bash\n# Basic JSON and pretty logging\ncargo run --example basic\n\n# Pretty logging with colors and fields\ncargo run --example pretty\n\n# Custom colors, outputs, and configurations\ncargo run --example custom\n\n# Flexible formatter examples with various layouts\ncargo run --example flexible\n```\n\n## API Reference\n\n### Logger Methods\n\n```rust\n// Create a new logger\nLogger::new(\"app-name\")\n\n// Configuration\n.with_level(Level::Debug)\n.with_formatter(Box::new(FlexibleFormatter::new()))\n.with_output(Box::new(StdoutOutput))\n.with_field(\"key\", \"value\")\n\n// Logging methods\n.trace(\"message\")\n.debug(\"message\")\n.info(\"message\")\n.warn(\"message\")\n.error(\"message\")\n.fatal(\"message\")\n\n// Logging with fields\n.info_with(\"message\", |log| {\n    log.string(\"key\", \"value\")\n       .number(\"count\", 42)\n       .bool(\"success\", true);\n})\n\n// Create child logger\n.child(\"module-name\")\n```\n\n### FlexibleFormatter Methods\n\n```rust\nFlexibleFormatter::new()\n    .with_time_format(\"%H:%M:%S\")\n    .clear_components()\n    \n    // Add specific components\n    .add_timestamp(position, color, prefix, suffix)\n    .add_logger_name(position, color, prefix, suffix)\n    .add_level(position, color, prefix, suffix)\n    .add_message(position, color, prefix, suffix)\n    .add_fields(position, color, prefix, suffix)\n    .add_custom_text(\"text\", position, color)\n    \n    // Generic component addition\n    .add_component(component_type, position, color, prefix, suffix)\n    \n    .with_no_colors()\n```\n\n### PrettyFormatter Methods\n\n```rust\nPrettyFormatter::new()\n    .with_time_format(\"%H:%M:%S\")\n    .with_color(Level::Error, \"\\x1b[91m\")\n    .with_no_colors()\n```\n\n## Formatter Comparison\n\n| Feature | JsonFormatter | PrettyFormatter | FlexibleFormatter |\n|---------|---------------|-----------------|-------------------|\n| JSON Output | ✅ | ❌ | ❌ |\n| Human Readable | ❌ | ✅ | ✅ |\n| Custom Colors | ❌ | ✅ | ✅ |\n| Custom Positioning | ❌ | ❌ | ✅ |\n| Custom Text | ❌ | ❌ | ✅ |\n| Prefixes/Suffixes | ❌ | ❌ | ✅ |\n| Performance | Fastest | Fast | Fast |\n| Use Case | Machine parsing | Development | Custom layouts |\n\n## Performance\n\nCappie is designed for high performance:\n\n- **Minimal allocations** - Efficient memory usage\n- **Fast JSON serialization** - Uses serde_json for speed\n- **Lazy evaluation** - Fields only processed when logging level is enabled\n- **Zero-cost abstractions** - No runtime overhead for disabled log levels\n- **Flexible without overhead** - FlexibleFormatter adds minimal cost\n\n## Real-World Usage Examples\n\n### Web Server Logging\n```rust\n// API request logging with flexible format\nlet api_logger = Logger::new(\"api\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_custom_text(\"🌐 \", ComponentPosition::Start, Some(\"\\x1b[94m\".to_string()))\n            .add_timestamp(ComponentPosition::Start, Some(\"\\x1b[90m\".to_string()), None, None)\n            .add_level(ComponentPosition::AfterTime, Some(\"\\x1b[32m\".to_string()), Some(\" [\".to_string()), Some(\"]\".to_string()))\n            .add_message(ComponentPosition::AfterLevel, None, Some(\" \".to_string()), None)\n            .add_fields(ComponentPosition::End, Some(\"\\x1b[36m\".to_string()), Some(\" → \".to_string()), None)\n    ));\n\napi_logger.info_with(\"Request processed\", |log| {\n    log.string(\"method\", \"GET\")\n       .string(\"path\", \"/api/users\")\n       .number(\"status\", 200)\n       .number(\"duration_ms\", 45);\n});\n```\n\n### Database Operations\n```rust\n// Database logging with custom format\nlet db_logger = Logger::new(\"database\")\n    .with_formatter(Box::new(\n        FlexibleFormatter::new()\n            .clear_components()\n            .add_custom_text(\"💾 DB \", ComponentPosition::Start, Some(\"\\x1b[95m\".to_string()))\n            .add_level(ComponentPosition::Start, Some(\"\\x1b[91m\".to_string()), Some(\"[\".to_string()), Some(\"]\".to_string()))\n            .add_message(ComponentPosition::AfterLevel, None, Some(\" \".to_string()), None)\n            .add_timestamp(ComponentPosition::End, Some(\"\\x1b[90m\".to_string()), Some(\" @\".to_string()), None)\n            .add_fields(ComponentPosition::AfterMessage, Some(\"\\x1b[33m\".to_string()), Some(\" {\".to_string()), Some(\"}\".to_string()))\n    ));\n```\n\n## Comparison with Pino\n\n| Feature | Cappie | Pino |\n|---------|---------|------|\n| JSON Logging | ✅ | ✅ |\n| Pretty Printing | ✅ | ✅ |\n| Flexible Formatting | ✅ | ❌ |\n| Child Loggers | ✅ | ✅ |\n| Custom Formatters | ✅ | ✅ |\n| Multiple Outputs | ✅ | Limited |\n| Custom Colors | ✅ | Limited |\n| Custom Positioning | ✅ | ❌ |\n| Performance | Very Fast | Fast |\n| Language | Rust | JavaScript |\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Acknowledgments\n\n- Inspired by [Pino](https://github.com/pinojs/pino) - The fast JSON logger for Node.js\n- Built with [serde](https://serde.rs/) for serialization\n- Uses [chrono](https://github.com/chronotope/chrono) for timestamp handling","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fditzdev%2Fcappie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fditzdev%2Fcappie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fditzdev%2Fcappie/lists"}