从零构建生产级日志分析体系:Flask + Docker + Nginx 完整实战

又到周末了,使用 claude 做点东西的心思又来了!那就找找工作中的痛点问题。
我们有个Java+Tomcat的 老项目,平时查日志只能去服务器上用命令来看,一点也不方便(后面新做的项目,很多框架里都自带了日志功能。还有的项目是用的 ElasticSearch)。
那就趁着周末,动手做一个吧!

我有一个Tomcat日志文件,平时用命令行查起来很不方便,想着可以做一个可视化的系统

如果不用ElasticSearch,自己用AI写一个可视化的,你觉得靠谱吗

我服务器是CentOS,上面有docker,最新日志是
/home/tomcatlog/jkwh_app_out.log,今天之前的日志会自动按日期生成目录,归纳到/home/tomcatlog/backuplog
下,如/logs_20251017/jkwh_app_out.log.1

和CHATGPT几轮沟通后,一个基本的方案就出来了!

一、你当前日志结构说明

当前正在写入的实时日志  └── backuplog/
      ├── logs_20251017/jkwh_app_out.log.1
      ├── logs_20251016/jkwh_app_out.log.1
      ├── logs_20251015/jkwh_app_out.log.1
      └── ... (按日期归档) ```
✅ 非常标准,实时日志 + 历史归档。
---
##  二、目标系统设计
我们做一个 Docker 应用,支持两个功能:
| 模块     | 功能描述                                                   | |
:----- | :----------------------------------------------------- | |
实时日志监控 | 通过 WebSocket 实时读取 `/home/tomcatlog/jkwh_app_out.log`   | |
历史日志浏览 | 自动列出 `/home/tomcatlog/backuplog` 下的日期目录,点击即可加载对应日志文件内容 |
---
## ⚙️ 三、目录映射设计
容器内目录映射:
| 主机路径                               | 容器内路径                   | 作用
| | :--------------------------------- | :---------------------- |
:----- | | `/home/tomcatlog/jkwh_app_out.log` |
`/app/logs/current.log` | 实时日志   | | `/home/tomcatlog/backuplog`
| `/app/backuplog`        | 历史日志目录 |
---
##  四、项目结构(完整方案)
```log-visualizer/  ├─ app.py                # Flask + SocketIO 后端
├─ templates/  │   └─ index.html        # 前端页面  ├─ requirements.txt
└─ Dockerfile ```
---
###  requirements.txt
```flask flask-socketio watchdog ```
---
### ⚙️ app.py
```python from flask import Flask, render_template, jsonify,
send_file, request from flask_socketio import SocketIO import os,
time, threading
app = Flask(__name__) socketio = SocketIO(app,
cors_allowed_origins="*")
CURRENT_LOG = "/app/logs/current.log" BACKUP_DIR = "/app/backuplog"
def tail_current_log():
    """持续读取实时日志"""
    if not os.path.exists(CURRENT_LOG):
        print(f"Log file not found: {CURRENT_LOG}")
        return
    with open(CURRENT_LOG, "r", encoding="utf-8", errors="ignore") as f:
        f.seek(0, os.SEEK_END)
        while True:
            line = f.readline()
            if line:
                socketio.emit("log_line", {"data": line})
            else:
                time.sleep(0.2)
@app.route("/") def index():
    return render_template("index.html")
@app.route("/api/backups") def list_backups():
    """列出所有日期目录"""
    dirs = sorted(os.listdir(BACKUP_DIR), reverse=True)
    return jsonify([d for d in dirs if d.startswith("logs_")])
@app.route("/api/view_log") def view_log():
    """查看指定日期的日志"""
    date_dir = request.args.get("date")
    log_path = os.path.join(BACKUP_DIR, date_dir, "jkwh_app_out.log.1")
    if not os.path.exists(log_path):
        return "Log not found", 404
    return send_file(log_path, mimetype="text/plain")
if __name__ == "__main__":
    threading.Thread(target=tail_current_log, daemon=True).start()
    socketio.run(app, host="0.0.0.0", port=8080) ```
---
###  templates/index.html
```html      
Tomcat 日志监控系统   
posted @ 2025-11-18 15:50  gccbuaa  阅读(8)  评论(0)    收藏  举报