GDPR-compliant privacy features including consent management, DO_NOT_TRACK support, and data sanitization
telemetry-kit includes comprehensive privacy controls to help you build GDPR-compliant applications:
DO_NOT_TRACK Support - Automatically respects the DO_NOT_TRACK environment variable
Consent Management - User consent tracking with persistent storage
Data Sanitization - Automatic removal of PII (paths, emails)
Data Retention - Configurable retention policies
Privacy Presets - Pre-configured strict, default, and minimal modes
Privacy features are enabled by default in telemetry-kit v0.2.0+
The simplest approach with sensible defaults:
use telemetry_kit :: prelude ::* ;
#[tokio :: main]
async fn main () -> telemetry_kit :: Result <()> {
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. build () ? ;
// Privacy enabled by default:
// - Respects DO_NOT_TRACK
// - Sanitizes paths and emails
// - 90-day retention
Ok (())
} Always check if the user has opted out:
if TelemetryKit :: is_do_not_track_enabled () {
println! ( "Telemetry disabled by user preference" );
return Ok (());
} Events are automatically sanitized:
telemetry . track_command ( "build" , | event | {
event
. flag ( "--release" )
. success ( true )
}) .await? ;
// Paths like /Users/john/project → ~/project
// Emails like user@example.com → email_<hash>
Maximum privacy protection, suitable for EU applications:
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. strict_privacy () // Enables strictest settings
. build () ? ;
// Strict mode settings:
// - Consent required: Yes
// - DO_NOT_TRACK respected: Yes
// - Path sanitization: Yes
// - Email sanitization: Yes
// - Data retention: 30 days
// - IP anonymization: Yes
Balanced privacy and functionality:
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. build () ? ; // Uses default privacy
// Default settings:
// - Consent required: No
// - DO_NOT_TRACK respected: Yes
// - Path sanitization: Yes
// - Email sanitization: Yes
// - Data retention: 90 days
// - IP anonymization: Yes
Minimal privacy restrictions (not recommended for production):
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. minimal_privacy ()
. build () ? ;
// Minimal settings:
// - Consent required: No
// - DO_NOT_TRACK respected: Yes (always)
// - Path sanitization: No
// - Email sanitization: No
// - Data retention: Forever
// - IP anonymization: No
For GDPR compliance, require explicit consent:
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. consent_required ( true )
. build () ? ;
// Events will be silently ignored until consent is granted
telemetry . track_command ( "test" , | e | e . success ( true )) .await? ;
// ↑ Not tracked (no consent yet)
// Grant consent
telemetry . grant_consent () ? ;
// Now tracking works
telemetry . track_command ( "test" , | e | e . success ( true )) .await? ;
// ↑ Tracked successfully
Consent is stored persistently in ~/.telemetry-kit/{service-name}-consent.json:
{
"status" : "Granted" ,
"timestamp" : "2025-01-15T10:30:00Z" ,
"service_name" : "my-app"
}
telemetry . deny_consent () ? ;
// All tracking is now disabled
telemetry . track_command ( "test" , | e | e . success ( true )) .await? ;
// ↑ Silently ignored
Equivalent to setting DO_NOT_TRACK=1:
telemetry . opt_out () ? ;
// User has opted out - no tracking
telemetry-kit always respects the DO_NOT_TRACK environment variable:
# Disable telemetry via environment variable
export DO_NOT_TRACK = 1
# Now all tracking is disabled
cargo run
Check programmatically:
if TelemetryKit :: is_do_not_track_enabled () {
println! ( "User has opted out of telemetry" );
return Ok (());
}
Accepted values:
DO_NOT_TRACK=1 → Telemetry disabled
DO_NOT_TRACK=true → Telemetry disabled
DO_NOT_TRACK=0 → Telemetry enabled
DO_NOT_TRACK=false → Telemetry enabled
Not set → Telemetry enabled (unless consent required)
By default, telemetry-kit sanitizes:
File Paths - Removes usernames
Email Addresses - Hashed to protect identity
// Before sanitization
let data = json! ({
"path" : "/Users/john/Documents/project" ,
"email" : "john@example.com"
});
// After sanitization
let data = json! ({
"path" : "~/Documents/project" ,
"email" : "email_a1b2c3d4"
});
Use the PrivacyManager directly:
use telemetry_kit :: privacy :: PrivacyManager ;
// Sanitize a path
let safe_path = PrivacyManager :: sanitize_path ( "/Users/john/secret.txt" );
println! ( "{}" , safe_path); // ~/secret.txt
// Sanitize an email
let safe_email = PrivacyManager :: sanitize_email ( "user@example.com" );
println! ( "{}" , safe_email); // email_b4c9a289323b21a0
Control what gets sanitized:
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. sanitize_paths ( true ) // Default: true
. sanitize_emails ( true ) // Default: true
. build () ? ;
Configure how long telemetry data is kept:
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. data_retention ( 30 ) // Keep for 30 days
. build () ? ;
// Clean up old data
let deleted = telemetry . cleanup () .await? ;
println! ( "Deleted {} old events" , deleted);
Retention values:
0 = Forever (not recommended)
30 = 30 days (strict mode default)
90 = 90 days (default mode default)
Any positive number = That many days
Fine-tune privacy settings:
use telemetry_kit :: privacy :: PrivacyConfig ;
let config = PrivacyConfig {
consent_required : true ,
respect_do_not_track : true , // Always true
sanitize_paths : true ,
sanitize_emails : true ,
data_retention_days : 60 ,
anonymize_ips : true ,
};
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. privacy (config)
. build () ? ;
if TelemetryKit :: is_do_not_track_enabled () {
return Ok (()); // Exit early
}
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. strict_privacy () // GDPR-compliant
. build () ? ;
use dialoguer :: Confirm ;
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. consent_required ( true )
. build () ? ;
// Ask user for consent
if Confirm :: new ()
. with_prompt ( "Allow anonymous usage statistics?" )
. interact () ?
{
telemetry . grant_consent () ? ;
println! ( "Thank you!" );
} else {
telemetry . deny_consent () ? ;
}
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. data_retention ( 30 ) // GDPR recommends 30-90 days
. build () ? ;
let telemetry = TelemetryKit :: builder ()
. service_name ( "my-app" ) ?
. sanitize_paths ( true ) // Remove usernames
. sanitize_emails ( true ) // Hash emails
. build () ? ;
To ensure GDPR compliance:
. strict_privacy () // Use strict preset
. minimal_privacy () // Use minimal preset
. privacy (config) // Custom config
. consent_required ( bool ) // Require consent
. data_retention (days) // Retention period
. sanitize_paths ( bool ) // Path sanitization
. sanitize_emails ( bool ) // Email sanitization
. grant_consent () // Grant consent
. deny_consent () // Deny consent
. opt_out () // Opt out completely
. is_do_not_track_enabled () // Check DNT (static)
PrivacyManager :: sanitize_path (path) // Sanitize path
PrivacyManager :: sanitize_email (email) // Sanitize email
See examples/privacy.rs for complete working examples.
The telemetry server can track how many requests include the DO_NOT_TRACK header without violating privacy:
Client respects DNT by not sending events
Server logs requests WITH DNT header
Aggregated metrics show: "X requests with DNT vs Y without"
This doesn't violate privacy (server-side aggregation only)
See Self-Hosting for server configuration.