Mock Collector
A mock OpenTelemetry OTLP collector server for testing applications that export telemetry data.
Features
- Multiple Signal Support: Logs, Traces, and Metrics
- Multiple Protocol Support: gRPC, HTTP/Protobuf, and HTTP/JSON
- Single Collector: One collector handles all signals - test logs, traces, and metrics together
- Fluent Assertion API: Easy-to-use builder pattern for test assertions
- Flexible Matching: Match by body/name, attributes, resource attributes, and scope attributes
- Severity Level Assertions: Assert on log severity levels (Debug, Info, Warn, Error, Fatal)
- Count-Based Assertions: Assert exact counts, minimum, or maximum number of matches
- Async-Ready: Built with Tokio for async/await compatibility
- Graceful Shutdown: Proper resource cleanup with shutdown signals
Installation
Add to your Cargo.toml (check the badge above for the latest version):
[]
= "0.2"
= { = "1", = ["macros", "rt-multi-thread"] }
Quick Start
gRPC Server
use ;
async
HTTP/JSON Server
use ;
async
HTTP/Protobuf Server
use ;
async
Testing Traces
The same server automatically supports traces! Simply use the trace assertion API:
use ;
async
Testing Metrics
The same server automatically supports metrics! Simply use the metric assertion API:
use ;
async
Testing All Signals Together
One collector handles all three signals simultaneously:
async
Assertion API
Log Assertions
// Assert at least one log matches
collector.expect_log_with_body.assert_exists;
// Assert no logs match (negative assertion)
collector.expect_log_with_body.assert_not_exists;
// Assert exact count
collector.expect_log_with_body.assert_count;
// Assert minimum
collector.expect_log_with_body.assert_at_least;
// Assert maximum
collector.expect_log_with_body.assert_at_most;
// Assert on severity levels
use SeverityNumber;
collector
.expect_log
.with_severity
.assert_count;
collector
.expect_log
.with_severity
.assert_exists;
// Combine severity with other criteria
collector
.expect_log_with_body
.with_severity
.with_resource_attributes
.assert_exists;
Trace Assertions
Span assertions use the same fluent API:
// Assert at least one span matches
collector.expect_span_with_name.assert_exists;
// Assert no spans match (negative assertion)
collector.expect_span_with_name.assert_not_exists;
// Assert exact count
collector.expect_span_with_name.assert_count;
// Assert minimum
collector.expect_span_with_name.assert_at_least;
// Assert maximum
collector.expect_span_with_name.assert_at_most;
Metric Assertions
Metric assertions use the same fluent API:
// Assert at least one metric matches
collector.expect_metric_with_name.assert_exists;
// Assert no metrics match (negative assertion)
collector.expect_metric_with_name.assert_not_exists;
// Assert exact count
collector.expect_metric_with_name.assert_count;
// Assert minimum
collector.expect_metric_with_name.assert_at_least;
// Assert maximum
collector.expect_metric_with_name.assert_at_most;
Histogram and Summary Assertions
For histogram and summary metrics, use type-specific assertion builders:
// Histogram assertions
collector
.expect_histogram
.with_attributes
.with_count_gte
.with_sum_gte
.with_bucket_count_gte // bucket index 2 has >= 50 observations
.assert_exists;
// Summary assertions with quantile checks
collector
.expect_summary
.with_count_gte
.with_quantile_lte // median <= 100ms
.with_quantile_lte // p99 <= 500ms
.assert_exists;
// Exponential histogram assertions
collector
.expect_exponential_histogram
.with_count_gte
.with_zero_count_lte
.with_scale_eq
.assert_exists;
Matching Criteria
All three signals (logs, spans, and metrics) support matching on attributes, resource attributes, and scope attributes:
// Logs
collector
.expect_log_with_body
.with_attributes
.with_resource_attributes
.with_scope_attributes
.assert_exists;
// Spans (same API!)
collector
.expect_span_with_name
.with_attributes
.with_resource_attributes
.with_scope_attributes
.assert_exists;
// Metrics (same API!)
collector
.expect_metric_with_name
.with_attributes
.with_resource_attributes
.with_scope_attributes
.assert_exists;
Inspection Methods
// Get counts
let log_count = collector.log_count;
let span_count = collector.span_count;
let metric_count = collector.metric_count;
// Get matching items
let log_assertion = collector.expect_log_with_body;
let matching_logs = log_assertion.get_all;
let log_match_count = log_assertion.count;
let span_assertion = collector.expect_span_with_name;
let matching_spans = span_assertion.get_all;
let span_match_count = span_assertion.count;
let metric_assertion = collector.expect_metric_with_name;
let matching_metrics = metric_assertion.get_all;
let metric_match_count = metric_assertion.count;
// Clear all collected data (logs, spans, AND metrics)
collector.clear;
// Debug dump all data
println!;
Sharing a Collector
You can share a collector between multiple servers or inspect logs without starting a server:
use Arc;
use RwLock;
use ;
let collector = new;
// Start multiple servers with the same collector
let grpc_server = with_collector.start.await?;
let http_server = with_collector.start.await?;
// Access the collector directly
let log_count = collector.read.await.log_count;
Examples
The examples/ directory contains complete working examples:
-
basic_grpc.rs - Getting started with gRPC
- Starting a server and sending logs
- Using
wait_for_*methods for async data - Basic assertion patterns and graceful shutdown
-
http_protocols.rs - HTTP/JSON and HTTP/Protobuf
- Using HTTP endpoints (
/v1/logs,/v1/traces,/v1/metrics) - Content-Type handling for JSON vs Protobuf
- Using HTTP endpoints (
-
metrics.rs - Metrics collection
- Sending metrics via gRPC
- Asserting on metric names and attributes
-
assertion_patterns.rs - Comprehensive assertion API
- Count assertions (
assert_count,assert_at_least,assert_at_most) - Negative assertions (
assert_not_exists) - Severity level filtering
- Using
dump()for debugging - Event assertions on spans
- Count assertions (
Run examples with:
# or: cargo run --example basic_grpc
Comparison with fake-opentelemetry-collector
This library was inspired by fake-opentelemetry-collector but adds:
- Full Signal Support: Test logs, traces, and metrics in the same collector
- HTTP Protocol Support: Both JSON and Protobuf over HTTP, not just gRPC
- Fluent Assertion API: Builder pattern for more readable tests
- Count Assertions:
assert_count(),assert_at_least(),assert_at_most() - Negative Assertions:
assert_not_exists()for verifying data doesn't exist - Scope Attributes: Support for asserting on scope-level attributes
- Better Error Messages: Detailed panic messages showing what was expected vs what was found
- Arc-Optimised Storage: Efficient memory usage for resource/scope attributes
- Builder Pattern: Simple defaults with
MockServer::builder().start()or full control
Development
A Nix flake provides a development shell with all required tools:
Common tasks are available via just:
License
Licensed under the MIT license.
Contributing
Contributions are welcome! Please feel free to open issues or submit pull requests.