Crate tracelogging_dynamic
source ·Expand description
TraceLoggingDynamic for Rust
tracelogging_dynamic
provides a flexible way to log
TraceLogging
(manifest-free) events to
ETW
(Event Tracing for Windows). The events can be generated and collected on Windows
Vista or later. The events can be decoded on Windows 10 or later.
This “dynamic” implementation of TraceLogging supports more functionality than the
implementation in the tracelogging
crate. For example, it supports
runtime-defined schema and can easily log arrays of strings. However, it is harder to
use, has higher runtime costs, and has additional runtime dependencies than the
tracelogging
crate. This dynamic implementation is intended for use only when the
set of events cannot be determined at compile-time. For example,
traceloggingdynamic
might be used to implement a middle-layer library providing
ETW support to a scripting language like JavaScript or Perl.
Overview
-
Create a pinned Provider object, e.g.
let mut provider = Box::pin(Provider::new());
- See the documentation for the Provider class for ways to pin the provider without a heap allocation.
-
Call Provider::register to open the connection to ETW, e.g.
unsafe { provider.as_mut().register(provider_name, options); }
- Safety: Provider::register is unsafe because a registered provider must be properly unregistered. This happens automatically when the provider is dropped, so you usually don’t need to worry about this, but it can be an issue in cases where dropping does not occur such as with static variables.
-
As needed, use an EventBuilder to construct and write events.
-
The provider will automatically unregister when it is dropped. You can manually call Provider::unregister if you want to unregister sooner or if the provider is a static variable.
Example
use tracelogging_dynamic as tld;
// Pinning is required because the register() method sets up a callback with ETW.
let mut provider = Box::pin(tld::Provider::new());
// Register the provider with name "MyCompany.MyComponent". If you don't register (or
// if register fails) then enabled() will always return false and write() will be a
// no-op.
unsafe {
provider.as_mut().register("MyCompany.MyComponent", &tld::Provider::options());
}
// If provider is not enabled for a given level + keyword, the write() call will do
// nothing. Check enabled(level, keyword) before building the event so we don't waste
// time on an event that nobody will receive.
let my_event_level = tld::Level::Verbose; // Severity level.
let my_event_keyword = 0x123; // User-defined category bits.
if provider.enabled(my_event_level, my_event_keyword) {
let field1_value = "FieldValue";
let field2_value = b'A';
// Create and write an event with two fields:
tld::EventBuilder::new()
// Most events specify 0 for event tag.
.reset("MyEventName", my_event_level, my_event_keyword, 0)
// Most fields use Default for event format and 0 for field tag.
.add_str8("FieldName1", field1_value, tld::OutType::Default, 0)
.add_u8("FieldName2", field2_value, tld::OutType::String, 0)
// If activity_id is None, event uses the current thread's activity.
// If related_id is None, event will not have a related activity.
.write(&provider, None, None);
}
Notes
The EventBuilder object is reusable. You may get a small performance benefit by reusing an EventBuilder object for multiple events rather than using a new EventBuilder for each event.
ETW events are limited in size (event size = headers + metadata + data). Windows will ignore any event that is larger than 64KB and will ignore any event that is larger than the buffer size of the recording session.
Most ETW decoding tools are unable to decode an event with more than 128 fields.
Collect the events using Windows SDK tools like
traceview or
tracelog.
Decode the events using Windows SDK tools like
traceview or
tracefmt.
For example, to collect events from a provider that was registered as
provider.register("MyCompany.MyComponent", ...)
:
tracelog -start MyTrace -f MyTraceFile.etl -guid *MyCompany.MyComponent -level 5 -matchanykw 0xf
<run your program>
tracelog -stop MyTrace
tracefmt -o MyTraceData.txt MyTraceFile.etl
Macros
- Converts a
std::time::SystemTime
value into a Windows FILETIME (represented asi64
). The resulting value can be used with [write_event!
] via thewin_filetime
field type.
Structs
- Advanced: Indicates routing and decoding for an event.
EventBuilder
is a builder for events to be written through a Provider.- Advanced: Used to indicate the field’s type for raw metadata operations.
- Indicates the severity of an event. Use Verbose if unsure.
- Indicates special semantics to be used by the event decoder for grouping and organizing events, e.g. for activities.
- Data formatting hint that may be used or ignored by decoders.
- Represents a connection for writing dynamic TraceLogging (manifest-free) events to ETW.
- Builder for advanced provider configuration. Used when registering a provider.
Enums
- Possible configurations under which this crate can be compiled:
Windows
orOther
.
Constants
- The configuration under which this crate was compiled:
Windows
orOther
.
Type Definitions
- Signature for a custom provider enable callback.