最近由于不像前段时间那么忙了,所以抽了个空看了下线上系统的运行日志,还是看到了很多的报错信息,并且还看到生产环境部分的业务配置的还是测试环境的地址,也就是生产上的业务白跑了,这些平时都关注不到的点,就这样被偶然发现了。相信像我这样情况的人不在少数,咱们生产系统,特别是微服务架构,如果公司人员少,很多信息就会被漏掉,当回过头来发现有问题的时候,这种有问题的程序已经在线上跑了很长一段时间了,可能出现数据断层或者数据错误,导致部分业务受损。所以基于此这两天研究下使用n8n工作流来实现对线上系统的自动巡检功能,当发现故障第一时间用邮件的形式推送给研发部,这样子便于提前发现,提早解决。
我们目前线上整体服务才能的是微服务架构,后端有好几个springboot服务,通过网关一起支撑起线上的产品,这些springboot服务的日志都是直接使用plumeLog进行采集的,想要看日志,直接通过plumeLog的dashboard进行查看即可,如下图:

所以对于我们做自动巡检这块只需要对接这里plumeLog存储的数据即可,目前我们部署的plumeLog数据是存储在elasticsearch中的,所以这里使用n8n做自动巡检运维功能的话,只需要从elasticsearch中查询数据即可,然后对数据进行处理,暂时用不着对接plumeLog。
这里我们实现使用n8n自动巡检的主要思路有:
1、制定一个定时任务 2、从elasticsearch中查询数据 3、使用ai agent进行错误分析,并且让他提供一些建议和意见。 4、通过邮件的形式发送给我们指定的邮箱。
这里由于主要是配合我们这篇文章进行演示,所以我把演示用的工作流给贴出来大家看看:

根据前面的思路我们整体实现的工作流如上图所示,下面我们针对上面的工作流进行挨个节点做下介绍:
首先我们巡检的话一般来说可以是每天或者每个小时,比如我们的业务是每天执行一遍,那么我们就需要在第一步制定一个定时器触发节点,时间可以根据自己的选择来进行,这里为了演示,我直接使用的是人工点击触发事件来进行演示。
第二步的code节点主要是为了方便使用函数获取具体的日期,在plumlog里面,数据是每一天存储在一个index里面的,如下图:

所以这里为了演示,我直接使用javascript节点获取当天的日期即可,对应的javascriot代码是:
// 创建一个Date对象,表示当前时刻 const now = new Date();
// 获取日期的各个部分(年、月、日) const year = now.getFullYear(); // 月份需要加1,因为getMonth()返回的月份从0开始(0代表一月) const month = String(now.getMonth() + 1).padStart(2, ‘0’); // 确保月份总是两位数 const day = String(now.getDate()).padStart(2, ‘0’); // 确保日期总是两位数
// 组合成 yyyyMMdd 格式的字符串 const formattedDate = ${year}${month}${day};
// 准备返回给n8n中下一个节点的数据 // 返回一个数组,其中包含一个json对象,对象中有一个formattedDate属性 return [{ json: { index_name: "plume_logrun"+formattedDate } }];
把这个代码贴到第二步的code节点就可以看到输出了对应的indexname,如下图:

今天是2025年12月3日,所以获取的是12月3日的日期,最后拼接成字符串,正好能对应上我们elasticsearch上的index_name

前一步我们已经使用代码生成了index_name,那么接下来我们就需要使用elasticsearch节点从elasticsearch中查询对应的数据了,所以这里我们的配置是:

我们在index_name的地方,把上一个节点生成的indexname给拖过来,下面的dsl里面,我们需要写查询的dsl,由于我们这里是做巡检,所以这里我们不是把所有的数据都给查询出来,而是只查询content字段里面有exception字段的数据,所以这里我们的dsl是:
{ "query": { "bool": { "must": [ { "match_phrase": { "content": "Exception" } } ] } } }
备注:
1、这里大家可以根据自己的实际情况进行查询,比如查询日志级别是error的数据
2、同时还可以根据其他的条件进行数据的筛选,比如我们每个小时都要巡检一次,那我们可能还需要在dsl里面添加dtTime的时间区间查询。
最后反正这里的dsl查询情况根据自己的实际需要进行填写即可,最后我们测试看看,是可以查询到数据的:

备注:
1、这里还有个需要注意的地方,即我们一般是需要查询所有数据的,我们上图为了演示可以看到limit是写死的10,实际中需要把return all这个开关给打开,而不是使用limit进行查询,避免数据不完整

