Skip to content

ETW: Provider name to GUID resolution via One-Collect APIs #316

Description

@swashtek

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions