Skip to content

Commit e2b6bac

Browse files
committed
Add the ability to generate limited FoundationDB logs
This commit adds a limited ability to generate FoundationDB logs. There's more variants to be added and any fields in the existing variants that have an internal complex structure have been dropped. Signed-off-by: Brian L. Troutwine <brian@troutwine.us>
1 parent 5bc0b2b commit e2b6bac

File tree

4 files changed

+92
-13
lines changed

4 files changed

+92
-13
lines changed

src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub struct Config {
2323
/// This variant controls what kind of line text is created by this program.
2424
#[derive(Debug, Deserialize, Copy, Clone)]
2525
pub enum Variant {
26+
/// Generates a limited subset of FoundationDB logs
27+
FoundationDb,
2628
/// Generates a static, user supplied data
2729
Static,
2830
/// Generates a line of printable ascii characters

src/file.rs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rand::RngCore;
99
use rand::{thread_rng, Rng};
1010
use rayon::prelude::*;
1111
use std::convert::TryInto;
12-
use std::num::{NonZeroU32, NonZeroU64};
12+
use std::num::NonZeroU32;
1313
use std::path::PathBuf;
1414
use tokio::fs;
1515
use tokio::io::{AsyncWriteExt, BufWriter};
@@ -57,8 +57,8 @@ const BLOCK_BYTE_SIZES: [usize; 6] = [
5757
32_000_000,
5858
];
5959

60-
fn total_newlines(input: &[u8]) -> NonZeroU64 {
61-
NonZeroU64::new(bytecount::count(input, b'\n') as u64).unwrap()
60+
fn total_newlines(input: &[u8]) -> u64 {
61+
bytecount::count(input, b'\n') as u64
6262
}
6363

6464
fn chunk_bytes<R>(rng: &mut R, input: usize, bytes_per_second: usize) -> Vec<usize>
@@ -79,11 +79,18 @@ where
7979
chunks
8080
}
8181

82+
#[derive(Debug)]
83+
struct Block {
84+
total_bytes: NonZeroU32,
85+
lines: u64,
86+
bytes: Vec<u8>,
87+
}
88+
8289
fn construct_block(
8390
block_bytes: usize,
8491
variant: Variant,
8592
static_path: Option<&PathBuf>,
86-
) -> Result<(NonZeroU32, NonZeroU64, Vec<u8>), Error> {
93+
) -> Result<Block, Error> {
8794
let mut rng = thread_rng();
8895
let mut bytes: Vec<u8> = vec![0; block_bytes];
8996
rng.fill_bytes(&mut bytes);
@@ -100,15 +107,22 @@ fn construct_block(
100107
Variant::Json => {
101108
payload::Json::arbitrary_take_rest(unstructured)?.to_bytes(&mut block)?;
102109
}
110+
Variant::FoundationDb => {
111+
payload::FoundationDb::arbitrary_take_rest(unstructured)?.to_bytes(&mut block)?;
112+
}
103113
}
104114
block.shrink_to_fit();
105115
if block.is_empty() {
106116
return Err(Error::BlockEmpty);
107117
}
108118

119+
let total_bytes = NonZeroU32::new(block.len().try_into().unwrap()).unwrap();
109120
let newlines = total_newlines(&block);
110-
let nz_bytes = NonZeroU32::new(block.len().try_into().unwrap()).unwrap();
111-
Ok((nz_bytes, newlines, block))
121+
Ok(Block {
122+
total_bytes,
123+
lines: newlines,
124+
bytes: block,
125+
})
112126
}
113127

114128
#[allow(clippy::ptr_arg)]
@@ -117,7 +131,7 @@ fn construct_block_cache<R>(
117131
mut rng: R,
118132
target: &LogTarget,
119133
labels: &Vec<(String, String)>,
120-
) -> Vec<(NonZeroU32, u64, Vec<u8>)>
134+
) -> Vec<Block>
121135
where
122136
R: Rng + Sized,
123137
{
@@ -128,11 +142,10 @@ where
128142
bytes_per_second,
129143
);
130144

131-
let block_cache: Vec<(NonZeroU32, u64, Vec<u8>)> = block_chunks
145+
let block_cache: Vec<Block> = block_chunks
132146
.into_par_iter()
133147
.map(|block_size| construct_block(block_size, target.variant, target.static_path.as_ref()))
134148
.map(std::result::Result::unwrap)
135-
.map(|(nzu32, nzu64, bytes)| (nzu32, nzu64.get(), bytes))
136149
.collect();
137150
gauge!("block_construction_complete", 1.0, labels);
138151
block_cache
@@ -147,7 +160,7 @@ pub struct Log {
147160
maximum_bytes_per_file: NonZeroU32,
148161
bytes_per_second: NonZeroU32,
149162
rate_limiter: RateLimiter<direct::NotKeyed, state::InMemoryState, clock::QuantaClock>,
150-
block_cache: Vec<(NonZeroU32, u64, Vec<u8>)>,
163+
block_cache: Vec<Block>,
151164
}
152165

153166
impl Log {
@@ -217,16 +230,20 @@ impl Log {
217230
.await?,
218231
);
219232

220-
for (total_bytes, total_newlines, block) in self.block_cache.iter().cycle() {
221-
self.rate_limiter.until_n_ready(*total_bytes).await?;
233+
for blk in self.block_cache.iter().cycle() {
234+
let total_bytes = blk.total_bytes;
235+
let total_newlines = blk.lines;
236+
let block = &blk.bytes;
237+
238+
self.rate_limiter.until_n_ready(total_bytes).await?;
222239

223240
{
224241
fp.write_all(block).await?;
225242
// block.len() and total_bytes are the same numeric value but we
226243
// avoid needing to get a plain value from a non-zero by calling
227244
// len here.
228245
counter!("bytes_written", block.len() as u64, &labels);
229-
counter!("lines_written", *total_newlines, &labels);
246+
counter!("lines_written", total_newlines, &labels);
230247

231248
bytes_written += block.len() as u64;
232249
gauge!("current_target_size_bytes", bytes_written as f64, &labels);

src/payload.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use std::io::{self, Write};
22

33
mod ascii;
4+
mod foundationdb;
45
mod json;
56
mod statik;
67

78
pub use ascii::Ascii;
9+
pub use foundationdb::FoundationDb;
810
pub use json::Json;
911
pub use statik::Static;
1012

src/payload/foundationdb.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use crate::payload::{Error, Serialize};
2+
use arbitrary::{self, Arbitrary};
3+
use std::io::Write;
4+
5+
#[derive(Arbitrary, Debug, serde::Serialize)]
6+
#[serde(tag = "type")]
7+
#[serde(rename_all = "PascalCase")]
8+
enum Member {
9+
// Many keys are missing, those with complex internal structure especially.
10+
SlowTask {
11+
severity: u8,
12+
m_clocks: u32,
13+
},
14+
TransactionMetrics {
15+
severity: u8,
16+
time: f32,
17+
id: u64,
18+
elapsed: f32,
19+
internal: u8,
20+
mean_latency: u16,
21+
median_latency: u16,
22+
max_latency: u16,
23+
latency90: u32,
24+
latency98: u32,
25+
mean_row_read_latency: f32,
26+
median_row_read_latency: f32,
27+
max_row_read_latency: f32,
28+
mean_commit_latency: u32,
29+
median_commit_latency: u32,
30+
max_commit_latency: u32,
31+
mean_grv_latency: f32,
32+
max_grv_latency: f32,
33+
mean_mutations_per_commit: u32,
34+
median_mutations_per_commit: u32,
35+
max_mutations_per_commit: u32,
36+
mean_bytes_per_commit: u32,
37+
median_bytes_per_commit: u32,
38+
max_bytes_per_commit: u32,
39+
},
40+
}
41+
42+
#[derive(Arbitrary, Debug)]
43+
pub struct FoundationDb {
44+
members: Vec<Member>,
45+
}
46+
47+
impl Serialize for FoundationDb {
48+
fn to_bytes<W>(&self, writer: &mut W) -> Result<(), Error>
49+
where
50+
W: Write,
51+
{
52+
for member in &self.members {
53+
serde_json::to_writer(&mut *writer, member)?;
54+
writeln!(writer)?;
55+
}
56+
Ok(())
57+
}
58+
}

0 commit comments

Comments
 (0)