Analog使用中的一些技巧和总结

简介: Analog是一款用来快速处理日志的开源工具,具有很高的效率,但是生成的结果并不美观,本文就analog使用过程中的一些问题进行总结,讨论如何对analog进行深度的定制使用。 处理经过压缩的多个日志文件 analog可以读取gz格式压缩的日志文件,并且支持读取多个文件。

Analog是一款用来快速处理日志的开源工具,具有很高的效率,但是生成的结果并不美观,本文就analog使用过程中的一些问题进行总结,讨论如何对analog进行深度的定制使用。

处理经过压缩的多个日志文件

analog可以读取gz格式压缩的日志文件,并且支持读取多个文件。这个选项在我们有多台前端Web服务器的时候可以用上,读取多个日志文件,可以通过两种方式实现:在配置文件中指定多行LOGFILE,或者在单个文件中使用通配符,后一种方法是最常用到的。

LOGFILE new1.log,old*.log
LOGFILE new2.log

Analog配置文件相关的设置技巧

Analog启动时,会读取配置文件和命令行中的配置信息,配置文件默认是 analog.cfg ,如果想要命令行中的配置信息优先级比较高,需要加上 –G 参数,这样才能在有重复的配置项时,以命令行中的为准。

analog支持读多个配置文件,但是如果多个配置文件中的配置项不同,就会发生混乱。如果真的需要读取多个配置文件,建议将一些基础性的配置信息放在默认配置文件中,一些个性的配置信息通过 +ganalog.x.cfg 包含进来。

analog中的配置项信息非常多,有些在命令行下有缩写的形式,有一些则没有,如果希望在命令行中指定没有缩写的配置信息,可以使用下面的形式,注意命令之间不能有空格。

+C”UNCOMPRESS *.gz gzcat”

./analog/analog -G +ganalog.cfg +Oanalog_reports/bizhouse/bizhouse-110221.html /data0/dpoolapachelog/110221/110221.biz.house.sina.com.cn_*.gz +C"HOSTNAME biz.house.sina.com.cn"

analog中关于日志文件和日志文件格式的配置项都是 cumulative (累加)的。如果我们的日志有两种格式,那么配置文件中写两行 LOGFORMAT 就可以保证不管遇到什么样的日志格式,都可以正常执行,这个特性在处理情况复杂的日志文件时非常有用。

配置HTML报告界面

图标和图标的链接

LOGO http://watchdog.com.cn/static/v1.0/logo.png
LOGOURL http://watchdog.com.cn

如何处理多个网站的日志文件

在我们的环境中,有很多个项目,日志的存储方式如下

/data/logs/2011-02-23/domain.a.com.cn-2011-02-23.ip1.tar.gz

/data/logs/2011-02-23/domain.a.com.cn-2011-02-23.ip2.tar.gz

/data/logs/2011-02-23/domain.b.com.cn-2011-02-23.ip1.tar.gz

/data/logs/2011-02-23/domain.b.com.cn-2011-02-23.ip2.tar.gz

目录中存在很多日志文件,使用analog进行分析比较麻烦的问题是这些日志的日志格式如果不一样,就不太好办。幸好 analog 的配置文件中对于日志格式的支持是累加的,可以在配置文件中使用这种方式进行配置。

