EventBuilder

Struct EventBuilder 

Source
pub struct EventBuilder { /* private fields */ }
Expand description

EventBuilder is a builder for events to be written through a Provider.

§Overview

  • Check EventSet::enabled, e.g. my_eventset_l5k1.enabled() and only do the remaining steps if it returns true. This avoids the unnecessary work of building and writing the event when no trace collection sessions are listening for your event.
  • Get an EventBuilder, e.g. let mut builder = EventBuilder::new();.
    • EventBuilder is reusable. In some scenarios, you may get a performance improvement by reusing builders instead of creating a new one for each event.
  • Call builder.reset("EventName", event_tag) to begin building an event.
    • The event name should be short and distinct. Don’t use same name for two events in the same provider that have different fields, levels, or keywords.
    • event_tag is a 16-bit provider-defined value that will be included in the metadata of the event. Use 0 if you are not using event tags.
  • For each field you want to add to the event, call one of the add methods, builder.add_KIND("FieldName", field_value, FieldFormat::FORMAT, field_tag).
    • Use EventBuilder::add_value to add a field containing a simple value like a bool, char, float, integer, or UUID.
    • Use EventBuilder::add_value_sequence to add a field containing a sequence of simple values like an array of integers.
    • Use EventBuilder::add_str to add a field containing a string or a binary blob.
    • Use EventBuilder::add_str_sequence to add a field containing a sequence of strings or a sequence of binary blobs.
    • Use EventBuilder::add_struct to add a field that contains a group of sub-fields.
    • The field name should be short and distinct.
    • The field_format controls the how the bytes of the field value will be interpreted by the decoder. For example, if you add a field with a 4-byte value, the field_format tells the decoder whether to treat these 4 bytes as a decimal signed integer, a decimal unsigned integer, a hexadecimal unsigned integer, a UCS-4 char, a float, a time, an errno, etc.
    • field_tag is a 16-bit provider-defined value that will be included in the metadata of the field. Use 0 if you are not using field tags.
  • If appropriate, configure other event options by calling:
    • builder.id_version(id, ver) to set a manually-assigned event id and version.
    • builder.opcode(opcode) to specify special semantics for the event, e.g. activity-start or activity-stop.
  • Call builder.write(event_set, activity_id, related_id) to send the event to the kernel.
    • activity_id is an optional 128-bit value that can be used during trace analysis to group and correlate events. This should be specified for events that are part of an activity (part of a group of related events), or None if the event is not part of an activity.
    • related_id is an optional 128-bit value that indicates the parent of a newly-started activity. This may be specified for ActivityStart events and should be None for other events.

§Event Size Limits

Linux tracepoints have a 64KB size limit. The size includes event headers (timestamp, level, etc.), metadata (event name, field names, field types), and data (field values). Events that are too large will cause builder.write to return an error.

Implementations§

Source§

impl EventBuilder

Source

pub fn new() -> EventBuilder

Returns a new event builder with default initial buffer capacity.

Default capacity is currently 256 bytes for meta and 256 bytes for data. Buffers will automatically grow as needed.

Source

pub fn new_with_capacity(meta_capacity: u16, data_capacity: u16) -> EventBuilder

Returns a new event builder with specified initial buffer capacities. Buffers will automatically grow as needed.

Source

pub fn reset(&mut self, name: &str, event_tag: u16) -> &mut Self

Clears the previous event (if any) from the builder and starts building a new event.

  • name is the event name. It should be short and unique. It must not contain any '\0' bytes.

  • event_tag is a 16-bit integer that will be recorded in the event and can be used for any provider-defined purpose. Use 0 if you are not using event tags.

Source

pub fn write( &self, event_set: &EventSet, activity_id: Option<&[u8; 16]>, related_id: Option<&[u8; 16]>, ) -> i32

Sends the finished event to the kernel with the provider, event level, and event keyword of the specified event set.

  • event_set should be a registered and enabled event set. Calling write on an unregistered or disabled event set is a safe no-op (usually returns 0 in this case, though it may return ERANGE if the event is too large).

  • activity_id contains the activity id to be assigned to the event. Use None if the event is not part of an activity. (An activity is a group of related events that all have the same activity id, started by an event with Opcode::ActivityStart and ended by an event with Opcode::ActivityStop.)

  • related_id contains the related activity id (parent activity) to be used for an activity-start event. Use None if this is not an activity-start event or if the activity does not have a parent activity. If activity_id is None, this must also be None.

Returns 0 for success. Returns EBADF (9) if no consumer is listening to this tracepoint. Returns ERANGE (34) if the event (headers + metadata + data) is greater than 64KB. Returns other errors as reported by writev. The return value is for diagnostic/debugging purposes only and should generally be ignored in retail builds.

Source

pub fn id_version(&mut self, id: u16, version: u8) -> &mut Self

Sets the id and version of the event. Default is id = 0, version = 0.

EventHeader events are primarily identified by event name, not by event id. Most events use id = 0, version = 0 and therefore do not need to call this method.

Events should use id = 0 and version = 0 unless they have a manually-assigned stable id. If the event has a manually-assigned stable id, it must be a nonzero value and the version should be incremented each time the event schema changes (i.e. each time the field names or field types are changed).

Source

pub fn opcode(&mut self, opcode: Opcode) -> &mut Self

Sets the opcode of the event. Default opcode is Opcode::Info (0).

Most events use opcode Info and therefore do not need to call this method.

You can use opcode to create an activity (a group of related events):

  1. Begin the activity by writing an activity-start event with opcode = ActivityStart, activity_id = the id of the new activity (generated by e.g. Uuid::new_v4), and related_id = the id of the parent activity (or None for no parent).
  2. As appropriate, write activity-info events with opcode = Info, activity_id = the id of the activity, and related_id = None.
  3. End the activity by writing an activity-stop event with opcode = ActivityStop, activity_id = the id of the activity, related_id = None, and the same event set as was used for the activity-start event.
Source

pub fn add_struct( &mut self, field_name: &str, struct_field_count: u8, field_tag: u16, ) -> &mut Self

Adds a field containing the specified number of sub-fields.

A struct is a way to logically group a number of fields. To add a struct to an event, call builder.add_struct("StructName", struct_field_count, field_tag). Then add struct_field_count more fields and they will be considered to be members of the struct.

  • field_name should be a short and distinct string that describes the field.

  • struct_field_count specifies the number of subsequent fields that will be considered to be part of this struct field. This must be in the range 1 to 127. Empty structs (structs that contain no fields) are not permitted.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

Structs can nest. Each nested struct and its fields count as 1 field for the parent struct.

Source

pub fn add_struct_with_bookmark( &mut self, field_name: &str, initial_struct_field_count: u8, field_tag: u16, field_count_bookmark: &mut usize, ) -> &mut Self

Advanced: Adds a field containing the specified number of sub-fields, returning a bookmark that can be used for a subsequent call to EventBuilder::set_struct_field_count. This can be used for cases where you do not yet know the actual number of fields that will be in the struct.

  • field_name should be a short and distinct string that describes the field.

  • initial_struct_field_count specifies your initial guess for the number of subsequent fields that will be considered to be part of this struct field. This must be in the range 1 to 127. Empty structs (structs that contain no fields) are not permitted.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

  • field_count_bookmark receives a bookmark that can later be used in a call to EventBuilder::set_struct_field_count.

Example:

// Assume some dynamic number of fields that can be enumerated but where we can't
// determine ahead of time how many fields there will be, i.e. where the
// collection of fields has `field_vals.is_empty()` and `field_vals.into_iter()`
// methods but does not have a `field_vals.len()` method.
let field_vals = [1, 2, 3];

use eventheader_dynamic as ehd;
let mut builder = ehd::EventBuilder::new();
builder.reset("EventWithStruct", 0);

// Structs with 0 fields are not allowed, so don't create a struct if field_vals is empty.
if !field_vals.is_empty() {
    let mut struct1_count = 0;
    let mut struct1_bookmark = 0;

    // Add the struct, tentatively set to 1 sub-field.
    builder.add_struct_with_bookmark("struct1", 1, 0, &mut struct1_bookmark);
    for val in field_vals {
        builder.add_value("val", val, ehd::FieldFormat::Default, 0);
        struct1_count += 1;
    }

    // Update the struct to set the actual number of sub-fields.
    builder.set_struct_field_count(struct1_bookmark, struct1_count);
}
Source

pub fn set_struct_field_count( &mut self, field_count_bookmark: usize, updated_struct_field_count: u8, ) -> &mut Self

Advanced: Changes the number of sub-fields in a struct, using a bookmark returned by EventBuilder::add_struct_with_bookmark. This can be used when you do not know the number of fields for a struct when the struct begins, but you determine the number of fields later.

  • field_count_bookmark is the value received from the call to EventBuilder::add_struct_with_bookmark for the struct that you are updating.

  • updated_struct_field_count is the new value to use for the struct’s field count. This must be in the range 1 to 127. Empty structs (structs that contain no fields) are not permitted.

Source

pub fn add_value<V: ValueField>( &mut self, field_name: &str, field_value: V, format: FieldFormat, field_tag: u16, ) -> &mut Self

Adds a field containing a simple value.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field. Note that the data is treated as raw bytes, i.e. there will be no error, warning, or data conversion if the type of the field_value parameter conflicts with the FieldFormat specified by the format parameter. See below for the types accepted for this parameter.

  • format indicates how the decoder should interpret the field data. For example, if the field value is i8 or i32, you would likely set format to FieldFormat::SignedInt, and if the field value is f64, you would likely set format to FieldFormat::Float.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

Types:

Notes:

Source

