Analytics
Connection event tracking with ClickHouse
trojan-rs includes an optional analytics module for tracking connection events. Events are buffered and written to ClickHouse for analysis.
Overview
Connection → Event Collector → Buffer → ClickHouse Writer → ClickHouse DBThe analytics system is double-gated:
- Compile-time: The
analyticsfeature flag must be enabled - Runtime: The
[analytics]config section must be present withenabled = true
Configuration
[analytics]
enabled = true
[analytics.clickhouse]
url = "http://localhost:8123" # ClickHouse HTTP endpoint
database = "trojan" # Database name
table = "connection_events" # Table name
username = "default" # ClickHouse username
password = "" # ClickHouse password
connect_timeout_secs = 5
request_timeout_secs = 10
[analytics.buffer]
max_events = 1000 # Max buffered events before flush
flush_interval_secs = 10 # Flush interval
[analytics.sampling]
rate = 1.0 # Sampling rate (0.0 to 1.0)
allowed_users = [] # Always sample these user hashes
[analytics.privacy]
record_ip = true # Record client IP addresses
mask_user_id = false # Mask user identifiers
record_sni = true # Record SNI valuesEvent Fields
Each connection event captures:
| Field | Type | Description |
|---|---|---|
timestamp | DateTime | Event timestamp |
connection_id | String | Unique connection identifier |
client_ip | String | Client IP address |
client_port | UInt16 | Client port |
user_hash | String | SHA-224 password hash |
command | String | Trojan command (connect/udp) |
target_host | String | Destination hostname |
target_port | UInt16 | Destination port |
bytes_up | UInt64 | Bytes uploaded |
bytes_down | UInt64 | Bytes downloaded |
duration_ms | UInt64 | Connection duration |
close_reason | String | Why the connection closed |
tls_version | String | TLS version used |
tls_cipher | String | TLS cipher suite |
sni | String | Server Name Indication |
alpn | String | Negotiated ALPN protocol |
auth_result | String | Authentication result |
transport | String | Transport type (tcp/websocket) |
Buffering
Events are collected in memory and flushed to ClickHouse when either:
- The buffer reaches
max_eventsevents - The
flush_interval_secstimer fires
This batches writes for efficiency. If ClickHouse is unreachable, events are dropped after the buffer fills.
Sampling
Control the volume of recorded events:
[analytics.sampling]
rate = 0.1 # Sample 10% of connections
allowed_users = ["abc123..."] # Always sample these usersrate = 1.0records all connectionsrate = 0.0disables recording (except allowed users)- Users in
allowed_usersare always sampled regardless of rate
Privacy Controls
[analytics.privacy]
record_ip = false # Omit client IP addresses
mask_user_id = true # Hash user identifiers
record_sni = false # Omit SNI valuesUse these settings to comply with privacy requirements.
ClickHouse Schema
The analytics module creates a table with the fields listed above. It also supports materialized views for common queries:
- Hourly traffic summary — Aggregated bytes by user per hour
- Connection count by target — Top destinations
- Error rate tracking — Authentication failures and connection errors
Example Queries
Traffic by user (last 24 hours)
SELECT
user_hash,
sum(bytes_up) AS total_up,
sum(bytes_down) AS total_down,
count() AS connections
FROM connection_events
WHERE timestamp > now() - INTERVAL 1 DAY
GROUP BY user_hash
ORDER BY total_down DESCTop destinations
SELECT
target_host,
count() AS connections,
sum(bytes_down) AS total_bytes
FROM connection_events
WHERE timestamp > now() - INTERVAL 1 DAY
GROUP BY target_host
ORDER BY connections DESC
LIMIT 20Authentication failures
SELECT
client_ip,
count() AS failures
FROM connection_events
WHERE auth_result != 'success'
AND timestamp > now() - INTERVAL 1 HOUR
GROUP BY client_ip
ORDER BY failures DESC