Skip to main content

TraceGrouping

Struct TraceGrouping 

Source
#[non_exhaustive]
pub struct TraceGrouping { pub session_id: Option<String>, pub end_user_hash: Option<String>, pub tags: Vec<String>, pub environment: Option<String>, pub release: Option<String>, }
Expand description

Vendor-neutral grouping of spans: which session, which end user, which tags, which environment, which release.

LLM observability backends filter at the level of the individual span, not only at the trace root, so the grouping has to reach every span rather than sit on the first one. Two ways to make that happen:

  • Without the otel feature, TraceGrouping::stamp fills the grouping fields — which every span this crate opens declares empty — on whichever span you hand it, and TraceGrouping::scope_span opens a parent span that carries them for a subscriber that flattens ancestors.
  • With the otel feature, crate::otel::attach_grouping puts the same values in OpenTelemetry baggage on the current context, where a baggage-copying span processor in the application’s SDK setup stamps them onto every span that starts underneath. The processor itself lives in the adopter’s code because it needs opentelemetry_sdk, which this crate does not depend on; crate::otel::grouping_from_baggage gives it the key/values to copy.

The end-user reference is always a digest — build it with TraceGrouping::with_account, which hashes the account id, or supply your own digest with TraceGrouping::with_end_user_hash. There is no constructor that takes a raw account or user identifier.

A backend that insists on its own attribute names is a renaming function over TraceGrouping::fields in the adopter’s code, not something this crate hardcodes.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§session_id: Option<String>

The session, recorded as session.id. Turnframe uses the conversation.

§end_user_hash: Option<String>

Digest of the end user, recorded as user.id. Never a raw identifier.

§tags: Vec<String>

Free-form grouping labels the application chose.

§environment: Option<String>

Deployment environment, e.g. production.

§release: Option<String>

Release or build of the running service.

Implementations§

Source§

impl TraceGrouping

Source

pub fn for_conversation(conversation_id: ConversationId) -> Self

Groups spans by conversation, which is the session a backend shows.

Source

pub fn with_account(self, account_id: &AccountId) -> Self

Adds the end user as the digest of an account id. The raw id is hashed by account_hash and never stored on the grouping.

Source

pub fn with_end_user_hash(self, hash: impl Into<String>) -> Self

Adds an end-user reference the caller has already hashed.

Source

pub fn with_tag(self, tag: impl Into<String>) -> Self

Adds a grouping label.

Source

pub fn with_environment(self, environment: impl Into<String>) -> Self

Sets the deployment environment.

Source

pub fn with_release(self, release: impl Into<String>) -> Self

Sets the release or build.

Source

pub fn fields(&self) -> Vec<(&'static str, String)>

The grouping as (attribute key, value) pairs in a stable order, omitting what is unset. Testable without a subscriber, and the set an adopter renames for a backend with its own spelling.

Source

pub fn stamp(&self, span: &Span)

Records the grouping on span.

Every span this crate opens declares the grouping fields empty, so this fills them in. Recording on a span that did not declare them is a no-op rather than an error.

Source

pub fn stamp_current(&self)

Records the grouping on the span that is currently entered.

Source

pub fn scope_span(&self) -> Span

Opens a span that carries the grouping and becomes the parent of every span opened while it is entered.

use turnframe_core::ids::{AccountId, ConversationId};
use turnframe_telemetry::tracing::TraceGrouping;

let grouping = TraceGrouping::for_conversation(ConversationId::nil())
    .with_account(&AccountId::from("acct-1"))
    .with_environment("production")
    .with_release("v0.1.0")
    .with_tag("trip");

let span = grouping.scope_span();
let _entered = span.enter();

Trait Implementations§

Source§

impl Clone for TraceGrouping

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TraceGrouping

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for TraceGrouping

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for TraceGrouping

Source§

impl PartialEq for TraceGrouping

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for TraceGrouping

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self> ⓘ

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more