{"id":15095901,"url":"https://github.com/uniharmonic/monophonic","last_synced_at":"2026-01-07T00:05:39.393Z","repository":{"id":245147333,"uuid":"817393982","full_name":"uniharmonic/monophonic","owner":"uniharmonic","description":"Gin \u0026 GORM logging middleware based on Zap | 基于 Zap 的 Gin \u0026 GORM 日志记录中间件","archived":false,"fork":false,"pushed_at":"2024-08-15T13:43:26.000Z","size":49,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-02-01T17:44:17.871Z","etag":null,"topics":["gin","go","golang","gorm","logging","zap"],"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/uniharmonic.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":"2024-06-19T15:57:30.000Z","updated_at":"2024-11-18T08:03:03.000Z","dependencies_parsed_at":"2024-11-21T02:22:46.806Z","dependency_job_id":"684c8a43-ec5c-4d0b-a0d1-8e9417409529","html_url":"https://github.com/uniharmonic/monophonic","commit_stats":{"total_commits":9,"total_committers":1,"mean_commits":9.0,"dds":0.0,"last_synced_commit":"f67def8d8a688d2b738ad614e01e6a301df98a45"},"previous_names":["xinitialization/xlogger","uniharmonic/monophonic","xenochrony/xylitol"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniharmonic%2Fmonophonic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniharmonic%2Fmonophonic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniharmonic%2Fmonophonic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniharmonic%2Fmonophonic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uniharmonic","download_url":"https://codeload.github.com/uniharmonic/monophonic/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245852610,"owners_count":20683065,"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":["gin","go","golang","gorm","logging","zap"],"created_at":"2024-09-25T15:43:33.803Z","updated_at":"2026-01-07T00:05:39.365Z","avatar_url":"https://github.com/uniharmonic.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg  align=\"right\" src=\"https://avatars.githubusercontent.com/u/168158486?s=200\u0026v=4\" height=\"200\" alt=\"logo\"/\u003e\n\n[![monophonic](https://readme-typing-svg.demolab.com?font=Pixelify+Sans\u0026size=64\u0026pause=1000\u0026center=false\u0026vCenter=true\u0026random=false\u0026width=435\u0026height=200\u0026lines=:=\u003e+monophonic+\u003c=:)](https://github.com/uniharmonic/monophonic)\n\n# Monophonic | 单声道\n\n本文档综合介绍了`GLogger`、`GMiddleware`及`GResponse`三个包的整合应用，旨在提升\nGo 项目的日志管理和 HTTP 响应处理能力，确保服务的健壮性和可观察性。\n\n## `GLogger` 模块\n\n`GLogger` 是下述所有中间件的基础模块，提供了日志记录、日志级别管理、日志输出配置\n等功能。\n\n### 功能\n\n- **日志级别管理**：通过`GetLogLevel`动态解析并设置日志级别，兼容字符串配置。\n- **日志记录**：提供结构化日志记录功能，包括生成唯一`traceId`。\n- **输出配置**：支持日志输出到控制台与文件，并通过`lumberjack`实现日志文件的自动\n  切割。\n\n### 使用示例\n\n#### 日志初始化\n\n模块引入时会自动初始化默认日志记录器，默认的日志记录级别为 `Debug`， 如果需要自\n定义日志记录器，可以在按照如下方式进行初始化。\n\n```go\npackage bootstrap\n\nimport (\n\t\"path\"\n\n\t\"github.com/uniharmonic/xerography/configs\"\n\t\"github.com/uniharmonic/monophonic\"\n\t\"github.com/uniharmonic/monophonic/logger\"\n)\n\nvar Logger logger.LogInterface\n\nfunc InitializeLogger() {\n\t// 此处可以修改为你自己对应的日志文件配置，例如从环境变量或者配置文件进行读取\n\tloglevel := \"Info\"\n\tlogfile := \"./tmp/run.log\"\n\t// 此处使用 Logger 来进行日志管理，实际上你仍然可以使用 monophonic.Default 来进行日志管理\n\tLogger = monophonic.New(loglevel, logfile)\n\tmonophonic.Default = Logger.(*logger.GLogger)\n}\n```\n\n#### 输出日志\n\n如果您需要手动输出某些日志，您可以使用`monophonic.Default`来输出日志。\n\n默认的输出级别有`Debug`、`Info`、`Warn`、`Error`和`Fatal`五个级别。\n\n```go\npackage main\n\nimport \"github.com/uniharmonic/monophonic\"\n\nfunc main() {\n\tmonophonic.Default.Debug(\"This is a log test for DEBUG level\")\n\tmonophonic.Default.Info(\"This is a log test for INFO level\")\n\tmonophonic.Default.Warn(\"This is a log test for WARN level\")\n\tmonophonic.Default.Error(\"This is a log test for ERROR level\")\n\t// Fatal 会导致程序退出\n\tmonophonic.Default.Fatal(\"This is a log test for FATAL level\")\n}\n```\n\n\u003e 注意：`Fatal`级别的日志会直接导致程序退出，请谨慎使用。\n\n#### 动态切换日志级别\n\n除了一开始进行日志级别的初始化外，您还可以通过`GLogger.SetLogLevel`函数动态调整日志级别。\n\n```go\nmonophonic.Default.SetLogLevel(\"Info\")\t// Info, Warn, Error, Fatal, Debug 均可（不区分大小写）\n```\n\n## Middleware（中间件）\n\n### Gin 中间件\n\n`GinLogger`和`GinRecovery`是`Gin`框架的中间件，用于接管 `Gin` 框架默认的记录请求日志和恢复程序异常。同时我们提供了 `GReturn` 中间件，用于返回自定义的响应结构体（统一返回的结构体）。\n\n#### 功能\n\n- **请求日志**：`GinLogger`中间件记录请求的基本信息，如请求方法、路径、客户端 IP\n  等。\n- **恢复机制**：`GinRecovery`中间件优雅处理 panic，记录错误日志并可选包含调用栈\n  信息，确保服务稳定性。\n- **Greturn**：\n  - **响应结构**：定义了一套响应结构体和接口，用于统一 API 响应格式。\n  - **成功/错误处理**：`OK`和`Error`函数分别处理成功和错误响应，自动设置响应码、消\n    息及日志记录。\n\n#### 使用示例\n\n1. **初始化**：首先您需要使用`GLogger`初始化日志系统。\n2. **中间件注册**：在 Gin 框架中注册`GinLogger`和`GinRecovery`中间件，实现请求日\n   志记录和异常恢复。\n3. **响应构建**：在业务逻辑中，利用`GResponse`封装响应，统一处理成功与错误情况，\n   自动记录响应日志。\n\n```go\npackage xgin\n\nimport (\n\t\"fmt\"\n\t\"github.com/uniharmonic/monophonic/middleware\"\n\t\"github.com/gin-gonic/gin\"\n)\n\n// New 初始化一个新的 xgin 实例并返回它\nfunc main() {\n\t// 日志初始化\n\t_HERE_IS_YOUR_LOGGER_INIT_CODE_HERE()\n\n\tr = gin.New()\n\t// 注册日志中间件\n\tr.Use(middleware.GinLogger(), middleware.GinRecovery(true))\n\n\t// 注册自定义响应中间件\n\tr.POST(\"/api/v1/user/login\", func(c *gin.Context) {\n\t\t// 定义一个变量来接收解析后的请求体数据\n\t\tvar loginReq LoginRequest\n\n\t\t// 使用ShouldBindJSON来读取并绑定JSON请求体到loginReq\n\t\tif err := c.ShouldBindJSON(\u0026loginReq); err == nil {\n\t\t\t// 成功解析，现在可以访问loginReq.Username和loginReq.Password\n\t\t\tfmt.Printf(\"Received login request: %+v\\n\", loginReq)\n\t\t} else {\n\t\t\t// 解析失败，返回错误信息\n\t\t\tresponse.Error(c, http.StatusBadRequest, err, \"Invalid request body\")\n\t\t\treturn\n\t\t}\n\n\t\t// 数据库连接池获取数据库连接，请把此处替换为你的连接池获取数据库连接的代码\n\t\tdb := bootstrap.GetDBFromPool(\"mysql\")\n\t\tvar user User.User\n\t\tresult := db.First(\u0026user, \"user_name = ? and password = ?\", loginReq.Username, Utils.SHA512(loginReq.Password))\n\n\t\t// 统一返回\n\t\tif result.Error != nil {\n\t\t\tresponse.Error(c, http.StatusUnauthorized, result.Error, \"Invalid username or password\")\n\t\t\treturn\n\t\t}\n\t\ttoken, err := services.GenerateJWT(user)\n\t\tif err != nil {\n\t\t\tresponse.Error(c, http.StatusInternalServerError, err, \"Failed to generate token\")\n\t\t\treturn\n\t\t}\n\t\tresponse.OK(c, gin.H{\"status\": \"ok\", \"type\": loginReq.Type, \"currentAuthority\": \"admin\", \"token\": token}, \"Successfully logged in\")\n\t}\n}\n```\n\n\u003e 此处日志记录会使用`monophonic.Default`来记录日志，因此你需要在初始化时设置默认日志记录器`monophonic.Default`为你自定义的日志记录器。\n\n### GORM 中间件\n\n`GORM`中间件用于记录`GORM`操作的日志，包括`SQL`语句、执行时间、参数等。\n\n此处执行比较简单，您只需要在构建数据库连接池时使用 `middleware.GetGormConfig` 方法注册`GORM`中间件即可。\n\n```go\n// 其中 error 是 GORM 的配置选项，用于控制错误日志的记录级别。\n// Info, Warn, Error, Fatal, Debug 均可（不区分大小写）。\n// 实质上是调用了 monophonic.Default.SetLogLevel 方法来设置日志级别。\ndb, err = gorm.Open(sqlite.Open(\"gorm.db\"), middleware.GetGormConfig(\"error\"))\n```\n\n\u003e 因为此处实质上是调用了 monophonic.Default.SetLogLevel 方法来设置日志级别，因此需要在初始化时设置默认日志记录器`monophonic.Default`为你自定义的日志记录器。\n\u003e 同时这样做实际上并不是真的修改了 GORM 的日志记录器，而是只是修改了默认的日志记录器导致其输出不显示而已，因此对于性能会有一定影响。\n\n## 待优化事项\n\n- [ ] GLogger 包优化\n\t- [ ] 优化日志级别预解析\n\t- [ ] 单例模式管理`GLogger`实例，减少内存占用和资源消耗。\n\t- [ ] 采用 Skipper 模式，允许用户自定义跳过某些请求的日志记录。\n- [ ] 中间件包优化\n\t- [ ] 为请求参数记录添加条件判断，仅在调试模式下执行，减轻生产环境负担。\n\t- [ ] 在 `Response` 对象中，在`Clone`方法中采用深拷贝，避免数据篡改风险，尤其是处理复杂数据结构时。\n\t- [ ] 优化错误处理逻辑，使`Msg`字段传达用户友好信息，而`Info`字段提供详细错误堆栈。\n- [ ] 在错误恢复逻辑中引入更精细的错误分类处理，优化日志记录策略。\n- [ ] 优化单元测试，确保每个功能模块的测试覆盖率达到100%。\n\n## Credits\n\n- [Gin + Gorm使用 Zap 做日志记录](https://www.majingzhen.com/article/16)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiharmonic%2Fmonophonic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funiharmonic%2Fmonophonic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiharmonic%2Fmonophonic/lists"}