Просмотр исходного кода

checkChannelDemandMatchDataJob

wangyunpeng 1 неделя назад
Родитель
Сommit
78f899632c

+ 6 - 0
core/src/main/java/com/tzld/videoVector/dao/mapper/pgVector/ext/ChannelDemandMatchResultMapperExt.java

@@ -1,5 +1,6 @@
 package com.tzld.videoVector.dao.mapper.pgVector.ext;
 
+import com.tzld.videoVector.model.dto.ChannelDemandMatchGroupCount;
 import com.tzld.videoVector.model.po.pgVector.ChannelDemandMatchResult;
 import java.util.List;
 import org.apache.ibatis.annotations.Param;
@@ -13,4 +14,9 @@ public interface ChannelDemandMatchResultMapperExt {
      * 批量插入匹配结果
      */
     int batchInsert(@Param("list") List<ChannelDemandMatchResult> list);
+
+    /**
+     * 按渠道、需求策略、匹配手段、维度分组统计当日数据量
+     */
+    List<ChannelDemandMatchGroupCount> groupCountByDt(@Param("dt") String dt);
 }

+ 113 - 2
core/src/main/java/com/tzld/videoVector/job/ChannelDemandMatchCheckJob.java

@@ -1,6 +1,9 @@
 package com.tzld.videoVector.job;
 
+import com.alibaba.fastjson.JSONObject;
 import com.tzld.videoVector.dao.mapper.pgVector.ChannelDemandMatchResultMapper;
+import com.tzld.videoVector.dao.mapper.pgVector.ext.ChannelDemandMatchResultMapperExt;
+import com.tzld.videoVector.model.dto.ChannelDemandMatchGroupCount;
 import com.tzld.videoVector.model.po.pgVector.ChannelDemandMatchResultExample;
 import com.tzld.videoVector.util.feishu.FeishuMessageSender;
 import com.xxl.job.core.biz.model.ReturnT;
@@ -11,6 +14,8 @@ import org.springframework.stereotype.Component;
 import javax.annotation.Resource;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 渠道需求匹配结果每日数据检查Job
