Skip to main content

munin_msbuild/jsonlog/
schema.rs

1// Copyright (c) Michael Grier
2
3//! On-disk schema for `.jsonlog` files.
4//!
5//! See `D-JL-1` in the workspace `DESIGN-NOTES.md`. The schema is versioned
6//! by the top-level [`JsonlogFile::munin_jsonlog_version`] field; v1 is the
7//! only supported version today.
8
9use serde::{Deserialize, Serialize};
10
11use crate::header::BinlogHeader;
12
13/// Current schema version. Readers reject any other value.
14pub const MUNIN_JSONLOG_VERSION: u32 = 1;
15
16/// Root object of a `.jsonlog` file.
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct JsonlogFile {
19    /// Schema version. Must equal [`MUNIN_JSONLOG_VERSION`].
20    pub munin_jsonlog_version: u32,
21
22    /// Binlog header (format version and minimum reader version).
23    pub header: JsonlogHeader,
24
25    /// Deduplicated string table. Index into this array is what every
26    /// "dedup string" reference in event payloads points at.
27    pub strings: Vec<String>,
28
29    /// Name-value list table. Each entry is a list of `[key, value]` index
30    /// pairs into [`strings`](Self::strings).
31    pub name_value_lists: Vec<Vec<[u32; 2]>>,
32
33    /// Embedded archive blobs (e.g. project imports), in the order they were
34    /// encountered in the binlog stream.
35    pub archives: Vec<ArchiveB64>,
36
37    /// Event records in stream order.
38    pub events: Vec<JsonlogEvent>,
39}
40
41/// JSON-friendly mirror of [`BinlogHeader`].
42#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
43pub struct JsonlogHeader {
44    pub file_format_version: i32,
45    pub min_reader_version: i32,
46}
47
48impl From<BinlogHeader> for JsonlogHeader {
49    fn from(h: BinlogHeader) -> Self {
50        Self {
51            file_format_version: h.file_format_version,
52            min_reader_version: h.min_reader_version,
53        }
54    }
55}
56
57impl From<JsonlogHeader> for BinlogHeader {
58    fn from(h: JsonlogHeader) -> Self {
59        Self {
60            file_format_version: h.file_format_version,
61            min_reader_version: h.min_reader_version,
62        }
63    }
64}
65
66/// An embedded archive blob, base64-encoded.
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct ArchiveB64 {
69    /// Base64 (standard alphabet, with padding) of the archive bytes.
70    pub data_b64: String,
71}
72
73/// One event record.
74///
75/// `kind` is the record-kind name (matching [`crate::BinaryLogRecordKind`]
76/// debug formatting, e.g. `"BuildStarted"`). The body carries either a
77/// `decoded` JSON object (when the current decoder understands the kind) or
78/// an opaque `payload_b64` fallback for forward-compatibility.
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct JsonlogEvent {
81    /// Record kind name (e.g. `"BuildStarted"`, `"Message"`).
82    pub kind: String,
83
84    /// Byte offset of the record's kind byte in the original decompressed
85    /// stream. Diagnostic parity with [`crate::EventMeta::byte_offset`].
86    pub byte_offset: u64,
87
88    /// Event body.
89    #[serde(flatten)]
90    pub body: JsonlogEventBody,
91}
92
93/// Decoded-vs-opaque payload for a [`JsonlogEvent`].
94///
95/// Serialized as one of two shapes:
96///
97/// ```json
98/// { "decoded": { ... event-specific fields ... } }
99/// ```
100///
101/// or
102///
103/// ```json
104/// { "payload_b64": "...base64..." }
105/// ```
106#[derive(Debug, Clone, Serialize, Deserialize)]
107#[serde(rename_all = "snake_case")]
108pub enum JsonlogEventBody {
109    /// Decoded event payload, schema specific to the event kind.
110    /// Populated by JL-1.4 / JL-1.5 with typed variants; for now the
111    /// payload is carried as a raw JSON value.
112    Decoded(serde_json::Value),
113
114    /// Opaque payload — base64 (standard alphabet, with padding) of the
115    /// stored record payload bytes. Used when the current decoder does
116    /// not understand the record kind.
117    PayloadB64(String),
118}