{"id":16475966,"url":"https://github.com/softprops/json-env-logger","last_synced_at":"2025-03-16T18:31:34.392Z","repository":{"id":41475792,"uuid":"276549127","full_name":"softprops/json-env-logger","owner":"softprops","description":"A structured JSON logger for Rust.","archived":false,"fork":false,"pushed_at":"2022-11-21T17:47:56.000Z","size":847,"stargazers_count":30,"open_issues_count":11,"forks_count":13,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-06T16:50:13.135Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/softprops.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-02T04:34:18.000Z","updated_at":"2025-02-17T11:01:43.000Z","dependencies_parsed_at":"2023-01-21T20:17:03.918Z","dependency_job_id":null,"html_url":"https://github.com/softprops/json-env-logger","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fjson-env-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fjson-env-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fjson-env-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softprops%2Fjson-env-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softprops","download_url":"https://codeload.github.com/softprops/json-env-logger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243826788,"owners_count":20354220,"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":"2024-10-11T12:41:05.631Z","updated_at":"2025-03-16T18:31:33.915Z","avatar_url":"https://github.com/softprops.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  json env logger\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n   A simple structured JSON logger for Rust\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca alt=\"GitHub Actions\" href=\"https://github.com/softprops/json-env-logger/actions\"\u003e\n    \u003cimg src=\"https://github.com/softprops/json-env-logger/workflows/Main/badge.svg\"/\u003e\n  \u003c/a\u003e\n  \u003ca alt=\"crates.io\" href=\"https://crates.io/crates/json-env-logger\"\u003e\n    \u003cimg src=\"https://img.shields.io/crates/v/json_env_logger.svg?logo=rust\"/\u003e\n  \u003c/a\u003e\n  \u003ca alt=\"docs.rs\" href=\"http://docs.rs/json-env-logger\"\u003e\n    \u003cimg src=\"https://docs.rs/json_env_logger/badge.svg\"/\u003e\n  \u003c/a\u003e\n  \u003ca alt=\"latest docs\" href=\"https://softprops.github.io/json-env-logger\"\u003e\n   \u003cimg src=\"https://img.shields.io/badge/docs-latest-green.svg\"/\u003e\n  \u003c/a\u003e\n  \u003ca alt=\"license\" href=\"LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg\"/\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n## install\n\nAdd the following to your `Cargo.toml` file\n\n```toml\n[dependencies]\njson_env_logger = \"0.1\"\n```\n\n## usage\n\n### tl;dr\n\nWhen you run\n\n```bash\n$ RUST_LOG=trace cargo -q run \\\n  --example default \\\n  --features iso-timestamps\n```\n\nYou will get\n\n```json\n{\"level\":\"TRACE\",\"ts\":\"2020-07-06T03:41:57.831Z\",\"msg\":\"I am a trace\",\"task_id\":567,\"thread_id\":\"12\"}\n{\"level\":\"DEBUG\",\"ts\":\"2020-07-06T03:41:57.832Z\",\"msg\":\"I am a debug\",\"foo\":1}\n{\"level\":\"INFO\",\"ts\":\"2020-07-06T03:41:57.832Z\",\"msg\":\"I am an info\"}\n{\"level\":\"WARN\",\"ts\":\"2020-07-06T03:41:57.832Z\",\"msg\":\"I am a warning\"}\n{\"level\":\"ERROR\",\"ts\":\"2020-07-06T03:41:57.832Z\",\"msg\":\"I am an error\"}\n```\n\n### basic use\n\nLike `env_logger`, call `init` before you start your logging engines.\n\n```rust\nfn main() {\n    json_env_logger::init();\n\n    log::info!(\"👋\")\n}\n```\n\nRun your program with `RUST_LOG=info your/bin`\n\n### adding more structure\n\nThe `log` crate is working its way towards adding first class interfaces for structured fields\nin its macros. Rather then reinvent that functionality, this crate embraces it.  `json_env_logger` will serialize these key-value pairs when present. Sadly the `log` crate\ndoesn't expose these macro interfaces quite yet. ...But `kv-log-macro` does!\n\n```toml\n[dependencies]\njson_env_logger = \"0.1\"\nkv-log-macro = \"1.0\"\n```\n\n```rust\n// the macros exported in this crate are\n// log compatible and will one day be merged \n// so save your future self the toil of find and replace\nuse kv_log_macro as log;\n\nfn main() {\n    json_env_logger::init();\n\n    log::info!(\"👋\", { size: \"medium\", age: 42 })\n}\n```\n\n\u003e ⭐ These structured fields are currently limited for now to values of type `u64`, `i64`, `f64`, `bool`, `char` or `str`\n\nRun your program with `RUST_LOG=info your/bin`\n\n### iso-timestamps\n\nBy default json_env_logger uses unix epoch time for timestamps. You might prefer\nISO-8601 timestamps instead. You can swap implementations with by enabling the `iso-timestamps` feature\n\n```toml\n[dependencies]\njson_env_logger = { version = \"0.1\", features = [\"iso-timestamps\"] }\n```\n\n```rust\nfn main() {\n    json_env_logger::init();\n\n    log::info!(\"👋\")\n}\n```\n\nRun your program with `RUST_LOG=info your/bin`\n\n### panic visibility\n\nWhen panics are unavoidable, you can register a panic hook that serializes the panic to json before logging it with `error!`\n\n```rust\nfn main() {\n    json_env_logger::init();\n    json_env_logger::panic_hook();\n\n    panic!(\"whoooops!\")\n}\n```\n\nRun your program with `RUST_LOG=info your/bin`\n\n\u003e ⭐ You can also serialize backtraces by enabling the `backtrace` cargo feature\n\n## faq\n\n\u003cdetails\u003e\u003csummary\u003eWhy do I need structured logging?\u003c/summary\u003e\n\u003cp\u003e\n\nMaybe you don't. ...But maybe you do! You might if you run applications in production in an environment whose log aggregation does useful things\nfor you if you emit json logs such as\n\n  - structured field based filters, an alternative to artisanal regex queries\n  - aggregation statistics \n  - alert automation\n  - anomaly detection\n  - basically anything a computer can do for you when it's logs are structured in a machine readable format \n\n\u003c/p\u003e\n\u003c/details\u003e\n\u0026nbsp;\n\n \u003cdetails\u003e\u003csummary\u003eWhat use case does json_env_logger target?\u003c/summary\u003e\n\u003cp\u003e\n\nMost folks on the Rust logging market start out with [`log`](https://crates.io/crates/log). They soon find they need configurable logging so they move to [`env_logger`](https://crates.io/crates/env_logger). Sometimes they want `env_logger` but pretty logging for host local application so they move to [`pretty_env_logger`](https://crates.io/crates/pretty_env_logger) of if you like [`emoji-logger`](https://crates.io/crates/emoji-logger).\n\nIn other cases you want to run applications in a cloud service that rewards you for emitting logs in JSON format. That's use case this targets, those coming from `env_logger` but would like to leverage build in JSON log parsing and discovery options their cloud provided offers for free.\n\u003c/p\u003e\n\u003c/details\u003e\n\u0026nbsp;\n \u003cdetails\u003e\u003csummary\u003eDoes one of these already exist?\u003c/summary\u003e\n\u003cp\u003e\n\nA few actually. Like many crates in the Rust ecosystem, they are all good. Picking a dependency is a dance of picking your tradeoffs given an application's goals and needs.\n\nThere's [`slog`](https://github.com/slog-rs/slog), an entire ecosystem of logging for Rust. It's strength is that its highly configurable. It's drawback is that it's highly configurable interface can get in the way of simple cases where you just want to emit structured logs in json without a lot of ceremony.\n\nHere's an example directly from its [docs](https://docs.rs/slog-json/2.3.0/slog_json/)\n\n```rust\n#[macro_use]\nextern crate slog;\nextern crate slog_json;\n\nuse slog::Drain;\nuse std::sync::Mutex;\n\nfn main() {\n    let root = slog::Logger::root(\n        Mutex::new(slog_json::Json::default(std::io::stderr())).map(slog::Fuse),\n        o!(\"version\" =\u003e env!(\"CARGO_PKG_VERSION\"))\n    );\n}\n```\n\nvs\n\n```rust\nfn main() {\n    json_env_logger::init();\n}\n```\n\n`slog`'s encouraged programming model is to pass loggers instances around as arguments. This is a good practice and allows for simple context propagation, but comes at the expense of being a much different programming model that others using the standard `log` crate have written code against so you may find yourself having to rewrite more code that just your program's initialization.\n\nThere's also [`femme`](https://github.com/lrlna/femme/) which is one part pretty printer, one part JSON logger, and one part WASM JavaScript object logger. It's strength is that is indeed pretty! It's not _just_ pretty logger and yet also not _just_ a JSON logger. It's an assortment of things making it broadly focused rather than narrowly focused on JSON log formatting. If you only use one of those things you might be packing more than you need.\n\nIf you are migrating from `env_logger`'s environment variable driving configuration options you are a bit out of luck. You will be finding yourself recompiling and rebuilding your application to change log levels.\n\n\u003c/p\u003e\n\u003c/details\u003e\n\u0026nbsp;\n\n \u003cdetails\u003e\u003csummary\u003eSo what are the tradeoffs of json_env_logger then?\u003c/summary\u003e\n\u003cp\u003e\n\nGlad you asked. It depends on `env_logger` which has some opinionated defaults, some of which you might not like. For example, it logs to stderr by default. You might play for team stdout. The good news is that json_env_logger exposes its interfaces for overriding those opinions. \n\nSome features available in `env_logger` `json_env_logger` doesn't use and those bring in extra transitive dependencies. We're aware. Luckily they are all behind `env_logger` feature flags and `json_env_logger` turns them all off! The only transient dependency is then just `log` which you already have if your doing any sort of logging:)\n\u003c/p\u003e\n\u003c/details\u003e\n\u0026nbsp;\n\n\u003cdetails\u003e\u003csummary\u003eI have more questions\u003c/summary\u003e\n\u003cp\u003e\n\n That's technically not a question but ok. Ask away by [opening a GitHub issue](https://github.com/softprops/json-env-logger/issues/new). Thanks!\n\u003c/p\u003e\n\u003c/details\u003e\n\u0026nbsp;\n\nDoug Tangren (softprops) 2020\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftprops%2Fjson-env-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftprops%2Fjson-env-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftprops%2Fjson-env-logger/lists"}