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
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(())
}
#include "quent-tutorial-dynamic-attributes-cpp-bridge/gen/quent.hpp"
int main() {
auto context = quent::Context::none();
auto task = context.task_observer()->handle();
quent::DynamicAttributes started_details;
started_details.add("queue", "priority");
started_details.add("attempt", std::uint64_t{2});
task.started(quent::task::Started{.details = std::move(started_details)});
quent::DynamicAttributes ended_details;
ended_details.add("cached", false);
ended_details.add("items_processed", std::uint64_t{128});
task.ended(quent::task::Ended{.details = std::move(ended_details)});
return 0;
}
import quent_tutorial_dynamic_attributes as quent
def main() -> None:
with quent.Context() as context:
task = context.task_observer().handle()
task.started(
details={"queue": "priority", "attempt": quent.DynamicValue.u64(2)}
)
task.ended(
details={
"cached": False,
"items_processed": quent.DynamicValue.u64(128),
}
)
if __name__ == "__main__":
main()
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. The target-language API provides wrappers or conversions for selecting an
exact numeric type. Dynamic attributes also support null values, which do not
retain an intended value type.
Use dynamic attributes for event details that cannot be defined in advance.