mock_collector/lib.rs
1//! A mock OpenTelemetry OTLP collector server for testing.
2//!
3//! This library provides a mock collector that can receive OTLP logs, traces, and metrics over gRPC, HTTP/JSON, or HTTP/Protobuf,
4//! and provides a fluent assertion API for verifying the received telemetry data in tests.
5//!
6//! # Features
7//!
8//! - **Multiple Signal Support**: Logs, Traces, and Metrics
9//! - **Single Collector**: One collector handles all signals - test logs, traces, and metrics together
10//! - **Multiple Protocol Support**: gRPC, HTTP/Protobuf, and HTTP/JSON
11//! - **Fluent Assertion API**: Easy-to-use builder pattern for test assertions
12//! - **Async Waiting**: Wait for telemetry to arrive with timeout support
13//! - **Severity Level Assertions**: Assert on log severity levels (Debug, Info, Warn, Error, Fatal)
14//! - **Count-Based Assertions**: Assert exact counts, minimums, or maximums
15//! - **Negative Assertions**: Verify logs/spans/metrics don't exist
16//! - **Async-Ready**: Built with Tokio for async/await compatibility
17//! - **Graceful Shutdown**: Proper resource cleanup
18//!
19//! # Quick Start
20//!
21//! ```no_run
22//! use mock_collector::{MockServer, Protocol};
23//!
24//! #[tokio::main]
25//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
26//! // Start a server (supports logs, traces, and metrics)
27//! let server = MockServer::builder().start().await?;
28//!
29//! // Your application exports logs, traces, and metrics here...
30//!
31//! // Assert on collected data
32//! server.with_collector(|collector| {
33//! // Logs
34//! collector
35//! .expect_log_with_body("Application started")
36//! .with_resource_attributes([("service.name", "my-service")])
37//! .assert_exists();
38//!
39//! // Logs with severity
40//! use mock_collector::SeverityNumber;
41//! collector
42//! .expect_log()
43//! .with_severity(SeverityNumber::Error)
44//! .assert_not_exists();
45//!
46//! // Traces
47//! collector
48//! .expect_span_with_name("Initialize")
49//! .with_resource_attributes([("service.name", "my-service")])
50//! .assert_exists();
51//!
52//! // Metrics
53//! collector
54//! .expect_metric_with_name("requests_total")
55//! .with_resource_attributes([("service.name", "my-service")])
56//! .assert_exists();
57//! }).await;
58//!
59//! // Graceful shutdown
60//! server.shutdown().await?;
61//! Ok(())
62//! }
63//! ```
64//!
65//! # Async Waiting
66//!
67//! When testing async telemetry pipelines, signals often arrive asynchronously after the
68//! operation that generates them completes. The library provides waiting methods to handle
69//! this pattern:
70//!
71//! ```no_run
72//! use mock_collector::MockServer;
73//! use std::time::Duration;
74//!
75//! # #[tokio::main]
76//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
77//! let server = MockServer::builder().start().await?;
78//!
79//! // Trigger async telemetry export...
80//!
81//! // Wait for telemetry to arrive before asserting
82//! server.wait_for_spans(1, Duration::from_secs(5)).await?;
83//! server.wait_for_logs(2, Duration::from_secs(5)).await?;
84//! server.wait_for_metrics(3, Duration::from_secs(5)).await?;
85//!
86//! // Or use a custom predicate for complex conditions
87//! server.wait_until(
88//! |c| c.expect_span_with_name("http.request")
89//! .with_attributes([("http.status_code", 200)])
90//! .count() >= 1,
91//! Duration::from_secs(5),
92//! ).await?;
93//!
94//! // Now safe to run assertions
95//! server.with_collector(|collector| {
96//! collector.expect_span_with_name("http.request").assert_exists();
97//! }).await;
98//! # Ok(())
99//! # }
100//! ```
101//!
102//! # Assertion API
103//!
104//! The library provides assertion methods for logs, traces, and metrics:
105//!
106//! ## Log Assertions
107//!
108//! - [`LogAssertion::assert_exists`]: Assert at least one log matches
109//! - [`LogAssertion::assert_not_exists`]: Assert no logs match
110//! - [`LogAssertion::assert_count`]: Assert exact number of matches
111//! - [`LogAssertion::assert_at_least`]: Assert minimum matches
112//! - [`LogAssertion::assert_at_most`]: Assert maximum matches
113//!
114//! ## Trace Assertions
115//!
116//! - [`SpanAssertion::assert_exists`]: Assert at least one span matches
117//! - [`SpanAssertion::assert_not_exists`]: Assert no spans match
118//! - [`SpanAssertion::assert_count`]: Assert exact number of matches
119//! - [`SpanAssertion::assert_at_least`]: Assert minimum matches
120//! - [`SpanAssertion::assert_at_most`]: Assert maximum matches
121//!
122//! ## Metric Assertions
123//!
124//! - [`MetricAssertion::assert_exists`]: Assert at least one metric matches
125//! - [`MetricAssertion::assert_not_exists`]: Assert no metrics match
126//! - [`MetricAssertion::assert_count`]: Assert exact number of matches
127//! - [`MetricAssertion::assert_at_least`]: Assert minimum matches
128//! - [`MetricAssertion::assert_at_most`]: Assert maximum matches
129//!
130//! ## Histogram, ExponentialHistogram, and Summary Assertions
131//!
132//! For type-specific metric assertions, use the dedicated builders:
133//!
134//! - [`HistogramAssertion`]: Assert on histogram count, sum, min, max, and bucket counts
135//! - [`ExponentialHistogramAssertion`]: Assert on exponential histogram with zero_count and scale
136//! - [`SummaryAssertion`]: Assert on summary count, sum, and quantile values
137//!
138//! ```no_run
139//! # use mock_collector::MockCollector;
140//! # let collector = MockCollector::new();
141//! // Histogram with value assertions
142//! collector
143//! .expect_histogram("http_request_duration")
144//! .with_count_gte(100)
145//! .with_sum_gte(5000.0)
146//! .assert_exists();
147//!
148//! // Summary with quantile assertions
149//! collector
150//! .expect_summary("response_time")
151//! .with_quantile_lte(0.99, 500.0) // p99 <= 500ms
152//! .assert_exists();
153//! ```
154//!
155//! ## Waiting Methods
156//!
157//! - [`ServerHandle::wait_until`]: Wait for a custom predicate to return true
158//! - [`ServerHandle::wait_for_spans`]: Wait for at least N spans to arrive
159//! - [`ServerHandle::wait_for_logs`]: Wait for at least N logs to arrive
160//! - [`ServerHandle::wait_for_metrics`]: Wait for at least N metrics to arrive
161//!
162//! # Examples
163//!
164//! See the [examples directory](https://github.com/djvcom/mock-collector/tree/main/examples)
165//! for complete working examples.
166
167mod collector;
168mod error;
169mod server;
170
171pub use collector::{
172 ExponentialHistogramAssertion, HistogramAssertion, LogAssertion, MetricAssertion,
173 MockCollector, SpanAssertion, SummaryAssertion, TestLogRecord, TestMetric, TestSpan,
174};
175pub use error::MockServerError;
176pub use opentelemetry_otlp::Protocol;
177pub use opentelemetry_proto::tonic::logs::v1::SeverityNumber;
178pub use server::{MockServer, MockServerBuilder, ServerHandle};