欢迎来到萧静默的博客

书山有路勤为径,学海无涯苦作舟。

SAP-ABAP-ST22主要内容获取程序

REPORT Z_SAVE_ST22_JOB MESSAGE-ID 00 NO STANDARD PAGE HEADING.
*&---------------------------------------------------------------------*
*&      程序名称:Z_SAVE_ST22_JOB
*&      功能:定时抓取指定时段ST22 DUMP、Z程序异常入库+超阈值邮件告警
*&      参数:P_HOUR=往前几小时;P_LINES=报错频次阈值;S_EMAIL收件邮箱
*&---------------------------------------------------------------------*
TYPES:
  BEGIN OF TYP_COMP,
    GPROGRAM TYPE SYREPID,    "报错程序名
    ERRID    TYPE S380ERRID,  "Runtime Error ID
    GSGUID   TYPE SYSUUID_C,   "唯一GUID
    ERRTYPE  TYPE ZTGETST22_ERRTYPE, "错误分类文本
    TIMES    TYPE STRING,     "报错次数
  END OF TYP_COMP.

*--全局数据定义
DATA:
  IT_ST22  TYPE STANDARD TABLE OF ZTGETST22,
  WA_ST22  TYPE ZTGETST22,
  IT_COMP  TYPE STANDARD TABLE OF TYP_COMP,
  WA_COMP  TYPE TYP_COMP,
  IT_EMAIL TYPE STANDARD TABLE OF TYP_COMP,
  WA_EMAIL TYPE TYP_COMP,
  GV_EMAIL TYPE AD_SMTPADR.

*--选择屏幕
PARAMETERS:
  P_DATE TYPE SY-DATUM.
SELECT-OPTIONS:
  S_EMAIL FOR GV_EMAIL NO INTERVALS. "收件邮箱清单

*----------------------------------------------------------------------*
INITIALIZATION.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
*----------------------------------------------------------------------*
START-OF-SELECTION.
  DATA:
    LV_BTIME TYPE SYUZEIT,
    LV_ETIME TYPE SYUZEIT,
    LV_INT   TYPE INT8,
    LIT_DATE TYPE SNAP_R_DATE,
    LWA_DATE TYPE SNAP_S_DATE,
    LIT_TIME TYPE SNAP_R_TIME,
    LWA_TIME TYPE SNAP_S_TIME.



  LWA_DATE-SIGN   = 'I'.
  LWA_DATE-OPTION = 'EQ'.
  LWA_DATE-LOW    = P_DATE.
  LWA_DATE-HIGH    = SY-DATUM.
  APPEND LWA_DATE TO LIT_DATE.
  PERFORM FRM_GET_DATA TABLES LIT_DATE LIT_TIME.

  CHECK IT_ST22 IS NOT INITIAL AND S_EMAIL[] IS NOT INITIAL.
  PERFORM FRM_FIND_DATA. "统计同程序同错误次数
  CHECK IT_EMAIL[] IS NOT INITIAL.
  PERFORM FRM_SEND_EMAIL. "发送HTML告警邮件

