Eclipse Test and Performance Tools Platform,第 2 部分: 监视应用程序
2009-12-19 00:00:00 来源:WEB开发网开始之前
关于本系列
为应用程序编写代码只是交付健壮的产品质量的程序所需的漫长过程的第一阶段。必须对代码进行测试,以检验它的操作和准确性。往往还必须对代码进行分析,以便消除性能瓶颈和资源浪费(尤其是内存)。还必须对代码进行监视,以便对故障进行定位、识别使用模式、寻找进一步增强和优化的机会以及探测入侵尝试和实际的入侵。
Eclipse Test and Performance Tools Platform(TPTP)是一种软件体系结构以及几个扩展了 Eclipse 平台的组件(到目前为止),包括测试、性能和监视工具。这个 “Eclipse Test and Performance Tools Platform” 系列讲解 TPTP 的功能。第 1 部分 演示了如何分析 Java™ 应用程序。第 2 部分演示如何捕获任意的日志文件,并将它们转换为得到广泛支持的 Common Base Events(CBE)格式。第 3 部分将解释如何管理应用程序测试。
关于本教程
本教程讲解如何使用 Eclipse TPTP 的功能将典型的应用程序日志文件转换为 CBE 格式。利用少量规范,再进行一些编码工作来创建一系列规则,就可以将任何日志文件转换为一种统一的结构化的格式。然后,就可以使用 Eclipse TPTP 和其他专用工具,快速地组合、处理和分析使用模式、性能和错误。
目标
在本教程中,要学习如何编写一个适配器(adapter),将典型的 Linux® 软件服务日志文件转换为 CBE 数据。将使用 Eclipse TPTP Adapter Configuration Editor 逐渐创建转换并进行调试,然后用 Generic Log Adapter(GLA)对数据进行输入、转换和输出。
前提条件
您应该具备软件开发经验并了解整个软件开发生命周期,包括测试和分析。还应该熟悉从命令行安装软件,以及设置和管理 shell 和系统环境变量,比如 shell 的 PATH 和 Java CLASSPATH。另外,具备阅读和编写正则表达式的经验也很重要。了解 Eclipse 和 Eclipse 用户界面(UI)范型也是有帮助的。
系统需求
可以在具有 JVM 的任何系统上运行 Eclipse,比如 Solaris、Linux、Mac OS X 或 Windows。如果系统上没有安装 JVM 和 Eclipse,那么所有软件至少需要 300 MB 的空闲磁盘空间。还需要有足够的空闲物理内存来运行 JVM。一般来说,建议使用 64 MB 或更多的空闲物理内存。
必须在 UNIX®、Linux®、Mac OS X 或 Microsoft® Windows® 系统上安装几个软件包。需要一个 Java 虚拟机(Java Virtual Machine,JVM)、Eclipse SDK 的一个副本、Eclipse TPTP 运行时的一个副本以及 Eclipse TPTP 所依赖的几个软件。还需要 Eclipse TPTP GLA,用于对独立应用程序或您自己的应用程序中的日志文件进行转换。下面是所需的所有软件:
从 Sun Microsystems 或 IBM 下载 Java 技术
Eclipse V3.1 Software Development Kit(SDK)
Eclipse Modeling Framework(EMF) SDK V2.1
XML Schema Infoset Model(XSD) SDK V2.1
Version 1.1.1 of Eclipse Unified Modeling Language(UML) 2
Eclipse TPTP 运行时
GLA 运行时
对日志文件进行转换和分析
为了支持以后的监视过程,复杂的应用程序(尤其是需要连续运行的应用程序)在开发期间通常会设计输出日志文件 的功能,日志文件是对应用程序活动的记录。一些活动是详细的内部诊断信息,这些信息对于隔离 bug 或者分析与其他系统和软件组件的交互是很重要的。日志中记录的一些活动可能是由应用程序本身发起的 —— 比如,读取配置文件或打开要监听的端口。其他活动可能是由对服务的请求生成的。
问题:对遗留应用程序的监视
根据应用程序的用途,系统管理员可能会不定期地查看程序的日志文件 —— 当发生错误时,甚至是在处理紧急事件时。另外,日志常常能够提供大量有价值的历史信息。例如,在 Apache HTTP Server 日志中可以找到通信流量和使用模式信息。
如果所有日志文件都至少捕获了最基本的信息,那么是很理想的。如果所有日志文件的格式都是一致的,那就更好了,尤其是从系统管理员的角度来看。一致性会使读取日志容易得多,有助于开发自动化工具(而且会大大减少开发成本),从而能够自动地从大量信息中筛选出重要的事件。
但是这种一致性是不现实的。应用程序是各种各样的,底层的操作系统设施和编程语言库也是不一样的。一些应用程序(“遗留的应用程序”)是 “顽固不化” 的,无法对它们进行调整,从而取得一致性。另外,昂贵而又稀缺的开发人员资源往往都用在新特性上了,没有时间去对原有特性进行翻新。
解决方案:对日志文件数据进行转换
既然理想情况是不现实的,而且认识到一个解决方案无法满足所有需求,那么更可行的办法就是对日志文件数据进行转换,从而满足某一事实标准并应用现代的分析工具。例如,在为记录、跟踪和分析事件(事件是指在计算系统中发生的情况)定义通用标准的研究工作中产生了 CBE 格式。CBE 数据是基于 XML 的,现在有许多工具能够处理和分析 CBE 数据。
然而,尽管从任意日志文件转换到 CBE 可能是可行的,但是这一过程可能不容易,也不便宜。考虑到应用程序的种类繁多,日志文件格式的数量也非常多,编写这么多转换本身就是一项繁重的任务。
Eclipse TPTP GLA 和 Adapter Configuration Editor 简化了转换的创建过程,由此简化了迁移到 CBE 的过程。GLA 在日志文件上应用由 Adapter Configuration Editor 创建的适配器 并产生 CBE 数据。Adapter Configuration Editor 可以运行手工建立的 Java 类(静态适配器(static adapter)),也可以运行一系列规则将日志文件分割成记录、字段和值,并将它们组合成 CBE 数据。后一种形式的适配器称为基于规则的适配器(rules-based adapter),它们不需要编写代码。而且,更好的是,Adapter Configuration Editor 在 Eclipse 中运行,提供了一个强大的适配器开发环境,在这个环境中可以逐渐地定义和测试自己的适配器。最后,还可以选择将 GLA 与自己的代码集成起来或者使用第三方工具,比如 IBM Log and Trace Analyzer,从而探测和研究产生的 CBE 事件文件。
本教程讲解如何使用 Eclipse TPTP GLA 和 Adapter Configuration Editor 的功能将典型的 Linux 应用程序日志文件转换为 CBE 事件。只要有日志文件在手并具备一点儿正则表达式知识,就能够将日志转换为统一的结构化的 CBE 格式。
安装所需的软件和组件
在开始之前,必须安装和设置所需的软件和组件(见 “前提条件”)。
安装 J2RE V1.4
下载并安装 Version 1.4 或 1.5(也称为 Version 5.0)。(如果您的系统已经安装了 J2RE V1.4 或更高版本,那么可以跳过这一步。)
通常,JRE 作为自解压的二进制代码发布。如果将 J2RE 包下载到自己的主目录,安装(在 Linux 上)通常很容易,见清单 1。
清单 1. J2RE V1.4 安装% cd ~
% mkdir ~/java
% cd ~/java
% mv ~/jre-1_5_0_06-linux-i586.bin .
% chmod +x jre-1_5_0_06-linux-i586.bin
% ./jre-1_5_0_06-linux-i586.bin
...
% rm ./jre-1_5_0_06-linux-i586.bin
% ls -F
jre1.5.0_06/
清单 1 中的命令安装 J2RE V1.5,但是安装 J2RE V1.4 的步骤是一样的(只是文件名不同)。
安装 Eclipse V3.1 SDK
下载适合自己平台的 Eclipse V3.1 SDK。可以在 Eclipse Downloads 找到这个 SDK。通常,安装时只需将 Eclipse tar 文件(.tar.gz)解压到您选择的目录中。
例如,如果使用 Linux,那么下载 Eclipse V3.1 SDK tar 文件并使用清单 2 中的命令将它解压到一个目录(比如 ~/java/)。
清单 2. 安装 Eclipse V3.1 SDK% cd ~/java
% mv ~/eclipse-SDK-3.1.1-linux-gtk.tar.gz .
% tar zxvf eclipse-SDK-3.1.1-linux-gtk.tar.gz
...
% rm eclipse-SDK-3.1.1-linux-gtk.tar.gz
为了确认已经成功地安装了 Eclipse,留在解压 Eclipse 的目录中,确保 java 可执行文件在 PATH 中并运行 java -jar eclipse/startup.jar。例如:
清单 3. 检验安装% export JAVA_DIR=$HOME/java
% export JAVA_HOME=$JAVA_DIR/jre1.5.0_06
% export PATH=$JAVA_HOME/bin
% export CLASSPATH=$JAVA_HOME
% cd $JAVA_DIR
% java -jar eclipse/startup.jar
如果 Eclipse 提示您为自己的工作空间选择一个目录,那么使用 $HOME/java/workspace。这个目录将容纳您在 Eclipse 中创建的所有项目。(当然,如果有许多项目,以后可以选择其他目录,让每个工作空间只包含一个项目。)现在退出 Eclipse 以便安装 Eclipse TPTP、它需要的软件和 GLA。
安装 TPTP 和 GLA 运行时
Eclipse TPTP 运行时包含创建、调试和运行适配器所需的软件。为了安装 Eclipse TPTP 软件,需要下载 Eclipse TPTP 和 GLA 运行时。它们通常以 zip 格式发布。将这两个文件转移到包含 J2RE 和 Eclipse 的目录并进行解压(见清单 4)。如果提示覆盖任何文件,那么只需选择 All。
清单 4. 安装 Eclipse TPTP 和 GLA% cd ~/java
% mv ~/tptp.runtime-TPTP-4.1.0.zip .
% mv ~/tptp.gla.runtime-TPTP-4.1.0.1.zip .
% unzip tptp.runtime-TPTP-4.1.0.zip
...
% unzip tptp.gla.runtime-TPTP-4.1.0.1.zip
...
% rm tptp.runtime-TPTP-4.1.0.zip
% rm tptp.gla.runtime-TPTP-4.1.0.1.zip
% ls -F
GenericLogAdapter/ eclipse/ jre1.5.0_06/
安装 EMF SDK V2.1
为了让 TPTP 正常工作,必须安装 EMF SDK V2.1。
如果 Eclipse 正在运行,就退出它并下载 EMF SDK V2.1。然后进入包含 Eclipse 文件夹的目录并运行 unzip emf-sdo-SDK-2.1.0.zip(见 清单 5)。
清单 5. 安装 EMF SDK V2.1% cd $JAVA_DIR
% ls
eclipse jre1.5.0_06
% mv ~/emf-sdo-SDK-2.1.0.zip .
% unzip emf-sdo-SDK-2.1.0.zip
creating: eclipse/features/
creating: eclipse/features/org.eclipse.emf.ecore.sdo_2.1.0/
creating: eclipse/features/org.eclipse.emf_2.1.0/
inflating: ...
...
% rm emf-sdo-SDK-2.1.0.zip
安装 XSD SDK V2.1
与前一个文件一样,进入包含 Eclipse 目录的目录并运行 unzip xsd-SDK-2.1.0.zip(见清单 6)。
清单 6. 安装 XSD SDK V2.1% cd $JAVA_DIR
% mv ~/xsd-SDK-2.1.0.zip .
% unzip xsd-SDK-2.1.0.zip
% rm xsd-SDK-2.1.0.zip
如果提示您确认覆盖任何文件,那么只需按 y(小写)对每个问题回答 “Yes”。
安装 UML V2.0 Metamodel Implementation
要使用 Eclipse TPTP 的 UML 特性,就必须安装 UML V2.0 Metamodel Implementation。如果正在使用 Eclipse V3.1.1,那么下载 V1.1.1 of UML 2,然后在包含 Eclipse 的目录中解压它的存档文件(见清单 7)。
清单 7. 安装 UML V2.0 Metamodel Implementation% cd $JAVA_DIR
% mv ~/uml2-1.1.1.zip .
% unzip uml2-1.1.1.zip
...
% rm uml2-1.1.1.zip
安装 Agent Controller
Agent Controller 是 Eclipse TPTP 的一个重要组件,它使 Eclipse 能够启动应用程序并与这些应用程序进行交互,从而提取分析数据。下载适合自己操作系统的 Agent Controller 运行时。接下来,在包含 Eclipse 的目录中创建一个称为 tptpd 的目录,并将 Agent Controller 存档文件解压到这个目录中(见清单 8)。
清单 8. 安装 Agent Controller% mkdir $JAVA_DIR/tptpd
% cd $JAVA_DIR/tptpd
% mv ~/tptpdc.linux_ia32-TPTP-4.1.0.zip .
% unzip tptpdc.linux_ia32-TPTP-4.1.0.zip
如果看到两个下面这样的错误:
清单 9. 安装 Agent Controllerlinking: lib/libxerces-c.so
warning: symbolic link (lib/libxerces-c.so) failed
linking: lib/libxerces-c.so.24
warning: symbolic link (lib/libxerces-c.so.24) failed
那么通过输入以下命令来手工地重新创建这两个链接:
清单 10. 安装 Agent Controller% cd $JAVA_DIR/tptpd/lib
% rm libxerces-c.so libxerces-c.so.24
% ln -s libxerces-c.so.24.0 libxerces-c.so
% ln -s libxerces-c.so.24.0 libxerces-c.so.24
添加 Agent Controller 目录
要使用 Agent Controller,必须将它的 lib 目录添加到 LD_LIBRARY_PATH 中。例如,如果正在运行 Linux 并采用以上步骤中给出的目录结构,那么用以下命令添加 $JAVA_DIR/tptpd/lib:
% export LD_LIBRARY_PATH=$JAVA_DIR/tptpd/lib:$LD_LIBRARY_PATH
还必须确保 Controller 的 lib 和 bin 目录的内容是可执行的。为此,运行:
% chmod +x $JAVA_DIR/tptpd/{bin,lib}/*
现在将配置、启动和停止 Agent Controller 的脚本添加到 PATH:
% export PATH=$JAVA_DIR/tptpd/bin:$PATH
针对环境配置 Agent Controller
最后,要配置 Agent Controller 以便匹配环境。进入 Agent Controller 的 bin 目录,然后运行 SetConfig.sh。
% cd $JAVA_DIR/tptpd/bin
% ./SetConfig.sh
当配置脚本提示您进行选择时,接受默认设置。运行配置脚本会在 Agent Controller 的文件层次结构中创建文件 config/serviceconfig.xml。
测试 Agent Controller
为了测试 Agent Controller,运行 RAStart.sh。为了停止 Agent Controller,运行 RAStop.sh:
清单 11. 测试 Agent Controllerdb% RAStart.sh
Starting Agent Controller
RAServer started successfully
% RAStop.sh
RAServer stopped, pid = 5891
RAServer stopped, pid = 5892
RAServer stopped, pid = 5893
RAServer stopped, pid = 5894
RAServer stopped, pid = 5895
RAServer stopped, pid = 5896
RAServer stopped, pid = 5897
RAServer stopped, pid = 5898
RAServer stopped, pid = 5899
RAServer stopped, pid = 5900
RAServer stopped, pid = 5901
RAServer stopped, pid = 5902
RAServer stopped, pid = 5904
RAServer stopped, pid = 5905
RAServer stopped, pid = 5906
现在完成了!重新启动 Eclipse,在 Eclipse 工具栏上应该会看到一个新按钮,如图 1 所示。这是 TPTP Profile 按钮,表示 TPTP 已经成功地安装了。就可以继续学习本教程了。
图 1. TPTP Profile 按钮
创建适配器
GLA 使用一个 XML 配置文件来控制如何分析和转换日志文件,以及如何输出数据。一个配置文件包含一个或多个上下文,在每个上下文中定义如何转换一种日志文件。在某些情况下,一个配置文件中的多个上下文可以同时运行。
适配器配置文件
首先,创建一个适配器配置文件来处理名为 daemon.log 的 Linux 日志文件。在运行 Debian Linux 的测试系统上,daemon.log 捕获来自 POP3(电子邮件)、THTTPD(“简化的” HTTP 服务器 —— 一种只处理静态文件的小型快速 Web 服务器)和 MyDNS(一种小型的容易配置的 Domain Name System(DNS)服务器)守护进程的消息。在 MySQL 守护进程启动和停止时,daemon.log 也进行记录。
清单 12 给出 POP3 和 THTTPD 服务器产生的一部分日志项。
清单 12. Linux daemon.log 文件的片段Mar 2 07:24:54 db popa3d[8861]: Session from 66.27.187.89
Mar 2 07:24:55 db popa3d[8861]: Authentication passed for joan
Mar 2 07:24:55 db popa3d[8861]: 1422 messages (11773432 bytes) loaded
Mar 2 07:24:57 db popa3d[8861]: 0 (0) deleted, 1422 (11773432) left
Mar 2 07:26:28 db thttpd[7784]: up 3600 seconds, stats for 3600 seconds:
Mar 2 07:26:28 db thttpd[7784]: thttpd - 0 connections (0/sec), 0 max simultaneous
Mar 2 07:26:28 db thttpd[7784]: map cache - 0 allocated, 0 active (0 bytes)...
Mar 2 07:26:28 db thttpd[7784]: fdwatch - 1589 selects (0.441389/sec)
Mar 2 07:26:28 db thttpd[7784]: timers - 3 allocated, 3 active, 0 free
Mar 2 07:27:35 db popa3d[8911]: Session from 71.65.224.25
Mar 2 07:27:35 db popa3d[8911]: Authentication passed for martin
Mar 2 07:27:35 db popa3d[8911]: 1350 messages (10880072 bytes) loaded
Mar 2 07:27:36 db popa3d[8911]: 4 (11356) deleted, 1346 (10868716) left
Mar 2 07:29:54 db popa3d[8963]: Session from 66.27.187.89
适配器配置文件中的每个上下文定义 6 个组件:上下文实例(context instance)、检测器(sensor)、提取器(extractor)、解析器(parser)、格式化器(formatter) 和 输出器(outputter)。上下文实例为转换的一般操作设置参数,包括日志是否连续地追加以及修改日志的频繁程度。从概念上讲,其他 5 个组件依次发挥作用,它们都读取输入、执行各自的任务并传递结果供进一步处理(某些格式化器例外,它们仅仅是将结果写到文件或控制台):
检测器分段读取日志文件,直到它遇到文件的末尾并暂停。然后,当检测器发现日志文件已经增长时,它就读取新增的数据。检测器将它的数据传递给下一阶段 —— 提取器。
提取器读取数据并将它分割为单独的记录。一个正则表达式定义了记录的开头是什么样的,另一个正则表达式定义记录的末尾。识别出单独的记录之后,这些记录传递给解析器进行进一步处理。
解析器每次从提取器读取一个记录,将每个记录分解为字段和值。另外,解析器能够根据记录的内容做出决策,应用一组或多组规则来产生字段和值。例如,如果一个日志文件记录了一个事件的开头、中间过程和结束,那么解析器能够将每个记录分解为此事件特有的一组字段和值。总之,解析器的目标是将每个日志文件项中的字段和值映射到 CBE XML 记录中的适当元素、属性和值。格式化器读取解析器的输出。
格式化器的工作很简单:它读取解析器创建的元素、属性和值,创建一个适合上下文中的下一阶段(输出器)使用的对象。
输出器使用来自格式化器的对象并输出这个对象。输出器将 XML 输出到文件或控制台。它们也能够创建新的日志文件或者将数据传递给某个守护进程。
下面 5 节描述如何定义上下文的 6 个组件。
创建适配器配置文件
首先,创建一个简单的 Eclipse 项目来包含适配器配置文件:
点击 File > New 并展开 Simple。选择 Project 并点击 Next。
将项目命名为 My Adapter 并点击 Finish。
点击 File > New > Other 并展开 Generic Log Adapter。选择 Generic Log Adapter File 并点击 Next。
选择 My Adapter 并将适配器文件命名为 my.adapter。点击 Next。
为希望用这个适配器处理的日志文件选择一个模板(见图 2)。
可以使用希望处理的日志文件的片段,或者日志文件的精确表示 —— 比如来自详细的规范。点击 Browse,在文件系统中找到并打开这个模板。在做出选择之后,点击 Finish。当提示您切换透视图时,点击 Yes。
图 2. 选择一个表示要转换的日志文件的模板
图 3 显示 Generic Log Adapter 透视图。可以看到,这个用户界面显示一个上下文实例,在其中检测器的属性指向刚才选择的模板日志文件。这个上下文实例还包含提取器、解析器、格式化器和输出器,这些必须进一步进行定义。
图 3. Generic Log Adapter 透视图
配置上下文
每个上下文实例描述如何处理一个日志文件。可以在上下文实例中设置几个选项。要看到这些选项,点击 Configuration 下面的 Context Instance。应该会看到与图 4 相似的面板。
图 4. 上下文实例选项
可以编辑 Description 来描述这个上下文的用途。另外:
如果日志文件会不断更新(daemon.log 就是这种情况),那么选中 Continuous operation 复选框。
Maximum idle time 是上下文应该等待日志文件更新的毫秒数,如果在这段时间内日志文件没有更新,那么上下文实例就关闭。
Pause interval 控制在到达日志文件末尾之后,上下文应该等待多长时间。
因为日志文件不一定是 ASCII 文本,所以可以设置 ISO language code(使用两个小写字母)、ISO country code(使用两个大写字母)和文件的 Encoding(使用来自 Internet Assigned Numbers Authority(IANA)字符集注册库的值)。在默认情况下,这些参数设置为 en、US 和 JVM 的默认编码。
最后,因为一些日志文件没有指出时区、年、月和日,而 CBE 要求有这 4 个值,可以在 Timezone GMT offset 和 Log file creation date 字段中提供替代值。
因为 daemon.log 会不断增长,所以选中 Continuous operation 复选框。因为邮件通常经常被查看,所以将 Maximum idle time 和 Pause interval 设置为 120。测试计算机位于科罗拉多,所以 GMT 是 -7。daemon.log 没有指定年,所以提供默认值 2006 作为替代值。在做这些修改之后,保存文件。
指定检测器
检测器读取日志文件并将收集的数据转发给提取器。下一步是指定检测器应该如何工作。
指定检测器如何工作
点击检测器。它的属性见图 5,这里也显示了为 daemon.log 检测器设置的值。
图 5. 设置 daemon.log 的检测器
因为 daemon.log 是单个文件,所以不需要改变 Sensor type 选项。Description 字段描述检测器的用途。Maximum blocking 定义在将输入传递给提取器之前要读取多少行。因为 daemon.log 中的项往往跨许多行,所以 10 是合理的设置。Confidence buffer size 的值表示包含日志文件最后 n 个字节的缓冲区的大小。如果日志改变了 —— 即,最后 n 个字节不同于可靠缓冲区中的内容,那么检测器就读取更多的输入。默认值是 1,024 字节,这对于这个示例是足够的。
有些日志在日志文件的末尾附加一个结束标志(在每次写新数据时)。通常,最好忽略这一数据,所以为了跳过结束标志,在 File footer size 中指定要跳过的字节数。daemon.log 没有结束标志,所以把这个值设置为 0。
如果展开 Sensor type(点击箭头),会看到另外两个属性:directory 和 fileName。这些属性最初设置为模板日志文件的位置和名称,但是以后可以改变它们来处理真实数据。
在设置检测器属性之后,不要忘了保存配置文件。另外,总的来说,在尝试运行适配器之前应该总是保存配置文件。
编辑提取器
检测器的作用是收集输入。提取器的作用是将输入流分割为单独的记录。(下一个组件 —— 解析器 —— 将每个记录分割为字段。)
配置提取器属性
为了编辑提取器,点击 Extractor。它的属性见图 6。提取器的属性指定每个记录的分界符,并控制这些分界符是否应该包含在传递给解析器的记录中。
图 6. 提取器属性
在示例日志文件(daemon.log)中,日志的每一行是一个单独的事件。这使得提取器很容易配置。(图 6 是适合 daemon.log 的配置。)
取消选中 Contains line breaks 复选框,因为 daemon.log 中的每一行是一个记录。但是,如果一个日志项跨许多行(MySQL 或 IBM DB2® 数据库日志就是这种情况),则要选中这个复选框。
在这个示例中,也取消选中 Replace line breaks 复选框。但是,如果日志文件包含换行符,则可以选中这个复选框,从而删除每个换行符或者将它们替换为特殊标志,这有利于进行分析。要删除换行符,只需选中这个复选框;要将每个换行符替换为一个符号,需要选中这个复选框并在 Line break symbol 字段中提供一个分界符。最好选择不会出现在这个日志文件中的符号。
Start pattern 和 End pattern 都是正则表达式,分别描述每个记录的开头和结尾。在这个示例中,每一行是一个记录,所以行首(^,脱字符)表示记录的开头,行末($,美元符号)表示记录的末尾。因为 ^ 和 $ 不表示任何内容,所以不需要包含在记录本身中。
保存配置。
MySQL 示例
为了进行对比,为 MySQL 的慢查询日志创建另一个提取器示例,这是一个特殊的日志,用来捕获不够优化的查询。慢查询日志中的每一项至少跨三行(见清单 13)。
清单 13. MySQL 慢查询日志的片段# Time: 030207 15:03:33
# Query_time: 13 Lock_time: 0 Rows_sent: 0 Rows_examined: 0
SELECT l FROM un WHERE ip='209.xx.xxx.xx';
# Time: 030207 15:03:42
# Query_time: 17 Lock_time: 1 Rows_sent: 0 Rows_examined: 0
SELECT l FROM un WHERE ip='214.xx.xxx.xx';
# Time: 030207 15:03:43
# Query_time: 57 Lock_time: 0 Rows_sent: 2117 Rows_examined: 4234
SELECT c,cn,ct FROM cr,l,un WHERE ci=lt AND lf='MP' AND ui=cu;
针对慢查询日志的提取器可能像图 7 这样。
图 7. MySQL 慢查询日志的提取器示例
图 8 显示三个记录中的第二个,这说明提取器成功地处理了每个记录。
图 8. 从慢查询日志提取的记录
对到目前为止做的工作进行测试
回到 daemon.log 适配器,现在可以对检测器和提取器组件进行测试,从而确认可以获得数据并将数据分割为记录。
重新运行适配器
看一下 Generic Log Adapter 透视图底部的两个面板。应该会看到与图 9 相似的内容。左边是 Extractor Result 面板;右边是重叠的 Formatter Result 面板、Sensor Result 面板和 Problems 面板。Extractor Result 面板中有一系列控制适配器的按钮。图 10 显示这些按钮的标签(把鼠标放在每个按钮上也可以看到工具提示。)
图 9. 上下文组件显示面板
图 10. 适配器控制按钮
点击 Rerun adapter 从日志文件模板的开头重新开始处理。然后点击 Next event 处理第一个事件。
Sensor Result 面板应该显示日志文件的前 10-20 行。
Extractor Result 面板应该显示日志文件的第一行,Mar 2 06:27:35 db popa3d[7964]: Session from 71.65.224.25。
Problems 面板应该是空的。但是,在运行适配器时要注意这个面板。如果忽略了必需的 CBE 属性、指定了无效的正则表达式或者使用了不支持的值,那么这个面板应该会指出这些问题。
Formatter Result 面板现在的意义不大,因为还必须定义解析器。但是,它展示了当前记录最初的 XML CBE:
清单 14. 当前记录最初的 XML CBE<CommonBaseEvent
creationTime="replace with our message text"
globalInstanceId="A1DAABE6C7876D20E8E9E8C475042F1B"
version="1.0.1">
</CommonBaseEvent>
以后您会看到,在定义了解析器之后,在这个 XML 中会自动地添加其他元素和属性。
要让提取器产生下一个记录,再次点击 Next event。要想一直处理到最后一个记录(在检测器目前已经收集的输入中),点击 Show last event。
建立解析器
检测器读取数据。提取器将数据分割为记录。解析器的作用是从每个记录中提取出特定的字段,并使用这些值构造出一个完整的 CBE XML 记录。
解析器的作用
解析器可以从日志文件中直接提取出某些字段,比如时间戳、主机名称、守护进程名称和文本消息。解析器也可以从记录中间接地获得数据。例如,解析器可能发现一个记录来自某个软件服务,并将 CBE componentIdType 属性设置为 ServiceName。在某些情况下,解析器甚至可能在记录中添加数据。尤其是,如果日志项没有记录事件的日、月、年和时区,那么解析器必须添加这些数据,才能创建有效的 CBE。
为了理解 daemon.log 示例的解析器,清单 15 给出了日志项 Mar 2 06:27:35 db popa3d[7964]: Session from 71.65.224.25 的有效 CBE XML 记录。显然,一些属性来自原来的日志项;其他属性是从隐含数据构造出来的。(许多属性值来自 Common Base Events Specification。在创建自己的解析器时参考这个文档是有帮助的。)
清单 15. daemon.log 中第一个记录的等效 CBE 记录<CommonBaseEvent
creationTime="2006-03-02T13:27:35.000Z"
globalInstanceId="A1DAABECA2ACB4F0E8E9E8C475042F1B"
msg="Session from 71.65.224.25"
version="1.0.1">
<sourceComponentId
component="popa3d"
componentIdType="ServiceName"
location="db.linux-mag.com"
locationType="Hostname"
subComponent="7964"
componentType="daemon"
/>
<situation
categoryName="StartSituation">
<situationType
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="StartSituation"
reasoningScope="EXTERNAL"
successDisposition="SUCCESSFUL"
situationQualifier="START INITIATED"/>
</situation>
</CommonBaseEvent>
另外,要记住每个 CBE(至少)必须定义 creationTime 属性、msg 属性和 sourceComponentId 元素(这个元素必须具有清单 15 所示的 6 个属性)。situation 元素(和其他元素)是可选的,它对事件进行详细说明。
解析器是如何工作的
点击 Generic Log Adapter 透视图中的 Parser,开始定义解析器。图 11 显示完成的解析器。对于清单 15 所示的 CBE 中的每个属性和元素,都有一个解析器任务。
图 11. 完成的 daemon.log 解析器
解析器的工作过程分两个阶段。首先,它将输入的记录(来自提取器)分割为位置(position),也就是编号的部分,每个部分之间由分隔符(separator token)。如果没有指定分隔符,那么跳过这一步。然后,解析器将记录分隔为指示(designation),也就是 (名称,值) 对,每个 (名称,值) 对是两个字符串,由指示符(designation token) 联结在一起。如果没有指定指示符,那么跳过后一步。
考虑这个例子:如果分隔符是正则表达式 [ ]+,指示符是 =(等号),而解析器处理以下记录:
03/05/06 12:51:06EST Mail name=joe action=login authentication=password
解析器会定义 6 个位置和 3 个指示,见表 1。
表 1. 解析器定义的位置和指示
位置/指示 | 值 |
1 | 03/05/06 |
2 | 12:51:06EST |
3 | |
4 | name=joe |
5 | action=login |
6 | authentication=password |
h{'name'} | joe |
h{'action'} | login |
h{'authentication'} | password |
注: 如果输入的记录以分隔符开头,那么创建的第一个位置是空的。
可以使用定义的所有位置和指示来简化每个解析器任务。例如,要创建 creationTime 属性,只需分析第二个位置。当然,完整的原始记录总是可用的。但是,位置和指示使解析任务更快而且更容易管理,因为源字符串更小。在许多情况下,可以将一个位置或指示直接用作 CBE 值。
解析示例日志项
再次点击 Parser。为了方便,使用分隔符 :[ ]+(一个冒号,后面是一个或多个空格)将每个 daemon.log 项分割为两个位置。daemon.log 日志项没有 (名称,值) 对,所以忽略指示符。这些设置见图 12。现在,保存设置。
图 12. 将记录分割为位置
设置 creationTime
设置 CBE 中的第一个必要字段:creationTime。目标是将 daemon.log 记录提供的时间戳转换为与 XML 模式 dateTime 数据类型兼容的时间格式。为了方便,适配器可以自动地将 java.text.SimpleDateFormat 类理解的时间格式转换为 XML 模式数据类型。
为了设置 creationTime 字段,执行以下步骤:
展开解析器并选择 creationTime。这是一个 CBE 必要字段,所以选中 Required by parent 复选框。
点击与 creationTime 相关联的替换规则。
对于 Positions,输入 1,因为第一个位置包含要提取的时间戳。
对于 Match,提供正则表达式 ^(\w{3})\s+(\d{1,2})\s+([\d:]+)\s+.*$。这个正则表达式捕获月份名称($1)、月中日($2)和日中的时间($3)。
对于 Substitute,输入 $1 $2 @YEAR $3 @TIMEZONE。
在这个解析任务的其余部分中,将使用这个替换表示而不是完整的输入记录。$1、$2 和 $3 来自前一步。但是,因为时间戳不包含年或时区,所以要使用与当前上下文实例相关联的年和时区(分别用 @YEAR 和 @TIMEZONE 表示)。因此,对于第一个 daemon.log 记录,Substitute 中的设置产生字符串 Mar 02 2006 06:27:35 -0700。
忽略 Substitute extension class 字段,这个字段允许提供一个 Java 类来进行进一步的替换,将替换的结果转换为正确的类型。可以使用 java.text.SimpleDateFormat 格式字符串完成这一任务。将 Time format 设置为 MMM dd yyyy hh:mm:ss Z,这表示 3 个字母的月份名、2 位的天数、4 位的年份以及由冒号分隔的小时、分钟和秒,还有一个 RFC 822 时区。
图 13 显示 creationTime 的最终设置。如果保存配置文件并重新运行适配器,那么 Formatter Result 面板应该会显示一个具有 creationTime="2006-03-02T13:27:35.000Z" 属性的新 XML 记录。
图 13. 将输入的时间戳解析为 creationTime 属性
获得消息
msg 属性是另一个 CBE 必要属性。按照以下步骤添加这个属性,并创建解析器任务来提取合适的值:
右击 CommonBaseEvent,然后点击 Add > msg。
点击 msg,然后选中 Required by parent 复选框。
展开 msg,然后点击 Substitution Rule。
在 Positions 字段中指定 2,因为日志项的消息部分位于第二个位置。(它是分隔符后的所有内容。)
对于 Match,指定一个选择整个字符串的正则表达式。正则表达式 ^(.*)$ 捕获所有内容并表示为 $1。
对于 Substitute,指定 $1。
图 14 显示最终的设置。
图 14. 提取消息的设置
保存配置文件并点击 Extractor Result 面板中的 Rerun adapter。点击 Next event 并切换到 Formatter Result 面板。应该会看到新的 msg 属性,msg="Session from 71.65.224.25"。
寻找源
CBE 记录的最后一个必要部分是 sourceComponentId,它用来记录事件所影响的组件(服务、系统等等)。在 daemon.log 这个示例中,影响的组件是在特定主机上运行的软件服务。解析器的任务是捕获并记录特定的组件。
再次右击 CommonBaseEvent,然后点击 Add > sourceComponentId。(图 15 显示可以添加到 CBE 中的所有属性。)为了明确,表 2 给出了 sourceComponentId 所需的所有设置。一个新设置是 Default value。如果分析规则发现匹配,但是没有提供替换值,那么使用 Default value。
图 15. 可以添加到 CBE 记录中的元素和属性列表
表 2. sourceComponentId 的设置
Item | Default value | Required by parent | Positions | Match | Substitute | 说明 |
component | Yes | 1 | ^.* db (\w+)\[.*$ | $1 | 捕获软件服务的名称,比如 pop3ad 或 mysqld。 | |
componentIdType | ServiceName | Yes | ^(.*) | 表示组件记录服务的名称;根据 CBE 规范,ServiceName 是这个属性的规定值之一。 | ||
componentType | daemon | Yes | ^(.*) | 描述组件的类。 | ||
location | db.linux-mag.com | Yes | ^(.*) | 指定与组件位置对应的物理地址。location 值的格式由 locationType 属性指定。对于这个属性,建议使用完全限定的主机名。在这里,因为日志项不包含主机名,所以通过默认值添加主机名。在其他情况下,可以从日志中直接解析出主机名。 | ||
locationType | Hostname | Yes | 1 | ^(.*) | 指定 location 属性中的值的格式和含义。可以使用许多关键字,在这里使用 Hostname 关键字。 | |
subComponent | Yes | ^.*\[(\d+)\].* | $1 | 表示事件影响的特定守护进程。 |
如果完成了表 2 中列出的所有修改,然后保存并重新运行适配器,那么应该会产生与清单 15 相似的 CBE 事件记录。作为另一个练习,将 situation 添加到 CBE 中。situation 描述造成事件的情况类型。例如,可以创建一个解析器以便在最初联系守护进程时创建一个 StartSituation,或者创建另一个解析器以便在进行请求时创建一个 RequestSituation。
situation 不是必需的(因此,可以禁用 Required by parent),但是它们有助于增加 CBE 记录的针对性。如果创建一个 situation 并添加一系列 situation 解析器,那么可以选择 Child choice 复选框,从而决定在产生匹配之后是否可以停止处理。
对于调试自己的解析器,有一个有帮助的技巧:如果需要一个属性,但是在(从提取器传递给解析器的)输入记录中没有找到,那么 Formatter Result 面板对于这个记录是空的。换句话说,必要属性的表现就像是逻辑 AND:如果出现不匹配,那么对这个记录的处理就会停止。所以,在调试规则时取消选中 Required by parent 复选框常常是有帮助的。缓慢且渐进地构建规则,同时通过观察 Problem 面板来寻找问题的线索。
格式化器和对输出器进行组织
既然解析器已经产生了属性和值,就必须将新数据组合成 CBE 实例。这就是格式化器的作用。
将 CBE XML 记录输出到文件
适配器格式化器不要求配置。它是一种内部操作,创建符合 CBE V1.0.1 规范的 CBE 对象。
在格式化器创建 CBE 对象之后,由输出器将这些对象输出到文件、标准输出、另一个日志、日志记录代理或日志分析程序。如果适配器配置定义了多个上下文,那么可以使用一个特殊的格式化器,让多个上下文向同一个文件中写记录。
为了简化,将 CBE XML 记录输出到一个文件:
点击 Generic Log Adapter 透视图中的 Outputter,然后为 Outputter type 选择 SingleFileOutputter。
右击 Outputter,然后点击 Add > property。
点击新属性,然后将 Property name 设置为 directory。将 Property value 设置为一个您能够写文件的目录。忽略文件名。只指定目录的路径,不带末尾的斜线。
再次右击 Outputter 并点击 Add > property。将新的 Property name 设置为 fileName,将 Property value 设置为文件名。将在 directory 指定的目录中创建这个文件。
修改上下文实例
除了修改配置,还必须修改上下文实例以使用适当的输出器类。为此,执行以下步骤:
展开 General Log Adapter 透视图中的 Contexts 并展开 Context Basic Context Implementation。
点击 Component Logging Agent Outputter。
将 Name 和 Description 改为 Single File Outputter。
将 Executable 类改为 org.eclipse.hyades.logging.adapter.outputters.CBEFileOutputter。
保存配置文件。
添加 SingleFileOutputterType
还有一个重要的步骤:由于某种原因,Adapter Configuration Editor 会忽略适配器配置文件的输出器定义中的一个重要元素。(可以在 developerWorks 自主计算论坛的 No Output from Outputter 上找到相关内容。)但是,可以快速地将这个元素手工添加到文件中。
使用编辑器打开文件 my.adapter。滚动到文件底部,寻找以下文本。
清单 16. 适配器配置<cc:Outputter
description="Single File Outputter"
uniqueID="N13725210AFF11DA8000AE8373D52828"
type="SingleFileOutputter">
<pu:Property propertyName="directory"
propertyValue="/home/mstreicher"/>
<pu:Property propertyName="fileName"
propertyValue="emitter.log"/>
<op:SingleFileOutputterType directory="/home/mstreicher"
fileName="emitter.log"/>
</cc:Outputter>
如果缺少 <op:SingleFileOutputterType... /> 行,那么添加它并修改 directory 和 fileName 属性的值,以匹配另外两个属性的值。然后保存文件。
运行 GLA
基于规则的适配器现在完成了。利用 Extractor Result 面板中的控件分步处理模板日志文件并检验其操作。如果确认一切正常,就可以使用单独的 GLA 来运行适配器。
使用 GLA 运行适配器
GLA 使用在适配器中创建的设置读取日志文件并生成一个 CBE XML 文档。清单 17 给出 my.adapter 文件的一小部分。
清单 17. my.adapater 文件的片段<adapter:Adapter...
<cc:ContextInstance
charset=""
continuousOperation="true"
description="A context for daemon.log"
isoCountryCode="" isoLanguageCode=""
maximumIdleTime="120"
pauseInterval="120"
timezone="-0700"
uniqueID="N05306B00AFF11DA8000AE8373D52828"
year="2006">
<cc:Sensor
description="Read the daemon.log"
uniqueID="N057E8B10AFF11DA8000AE8373D52828"
confidenceBufferSize="1024"
fileFooterSize="0"
maximumBlocking="10"
type="SingleFileSensor">
<pu:Property
propertyName="directory"
propertyValue="/home/mstreicher/java-tptp-gla"
/>
<pu:Property
propertyName="fileName"
propertyValue="daemon.log"
/>
<sensor:SingleFileSensor
directory="/home/mstreicher/java-tptp-gla"
fileName="daemon.log"'
/>
</cc:Sensor>
<ex:Extractor
containsLineBreaks="false"
description="Divide daemon.log into individual records"
endPattern="$"
includeEndPattern="false"
includeStartPattern="false"
lineBreakSymbol=""
replaceLineBreaks="false"
startPattern="^"
uniqueID="N05AA7D00AFF11DA8000AE8373D52828"
/>
.
</adapter:Adapter>
要运行 GLA,首先必须编辑它的脚本,指向安装它的位置。使用编辑器打开 GenericLogAdapter/bin 中的 gla.sh 文件。(如果严格按照安装说明进行安装,那么这个文件位于 ~/java/GenericLogAdapter/bin/gla.sh。)找到 GLA_HOME=/home/eclipse/GenericLogAdapter 行,将路径改为指向包含 GLA 副本的目录。如果严格按照说明进行安装,那么将这一行改为 GLA_HOME=~/java/GenericLogAdapter。保存文件。
接下来,在自己的 Eclipse 工作空间的 My Adapter 目录下找到 my.adapter 文件。在测试系统上,my.adapter 在 ~/workspace/My Adapter/my.adapter 中。为了运行适配器,执行 gla.sh,提供适配器文件的路径作为惟一的参数:
% ~/java/GenericLogAdapter/bin/gla.sh ~/workspace/My\ Adapter/my.adapter
过一会儿,emitter.log 文件应该会出现在您的主目录中(或者在输出器配置中指定的创建文件的目录中)。
结束语
本教程演示了如何创建基于规则的适配器,从而将典型的 Linux 日志文件转换为 CBE 日志文件。有了 CBE 日志,就可以使用 Autonomic Computing Toolkit 的 Log and Trace Analyzer 这样的工具来进一步处理 CBE 数据。
另外,如果 Adapter Configuration Editor 提供的规则构造不适合您的日志文件,也可以集成自己的 Java 类来解析并输出 CBE 格式。与基于规则的适配器不同,静态适配器(之所以称为静态适配器是因为它使用 Java 类而不是规则)只需要检测器和输出器,它们由 Java 代码提供。仍然采用最终的配置文件来运行 GLA,但是在 GLA CLASSPATH 中必须包含您的 Java 类。
无论是哪种情况,Adapter Configuration Editor 和 GLA 都提供了一个强大的环境,在这个环境中可以使用现代的自主计算工具来分析现有的(甚至遗留的)应用程序的行为。从任意数量的日志文件格式转换到 CBE 只需要做很少的工作;利用规则或自己的代码,就可以轻松地完成复杂的转换。
更多精彩
赞助商链接