pub fn add_value_sequence<'a, V: 'a + ValueField>( &mut self, field_name: &str, field_values: impl IntoIterator<Item = &'a V>, format: FieldFormat, field_tag: u16, ) -> &mut Self

Adds a field containing a sequence of simple values such as an array of integers.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as an IntoIterator-of-reference- to-ELEMENT, e.g. &[u8] or &[float]. The ELEMENT types accepted by this method are the same as the value types accepted by EventBuilder::add_value. Note that the element data is treated as raw bytes, i.e. there will be no error, warning, or data conversion if the type of the element conflicts with the FieldFormat specified by the format parameter.

  • format indicates how the decoder should interpret the field data. For example, if the field value is &[i8] or &[i32], you would likely set format to FieldFormat::SignedInt, and if the field value is &[f64], you would likely set format to FieldFormat::Float.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

See EventBuilder::add_value for additional details about the compatible element types and how they are treated.

For strings or binary blobs, use EventBuilder::add_str instead of this method. If you pass a string or blob to this method, the decoder will format the field as an array of values (e.g. ['a', 'b', 'c'] or [0x61, 0x62, 0x63]) rather than as a string or blob (e.g. "abc" or "61 62 63").

Source

pub fn add_str<V: StringField>( &mut self, field_name: &str, field_value: impl AsRef<[V]>, format: FieldFormat, field_tag: u16, ) -> &mut Self

Adds a field containing a string or a binary blob.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as a &[ELEMENT], e.g. &[u8] or &[char]. See below for the ELEMENT types accepted for this parameter.

  • format indicates how the decoder should interpret the field data. For example, if the field value is a Unicode string, you would likely set format to FieldFormat::Default (resulting in the field decoding as StringUtf), and if the field value is a binary blob, you would likely set format to FieldFormat::HexBytes.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

Types:

Note that FieldFormat::Default saves 1 byte in the trace. For string/binary encodings, FieldFormat::Default is treated as FieldFormat::StringUtf, so you can save 1 byte in the trace by using FieldFormat::Default instead of FieldFormat::StringUtf for string fields.

This is the same as add_cstr except that the field will be encoded as a counted sequence instead of as a nul-terminated string. In most cases you should prefer this method and use add_cstr only if you specifically need the nul-terminated encoding.

Source

pub fn add_str_sequence<I: IntoIterator, V: StringField>( &mut self, field_name: &str, field_values: I, format: FieldFormat, field_tag: u16, ) -> &mut Self
where I::Item: AsRef<[V]>,

Adds a field containing a sequence of strings or binary blobs.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as an IntoIterator-of-&[ELEMENT].

  • format indicates how the decoder should interpret the field data. For example, if the field value contains Unicode strings, you would likely set format to FieldFormat::Default (resulting in the field decoding as StringUtf), and if the field value contains binary blobs, you would likely set format to FieldFormat::HexBytes.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

See EventBuilder::add_str for additional details about the compatible element types and how they are treated.

This is the same as add_cstr_sequence except that the field will be encoded as a counted sequence instead of as a nul-terminated string. In most cases you should prefer this method and use add_cstr_sequence only if you specifically need the nul-terminated encoding.

Source

pub fn add_cstr<V: StringField>( &mut self, field_name: &str, field_value: impl AsRef<[V]>, format: FieldFormat, field_tag: u16, ) -> &mut Self

Adds a field containing a nul-terminated string.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as a &[ELEMENT], e.g. &[u8] or &[char]. The field will include the provided values up to the first 0 value in the slice (if any). See below for the element types accepted for this parameter.

  • format indicates how the decoder should interpret the field data. For example, if the field value is a Unicode string, you would likely set format to FieldFormat::Default (resulting in the field decoding as StringUtf), and if the field value is a binary blob, you would likely set format to FieldFormat::HexBytes.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

Types:

Note that FieldFormat::Default saves 1 byte in the trace. For string/binary encodings, FieldFormat::Default is treated as FieldFormat::StringUtf, so you can save 1 byte in the trace by using FieldFormat::Default instead of FieldFormat::StringUtf for string fields.

This is the same as add_str except that the field will be encoded as a nul-terminated string instead of as a counted string. In most cases you should prefer add_str and use this method only if you specifically need the nul-terminated encoding.

Source

pub fn add_cstr_sequence<I: IntoIterator, V: StringField>( &mut self, field_name: &str, field_values: I, format: FieldFormat, field_tag: u16, ) -> &mut Self
where I::Item: AsRef<[V]>,

Adds a field containing a sequence of nul-terminated strings.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as an IntoIterator-of-&[ELEMENT].

  • format indicates how the decoder should interpret the field data. For example, if the field value contains Unicode strings, you would likely set format to FieldFormat::StringUtf.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

See EventBuilder::add_cstr for additional details about the compatible element types and how they are treated.

This is the same as add_str_sequence except that the field will be encoded as a nul-terminated string instead of as a counted string. In most cases you should prefer add_str_sequence and use this method only if you specifically need the nul-terminated encoding.

Source

pub fn add_binary<V: BinaryField>( &mut self, field_name: &str, field_value: impl AsRef<[V]>, format: FieldFormat, field_tag: u16, ) -> &mut Self

Adds a field containing a nullable value or a binary blob.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as a &[ELEMENT], i.e. &[u8] or &[i8].

  • format indicates how the decoder should interpret the field data. For example, if the field value is a binary blob, you would likely set format to FieldFormat::Default (resulting in the field decoding as HexBytes), and if the field value is a nullable unsigned integer (length 0 for null or length 1, 2, 4, or 8 for non-null), you would set format to FieldFormat::UnsignedInt.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

Types:

  • The field will be encoded as FieldEncoding::BinaryLength16Char8.
  • If format is FieldFormat::Default, the field will be formatted as FieldFormat::HexBytes.
  • This can be used with any format.
    • When used with a variable-length format like HexBytes or one of the String formats, this results in a variable-length sequence.
    • When used with a fixed-length format like UnsignedInt, this results in a nullable field. If the length of the provided field_value is 0, the field will be interpreted as null. If the length is 1, 2, 4, or 8, the field will be interpreted as an unsigned integer. If the length is anything else, the field will be interpreted as HexBytes.

Note that FieldFormat::Default saves 1 byte in the trace. For binary encodings, FieldFormat::Default is treated as FieldFormat::HexBytes, so you can save 1 byte in the trace by using FieldFormat::Default instead of FieldFormat::HexBytes.

Source

pub fn add_binary_sequence<I: IntoIterator, V: BinaryField>( &mut self, field_name: &str, field_values: I, format: FieldFormat, field_tag: u16, ) -> &mut Self
where I::Item: AsRef<[V]>,

Adds a field containing a sequence of nullable values or binary blobs.

  • field_name should be a short and distinct string that describes the field.

  • field_value provides the data for the field as an IntoIterator-of-&[ELEMENT].

  • format indicates how the decoder should interpret the field data. For example, if the field value contains binary blobs, you would likely set format to FieldFormat::Default (resulting in the field decoding as HexBytes), and if the field value contains nullable unsigned integers (length 0 for null or length 1, 2, 4, or 8 for non-null), you would set format to FieldFormat::UnsignedInt.

  • field_tag is a 16-bit integer that will be recorded in the field and can be used for any provider-defined purpose. Use 0 if you are not using field tags.

See EventBuilder::add_binary for additional details about the compatible element types and how they are treated.

Source

pub fn raw_add_meta_scalar( &mut self, field_name: &str, encoding: FieldEncoding, format: FieldFormat, field_tag: u16, ) -> &mut Self

Advanced scenarios: Directly adds unchecked metadata to the event. Using this method may result in events that do not decode correctly.

There are a few things that are supported by EventHeader that cannot be expressed by directly calling the add methods, e.g. array-of-struct. If these edge cases are important, you can use the raw_add_meta and raw_add_data methods to generate events that would otherwise be impossible. Doing this requires advanced understanding of the EventHeader encoding system. If done incorrectly, the resulting events will not decode properly.

Source

pub fn raw_add_meta_vcount( &mut self, field_name: &str, encoding: FieldEncoding, format: FieldFormat, field_tag: u16, ) -> &mut Self

Advanced scenarios: Directly adds unchecked metadata to the event. Using this method may result in events that do not decode correctly.

There are a few things that are supported by EventHeader that cannot be expressed by directly calling the add methods, e.g. array-of-struct. If these edge cases are important, you can use the raw_add_meta and raw_add_data methods to generate events that would otherwise be impossible. Doing this requires advanced understanding of the EventHeader encoding system. If done incorrectly, the resulting events will not decode properly.

Source

pub fn raw_add_data_value<T: Copy>(&mut self, value: &T) -> &mut Self

Advanced scenarios: Directly adds unchecked data to the event. Using this method may result in events that do not decode correctly.

There are a few things that are supported by EventHeader that cannot be expressed by directly calling the add methods, e.g. array-of-struct. If these edge cases are important, you can use the raw_add_meta and raw_add_data methods to generate events that would otherwise be impossible. Doing this requires advanced understanding of the EventHeader encoding system. If done incorrectly, the resulting events will not decode properly.

Source

pub fn raw_add_data_slice<T: Copy>(&mut self, value: &[T]) -> &mut Self

Advanced scenarios: Directly adds unchecked data to the event. Using this method may result in events that do not decode correctly.

There are a few things that are supported by EventHeader that cannot be expressed by directly calling the add methods, e.g. array-of-struct. If these edge cases are important, you can use the raw_add_meta and raw_add_data methods to generate events that would otherwise be impossible. Doing this requires advanced understanding of the EventHeader encoding system. If done incorrectly, the resulting events will not decode properly.

Trait Implementations§

Source§

impl Debug for EventBuilder

Source§

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

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

impl Default for EventBuilder

Source§

fn default() -> Self

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

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.