接下来我们又增加了一个code节点,这个code节点的作用主要是聚合,比如我们前面使用elasticsearch查询数据,那查询的结果是一条条的,我们不可能把这一条条的数据挨个拿给ai进行分析,这样既浪费token,同时最后每一条错误信息都发送一封邮件,这不是我们想要的。所以这里我们使用code节点,把所有的错误数据给综合一下,弄成一条发给ai进行分析即可,所以这里code节点我们的javascript代码是:
// 获取上一个节点传来的所有数据项(数组) const allInputItems = $input.all();
// 处理所有项,将它们收集到一个数组中 const allErrors = allInputItems.map((inputItem) => { const itemData = inputItem.json; return { appName: itemData.appName || "未知应用", className: itemData.className || "未知类", content: itemData.content ? itemData.content.substring(0, 200) + "…" : "无内容", dtTime: itemData.dtTime ? new Date(itemData.dtTime).toISOString() : "无时间戳" }; });
// 只返回一条数据,包含所有错误信息的数组 return [{ json: { all_errors: allErrors, // 包含所有错误对象的数组 total_count: allErrors.length, // 错误总数 summary: 系统检测到 ${allErrors.length} 条错误日志需要分析, timestamp: new Date().toISOString() } }];
最后我们运行一下,看下最后的结果:

可以看到上一个节点数据里面一条条的数据都被我们的code节点统一综合输出到了all_errors节点里面了。
这个节点主要是让ai帮我们分析错误,所以添加一个ai agent节点,模型的话我们还是使用硅基流动的qwen3-8b(最主要是免费,香啊)。然后这里我们需要在ai agent节点里面配置独赢的system.message和prompt,对应的信息是:
system.message信息:
你是一名经验丰富的Java后端架构师和SRE工程师。你的任务是分析系统错误日志,提供专业的故障分析和解决方案建议。
prompt信息:
请分析以下系统错误日志数据,这些是从pd-payments应用获取的10条错误记录:
应用名称:{{ \(json.all_errors[0].appName }} 错误总数:{{ \)json.all_errors.length }} 条
错误详情: }
请用以下表格格式输出分析结果:
| 分析维度 | 分析结果 |
|---|---|
| 主要异常类型 | |
| 异常简要解读 | |
| 发生位置/链路 | |
| 最可能的根本原因 | |
| 立即补救措施 | |
| 长期预防建议 |
请基于实际的错误内容进行分析,不要使用预设示例。
这是根据我的实际情况设置的系统词和提示词,大家可以根据自己的情况进行改写,最后我们运行一遍看看效果:

可以看到这里右侧的输出使用了markdown的表格形式进行了输出。
这里为什么我们又添加了一个code节点呢?主要是因为后面我们要发送邮件的话,邮件内容不支持markdown格式的显示,看起来就非常凌乱,比如:

这种是不是看起来非常的凌乱,也不方便我们进行分析,所以这里我们转换一下思路,既然邮件内容不支持markdown格式显示,那肯定是支持html格式显示的啊,所以我们把markdown格式的表格内容转换成html格式的内容,所以这里我们code节点的代码是:
// 从AI Agent节点获取Markdown表格 const markdownTable = items[0].json.output;
// 将Markdown表格转换为HTML表格的函数 function markdownTableToHTML(markdown) ; }); html += ''; // 处理数据行(跳过分隔线) for (let i = 2; i < lines.length; i++) ">${cell.trim()}; }); html += ‘’; } html += ‘’; return html; }
// 转换并返回 const htmlTable = markdownTableToHTML(markdownTable);
// 创建完整的HTML邮件内容 const emailHTML =
🚨 系统错误分析报告
生成时间: ${new Date().toLocaleString()}
📊 分析概览
基于系统日志的深度分析,识别关键问题并提供解决方案
📋 详细分析结果
${htmlTable}
此邮件由n8n工作流自动生成
;
return [{ json: { html_content: emailHTML, original_markdown: markdownTable } }];
最后我们运行下结果看看效果:

这里确实已经转换成了html内容了。
接下来就是最后的发送邮件的节点了,这里很简单,配置下对应的smtp账号及发件人,收件人,主题即可。

然后我们点击测试,去邮箱里面看看

是不是就非常直观了,不仅分析了错误,同时还把解决办法及预防等措施都展示出来了。
以上就是我们内部实现运维场景的自动巡检,自动报警的案例。最后按照惯例,附上本案例的json,登录后即可下载。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/274612.html