APACHEDEFAULTLOGFORMAT (%h %l %u %t %T \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Cookie}i\")
APACHEDEFAULTLOGFORMAT (%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\")

只要配置的日志格式包括了所有可能的日志格式,我们就可以使用一个配置文件来进行所有日志文件的分析了。为了分析众多的日志文件,我写了一个脚本,通过读取一个项目列表文件,分析目录中对应的项目日志。然后汇总到一个数据库中进行展示,这样就方便我们查看多个网站的日志统计数据。分享如下:Wd_analog.pl

#!/usr/bin/perl -w

# This script use analog to analyze all the apache logs and send main result to watchdog.sample.com.cn site
# Author:shiqiang at 2011-2-24
# Revision History:
# 2011-02-25 shiqiang Use Getopt::Long to parse parameters
# 2011-02-25 shiqiang add some parameters to make this script common to use
# 2011-02-24 shiqiang create file

use strict;
use Getopt::Long;
use diagnostics;
use LWP;
my $version = "1.0";
my $usage = "Welcome to use wd_analog.pl $version\n";
my $help = 0;

#Declare default values for variables
my $verbose = 0;
my $debug = -1;
my $config = "project_list";
chomp(my $date = `date -d '1 day ago' +%y%m%d`);
chomp(my $report_date = `date -d '1 day ago' +%Y-%m-%d`);

chomp(my $base_path = `pwd`);
# Analog binary path
my $analog = ("/data0/vhosts/analog.sample.com.cn/htdocs/analog/analog");
my $log_store_path = $base_path . "/computer_result/";
my $log_file = $base_path . "/computer_result/wd_analog_log";
my $apache_log_path = "/data0/dpoolapachelog/";

#process options from command line
GetOptions(
    'verbose+' => \$verbose,
    'config|f=s' => \$config,
    'date|d=s' => \$date,
    'help|?' => \$help,
    'debug:i' => \$debug
);

if( $help ){
    print $usage;
    print "Sample:wd_analog.pl -config=config_file_path -date=cur_date\n";
    exit(0);
}

die "Config file doesn't exists or incorrupt" if ! -f $config;
my @content = `cat $config`;
my %project_list = ();

#
# Parse the project domain and generate the module name
# we trim the "www" prefix and ".com\.cn\" suffix to create the module name
#
for my $value ( @content ){
    chomp( $value );
    my $module = $value;
    $module =~ s/www|sina\.com\.cn|\.com\.cn|\.cn|\.com|\.//g;
    $project_list{$value} = $module;
}

#
# Iterate all the project and run analog
#
my $browser = LWP::UserAgent->new();
my @keys = sort keys %project_list;
for my $key ( @keys ) {
    # Define trhee parameters used for analog
    my $module = $project_list{$key};
    my $domain_keyword = $key;
    my $cur_date = $date;
    $log_store_path .= $module;
    `mkdir -p $log_store_path` if ! -d $log_store_path;
    #`echo "=================================" >> $log_file 2>1&`;
    `echo $key=$project_list{$key} >> $log_file 2>1&`;
    `./analog/analog -G +ganalog.cfg +O$log_store_path/$module-$cur_date.txt $apache_log_path$date/$date.*${domain_keyword}_*.gz +C"HOSTNAME $domain_keyword" +C"OUTPUT COMPUTER"`;

    # Parse the stat result and do some post processing
    my %stat;
    my $k;
    foreach $k ("B7", "BT", "CL", "F7", "FL", "FRd", "FRh", "FRmi", "FRmo", "FRy", "H7", "LRd", "LRh", "LRmi", "LRmo", "LRy", "N7", "NF", "NH", "P7", "PR", "R7", "RR", "S7", "SR", "UL") { $stat{$k} = 0; }
    $stat{HN} = "";
    # Analog doesn't necessarily create lines for all values
    open(INPUT, "$log_store_path/$module-$cur_date.txt" ) or die "Faile to open stat result file $domain_keyword:$log_store_path/$module-$cur_date.txt";
    while (<INPUT>) {
        chomp;
        if (m{^x    FR    (\d+)\t(\d+)\t(\d+)\t(\d+)\t(\d+)$}) {
            ($stat{FRy}, $stat{FRmo}, $stat{FRd}, $stat{FRh}, $stat{FRmi}) = ($1, $2, $3, $4, $5)
        }
        elsif (m{^x    LR    (\d+)\t(\d+)\t(\d+)\t(\d+)\t(\d+)$}) {
            ($stat{LRy}, $stat{LRmo}, $stat{LRd}, $stat{LRh}, $stat{LRmi}) = ($1, $2, $3, $4, $5)
        }
        elsif (m{^x    ([A-Z][A-Z7])    ([^/]+)$}) { $stat{$1} = $2; }
    }

    my $pv = 0;
    $pv = $stat{PR}/$stat{NH} if $stat{NH} ne '0';
    my $response = $browser->post("http://watchdog.sample.com.cn/log/save", ["domain"=>$stat{HN},"requests"=>$stat{SR},"pages"=>$stat{PR},"pv"=> $pv,"traffic"=>$stat{BT},"uip"=>$stat{NH},"stats_date"=>"$report_date"]);;
    die "Post data failed : $response->content !" if $response->content ne '0';
    $log_store_path = $base_path . "/computer_result/";
}

 

 

Analog中几种固定的日志格式

 

Common format, LOGFORMAT COMMON

 

jay.bird.com - fred [25/Dec/1998:17:45:35 +0000]
      "GET /~sret1/ HTTP/1.0" 200 1243
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%j%w%r%wHTTP%j" %c %b)
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%j%w%r" %c %b)
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%r" %c %b)
Microsoft common format, LOGFORMAT MS-COMMON
jay.bird.com - fred [25/Dec/1998:17:45:35 +0000]
      "GET /~sret1/ "HTTP/1.0" 200 1243
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%j%w%r%w"HTTP%j" %c %b)
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%j%w%r" %c %b)
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%r" %c %b)
Combined log, LOGFORMAT COMBINED
jay.bird.com - fred [25/Dec/1998:17:45:35 +0000] "GET /~sret1/ HTTP/1.0" 200
      1243 "http://www.site.com/" "Mozilla/2.0 (X11; I; HP-UX A.09.05)"
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%j%w%r%wHTTP%j" %c %b "%f" "%B")
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%j%w%r" %c %b "%f" "%B")
LOGFORMAT (%S %j %u [%d/%M/%Y:%h:%n:%j] "%r" %c %b "%f" "%B")
Referrer log, LOGFORMAT REFERRER
[25/Dec/1998:17:45:35] http://www.site.com/ -> /~sret1/
or http://www.site.com/ -> /~sret1/
LOGFORMAT ([%d/%M/%Y:%h:%n:%j] %f -> %*r)
LOGFORMAT (%f -> %*r)
Browser log, LOGFORMAT BROWSER
[25/Dec/1998:17:45:35] Mozilla/2.0 (X11; I; HP-UX A.09.05)
LOGFORMAT ([%d/%M/%Y:%h:%n:%j] %B)
Microsoft log, North American dates, LOGFORMAT MICROSOFT-NA
192.64.25.41, -, 12/25/98, 17:45:35, W3SVC1, HOST1, 192.16.225.10,
      2178, 303, 1243, 200, 0, GET, /~sret1/, -,