*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DATA
*&---------------------------------------------------------------------*
FORM FRM_GET_DATA TABLES PT_DATE TYPE SNAP_R_DATE
                      PT_TIME TYPE SNAP_R_TIME.
  DATA:
    LIT_SNAP       TYPE SNAP_T_DECODED,
    LWA_SNAP       TYPE SNAP_DECODED,
    LIT_HOST       TYPE SNAP_R_HOST,
    LIT_UNAME      TYPE SNAP_R_UNAME,
    LIT_CLIENT     TYPE SNAP_R_CLIENT,
    LIT_ERRID      TYPE SNAP_R_ERRID,
    LIT_CATE       TYPE SNAP_R_CATEGORY,
    LIT_TABT       TYPE SNAP_R_TAG_ATTR,
    LIT_ATTR       TYPE SNAP_ATTRIBUTES,
    LWA_ATTR       TYPE SNAP_ATTRIBUTE,
    LIT_CATEGORIES TYPE ST22_CATEGORIES,
    LWA_CATEGORIES TYPE STRING,
    LV_INDEX       TYPE I,
    LV_OK          TYPE CHAR1,
    LV_LINES       TYPE I,
    LIT_STR        TYPE TABLE OF STRING,
    LWA_STR        TYPE STRING,
    LIT_0015       TYPE TABLE OF ZTAB0015,
    LWA_0015       TYPE ZTAB0015.

  "调用标准类获取DUMP清单
  CALL METHOD CL_ABAP_SNAP=>GET_RAW_CONTENT
    EXPORTING
      P_R_DATE         = PT_DATE[]
      P_R_TIME         = PT_TIME[]
      P_R_HOST         = LIT_HOST
      P_R_UNAME        = LIT_UNAME
      P_R_CLIENT       = LIT_CLIENT
      P_R_ERRID        = LIT_ERRID
      P_R_CATEGORY     = LIT_CATE
      P_R_TAG_ATTR     = LIT_TABT
    IMPORTING
      P_SNAP_T_DECODED = LIT_SNAP.

  LOOP AT LIT_SNAP INTO LWA_SNAP.
    LIT_ATTR = LWA_SNAP-ATTRIBUTES.
    CLEAR: LV_OK, WA_ST22.

    "=====取AC字段(程序栈)=====
    READ TABLE LIT_ATTR INTO LWA_ATTR WITH KEY ID = 'AC'.
    IF SY-SUBRC = 0.
      SPLIT LWA_ATTR-VALUE AT '/' INTO TABLE LIT_STR.
      LV_LINES = LINES( LIT_STR ).
      READ TABLE LIT_STR INTO LWA_STR INDEX LV_LINES.
      IF LWA_STR(1) = 'Z'.
        LV_OK = 'X'.
        WA_ST22-GPROGRAM = LWA_STR.
        PERFORM FRM_GET_MODULE USING WA_ST22-GPROGRAM CHANGING WA_ST22-ERRMODULE.
      ELSEIF LIT_STR IS INITIAL.
        SPLIT LWA_ATTR-VALUE AT SPACE INTO TABLE LIT_STR.
        LV_LINES = LINES( LIT_STR ).
        READ TABLE LIT_STR INTO LWA_STR INDEX LV_LINES.
        IF LWA_STR(1) = 'Z'.
          LV_OK = 'X'.
          WA_ST22-GPROGRAM = LWA_STR.
          PERFORM FRM_GET_MODULE USING WA_ST22-GPROGRAM CHANGING WA_ST22-ERRMODULE.
        ENDIF.
      ENDIF.
    ENDIF.

    "=====取AM字段(主程序)=====
    READ TABLE LIT_ATTR INTO LWA_ATTR WITH KEY ID = 'AM'.
    IF SY-SUBRC = 0 AND LWA_ATTR-VALUE(1) = 'Z'.
      LV_OK = 'X'.
      WA_ST22-GPROGRAM = LWA_ATTR-VALUE.
      PERFORM FRM_GET_MODULE USING WA_ST22-GPROGRAM CHANGING WA_ST22-ERRMODULE.
    ENDIF.

    "=====取AP字段(包含SAPLZ/Z开头)=====
    READ TABLE LIT_ATTR INTO LWA_ATTR WITH KEY ID = 'AP'.
    IF SY-SUBRC = 0.
      IF LWA_ATTR-VALUE(5) = 'SAPLZ' OR LWA_ATTR-VALUE(1) = 'Z'.
        LV_OK = 'X'.
        WA_ST22-GPROGRAM = LWA_ATTR-VALUE.
        PERFORM FRM_GET_MODULE USING WA_ST22-GPROGRAM CHANGING WA_ST22-ERRMODULE.
      ENDIF.
      "排除CLUR_NW7_SERVER异常
      IF LWA_ATTR-VALUE = 'CLUR_NW7_SERVER===============CP' AND LWA_SNAP-ERRID = 'UNCAUGHT_EXCEPTION'.
        CLEAR LV_OK.
      ENDIF.
    ENDIF.

    CHECK LV_OK = 'X'. "只保留Z程序DUMP

    "生成唯一GUID
    CALL FUNCTION 'GUID_CREATE'
      IMPORTING
        EV_GUID_32 = WA_ST22-GSGUID.

    "填充基础字段
    WA_ST22-ERRDATE  = LWA_SNAP-DATE.
    WA_ST22-ERRTIME  = LWA_SNAP-TIME.
    WA_ST22-HOST     = LWA_SNAP-HOST.
    WA_ST22-OPUNAME  = LWA_SNAP-UNAME.
    WA_ST22-CLIENT   = LWA_SNAP-CLIENT.
    WA_ST22-ERRID    = LWA_SNAP-ERRID.
    WA_ST22-CNAME    = SY-UNAME.
    WA_ST22-DATUM    = SY-DATUM.
    WA_ST22-UZEIT    = SY-UZEIT.

    "关联人员编码表ZTAB0015
    SELECT * INTO CORRESPONDING FIELDS OF TABLE @LIT_0015 FROM ZTAB0015 WHERE UNAME = @WA_ST22-OPUNAME.
    LOOP AT LIT_0015 INTO LWA_0015.
      CONCATENATE WA_ST22-HCODE LWA_0015-HCODE INTO WA_ST22-HCODE SEPARATED BY ','.
    ENDLOOP.
    IF WA_ST22-HCODE IS NOT INITIAL.
      WA_ST22-HCODE = WA_ST22-HCODE+1.
    ENDIF.

    "获取错误分类文本
    CALL FUNCTION 'RS_ST22_GET_DUMP_CATEGORY'
      EXPORTING
        P_NAME     = LWA_SNAP-ERRID
      IMPORTING
        P_CATEGORY = LV_INDEX.
    CALL FUNCTION 'RS_ST22_GET_CATEGORIES'
      IMPORTING
        P_LEGEND = LIT_CATEGORIES.
    READ TABLE LIT_CATEGORIES INTO LWA_CATEGORIES INDEX LV_INDEX.
    WA_ST22-ERRTYPE = LWA_CATEGORIES.

    APPEND WA_ST22 TO IT_ST22.
  ENDLOOP.

  "批量更新自定义表
  IF IT_ST22 IS NOT INITIAL.
    MODIFY ZTGETST22 FROM TABLE IT_ST22.
    LV_LINES = LINES( IT_ST22 ).
    MESSAGE S368(00) WITH '成功更新数据条数:' LV_LINES.
  ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  FRM_GET_MODULE
*&      功能:根据程序名匹配业务模块MM/FI/CO/PO/PL
*&---------------------------------------------------------------------*
FORM FRM_GET_MODULE USING P_STR TYPE SYREPID
                          CHANGING P_ERRMODULE TYPE ZTGETST22-ERRMODULE.
  CLEAR P_ERRMODULE.
  IF P_STR CS 'PO'.
    P_ERRMODULE = 'PO'.
  ELSEIF P_STR CS 'PL'.
    P_ERRMODULE = 'PL'.
  ELSEIF P_STR CS 'FI'.
    P_ERRMODULE = 'FI'.
  ELSEIF P_STR CS 'CO'.
    P_ERRMODULE = 'CO'.
  ELSEIF P_STR CS 'MM'.
    P_ERRMODULE = 'MM'.
  ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  FRM_FIND_DATA
*&      功能:按程序+错误ID分组统计报错次数,超阈值存入IT_EMAIL用于发邮件
*&---------------------------------------------------------------------*
FORM FRM_FIND_DATA .
  DATA: LV_TIMES TYPE INT8 VALUE 0,
        LWA_HEAD TYPE TYP_COMP.

  REFRESH: IT_COMP, IT_EMAIL.
  LOOP AT IT_ST22 INTO WA_ST22.
    WA_COMP-GPROGRAM = WA_ST22-GPROGRAM.
    WA_COMP-ERRID    = WA_ST22-ERRID.
    WA_COMP-ERRTYPE  = WA_ST22-ERRTYPE.
    WA_COMP-GSGUID   = WA_ST22-GSGUID.
    WA_COMP-TIMES    = '1'. "修复原代码缺失赋值
    APPEND WA_COMP TO IT_COMP.
  ENDLOOP.

  SORT IT_COMP BY GPROGRAM ERRID.
