Skip to content

Commit 4a170d7

Browse files
committed
[ereporter] data loss as a first class citizen
1 parent a6dd46d commit 4a170d7

File tree

3 files changed

+115
-33
lines changed

3 files changed

+115
-33
lines changed

ereporter/api/src/lib.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub trait EreporterApi {
2525
async fn ereports_list(
2626
request_context: RequestContext<Self::Context>,
2727
query: Query<PaginationParams<EmptyScanParams, Generation>>,
28-
) -> Result<HttpResponseOk<ResultsPage<Ereport>>, HttpError>;
28+
) -> Result<HttpResponseOk<ResultsPage<Entry>>, HttpError>;
2929

3030
/// Informs the reporter that it may freely discard ereports with sequence
3131
/// numbers less than or equal to `seq`.
@@ -46,14 +46,42 @@ pub struct SeqPathParam {
4646
pub seq: Generation,
4747
}
4848

49-
/// An error report.
49+
/// An entry in the ereport batch returned by a reporter.
5050
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)]
51-
pub struct Ereport {
51+
pub struct Entry {
5252
/// UUID of the entity that generated this ereport.
5353
pub reporter_id: Uuid,
5454
/// The ereport's sequence number, unique with regards to ereports generated
5555
/// by the entity with the `reporter_id`.
5656
pub seq: Generation,
57+
58+
pub value: EntryKind,
59+
}
60+
61+
/// Kinds of entry in a batch.
62+
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)]
63+
#[serde(rename_all = "snake_case")]
64+
pub enum EntryKind {
65+
/// An ereport.
66+
Ereport(Ereport),
67+
/// Ereports may have been lost.
68+
DataLoss {
69+
/// The number of ereports that were discarded, if it is known.
70+
///
71+
/// If ereports are dropped because a buffer has reached its capacity,
72+
/// the reporter is strongly encouraged to attempt to count the number
73+
/// of ereports lost. In other cases, such as a reporter crashing and
74+
/// restarting, the reporter may not be capable of determining the
75+
/// number of ereports that were lost, or even *if* data loss actually
76+
/// occurred. Therefore, a `None` here indicates *possible* data loss,
77+
/// while a `Some(u32)` indicates *known* data loss.
78+
dropped: Option<u32>,
79+
},
80+
}
81+
82+
/// An error report.
83+
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)]
84+
pub struct Ereport {
5785
/// A string indicating the kind of ereport.
5886
///
5987
/// This may be used by diagnosis engines as an indication of what `facts`

ereporter/src/buffer.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ pub(crate) enum ServerReq {
1717
List {
1818
start_seq: Option<Generation>,
1919
limit: usize,
20-
tx: oneshot::Sender<Vec<ereporter_api::Ereport>>,
20+
tx: oneshot::Sender<Vec<ereporter_api::Entry>>,
2121
},
2222
}
2323

2424
pub(crate) struct Buffer {
2525
pub(crate) seq: Generation,
26-
pub(crate) buf: VecDeque<ereporter_api::Ereport>,
26+
pub(crate) buf: VecDeque<ereporter_api::Entry>,
2727
pub(crate) log: slog::Logger,
2828
pub(crate) id: Uuid,
2929
pub(crate) ereports: mpsc::Receiver<EreportData>,
@@ -111,12 +111,14 @@ impl Buffer {
111111
fn push_ereport(&mut self, ereport: EreportData) {
112112
let EreportData { facts, class, time_created } = ereport;
113113
let seq = self.seq;
114-
self.buf.push_back(ereporter_api::Ereport {
115-
facts,
116-
class,
117-
time_created,
118-
reporter_id: self.id,
114+
self.buf.push_back(ereporter_api::Entry {
119115
seq,
116+
reporter_id: self.id,
117+
value: ereporter_api::EntryKind::Ereport(ereporter_api::Ereport {
118+
facts,
119+
class,
120+
time_created,
121+
}),
120122
});
121123
self.seq = self.seq.next();
122124
slog::trace!(

openapi/ereporter.json

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"content": {
4343
"application/json": {
4444
"schema": {
45-
"$ref": "#/components/schemas/EreportResultsPage"
45+
"$ref": "#/components/schemas/EntryResultsPage"
4646
}
4747
}
4848
}
@@ -90,21 +90,10 @@
9090
},
9191
"components": {
9292
"schemas": {
93-
"Ereport": {
94-
"description": "An error report.",
93+
"Entry": {
94+
"description": "An entry in the ereport batch returned by a reporter.",
9595
"type": "object",
9696
"properties": {
97-
"class": {
98-
"description": "A string indicating the kind of ereport.\n\nThis may be used by diagnosis engines as an indication of what `facts` to expect.",
99-
"type": "string"
100-
},
101-
"facts": {
102-
"description": "The set of facts (key-value pairs) associated with this ereport.",
103-
"type": "object",
104-
"additionalProperties": {
105-
"type": "string"
106-
}
107-
},
10897
"reporter_id": {
10998
"description": "UUID of the entity that generated this ereport.",
11099
"type": "string",
@@ -118,29 +107,65 @@
118107
}
119108
]
120109
},
121-
"time_created": {
122-
"description": "The UTC timestamp when this ereport was observed, as determined by the reporter.",
123-
"type": "string",
124-
"format": "date-time"
110+
"value": {
111+
"$ref": "#/components/schemas/EntryKind"
125112
}
126113
},
127114
"required": [
128-
"class",
129-
"facts",
130115
"reporter_id",
131116
"seq",
132-
"time_created"
117+
"value"
118+
]
119+
},
120+
"EntryKind": {
121+
"description": "Kinds of entry in a batch.",
122+
"oneOf": [
123+
{
124+
"description": "An ereport.",
125+
"type": "object",
126+
"properties": {
127+
"ereport": {
128+
"$ref": "#/components/schemas/Ereport"
129+
}
130+
},
131+
"required": [
132+
"ereport"
133+
],
134+
"additionalProperties": false
135+
},
136+
{
137+
"description": "Ereports may have been lost.",
138+
"type": "object",
139+
"properties": {
140+
"data_loss": {
141+
"type": "object",
142+
"properties": {
143+
"dropped": {
144+
"nullable": true,
145+
"description": "The number of ereports that were discarded, if it is known.\n\nIf ereports are dropped because a buffer has reached its capacity, the reporter is strongly encouraged to attempt to count the number of ereports lost. In other cases, such as a reporter crashing and restarting, the reporter may not be capable of determining the number of ereports that were lost, or even *if* data loss actually occurred. Therefore, a `None` here indicates *possible* data loss, while a `Some(u32)` indicates *known* data loss.",
146+
"type": "integer",
147+
"format": "uint32",
148+
"minimum": 0
149+
}
150+
}
151+
}
152+
},
153+
"required": [
154+
"data_loss"
155+
],
156+
"additionalProperties": false
157+
}
133158
]
134159
},
135-
"EreportResultsPage": {
160+
"EntryResultsPage": {
136161
"description": "A single page of results",
137162
"type": "object",
138163
"properties": {
139164
"items": {
140165
"description": "list of items on this page of results",
141166
"type": "array",
142167
"items": {
143-
"$ref": "#/components/schemas/Ereport"
168+
"$ref": "#/components/schemas/Entry"
144169
}
145170
},
146171
"next_page": {
@@ -153,6 +178,33 @@
153178
"items"
154179
]
155180
},
181+
"Ereport": {
182+
"description": "An error report.",
183+
"type": "object",
184+
"properties": {
185+
"class": {
186+
"description": "A string indicating the kind of ereport.\n\nThis may be used by diagnosis engines as an indication of what `facts` to expect.",
187+
"type": "string"
188+
},
189+
"facts": {
190+
"description": "The set of facts (key-value pairs) associated with this ereport.",
191+
"type": "object",
192+
"additionalProperties": {
193+
"type": "string"
194+
}
195+
},
196+
"time_created": {
197+
"description": "The UTC timestamp when this ereport was observed, as determined by the reporter.",
198+
"type": "string",
199+
"format": "date-time"
200+
}
201+
},
202+
"required": [
203+
"class",
204+
"facts",
205+
"time_created"
206+
]
207+
},
156208
"Error": {
157209
"description": "Error information from a response.",
158210
"type": "object",

0 commit comments

Comments
 (0)