Sampler API ​
The Sampler struct controls log throughput by selectively processing records.
Quick Reference: Method Aliases ​
| Full Method | Alias(es) | Description |
|---|---|---|
init() | create() | Initialize sampler |
deinit() | destroy() | Deinitialize sampler |
setAcceptCallback() | onAccept() | Set accept callback |
setRejectCallback() | onReject() | Set reject callback |
setRateLimitCallback() | onRateLimit() | Set rate limit callback |
setAdjustmentCallback() | onAdjustment() | Set adjustment callback |
shouldSampleWithReason() | sampleWithReason(), decision() | Sample with reject reason details |
reset() | clear() | Reset sampler state |
resetStats() | clearStats() | Reset statistics |
isEnabled() | enabled() | Check if sampler is enabled |
strategyName() | name() | Get strategy name |
totalProcessed() | total_() | Get total processed count |
totalAccepted() | accepted_() | Get total accepted count |
totalRejected() | rejected_() | Get total rejected count |
shouldSample() | sample(), check(), allow() | Check if record should be sampled |
setStrategy() | configure() | Update strategy at runtime |
setProbability() | probability(), setProb() | Set probability strategy with clamping |
setRateLimit() | rateLimit(), configureRateLimit() | Set rate-limit strategy |
setEveryN() | everyN() | Set deterministic every-N strategy |
setAdaptive() | adaptive() | Set adaptive strategy with normalized bounds |
disableSampling() | disable(), off() | Disable filtering (allow all records) |
remainingWindowQuota() | quotaLeft() | Remaining rate-limit tokens in current window |
windowResetInMs() | resetInMs() | Milliseconds until window reset |
acceptRate() | acceptanceRate() | Convenience accept rate from stats |
rejectRate() | rejectionRate() | Convenience reject rate from stats |
getCurrentRate() | rate() | Get current sampling rate |
getStats() | statistics(), stats_() | Get sampler statistics |
Overview ​
Samplers reduce log volume in high-throughput systems using various strategies like probability sampling, rate limiting, every-n sampling, and adaptive sampling. All operations are thread-safe with atomic counters.
Types ​
Sampler ​
The main sampler controller with atomic state and statistics.
pub const Sampler = struct {
allocator: std.mem.Allocator,
strategy: Strategy,
state: SamplerState,
stats: SamplerStats,
mutex: std.Thread.Mutex,
// Callbacks
on_sample_accepted: ?*const fn (u64) void,
on_sample_rejected: ?*const fn (u64) void,
on_rate_adjusted: ?*const fn (f64, f64) void,
};Strategy ​
The sampling strategy to use.
pub const Strategy = union(enum) {
none: void, // No sampling, all pass
probability: f64, // 0.0 - 1.0
rate_limit: RateLimitConfig,
every_n: u32, // 1 in N
adaptive: AdaptiveConfig,
};RateLimitConfig ​
Configuration for rate limiting.
pub const RateLimitConfig = struct {
max_records: u64, // Maximum records per window
window_ms: u64, // Window size in milliseconds
};AdaptiveConfig ​
Configuration for adaptive sampling.
pub const AdaptiveConfig = struct {
target_rate: u32, // Target logs per second
min_sampling_rate: f64, // Minimum sampling probability
adjustment_interval_ms: u64, // How often to adjust
};SamplerStats ​
Statistics for sampler operations.
pub const SamplerStats = struct {
total_processed: std.atomic.Value(u64),
total_accepted: std.atomic.Value(u64),
total_rejected: std.atomic.Value(u64),
current_rate: std.atomic.Value(f32),
pub fn acceptRate(self: *const SamplerStats) f64;
};SampleDecision ​
Detailed decision payload returned by shouldSampleWithReason().
pub const SampleDecision = struct {
accepted: bool,
sample_rate: f64,
reject_reason: ?SampleRejectReason = null,
};Methods ​
Initialization ​
init(allocator: std.mem.Allocator, strategy: Strategy) Sampler ​
Initializes a new Sampler instance with the specified strategy.
Alias: create
deinit(self: *Sampler) void ​
Releases all resources associated with the sampler.
Alias: destroy
Sampling ​
shouldSample() bool ​
Determines if the current record should be sampled (processed). Returns true to process, false to drop.
Alias: sample, check, allow
shouldSampleWithReason() SampleDecision ​
Evaluates sampling and returns structured decision details including reject reason.
Alias: sampleWithReason, decision
setStrategy(strategy: Strategy) void ​
Updates sampler strategy at runtime and resets strategy-specific counters.
Alias: configure
setProbability(probability_value: f64) void ​
Sets probability sampling strategy and clamps value into [0.0, 1.0].
Alias: probability, setProb
setRateLimit(max_records: u32, window_ms: u64) void ​
Sets rate-limit strategy with safe normalization:
max_records == 0becomes1window_ms == 0uses centralized default window
Alias: rateLimit, configureRateLimit
setEveryN(n: u32) void ​
Sets deterministic every-N sampling strategy.
Alias: everyN
setAdaptive(config: AdaptiveConfig) void ​
Sets adaptive strategy and normalizes min/max sampling bounds.
Alias: adaptive
disableSampling() void ​
Disables filtering strategy (.none) so all records are accepted.
Alias: disable, off
remainingWindowQuota() ?u32 ​
For .rate_limit strategy, returns remaining records in current window. Returns null for non-rate-limit strategies.
Alias: quotaLeft
windowResetInMs() ?u64 ​
For .rate_limit strategy, returns milliseconds until current window reset. Returns null for non-rate-limit strategies.
Alias: resetInMs
acceptRate() f64 ​
Convenience wrapper around sampler stats accept rate.
Alias: acceptanceRate
rejectRate() f64 ​
Convenience wrapper around sampler stats reject rate.
Alias: rejectionRate
Statistics ​
getStats() SamplerStats ​
Returns current sampler statistics.
Alias: statistics, stats_
getCurrentRate() f64 ​
Returns the current sampling rate.
Alias: rate
resetStats() void ​
Resets all statistics to zero.
totalProcessed() u64 ​
Returns total records processed.
totalAccepted() u64 ​
Returns total records accepted.
totalRejected() u64 ​
Returns total records rejected.
SamplerStats Methods ​
The SamplerStats struct provides comprehensive statistics tracking:
pub const SamplerStats = struct {
total_records_sampled: std.atomic.Value(Constants.AtomicUnsigned),
records_accepted: std.atomic.Value(Constants.AtomicUnsigned),
records_rejected: std.atomic.Value(Constants.AtomicUnsigned),
rate_limit_exceeded: std.atomic.Value(Constants.AtomicUnsigned),
rate_adjustments: std.atomic.Value(Constants.AtomicUnsigned),
/// Calculate current accept rate (0.0 - 1.0)
pub fn getAcceptRate(self: *const SamplerStats) f64;
/// Calculate current reject rate (0.0 - 1.0)
pub fn getRejectRate(self: *const SamplerStats) f64;
/// Returns true if any records have been rejected.
pub fn hasRejections(self: *const SamplerStats) bool;
/// Returns true if rate limit has been exceeded at least once.
pub fn hasRateLimitExceeded(self: *const SamplerStats) bool;
/// Returns the rate limit exceeded percentage (0.0 - 1.0).
pub fn getRateLimitExceededRate(self: *const SamplerStats) f64;
/// Returns total records sampled as u64.
pub fn getTotal(self: *const SamplerStats) u64;
/// Returns accepted records count as u64.
pub fn getAccepted(self: *const SamplerStats) u64;
/// Returns rejected records count as u64.
pub fn getRejected(self: *const SamplerStats) u64;
};State ​
isEnabled() bool ​
Returns true if sampling is enabled (strategy != none).
strategyName() []const u8 ​
Returns the name of the current strategy.
Callbacks ​
setAcceptedCallback(callback: *const fn (u64) void) void ​
Sets callback for accepted samples.
setRejectedCallback(callback: *const fn (u64) void) void ​
Sets callback for rejected samples.
setRateAdjustedCallback(callback: *const fn (f64, f64) void) void ​
Sets callback for rate adjustments (adaptive strategy).
Presets ​
SamplerPresets ​
pub const SamplerPresets = struct {
/// No sampling - all records pass through.
pub fn none(allocator) Sampler;
/// Sample approximately 10% of records.
pub fn sample10Percent(allocator) Sampler;
/// Sample approximately 50% of records.
pub fn sample50Percent(allocator) Sampler;
/// Sample approximately 1% of records (high-volume production).
pub fn sample1Percent(allocator) Sampler;
/// Limit to 10 records per second (debug/low-volume).
pub fn limit10PerSecond(allocator) Sampler;
/// Limit to 100 records per second.
pub fn limit100PerSecond(allocator) Sampler;
/// Limit to 1000 records per second.
pub fn limit1000PerSecond(allocator) Sampler;
/// Sample every 5th record.
pub fn every5th(allocator) Sampler;
/// Sample every 10th record.
pub fn every10th(allocator) Sampler;
/// Sample every 100th record (high-volume production).
pub fn every100th(allocator) Sampler;
/// Adaptive sampling targeting 100 records per second.
pub fn adaptive100PerSecond(allocator) Sampler;
/// Adaptive sampling targeting 1000 records per second.
pub fn adaptive1000PerSecond(allocator) Sampler;
/// Creates a sampled sink configuration.
pub fn createSampledSink(file_path: []const u8) SinkConfig;
};Example ​
const Sampler = @import("logly").Sampler;
const SamplerPresets = @import("logly").SamplerPresets;
// Create sampler with 10% probability
var sampler = Sampler.init(allocator, .{ .probability = 0.1 });
defer sampler.deinit();
// Or use presets
var sampler2 = SamplerPresets.limit100PerSecond(allocator);
defer sampler2.deinit();
// Check if record should be sampled
for (records) |record| {
if (sampler.shouldSample()) {
// Process this record
processRecord(record);
}
}
// Check statistics
const stats = sampler.getStats();
std.debug.print("Accept rate: {d:.2}%\n", .{stats.acceptRate() * 100});
std.debug.print("Processed: {d}, Accepted: {d}, Rejected: {d}\n", .{
sampler.totalProcessed(),
sampler.totalAccepted(),
sampler.totalRejected(),
});
// Check if sampling is active
if (sampler.isEnabled()) {
std.debug.print("Strategy: {s}\n", .{sampler.strategyName()});
}Strategy Selection Guide ​
| Strategy | Use Case | Overhead |
|---|---|---|
none | No sampling needed | Zero |
probability | Random sampling for debugging | Very low |
rate_limit | Strict throughput control | Low |
every_n | Predictable sampling | Very low |
adaptive | Dynamic load handling | Low |
Performance ​
- Lock-free fast path for read-only checks
- Atomic counters for thread-safe statistics
- Minimal overhead in all strategies
- Adaptive adjustment only during adjustment intervals
See Also ​
- Filtering Guide - Content-based filtering
- Metrics API - Performance monitoring
