@@ -80,40 +80,70 @@ For more on how to use these configuration variables, see the [configuration doc
8080
8181## Practical Usage
8282
83- ### Instrumenting Functions
83+ There are two valid ways to emit KVP data:
84+ - Use the direct ` Kvp ` client API for explicit event/report writes.
85+ - Use tracing instrumentation (` #[instrument] ` and ` event! ` ) with ` setup_layers ` .
8486
85- To instrument code with tracing, use the ` #[instrument] ` attribute on functions:
87+ ### Using the KVP Client API
8688
87- ``` rust
88- use tracing :: {instrument, Level , event};
89+ For external callers that want to emit KVP diagnostics directly, use the ` Kvp ` client:
8990
90- #[instrument(fields(user_id = ? user. id))]
91- async fn provision_user (user : User ) -> Result <(), Error > {
92- event! (Level :: INFO , " Starting user provisioning" );
93-
94- // Function logic
95-
96- event! (Level :: INFO , " User provisioning completed successfully" );
91+ ``` rust
92+ use libazureinit :: logging :: {Kvp , KvpOptions };
93+ use tracing :: Level ;
94+
95+ #[tokio:: main]
96+ async fn main () -> anyhow :: Result <()> {
97+ // Simple path: all defaults
98+ let kvp = Kvp :: new ()? ;
99+ kvp . emit (" Provisioning started" , None )? ; // defaults to DEBUG
100+ kvp . emit (" Provisioning info event" , Some (Level :: INFO ))? ;
101+ kvp . emit_health_report (" result=success" )? ;
102+ kvp . close (). await ? ;
103+
104+ // Advanced path: override defaults
105+ let custom = Kvp :: with_options (
106+ KvpOptions :: default ()
107+ . vm_id (" 00000000-0000-0000-0000-000000000001" )
108+ . event_prefix (" my-service" )
109+ . file_path (" /var/lib/hyperv/.kvp_pool_1" )
110+ . truncate_on_start (true ),
111+ )? ;
112+ custom . emit (" Custom event payload" , None )? ;
113+ custom . close (). await ? ;
97114 Ok (())
98115}
99116```
100117
101- ### Emitting Events
118+ Default behavior for ` Kvp::new() ` :
119+ - ` vm_id ` : resolved from platform metadata (` get_vm_id ` )
120+ - ` event_prefix ` : ` "azure-init-<version>" ` (e.g. ` "azure-init-0.1.1" ` )
121+ - ` file_path ` : ` /var/lib/hyperv/.kvp_pool_1 `
122+ - ` truncate_on_start ` : ` true `
123+
124+ ### Truncation and Locking Behavior
125+
126+ On startup, KVP performs a stale-data check and may truncate the guest pool file.
102127
103- To record specific points within a span:
128+ - The truncate path uses file locking to avoid races between clients.
129+ - If truncation lock acquisition is unavailable (another client already holds it),
130+ initialization continues without failing.
131+ - This lock-contention case is expected in multi-client scenarios and is logged.
132+
133+ ### Instrumenting with Tracing
134+
135+ ` azure-init ` itself continues to use tracing layers (` setup_layers ` ) for KVP emission.
136+ To instrument code with tracing, use the ` #[instrument] ` attribute and ` event! ` :
104137
105138``` rust
106- use tracing :: {event, Level };
107-
108- fn configure_ssh_keys (user : & str , keys : & [String ]) {
109- event! (Level :: INFO , user = user , key_count = keys . len (), " Configuring SSH keys" );
110-
111- for (i , key ) in keys . iter (). enumerate () {
112- event! (Level :: DEBUG , user = user , key_index = i , " Processing SSH key" );
113- // Process each key
114- }
115-
116- event! (Level :: INFO , user = user , " SSH keys configured successfully" );
139+ use tracing :: {event, instrument, Level };
140+
141+ #[instrument(fields(user_id = ? user. id))]
142+ async fn provision_user (user : User ) -> Result <(), Error > {
143+ event! (Level :: INFO , " Starting user provisioning" );
144+ // Function logic
145+ event! (Level :: INFO , " User provisioning completed successfully" );
146+ Ok (())
117147}
118148```
119149
0 commit comments