192.64.25.41, -, 12/25/2001, 17:45:35, W3SVC1, HOST1, 192.16.225.10,
      2178, 303, 1243, 200, 0, GET, /~sret1/, -,
LOGFORMAT (%S, %u, %m/%d/%Z, %h:%n:%j, W3SVC%j, %j, %v,
      %T, %j, %b, %c, %j, %j, %r, %q,)
LOGFORMAT (%*S, %*u, %m/%d/%Z, %h:%n:%j, %j)
Microsoft log, international dates, LOGFORMAT MICROSOFT-INT
192.64.25.41, -, 25/12/98, 17:45:35, W3SVC1, HOST1, 192.16.225.10,
      2178, 303, 1243, 200, 0, GET, /~sret1/, -,
192.64.25.41, -, 25/12/2001, 17:45:35, W3SVC1, HOST1, 192.16.225.10,
      2178, 303, 1243, 200, 0, GET, /~sret1/, -,
LOGFORMAT (%S, %u, %d/%m/%Z, %h:%n:%j, W3SVC%j, %j, %v,
      %T, %j, %b, %c, %j, %j, %r, %q,)
LOGFORMAT (%*S, %*u, %d/%m/%Z, %h:%n:%j, %j)
WebSite log, North American dates, LOGFORMAT WEBSITE-NA
12/25/98 17:45:35  jay.bird.com  host1  Server  fred  GET  /~sret1/
   http://www.site.com/    Mozilla/2.0 (X11; I; HP-UX A.09.05)  200  1243  2178
