在后台开发中, 经常遇到服务波动的情况, 一般来说, 在监控系统中可以看到这种波动, 那是否与我们机器上的错误log对应起来了呢? 我们有必要对机器上的错误log进行统计!
规范log中一般会有时间, 假设时间格式为: xxx[2016-11-20 hh:mm:ss]yyy, 那么怎样统计错误log是否集中在某以时间段呢? 写个C++程序吧:
结果:
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
string findTime(const string &str)
{
unsigned int pos = str.find("[201");
if(pos == string::npos)
{
return "[system error]";
}
return str.substr(pos, 21);
}
int main()
{
ifstream in("data.txt"); // data.txt为log文件
string filename;
string line;
vector<string> vecString;
map<string, unsigned int> m;
if(in) // 有该文件
{
while (getline (in, line)) // line中不包括每行的换行符
{
if(line == "")
{
continue;
}
vecString.push_back(line);
string time = findTime(line);
m[time]++;
}
}
else // 没有该文件
{
cout <<"no such file" << endl;
}
map<string, unsigned int>::iterator it;
for(it = m.begin(); it != m.end(); ++it)
{
printf("%s %d\n", it->first.c_str(), it->second);
}
return 0;
}
部分结果如下:
..................
[2016-11-20 12:00:07] 15
[2016-11-20 12:00:08] 23
[2016-11-20 12:00:09] 18
[2016-11-20 12:00:10] 19
[2016-11-20 12:00:11] 13
[2016-11-20 12:00:12] 29
[2016-11-20 12:00:13] 18
[2016-11-20 12:00:14] 21
[2016-11-20 12:00:15] 15
[2016-11-20 12:00:16] 15
[2016-11-20 12:00:17] 14
[2016-11-20 12:00:18] 10
[2016-11-20 12:00:19] 16
[2016-11-20 12:00:20] 20
[2016-11-20 12:00:21] 13
[2016-11-20 12:00:22] 29
[2016-11-20 12:00:23] 15
..................
这个程序有两个毛病: 1. 没有按照频率排序(尽管改一改也可以做到) 2. 实际操作起来, 用起来不爽, 不方便, 不直接。 怎么办呢? 还是求助于awk、sort等命令吧:
cat data.txt | awk -F "2016-" '{printf("[2016-%14.14s]\n", $2)}' | sort |uniq -c|sort -rnk 1 | head -n 10
结果为:
375 [2016- ]
46 [2016-11-20 12:29:07]
41 [2016-11-20 12:27:45]
39 [2016-11-20 12:32:35]
38 [2016-11-20 12:27:20]
38 [2016-11-20 12:24:52]
37 [2016-11-20 12:32:48]
37 [2016-11-20 12:32:09]
36 [2016-11-20 12:27:25]
36 [2016-11-20 12:26:03]
看看, 这是多么爽的结果, 用好工具, 真的能事半功倍
如果要按照时间来排序, 观察随事变变化, 那就去掉sort -rnk 1吧。 还有个问题, 如果是每秒统计, 颗粒度太小, 结果太多, 我们可以改为更常用的按分统计: 如:
cat data.txt | awk -F "2016-" '{printf("[2016-%11.11s]\n", $2)}' | sort |uniq -c|sort -rnk 1 | head -n 10
cat data.txt | awk -F "2016-" '{printf("[2016-%11.11s]\n", $2)}' | sort |uniq -c