一、为什么COBOL程序需要更好的日志管理

如果你维护过COBOL程序,肯定遇到过这种情况:半夜被报警叫醒,却发现日志里只有"ERROR 123"这样让人摸不着头脑的信息。这种时候,你可能会想——要是当初写日志的人能多花5分钟描述问题该多好。

COBOL程序往往运行在银行、保险等关键业务系统,一个简单的交易失败可能影响成千上万的用户。但很多老系统的日志还停留在"输出必要信息"的原始阶段,导致排查问题就像在黑暗中摸索。

二、COBOL日志的常见问题

先看看这段典型的"问题日志"代码:

* 技术栈:IBM COBOL V6.3
IDENTIFICATION DIVISION.
PROGRAM-ID. TRANSFER-FUNDS.

PROCEDURE DIVISION.
    IF WS-ACCOUNT-BALANCE < WS-TRANSFER-AMOUNT
        DISPLAY "ERROR 501"  *> 余额不足错误
    ELSE
        PERFORM TRANSFER-MONEY
        IF WS-TRANSFER-STATUS NOT = "SUCCESS"
            DISPLAY "ERROR 502"  *> 转账失败
        END-IF
    END-IF.

这段代码有两个明显问题:

  1. 错误代码没有上下文(比如账户号、金额等)
  2. 成功操作完全没有记录

三、实用的COBOL日志策略

3.1 结构化日志模板

改进后的版本:

* 技术栈:IBM COBOL V6.3
IDENTIFICATION DIVISION.
PROGRAM-ID. TRANSFER-FUNDS-LOGGING.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 LOG-MESSAGE      PIC X(100).
01 TIMESTAMP        PIC X(23).

PROCEDURE DIVISION.
    MOVE FUNCTION CURRENT-DATE TO TIMESTAMP
    
    IF WS-ACCOUNT-BALANCE < WS-TRANSFER-AMOUNT
        STRING TIMESTAMP " | ERROR | ACCT:" WS-ACCOUNT-NO 
               " | REQ:" WS-TRANSFER-AMOUNT " | BAL:" WS-ACCOUNT-BALANCE
               " | CODE:INSUFFICIENT_FUNDS"
          INTO LOG-MESSAGE
        DISPLAY LOG-MESSAGE
    ELSE
        PERFORM TRANSFER-MONEY
        STRING TIMESTAMP " | INFO | ACCT:" WS-ACCOUNT-NO 
               " | AMT:" WS-TRANSFER-AMOUNT " | NEW_BAL:" WS-NEW-BALANCE
          INTO LOG-MESSAGE
        DISPLAY LOG-MESSAGE
        
        IF WS-TRANSFER-STATUS NOT = "SUCCESS"
            STRING TIMESTAMP " | ERROR | ACCT:" WS-ACCOUNT-NO 
                   " | DETAIL:" WS-ERROR-DETAIL " | CODE:TRANSFER_FAILED"
              INTO LOG-MESSAGE
            DISPLAY LOG-MESSAGE
        END-IF
    END-IF.

关键改进点:

  • 添加时间戳便于追踪
  • 使用统一格式:时间 | 级别 | 关键字段 | 错误详情
  • 记录成功操作便于审计

3.2 日志级别控制

建议实现简单的日志分级:

* 技术栈:IBM COBOL V6.3
01 LOG-LEVEL        PIC X(5) VALUE "INFO". *> 可配置为 ERROR/WARN/INFO/DEBUG

PROCEDURE DIVISION.
    IF LOG-LEVEL = "DEBUG"
        STRING TIMESTAMP " | DEBUG | " WS-VARIABLE-DUMP
          INTO LOG-MESSAGE
        DISPLAY LOG-MESSAGE
    END-IF.

四、高级日志技巧

4.1 交易追踪ID

跨程序调用时,添加唯一ID串联日志:

* 技术栈:IBM COBOL V6.3
01 TRACE-ID         PIC X(32).

PROCEDURE DIVISION.
    CALL "GENERATE-UUID" USING TRACE-ID
    
    STRING TIMESTAMP " | " TRACE-ID " | INFO | START TRANSFER"
      INTO LOG-MESSAGE
    DISPLAY LOG-MESSAGE
    
    CALL "VALIDATE-ACCOUNT" USING TRACE-ID...

4.2 自动日志归档

通过JCL实现日志轮转:

//LOGROTATE  EXEC PGM=IEBGENER
//SYSUT1     DD DSN=SYSTEM.LOG.TODAY,DISP=SHR
//SYSUT2     DD DSN=SYSTEM.LOG.ARCHIVE(+1),DISP=NEW
//SYSPRINT   DD SYSOUT=*
//SYSIN      DD DUMMY

五、实际应用场景

银行转账系统案例

  • 问题:某转账交易偶尔失败,但无法重现
  • 旧日志:只记录"ERROR 502"
  • 新日志:
    2023-11-20T15:23:45 | ABC123 | ERROR | ACCT:88889999 | REQ:5000.00 | BAL:4800.00 | CODE:INSUFFICIENT_FUNDS
    
    立即发现是特定金额的并发请求导致余额计算问题

六、技术优缺点

优点

  • 排查时间从平均4小时缩短到30分钟
  • 审计合规性提升
  • 新员工更容易理解系统行为

缺点

  • 日志量增加约20%
  • 需要改造老代码(但可以逐步进行)

七、注意事项

  1. 敏感信息过滤:不要在日志中记录完整卡号等数据

    STRING "ACCT:" WS-ACCOUNT-NO(1:4) "****"  *> 只显示前四位
    
  2. 性能考量:高频交易中避免记录过多DEBUG信息

  3. 存储规划:确保日志系统有足够空间

八、总结

好的日志就像程序的"黑匣子",在出问题时能快速定位原因。对于COBOL系统,虽然改造老代码需要投入,但带来的运维效率提升是立竿见影的。建议从最关键的交易程序开始,逐步实施以下改进:

  1. 添加时间戳和交易ID
  2. 采用统一格式
  3. 实现日志分级
  4. 确保记录成功操作

记住:你今天多写的5分钟日志,可能会在未来拯救某个同事的通宵加班。