用 map[string]float64 存关键词权重,配合 strings.fieldsfunc 自定义分词,遍历匹配累加得分;优先用 strings.contains,需边界时用 \b 正则;按业务选去重/频次/位置加权;阈值基于历史样本分位数动态配置。

怎么用 Go 写一个基于关键词权重的日志评分器
直接说结论:用 map[string]float64 存关键词权重,配合 strings.Fields() 或正则分词,再遍历匹配累加得分——简单、可控、无需引入第三方分词库。别一上来就搞 TF-IDF 或 NLP 模型,日志文本短、结构松散、关键词明确,权重规则才是核心。
关键词匹配该用 strings.Contains 还是正则?
多数日志场景下,strings.Contains 更快更稳;但要注意边界误匹配(比如 “err” 匹配到 “error” 和 “terrify”)。真正需要精确词边界时,才用 regexp.MustCompile(`\berr\b`)。实际选型看三点:
- 日志字段是否已结构化(如 JSON 字段
message)——若已提取纯文本,strings.Contains足够 - 关键词是否含特殊字符(如
"[ERROR]")——这时必须用正则转义或regexp.QuoteMeta - 性能敏感度——10 万条/秒日志处理时,
strings.Contains比编译正则快 3–5 倍
权重叠加逻辑怎么避免重复计分
日志里同一词反复出现(如 “failed failed failed”),按业务意图决定是否去重。常见做法:
- 只计一次:
seen := make(map[string]bool),匹配前查是否存在 - 按频次累加:
score += weight * count,需先用strings.Count()或切片遍历统计 - 按位置加权:靠前的词权重 ×1.2,可用
strings.Index()判断首次出现位置
注意:不要用 strings.Split(text, " ") 做分词——日志含标点(如 "timeout: connect failed.")会导致 "failed." 匹配失败;改用 strings.FieldsFunc(text, func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsNumber(r) }) 更鲁棒。
分级阈值怎么设才不容易翻车
阈值不是拍脑袋定的,得结合历史日志样本分布。实操建议:
- 先跑全量日志抽样(比如 1000 条),用你的权重规则批量打分,用
sort.Float64s排序后取 90% 分位数作为high阈值 - 避免硬编码
if score > 5.0—— 改成配置文件读取,例如config.Thresholds = map[string]float64{"low": 1.0, "medium": 3.0, "high": 7.0} - 留一个兜底档位(如
"unknown"),当总分 = 0 且无任何关键词命中时返回,防止误判“安静即正常”
最常被忽略的是日志时间戳和来源服务名——它们本身不含语义,但若混在 message 字段里参与评分,会稀释关键词权重。预处理时最好先用正则剥离 ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 和 service=xxx 类前缀。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