@@ -23,6 +28,9 @@ public class ChannelDemandMatchCheckJob {
     @Resource
     private ChannelDemandMatchResultMapper resultMapper;
 
+    @Resource
+    private ChannelDemandMatchResultMapperExt resultMapperExt;
+
     /**
      * 飞书机器人webhook ID
      */
@@ -37,6 +45,13 @@ public class ChannelDemandMatchCheckJob {
         String dt = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
         log.info("开始检查 channel_demand_match_result 表当日数据, dt={}", dt);
 
+        // 按维度分组统计,通过飞书互动表格消息输出
+        List<ChannelDemandMatchGroupCount> groupCounts = resultMapperExt.groupCountByDt(dt);
+        log.info("channel_demand_match_result 表当日({})分组统计, 共 {} 个分组", dt, groupCounts.size());
+        if (!groupCounts.isEmpty()) {
+            sendGroupCountTable(dt, groupCounts, true);
+        }
+
         try {
             ChannelDemandMatchResultExample example = new ChannelDemandMatchResultExample();
             example.createCriteria().andDtEqualTo(dt);
@@ -48,12 +63,12 @@ public class ChannelDemandMatchCheckJob {
                 String alertMsg = String.format(
                         "【渠道需求匹配告警】channel_demand_match_result 表当日(%s)暂无数据,请检查 channelDemandMatchJob 执行状态。", dt);
                 FeishuMessageSender.sendWebHookMessage(FEISHU_ROBOT_ID, alertMsg);
-                log.warn("channel_demand_match_result 表当日无数据,已发送飞书报警, dt={}", dt);
+                log.warn("channel_demand_match_result 表当日无数据,已发送飞书报警, dt={} ,<at user_id=\"g6732afb\">王云鹏</at>", dt);
             } else if (count < 100000) {
                 String alertMsg = String.format(
                         "【渠道需求匹配告警】channel_demand_match_result 表当日(%s)数据量不足,当前仅 %d 条(阈值 100000),请关注。", dt, count);
                 FeishuMessageSender.sendWebHookMessage(FEISHU_ROBOT_ID, alertMsg);
-                log.warn("channel_demand_match_result 表当日数据量不足,已发送飞书报警, dt={}, count={}", dt, count);
+                log.warn("channel_demand_match_result 表当日数据量不足,已发送飞书报警, dt={}, count={} ,<at user_id=\"g6732afb\">王云鹏</at>", dt, count);
             }
 
             return ReturnT.SUCCESS;
@@ -62,4 +77,100 @@ public class ChannelDemandMatchCheckJob {
             return new ReturnT<>(ReturnT.FAIL_CODE, "检查失败: " + e.getMessage());
         }
     }
+
+    /**
+     * 发送分组统计表格到飞书(interactive 消息)
+     */
+    private void sendGroupCountTable(String dt, List<ChannelDemandMatchGroupCount> groupCounts, boolean atAll) {
+        // 构建列定义
+        List<JSONObject> columns = new ArrayList<>();
+        columns.add(createColumn("channel_name", "渠道", "text"));
+        columns.add(createColumn("demand_strategy", "需求策略", "text"));
+        columns.add(createColumn("match_method", "匹配手段", "text"));
+        columns.add(createColumn("dimension", "维度", "text"));
+        columns.add(createColumn("count", "数量", "text"));
+
+        // 构建行数据
+        List<JSONObject> rows = new ArrayList<>();
+        for (ChannelDemandMatchGroupCount gc : groupCounts) {
+            JSONObject row = new JSONObject();
+            row.put("channel_name", nullToEmpty(gc.getChannelName()));
+            row.put("demand_strategy", nullToEmpty(gc.getDemandStrategy()));
+            row.put("match_method", nullToEmpty(gc.getMatchMethod()));
+            row.put("dimension", nullToEmpty(gc.getDimension()));
+            row.put("count", String.valueOf(gc.getCount()));
+            rows.add(row);
+        }
+
+        // 构建飞书 interactive card
+        JSONObject card = buildTableCard("渠道需求匹配分组统计 (" + dt + ")", columns, rows, atAll);
+        JSONObject bodyParam = new JSONObject();
+        bodyParam.put("msg_type", "interactive");
+        bodyParam.put("card", card);
+        FeishuMessageSender.sendWebHookMessage(FEISHU_ROBOT_ID, bodyParam);
+    }
+
+    private JSONObject createColumn(String name, String displayName, String dataType) {
+        JSONObject column = new JSONObject();
+        column.put("name", name);
+        column.put("display_name", displayName);
+        column.put("data_type", dataType);
+        column.put("width", "auto");
+        column.put("horizontal_align", "left");
+        column.put("vertical_align", "top");
+        return column;
+    }
+
+    private JSONObject buildTableCard(String title, List<JSONObject> columns, List<JSONObject> rows, boolean atAll) {
+        JSONObject card = new JSONObject();
+
+        // header
+        JSONObject header = new JSONObject();
+        header.put("template", "blue");
+        JSONObject titleObj = new JSONObject();
+        titleObj.put("content", title);
+        titleObj.put("tag", "plain_text");
+        header.put("title", titleObj);
+        card.put("header", header);
+
+        // elements
+        List<JSONObject> elements = new ArrayList<>();
+
+        JSONObject tableElement = new JSONObject();
+        tableElement.put("tag", "table");
+        tableElement.put("page_size", rows.size());
+        tableElement.put("row_height", "low");
+
+        JSONObject headerStyle = new JSONObject();
+        headerStyle.put("text_align", "left");
+        headerStyle.put("text_size", "normal");
+        headerStyle.put("background_style", "none");
+        headerStyle.put("text_color", "grey");
+        headerStyle.put("bold", true);
+        headerStyle.put("lines", 1);
+        tableElement.put("header_style", headerStyle);
+
+        tableElement.put("columns", columns);
+        tableElement.put("rows", rows);
+
+        elements.add(tableElement);
+
+        if (atAll) {
+            JSONObject atAllElement = new JSONObject();
+            atAllElement.put("tag", "div");
+            JSONObject atAllElementText = new JSONObject();
+            atAllElementText.put("content", "<at id=all></at>");
+            atAllElementText.put("tag", "lark_md");
+            atAllElement.put("text", atAllElementText);
+            elements.add(atAllElement);
+        }
+
+        card.put("elements", elements);
+
+        return card;
+    }
+
+    private String nullToEmpty(String value) {
+        return value == null ? "" : value;
+    }
 }

+ 16 - 0
core/src/main/java/com/tzld/videoVector/model/dto/ChannelDemandMatchGroupCount.java

@@ -0,0 +1,16 @@
+package com.tzld.videoVector.model.dto;
+
+import lombok.Data;
+
+/**
+ * channel_demand_match_result 表分组统计结果
+ */
+@Data
+public class ChannelDemandMatchGroupCount {
+
+    private String channelName;
+    private String demandStrategy;
+    private String matchMethod;
+    private String dimension;
+    private Long count;
+}

+ 12 - 0
core/src/main/resources/mapper/pgVector/ext/ChannelDemandMatchResultMapperExt.xml

@@ -38,4 +38,16 @@
       #{item.matchGeneralizedElement,jdbcType=VARCHAR}, #{item.matchGeneralizedPointType,jdbcType=VARCHAR})
     </foreach>
   </insert>
+
+  <select id="groupCountByDt" resultType="com.tzld.videoVector.model.dto.ChannelDemandMatchGroupCount">
+    SELECT channel_name     AS channelName,
+           demand_strategy  AS demandStrategy,
+           match_method     AS matchMethod,
+           dimension,
+           COUNT(1)         AS count
+    FROM channel_demand_match_result
+    WHERE dt = #{dt}
+    GROUP BY channel_name, demand_strategy, match_method, dimension
+    ORDER BY channel_name, demand_strategy, match_method, dimension
+  </select>
 </mapper>