开发了一个 nginx 日志分析面板 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
MagicCoder
V2EX    分享创造

开发了一个 nginx 日志分析面板

  •  1
     
  •   MagicCoder 2 天前 1872 次点击

    前言

    最近在优化网站访问链路的过程中,部署了一套 WAF 防火墙,它大部分功能都做的挺好,美中不足的地方就是针对于网站访客的相关功能需要付费( 3600 元/年)才能用。

    付费是不可能付费的,找了一圈 nginx 日志分析的开源项目,大部分都做的挺简陋的,要么就是做的很重,需要部署其他服务。

    既然找不到合适的,那就自己动手写一个吧!

    如果看不到图片的话,直接访问我个人网站上发布的。https://www.kaisir.cn/post/186

    实现效果

    做了 4 个模块对日志数据进行分析。

    • 访问概况
    • 数据日报
    • 实时访问
    • 访问明细

    image-20260108124900609

    访问概况

    概况模块中,做了 8 个维度的数据分析。

    核心指标

    在这个维度中,针对 http 状态码、浏览量、访客数、会话数做了更细致的划分。

    image-20260108125517344

    每一个划分中,在详情面板里,都可以看到这个访客在什么时间做了什么事情。

    image-20260108125954027

    image-20260108130323366

    image-20260108130405011

    image-20260108130452437

    趋势分析 & 新老访客

    这一部分可以看到每天的访问趋势以及当天与前一天的新老访客占比。

    image-20260108130725966

    来路、受访页、入口页

    这部分可以看到访客的来源,以及每个路径的访问次数。

    image-20260108131048943

    地域 & 终端设备

    这部分可以看到每个省份的访问情况以及访问设备的分布情况。

    image-20260108131213706

    数据日报

    在这个模块中,可以看到每天的浏览量、访客数、平均访问时长等信息。

    image-20260108134815067

    image-20260108140538356

    实时访问

    在这个模块里,可以查看最近 5/15/30 分钟内的访问情况

    image-20260108141207205

    访问明细

    这个模块就以表格的形式展示每一条日志。

    image-20260108141436301

    如何使用

    为了方便使用,我已经将这个项目打包成镜像发布到 dockerhub 上了,镜像名为magiccoders/nginxpulse,可以通过 docker 的形式使用,也可以通过 docker compose 的形式使用。

    需要传入的参数:

    • WEBSITES 它的值是个数组,一个对象就是一个网站,需要传入网站名、日志路径、网址(或者内网 ip ,主要用于站内/站外的区分)
    • ports 端口映射,容器内暴露出来的端口是 8088
    • volumes 文件挂载,这里需要挂载:日志文件、容器内产生的数据文件、时区

    此处我以 docker compose 的形式举例:

    version: "3" services: nginxpulse: image: magiccoders/nginxpulse:latest container_name: local_nginxpulse ports: - "9200:8088" environment: WEBSITES: '[{"name":"神奇的程序员","logPath":"/var/log/nginx/access.log","domains":["kaisir.cn","www.kaisir.cn"]}]' #domains 用于“来源( referer )统计”的站内/站外分类 PV_EXCLUDE_IPS: '["127.0.0.1", "::1", "10.10.0.1", "192.168.30.21"]' #pv 统计时需要排除的 ip volumes: - ./nginx_data/logs/all/access.log:/var/log/nginx/access.log - ./nginxpulse_data:/app/nginxpulse_data - /etc/localtime:/etc/localtime restart: unless-stopped 

    写在最后

    至此,文章就分享完毕了。

    我是神奇的程序员,一位前端开发工程师。

    如果你对我感兴趣,请移步我的个人网站,进一步了解。

    25 条回复    2026-01-09 13:41:03 +08:00
    NouveauNom
        1
    NouveauNom  
       2 天前
    建议加入一个查看 url 记录,请求时长,包体,请求内容。就像抓包软件那样,可以方便排查接口问题,哪里卡了之类的。之前见某家的 cdn 有这个功能。很强。后面自己找没找到合适的。
    4ark
        2
    4ark  
       2 天前
    看着挺不错,以后有需要可以接一下
    4ark
       
    4ark  
       2 天前
    PS:会考虑开源吗?
    MagicCoder
        4
    MagicCoder  
    OP
       2 天前
    @4ark 晚点开源,现在代码写的比较乱,我得先整理下
    MagicCoder
        5
    MagicCoder  
    OP
       2 天前
    @NouveauNom 可以,我晚点看看
    Daybyedream
        6
    Daybyedream  
       2 天前
    我们是日志发到日志服务器里,grafana 加个数据源,要啥自己弄就完事。
    Kirkcong
        7
    Kirkcong  
       2 天前   1
    @Livid 推广或分享创造
    renchong
        8
    renchong  
       2 天前
    楼主用的什么 waf 防火墙
    MagicCoder
        9
    MagicCoder  
    OP
       2 天前
    @renchong 就雷池
    lneoi
        10
    lneoi  
       2 天前
    挺漂亮的
    brobot
        11
    wbrobot  
       2 天前
    goaccess 用过吗?
    MagicCoder
        12
    MagicCoder  
    OP
       2 天前
    @wbrobot 之前搜到过,看到那个 UI 太古老了
    alenryuichi
        13
    alenryuichi  
       2 天前
    挺不错的 赞
    stinkytofux
        14
    stinkytofux  
       2 天前
    @MagicCoder #9 雷池收费的地方太多了, 基本上点啥都要收费. 还有没有其他可以平替的.
    MagicCoder
        15
    MagicCoder  
    OP
       2 天前
    @stinkytofux 没找到能平替的 现在感觉他能防住一些攻击就够了
    mgcnrx11
        16
    mgcnrx11  
       2 天前
    好漂亮。有个问题,一个 nginx 反向代理了多个网址。日志可以区分吗?
    MagicCoder
        17
    MagicCoder  
    OP
       2 天前
    @mgcnrx11 这个在 nginx 里主动记录进日志应该就能区分了
    FeranyDev
        18
    FeranyDev  
       2 天前
    nginx 输出的日志有什么格式要求吗,我这个好像获取不到日志。
    bpf2049
        19
    bpf2049  
       2 天前
    ,同使用雷池,期待开源
    MagicCoder
        20
    MagicCoder  
    OP
       2 天前
    @FeranyDev 不能自己定义格式,需要保持他的默认规则 像这样:
    4.213.160.187 - - [31/Dec/2025:15:40:45 +0800] "GET /wp-includes/index.php HTTP/1.1" 404 41912 "https://www.google.fr/" "Mozilla/5.0 (Linux; Android 13; SM-S908E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36"
    4.213.160.187 - - [31/Dec/2025:15:40:46 +0800] "GET /wp-includes/js/crop/cropper.php HTTP/1.1" 404 41912 "https://www.yahoo.com/" "Mozilla/5.0 (Linux; Android 12; 2201116SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36"
    4.213.160.187 - - [31/Dec/2025:15:40:48 +0800] "GET /wp-includes/js/dist/ HTTP/1.1" 404 41912 "https://www.google.fr/" "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1"
    10.10.0.1 - - [31/Dec/2025:15:40:48 +0800] "GET / HTTP/1.1" 200 19946 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 SafeLine-CE/v9-2-8"
    FeranyDev
        21
    FeranyDev  
       2 天前
    @MagicCoder #20 好吧,我还说他默认给的不全来着。期待能出探针用于获取外部服务器的日志。
    GetOctober
        22
    GetOctober  
       2 天前
    ui 用的什么组件?挺好看的
    dddddddddd
        23
    dddddddddd  
       1 天前
    期待开源
    MagicCoder
        24
    MagicCoder  
    OP
       1 天前
    @GetOctober 手写的
    MagicCoder
        25
    MagicCoder  
    OP
       1 天前
    @dddddddddd 嗯嗯 整理好了就开
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2637 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 04:04 PVG 12:04 LAX 20:04 JFK 23:04
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86