{"id":13830243,"url":"https://github.com/go-simpler/sloggen","last_synced_at":"2025-12-14T20:56:15.272Z","repository":{"id":189835316,"uuid":"681400520","full_name":"go-simpler/sloggen","owner":"go-simpler","description":"🪵 Generate domain-specific wrappers for log/slog","archived":false,"fork":false,"pushed_at":"2025-06-09T17:11:21.000Z","size":86,"stargazers_count":22,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-30T10:58:54.628Z","etag":null,"topics":["codegen","go","logging","slog","tool"],"latest_commit_sha":null,"homepage":"https://go-simpler.org/sloggen","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-simpler.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":"2023-08-22T00:03:07.000Z","updated_at":"2025-05-08T20:21:21.000Z","dependencies_parsed_at":"2023-08-22T01:39:30.730Z","dependency_job_id":"56a243b9-7c5a-44e7-ac01-bec4b5c77d8f","html_url":"https://github.com/go-simpler/sloggen","commit_stats":null,"previous_names":["go-simpler/slog-gen"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/go-simpler/sloggen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-simpler%2Fsloggen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-simpler%2Fsloggen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-simpler%2Fsloggen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-simpler%2Fsloggen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-simpler","download_url":"https://codeload.github.com/go-simpler/sloggen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-simpler%2Fsloggen/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264450556,"owners_count":23610194,"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":["codegen","go","logging","slog","tool"],"created_at":"2024-08-04T10:00:57.741Z","updated_at":"2025-12-14T20:56:15.217Z","avatar_url":"https://github.com/go-simpler.png","language":"Go","funding_links":[],"categories":["Go","General"],"sub_categories":[],"readme":"# sloggen\n\n[![checks](https://github.com/go-simpler/sloggen/actions/workflows/checks.yml/badge.svg)](https://github.com/go-simpler/sloggen/actions/workflows/checks.yml)\n[![pkg.go.dev](https://pkg.go.dev/badge/go-simpler.org/sloggen.svg)](https://pkg.go.dev/go-simpler.org/sloggen)\n[![goreportcard](https://goreportcard.com/badge/go-simpler.org/sloggen)](https://goreportcard.com/report/go-simpler.org/sloggen)\n[![codecov](https://codecov.io/gh/go-simpler/sloggen/branch/main/graph/badge.svg)](https://codecov.io/gh/go-simpler/sloggen)\n\nGenerate domain-specific wrappers for `log/slog`.\n\n## 📌 About\n\nWhen using `log/slog` in a production-grade project, it is useful to write helpers to prevent typos in the keys:\n\n```go\nslog.Info(\"a user has logged in\", \"user_id\", 42)\nslog.Info(\"a user has logged out\", \"user_ip\", 42) // oops :(\n```\n\nDepending on your code style, these can be simple constants (if you prefer key-value pairs)...\n\n```go\nconst UserId = \"user_id\"\n```\n\n...or custom `slog.Attr` constructors (if you're a safety/performance advocate):\n\n```go\nfunc UserId(value int) slog.Attr { return slog.Int(\"user_id\", value) }\n```\n\n`sloggen` generates such helpers for you, so you don't have to write them manually.\n\n---\n\nThe default `log/slog` levels cover most use cases, but at some point you may want to introduce custom levels that better suit your app.\nAt first glance, this is as simple as defining a constant:\n\n```go\nconst LevelAlert = slog.Level(12)\n```\n\nHowever, custom levels are treated differently than the first-class citizens `Debug`/`Info`/`Warn`/`Error`:\n\n```go\nslog.Log(nil, LevelAlert, \"msg\") // want \"ALERT msg\"; got \"ERROR+4 msg\"\n```\n\n`sloggen` solves this inconvenience by generating not only the levels themselves, but also the necessary helpers.\n\nUnfortunately, the only way to use such levels is the `Log` method, which is quite verbose.\n`sloggen` can generate a custom `Logger` type so that custom levels can be used just like the builtin ones:\n\n```go\n// before:\nlogger.Log(nil, LevelAlert, \"msg\", \"key\", \"value\")\n// after:\nlogger.Alert(\"msg\", \"key\", \"value\")\n```\n\nAdditionally, there are options to choose the API style of the arguments (`...any` or `...slog.Attr`) and to add/remove `context.Context` as the first parameter.\nThis allows you to adjust the logging API to your own code style without sacrificing convenience.\n\n\u003e [!tip]\n\u003e Various API rules for `log/slog` can be enforced by the [`sloglint`][1] linter. Give it a try too!\n\n## 🚀 Features\n\n* Generate key constants and `slog.Attr` constructors\n* Generate custom levels with helpers for parsing/printing\n* Generate a custom `Logger` type with methods for custom levels\n* Codegen-based, so no runtime dependency introduced\n\n## 📦 Install\n\nAdd the following directive to any `.go` file and run `go generate ./...`.\n\n```go\n//go:generate go run go-simpler.org/sloggen@\u003cversion\u003e [flags]\n```\n\nWhere `\u003cversion\u003e` is the version of `sloggen` itself (use `latest` for automatic updates) and `[flags]` is the list of [available options](#help).\n\n## 📋 Usage\n\nThere are two ways to provide options to `sloggen`: CLI flags and a `.yml` config file.\nThe former works best for few options and requires only a single `//go:generate` directive.\nFor many options it may be more convenient to use a config file, since `go generate` does not support multiline commands.\nThe config file can also be reused between several (micro)services if they share the same domain.\n\nTo get started, see the [`example_test.go`](example_test.go) file and the [`example`](example) directory.\n\n### Key constants\n\nThe `-c` flag (or the `consts` field) is used to generate a key constant.\nFor example, `-c=used_id` results in:\n\n```go\nconst UserId = \"user_id\"\n```\n\n### Attribute constructors\n\nThe `-a` flag (or the `attrs` field) is used to generate a custom `slog.Attr` constructor.\nFor example, `-a=used_id:int` results in:\n\n```go\nfunc UserId(value int) slog.Attr { return slog.Int(\"user_id\", value) }\n```\n\n### Custom levels\n\nThe `-l` flag (or the `levels` field) is used to generate a custom `slog.Level`.\nFor example, `-l=alert:12` results in:\n\n```go\nconst LevelAlert = slog.Level(12)\n\nfunc ParseLevel(s string) (slog.Level, error) {...}\nfunc RenameLevels(_ []string, attr slog.Attr) slog.Attr {...}\n```\n\nThe `ParseLevel` function should be used to parse the level from a string (e.g. from an environment variable):\n\n```go\nlevel, err := slogx.ParseLevel(\"ALERT\")\n```\n\nThe `RenameLevels` function should be used as `slog.HandlerOptions.ReplaceAttr` to print custom level names correctly:\n\n```go\nlogger := slog.New(slog.NewTextHandler(os.Stdout, \u0026slog.HandlerOptions{\n    Level:       level,\n    ReplaceAttr: slogx.RenameLevels,\n}))\n```\n\n### Custom Logger\n\nThe `-logger` flag (or the `logger` field) is used to generate a custom `Logger` type with methods for custom levels.\n\nThe `-api` flag (or the `logger.api` field) is used to choose the API style of the arguments: `any` for `...any` (key-value pairs) and `attr` for `...slog.Attr`.\n\nThe `-ctx` flag (or the `logger.ctx` field) is used to add or remove `context.Context` as the first parameter.\n\nFor example, `-l=alert:12 -logger -api=attr -ctx` results in:\n\n```go\ntype Logger struct{ handler slog.Handler }\n\nfunc New(h slog.Handler) *Logger { return \u0026Logger{handler: h} }\n\nfunc (l *Logger) Alert(ctx context.Context, msg string, attrs ...slog.Attr) {...}\n```\n\nThe generated `Logger` has all the utility methods of the original `slog.Logger`, including `Enabled()`, `With()` and `WithGroup()`.\n\nSince `Logger` is just a frontend, you can always fall back to `slog.Logger` (e.g. to pass it to a library) using the `Handler()` method:\n\n```go\nslog.New(logger.Handler())\n```\n\n### Help\n\n```shell\nUsage: sloggen [flags]\n\nFlags:\n    -config \u003cpath\u003e        read config from the file instead of flags\n    -dir \u003cpath\u003e           change the working directory before generating files\n    -pkg \u003cname\u003e           the name for the generated package (default: slogx)\n    -i \u003cimport\u003e           add import\n    -l \u003cname:severity\u003e    add level\n    -c \u003ckey\u003e              add constant\n    -a \u003ckey:type\u003e         add attribute\n    -logger               generate a custom Logger type\n    -api \u003cany|attr\u003e       the API style for the Logger's methods (default: any)\n    -ctx                  add context.Context to the Logger's methods\n    -h, -help             print this message and quit\n```\n\nFor the description of the config file fields, see [`.slog.example.yml`](.slog.example.yml).\n\n[1]: https://github.com/go-simpler/sloglint\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-simpler%2Fsloggen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-simpler%2Fsloggen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-simpler%2Fsloggen/lists"}