*  LOOP AT IT_COMP INTO WA_COMP.
*    LV_TIMES = LV_TIMES + 1.
*    LWA_HEAD = WA_COMP.
*
*    AT END OF ERRID.
*      IF LV_TIMES >= P_LINES.
*        LWA_HEAD-TIMES = |{ LV_TIMES }|.
*        APPEND LWA_HEAD TO IT_EMAIL.
*      ENDIF.
*      CLEAR LV_TIMES.
*    ENDAT.
*  ENDLOOP.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  FRM_SEND_EMAIL
*&      功能:BCS发送HTML格式异常告警邮件
*&---------------------------------------------------------------------*
FORM FRM_SEND_EMAIL .
  DATA:
    L_SUBJECT          TYPE SO_OBJ_DES VALUE '【SAP系统ST22异常告警】Z程序运行DUMP超标',
    LR_EMAIL_BODY      TYPE REF TO CL_DOCUMENT_BCS,
    LR_EMAIL           TYPE REF TO CL_BCS,
    L_MAIL_ADDRESS     TYPE ADR6-SMTP_ADDR,
    LR_RECEIVER        TYPE REF TO CL_CAM_ADDRESS_BCS,
    L_SENDER           TYPE REF TO CL_SAPUSER_BCS,
    LO_CX_SEND_REQ_BCS TYPE REF TO CX_SEND_REQ_BCS,
    L_SEND_RESULT      TYPE OS_BOOLEAN,
    GT_MAIL_BODY       TYPE SOLI_TAB,
    WA_MAIL_BODY       TYPE SOLI,
    LO_MIME_HELPER     TYPE REF TO CL_GBT_MULTIRELATED_SERVICE.

  CONSTANTS:
    GC_CRLF TYPE C VALUE CL_BCS_CONVERT=>GC_CRLF.

  "拼接HTML正文
  CLEAR GT_MAIL_BODY.
  WA_MAIL_BODY-LINE = '<html>'.                  APPEND WA_MAIL_BODY TO GT_MAIL_BODY.
  WA_MAIL_BODY-LINE = '<head>'.                 APPEND WA_MAIL_BODY TO GT_MAIL_BODY.
  WA_MAIL_BODY-LINE = '<meta http-equiv="Content-Type" content="text/html;charset=gb2312">'. APPEND WA_MAIL_BODY TO GT_MAIL_BODY.
  WA_MAIL_BODY-LINE = '<title>SAP DUMP异常通知</title></head><body>'. APPEND WA_MAIL_BODY TO GT_MAIL_BODY.

  LOOP AT IT_EMAIL INTO WA_EMAIL.
    CONCATENATE '''' WA_EMAIL-ERRID '''' INTO WA_EMAIL-ERRID.
    CONCATENATE '''' WA_EMAIL-ERRTYPE '''' INTO WA_EMAIL-ERRTYPE.
    CONDENSE WA_EMAIL-TIMES NO-GAPS.
    WA_MAIL_BODY-LINE = |程序名:{ WA_EMAIL-GPROGRAM },发生次数:{ WA_EMAIL-TIMES }次,错误ID:{ WA_EMAIL-ERRID },错误分类:{ WA_EMAIL-ERRTYPE }<br>|.
    APPEND WA_MAIL_BODY TO GT_MAIL_BODY.
  ENDLOOP.

  WA_MAIL_BODY-LINE = '</body></html>'. APPEND WA_MAIL_BODY TO GT_MAIL_BODY.

  "构建MIME HTML邮件
  CREATE OBJECT LO_MIME_HELPER.
  CALL METHOD LO_MIME_HELPER->SET_MAIN_HTML EXPORTING CONTENT = GT_MAIL_BODY.

  TRY.
      CALL METHOD CL_DOCUMENT_BCS=>CREATE_FROM_MULTIRELATED
        EXPORTING
          I_SUBJECT          = L_SUBJECT
          I_MULTIREL_SERVICE = LO_MIME_HELPER
        RECEIVING
          RESULT             = LR_EMAIL_BODY.
    CATCH CX_DOCUMENT_BCS CX_BCOM_MIME.
      MESSAGE S208(00) WITH '创建邮件文档异常' DISPLAY LIKE 'E'.
      EXIT.
  ENDTRY.

  "创建发送实例
  LR_EMAIL = CL_BCS=>CREATE_PERSISTENT( ).
  LR_EMAIL->SET_DOCUMENT( LR_EMAIL_BODY ).

  "填充收件人
  LOOP AT S_EMAIL INTO DATA(LWA_EMAIL).
    L_MAIL_ADDRESS = LWA_EMAIL-LOW.
    TRY.
        LR_RECEIVER = CL_CAM_ADDRESS_BCS=>CREATE_INTERNET_ADDRESS( L_MAIL_ADDRESS ).
        LR_EMAIL->ADD_RECIPIENT( I_RECIPIENT = LR_RECEIVER ).
      CATCH CX_ADDRESS_BCS.
    ENDTRY.
  ENDLOOP.

  "发件人
  L_SENDER = CL_SAPUSER_BCS=>CREATE( 'XX-NOTICE' ).
  LR_EMAIL->SET_SENDER( L_SENDER ).
  LR_EMAIL->SET_STATUS_ATTRIBUTES( I_REQUESTED_STATUS = 'E' I_STATUS_MAIL = 'E' ).

  "立即发送
  TRY.
      CALL METHOD LR_EMAIL->SET_SEND_IMMEDIATELY EXPORTING I_SEND_IMMEDIATELY = 'X'.
    CATCH CX_SEND_REQ_BCS.
  ENDTRY.

  TRY.
      CALL METHOD LR_EMAIL->SEND RECEIVING RESULT = L_SEND_RESULT.
      COMMIT WORK.
    CATCH CX_SEND_REQ_BCS INTO LO_CX_SEND_REQ_BCS.
  ENDTRY.
ENDFORM.

 

posted @ 2026-06-03 15:38  萧静默  阅读(3)  评论(0)    收藏  举报