自定义日志
在上面我们利用EventLog输出的事件中,我们以一个字符串的形式输出了文件名和耗时。为了更加便于我们对日志进行进一步的筛选,我们希望将其输出成一个字符串和一个整数值的形式:字符串记录复制的文件名,而相应的整数值则记录复制操作的耗时。针对这种情况,我们就需要对事件进行自定义了。
在Visual Studio 2010中,自定义ETW事件按照如下的5个设计步骤进行:
图3 自定义ETW事件的步骤
1. 设计
所谓设计,就是定义我们需要在事件中输出哪些信息,比如事件的类型,等级,通道以及事件模板等等。在这里,我们需要输出的是被复制的文件的名字和复制操作耗时,所以我们决定采用事件模板,其中包含一个字符串值和一个整数值,分别用于记录文件名和操作耗时。
2. 定义事件XML文件
在ETW中,我们使用一个XML文件来描述和定义一个事件。在这个XML文件中,我们定义了Provider的GUID,事件,事件模板,以及通道等等事件属性。虽然我们可以用文本编辑器手动地编写这个XML文件,但是更简单地是使用Windows SDK中的Manifest Generator(ecmangen.exe)工具创建事件的XML文件。
图4 用Manifest_Generator创建事件的XML文件
在这里,我们简单地定义了一个Provider,其中它提供了一个事件模板(Template),包含一个字符串项目和整数项目,可以供我们填充文件名和复制耗时。最后,我们可以得到这样一个定义事件的XML文件FileCopier.Manifest.xml:
<?xml version="1.0" encoding="UTF-16"?>
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:trace="http://schemas.microsoft.com/win/2004/08/events/trace">
<instrumentation>
<events>
<provider name="SimpleEtwProvider" guid="{D9B453B9-6230-486C-8DEC-C7C5A2230D04}" symbol="SimpleEtwProvider" resourceFileName="D:\Programs\FileCopier.exe" messageFileName="D:\Programs\FileCopier.exe" message="$(string.ProviderMessage)">
<events>
<event symbol="SimpleEvent" value="1001" version="1" channel="SimpleOperationalChannel" level="win:Informational" task="SimpleTask" opcode="SimpleOpcode" template="SimpleTemplate" keywords="SimpleKeyword " message="$(string.SimpleEtwProvider.SimpleEvent.message)">
</event>
</events>
<levels>
</levels>
<tasks>
<task name="SimpleTask" symbol="SimpleTask" value="1" eventGUID="{9B0655BE-219F-439E-9439-B604BD822E22}">
</task>
</tasks>
<opcodes>
<opcode name="SimpleOpcode" symbol="SimpleOpcode" value="10">
</opcode>
</opcodes>
<channels>
<channel name="SimpleOperationalChannel" chid="SimpleOperationalChannel" symbol="SimpleOperationalChannel" type="Operational" enabled="true">
</channel>
</channels>
<keywords>
<keyword name="SimpleKeyword" symbol="SimpleKeyword" mask="0x1">
</keyword>
</keywords>
<templates>
<template tid="SimpleTemplate">
<data name="StringData" inType="win:UnicodeString" outType="xs:string">
</data>
<data name="IntegerData" inType="win:Int32" outType="xs:int">
</data>
</template>
</templates>
</provider>
</events>
</instrumentation>
<localization>
<resources culture="en-US">
<stringTable>
<string id="level.Informational" value="Information">
</string>
<string id="SimpleEtwProvider.SimpleEvent.message" value="A simple event to demo ETW...">
</string>
<string id="ProviderMessage" value="Simple Event Trace for Windows Provider">
</string>
</stringTable>
</resources>
</localization>
</instrumentationManifest>
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:trace="http://schemas.microsoft.com/win/2004/08/events/trace">
<instrumentation>
<events>
<provider name="SimpleEtwProvider" guid="{D9B453B9-6230-486C-8DEC-C7C5A2230D04}" symbol="SimpleEtwProvider" resourceFileName="D:\Programs\FileCopier.exe" messageFileName="D:\Programs\FileCopier.exe" message="$(string.ProviderMessage)">
<events>
<event symbol="SimpleEvent" value="1001" version="1" channel="SimpleOperationalChannel" level="win:Informational" task="SimpleTask" opcode="SimpleOpcode" template="SimpleTemplate" keywords="SimpleKeyword " message="$(string.SimpleEtwProvider.SimpleEvent.message)">
</event>
</events>
<levels>
</levels>
<tasks>
<task name="SimpleTask" symbol="SimpleTask" value="1" eventGUID="{9B0655BE-219F-439E-9439-B604BD822E22}">
</task>
</tasks>
<opcodes>
<opcode name="SimpleOpcode" symbol="SimpleOpcode" value="10">
</opcode>
</opcodes>
<channels>
<channel name="SimpleOperationalChannel" chid="SimpleOperationalChannel" symbol="SimpleOperationalChannel" type="Operational" enabled="true">
</channel>
</channels>
<keywords>
<keyword name="SimpleKeyword" symbol="SimpleKeyword" mask="0x1">
</keyword>
</keywords>
<templates>
<template tid="SimpleTemplate">
<data name="StringData" inType="win:UnicodeString" outType="xs:string">
</data>
<data name="IntegerData" inType="win:Int32" outType="xs:int">
</data>
</template>
</templates>
</provider>
</events>
</instrumentation>
<localization>
<resources culture="en-US">
<stringTable>
<string id="level.Informational" value="Information">
</string>
<string id="SimpleEtwProvider.SimpleEvent.message" value="A simple event to demo ETW...">
</string>
<string id="ProviderMessage" value="Simple Event Trace for Windows Provider">
</string>
</stringTable>
</resources>
</localization>
</instrumentationManifest>
图4 用Manifest_Generator创建事件的XML文件