nginx服务器日志分析的web实现
博客专区 > 老海 的博客 > 博客详情
nginx服务器日志分析的web实现
老海 发表于3年前
nginx服务器日志分析的web实现
  • 发表于 3年前
  • 阅读 100
  • 收藏 2
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 多站点nginx服务器日志切割后存储到数据库,方便日志数据查看。

      其实GoAccess作为nginx服务器的日志实时分析是不错的,可以在命令行快速地查看统计报告,过滤搜索引擎的ip,查看用户操作系统等,也可以生成html的报告。web呈现的日志分析工具AWStats界面也还不错。不过要想把多台分散的服务器的日志统一查看,还要方便其他Partner查看,感觉还是自己简单搞一个比较好,毕竟不管用什么工具原始的日志数据都是一样的,自己定义过滤方法就好了,于是开始了重复造轮子的工作。

      实现方式是先切割每个站点的日志,然后解析日志文件存入数据库,这个数据库如果用rds的话,分散的数据也可以比较方便的集中存进去。这样之后就可以通过sql来进行过滤,选出需要的数据就可以在web端查看了。

日志切割:

1
2
3
#!/bin/bash
mv/your/log/path/your/log/path-`date+%Y%m%d`
killall -s USR1 nginx

      将脚本加入任务计划,每日执行,即可得到每天的日志,当然也可以压缩一下,这样到时候解析的时候先解压就好了。

      然后就是写php解析文件导入数据库的方法,网上搜搜发现有现成的,那改改就可以用了,数据连接用的mysql_connect(),也不改成pdo了,先执行试试。

解析文件导入数据库代码如下:

addlog.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//数据库连接
functionconnectDB(){
    if(!isset($connect)) {
        $connect= mysql_connect("host","username","password");
        if(!$connect) {
            die('Can not connect to database.');
        }
        mysql_select_db("yourLogDb",$connect);
        mysql_query("SET NAMES utf8",$connect);
        $conn=$connect;
    }
    return$conn;
}
 
/**
 * [loadTxtDataIntoDatabase description]
 * @param  [string]    $splitChar  [spliter]
 * @param  [string]    $file       [filePath]
 * @param  [string]    $table      [tableName]
 * @param  [dbConnect] $conn       [dbConnect]
 * @param  [array]     $fields     [tableFields]
 * @param  [string]    $insertType [INSERT or REPLACE]
 * @return [array]     result
 */
functionloadTxtDataIntoDatabase($splitChar,$file,$table,$conn,$fields=array(),$insertType='INSERT'){
    if(empty($fields))$head="{$insertType} INTO `{$table}` VALUES('";
    else$head="{$insertType} INTO `{$table}`(`".implode('`,`',$fields)."`) VALUES('";
    $end="')";   //生成sql首尾
 
    $f1=fopen($file,'r');
    $tmp=tempnam('/your/temp/file/path','tem');//创建临时文件
    $f2=fopen($tmp,'w');
    while(!feof($f1)){
      $line=fgets($f1);
      //过滤static文件夹下的css、js等静态文件,如果需要这些数据的话可以不用过滤
      if(!strpos($line,'/static/'))fputs($f2,$line);
    }
    fclose($f1);
    fclose($f2);
    rename($tmp,$file);
 
    $sqldata= trim(file_get_contents($file));
    if(preg_replace('/\s*/i','',$splitChar) =='') {
        $splitChar='/(\w+)(\s+)/i';
        $replace="$1','";
        $specialFunc='preg_replace';
    }else{
        $splitChar=$splitChar;
        $replace="','";
        $specialFunc='str_replace';
    }
 
    $sqldata= preg_replace('/(\s*)(\n+)(\s*)/i','\'),(\'',$sqldata);   //删除换行
    $sqldata=$specialFunc($splitChar,$replace,$sqldata);               //替换分隔符
    $query=$head.$sqldata.$end;   //合成sql语句
    if(mysql_query($query,$conn))returnarray(true);
    else{
        returnarray(false,mysql_error($conn),mysql_errno($conn));
    }
}
 
/**
 * [addLogToTabel description]
 * @param  [string] $filepath  [nginxLogPath]
 * @param  [string] $tablename [tableName]
 * @return          result
 */
functionaddLogToTabel($filepath,$tablename){
    $splitChar='yoursplitChar';   //分隔符,要与nginx日志中定义的分割符相同
    $date=date("Ymd",time());
    $file=$filepath.'-'.$date;
    //这里的字段定义与nginxlog里面的默认项相同,可以按需更改
    $fields=array('remote_addr','remote_user','time_local','request','status',
              'body_bytes_s','http_referer','http_user_agent','http_x_forwarded_for');
    $table=$tablename;
    $conn= connectDB();
    $result= loadTxtDataIntoDatabase($splitChar,$file,$table,$conn,$fields);
    if(array_shift($result)){
        echo'Success!';
    }else{
        echo'Failed!--Error:'.array_shift($result).'<br/>';
    }
}

      这里addLogToTabel方法里的分隔符($splitChar)需要定义好,不能是“-”之类的会与nginxlog里面的字段内容冲突的符号,不然执行sql时会报错。

      然后添加一个文件来调用addLogToTabel方法就可以完成解析日志存入数据库的操作了。

调用代码:

site.php
1
2
3
4
5
6
7
require'addlog.php';
try{
    addLogToTabel('/your/log/path','tableName');
}catch(Exception$e) {
    print$e->getMessage();
    exit();
}

      执行site.php,显示“Success!”,数据导入就好了,把site.php也加入任务计划,就可以每天自动解析日志导入数据库了。

      同样的方法可以把nginx的errorlog也导入到数据库中来查看,不过errorlog可能实时查看和处理会更好。

      之后的操作就是通过sql从数据库按需选取数据在页面上显示出来了,比如需要查看真实用户的访问量,就把Googlebot、Baiduspider、bingbot等搜索引擎的数据过滤掉;如果要需要查看特定ip的浏览量,通过GROUP BY就可以统计出;如果需要查看ip对应的地理位置,那就使用一些ip库的api来获取……其他一些复杂的分析也可以基于数据库中的日志数据进行分析了。

      下面是一个站点的单日ip和userAgent浏览量的简单统计结果,搜索引擎的数据还没过滤掉的情况:

ip

useragent

      一个简单的web端日志查看应用差不多弄好了,更多的统计分析功能可以慢慢加上去。由于是用数据库存储日志数据,后期访问量大了产生很多日志的时候会影响查询速度,新增日志数据的开销也会增大,不过现在还没到那个程度,积累一段时间的数据先用水平分表来解决一下就好了。

标签: nginx日志分析
共有 人打赏支持
粉丝 3
博文 3
码字总数 0
作品 3
×
老海
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: