基于 Go 语言 + Ollama 的智能日志分析工具的完整实战教程,包含环境搭建、核心代码实现、测试运行和优化扩展,能直接落地使用而非仅片段代码。这份实战教程会从 0 到 1 构建工具,聚焦实用性和可操作性,适配新手也兼顾生产级基础要求。
一、工具核心目标
- 读取指定路径的日志文件(支持
.log/.txt格式) - 提取日志中的异常信息(错误、警告、超时等关键词)
- 调用本地 Ollama 部署的大模型,分析异常原因并给出解决方案
- 输出结构化的分析报告(文本 + JSON 格式)
二、环境准备
1. 基础环境安装
(1) Go 环境(1.21+)
bash
# 下载安装(以Linux为例,Windows/Mac可从官网下载安装包)
wget https://dl.google.com/go/go1.22.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
# 配置环境变量(~/.bashrc 或 ~/.zshrc)
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
source ~/.bashrc
# 验证
go version # 输出 go1.22.0 linux/amd64 即成功
(2) Ollama 安装与模型部署
bash
# 安装Ollama(跨平台通用命令)
curl https://ollama.ai/install.sh | sh
# 启动Ollama服务(默认端口 11434)
ollama serve &
# 拉取轻量且适配代码分析的模型(Llama 3 8B,约4GB显存即可运行)
ollama pull llama3
# 验证Ollama是否正常
ollama run llama3 "你好" # 能返回回复即成功
2. 项目初始化
bash
# 创建项目目录
mkdir go-ollama-log-analyzer && cd go-ollama-log-analyzer
# 初始化Go模块
go mod init log-analyzer
# 安装依赖包
go get github.com/ollama/ollama-go # Ollama官方Go SDK
go get github.com/sirupsen/logrus # 日志库(可选,用于工具自身日志)
三、项目结构设计
go-ollama-log-analyzer/
├── go.mod # 模块依赖
├── go.sum # 依赖校验
├── main.go # 主程序入口
├── logreader/ # 日志读取模块
│ └── reader.go # 日志读取、预处理逻辑
├── aianalyzer/ # AI分析模块
│ └── analyzer.go # 调用Ollama、生成分析报告
└── test.log # 测试日志文件(自行创建)
四、核心代码实现
1. 日志读取模块(logreader/reader.go)
负责读取日志文件、过滤空行、提取异常关键词(可自定义):
go
package logreader
import (
"bufio"
"fmt"
"os"
"strings"
)
// 异常关键词列表(可根据业务扩展)
var errorKeywords = []string{"error", "Error", "ERROR", "panic", "Panic", "PANIC",
"timeout", "Timeout", "TIMEOUT", "fail", "Fail", "FAIL", "warning", "Warning", "WARNING"}
// LogContent 日志内容结构体
type LogContent struct {
RawContent string // 原始日志内容
ErrorLines []string // 提取的异常行
FilePath string // 日志文件路径
}
// ReadLog 读取指定路径的日志文件
func ReadLog(filePath string) (*LogContent, error) {
// 检查文件是否存在
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("打开日志文件失败: %v", err)
}
defer file.Close()
var rawContent string
var errorLines []string
scanner := bufio.NewScanner(file)
// 逐行读取日志
lineNum := 0
for scanner.Scan() {
lineNum++
line := scanner.Text()
rawContent += line + "\n"
// 过滤空行
if strings.TrimSpace(line) == "" {
continue
}
// 检测异常行并记录(带行号便于定位)
for _, keyword := range errorKeywords {
if strings.Contains(line, keyword) {
errorLines = append(errorLines, fmt.Sprintf("第%d行: %s", lineNum, line))
break // 避免同一行匹配多个关键词重复添加
}
}
}
// 检查读取过程中的错误
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("读取日志文件出错: %v", err)
}
return &LogContent{
RawContent: rawContent,
ErrorLines: errorLines,
FilePath: filePath,
}, nil
}
// GetErrorSummary 生成异常行摘要(避免内容过长,Ollama处理慢)
func (lc *LogContent) GetErrorSummary() string {
if len(lc.ErrorLines) == 0 {
return "未检测到异常日志行"
}
// 最多取20行异常行(防止内容超限)
maxLines := 20
if len(lc.ErrorLines) < maxLines {
maxLines = len(lc.ErrorLines)
}
return strings.Join(lc.ErrorLines[:maxLines], "\n")
}
2. AI分析模块(aianalyzer/analyzer.go)
负责调用Ollama API、发送日志异常内容、生成结构化分析报告:
go
package aianalyzer
import (
"context"
"fmt"
"log"
"github.com/ollama/ollama-go"
)
// OllamaConfig Ollama配置
type OllamaConfig struct {
ModelName string // 模型名称(如llama3)
BaseURL string // Ollama服务地址(默认http://localhost:11434)
}
// AnalysisReport AI分析报告
type AnalysisReport struct {
ErrorSummary string // 异常日志摘要
Reason string // 异常原因分析
Solution string // 建议解决方案
ModelResponse string // 模型原始回复
}
// AnalyzeLog 调用Ollama分析日志异常
func AnalyzeLog(errorSummary string, config OllamaConfig) (*AnalysisReport, error) {
// 初始化Ollama客户端
client, err := ollama.NewClient(config.BaseURL)
if err != nil {
return nil, fmt.Errorf("创建Ollama客户端失败: %v", err)
}
// 构建提示词(Prompt Engineering,关键!)
prompt := fmt.Sprintf(`
你是一位资深的Go语言后端工程师和运维专家,擅长分析各类日志异常。
请分析以下日志中的异常内容,要求:
1. 明确指出异常的核心原因(简洁明了);
2. 给出具体、可落地的解决方案(分点说明);
3. 语言使用中文,避免冗余,聚焦问题解决。
异常日志内容:
%s
`, errorSummary)
// 调用Ollama生成回复
req := ollama.GenerateRequest{
Model: config.ModelName,
Prompt: prompt,
// 控制生成参数,提升响应速度
Options: map[string]interface{}{
"temperature": 0.1, // 低随机性,保证结果稳定
"max_tokens": 1000, // 最大生成token数
},
}
// 流式接收响应(也可使用非流式,根据需求选择)
stream, err := client.Generate(context.Background(), &req)
if err != nil {
return nil, fmt.Errorf("调用Ollama模型失败: %v", err)
}
// 拼接完整回复
var fullResponse string
for {
resp, err := stream.Recv()
if err != nil {
if err.Error() == "EOF" {
break // 流结束
}
log.Printf("接收模型响应出错: %v", err)
break
}
fullResponse += resp.Response
}
// 解析回复,拆分原因和解决方案(简单拆分,也可使用JSON格式输出)
reason, solution := parseResponse(fullResponse)
return &AnalysisReport{
ErrorSummary: errorSummary,
Reason: reason,
Solution: solution,
ModelResponse: fullResponse,
}, nil
}
// parseResponse 简单解析模型回复,拆分原因和解决方案
func parseResponse(response string) (reason, solution string) {
// 按关键词拆分(可根据模型回复风格调整)
reasonKey := "异常原因:"
solutionKey := "解决方案:"
reasonIdx := strings.Index(response, reasonKey)
solutionIdx := strings.Index(response, solutionKey)
if reasonIdx != -1 {
if solutionIdx != -1 {
reason = strings.TrimSpace(response[reasonIdx+len(reasonKey) : solutionIdx])
} else {
reason = strings.TrimSpace(response[reasonIdx+len(reasonKey):])
}
} else {
reason = "未识别到明确的异常原因分析"
}
if solutionIdx != -1 {
solution = strings.TrimSpace(response[solutionIdx+len(solutionKey):])
} else {
solution = "未识别到明确的解决方案"
}
return
}
// 辅助函数:字符串处理(上面用到,需补充)
import "strings"
3. 主程序入口(main.go)
整合日志读取和AI分析模块,提供命令行交互:
go
package main
import (
"flag"
"fmt"
"log"
"os"
"log-analyzer/aianalyzer"
"log-analyzer/logreader"
)
func main() {
// 解析命令行参数
logFile := flag.String("file", "", "日志文件路径(必填,如./test.log)")
model := flag.String("model", "llama3", "Ollama模型名称(默认llama3)")
ollamaURL := flag.String("url", "http://localhost:11434", "Ollama服务地址(默认http://localhost:11434)")
flag.Parse()
// 校验必填参数
if *logFile == "" {
fmt.Println("错误:必须指定日志文件路径,使用 -file 参数,如:./log-analyzer -file ./test.log")
flag.Usage()
os.Exit(1)
}
// 1. 读取并预处理日志
fmt.Printf("正在读取日志文件:%s\n", *logFile)
logContent, err := logreader.ReadLog(*logFile)
if err != nil {
log.Fatalf("读取日志失败:%v", err)
}
// 2. 检查是否有异常行
if len(logContent.ErrorLines) == 0 {
fmt.Println("✅ 日志文件中未检测到异常内容")
os.Exit(0)
}
fmt.Printf("🔍 检测到 %d 行异常日志,正在调用AI分析...\n", len(logContent.ErrorLines))
// 3. 调用Ollama分析日志
config := aianalyzer.OllamaConfig{
ModelName: *model,
BaseURL: *ollamaURL,
}
report, err := aianalyzer.AnalyzeLog(logContent.GetErrorSummary(), config)
if err != nil {
log.Fatalf("AI分析失败:%v", err)
}
// 4. 输出结构化分析报告
fmt.Println("\n==================== 智能日志分析报告 ====================")
fmt.Printf("📄 分析文件:%s\n", *logFile)
fmt.Printf("\n❌ 异常摘要:\n%s\n", report.ErrorSummary)
fmt.Printf("\n🔍 异常原因:\n%s\n", report.Reason)
fmt.Printf("\n💡 解决方案:\n%s\n", report.Solution)
fmt.Println("==========================================================")
// 可选:将报告写入文件
// saveReportToFile(report, *logFile + ".analysis.txt")
}
// 可选功能:将报告写入文件
func saveReportToFile(report *aianalyzer.AnalysisReport, outputPath string) {
content := fmt.Sprintf(`智能日志分析报告
分析文件:%s
异常摘要:
%s
异常原因:
%s
解决方案:
%s
模型原始回复:
%s
`, outputPath, report.ErrorSummary, report.Reason, report.Solution, report.ModelResponse)
err := os.WriteFile(outputPath, []byte(content), 0644)
if err != nil {
log.Printf("写入分析报告文件失败:%v", err)
} else {
fmt.Printf("\n📝 分析报告已保存至:%s\n", outputPath)
}
}
五、测试运行
1. 创建测试日志文件(test.log)
2026-01-15 10:00:00 [INFO] 服务启动成功,监听端口8080
2026-01-15 10:01:20 [ERROR] 数据库连接失败:dial tcp 127.0.0.1:3306: connect: connection refused
2026-01-15 10:01:25 [WARNING] 缓存过期,命中率仅50%
2026-01-15 10:02:00 [ERROR] /api/user接口超时:请求耗时3000ms,超过阈值2000ms
2026-01-15 10:03:00 [INFO] 处理用户请求,user_id=12345
2. 编译并运行程序
bash
# 编译Go程序
go build -o log-analyzer main.go
# 运行工具(指定测试日志文件)
./log-analyzer -file ./test.log
3. 预期输出
正在读取日志文件:./test.log
🔍 检测到 3 行异常日志,正在调用AI分析...
==================== 智能日志分析报告 ====================
📄 分析文件:./test.log
❌ 异常摘要:
第2行: 2026-01-15 10:01:20 [ERROR] 数据库连接失败:dial tcp 127.0.0.1:3306: connect: connection refused
第3行: 2026-01-15 10:01:25 [WARNING] 缓存过期,命中率仅50%
第4行: 2026-01-15 10:02:00 [ERROR] /api/user接口超时:请求耗时3000ms,超过阈值2000ms
🔍 异常原因:
1. 数据库连接失败:MySQL服务未启动或端口3306被占用,导致应用无法建立连接;
2. 缓存命中率低:缓存过期策略不合理,未及时更新缓存数据;
3. 接口超时:/api/user接口处理逻辑耗时过长,或数据库查询未优化。
💡 解决方案:
1. 数据库连接问题:
- 检查MySQL服务状态:systemctl status mysqld
- 验证3306端口是否被占用:netstat -tulpn | grep 3306
- 确认数据库配置(地址、端口、用户名密码)是否正确;
2. 缓存问题:
- 调整缓存过期时间,根据业务场景设置合理的TTL;
- 实现缓存预热机制,避免缓存空窗期;
3. 接口超时问题:
- 优化/api/user接口的SQL查询(添加索引、减少联表);
- 增加接口超时阈值(或异步处理耗时逻辑);
- 增加接口监控,定位具体耗时环节。
==========================================================
六、优化与扩展(生产级建议)
1. 基础优化
- 日志分片:支持超大日志文件(GB级)的分片读取,避免内存溢出;
- 并发处理:多日志文件并行分析(使用Go goroutine);
- 参数配置 :将Ollama模型、异常关键词等配置抽离到
config.yaml文件; - 错误重试 :Ollama调用失败时自动重试(使用
github.com/avast/retry-go)。
2. 功能扩展
- Web化:基于Gin框架封装HTTP接口,提供网页版日志分析工具;
- 定时分析:结合cron定时任务,自动分析指定目录的日志文件;
- 报告推送:分析完成后推送报告到钉钉/企业微信/邮件;
- 多模型支持:适配Qwen、Phi-3等轻量模型,根据需求切换。
3. 性能优化
- 日志过滤:只提取最近N小时的日志,减少AI处理量;
- 模型量化 :使用Ollama的模型量化功能(如
ollama create llama3-quant -f Modelfile),降低显存占用; - 响应缓存:相同日志内容的分析结果缓存到本地,避免重复调用模型。
总结
- 核心流程:该工具的核心逻辑是「日志读取→异常提取→AI分析→报告输出」,利用Go的高效IO处理日志,Ollama的本地大模型完成智能分析,避免依赖云端API;
- 关键要点:Prompt设计决定分析质量(需明确要求模型输出格式)、日志预处理减少无效内容(提升AI分析效率)、本地部署保证数据安全;
- 落地建议:先从测试环境验证,再根据业务日志格式调整异常关键词,最后扩展定时/推送功能适配生产场景。