Summary
Add public ETW helpers that resolve provider names to the GUIDs needed by EtwSession::enable_provider.
Today, enable_provider only accepts a Guid, so any consumer starting from a provider name has to implement its own name-to-GUID resolution. That logic differs by provider model:
- Manifest/classic MOF providers must be looked up from the OS provider database.
- TraceLogging / TraceLoggingDynamic providers use the EventSource name-hash convention and can be derived directly from the provider name.
This issue proposes exposing both resolution paths from one_collect so consumers can reuse a single implementation instead of duplicating TDH enumeration code and EventSource hashing logic.
Proposed API
#[derive(Clone, Copy)]
pub struct RegisteredProvider {
pub guid: Guid,
pub schema_source: u32,
}
pub fn registered_providers() -> anyhow::Result<HashMap<String, RegisteredProvider>>;
impl Guid {
pub fn from_eventsource_name(name: &str) -> Guid;
}
pub fn guid_from_tracelogging_name(provider_name: &str) -> anyhow::Result<Guid>;
Scope
In scope
- Add
registered_providers() in one_collect::etw to enumerate OS-registered ETW providers via TdhEnumerateProviders and return a case-insensitive name -> RegisteredProvider map.
- Add a public
RegisteredProvider type carrying the resolved control guid and schema_source.
- Expose the EventSource/TraceLogging name-hash convention as
Guid::from_eventsource_name.
- Add a Windows-facing
guid_from_tracelogging_name wrapper in one_collect::etw.
- Refactor existing internal EventSource hashing code to delegate to the new shared implementation.
Out of scope
- A policy layer that decides when to use registered lookup vs. TraceLogging name-hash.
- Global caching across calls.
- Adding
EtwSession::enable_provider_by_name.
- Explicit WPP support.
Design notes
- Place this surface in
etw, next to EtwSession::enable_provider, rather than in etw::tdh.
registered_providers() should do a single TdhEnumerateProviders pass and return an owned map.
- Include both manifest (
SchemaSource == 0) and classic MOF (SchemaSource == 1) providers.
- Normalize map keys to lowercase for case-insensitive lookup.
- For duplicate provider names, keep the first entry.
guid_from_tracelogging_name should cover self-describing TraceLogging / TraceLoggingDynamic names and direct {GUID} literals.
- Consumers should try
registered_providers() first and only fall back to TraceLogging name-hash resolution when the name is absent from the registered map.
Implementation notes
- Reuse
windows-sys TDH types/functions already used in the ETW codepath (TdhEnumerateProviders, PROVIDER_ENUMERATION_INFO, TRACE_PROVIDER_INFO).
- Use a properly aligned buffer for provider enumeration; do not reinterpret an under-aligned
Vec<u8>.
- Preserve the existing
.NET helper behavior, but route the shared EventSource hash path through Guid::from_eventsource_name so there is a single copy of the namespace/encoding logic.
Motivation
This is primarily needed by downstream ETW consumers that are configured by provider name rather than GUID. In particular, the otel-arrow ETW receiver currently carries both:
- its own
TdhEnumerateProviders FFI for registered provider lookup, and
- a duplicate copy of the EventSource namespace/hash logic.
Publishing this API from one_collect would let downstream consumers delete that duplicated logic and keep only their configuration policy.
Acceptance criteria
- Consumers can resolve manifest/classic MOF provider names through
registered_providers().
- Consumers can resolve TraceLogging / TraceLoggingDynamic names through
Guid::from_eventsource_name / guid_from_tracelogging_name.
- Internal duplicated EventSource hash logic is consolidated behind the new public API.
- The API is released in a published
one_collect version so downstream consumers can adopt it.
Summary
Add public ETW helpers that resolve provider names to the GUIDs needed by
EtwSession::enable_provider.Today,
enable_provideronly accepts aGuid, so any consumer starting from a provider name has to implement its own name-to-GUID resolution. That logic differs by provider model:This issue proposes exposing both resolution paths from
one_collectso consumers can reuse a single implementation instead of duplicating TDH enumeration code and EventSource hashing logic.Proposed API
Scope
In scope
registered_providers()inone_collect::etwto enumerate OS-registered ETW providers viaTdhEnumerateProvidersand return a case-insensitivename -> RegisteredProvidermap.RegisteredProvidertype carrying the resolved controlguidandschema_source.Guid::from_eventsource_name.guid_from_tracelogging_namewrapper inone_collect::etw.Out of scope
EtwSession::enable_provider_by_name.Design notes
etw, next toEtwSession::enable_provider, rather than inetw::tdh.registered_providers()should do a singleTdhEnumerateProviderspass and return an owned map.SchemaSource == 0) and classic MOF (SchemaSource == 1) providers.guid_from_tracelogging_nameshould cover self-describing TraceLogging / TraceLoggingDynamic names and direct{GUID}literals.registered_providers()first and only fall back to TraceLogging name-hash resolution when the name is absent from the registered map.Implementation notes
windows-sysTDH types/functions already used in the ETW codepath (TdhEnumerateProviders,PROVIDER_ENUMERATION_INFO,TRACE_PROVIDER_INFO).Vec<u8>..NEThelper behavior, but route the shared EventSource hash path throughGuid::from_eventsource_nameso there is a single copy of the namespace/encoding logic.Motivation
This is primarily needed by downstream ETW consumers that are configured by provider name rather than GUID. In particular, the
otel-arrowETW receiver currently carries both:TdhEnumerateProvidersFFI for registered provider lookup, andPublishing this API from
one_collectwould let downstream consumers delete that duplicated logic and keep only their configuration policy.Acceptance criteria
registered_providers().Guid::from_eventsource_name/guid_from_tracelogging_name.one_collectversion so downstream consumers can adopt it.