ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Telegraf webhooks GitHub 输入插件:采集 GitHub 事件指标的完整配置与实现解析

Telegraf webhooks GitHub 输入插件:采集 GitHub 事件指标的完整配置与实现解析 Telegraf webhooks GitHub 输入插件采集 GitHub 事件指标的完整配置与实现解析【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf本文以 Telegraf 的webhooks服务输入插件中的 GitHub 子模块为主线完整讲解如何配置插件与 GitHub Webhook、各事件如何被转换为github_webhooks指标含全部 22 类事件的 Tag/Field 映射、以及 HMAC 签名与 Basic Auth 两种安全校验机制并结合 github_webhooks.go 与 github_webhooks_models.go 的源码还原从 HTTP 请求到指标产出的完整调用链帮助读者既能照做配置也能读懂底层实现。一、插件定位GitHub 事件如何进入 Telegrafwebhooks是 Telegraf 的一个Service Input 插件不同于按interval周期采集的普通输入插件它在后台启动一个 HTTP 服务监听端口等待外部系统GitHub、Rollbar、Mandrill 等主动推送事件。插件支持注册多个 webhook 监听器完整列表见 webhooks READMEArtifactory、Filestack、Github、Mandrill、Papertrail、Particle、Rollbar。GitHub 子模块位于 plugins/inputs/webhooks/github/其目录下的 README.md 即本插件的官方文档定义了每个 GitHub 事件落地为哪些 Tag 与 Field。作为 Service Input它有两个使用上的关键特性引自 webhooks README全局或插件级的interval设置对它不生效--test、--test-wait、--once等 CLI 选项可能不会为它产生输出。插件的注册逻辑在 webhooks.goinit()中将webhooks注册到输入插件注册表Start()中为每个配置了子表如[inputs.webhooks.github]的 webhook 调用其Register()方法挂到gorilla/mux路由上然后启动 HTTP Server 监听service_address。二、配置说明sample.conf 全量解读GitHub webhook 的配置嵌在[[inputs.webhooks]]子表内官方示例配置见 sample.conf# A Webhooks Event collector [[inputs.webhooks]] ## Address and port to host Webhook listener on service_address :1619 ## Maximum duration before timing out read of the request # read_timeout 10s ## Maximum duration before timing out write of the response # write_timeout 10s [inputs.webhooks.github] path /github # secret ## HTTP basic auth #username #password 各配置项含义如下参数解析对应 webhooks.go 中的Webhooks结构体配置项所属层级默认值说明service_address[[inputs.webhooks]]:1619webhook 监听器的地址与端口所有子 webhook 共用此服务read_timeout/write_timeout[[inputs.webhooks]]10s请求读取/响应写出的超时。从源码看Start() 中当配置值小于 1 秒时会回退到defaultReadTimeout/defaultWriteTimeout均为 10 秒path[inputs.webhooks.github]/githubGitHub 事件的接收路径即 Payload URL 的末尾路径secret[inputs.webhooks.github]空用于校验 GitHub 请求 HMAC 签名的密钥详见第四节username/password[inputs.webhooks.github]空可选的 HTTP Basic Auth 凭据path字段决定了 GitHub 侧 Payload URL 的最后一节secret与 Basic Auth 两项均可省略不配置时对应校验被跳过。三、GitHub 侧 Webhook 配置步骤按照 github/README.md 的指引在 GitHub 上完成对接只需四步打开组织的设置页github.com/{my_organization}进入Settings Webhooks Add webhookPayload URL填http://my_ip:1619/github其中端口1619对应service_address/github对应pathContent type选application/json在 “Which events would you like to trigger this webhook?” 一节选择Send me everything全部事件。配置完成后所有被识别的事件默认写入github_webhooksmeasurement。需要说明的是文档中提及可通过measurement_name自定义测量名但从当前源码看measurement 名被固定为常量meas github_webhooks见 github_webhooks_models.go上报时也是硬编码的github_webhooks见 github_webhooks.go。因此在当前仓库版本中应以github_webhooks为准。此外文档还指出可以配置一个secret让 Telegraf 用它验证请求的真实性——这是该插件最核心的安全能力下面从源码角度展开。四、请求处理流程从 HTTP 请求到指标GitHub 子插件的全部 HTTP 逻辑集中在 github_webhooks.go 的Webhook结构体中。4.1 路由注册Register()L26-L32把eventHandler以POST方法绑定到配置的Path上并记录启动日志Started the webhooks_github on pathfunc (gh *Webhook) Register(router *mux.Router, acc telegraf.Accumulator, log telegraf.Logger) { router.HandleFunc(gh.Path, gh.eventHandler).Methods(POST) ... }Webhook结构体内嵌了auth.BasicAuth来自 plugins/common/auth/basic_auth.go这正是配置中username/password的落点。4.2 事件处理器与校验顺序eventHandlerL34-L66的处理顺序和返回码如下Basic Auth 校验调用内嵌的gh.Verify(r)失败则返回401 Unauthorized。从 BasicAuth.Verify 的源码看只有当username和password都为空时才直接放行返回 true一旦配置了任一项即要求请求携带正确的Authorization: Basic头且比较使用crypto/subtle.ConstantTimeCompare做常量时间比较以防时序侧信道。读取请求体读取出错返回400 Bad Request。签名校验仅当配置了Secret时才执行checkSignature()见下小节校验失败会记录错误日志Fail to check the github webhook signature并返回400。事件分发newEvent()根据请求头X-Github-Event将 JSON 载荷反序列化为对应的事件结构体失败返回400。产出指标事件结构体调用newMetric()得到指标后通过acc.AddFields(github_webhooks, fields, tags, time)提交最终返回200 OK。4.3 支持的事件类型newEvent()L84-L137是一个显式 switch 分发支持以下 22 种事件加上被静默忽略的pingcommit_comment、create、delete、deployment、deployment_status、fork、gollum、issue_comment、issues、member、membership、page_build、ping、public、pull_request、pull_request_review_comment、push、release、repository、status、team_add、watch、workflow_job、workflow_run。两个值得注意的行为ping事件GitHub 在创建 Webhook 时会发送ping测试请求。源码中该分支直接return nil, nil——不报错也不产生指标处理器最终返回 200因此新配置的 webhook 能通过 GitHub 的连通性测试未识别事件返回newEventError{Not a recognized event type}对应 HTTP400且不会产出任何指标。4.4 签名校验HMAC-SHA1GitHub Webhook 的X-Hub-Signature头为 HMAC-SHA1 摘要。Telegraf 的实现见 L139-L150func checkSignature(secret string, data []byte, signature string) bool { return hmac.Equal([]byte(signature), []byte(generateSignature(secret, data))) } func generateSignature(secret string, data []byte) string { mac : hmac.New(sha1.New, []byte(secret)) if _, err : mac.Write(data); err ! nil { return err.Error() } result : mac.Sum(nil) return sha1 hex.EncodeToString(result) }即用配置的secret作为密钥、请求体原文作为数据计算 HMAC-SHA1加上sha1前缀后与请求头比较比较使用hmac.Equal。源码注释中显式保留了 SHA-1 的使用附nolint:gosec因为这是 GitHub 协议本身要求的算法而非插件自选。对应的单测在 github_webhooks_test.go 中验证了签名正确时通过、密钥不匹配时拒绝TestEventWithSignatureSuccess/TestEventWithSignatureFailL125-L131则覆盖了完整请求链路上的 200/400 行为。安全建议secret与 Basic Auth 是两道可叠加的防线若监听地址暴露在公网建议至少配置其中一项。五、指标映射总览Tag 与 Field 的设计模式github/README.md 用统一格式描述每个事件落地后的数据结构# TAGS * tagKey tagValue type # FIELDS * fieldKey fieldValue type其中 Tag/Field 的取值来源指向入站 JSON 对象中的路径。从 github_webhooks_models.go 的源码看所有事件结构体都共享两类公共子结构type repository struct { Repository string json:full_name Private bool json:private Stars int json:stargazers_count Forks int json:forks_count Issues int json:open_issues_count } type sender struct { User string json:login Admin bool json:site_admin }这解释了文档中几乎所有事件共享同一组基础 Tagevent、repository、private、user、admin与基础 Fieldstars、forks、issues的原因它们分别来自X-Github-Event请求头、event.repository.full_name、event.repository.private、event.sender.login、event.sender.site_admin以及repository子结构里的三个计数字段。每个事件结构体实现newMetric()接口统一通过metric.New(meas, tags, fields, time.Now())构造指标。六、全部事件的 Tag/Field 明细以下按 github/README.md 原文逐事件完整列出值来源为入站 JSON 路径。除特别标注外eventTag 均取自headers[X-Github-Event]。commit_commentTagseventheaders[X-Github-Event] (string)、repositoryevent.repository.full_name (string)、privateevent.repository.private (bool)、userevent.sender.login (string)、adminevent.sender.site_admin (bool)Fieldsstarsevent.repository.stargazers_count (int)、forksevent.repository.forks_count (int)、issuesevent.repository.open_issues_count (int)、commitevent.comment.commit_id (string)、commentevent.comment.body (string)create / delete两者映射完全一致。Tags同上述基础 5 项event分别为create/deleteFields基础 3 项 refevent.ref (string)、refTypeevent.ref_type (string)deploymentTags基础 5 项Fields基础 3 项 commitevent.deployment.sha (string)、taskevent.deployment.task (string)、environmentevent.deployment.environment (string)、descriptionevent.deployment.description (string)deployment_statusTags基础 5 项注意从 源码 看该事件的eventTag 实际被写死为字符串delete与文档标题的deployment_status不一致属于源码中的笔迹使用event做过滤时需留意Fieldsdeployment事件的 7 项 depStateevent.deployment_status.state (string)、depDescriptionevent.deployment_status.description (string)forkTags基础 5 项Fields基础 3 项 forkeeevent.forkee.repository (string)源码中该 Field 的实际键名为fork见 forkEvent.newMetric以源码为准gollumTags基础 5 项Fields仅基础 3 项stars/forks/issues。源码注释中标明了对pages数组暂不处理gollumEvent.newMetric。issue_commentTags基础 5 项 issueevent.issue.number (int)Fields基础 3 项 titleevent.issue.title (string)、commentsevent.issue.comments (int)、bodyevent.comment.body (string)issuesTags基础 5 项 issueevent.issue.number (int)、actionevent.action (string)源码中eventTag 的值为issue见 issuesEvent.newMetricFields基础 3 项 titleevent.issue.title (string)、commentsevent.issue.comments (int)memberTags基础 5 项Fields基础 3 项 newMemberevent.sender.login (string)、newMemberStatusevent.sender.site_admin (bool)源码实际取自event.member子结构见 memberEvent.newMetric文档标注为 sender以源码为准membershipTagseventheaders[X-Github-Event]、userevent.sender.login、adminevent.sender.site_admin、actionevent.action该事件无 repository 相关 TagFieldsnewMemberevent.sender.login (string)、newMemberStatusevent.sender.site_admin (bool)源码实际取自event.member子结构page_buildTags基础 5 项Fields仅基础 3 项publicTags基础 5 项Fields仅基础 3 项pull_requestTags基础 5 项 actionevent.action (string)、prNumberevent.pull_request.number (int)Fields基础 3 项 stateevent.pull_request.state (string)、titleevent.pull_request.title (string)、commentsevent.pull_request.comments (int)、commitsevent.pull_request.commits (int)、additionsevent.pull_request.additions (int)、deletionsevent.pull_request.deletions (int)、changedFilesevent.pull_request.changed_files (int)pull_request_review_commentTags基础 5 项 actionevent.action (string)、prNumberevent.pull_request.number (int)Fieldspull_request事件的 10 项 commentFileevent.comment.file (string)、commentevent.comment.body (string)源码中commentFile取自 JSON 的path字段见 pullRequestReviewComment 结构体pushTags基础 5 项Fields基础 3 项 refevent.ref (string)、beforeevent.before (string)、afterevent.after (string)releaseTags基础 5 项Fields基础 3 项 tagNameevent.release.tag_name (string)repositoryTags基础 5 项Fields仅基础 3 项statusTags基础 5 项Fields基础 3 项 commitevent.sha (string)、stateevent.state (string)team_addTags基础 5 项Fields基础 3 项 teamNameevent.team.name (string)watchTags基础 5 项注意从 源码 看eventTag 被写死为delete同样属于源码笔迹Fields仅基础 3 项workflow_jobTagsevent、actionevent.action、repository、private、user、admin基础项nameevent.workflow_job.name (string)、conclusionevent.workflow_job.conclusion (string)FieldsField来源条件run_attemptevent.workflow_job.run_attempt (int)始终queue_timestarted_at − created_at毫秒仅action in_progress时计算run_timecompleted_at − started_at毫秒仅action completed时计算head_branchevent.workflow_job.head_branch (string)始终run_idevent.workflow_job.run_id (int)始终计算逻辑见 workflowJobEvent.newMetric不满足条件时对应时间字段为 0。workflow_runTags基础 5 项 action、nameevent.workflow_run.name、conclusionevent.workflow_run.conclusionFieldsField来源条件run_attemptevent.workflow_run.run_attempt (int)始终run_timecompleted_at − run_started_at毫秒源码实现为updated_at − run_started_at见 workflowRunEvent.newMetric仅action completed时计算head_branchevent.workflow_run.head_branch (string)始终run_idevent.workflow_run.id (int)始终workflow_job/workflow_run是两类最贴近 CI 监控的事件conclusionrun_time两个组合即可回答“哪个 job/branch 的流水线失败、每次跑多久”的问题。七、测试与验证用仓库自带测试用例回放请求该插件的测试体系完整还原了“真实 GitHub 推送”的场景可以直接作为本地验证模板github_webhooks_mock_json_test.go 为每个事件提供了贴近 GitHub 真实 payload 的完整 JSON 样例3500 行例如commitCommentEventJSON()包含真实的 repository/sender 嵌套结构github_webhooks_test.go 用httptest构造带X-Github-Event请求头的 POST 请求直接调用eventHandler覆盖全部 22 种事件 ping签名链路有独立断言TestCheckSignatureSuccessL189-L193验证密钥my_little_secret与 bodyrandom-signature-body对应sha13dca279e731c97c38e3019a075dee9ebbd0a99f0TestWorkflowJob/TestWorkflowRunL133-L187以完整断言钉死了 workflow 事件产出的 Tag/Field 值如run_time: 27000、run_id: 12537003369是核对时间计算逻辑的权威依据。若需在自己的环境复现最小验证方式是配置插件后curl -X POST -H X-Github-Event: ping -d http://host:1619/github应得到 HTTP 200 且不产生指标随后在 GitHub 设置页保存 webhook 时触发的 ping 同样会被静默接受。八、部署注意事项小结端口与路径对齐Payload URL 的端口必须等于service_address默认 1619路径必须等于path默认/github两者任一不匹配都会收不到事件安全配置公网暴露时建议同时启用secretHMAC 签名或 Basic Auth两者独立生效签名失败返回 400、认证失败返回 401超时read_timeout/write_timeout小于 1 秒的配置会被强制回退为 10 秒不要期望亚秒级超时事件过滤插件对“全部事件”做统一落库若只关心 CI 或 PR 指标可配合 Telegraf 的 processor/filter见 CONFIGURATION.md在采集端按eventTag 过滤减少存储压力源码笔迹提醒deployment_status与watch事件的eventTag 在源码中被写为deleteissues事件被写为issuefork事件的字段键为fork而非forkee编写查询时建议先用SELECT * FROM github_webhooks LIMIT 1核对实际落库的键值。【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表