Skip to content

Commit b87c88d

Browse files
authored
[otap-df-quiver] Scaffolding for otap-df-quiver crate (#1495)
Introduces the experimental `otap-df-quiver` crate into the main `otap-dataflow` Rust workspace. Changes include configuration scaffolding, placeholder APIs, and benchmarking stubs, but do not yet implement actual data persistence. Integration is opt-in via the new `quiver-persistence` Cargo feature, which is disabled by default to keep the experimental code path out of release builds.
1 parent eb21ce2 commit b87c88d

File tree

12 files changed

+936
-7
lines changed

12 files changed

+936
-7
lines changed

rust/experimental/quiver/README.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
11
# Quiver (Experimental) - Arrow-Based Persistence for OTAP Dataflow - README
22

3-
This crate hosts the experimental Arrow-based persistence components described
4-
in [ARCHITECTURE.md](./ARCHITECTURE.md). It provides a standalone persistence
5-
library which embed into `otap-dataflow` or other telemetry pipelines that need durable
6-
buffering of Arrow payloads.
3+
The source for the experimental crate now lives under
4+
`rust/otap-dataflow/crates/quiver`. This directory keeps the architecture notes
5+
and high level design documents, while the shared `otap-dataflow` workspace
6+
hosts the actual Rust code so the project inherits the same lint, fmt, and test
7+
infrastructure.
8+
9+
The crate currently exposes configuration scaffolding, placeholder engine APIs,
10+
and Criterion bench harness stubs. No bytes are persisted yet; every ingest
11+
call intentionally returns `QuiverError::Unimplemented` until Phase 1 wires in
12+
the WAL.
13+
14+
Integration with the `otap-df` binary is opt-in via the Cargo feature
15+
`quiver-persistence`. The feature is *disabled by default*, so release builds
16+
never pull in the experimental persistence code path unless the flag is
17+
explicitly enabled.
718

819
## Status
920

10-
**Not production-ready** This crate is being prototyped based on the specifications
11-
below (which may be updated as development proceeds). It is not yet stable or suitable
12-
for taking a dependency on.
21+
**Not production-ready** This crate is being developed based on the
22+
specifications in `ARCHITECTURE.md` (which may be updated as development
23+
proceeds). It is not yet stable or suitable for taking a dependency on.
24+
25+
## Quick start
26+
27+
```bash
28+
cd rust/otap-dataflow
29+
cargo test -p otap-df-quiver # unit tests + doc tests
30+
cargo bench -p otap-df-quiver # opt-in Criterion bench stub
31+
# Enable the downstream integration (still a stub) when needed
32+
cargo test -p otap-df --features quiver-persistence
33+
```
34+
35+
The bench currently measures the placeholder ingest path so we have a home for
36+
future perf instrumentation once real I/O lands.

rust/otap-dataflow/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ otap-df-config.workspace = true
3434
otap-df-controller.workspace = true
3535
otap-df-otap.workspace = true
3636
thiserror.workspace = true
37+
quiver = { workspace = true, optional = true }
3738
serde_json.workspace = true
3839
clap.workspace = true
3940
mimalloc-rust.workspace = true
@@ -44,12 +45,14 @@ otap-df-pdata-otlp-model = { path = "./crates/pdata/src/otlp/model"}
4445
otap-df-config = { path = "crates/config" }
4546
otap-df-controller = { path = "crates/controller" }
4647
otap-df-otap = { path = "crates/otap" }
48+
quiver = { package = "otap-df-quiver", path = "crates/quiver" }
4749

4850
ahash = "0.8.11"
4951
arrayvec = "0.7.6"
5052
arrow = "57.0"
5153
arrow-ipc = { version = "57.0", features=["zstd"] }
5254
arrow-schema = { version = "57.0" }
55+
arrow-array = { version = "57.0" }
5356
async-stream = "0.3.6"
5457
async-trait = "0.1.88"
5558
async-unsync = "0.3.0"
@@ -149,6 +152,8 @@ default = []
149152
unsafe-optimizations = ["unchecked-index", "unchecked-arithmetic"]
150153
unchecked-index = []
151154
unchecked-arithmetic = []
155+
# Experimental persistence prototype (opt-in)
156+
quiver-persistence = ["quiver"]
152157
# Experimental exporters (opt-in)
153158
experimental-exporters = ["otap-df-otap/experimental-exporters"]
154159
geneva-exporter = ["otap-df-otap/geneva-exporter"]
File renamed without changes.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[package]
2+
name = "otap-df-quiver"
3+
description = "Embeddable Arrow-based segment store"
4+
version.workspace = true
5+
edition.workspace = true
6+
authors.workspace = true
7+
repository.workspace = true
8+
license.workspace = true
9+
publish.workspace = true
10+
rust-version.workspace = true
11+
keywords = ["opentelemetry", "arrow", "persistence", "quiver"]
12+
categories = ["database", "data-structures"]
13+
14+
[lib]
15+
name = "quiver"
16+
path = "src/lib.rs"
17+
18+
[features]
19+
default = ["otap-dataflow-integrations"]
20+
otap-dataflow-integrations = []
21+
serde = ["dep:serde"]
22+
23+
[dependencies]
24+
arrow-array.workspace = true
25+
arrow-schema.workspace = true
26+
serde = { workspace = true, optional = true }
27+
thiserror.workspace = true
28+
29+
[dev-dependencies]
30+
criterion.workspace = true
31+
32+
[lints]
33+
workspace = true
34+
35+
[[bench]]
36+
name = "ingest"
37+
harness = false
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Quiver (Experimental) - Arrow-Based Persistence for OTAP Dataflow - README
2+
3+
Quiver is a standalone, embeddable Arrow-based segment store
4+
packaged as a reusable Rust crate. See `ARCHITECTURE.md`
5+
for more details.
6+
7+
The crate currently exposes configuration scaffolding, placeholder engine APIs,
8+
and Criterion bench harness stubs. No bytes are persisted yet; every ingest
9+
call intentionally returns `QuiverError::Unimplemented`.
10+
11+
Integration with the `otap-df` binary is opt-in via the Cargo feature
12+
`quiver-persistence`. The feature is *disabled by default*, so release builds
13+
never pull in the experimental persistence code path unless the flag is
14+
explicitly enabled.
15+
16+
## Status
17+
18+
**Not production-ready** This crate is being prototyped based on the
19+
specifications in `ARCHITECTURE.md` (which may be updated as development proceeds).
20+
*It is not yet complete, stable or suitable for taking a dependency on.*
21+
22+
## Quick start
23+
24+
```bash
25+
cd rust/otap-dataflow
26+
cargo test -p otap-df-quiver # unit tests + doc tests
27+
cargo bench -p otap-df-quiver # opt-in Criterion bench stub
28+
# Enable the downstream integration (still a stub) when needed
29+
cargo test -p otap-df --features quiver-persistence
30+
```
31+
32+
The bench currently measures the placeholder ingest path so we have a home for
33+
future perf instrumentation once real I/O lands.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Criterion micro-benchmark for the placeholder Quiver ingest path.
5+
6+
#![allow(missing_docs)]
7+
8+
use std::sync::Arc;
9+
use std::time::SystemTime;
10+
11+
use arrow_array::RecordBatch;
12+
use arrow_schema::{DataType, Field, Schema};
13+
use criterion::{Criterion, criterion_group, criterion_main};
14+
use quiver::config::QuiverConfig;
15+
use quiver::engine::QuiverEngine;
16+
use quiver::record_bundle::{BundleDescriptor, PayloadRef, RecordBundle, SlotDescriptor, SlotId};
17+
18+
struct DummyBundle {
19+
descriptor: BundleDescriptor,
20+
batch: RecordBatch,
21+
}
22+
23+
impl DummyBundle {
24+
fn new() -> Self {
25+
let schema = Arc::new(Schema::new(vec![Field::new(
26+
"value",
27+
DataType::Int64,
28+
false,
29+
)]));
30+
Self {
31+
descriptor: BundleDescriptor::new(vec![SlotDescriptor::new(SlotId::new(0), "Logs")]),
32+
batch: RecordBatch::new_empty(schema),
33+
}
34+
}
35+
}
36+
37+
impl RecordBundle for DummyBundle {
38+
fn descriptor(&self) -> &BundleDescriptor {
39+
&self.descriptor
40+
}
41+
42+
fn ingestion_time(&self) -> SystemTime {
43+
SystemTime::now()
44+
}
45+
46+
fn payload(&self, slot: SlotId) -> Option<PayloadRef<'_>> {
47+
if slot == SlotId::new(0) {
48+
Some(PayloadRef {
49+
schema_fingerprint: [0; 32],
50+
batch: &self.batch,
51+
})
52+
} else {
53+
None
54+
}
55+
}
56+
}
57+
58+
/// Measures the placeholder ingest path so we can wire perf tooling later.
59+
fn ingest_placeholder(c: &mut Criterion) {
60+
let engine = QuiverEngine::new(QuiverConfig::default()).expect("config valid");
61+
let bundle = DummyBundle::new();
62+
63+
let _ = c.bench_function("ingest_placeholder", |b| {
64+
b.iter(|| {
65+
let _ = engine.ingest(&bundle);
66+
});
67+
});
68+
}
69+
70+
criterion_group!(benches, ingest_placeholder);
71+
criterion_main!(benches);

0 commit comments

Comments
 (0)