{"id":15554943,"url":"https://github.com/go-clog/clog","last_synced_at":"2025-04-13T04:10:32.093Z","repository":{"id":49840693,"uuid":"80851927","full_name":"go-clog/clog","owner":"go-clog","description":"Package clog is a channel-based logging package for Go","archived":false,"fork":false,"pushed_at":"2023-12-18T02:11:18.000Z","size":107,"stargazers_count":169,"open_issues_count":4,"forks_count":18,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-24T09:16:39.884Z","etag":null,"topics":["console","discord","file","go","logging","lsif-enabled","slack"],"latest_commit_sha":null,"homepage":"","language":"Go","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/go-clog.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":"2017-02-03T17:26:02.000Z","updated_at":"2024-12-20T02:28:13.000Z","dependencies_parsed_at":"2025-01-16T11:09:19.592Z","dependency_job_id":"a38b41bd-2fbc-4879-acfd-a5471f032bb3","html_url":"https://github.com/go-clog/clog","commit_stats":{"total_commits":50,"total_committers":3,"mean_commits":"16.666666666666668","dds":"0.040000000000000036","last_synced_commit":"ff3132fc84adc6e711eb3265738fbe4dc42434ce"},"previous_names":["unknwon/clog"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-clog%2Fclog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-clog%2Fclog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-clog%2Fclog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-clog%2Fclog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-clog","download_url":"https://codeload.github.com/go-clog/clog/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248661704,"owners_count":21141450,"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":["console","discord","file","go","logging","lsif-enabled","slack"],"created_at":"2024-10-02T15:05:10.434Z","updated_at":"2025-04-13T04:10:32.064Z","avatar_url":"https://github.com/go-clog.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Clog \n\n[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/go-clog/clog/Go?logo=github\u0026style=for-the-badge)](https://github.com/go-clog/clog/actions?query=workflow%3AGo)\n[![codecov](https://img.shields.io/codecov/c/github/go-clog/clog/master?logo=codecov\u0026style=for-the-badge)](https://codecov.io/gh/go-clog/clog)\n[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge\u0026logo=go)](https://pkg.go.dev/unknwon.dev/clog/v2?tab=doc)\n[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge\u0026logo=sourcegraph)](https://sourcegraph.com/github.com/go-clog/clog)\n\n![](https://avatars1.githubusercontent.com/u/25576866?v=3\u0026s=200)\n\nPackage clog is a channel-based logging package for Go.\n\nThis package supports multiple loggers across different levels of logging. It uses Go's native channel feature to provide goroutine-safe mechanism on large concurrency.\n\n## Installation\n\nThe minimum requirement of Go is **1.11**.\n\n\tgo get unknwon.dev/clog/v2\n    \nPlease apply `-u` flag to update in the future.\n\n## Getting Started\n\nIt is extremely easy to create one with all default settings. Generally, you would want to create new logger inside `init` or `main` function.\n\nLet's create a logger that prints logs to the console:\n\n```go\nimport (\n\tlog \"unknwon.dev/clog/v2\"\n)\n\nfunc init() {\n\terr := log.NewConsole()\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n\nfunc main() {\n\tlog.Trace(\"Hello %s!\", \"World\") // YYYY/MM/DD 12:34:56 [TRACE] Hello World!\n\tlog.Info(\"Hello %s!\", \"World\")  // YYYY/MM/DD 12:34:56 [ INFO] Hello World!\n\tlog.Warn(\"Hello %s!\", \"World\")  // YYYY/MM/DD 12:34:56 [ WARN] Hello World!\n\n\t// Graceful stopping all loggers before exiting the program.\n\tlog.Stop()\n}\n```\n\nThe code inside `init` function is equivalent to the following:\n\n```go\nfunc init() {\n\terr := log.NewConsole(0, \n        log.ConsoleConfig{\n\t\t    Level: log.LevelTrace,\n\t    },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\nOr expand further:\n\n```go\nfunc init() {\n\terr := log.NewConsoleWithName(log.DefaultConsoleName, 0, \n        log.ConsoleConfig{\n\t\t    Level: log.LevelTrace,\n\t    },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\n- The `0` is an integer type so it is used as underlying buffer size. In this case, `0` creates synchronized logger (call hangs until write is finished).\n- Any non-integer type is used as the config object, in this case `ConsoleConfig` is the respective config object for the console logger.\n- The `LevelTrace` used here is the lowest logging level, meaning prints every log to the console. All levels from lowest to highest are: `LevelTrace`, `LevelInfo`, `LevelWarn`, `LevelError`, `LevelFatal`, each of them has at least one respective function, e.g. `log.Trace`, `log.Info`, `log.Warn`, `log.Error` and `log.Fatal`.\n\nIn production, you may want to make log less verbose and be asynchronous:\n\n```go\nfunc init() {\n\t// The buffer size mainly depends on number of logs could be produced at the same time, \n\t// 100 is a good default.\n\terr := log.NewConsole(100,\n        log.ConsoleConfig{\n\t\t    Level:      log.LevelInfo,\n\t    },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\n- When you set level to be `LevelInfo`, calls to the `log.Trace` will be simply noop.\n- The console logger comes with color output, but for non-colorable destination, the color output will be disabled automatically.\n\nOther builtin loggers are file (`log.NewFile`), Slack (`log.NewSlack`) and Discord (`log.NewDiscord`), see later sections in the documentation for usage details.\n\n### Multiple Loggers\n\nYou can have multiple loggers in different modes across levels.\n\n```go\nfunc init() {\n\terr := log.NewConsole()\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n\terr := log.NewFile(\n        log.FileConfig{\n\t\t    Level:    log.LevelInfo,\n\t\t    Filename: \"clog.log\",\n\t    },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\nIn this example, all logs will be printed to console, and only logs with level Info or higher (i.e. Warn, Error and Fatal) will be written into file.\n\n### Write to a specific logger\n\nWhen multiple loggers are registered, it is also possible to write logs to a special logger by giving its name.\n\n```go\nfunc main() {\n\tlog.TraceTo(log.DefaultConsoleName, \"Hello %s!\", \"World\")\n\tlog.InfoTo(log.DefaultConsoleName, \"Hello %s!\", \"World\")\n\tlog.WarnTo(log.DefaultConsoleName, \"Hello %s!\", \"World\")\n\tlog.ErrorTo(log.DefaultConsoleName, \"So bad... %v\", err)\n\tlog.FatalTo(log.DefaultConsoleName, \"Boom! %v\", err)\n\n\t// ...\n}\n```\n\n### Caller Location\n\nWhen using `log.Error` and `log.Fatal` functions, the caller location is written along with logs. \n\n```go\nfunc main() {\n\tlog.Error(\"So bad... %v\", err) // YYYY/MM/DD 12:34:56 [ERROR] [...er/main.go:64 main()] ...\n\tlog.Fatal(\"Boom! %v\", err)     // YYYY/MM/DD 12:34:56 [FATAL] [...er/main.go:64 main()] ...\n\n\t// ...\n}\n```\n\n- Calling `log.Fatal` will exit the program.\n- If you want to have different skip depth than the default, use `log.ErrorDepth` or `log.FatalDepth`.\n\n### Clean Exit\n\nYou should always call `log.Stop()` to wait until all logs are processed before program exits.\n\n## Builtin Loggers\n\n### File Logger\n\nFile logger is the single most powerful builtin logger, it has the ability to rotate based on file size, line, and date:\n\n```go\nfunc init() {\n\terr := log.NewFile(100, \n        log.FileConfig{\n            Level:              log.LevelInfo,\n            Filename:           \"clog.log\",  \n            FileRotationConfig: log.FileRotationConfig {\n                Rotate: true,\n                Daily:  true,\n            },\n        },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\nIn case you have some other packages that write to a file, and you want to take advatange of this file rotation feature. You can do so by using the `log.NewFileWriter` function. It acts like a standard `io.Writer`.\n\n```go\nfunc init() {\n\tw, err := log.NewFileWriter(\"filename\",\n        log.FileRotationConfig{\n            Rotate: true,\n            Daily:  true,\n        },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\n### Slack Logger\n\nSlack logger is also supported in a simple way:\n\n```go\nfunc init() {\n\terr := log.NewSlack(100,\n        log.SlackConfig{\n            Level: log.LevelInfo,\n            URL:   \"https://url-to-slack-webhook\",\n        },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\nThis logger also works for [Discord Slack](https://discordapp.com/developers/docs/resources/webhook#execute-slackcompatible-webhook) endpoint.\n\n### Discord Logger\n\nDiscord logger is supported in rich format via [Embed Object](https://discordapp.com/developers/docs/resources/channel#embed-object):\n\n```go\nfunc init() {\n\terr := log.NewDiscord(100,\n        log.DiscordConfig{\n            Level: log.LevelInfo,\n            URL:   \"https://url-to-discord-webhook\",\n        },\n    )\n\tif err != nil {\n\t\tpanic(\"unable to create new logger: \" + err.Error())\n\t}\n}\n```\n\nThis logger automatically retries up to 3 times if hits rate limit with respect to `retry_after`.\n\n## Build Your Own Logger\n\nYou can implement your own logger and all the concurrency stuff are handled automatically!\n\nHere is an example which sends all logs to a channel, we call it `chanLogger` here:\n\n```go\nimport log \"unknwon.dev/clog/v2\"\n\ntype chanConfig struct {\n\tc chan string\n}\n\nvar _ log.Logger = (*chanLogger)(nil)\n\ntype chanLogger struct {\n\tname  string\n\tlevel log.Level\n\tc     chan string\n}\n\nfunc (l *chanLogger) Name() string     { return l.name }\nfunc (l *chanLogger) Level() log.Level { return l.level }\n\nfunc (l *chanLogger) Write(m log.Messager) error {\n\tl.c \u003c- m.String()\n\treturn nil\n}\n\nfunc main() {\n\tlog.New(\"channel\", func(name string, vs ...interface{}) (log.Logger, error) {\n\t\tvar cfg *chanConfig\n\t\tfor i := range vs {\n\t\t\tswitch v := vs[i].(type) {\n\t\t\tcase chanConfig:\n\t\t\t\tcfg = \u0026v\n\t\t\t}\n\t\t}\n\n\t\tif cfg == nil {\n\t\t\treturn nil, fmt.Errorf(\"config object with the type '%T' not found\", chanConfig{})\n\t\t} else if cfg.c == nil {\n\t\t\treturn nil, errors.New(\"channel is nil\")\n\t\t}\n\n\t\treturn \u0026chanLogger{\n\t\t\tname: name,\n\t\t\tc:    cfg.c,\n\t\t}, nil\n\t})\n}\n```\n\nHave fun!\n\n## Credits\n\n- Avatar is a modified version based on [egonelbre/gophers' scientist](https://github.com/egonelbre/gophers/blob/master/vector/science/scientist.svg).\n\n## License\n\nThis project is under MIT License. See the [LICENSE](LICENSE) file for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-clog%2Fclog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-clog%2Fclog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-clog%2Fclog/lists"}