{"id":24849144,"url":"https://github.com/knutwalker/env-logger","last_synced_at":"2025-03-26T11:25:12.907Z","repository":{"id":274119276,"uuid":"921971098","full_name":"knutwalker/env-logger","owner":"knutwalker","description":"A pretty and simple logger for Zig","archived":false,"fork":false,"pushed_at":"2025-03-21T19:29:08.000Z","size":406,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T20:11:50.790Z","etag":null,"topics":["cli","env-logger","logging","zig"],"latest_commit_sha":null,"homepage":"https://knutwalker.github.io/env-logger/","language":"Zig","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/knutwalker.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}},"created_at":"2025-01-25T01:28:04.000Z","updated_at":"2025-03-21T19:29:11.000Z","dependencies_parsed_at":"2025-01-25T02:27:02.115Z","dependency_job_id":"ee0d9f36-1f21-48c5-bfde-b077844522b9","html_url":"https://github.com/knutwalker/env-logger","commit_stats":null,"previous_names":["knutwalker/env-logger"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Fenv-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Fenv-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Fenv-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knutwalker%2Fenv-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/knutwalker","download_url":"https://codeload.github.com/knutwalker/env-logger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245642570,"owners_count":20648875,"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":["cli","env-logger","logging","zig"],"created_at":"2025-01-31T12:29:51.758Z","updated_at":"2025-03-26T11:25:12.900Z","avatar_url":"https://github.com/knutwalker.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- Autogenerated: Edit `README.md.tpl` and run `zig build readme` --\u003e\n\n# env-logger [![CI Status][ci-badge]][ci-url] ![License: MIT][license-badge]\n\n[ci-badge]: https://github.com/knutwalker/env-logger/actions/workflows/ci.yml/badge.svg\n[ci-url]: https://github.com/knutwalker/env-logger\n[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=shield\n\nA pretty logger for Zig, inspired by [pretty_env_logger](https://github.com/seanmonstar/pretty-env-logger).\n\nThe logger works together with the `std.log` API.\nIt provides a `logFn` function that can be set to your `std.Options`.\n\n## Quick start example\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{});\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![quick.png](images/quick.png)\n\n## Installation\n\nUpdate to latest version:\n\n```sh\nzig fetch --save git+https://github.com/knutwalker/env-logger.git\n```\n\nAdd to `build.zig`:\n\n```zig\nexe.root_module.addImport(\"env-logger\", b.dependency(\"env-logger\", .{}).module(\"env-logger\"));\n```\n\n\u003e [!IMPORTANT]\n\u003e `env-logger` tracks Zig `0.14.0`\n\n## Examples\n\n### Starting example\n\nSetting up the logger happens in two steps:\n\n1. Call `env_logger.setup(.{})` and set the value as your `std.Options`.\n2. Call `env_logger.init(.{})` once and as early as possible to initialize the logger.\n\n`env-logger` will read the `ZIG_LOG` environment variable and parse it as the log level.\nIt logs colored messages to stderr by default.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{});\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![starting.png](images/starting.png)\n\n### Trace level\n\nZig does not define a `.trace` log level in `std.log.Level`.\n`env-logger` can still log trace messages at a `.trace` level.\n\nFirst enable this in the `setup` opts.\nTo log a trace message, prefix a debug message with `TRACE: ` (including the colon and space).\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{\n    .enable_trace_level = true,\n});\n\npub fn main() !void {\n    env_logger.init(.{});\n\n    if (!env_logger.defaultLevelEnabled(.trace)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=trace ...`\\n\", .{});\n    }\n\n    std.log.debug(\"TRACE: debug message\", .{});\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![trace_level.png](images/trace_level.png)\n\n### Custom environment variable\n\nBy default, the logger will look for the `ZIG_LOG` environment variable in order to configure the log level.\nIf you want to use a different environment variable, set the name in the`filter` option.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{\n        .filter = .{ .env = .{ .name = \"MY_LOG_ENV\" } },\n    });\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env MY_LOG_ENV=debug ...`\\n\", .{});\n    }\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![custom_env.png](images/custom_env.png)\n\n### Scoped logging\n\nScoped loggers other than the `.default` scope will be included in the log message.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{});\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    const log = std.log.scoped(.scope);\n\n    log.debug(\"debug message\", .{});\n    log.info(\"info message\", .{});\n    log.warn(\"warn message\", .{});\n    log.err(\"error message\", .{});\n}\n\n```\n\n![scoped_log.png](images/scoped_log.png)\n\n### Dynamic log level\n\nThe log level can also be set programmatically instead of using the environment variable.\nIt can also be changed at runtime.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{\n        .filter = .{ .level = .info },\n    });\n\n    std.log.debug(\"you don't see me\", .{});\n    std.log.info(\"but I am here\", .{});\n\n    // env_logger.set_log_level(.debug);\n\n    std.log.debug(\"now you see me\", .{});\n}\n\n```\n\n![dynamic_log_level.png](images/dynamic_log_level.png)\n\n### Custom `std.Options`\n\nIn case you want to set other `std.Options`, you can use the `env_logger.setupWith` function.\nAlternatively, you can use the `env_logger.setupFn` function and set the `logFn` field.\nThis allows you to statically disable certain log levels since the `setup` function sets the `log_level` field to `.debug`.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setupWith(\n    .{},\n    // The second argument is the std.Options that will be set.\n    .{\n        .fmt_max_depth = 64,\n    },\n);\n\npub fn main() !void {\n    env_logger.init(.{});\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n### Only log messages\n\nYou can disable the level and logger parts of the log message and only render the message itself.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{\n        .render_level = false,\n        .render_logger = false,\n    });\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    const log = std.log.scoped(.scope);\n\n    log.debug(\"debug message\", .{});\n    log.info(\"info message\", .{});\n    log.warn(\"warn message\", .{});\n    log.err(\"error message\", .{});\n}\n\n```\n\n![only_messages.png](images/only_messages.png)\n\n### Add timestamps\n\nYou can also add timestamps to the log messages.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{\n        .render_timestamp = true,\n    });\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![add_timestamps.png](images/add_timestamps.png)\n\n### Log to different outputs\n\nBy default, the logger logs to stderr, but it can also be configured to log to stdout, append to a file, or write to a writer.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    defer _ = gpa.deinit();\n    const allocator = gpa.allocator();\n\n    var args = try std.process.argsWithAllocator(allocator);\n    defer args.deinit();\n\n    _ = args.next() orelse return; // skip the executable name\n\n    const output_filename = args.next() orelse {\n        std.debug.print(\"Usage: log_to_file $FILENAME\\n\", .{});\n        std.process.exit(1);\n    };\n\n    var output: env_logger.InitOptions.Output = .stderr;\n    var buf: ?std.ArrayList(u8) = null;\n    defer if (buf) |b| b.deinit();\n\n    if (std.mem.eql(u8, output_filename, \"-\")) {\n        output = .stdout;\n    } else if (std.mem.eql(u8, output_filename, \"+\")) {\n        buf = .init(allocator);\n        output = .{ .writer = buf.?.writer().any() };\n    } else {\n        const output_file = try std.fs.cwd().createFile(\n            output_filename,\n            // Set `truncate` to false to append to the file.\n            .{ .truncate = false },\n        );\n        output = .{ .file = output_file };\n    }\n\n    env_logger.init(.{ .output = output });\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n\n    if (buf) |b| {\n        std.debug.print(\"Contents of buffer:\\n{s}\\n\", .{b.items});\n    }\n}\n\n```\n\n### Configure colors\n\nBy default, the logger will detect if the terminal supports colors and use them.\nYou can disable this by setting the `enable_color` option to `false`.\nAlternatively, you can force the logger to use colors by setting the `force_color` option to `true`.\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    env_logger.init(.{\n        // disable all use of colors,\n        .enable_color = false,\n        // force the use of colors, also for files and writers\n        .force_color = true,\n    });\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    // try piping stderr to a file, it's still colored\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![colors.png](images/colors.png)\n\n### Configure allocators\n\nParsing and constructing the log filter requires allocations.\nBy default, the logger uses the `std.heap.page_allocator` for this.\nIf you want to use a different allocator, you can set the `allocator` option to a `std.mem.Allocator`.\n\nSince the filter is supposed to be kept for the remainder\nof the program's lifetime, you can set two different allocators, one\nfor all the parsing (e.g. a gpa, like the `DebugAllocator`), and another\none for the final filter allocation (e.g. an arena allocator).\n\n```zig\nconst std = @import(\"std\");\nconst env_logger = @import(\"env-logger\");\n\npub const std_options = env_logger.setup(.{});\n\npub fn main() !void {\n    var gpa: std.heap.DebugAllocator(.{ .verbose_log = true }) = .init;\n    defer if (gpa.deinit() == .leak) @panic(\"memory leak\");\n\n    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);\n    defer arena.deinit();\n\n    env_logger.init(.{ .allocator = .{ .split = .{\n        .parse_gpa = gpa.allocator(),\n        .filter_arena = arena.allocator(),\n    } } });\n\n    if (!env_logger.defaultLevelEnabled(.debug)) {\n        std.debug.print(\"To see all log messages, run with `env ZIG_LOG=debug ...`\\n\", .{});\n    }\n\n    std.log.debug(\"debug message\", .{});\n    std.log.info(\"info message\", .{});\n    std.log.warn(\"warn message\", .{});\n    std.log.err(\"error message\", .{});\n}\n\n```\n\n![allocator.png](images/allocator.png)\n\n\n## Contributing\n\nContributions are welcome!\n\nPlease open an issue or a pull request if you have any suggestions or improvements.\n\n\n## License\n\nenv-logger is licensed under the [MIT License](http://opensource.org/licenses/MIT)\n\n---\n\n\u003c!-- vim: set ft=markdown: --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknutwalker%2Fenv-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknutwalker%2Fenv-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknutwalker%2Fenv-logger/lists"}