LOGFORMAT (%m/%d/%y %h:%n:%j\t%S\t%v\t%j\t%u\t%j\t%r\t%f\t%j\t%B\t%c\t%b\t%T)
WebSite log, international dates, LOGFORMAT WEBSITE-INT
25/12/98 17:45:35  jay.bird.com  host1  Server  fred  GET  /~sret1/
   http://www.site.com/    Mozilla/2.0 (X11; I; HP-UX A.09.05)  200  1243  2178
LOGFORMAT (%d/%m/%y %h:%n:%j\t%S\t%v\t%j\t%u\t%j\t%r\t%f\t%j\t%B\t%c\t%b\t%T)
MacHTTP format, LOGFORMAT MACHTTP
12/25/98  17:45:35   OK    jay.bird.com  /~sret1/  1243
LOGFORMAT (%m/%d/%y\t%h:%n:%j \t%C%w%S\t%r\t%b)

参考资料:
1、Analog Docs
2、Logwrangler
3、Perl Doc Getopt::Long

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
Oracle Java Unix
Java/JDK下载、安装与环境变量配置超详细教程(2022更新)保姆级,秒会
Java/JDK下载、安装与环境配置超详细教程(2022更新)保姆级,小白秒会[学习必备,建议收藏]。包含JDK8、JDK11、JDK17、JDK19等,本文将从JDK的下载与安装讲起,在从配置到第一个HelloWrold实践结束。在观看本文前我们需要知道JDK是什么,有什么作用?JDK是Java的开发工具包,包括JVM虚拟机,核心类库,开发工具。
3160 0
Java/JDK下载、安装与环境变量配置超详细教程(2022更新)保姆级,秒会
|
前端开发 JavaScript
HTML+CSS+JS 实现一个漂亮的登陆页面
HTML+CSS+JS 实现一个漂亮的登陆页面
408 1
HTML+CSS+JS 实现一个漂亮的登陆页面
|
6月前
|
JavaScript 前端开发
JQuery入门到精通教程()
JQuery入门到精通教程()
35 0
|
8月前
|
机器学习/深度学习 前端开发 数据可视化
Streamlit 入门教程:构建一个Dashboard
Streamlit 是一个用于创建数据科学和机器学习应用程序的开源 Python 库。它的主要目标是使开发人员能够以简单的方式快速构建交互式的数据应用,而无需过多的前端开发经验。Streamlit 提供了一种简单的方法来转换数据脚本或分析代码为具有可视化界面的应用程序,这些应用程序可以通过网络浏览器访问。
355 2
|
存储 iOS开发 UED
iOS 性能检测新方式​——AnimationHitches
iOS 性能检测新方式​——AnimationHitches
iOS 性能检测新方式​——AnimationHitches
|
前端开发 Java Windows
JDK1.8下载、安装和环境配置教程(详细)
JDK1.8下载、安装和环境配置教程(详细)
1817 0
JDK1.8下载、安装和环境配置教程(详细)
|
API 开发工具 Python
xlwings库 | Excel与Python的完美结合(附使用文档)
xlwings库 | Excel与Python的完美结合(附使用文档)
1673 0
xlwings库 | Excel与Python的完美结合(附使用文档)
|
XML 存储 JSON
高德APP启动耗时剖析与优化实践(iOS篇)
最近高德地图APP完成了一次启动优化专项,超预期将双端启动的耗时都降低了65%以上,iOS在iPhone7上速度达到了400毫秒以内。就像产品们用后说的,快到不习惯。算一下每天为用户省下的时间,还是蛮有成就感的,本文做个小结。
高德APP启动耗时剖析与优化实践(iOS篇)
|
XML druid Java
SpringBoot中如何使用xml方式整合Mybatis? | 带你读《SpringBoot实战教程》之二十
本节介绍了SpringBoot中使用xml方式整合Mybatis的详细过程。
SpringBoot中如何使用xml方式整合Mybatis? | 带你读《SpringBoot实战教程》之二十
|
监控 Apache
awstats搭建及使用心得
工作环境: 操作系统:RedHat 4.8 软件版本:apache是系统自带的(你的服务器上只有一个http服务器),awstats版本是6.5。 我先模拟服务器上只有一个系统自带的http服务器的情况: 将awstats上传到你的linux服务器的/root目录下 ...
1036 0