Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
policy-rs
Rust implementation of the Tero Policy Specification for high-performance log policy evaluation and transformation.
Another implementation of this specification is available in Tero Edge, a Zig-based observability edge runtime, providing the policy evaluation engine for filtering, sampling, and transforming telemetry data.
Features
- High-performance pattern matching using Hyperscan for parallel regex evaluation
- Policy-based log filtering with keep, drop, sample, and rate-limit actions
- Log transformations including field removal, redaction, renaming, and addition
- Multiple policy providers with live reload support
- Zero-allocation field access through the
Matchabletrait - Async-first design built on Tokio
Installation
Add to your Cargo.toml:
[]
= { = "https://github.com/usetero/policy-rs" }
Quick Start
use ;
async
Core Concepts
Policy Registry
The PolicyRegistry manages policies from multiple providers and maintains an
immutable snapshot for lock-free evaluation:
let registry = new;
// Subscribe to a file-based provider (auto-reloads on changes)
let provider = new;
registry.subscribe?;
// Or register a custom provider
let handle = registry.register_provider;
handle.update;
// Get immutable snapshot for evaluation
let snapshot = registry.snapshot;
Policy Engine
The PolicyEngine evaluates logs against compiled policies using Hyperscan for
pattern matching:
let engine = new;
let snapshot = registry.snapshot;
// Read-only evaluation
let result = engine.evaluate.await?;
// Evaluation with transformations applied
let result = engine.evaluate_and_transform.await?;
Evaluation Results
Implementing the Traits
To evaluate your log types, implement the Matchable trait. For transformation
support, also implement Transformable.
Matchable Trait
The Matchable trait provides field access for pattern matching with two
primitives: get_field returns the field's string value (for regex / equals /
contains matchers), and field_exists reports presence regardless of value
type (for exists: true matchers).
use Cow;
use ;
use LogField;
The default field_exists is self.get_field(field).is_some(), which is
correct as long as every present value is a string. If your records carry
non-string values (numbers, booleans, structured values), override
field_exists so exists: true matchers fire on those attributes — a record
whose count: 42 lives only as an integer would otherwise be reported as
absent because get_field cannot return a string for it.
For example, a record that holds OTel-style typed values:
Without the override, a policy with exists: true on count (stored as
AnyValue::Int(42)) would not fire, because get_field correctly returns
None for a value that can't be expressed as a string.
Transformable Trait
The Transformable trait exposes three minimal write primitives —
set_field, delete_field, and move_field. The engine composes these with
the read side of Matchable to drive higher-level transform ops (regex
redact, upsert add, rename-with-upsert), so consumers don't have to express
upsert checks or regex matching themselves.
use ;
use LogField;
The engine constructs to so its variant matches the source's attribute
namespace — e.g. renaming a ResourceAttribute produces a target selector
of ResourceAttribute. Implementors should dispatch on to's variant
rather than assuming a primary namespace.
Advanced Usage
Custom Policy Providers
Implement PolicyProvider to load policies from custom sources:
use ;
// Use with the registry
let registry = new;
let provider = new;
registry.subscribe?;
Policy Statistics
Track policy hit/miss rates and transform statistics:
let snapshot = registry.snapshot;
for entry in snapshot.iter
Multiple Providers
Combine policies from multiple sources:
let registry = new;
// File-based policies
let file_provider = new;
registry.subscribe?;
// Programmatic policies
let handle = registry.register_provider;
handle.update;
// All policies are merged in the snapshot
let snapshot = registry.snapshot;
Configuration-Based Providers
Use the config module to define providers in JSON/TOML configuration files. The
ProviderConfig type is designed to be embedded in your application's config:
use ;
use PolicyRegistry;
use Deserialize;
// Parse your app config
let config: AppConfig = from_str?;
// Register all providers at once
let registry = new;
register_providers?;
Provider Config Format
Each provider configuration has a type field that determines the provider:
File Provider:
HTTP Provider (requires http feature):
gRPC Provider (requires grpc feature):
You can also parse just the provider list directly:
let providers: = from_str?;
Transform Order
When using evaluate_and_transform, transformations are applied in a fixed
order:
- Remove - Delete fields
- Redact - Replace field values with placeholders
- Rename - Rename fields to new keys
- Add - Add new fields
Transforms from all matching policies are applied, not just the winning policy.
Policy Format
Policies are defined using the Tero Policy protobuf schema. Example JSON:
Keep Values
"all"- Keep all matching logs"none"- Drop all matching logs"50%"- Sample 50% of matching logs"100/s"- Rate limit to 100 logs per second"1000/m"- Rate limit to 1000 logs per minute
Match Fields
logField- Simple fields:BODY,SEVERITY_TEXT,TRACE_ID,SPAN_ID, etc.logAttribute- Log attributes by keyresourceAttribute- Resource attributes by keyscopeAttribute- Scope attributes by key
Match Types
exact- Exact string matchregex- Regular expression matchexists- Field existence check
Examples
See the examples/ directory:
basic_usage.rs- Load policies and evaluate logstransforms.rs- Apply log transformationsmultiple_providers.rs- Combine multiple policy sourcescustom_provider.rs- Implement a custom providerconfig_providers.rs- Configure providers via JSON config
Run examples with:
License
Apache-2.0