Thursday, August 4, 2011

How to Add Instrumentation to Your Manifest

To enable ETW performance tracing for your binary, the first thing you need to do is add an instrumentation section. Here is the MSDN documentation on how to do this if you want to read about this in detail:

http://msdn.microsoft.com/en-us/library/aa382776(v=VS.85).aspx

Also in the introduction for ETW (http://msdn.microsoft.com/en-us/magazine/cc163437.aspx), they make a tool recommendation for generating a manifest for ETW (ecmangen.exe). It is available in the Windows SDK. You can try it out; it may meet your needs just fine. As a person who still favors writing code in Vi, I opted to roll my own. Tools are great when they work for you. Using a tool; however, doesn’t make up for actually knowing how things work. It is good to understand how things work when things don’t come together. Read on if you would rather roll your own.

So below is the events section instrumentation manifest that has one start and stop even. You will need a start and stop for everything you want to time.

<events>

<event

channel="50"

keywords="Component query"

level="win:Informational"

message="$(string.event_5501)"

opcode="win:Start"

symbol="CREATE_QUERY_START"

task="component_CreateQuery"

template="INFO_CONTEXT_INFO"

value="5500"

/>

<event

channel="50"

keywords="Component query"

level="win:Informational"

message="$(string.event_5502)"

opcode="win:Stop"

symbol="CREATE_QUERY_STOP"

task="component_CreateQuery"

template="INFO_CONTEXT_INFO"

value="5501"

/>

events>

With some highlighting, I will show you where all the bits line up inside the full manifest.

<events>

<event

channel="50"

keywords="Component query"

level="win:Informational"

message="$(string.event_5501)"

opcode="win:Start"

symbol="CREATE_QUERY_START"

task="component_CreateQuery"

template="INFO_CONTEXT_INFO"

value="5500"

/>

<event

channel="50"

keywords="Component query"

level="win:Informational"

message="$(string.event_5502)"

opcode="win:Stop"

symbol="CREATE_QUERY_STOP"

task="component_CreateQuery"

template="INFO_CONTEXT_INFO"

value="5501"

/>

events>

Here is the full manifest:

xml version='1.0' encoding='utf-8' standalone='yes'?>

<assembly

xmlns="urn:schemas-microsoft-com:asm.v3"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

manifestVersion="1.0"

>

<assemblyIdentity

buildType="$(build.buildType)"

language="neutral"

name="Microsoft-Windows-Component"

processorArchitecture="$(build.arch)"

publicKeyToken="$(Build.WindowsPublicKeyToken)"

version="$(build.version)"

versionScope="nonSxS"

/>

<instrumentation xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events">

<events xmlns="http://schemas.microsoft.com/win/2004/08/events">

<provider

guid="{56c71c31-cfbd-4cdd-8559-505e042bbbe1}"

message="$(string.EventProviderName)"

messageFileName="%SystemRoot%\system32\component.dll"

name="Microsoft-Windows-ComponentProvider"

resourceFileName="%SystemRoot%\system32\component.dll"

symbol="component"

>

<channels>

<channel

chid="50"

name="Microsoft-Windows-ComponentProvider/Performance"

symbol="MS_COMPONENT_PERFORMANCE"

type="Analytic"

/>

channels>

<keywords>

<keyword

mask="0x1"

name="PerfTrackContext"

/>

<keyword

mask="0x2"

name="Component"

/>

<keyword

mask="0x4"

name="query"

/>

keywords>

<tasks>

<task

name="component_CreateQuery"

value="5000"

/>

tasks>

<templates>

<template tid="INFO_CONTEXT_INFO">

<data

inType="win:Pointer"

name="Context"

/>

template>

templates>

<events>

<event

channel="50"

keywords="Component query"

level="win:Informational"

message="$(string.event_5501)"

opcode="win:Start"

symbol="CREATE_QUERY_START"

task="component_CreateQuery"

template="INFO_CONTEXT_INFO"

value="5500"

/>

<event

channel="50"

keywords="Component query"

level="win:Informational"

message="$(string.event_5502)"

opcode="win:Stop"

symbol="CREATE_QUERY_STOP"

task="component_CreateQuery"

template="INFO_CONTEXT_INFO"

value="5501"

/>

events>

provider>

events>

instrumentation>

<localization>

<resources culture="en-US">

<stringTable>

<string

id="EventProviderName"

value="Microsoft-Windows-Component"

/>

<string

id="event_5501"

value="create query has started."

/>

<string

id="event_5502"

value="create query has exited."

/>

stringTable>

resources>

localization>

<dependency

discoverable="false"

optional="false"

resourceType="Resources"

>

<dependentAssembly dependencyType="prerequisite">

<assemblyIdentity

buildType="$(build.buildType)"

language="*"

name="Microsoft-Windows-Component.Resources"

processorArchitecture="$(build.processorArchitecture)"

publicKeyToken="$(Build.WindowsPublicKeyToken)"

version="$(build.version)"

versionScope="nonSxS"

/>

dependentAssembly>

dependency>

assembly>