{"id":51186326,"url":"https://github.com/yuan-shuo/zerotele","last_synced_at":"2026-06-27T10:30:47.133Z","repository":{"id":357377261,"uuid":"1236610176","full_name":"yuan-shuo/zerotele","owner":"yuan-shuo","description":"为 gozero 写的观测代码生成器，使用一份 yaml 文件作为代码生成信息来源","archived":false,"fork":false,"pushed_at":"2026-05-12T13:45:27.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-12T15:23:09.612Z","etag":null,"topics":["generator","gozero","logger","metrics","promtheus","telemetry"],"latest_commit_sha":null,"homepage":"","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/yuan-shuo.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-12T12:07:47.000Z","updated_at":"2026-05-12T14:11:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yuan-shuo/zerotele","commit_stats":null,"previous_names":["yuan-shuo/zerotele"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/yuan-shuo/zerotele","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuan-shuo%2Fzerotele","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuan-shuo%2Fzerotele/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuan-shuo%2Fzerotele/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuan-shuo%2Fzerotele/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yuan-shuo","download_url":"https://codeload.github.com/yuan-shuo/zerotele/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuan-shuo%2Fzerotele/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34850575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["generator","gozero","logger","metrics","promtheus","telemetry"],"created_at":"2026-06-27T10:30:45.840Z","updated_at":"2026-06-27T10:30:47.126Z","avatar_url":"https://github.com/yuan-shuo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zerotele\n\n[![CI](https://github.com/yuan-shuo/zerotele/workflows/ci/badge.svg)](https://github.com/yuan-shuo/zerotele/actions/workflows/ci.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/yuan-shuo/zerotele)](https://goreportcard.com/report/github.com/yuan-shuo/zerotele)\n[![codecov](https://codecov.io/gh/yuan-shuo/zerotele/branch/main/graph/badge.svg)](https://codecov.io/gh/yuan-shuo/zerotele)\n[![Release](https://img.shields.io/github/release/yuan-shuo/zerotele.svg)](https://github.com/yuan-shuo/zerotele/releases/latest)\n[![Go Version](https://img.shields.io/badge/go%20version-%3E=1.25-61CFDD.svg)](https://golang.org/)\n\n用于生成 go-zero 观测代码的工具：用于补足 go-zero 未封装或缺少类型安全的部分观测功能：日志、指标\n\n## 功能特性\n\n- **统一配置**：通过一份 YAML 配置文件同时管理日志字段和指标定义\n- **类型安全**：为日志字段和指标标签生成专门的类型，编译期检查避免错误\n- **IDE 友好**：通过 `W` 前缀的构造器函数，IDE 自动补全一目了然\n- **链式调用**：支持流畅的链式 API，代码更简洁优雅\n- **自动排序**：带 `s` 后缀的日志方法按 YAML 字段定义顺序自动排序，无需手动控制字段顺序\n- **自动脱敏**：支持敏感数据自动脱敏，符合 `go-zero` 的 `Sensitive` 接口\n- **基数控制**：指标标签支持枚举值限制，防止标签基数爆炸\n- **自动补全 mask 函数**：自动生成未实现的脱敏函数存根，避免手动查看类型\n\n## 安装\n\n使用 `go install` 安装，或者通过 [release](https://github.com/yuan-shuo/zerotele/releases/latest) 获取二进制文件自行存放到环境变量目录下\n\n```bash\ngo install github.com/yuan-shuo/zerotele@latest\n```\n\n或者从源码构建：\n\n```bash\ngit clone https://github.com/yuan-shuo/zerotele.git\ncd zerotele\ngo build -o zerotele .\n```\n\n## 指令集\n\n### zerotele check\n用于校验 YAML 配置文件是否符合规范，一次性输出所有校验错误及错误总数\n```bash\n# 校验 zerotele.yaml 文件\nzerotele check zerotele.yaml\n```\n\n### zerotele lf\n用于省略 gozero 日志统一字段及重复的脱敏创建操作\n```bash\n# 在 ./internal/logger 目录下生成日志字段代码\nzerotele lf zerotele.yaml -d ./internal/logger\n# 在 ./logger 目录下生成日志字段代码 (更全面)\n# 并自动补全 ./internal/logger/mask.go 的脱敏函数存根\n# 若不存在 mask.go 会自行在 -d 指定的目录创建\nzerotele lf zerotele.yaml -d ./internal/logger -m mask.go\n```\n\n\n### zerotele met\n用于封装 gozero 的指标功能，使其满足类型安全和基数控制\n```bash\n# 在 ./internal/metrics 目录下生成类型安全指标器代码\nzerotele met zerotele.yaml -d ./internal/metrics\n```\n\n## 使用方法\n\n### 创建 YAML 配置文件\n\n参考 `zerotele.example.yaml` 创建你的配置文件：\n\n```yaml\n# 观测服务名\nservice: user\n\n# 日志字段清单\nlogfields:\n  - name: user_id\n    type: int64\n    mask: true\n    comment: 用户ID\n\n  - name: user_name\n    type: string\n    comment: 用户名\n\n# 指标清单\nmetrics:\n  # Counter 类型示例\n  - name: registrations_total\n    help: Total number of user registrations\n    type: counter\n    labels:\n      - name: source\n        vals: [app, web]\n      - name: error_type\n        vals: [\"*\"]\n    methods: [inc, add]\n\n  # Gauge 类型示例\n  - name: active_connections\n    help: Current number of active connections\n    type: gauge\n    labels:\n      - name: pool\n        vals: [default, cache, db]\n    methods: [set, inc, dec]\n\n  # Histogram 类型示例\n  - name: request_duration_ms\n    help: HTTP request duration in milliseconds\n    type: histogram\n    labels:\n      - name: method\n        vals: [GET, POST, PUT, DELETE]\n    buckets: [5, 10, 25, 50, 100, 250, 500, 1000]\n    methods: [observe]\n```\n\n### 在项目中使用生成的代码\n\n通过指令集中的代码获取生成的go代码文件\n\n#### 使用日志字段\n\n**传统方式（仍然支持）**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"yourproject/internal/logger\"\n    \"github.com/zeromicro/go-zero/core/logx\"\n)\n\nfunc main() {\n    ctx := context.Background()\n    log := logx.WithContext(ctx)\n\n    // 结构化日志，自动脱敏\n    log.Infow(\"用户登录\",\n        logger.WUserId(12345678),           // 输出: \"user_id\": \"****5678\" (脱敏后)\n        logger.WUserName(\"张三\"),            // 输出: \"user_name\": \"张三\"\n    )\n}\n```\n\n**链式调用方式（推荐）**\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"yourproject/internal/logger\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    // 方式1：自动排序（带 s 后缀的方法）\n    // 字段按 YAML 中定义的顺序输出，无需关心代码中的调用顺序\n    logger.L(ctx, \"用户登录\").\n        WUserName(\"张三\").      // 在 YAML 中后定义\n        WUserId(12345678).      // 在 YAML 中先定义\n        Infos()                 // 输出顺序: user_id -\u003e user_name\n\n    // 方式2：保持代码顺序（不带 s 后缀的方法）\n    // 字段按代码中调用的顺序输出\n    logger.L(ctx, \"用户登录\").\n        WUserName(\"张三\").      // 先输出\n        WUserId(12345678).      // 后输出\n        Info()                  // 输出顺序: user_name -\u003e user_id\n}\n```\n\n**链式调用方法说明**\n\n| 方法 | 是否排序 | 说明 |\n|------|----------|------|\n| `L(ctx, content)` | - | 创建日志构建器 |\n| `WFieldName(value)` | - | 添加字段（以 `W` 开头，IDE 自动提示） |\n| `Debugs()` | 排序 | Debug 级别，按 YAML 字段顺序输出 |\n| `Infos()` | 排序 | Info 级别，按 YAML 字段顺序输出 |\n| `Errors()` | 排序 | Error 级别，按 YAML 字段顺序输出 |\n| `Slows()` | 排序 | Slow 级别，按 YAML 字段顺序输出 |\n| `Debug()` | 不排序 | Debug 级别，按代码调用顺序输出 |\n| `Info()` | 不排序 | Info 级别，按代码调用顺序输出 |\n| `Error()` | 不排序 | Error 级别，按代码调用顺序输出 |\n| `Slow()` | 不排序 | Slow 级别，按代码调用顺序输出 |\n\n#### 使用指标\n\n```go\npackage main\n\nimport (\n    \"yourproject/internal/metrics\"\n)\n\nfunc main() {\n    // 创建指标实例\n    m := metrics.NewMetrics()\n\n    // 使用 Counter\n    m.RegistrationsTotal.Inc(logger.SourceApp, \"err_1001\")\n    m.RegistrationsTotal.Add(5, logger.SourceWeb, \"\")\n\n    // 使用 Gauge\n    m.ActiveConnections.Set(100, logger.PoolDefault)\n    m.ActiveConnections.Inc(logger.PoolCache)\n    m.ActiveConnections.Dec(logger.PoolDb)\n\n    // 使用 Histogram\n    m.RequestDurationMs.Observe(150, logger.MethodGET)\n}\n```\n\n### 实现脱敏函数 ( 针对 mask: true )\n\n如果使用 `-m` 参数运行工具，会自动生成 `mask.go` 文件：\n\n```go\npackage logger\n\n// maskUserId 对用户ID进行脱敏\n// 请在此实现具体的脱敏逻辑\nfunc maskUserId(userId int64) any {\n    // TODO: 实现用户ID脱敏逻辑\n    return userId\n}\n```\n\n你只需要填充具体的脱敏逻辑即可。当你添加新的 mask 字段后，再次使用 `-m` 运行工具，会自动追加新的函数存根，不会覆盖已有的实现。\n\n**示例：实现脱敏逻辑**\n\n```go\npackage logger\n\nimport \"strconv\"\n\n// maskUserId 对用户ID进行脱敏\n// 脱敏规则：显示前2位和后2位，中间用 **** 替换\nfunc maskUserId(userId int64) any {\n    s := strconv.FormatInt(userId, 10)\n    if len(s) \u003c= 4 {\n        return \"****\"\n    }\n    return s[:2] + \"****\" + s[len(s)-2:]\n}\n```\n\n## 配置文件说明\n\n### 根级字段\n\n| 字段 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `service` | string | 是 | 观测服务名，作为指标的 service 标签值 |\n| `logfields` | array | 否 | 日志字段列表 |\n| `metrics` | array | 否 | 指标列表 |\n\n### 日志字段配置\n\n| 字段 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | 是 | 字段名（snake_case），如 `user_id` |\n| `type` | string | 是 | Go 类型，如 `string`, `int64`, `bool` 等 |\n| `mask` | bool | 否 | 是否需要脱敏，默认 `false` |\n| `comment` | string | 否 | 字段注释说明 |\n\n### 指标配置\n\n| 字段 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | 是 | 指标名称（snake_case） |\n| `help` | string | 是 | 指标帮助信息 |\n| `type` | string | 是 | 指标类型：`counter`, `gauge`, `histogram` |\n| `labels` | array | 否 | 标签列表 |\n| `methods` | array | 是 | 支持的方法列表 |\n| `buckets` | array | 否 | 直方图桶边界（仅 histogram） |\n\n### 标签配置\n\n| 字段 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| `name` | string | 是 | 标签名（snake_case） |\n| `vals` | array | 是 | 标签可选值列表，使用 `[\"*\"]` 表示任意值 |\n\n### 支持的方法\n\n| 指标类型 | 方法 | 说明 |\n|----------|------|------|\n| Counter | `inc` | 递增计数器 |\n| Counter | `add` | 增加指定值 |\n| Gauge | `set` | 设置值 |\n| Gauge | `inc` | 递增 |\n| Gauge | `dec` | 递减 |\n| Histogram | `observe` | 记录观察值 |\n\n## 命名规范\n\n### snake_case 命名规范（OpenTelemetry）\n\n需要满足 snake_case 规范的内容：\n- `service`\n- `logfields[].name`\n- `metrics[].name`\n- `metrics[].labels[].name`\n\n命名规则：\n- 必须以小写字母开头\n- 只能包含小写字母、数字和下划线\n- 不能连续出现多个下划线\n- 不能以下划线开头或结尾\n- 有效示例：`user_id`, `http_request_duration`, `trace_id`\n- 无效示例：`UserID`, `user-id`, `user__id`, `_user_id`, `user_id_`, `123_user`\n\n### 命名转换规则\n\n| YAML 配置 | Go 类型名 | 说明 |\n|-----------|-----------|------|\n| `name: user_id` | `UserId` | 字段类型名 |\n| `name: user_id` | `WUserId()` | 构造器函数名 |\n| `name: user_id` | `user_id` | JSON 字段名 |\n| `label: source` | `Source` | 枚举类型名 |\n| `label: source` | `SourceApp` | 枚举值名（PascalCase） |\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuan-shuo%2Fzerotele","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyuan-shuo%2Fzerotele","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuan-shuo%2Fzerotele/lists"}