4. Exporter 代码规范与风格

在 Exporter 开发中,代码规范与风格直接影响可维护性、可读性以及团队协作效率。本章围绕 Go 和 Python 两种主流 Exporter 实现语言,系统讲解格式化工具、命名规范、注释规范与错误处理规范,确保产出代码符合生产级标准。

核心原则:代码规范不是审美问题,而是降低认知负载、减少 Bug 引入概率的工程手段。Exporter 作为采集代理,常运行在受限环境,规范代码更易审计、调试与扩展。

4.1 代码格式化工具

格式化工具消除人为风格差异,使团队代码呈现统一视觉结构。Go 与 Python 社区均有官方推荐工具。

语言 工具 命令示例 集成方式
Go gofmt(官方) gofmt -l -w ./ IDE 保存时自动格式化;CI 阶段 gofmt -d . 检查差异
Go goimports(增强版) goimports -l -w ./ 在 gofmt 基础上自动管理 import 分组与排序
Python black(官方推荐) black --line-length 88 ./ pre-commit hook;CI 阶段 black --check .
Python isort(import 排序) isort --profile black ./ 配合 black 使用,确保 import 顺序一致
避坑提示:不要使用 gofmt -r 做全局重写规则,除非你完全理解 AST 变换副作用。Python 项目中 black 与 flake8 的 max-line-length 必须保持一致(通常 88)。

4.2 命名规范

命名是代码中最频繁的沟通载体。Exporter 代码中命名应自描述、无歧义、符合语言惯例。

4.2.1 Go 命名规范

  • 包名:小写、单数、无下划线(如 collector、metrics)。
  • 导出标识符:首字母大写(如 CollectMetrics、ExporterConfig)。
  • 未导出标识符:首字母小写,驼峰式(如 metricCache、scrapeDuration)。
  • 接口名:以 -er 结尾(如 Collector、Scraper)。
  • 缩写词:全大写或全小写,保持一致性(如 HTTPClient 而非 HttpClient)。

4.2.2 Python 命名规范

  • 模块/包名:全小写、下划线分隔(如 exporter_base.py、metric_registry)。
  • 类名:驼峰式、首字母大写(如 CustomCollector、ExporterConfig)。
  • 函数/方法名:全小写、下划线分隔(如 collect_metrics()、_build_description())。
  • 常量:全大写、下划线分隔(如 DEFAULT_PORT、MAX_RETRY)。
  • 私有属性:单下划线前缀(如 _internal_state)。
Exporter 特有注意:Metric 名称(如 node_cpu_seconds_total)遵循 Prometheus 命名规范,不要与代码内部变量命名混淆。代码变量用 cpuSecondsTotal(Go)或 cpu_seconds_total(Python)均可,但 Prometheus 输出必须使用下划线格式。

4.3 注释规范

注释解释“为什么”而非“是什么”。Exporter 代码中注释应聚焦于采集逻辑、指标含义、边界条件。

注释类型 Go 写法 Python 写法 说明
包/模块注释 // Package collector implements ... """This module provides ...""" 位于文件头部,描述整体职责
导出类型/函数注释 // CollectMetrics gathers ...(以标识符开头) docstring 紧接定义,用 """ 包裹 必须包含参数、返回值、可能的错误
内部逻辑注释 // 此处使用指数退避避免上游过载 # 此处使用指数退避避免上游过载 解释复杂算法或非显而易见的选择
TODO/FIXME // TODO(owner): 需要处理超时场景 # TODO(owner): 需要处理超时场景 附带责任人,避免永久遗留
// Go 注释示例:导出函数注释
// CollectMetrics 执行一次完整的指标采集循环。
// 它遍历所有注册的 SubCollector,调用其 Collect 方法,
// 并将结果写入 MetricFamily 切片。
// 如果任何 SubCollector 返回错误,该错误会被包装后返回,
// 但已采集的部分指标仍会保留在结果中。
func CollectMetrics(registry *Registry) ([]*MetricFamily, error) {
    // ...
}
# Python 注释示例:模块与类 docstring
"""Custom collector for PostgreSQL replication lag.

This collector connects to the specified PostgreSQL instance
and exposes replication delay metrics in seconds.
"""

class ReplicationLagCollector:
    """Collector for replication lag metrics.

    Args:
        dsn: PostgreSQL connection string.
        timeout: query timeout in seconds.

    Raises:
        ConnectionError: if unable to establish initial connection.
    """
    def __init__(self, dsn: str, timeout: int = 5):
        ...

4.4 错误处理规范

Exporter 运行在无人值守的生产环境,错误处理必须做到:不吞没关键错误、不泄露敏感信息、不导致僵尸进程。

4.4.1 Go 错误处理

  • 始终检查错误:使用 if err != nil 模式,不要用 _ 忽略可能失败的调用。
  • 错误包装:使用 fmt.Errorf("operation: %w", err) 保留原始错误链。
  • 区分临时性与永久性错误:临时错误可重试,永久错误应记录并跳过当前采集周期。
  • 不要 panic:Exporter 中 panic 会导致整个进程退出,应使用 recover 保护顶层采集入口。

4.4.2 Python 错误处理

  • 精确捕获异常:避免裸 except:,应捕获 ConnectionError、TimeoutError 等具体类型。
  • 使用日志记录:用 logging.exception() 记录异常堆栈,不要用 print()。
  • 采集失败不影响其他指标:单个指标采集失败应记录错误并继续,而非中断整个 Exporter。
  • 上下文管理器:使用 with 语句管理连接、文件句柄,确保资源释放。
Exporter 错误处理黄金法则:采集作业中,永远不要因为一个上游端点超时而导致整个 Exporter 崩溃。使用超时控制、熔断机制和独立的 goroutine/协程隔离故障域。

4.5 规范全景图

以下 SVG 展示了 Exporter 代码规范从工具链到运行时的完整覆盖范围,帮助开发者建立全局视角。

Exporter 代码规范全景图 格式化工具 gofmt / black Import 管理 goimports / isort Lint 检查 golangci-lint / flake8 CI 门禁 pre-commit / GitHub Actions 命名规范 包名 / 类型 / 函数 / 变量 / 常量 Go: 驼峰 + 导出大写 | Python: 下划线 + 类驼峰 注释规范 包注释 / 导出注释 / 内部注释 / TODO 解释 Why 而非 What,聚焦采集逻辑 错误处理规范 Go: 显式检查 err / 错误链包装 / 避免 panic / 区分临时与永久错误 Python: 精确捕获 / logging.exception / 采集隔离 / with 资源管理 规范目标:可读性 → 可维护性 → 可审计性 → 生产可靠性

4.6 规范落地检查清单

在提交 Exporter 代码前,建议逐项核对以下清单,确保规范完整落地。

检查项 Go 要求 Python 要求 验证方式
格式化 gofmt -d . 无 diff black --check . 通过 CI 阶段自动执行
Import 排序 goimports 无 diff isort --check-only . 通过 pre-commit hook
导出标识符注释 所有导出类型/函数有注释 所有 public 类/函数有 docstring lint 规则检查
错误检查 无忽略的 err 返回值 无裸 except: 静态分析工具
资源释放 defer 关闭连接/文件 with 语句管理资源 代码审查
采集隔离 单个 collector panic 不影响全局 单个指标异常不中断采集循环 单元测试 + 集成测试
推荐实践:在项目根目录放置 .golangci.yml 或 .flake8 配置文件,并在 CI 中集成规范检查。对于团队新成员,建议使用 pre-commit 框架在本地提交前自动修复格式问题,降低人工审查负担。