ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenTelemetry Collector scraperhelper 完全指南:构建定时抓取型 Receiver 的控制器框架

OpenTelemetry Collector scraperhelper 完全指南:构建定时抓取型 Receiver 的控制器框架 OpenTelemetry Collector scraperhelper 完全指南构建定时抓取型 Receiver 的控制器框架【免费下载链接】opentelemetry-collectorOpenTelemetry Collector项目地址: https://gitcode.com/GitHub_Trending/op/opentelemetry-collectorscraperhelper 是 OpenTelemetry Collector 中用于构建「定时抓取型 Receiver」的核心控制器框架它定义了一个 scraper抓取器如何连接并抓取外部数据源并由内置控制器按固定时间间隔调度抓取、聚合数据并传递给下游 Consumer。读完本文你将掌握 scraperhelper 的 ControllerConfig 全部配置项与默认值、ControllerOption 编程接口、抓取调度与错误处理机制以及如何在自己开发的 Receiver 中集成 scraperhelper 并利用其内置可观测性指标。什么是 scraperhelper在 OpenTelemetry Collector 的组件体系中Receiver 负责从外部数据源接收遥测数据。其中一类典型的 Receiver例如各类 Prometheus 风格的指标采集器并不被动等待数据上报而是需要主动按周期连接外部数据源并抓取scrape数据这种模式在 scraper/scraper.go 中被抽象为scraper接口。scraperhelper位于 scraper/scraperhelper就是为这类「抓取型 Receiver」提供的官方辅助库。其核心价值在于提供统一的ControllerConfig配置结构屏蔽抓取周期、启动延迟、超时等通用参数的样板代码提供控制器Controller按配置的collection_interval周期性地调用 scraper 并自动处理调度、并发与生命周期提供ControllerOption机制让开发者以声明式方式注册一个或多个 scraper内置完整可观测性为每次抓取记录指标与 trace span将抓取数据交给下游 Consumer。从架构上可以这样理解 scraperhelper 的分层scraper定义「如何连接并抓取外部数据源」对应 scraper 包 中的scraper.Metrics/scraper.Logs接口scraperhelper负责把若干 scraper 组装成一个标准的receiver.Logs/receiver.Metricscontroller.go内部 controller负责真正的定时调度、启动与关闭internal/controller/controller.go。按照 docs/component-stability.md 中的稳定性定义scraperhelper 当前的稳定性状态为Betametrics 与 logs 信号均可用意味着该组件 API 相对稳定、可放心用于生产组件开发。ControllerConfig抓取控制器的通用配置ControllerConfig是 scraper 控制器接收器可内嵌的通用配置结构。文档说明指出「Scraper controller receivers can embed this struct, instead of receiver.Settings, and extend it with more fields if needed.」——即抓取型 Receiver 在定义自己的 Config 时应当内嵌该结构体而不是receiver.Settings并可继续扩展自己的字段。其字段定义来自 config.schema.yaml具体如下配置项类型默认值说明collection_intervaltime.Duration字符串如1m1m1 分钟抓取器被调度的频率即两次抓取之间的间隔initial_delaytime.Duration1s1 秒抓取器启动后的首次调度延迟任何非正值都视为立即开始timeouttime.Duration0不设置可选值用于设置抓取操作的 context 截止时间deadline默认值与校验规则上述默认值来自生成的配置结构 internal/controller/generated_config.gofunc NewDefaultControllerConfig() ControllerConfig { return ControllerConfig{ CollectionInterval: 1 * time.Minute, InitialDelay: 1 * time.Second, Timeout: 0, } }而校验逻辑位于 internal/controller/config_validation.govar errNonPositiveInterval errors.New(requires positive value) func validateControllerConfig(set *ControllerConfig) (errs error) { if set.CollectionInterval 0 { errs multierr.Append(errs, fmt.Errorf(collection_interval: %w, errNonPositiveInterval)) } if set.Timeout 0 { errs multierr.Append(errs, fmt.Errorf(timeout: %w, errNonPositiveInterval)) } return errs }从源码可以确认三条规则collection_interval必须为正数大于 0否则报错collection_interval: requires positive valuetimeout不能为负数为 0 表示不设置超时initial_delay没有强制校验——负数或 0 会被视为「立即开始」。ControllerConfig通过 generated_config.go 暴露为scraperhelper.ControllerConfig并提供scraperhelper.NewDefaultControllerConfig()工厂函数供 Receiver 在CreateDefaultConfig()中调用。核心 API把 scraper 组装成 Receiverscraperhelper 的最核心编程模型是「选项Option模式」。开发者通过一组ControllerOption声明要抓取的 scraper 及其配置然后调用NewLogsController/NewMetricsController得到标准的receiver.Logs/receiver.Metrics。以下 API 均定义在 controller.go 中。AddMetricsScraper注册一个现成的 Metrics Scraperfunc AddMetricsScraper(t component.Type, sc scraper.Metrics) ControllerOption将已有的scraper.Metrics实例注册进控制器使其按配置的采集间隔被调用。该函数内部会通过scraper.NewFactory构建一个临时的工厂等价于AddFactoryWithConfig的便捷封装。抓取产生的 metrics 会传递给下游 Consumer同时上报可观测性信息。AddFactoryWithConfig注册 Scraper 工厂与配置func AddFactoryWithConfig(f scraper.Factory, cfg component.Config) ControllerOption这是更通用的方式注册一个scraper.Factory及配套的cfg控制器会在初始化阶段调用f.CreateMetrics/f.CreateLogs来创建实际的 scraper 实例。这样可以复用标准工厂的依赖注入流程适合需要按配置动态构造 scraper 的场景。WithTickerChannel测试专用func WithTickerChannel(tickerCh -chan time.Time) ControllerOption允许调用方覆盖控制器内部的 ticker channel从而手动控制每次抓取的触发时机。该函数注释明确指出「This is only expected to be used by tests」——从源码结构看它让测试可以在不等待真实时间流逝的情况下精确驱动抓取循环参考 internal/controller/controller.go 中startScraping对tickerCh的读取逻辑。NewLogsController / NewMetricsControllerfunc NewLogsController(cfg *ControllerConfig, rSet receiver.Settings, nextConsumer consumer.Logs, options ...ControllerOption, ) (receiver.Logs, error) func NewMetricsController(cfg *ControllerConfig, rSet receiver.Settings, nextConsumer consumer.Metrics, options ...ControllerOption, ) (receiver.Metrics, error)两个构造函数分别产出 logs 与 metrics 信号的标准 Receiver。从 controller.go 的实现可以看出它们的统一流程遍历所有ControllerOption收集工厂列表对每个工厂调用controller.GetSettingsinternal/controller/controller.go生成带scrapertype日志字段的scraper.Settings并调用CreateLogs/CreateMetrics创建 scraper用wrapObsMetrics/wrapObsLogs包装 scraper注入遥测埋点将全部 scraper 交给controller.NewController由其统一调度。调度循环与组件生命周期抓取的调度与生命周期管理由 internal/controller/controller.go 中的泛型Controller[T]完成其Start、Shutdown与startScraping三个方法构成了完整闭环。Start启动全部 scraper 并开启调度func (sc *Controller[T]) Start(ctx context.Context, host component.Host) error { for _, scrp : range sc.Scrapers { if err : scrp.Start(ctx, host); err ! nil { return err } } sc.startScraping(ctx) return nil }Start先依次启动所有注册的 scraper任一失败则立即返回错误随后启动抓取循环。startScraping定时抓取的核心循环调度循环internal/controller/controller.go的行为值得仔细推敲func (sc *Controller[T]) startScraping(ctx context.Context) { ctx context.WithoutCancel(ctx) sc.wg.Go(func() { if sc.initialDelay 0 { select { case -time.After(sc.initialDelay): case -sc.done: return } } if sc.tickerCh nil { ticker : time.NewTicker(sc.collectionInterval) defer ticker.Stop() sc.tickerCh ticker.C } for { // 组件启动后立即执行一次抓取 // 而不是等待完整周期后才开始。 _ sc.scrapeFunc(ctx, sc) select { case -sc.done: return default: } select { case -sc.tickerCh: case -sc.done: return } } }) }从这段代码可以提炼出四个关键行为首次抓取立即执行循环体先无条件调用一次scrapeFunc注释明确说明这是「ensure that scrapers start from when the component starts instead of waiting for the full duration to start」——组件启动后立即抓取而不是傻等一个完整的采集周期initial_delay 只影响首次调度initial_delay仅在循环真正开始前生效通过time.After实现其用途是给 scraper 留出初始化缓冲时间避免与 Collector 启动高峰期争抢资源双重 done 检查循环在每次抓取后先做一次非阻塞的done检查再做阻塞的select注释指出这是为了避免「scrapeFunc 执行较慢时ticker 与 done 同时就绪却无法保证及时关闭」的竞态超时通过 context 注入当cfg.Timeout 0时构造函数会包装scrapeFunc为每次抓取创建一个context.WithTimeout截止上下文internal/controller/controller.go超时后抓取会被强制终止。Shutdown优雅关闭Shutdown先close(sc.done)通知调度循环退出并Wait等待其结束随后依次调用所有 scraper 的Shutdown并用multierr.Append聚合所有错误一并返回。数据流与错误处理控制器每次抓取都会经历「抓取 → 聚合 → 消费 → 观测」四个阶段。以 metrics 为例controller.go 中的scrapeMetrics展示了完整逻辑func scrapeMetrics(ctx context.Context, c *controller.Controller[scraper.Metrics], nextConsumer consumer.Metrics) error { var errs []error metrics : pmetric.NewMetrics() for i : range c.Scrapers { md, err : c.Scrapers[i].ScrapeMetrics(ctx) if err ! nil { errs append(errs, err) if !scrapererror.IsPartialScrapeError(err) { continue } } md.ResourceMetrics().MoveAndAppendTo(metrics.ResourceMetrics()) } dataPointCount : metrics.DataPointCount() ctx c.Obsrecv.StartMetricsOp(ctx) err : nextConsumer.ConsumeMetrics(ctx, metrics) c.Obsrecv.EndMetricsOp(ctx, , dataPointCount, err) return errors.Join(append(errs, err)...) }关键点多 scraper 聚合控制器可管理多个 scraper所有抓取结果通过MoveAndAppendTo合并到一份pmetric.Metrics中一次性地传给下游nextConsumer部分失败不丢弃数据利用 scraper/scrapererror 中的PartialScrapeError与IsPartialScrapeError——只有当错误不是部分抓取错误时才跳过该 scraper 的数据若是部分抓取错误则保留已抓取的部分数据继续聚合。这种设计保证了「抓到一个算一个」的容错语义错误聚合所有 scraper 的错误与消费错误通过errors.Join合并为单一返回值方便上层统一处理观测埋点抓取与消费被Obsrecv.StartMetricsOp/EndMetricsOp包裹产出标准的 receiver 观测报告ObsReport。logs 信号的scrapeLogs流程完全对称只是信号类型替换为plog.Logs与LogRecordCount()。内置可观测性抓取指标与追踪scraperhelper 为每次抓取注入了完整的可观测性能力这是它区别于「自己手写抓取循环」的重要优势。其实现位于 obs_metrics.go 与 obs_logs.go遥测指标由 mdatagen 生成见 internal/metadata。内部遥测指标根据 documentation.mdscraperhelper 会对外发出以下 4 个指标当前稳定性级别均为 Alphaotelcol_scraper_errored_log_records无法被成功抓取的 log record 数量。UnitMetric TypeValue TypeMonotonicStability{record}SumInttrueAlphaotelcol_scraper_errored_metric_points无法被成功抓取的 metric point 数量。UnitMetric TypeValue TypeMonotonicStability{datapoint}SumInttrueAlphaotelcol_scraper_scraped_log_records成功抓取的 log record 数量。UnitMetric TypeValue TypeMonotonicStability{record}SumInttrueAlphaotelcol_scraper_scraped_metric_points成功抓取的 metric point 数量。UnitMetric TypeValue TypeMonotonicStability{datapoint}SumInttrueAlpha埋点实现原理在 obs_metrics.go 中可以看到具体的计数与 span 逻辑每个抓取请求对应一个命名 span格式为scraper/scraperID/ScrapeMetrics指标与 span 都会带上receiverreceiverID与scraperscraperID属性方便按组件维度过滤分析抓取成功后累加ScraperScrapedMetricPoints若返回的是PartialScrapeError则通过partialErr.Failed精确记录失败数量numErroredMetrics同时仍把已抓取的md.MetricCount()计入成功数span 上会记录format信号类型、scraped_metric_points、errored_metric_points三个属性抓取出错时 span 状态被置为codes.Error并携带错误信息包装后的 scraper 通过scraper.NewMetrics(scraperFuncs, scraper.WithStart(sc.Start), scraper.WithShutdown(sc.Shutdown))重新构造因此原有 Start/Shutdown 生命周期得以保留。这意味着任何基于 scraperhelper 构建的抓取型 Receiver都自动获得上述指标与追踪能力无需自行实现埋点。实战在自定义 Receiver 中集成 scraperhelper下面是一个将 scraperhelper 集成到抓取型 Metrics Receiver 中的典型用法与 scraper/scraperhelper/controller_test.go 中的测试模式一致。第一步在 Config 中内嵌 ControllerConfigtype Config struct { scraperhelper.ControllerConfig mapstructure:,squash // ... 自己的扩展字段如 endpoint、api_token 等 }第二步在工厂中提供默认配置func createDefaultConfig() component.Config { return Config{ ControllerConfig: scraperhelper.NewDefaultControllerConfig(), // 初始化自己的字段默认值 } }第三步在 CreateMetrics 中组装控制器func createMetricsReceiver( _ context.Context, set receiver.Settings, cfg component.Config, nextConsumer consumer.Metrics, ) (receiver.Metrics, error) { c : cfg.(*Config) // 构造 scraperConnect 用于建立连接Scrape 用于单次抓取 sc : myScraper{cfg: c} metricsScraper, err : scraper.NewMetrics( sc.scrape, // func(ctx) (pmetric.Metrics, error) scraper.WithStart(sc.start), scraper.WithShutdown(sc.shutdown), ) if err ! nil { return nil, err } return scraperhelper.NewMetricsController( c.ControllerConfig, set, nextConsumer, scraperhelper.AddMetricsScraper(component.MustNewType(myreceiver), metricsScraper), ) }这样产出的receiver.Metrics即具备完整的周期性调度、超时控制、生命周期管理与内置可观测性。若需要支持 logs 信号只需将scraper.NewMetrics换成scraper.NewLogs并调用scraperhelper.NewLogsController。测试驱动开发scraperhelper 的测试controller_test.go、internal/controller/controller_test.go覆盖了多 scraper 调度、部分抓取错误、超时、关闭竞态等场景。开发者在为自己的组件编写测试时可以借鉴其模式使用WithTickerChannel注入手动 ticker精确控制抓取时机避免依赖真实时钟构造返回PartialScrapeError的 fake scraper验证「部分失败数据仍被保留」的语义通过nextConsumer捕获实际消费的数据断言抓取结果与调用次数。稳定性与生态位置稳定性scraperhelper 的 metrics 与 logs 信号均为Beta稳定级别见 README.md依据是 docs/component-stability.md 中关于 Beta 的定义功能完备、已验证可依赖其 API。相关生态scraper 接口的底层定义在 scraper/scraper.go错误处理语义依赖 scraper/scrapererror与 scraperhelper 同级的实验性扩展包xscraperhelper见 scraper/scraperhelper/xscraperhelper提供了 profiles 信号等实验能力的支持其内部同样复用internal/controller这套调度核心。总结scraperhelper 以「一个配置结构 一组 ControllerOption 一个调度控制器」的简洁模型把抓取型 Receiver 开发中最容易出错的定时调度、生命周期、错误聚合与可观测性全部标准化。开发者只需聚焦实现scraper的 Connect/Scrape 逻辑即可获得一个生产级的周期性抓取组件——这也正是 Collector 生态中大量抓取型 Receiver 的共同底座。基于 controller.go 与 internal/controller/controller.go 的源码你可以在自己的 Receiver 中安全地依赖这套 Beta 级 API并利用otelcol_scraper_scraped_*与otelcol_scraper_errored_*系列指标快速定位抓取健康度问题。【免费下载链接】opentelemetry-collectorOpenTelemetry Collector项目地址: https://gitcode.com/GitHub_Trending/op/opentelemetry-collector创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表