Skip to content

Commit ecda0f9

Browse files
committed
feat(core): add support for dynamic tracing config
1 parent 5b52fc2 commit ecda0f9

File tree

19 files changed

+472
-56
lines changed

19 files changed

+472
-56
lines changed

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,16 +280,16 @@ path = "packages/common/error/core"
280280
[workspace.dependencies.rivet-error-macros]
281281
path = "packages/common/error/macros"
282282

283-
[workspace.dependencies.gas]
284-
package = "gasoline"
285-
path = "packages/common/gasoline/core"
286-
287283
[workspace.dependencies.gasoline]
288284
path = "packages/common/gasoline/core"
289285

290286
[workspace.dependencies.gasoline-macros]
291287
path = "packages/common/gasoline/macros"
292288

289+
[workspace.dependencies.gas]
290+
package = "gasoline"
291+
path = "packages/common/gasoline/core"
292+
293293
[workspace.dependencies.rivet-logs]
294294
path = "packages/common/logs"
295295

@@ -375,6 +375,9 @@ path = "packages/services/epoxy"
375375
[workspace.dependencies.internal]
376376
path = "packages/services/internal"
377377

378+
[workspace.dependencies.rivet-tracing-reconfigure]
379+
path = "packages/services/tracing-reconfigure"
380+
378381
[workspace.dependencies.namespace]
379382
path = "packages/services/namespace"
380383

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Dynamic Tracing Configuration
2+
3+
Dynamically reconfigure log levels and OpenTelemetry sampling for all running services without restart.
4+
5+
## Log Filter Configuration
6+
7+
Control which log messages are displayed by setting filter directives (similar to `RUST_LOG`).
8+
9+
**Set log filter to debug**
10+
11+
```bash
12+
rivet-engine tracing config -f debug
13+
14+
# Or via HTTP API:
15+
curl -X PUT http://localhost:6421/debug/tracing/config \
16+
-H "Content-Type: application/json" \
17+
-d '{"filter":"debug"}'
18+
```
19+
20+
**Debug a specific package**
21+
22+
```bash
23+
rivet-engine tracing config -f "debug,rivet_api_peer=trace"
24+
25+
# Or via HTTP API:
26+
curl -X PUT http://localhost:6421/debug/tracing/config \
27+
-H "Content-Type: application/json" \
28+
-d '{"filter":"debug,rivet_api_peer=trace"}'
29+
```
30+
31+
**Reset log filter to defaults**
32+
33+
```bash
34+
rivet-engine tracing config -f ""
35+
36+
# Or via HTTP API:
37+
curl -X PUT http://localhost:6421/debug/tracing/config \
38+
-H "Content-Type: application/json" \
39+
-d '{"filter":null}'
40+
```
41+
42+
## OpenTelemetry Sampler Ratio
43+
44+
Control what percentage of traces are sampled and sent to the OpenTelemetry collector.
45+
46+
**Set sampler ratio to 10%**
47+
48+
```bash
49+
rivet-engine tracing config -s 0.1
50+
51+
# Or via HTTP API:
52+
curl -X PUT http://localhost:6421/debug/tracing/config \
53+
-H "Content-Type: application/json" \
54+
-d '{"sampler_ratio":0.1}'
55+
```
56+
57+
**Set sampler ratio to 100% (capture all traces)**
58+
59+
```bash
60+
rivet-engine tracing config -s 1.0
61+
62+
# Or via HTTP API:
63+
curl -X PUT http://localhost:6421/debug/tracing/config \
64+
-H "Content-Type: application/json" \
65+
-d '{"sampler_ratio":1.0}'
66+
```
67+
68+
**Reset sampler ratio to default**
69+
70+
```bash
71+
rivet-engine tracing config -s 0.001
72+
73+
# Or via HTTP API:
74+
curl -X PUT http://localhost:6421/debug/tracing/config \
75+
-H "Content-Type: application/json" \
76+
-d '{"sampler_ratio":null}'
77+
```
78+

out/openapi.json

Lines changed: 0 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/common/metrics/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ mod buckets;
55
pub use buckets::*;
66
pub use opentelemetry as otel;
77
pub use opentelemetry::KeyValue;
8-
pub use providers::{OtelProviderGuard, init_otel_providers};
8+
pub use providers::{OtelProviderGuard, init_otel_providers, set_sampler_ratio};

packages/common/metrics/src/providers.rs

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Based off of https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/examples/opentelemetry-otlp.rs
22
// Based off of https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/examples/opentelemetry-otlp.rs
33

