DataHub 摄取任务遥测上报框架(Reporting Framework)实战与源码解析
【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub
导读
本文围绕 DataHub 元数据摄取(ingestion)管线中的Reporting Framework(遥测上报框架)展开,讲解如何通过reporting配置项把每次摄取任务运行(job run)的遥测数据(telemetry)上报到 DataHub 后端或其他目的地,用于监控、审计与排障。读完本文,你将掌握:在 recipe 中配置datahub上报 Provider 与pipeline_name的正确姿势、服务端statefulIngestion能力的前置检查方法、以及如何基于PipelineRunListener接口开发自定义上报 Provider 并注册为 DataHub 插件。
DataHub 摄取遥测上报框架是什么
DataHub 的 reporting framework 允许在摄取(ingestion)管线中配置一个或多个reporting provider(上报提供者),将每次摄取任务运行的遥测信息发送到外部系统以便监控。它由 DataHub 的stateful ingestion(有状态摄取)框架提供能力支撑,datahub类型的 reporting provider 随标准客户端一起安装,默认把摄取任务遥测上报到 DataHub 后端。
从架构上看,上报机制与"任务/作业"(job)概念绑定:一条摄取管线(pipeline)内的 source 连接器会执行多个 job,每个 job 的运行遥测由 reporting provider 负责保存与检索。遥测数据最终落到 DataHub 后端的timeseries aspect中(即datahubIngestionRunSummary),从而支持按时间维度查询与监控。
前置条件:服务端需具备有状态摄取能力
注意:该功能要求服务端具备statefulIngestion能力,这是 metadata service 版本>= 0.8.20的功能。可以通过访问 GMS 的/config接口检查:
curl http://<datahub-gms-endpoint>/config { models: { }, statefulIngestionCapable: true, # <-- 必须存在且为 true retention: "true", noCode: "true" }只有statefulIngestionCapable字段存在且为true,datahub类型的 reporting provider 才能正常工作。若服务端版本过旧或未开启该能力,上报会失败或静默无效。
在 Recipe 中配置 reporting provider
摄取管线的 reporting providers 是一个配置对象列表,位于管线的reporting配置参数下;每个 reporting provider 配置都是"type + config"键值对。遥测数据会发送给列表中的所有 reporting provider。
YAML recipe 中约定:.表示嵌套字段,[idx]表示对象数组中的第 idx 个元素。
| 字段 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|
reporting[idx].type | ✅ | datahub | 已在 DataHub 中注册的摄取上报 provider 类型。 |
reporting[idx].config | 若在管线级别配置了datahub_api,则使用该配置;否则使用默认的DatahubClientConfig(默认值参见 metadata-ingestion/src/datahub/ingestion/graph/client.py)。 | 初始化 datahub reporting provider 所需的配置。 | |
pipeline_name | ✅ | 摄取管线的名称。作为该管线内每个 job 上报的遥测数据的标识键(identifying key)的一部分。 |
其中pipeline_name至关重要:从源码看,它会参与遥测实体的唯一标识生成。在 datahub_ingestion_run_summary_provider.py 中,generate_unique_key依据source.type、pipeline_name与platform_instance生成标识键,generate_entity_name将其拼装为形如[CLI] {source_type} ({platform_instance}) [{pipeline_name}]的实体名。更改pipeline_name会导致旧的遥测数据无法再与新的运行关联,因此应将其视为长期稳定的标识。
支持的 Source
- 所有基于 SQL 的 source(如 snowflake、bigquery、redshift 等)。
snowflake_usage。
完整示例配置
source: type: "snowflake" config: username: <user_name> password: <password> role: <role> host_port: <host_port> warehouse: <ware_house> # Rest of the source specific params ... # 必填。更改它会导致旧遥测数据的关联丢失。 pipeline_name: "my_snowflake_pipeline_1" # 管线级别的 datahub_api 配置。 datahub_api: # 可选。若提供,该配置将被 "datahub" 摄取状态 provider 使用。 server: "http://localhost:8080" sink: type: "datahub-rest" config: server: "http://localhost:8080" reporting: - type: "datahub" # 必填 config: # 可选 datahub_api: # 默认值 server: "http://localhost:8080"该配置的行为要点:
pipeline_name在顶层声明,作为遥测标识键的一部分;- 顶层
datahub_api是可选配置,若存在则同时被datahub摄取状态 provider 与 reporting provider 复用; reporting[0].config.datahub_api可显式覆盖上报目的端;若不写,则回落到管线级datahub_api,再回落为默认DatahubClientConfig;- 上报通道的承载 sink 即管线自身的 sink(
datahub-rest/datahub-kafka)。
管线如何加载与调度 reporting provider(源码视角)
注册表与插件机制
datahub与file两个 reporting provider 通过 Python entry points 注册。注册表定义在 reporting_provider_registry.py:
from datahub.ingestion.api.pipeline_run_listener import PipelineRunListener from datahub.ingestion.api.registry import PluginRegistry reporting_provider_registry = PluginRegistry[PipelineRunListener]() reporting_provider_registry.register_from_entrypoint( "datahub.ingestion.reporting_provider.plugins" )而 entry points 在 metadata-ingestion/setup.py 中声明:
"datahub.ingestion.reporting_provider.plugins": [ "datahub = datahub.ingestion.reporting.datahub_ingestion_run_summary_provider:DatahubIngestionRunSummaryProvider", "file = datahub.ingestion.reporting.file_reporter:FileReporter", ],可以看到类型字符串到实现类的映射:datahub→DatahubIngestionRunSummaryProvider,file→FileReporter。测试 test_plugin_system.py 也验证了注册表中包含["datahub", "file"]两个 provider。
管线初始化与默认上报行为
在 pipeline.py 的_configure_reporting中,上报 provider 的装配逻辑为:
- dry-run 模式下不上报任何遥测数据;
report_to=None表示完全禁用上报;report_to="datahub"(默认值)时,若 recipe 的reporting列表中还没有datahub类型,会自动追加一个默认的{"type": "datahub"}reporter;report_to被指定为其他字符串时,被当作文件名,自动追加{"type": "file", "config": {"filename": report_to}}文件上报器;- 随后遍历
reporting列表,从注册表解析类型并调用reporter_class.create(...)实例化;初始化失败时,若该 reporter 标记了required: true则直接抛错,否则仅记录警告。required字段定义在 pipeline_config.py 的ReporterConfig中。
在管线生命周期中,on_start在摄取开始时被调用(_notify_reporters_on_ingestion_start),on_completion通过 sink 的register_pre_shutdown_callback挂载,在摄取结束、sink 关闭前执行(pipeline.py)。完成回调会根据管线最终状态传入SUCCESS、FAILURE、CANCELLED或UNKNOWN状态码(pipeline.py)。
生命周期接口:PipelineRunListener
所有 reporting provider 必须实现 PipelineRunListener 抽象基类,它定义了三个方法:
class PipelineRunListener(ABC): @abstractmethod def on_start(self, ctx: PipelineContext) -> None: # 摄取启动时的钩子 pass @abstractmethod def on_completion( self, status: str, report: Dict[str, Any], ctx: PipelineContext, ) -> None: # 摄取完成/失败时的钩子 pass @classmethod @abstractmethod def create( cls, config_dict: Dict[str, Any], ctx: PipelineContext, sink: Sink, ) -> "PipelineRunListener": # 创建与初始化 passdatahub 上报 Provider 的内部原理
DatahubIngestionRunSummaryProvider(type 为datahub)是开箱即用的上报实现,构建在datahub_api客户端与 DataHub 后端的timeseries aspect 能力之上,实现在 datahub_ingestion_run_summary_provider.py。
配置项
| 字段 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|
type | ✅ | datahub | 已在 DataHub 中注册的摄取上报 provider 类型。 |
config | 管线级datahub_api配置;否则默认DatahubClientConfig(默认值参见 metadata-ingestion/src/datahub/ingestion/graph/client.py)。 | 初始化 datahub reporting provider 所需的配置。 |
此外,实现中还定义了report_recipe: bool = True(是否将脱敏后的 recipe 上报,可通过config.report_recipe: false关闭)以及config.sink(允许显式指定上报所用的 sink,否则复用管线当前 sink,且要求 sink 必须是datahub-rest或datahub-kafka,否则上报器会被禁用)。
运行时的数据流
- 初始化:根据
pipeline_name、source.type、platform_instance生成唯一标识键与实体名(形如[CLI] snowflake (prod) [my_snowflake_pipeline_1]),并构造dataHubIngestionSource实体的dataHubIngestionSourceInfoaspect(含脱敏 recipe、DataHub 版本号、executor id),异步写入 sink。 - on_start:构造
dataHubExecutionRequest实体的dataHubExecutionRequestInputaspect,记录任务名CLI Ingestion、recipe、版本、请求时间与来源,并通过同步模式(EmitMode.SYNC_PRIMARY)立即写入,保证执行请求先于结果落库。 - on_completion:将运行报告(structured report)与日志缓冲拼接为 summary,通过
SecretMaskingFilter对 secret 进行脱敏后,写入dataHubExecutionRequestResultaspect,包含状态、开始时间、持续时长(durationMs)与结构化报告(StructuredExecutionReportClass,类型CLI_INGEST,JSON content type)。
其中 summary 会被截断到 800,000 字符(_MAX_SUMMARY_SIZE),以确保生成的 MCP(MetadataChangeProposal)不会超过 GMS 的 payload 限制。
遥测数据模型
上报数据的模型为 DatahubIngestionRunSummary.pdl,这是一个timeseries 类型 aspect,包含三类字段:
- 标识与状态:
pipelineName(用户提供的稳定唯一标识,如my_snowflake1-to-datahub)、platformInstanceId(摄取管线运行所针对的实例,如 BigQuery 项目 id、MySQL 主机名等)、runId、runStatus(Succeeded / Skipped / Failed 等)。 - 运行指标:
numWorkUnitsCommitted、numWorkUnitsCreated、numEvents(MCE + MCP 事件数)、numEntities(唯一 entity urn 数)、numAspects、numSourceAPICalls/totalLatencySourceAPICalls、numSinkAPICalls/totalLatencySinkAPICalls、numWarnings、numErrors、numEntitiesSkipped。 - 运行上下文:
config(非敏感的 YAML 配置键值对 JSON 字符串)、custom_summary、softwareVersion、systemHostName、operatingSystemName、numProcessors、totalMemory、availableMemory等主机信息。
正是这些 timeseries 字段,使得每次摄取运行的历史遥测可以在 DataHub 中被检索、聚合与监控,例如按pipelineName与platformInstanceId追踪一段时间内各任务的成功率与耗时变化。
开发者指南:编写自定义上报 Provider
除了开箱即用的datahubprovider,你还可以按照下面的模式为摄取管线接入自定义上报目标(例如本地文件、内部监控系统等)。
步骤一:实现 PipelineRunListener
参考自带的fileprovider —— file_reporter.py。它把结构化运行报告写成 JSON 文件:
class FileReporterConfig(ConfigModel): filename: str format: str = "json" @field_validator("format", mode="after") @classmethod def only_json_supported(cls, v: str) -> str: if v and v.lower() != "json": raise ValueError( f"Format {v} is not yet supported. Only json is supported at this time" ) return von_start为空实现,on_completion将报告通过SecretMaskingFilter脱敏后写入指定文件。配置里format字段目前仅支持json,其他值会在校验阶段直接报错——这说明自定义 provider 应尽可能在配置校验期暴露错误。
步骤二:注册到 entry_points
在 metadata-ingestion/setup.py 的entry_points中加入datahub.ingestion.reporting_provider.plugins键,格式为"<type> = <module路径>:<类名>":
entry_points = { # <snip other keys> "datahub.ingestion.reporting_provider.plugins": [ "datahub = datahub.ingestion.reporting.datahub_ingestion_run_summary_provider:DatahubIngestionRunSummaryProvider", "file = datahub.ingestion.reporting.file_reporter:FileReporter", # 在此追加自定义 provider,例如: # "my_reporter = my_package.my_reporter:MyReporter", ], }注册完成后,PluginRegistry会通过register_from_entrypoint自动发现该类型,用户即可在 recipe 的reporting列表中以type: "my_reporter"引用它。
使用建议与注意事项
- 保持
pipeline_name稳定:它是遥测数据关联的历史键,改名会导致旧的运行遥测无法与后续运行建立关联,也会改变生成的 ingestion source 实体名。 - 先确认服务端能力:在开启
datahubreporting 前,通过curl <gms>/config检查statefulIngestionCapable是否为true;版本低于0.8.20的 metadata service 不支持该功能。 - 上报通道复用管线 sink:
datahubprovider 默认复用管线的datahub-rest/datahub-kafkasink;如果 sink 类型不受支持,上报器会被自动禁用(抛出IgnorableError并被当作非致命问题处理)。 - 敏感信息保护:上报的 recipe 与运行报告会经过
redact_raw_config与SecretMaskingFilter脱敏;如不希望 recipe 被上报,可在 provider 的config中设置report_recipe: false。 - 超大运行报告:summary 会被截断到 800,000 字符以内,避免生成的 MCP 超出 GMS payload 限制;对超长日志应依赖 DataHub 侧的日志检索能力,而非遥测 summary。
- dry-run 模式不会触发任何上报,便于本地调试时避免污染线上遥测数据。
【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考