Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Dynamic attributes

Most event attributes have names and types fixed by the schema. This lets the generated instrumentation API check their use before the application runs.

The dynamic type provides a typed container whose keys and value types are chosen when the event is emitted. It is useful when the available details cannot be known while writing the schema. The generated event method still requires a dynamic attribute container, but the schema does not check the keys or types placed inside it. Prefer regular attributes for stable event data.

YAML model

quent: alpha
model: dynamic_data

entities:
  Task:
    events:
      started:
        attributes:
          details: dynamic
      ended:
        attributes:
          details: dynamic

The schema declares one dynamic container on each event. It does not declare the individual keys that the containers will hold.

Instrumentation API

// SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

#[allow(unused)]
mod instrumentation {
    include!(concat!(env!("OUT_DIR"), "/dynamic_data.rs"));
}

use instrumentation::{Context, DynamicAttributes, DynamicData, Noop, Task};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let context = Context::<DynamicData>::try_new(Noop)?;
    let mut task = context.observer::<Task>().handle();

    let mut started_details = DynamicAttributes::new();
    started_details.add("queue", "priority");
    started_details.add("attempt", 2_u64);
    task.started(started_details)?;

    let mut ended_details = DynamicAttributes::new();
    ended_details.add("cached", false);
    ended_details.add("items_processed", 128_u64);
    task.ended(ended_details)?;

    Ok(())
}

The generic add method converts each supported Rust value into its dynamic representation. The application adds a string and an integer to the started event, then a boolean and an integer to the ended event. Each value retains its runtime type; integer suffixes such as _u64 select the intended type. Use DynamicNull for a key with no value: attributes.add("key", instrumentation::DynamicNull). Null values do not retain an intended value type.

Key point

Use dynamic attributes for event details that cannot be defined in advance.

Check yourself

Where are keys such as queue and cached defined?

What is the main tradeoff of using dynamic?