{"id":20762521,"url":"https://github.com/welllog/olog","last_synced_at":"2025-04-30T07:08:48.920Z","repository":{"id":153796429,"uuid":"626497959","full_name":"welllog/olog","owner":"welllog","description":"a lightweight, high-performance, out-of-the-box logging library that relies solely on the Go standard library","archived":false,"fork":false,"pushed_at":"2024-09-11T01:28:13.000Z","size":100,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-30T07:08:42.163Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/welllog.png","metadata":{"files":{"readme":"README-CN.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-04-11T15:29:26.000Z","updated_at":"2024-09-11T01:26:33.000Z","dependencies_parsed_at":"2024-11-17T10:36:05.501Z","dependency_job_id":"442e9f50-8e89-4209-92d6-4c81ce7a5db5","html_url":"https://github.com/welllog/olog","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/welllog%2Folog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/welllog%2Folog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/welllog%2Folog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/welllog%2Folog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/welllog","download_url":"https://codeload.github.com/welllog/olog/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251658207,"owners_count":21622820,"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-11-17T10:35:49.431Z","updated_at":"2025-04-30T07:08:48.903Z","avatar_url":"https://github.com/welllog.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cbr\u003e \u003ca href=\"README.md\"\u003eEnglish\u003c/a\u003e | 中文\n\u003c/p\u003e\n\n# olog\n* olog是一个轻量级、高性能、开箱即用的日志库，完全依赖于Go标准库。\n* 支持以JSON、纯文本以及自定义格式输出日志。\n* 支持设置上下文处理函数，以从上下文中检索字段以进行输出。\n* 支持七个日志级别：TRACE、DEBUG、INFO、NOTICE、WARN、ERROR和FATAL，对应于“trace”、“debug”、“info”、“notice”、“warn”、“error”和“fatal”标签。用户还可以定义自己的语义标签，如“slow”和“stat”。\n* 提供输出开关控制，除了FATAL之外的所有日志级别都可以控制输出。\n* 增强了对调用者打印的控制。用户可以在全局设置中禁用调用者打印以提高性能，但可以在打印某些关键日志时启用调用者打印支持。\n* 为用户提供了一个Logger接口，以便轻松构建自己的日志记录器。\n\n### 代码示例\n```go\n    Trace(\"hello world\")\n    Tracew(\"hello\", Field{Key: \"name\", Value: \"bob\"})\n    Debug(\"hello world\")\n    Infow(\"hello\", Field{Key: \"name\", Value: \"linda\"}, Field{Key: \"age\", Value: 18})\n    Noticef(\"hello %s\", \"world\")\n    Warnf(\"hello %s\", \"world\")\n    Warnw(\"hello\", Field{Key: \"order_no\", Value: \"AWESDDF\"})\n    Errorw(\"hello world\", Field{Key: \"success\", Value: true})\n    Log(Record{Level: DEBUG, LevelTag: \"print\", Caller: Disable, Fields: []Field{{Key: \"price\", Value: 32.5}},\n        Stack: Enable, StackSize: 1, MsgOrFormat: \"hello world\"})\n    Fatal(\"fatal exit\")\n```\njson输出如下：\n```json\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"trace\",\"caller\":\"olog/log_test.go:377\",\"content\":\"hello world\",\"stack\":\"\\ngithub.com/welllog/olog.TestPlainOutput\\n\\t/olog/log_test.go:377\\ntesting.tRunner\\n\\t/usr/local/opt/go/libexec/src/testing/testing.go:1576\\nruntime.goexit\\n\\t/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1598\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"trace\",\"caller\":\"olog/log_test.go:378\",\"content\":\"hello\",\"name\":\"bob\",\"stack\":\"\\ngithub.com/welllog/olog.TestPlainOutput\\n\\t/olog/log_test.go:378\\ntesting.tRunner\\n\\t/usr/local/opt/go/libexec/src/testing/testing.go:1576\\nruntime.goexit\\n\\t/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1598\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"debug\",\"caller\":\"olog/log_test.go:379\",\"content\":\"hello world\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"info\",\"caller\":\"olog/log_test.go:380\",\"content\":\"hello\",\"name\":\"linda\",\"age\":18}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"notice\",\"caller\":\"olog/log_test.go:381\",\"content\":\"hello world\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"warn\",\"caller\":\"olog/log_test.go:382\",\"content\":\"hello world\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"warn\",\"caller\":\"olog/log_test.go:383\",\"content\":\"hello\",\"order_no\":\"AWESDDF\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"error\",\"caller\":\"olog/log_test.go:384\",\"content\":\"hello world\",\"success\":true}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"print\",\"content\":\"hello world\",\"price\":32.5,\"stack\":\"\\ngithub.com/welllog/olog.TestPlainOutput\\n\\t/olog/log_test.go:385\"}\n{\"@timestamp\":\"2023-04-20T18:33:42+08:00\",\"level\":\"fatal\",\"caller\":\"olog/log_test.go:388\",\"content\":\"fatal exit\"}\n```\nplain输出如下：\n```\n2023-04-20T18:32:09+08:00\ttrace\tolog/log_test.go:377\thello world\tstack=\ngithub.com/welllog/olog.TestPlainOutput\n\t/olog/log_test.go:377\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:1576\nruntime.goexit\n\t/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1598\n2023-04-20T18:32:09+08:00\ttrace\tolog/log_test.go:378\thello\tname=bob\tstack=\ngithub.com/welllog/olog.TestPlainOutput\n\t/olog/log_test.go:378\ntesting.tRunner\n\t/usr/local/opt/go/libexec/src/testing/testing.go:1576\nruntime.goexit\n\t/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1598\n2023-04-20T18:32:09+08:00\tdebug\tolog/log_test.go:379\thello world\n2023-04-20T18:32:09+08:00\tinfo\tolog/log_test.go:380\thello\tname=linda\tage=18\n2023-04-20T18:32:09+08:00\tnotice\tolog/log_test.go:381\thello world\n2023-04-20T18:32:09+08:00\twarn\tolog/log_test.go:382\thello world\n2023-04-20T18:32:09+08:00\twarn\tolog/log_test.go:383\thello\torder_no=AWESDDF\n2023-04-20T18:32:09+08:00\terror\tolog/log_test.go:384\thello world\tsuccess=true\n2023-04-20T18:32:09+08:00\tprint\thello world\tprice=32.5\tstack=\ngithub.com/welllog/olog.TestPlainOutput\n\t/olog/log_test.go:385\n2023-04-20T18:32:09+08:00\tfatal\tolog/log_test.go:388\tfatal exit\n```\n\n### contextLogger使用\n```go\n        SetDefCtxHandle(func(ctx context.Context) []Field {\n\t\tvar fs []Field\n\t\tuid, ok := ctx.Value(\"uid\").(int)\n\t\tif ok {\n\t\t\tfs = append(fs, Field{Key: \"uid\", Value: uid})\n\t\t}\n\n\t\tname, ok := ctx.Value(\"name\").(string)\n\t\tif ok {\n\t\t\tfs = append(fs, Field{Key: \"name\", Value: name})\n\t\t}\n\t\treturn fs\n\t})\n        logger := WithContext(GetLogger(), context.WithValue(context.Background(), \"uid\", 3))\n\tlogger.Debug(\"test\")\n\t\t\n        logger = WithContext(logger, context.WithValue(context.Background(), \"name\", \"bob\"))\n        logger = WithEntries(logger, map[string]any{\"requestId\": \"ae32fec\"})\n\tlogger.Debug(\"test 2\")\n```\n\n### 实现自己的logger\n```\ntype CustomLogger struct {\n\tLogger\n}\n\nfunc (l *CustomLogger) Slow(a ...any) {\n    l.Log(Record{Level: WARN, LevelTag: \"slow\", CallerSkip: 1, MsgArgs: a})\n}\n\nfunc (l *CustomLogger) Stat(a ...any) {\n    l.Log(Record{Level: INFO, LevelTag: \"stat\", CallerSkip: 1, MsgArgs: a})\n}\n\nfunc (l *CustomLogger) Debug(a ...any) {\n    l.Log(Record{Level: DEBUG, CallerSkip: 1, Caller: Enable, MsgArgs: a})\n}\n```\n\n### slog支持\n```\nlogger := slog.New(\n    NewSlogHandler(NewLogger()),\n)\n\nlogger.Info(\"hello world\")\n```\n\n### 日志内容输出\n目前日志内容默认输出到控制台。\n如果需要输出内容到文件中，需要设置日志的Writer,可以通过将文件指针传递给NewWriter函数来构造一个Writer。\n如果想要实现更强大的输出控制如切割日志文件,可以使用[github.com/lestrrat-go/file-rotatelogs](https://github.com/lestrrat-go/file-rotatelogs)来构造Writer。\n自主实现Write方法时需要注意参数[]byte不应该超出该方法的作用域，否则可能会导致数据并发问题并导致混乱。\n\n### 性能\n记录一条消息和3个字段(禁用caller输出,并发测试)：\n```\ngoos: darwin\ngoarch: arm64\npkg: github.com/welllog/olog\nBenchmarkInfow\nBenchmarkInfow/std.logger\nBenchmarkInfow/std.logger-10         \t 3760806\t       287.4 ns/op\t      48 B/op\t       1 allocs/op\nBenchmarkInfow/olog.json\nBenchmarkInfow/olog.json-10          \t14397530\t        77.93 ns/op\t      96 B/op\t       1 allocs/op\nBenchmarkInfow/olog.plain\nBenchmarkInfow/olog.plain-10         \t21455214\t        56.19 ns/op\t      96 B/op\t       1 allocs/op\nBenchmarkInfow/olog.ctx.json\nBenchmarkInfow/olog.ctx.json-10      \t14290038\t        83.48 ns/op\t      96 B/op\t       1 allocs/op\nBenchmarkInfow/olog.ctx.plain\nBenchmarkInfow/olog.ctx.plain-10     \t19133161\t        59.64 ns/op\t      96 B/op\t       1 allocs/op\nPASS\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwelllog%2Folog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwelllog%2Folog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwelllog%2Folog/lists"}