Page 150 - 《软件学报》2026年第7期
P. 150
周俊伟 等: PCLog: 近端策略优化与行为克隆自适应日志异常检测 2835
处理流程如图 2 所示, 主要包括参数替换、日志事件提取与句向量生成 3 个步骤. 一条原始日志记录由日志头
(Header) 与日志体 (Body) 两部分组成, 其中日志头包含时间戳、进程编号、日志级别与系统模块等信息; 日志体
则记录了系统在特定时刻的运行状态, 通常由开发人员通过打印语句输出, 包括固定格式的日志事件 (模板) 与变
化部分的参数内容 (如文件路径、IP 地址、MAC 地址、主机名等). 为统一格式, 本文首先利用正则表达式识别日
志体中的参数值, 并将其替换为相应的标签标记. 部分典型替换示例如表 1 所示.
1 081109 203551 149 INFO PacketResponder:PacketResponder 0 for block blk_31 terminating
2 081109 203552 149 INFO PacketResponder:PacketResponder 1 for block blk_31 terminating
3 081109 203553 149 INFO PacketResponder:Received block blk_31 of size 64 from /10.2.6.2
4 081109 20355428 WARNFSNamesystem: BLOCK* NameSystem.allocateBlock: /user/part1 blk_-90
5 081109 20355513 INFODataBlockScanner:Verification succeeded for blk_-90
数据预处理
日志头 日志体
行号 时间戳 进程号 警告级别 组件 模板 (日志事件) 参数列表
PacketResponder number
1 081109 203551 149 INFO PacketResponder [0,blk_31]
for block terminating
PacketResponder number
2 081109 203552 149 WARN PacketResponder [1,blk_31]
for block terminating
Received block of size
3 081109 203553 149 INFO PacketResponder [64,blk_31,/10.2.6.2]
number from IP
BLOCK* NameSystem
4 081109 203554 28 INFO FSName system [/user/part1,blk_-90]
allocateBlock path
Verification succeeded
5 081109 203555 13 INFO DataBlockScanner [blk_-90]
for block
图 2 日志预处理
表 1 参数替换示例
正则表达式 参数实例 替换标签
\d{1, 3}\.\d{1, 3}\.\d{1, 3}\.\d{1, 3} 10.2.6.2 ip
0x[a-fA-F0-9]{8} 0x00544ea8 hex
R\d+-[ - ]* R23-M1-N4-I1J8-U01 device
^(\w+)*\w+$ /user/part1 path
(\d+) 64 number
替换完成后, 日志体格式高度统一, 通过去重即可提取出标准化的日志事件. 由于日志事件的种类有限, 本文
为每类事件分配唯一编号, 并将其作为动作集输入至强化学习模型中. 进一步地, 为保留日志的语义信息, 本文采
用句向量嵌入方法将文本形式的日志事件映射为固定维度的高维稠密向量. 具体而言, 首先利用公开语料预训练
词向量, 再通过平滑逆频率 (smooth inverse frequency, SIF) 方法生成日志句向量. 设一条日志消息 m 中包含|m|个
词, 其句向量表示为:
1 ∑ a
t
V m = w i ,V m = V m −uu V m (1)
|m| a+ p(w)
其中, a 为平滑常数, p(w) 为词 w 的出现概率; 第 1 个等式得到的向量被拼接成矩阵 X, 而 u 是 X 的第 1 个奇异向
量; 第 2 个等式从每个句子向量中移除了其在 u 上的投影. 此方法能够有效保留词语的关键信息, 同时具有良好的
计算效率与鲁棒性.
最后, 依据日志中的唯一标识符 (如 BlockID、InstanceID) 对日志进行分组, 形成按时间排序的日志序列, 作
为状态-动作序列输入模型. 在 HDFS 数据集中使用 BlockID 分组, 在 OpenStack 中使用 InstanceID 分组, 对于
BGL 数据集则采用滑动窗口方式切分. 每条日志序列均记录了系统事件的执行顺序与模式, 为后续建模提供关键
上下文信息.

