Skip to content

Commit 5528da4

Browse files
committed
refactor(kvp): replace tracing-layer wrapper with direct Kvp client API
1 parent 6002c6b commit 5528da4

3 files changed

Lines changed: 297 additions & 140 deletions

File tree

doc/libazurekvp.md

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)