4+
use std::sync::{Arc, RwLock, OnceLock};
45
use opentelemetry::{KeyValue, global};
6+
use opentelemetry::trace::{SamplingResult, SpanKind};
57
use opentelemetry_otlp::WithExportConfig;
68
use opentelemetry_sdk::{
79
Resource,
@@ -11,6 +13,65 @@ use opentelemetry_sdk::{
1113
};
1214
use opentelemetry_semantic_conventions::{SCHEMA_URL, attribute::SERVICE_VERSION};
1315

16+
/// Dynamic sampler that can be updated at runtime
17+
#[derive(Clone, Debug)]
18+
struct DynamicSampler {
19+
ratio: Arc<RwLock<f64>>,
20+
}
21+
22+
impl DynamicSampler {
23+
fn new(ratio: f64) -> Self {
24+
Self {
25+
ratio: Arc::new(RwLock::new(ratio)),
26+
}
27+
}
28+
29+
fn set_ratio(&self, ratio: f64) {
30+
if let Ok(mut r) = self.ratio.write() {
31+
*r = ratio;
32+
}
33+
}
34+
}
35+
36+
impl opentelemetry_sdk::trace::ShouldSample for DynamicSampler {
37+
fn should_sample(
38+
&self,
39+
parent_context: Option<&opentelemetry::Context>,
40+
trace_id: opentelemetry::trace::TraceId,
41+
_name: &str,
42+
_span_kind: &SpanKind,
43+
_attributes: &[KeyValue],
44+
_links: &[opentelemetry::trace::Link],
45+
) -> SamplingResult {
46+
let ratio = self.ratio.read().ok().map(|r| *r).unwrap_or(0.001);
47+
48+
// Use TraceIdRatioBased sampling logic
49+
let sampler = Sampler::TraceIdRatioBased(ratio);
50+
sampler.should_sample(
51+
parent_context,
52+
trace_id,
53+
_name,
54+
_span_kind,
55+
_attributes,
56+
_links,
57+
)
58+
}
59+
}
60+
61+
static SAMPLER: OnceLock<DynamicSampler> = OnceLock::new();
62+
63+
/// Update the sampler ratio at runtime
64+
pub fn set_sampler_ratio(ratio: f64) -> anyhow::Result<()> {
65+
let sampler = SAMPLER
66+
.get()
67+
.ok_or_else(|| anyhow::anyhow!("sampler not initialized"))?;
68+
69+
sampler.set_ratio(ratio);
70+
tracing::info!(?ratio, "updated sampler ratio");
71+
72+
Ok(())
73+
}
74+
1475
fn resource() -> Resource {
1576
let mut resource = Resource::builder()
1677
.with_service_name(rivet_env::service_name())
@@ -48,14 +109,20 @@ fn init_tracer_provider() -> SdkTracerProvider {
48109
.build()
49110
.unwrap();
50111

112+
// Create dynamic sampler with initial ratio from env
113+
let initial_ratio = std::env::var("RIVET_OTEL_SAMPLER_RATIO")
114+
.ok()
115+
.and_then(|s| s.parse::<f64>().ok())
116+
.unwrap_or(0.001);
117+
118+
let dynamic_sampler = DynamicSampler::new(initial_ratio);
119+
120+
// Store sampler globally for later updates
121+
let _ = SAMPLER.set(dynamic_sampler.clone());
122+
51123
SdkTracerProvider::builder()
52-
// Customize sampling strategy
53-
.with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased(
54-
std::env::var("RIVET_OTEL_SAMPLER_RATIO")
55-
.ok()
56-
.and_then(|s| s.parse::<f64>().ok())
57-
.unwrap_or(0.001),
58-
))))
124+
// Customize sampling strategy with parent-based sampling using our dynamic sampler
125+
.with_sampler(Sampler::ParentBased(Box::new(dynamic_sampler)))
59126
// If export trace to AWS X-Ray, you can use XrayIdGenerator
60127
.with_id_generator(RandomIdGenerator::default())
61128
.with_resource(resource())

packages/common/runtime/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ license.workspace = true
66
edition.workspace = true
77

88
[dependencies]
9+
anyhow.workspace = true
910
console-subscriber.workspace = true
1011
lazy_static.workspace = true
1112
rivet-metrics.workspace = true

packages/common/runtime/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use tokio::sync::{Notify, OnceCell};
55
mod metrics;
66
mod traces;
77

8+
pub use traces::reload_log_filter;
9+
810
static SHUTDOWN: OnceCell<Arc<Notify>> = OnceCell::const_new();
911

1012
/// Returns `None` if the runtime was shut down manually.

0 commit comments

Comments
 (0)