LogProx
HTTP proxy with conditional logging and request control
Why?!
At a previous company there was an external API we integrated with. Its versioning strategy was somewhat aggressive and we would incur penalties for accessing deprecated API versions. The idea for logprox was born out of that restriction. Old API calls (sometimes saved on someone's machine, test calls, etc) would potentially put the company at risk. If all calls were proxied through a logging mechanism, not only could we determine where the deprecated calls were coming from, we could block those calls entirely.
Quick Start
Installation
# Install via cargo
# Build from source
Basic Usage
# Start with default config (reads config.yaml)
# Specify custom config via env var
CONFIG_FILE=my-config.yaml
# Override port
PORT=8080 CONFIG_FILE=config.yaml
Simple Example
Create config.yaml:
logging:
default: false
rules:
- name: "Monitor API calls"
match_conditions:
path:
patterns:
capture:
method: true
path: true
timing: true
Start LogProx and test:
# Proxy format: http://host:port/https://upstream-domain/path
Features
- Conditional Logging: Log requests based on path, method, headers, body
- Request Control: Drop requests based on configurable rules
- Hot Reload: Update configuration without restarting
- Built-in Monitoring: Health checks and configuration endpoints
Architecture
┌─────────────┐ ┌───────────┐ ┌────────────────┐
│ Client │───▶│ LogProx │───▶│ Upstream API │
│ Application │ │ │ │ │
└─────────────┘ └───────────┘ └────────────────┘
│
▼
┌────────────┐
│ Logs & │
│ Metrics │
└────────────┘
Configuration
LogProx uses YAML configuration with environment variable support (${VAR_NAME}).
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
CONFIG_FILE |
config.yaml |
Configuration file path |
Quick Reference
logging:
default: false
rules:
- name: "API Monitoring"
match_conditions:
path:
methods:
capture:
drop:
default: false
rules:
- name: "Block Bots"
match_conditions:
headers:
response:
response_logging:
default: false
rules:
- name: "Log Errors"
match_conditions:
status_codes:
capture:
Request Format
Proxy requests use URL path encoding:
http://localhost:3000/https://api.example.com/users/123
↑
Encoded upstream URL
Pattern Matching
Regex Examples:
.*- Match any characters^/api/- Match paths starting with /api/\d+- Match one or more digits(option1|option2)- Match either option
Matching Logic:
- Path patterns: At least one must match
- Methods: Must be in methods list (if specified)
- Headers: All specified headers must match
- Body patterns: At least one must match
- Rule evaluation: First match wins
API Reference
| Endpoint | Method | Response |
|---|---|---|
/health |
GET | 200 OK with body "OK" |
/config |
GET | Current JSON configuration |
/config/docs |
GET | Configuration documentation |
/config/reload |
POST | Reload configuration |
Usage Examples
# Health check
# Get current config
|
# Reload configuration
# View documentation
Troubleshooting
Configuration Issues
# Validate YAML syntax
# Enable debug logging
RUST_LOG=debug
Common Problems
- Invalid proxy format: Use
/https://domain/pathformat - Regex errors: Test patterns with regex debugger
- Permission denied: Check config file permissions
Performance
Per-Request Latency
| Metric | Time |
|---|---|
| Average proxy overhead | ~35µs |
| Direct upstream (local) | ~40µs |
| Proxied request (local) | ~75µs |
Running Benchmarks
# Micro-benchmarks
# Comprehensive benchmarks
Micro-benchmark Highlights
| Operation | Time |
|---|---|
| Cached regex lookup | 10-27 ns |
| Header iteration (6 headers) | 15 ns |
| Config lock (single) | 14 ns |
| String operations (optimized) | 17 ns |
| YAML config parsing | 10 µs |
License
GNU GPLv3 © Bryan Lott