[英]Event Trace for Windows (ETW) FileName in File events missing
I am trying to do some work with ETW in C#.我正在尝试在 C# 中使用 ETW 做一些工作。 Some raw events require a sort of 'aggregation' performed on them to obtain the full data in each event.
一些原始事件需要对它们执行某种“聚合”以获得每个事件中的完整数据。 This action takes information from some events and fills it in others.
此操作从某些事件中获取信息并将其填充到其他事件中。
This action can be performed on the output file of the ETW framework however I need to perform it dynamically in the real time of event apperance.此操作可以在 ETW 框架的 output 文件上执行,但是我需要在事件出现的实时动态执行它。 I managed to perform this for the registry events and their missing "KeyName" values thanks to the answers in this thread.
由于此线程中的答案,我设法为注册表事件及其丢失的“KeyName”值执行此操作。
I could not however find any information that would allow me to interpret the ETW file events to figure out the "FileName" attribute in each event.但是,我找不到任何信息可以让我解释 ETW 文件事件以找出每个事件中的“文件名”属性。
Does anyone know how the FileIO events should be interpreted to obtain missing "FileNames" in each event?有谁知道应该如何解释 FileIO 事件以在每个事件中获取缺少的“FileNames”? Are there any resources on this topic that I might have missed?
有没有我可能错过的关于这个主题的资源?
Ps.附言。 I am sorry if this question is unclear.
如果这个问题不清楚,我很抱歉。
You might be missing FileRundown events.您可能缺少 FileRundown 事件。 Normally,
KernelTraceEventParserState
keeps a dictionary which maps FileObject/FileKey to FileName.通常,
KernelTraceEventParserState
保留一个字典,将 FileObject/FileKey 映射到 FileName。 KernelTraceEventParser
configures various hooks to fill this dictionary. KernelTraceEventParser
配置各种钩子来填充这个字典。 The first problems are cleanup and delete events that remove file names from the dictionary before your hook is called.第一个问题是清理和删除事件,在调用钩子之前从字典中删除文件名。 For other events, the problem is that you miss FileKey mappings for processes that were running before your trace started.
对于其他事件,问题是您错过了跟踪开始之前正在运行的进程的 FileKey 映射。 And I haven't found a way to force the rundown events to run at the begging of the session.
而且我还没有找到一种方法来强制破败事件在 session 的请求下运行。 The only workaround I can propose is to run a short trace session with
DiskIO | DiskFileIO
我可以建议的唯一解决方法是使用 DiskIO 运行短跟踪
DiskIO | DiskFileIO
DiskIO | DiskFileIO
keywords enabled and prepare your file key map.启用
DiskIO | DiskFileIO
关键字并准备文件密钥 map。 Later, in the main session, update it when you receive the FileIO/Create
event.稍后,在主 session 中,在收到
FileIO/Create
事件时对其进行更新。 You may check a post on my blog to learn more details.您可以查看我博客上的帖子以了解更多详细信息。
Below, I paste the F# code I used to test FileIO events.下面,我粘贴了我用来测试 FileIO 事件的 F# 代码。 I hope it will help you with your scenario.
我希望它会帮助你解决你的场景。
open System
open System.Threading
open Microsoft.Diagnostics.Tracing
open Microsoft.Diagnostics.Tracing.Parsers
open Microsoft.Diagnostics.Tracing.Session
open System.Collections.Generic
open Microsoft.Diagnostics.Tracing.Parsers.Kernel
type NtKeywords = KernelTraceEventParser.Keywords
type ClrKeywords = ClrTraceEventParser.Keywords
let rundownFileKeyMap sessionName =
use session = new TraceEventSession(sessionName)
let traceFlags = NtKeywords.DiskFileIO ||| NtKeywords.DiskIO
session.EnableKernelProvider(traceFlags, NtKeywords.None) |> ignore
let fileKeyMap = Dictionary<uint64, string>()
session.Source.Kernel.add_FileIOFileRundown(fun ev -> fileKeyMap.[ev.FileKey] <- ev.FileName)
use cts = new CancellationTokenSource(TimeSpan.FromSeconds(2.0))
use _r = cts.Token.Register(fun _ -> session.Stop() |> ignore)
session.Source.Process() |> ignore
fileKeyMap
let processEvent (fileObjectAndKeyMap : Dictionary<uint64, string>) (ev : TraceEvent) =
let opcode = int32(ev.Opcode)
let fileKey =
let i = ev.PayloadIndex("FileKey")
if i >= 0 then ev.PayloadValue(i) :?> uint64 else 0UL
let fileObject =
let i = ev.PayloadIndex("FileObject")
if i >= 0 then ev.PayloadValue(i) :?> uint64 else 0UL
let path =
if opcode = 64 (* create *) then
let ev = ev :?> FileIOCreateTraceData
let fileName = ev.FileName
fileObjectAndKeyMap.[fileObject] <- fileName
fileName
else
let chooser k =
match fileObjectAndKeyMap.TryGetValue(k) with
| (true, s) -> Some s
| (false, _) -> None
seq { fileKey; fileObject }
|> Seq.tryPick chooser
|> Option.defaultValue "n/a"
printfn "%d %s (%d) (%s) [%d.%d] (%s) key: 0x%X object: 0x%X '%s'"
(uint32(ev.EventIndex)) ev.EventName opcode (ev.GetType().Name)
ev.ProcessID ev.ThreadID ev.ProcessName fileKey fileObject path
[<EntryPoint>]
let main _ =
let sessionName = sprintf "mytrace-%d" DateTime.UtcNow.Ticks
use session = new TraceEventSession(sessionName)
let traceFlags = NtKeywords.FileIOInit
let stackFlags = NtKeywords.None
session.EnableKernelProvider(traceFlags, stackFlags) |> ignore
printf "Collecting rundown events..."
let fileObjectAndKeyMap = rundownFileKeyMap (sprintf "%s_rundown" sessionName)
printfn "done"
printfn "Key map size: %d" fileObjectAndKeyMap.Count
use _sub = session.Source.Kernel.Observe(fun s -> s.StartsWith("FileIO", StringComparison.Ordinal))
|> Observable.subscribe (processEvent fileObjectAndKeyMap)
Console.CancelKeyPress.Add(fun ev -> ev.Cancel <- true; session.Stop() |> ignore)
session.Source.Process() |> ignore
printfn "Key map size: %d" fileObjectAndKeyMap.Count
0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.