OpenMetadata设置数据质量规则,并通过钉钉告警

本文重点讲解如何将OpenMetadata的异常提醒通过Webhook发送到钉钉,设置数据质量规则较简单,看下图即可。有一些规则,也可以自定义SQL。

设置好规则后,添加提醒。

目的地选择 webhook,注意url不能是内网

OpenMetadata 不支持直接发钉钉消息 ,它只能发通用的 HTTP Webhook(JSON 格式)。而钉钉机器人有自己的消息格式要求(markdown 结构、签名验证等)。

需要写个脚本充当中间层
OpenMetadata → 钉钉的 Webhook 转发服务

复制代码
OpenMetadata 告警触发
       ↓
POST http://xxx:8787/dingtalk
       ↓
解析 OpenMetadata 的 JSON 数据
提取:表名、规则名、状态、结果、时间
       ↓
组装成钉钉 markdown 消息格式
计算 HMAC 签名(防伪造)
       ↓
POST https://oapi.dingtalk.com/robot/send(钉钉官方接口)
       ↓
钉钉群收到告警消息

核心功能总结:

  • 格式转换:把 OpenMetadata 的通用 JSON 转成钉钉能识别的 markdown 消息
  • 签名计算:钉钉加签安全模式需要 HMAC-SHA256 签名,脚本自动计算
  • 字段提取:从复杂的 OpenMetadata 事件数据里提取关键信息(表名、状态、检测结果等)展示给人看

下面是python代码:

python 复制代码
from flask import Flask, request
import requests, json, time, hmac, hashlib, base64, urllib.parse

app = Flask(__name__)

DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=xxx" # 通过钉钉群创建机器人获得,群之间不能共用
DINGTALK_SECRET  = "SECxxx"   # 没开加签则留空字符串

def get_sign():
    timestamp = str(round(time.time() * 1000))
    secret_enc = DINGTALK_SECRET.encode('utf-8')
    string_to_sign = f'{timestamp}\n{DINGTALK_SECRET}'
    hmac_code = hmac.new(secret_enc, string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
    return timestamp, sign

@app.route("/dingtalk", methods=["POST"])
def forward():
    data = request.json or {}
    print("收到数据keys:", list(data.keys()))

    # 兼容两种结构:fieldsUpdated 在顶层 或 在 changeDescription 里
    change_desc = data.get("changeDescription") or data

    new_value = {}
    for field in change_desc.get("fieldsUpdated", []):
        if field.get("name") == "testCaseResult":
            new_value = field.get("newValue", {})
            break

    # entity 可能是 JSON 字符串、字典、或不存在
    entity_raw = data.get("entity", "{}")
    try:
        entity_obj = json.loads(entity_raw) if isinstance(entity_raw, str) else entity_raw
    except:
        entity_obj = {}

    case_fqn = new_value.get("testCaseFQN", entity_obj.get("fullyQualifiedName", "未知"))
    
    # entityFQN 可能不存在,安全取第二段
    entity_fqn = entity_obj.get("entityFQN", "")

    status  = new_value.get("testCaseStatus", "未知")
    result  = new_value.get("result", "")
    ev_ts   = data.get("timestamp", 0)
    ev_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ev_ts / 1000)) if ev_ts else "未知"
    color   = "⚠️" if status in ("Failed", "FAILED") else "✅"

    msg = {
        "msgtype": "markdown",
        "markdown": {
            "title": "数据质量告警",
            "text": (
                f"## {color} 数据质量告警\n\n"
                f"**Case FQN**:`{case_fqn}`\n\n"
                f"**表**:`{entity_fqn}`\n\n"
                f"**结果**:{result}\n\n"
                f"**状态**:{status}\n\n"
                f"**时间**:{ev_time}\n\n"
            )
        }
    }

    print("发送msg:", json.dumps(msg, ensure_ascii=False))

    url = DINGTALK_WEBHOOK
    if DINGTALK_SECRET:
        ts, sign = get_sign()
        url += f"&timestamp={ts}&sign={sign}"

    resp = requests.post(url, json=msg)
    result_json = resp.json()
    print("钉钉返回:", result_json)

    if result_json.get("errcode", 0) != 0:
        return {"code": 500, "body": result_json}, 500

    return {"code": resp.status_code, "body": result_json}

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8787)

如果不通,下图标红pending会有提醒积压,如果报错说明是通的,如500,需看日志。消息格式需符合钉钉要求!

查看相关日志

powershell 复制代码
docker logs openmetadata_server --tail=200 2>&1 | grep -iE "event|alert|webhook|pending|notification|error|exception"
相关推荐
观测云1 天前
观测云集成钉钉 SSO 最佳实践
钉钉·sso·观测云
终端行者1 天前
Jenkins流水线添加企业微信或者钉钉通知 pipeline 如何通过企微/钉钉通知
ci/cd·jenkins·钉钉·企业微信
就叫飞六吧3 天前
钉钉组织架构同步到本地(排除管理员+管理员两版本)
钉钉
小小AK3 天前
钉钉与金蝶云星空无缝集成方案
大数据·人工智能·钉钉
dtsola11 天前
小遥搜索v1.8.0版本更新【钉钉文档+知识库支持】
程序员·钉钉·ai搜索·ai创业·独立开发者·个人开发者·一人公司
医疗信息化王工13 天前
钉钉小程序开发实战:投诉管理系统
小程序·钉钉·开发·投诉管理
医疗信息化王工14 天前
钉钉小程序开发实战:手术查询小程序
小程序·钉钉·手术查询
二进喵14 天前
OpenClaw 接入钉钉完整指南
钉钉
Teable任意门互动14 天前
多维表格本地化部署实践解析 企业如何实现数据自主可控路径
数据库·excel·钉钉·飞书·开源软件