A CLI tool for analyzing Rails application logs from AWS CloudWatch Logs. This tool aggregates request metrics by path, providing insights into application performance including request counts and response times.
- CloudWatch Integration: Seamlessly fetches logs from AWS CloudWatch Logs with intelligent pagination
- Rails Log Analysis: Parses both standard and production format Rails logs with session-based request matching
- Path Normalization: Converts dynamic paths to parameterized routes for meaningful aggregation
- Performance Metrics: Calculates min/max/average response times and request counts
- Configurable Exclusions: Filter out unwanted paths using exact matches, prefixes, or regex patterns
- JSON Output: Structured output sorted by request count for easy integration with other tools
- JST Time Support: User-friendly time input in JST with automatic UTC conversion for CloudWatch
- High Performance: Optimized CloudWatch filter patterns reduce data transfer and processing costs
- Go 1.24.5 or later
- AWS CLI configured with appropriate permissions
- AWS credentials for CloudWatch Logs access
git clone https://github.com/kgrsutos/CW-RailsPathMetrics.git
cd CW-RailsPathMetrics
make buildgo install github.com/kgrsutos/cw-railspathmetrics/cmd/cwrstats@latestAfter installation, the binary will be available in your $GOPATH/bin directory.
# Using default configuration
./cwrstats analyze \
--start "2025-07-01T00:00:00" \
--end "2025-07-01T23:59:59" \
--log-group "/aws/rails/production-log" \
--profile myprofile
# Using custom configuration file
./cwrstats analyze \
--config /path/to/excluded_paths.yml \
--start "2025-07-01T00:00:00" \
--end "2025-07-01T23:59:59" \
--log-group "/aws/rails/production-log" \
--profile myprofile| Flag | Description | Required | Format |
|---|---|---|---|
--start |
Start time in JST | Yes | 2006-01-02T15:04:05 |
--end |
End time in JST | Yes | 2006-01-02T15:04:05 |
--log-group |
CloudWatch Logs log group name | Yes | String |
--profile |
AWS profile name | Yes | String |
--config |
Path to custom exclusion configuration file | No | String |
The tool outputs JSON with request metrics sorted by request count (descending):
[
{
"path": "/users/:id",
"count": 1250,
"max_time_ms": 890,
"min_time_ms": 45,
"avg_time_ms": 121
}
]The application supports configurable path exclusions with automatic configuration file discovery.
excluded_paths:
# Exact path match
- exact: "/health"
# Prefix match
- prefix: "/rails/active_storage"
# Regex pattern match
- pattern: "^/api/internal/.*"The application searches for configuration files in the following locations (in order of preference):
- Custom path (via
--configflag):/path/to/custom/excluded_paths.yml - XDG config directory:
$XDG_CONFIG_HOME/cw-railspathmetrics/excluded_paths.yml - User config directory:
$HOME/.config/cw-railspathmetrics/excluded_paths.yml - User app directory:
$HOME/.cw-railspathmetrics/excluded_paths.yml - Default fallback: Built-in exclusion for
/rails/active_storageprefix
After installing via go install, create a configuration file:
# Create config directory
mkdir -p ~/.config/cw-railspathmetrics
# Create configuration file
cat > ~/.config/cw-railspathmetrics/excluded_paths.yml << EOF
excluded_paths:
- exact: "/health"
- exact: "/ping"
- prefix: "/rails/active_storage"
- prefix: "/assets"
- pattern: "^/api/internal/.*"
EOFEnsure your AWS profile has the following IAM permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:FilterLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams"
],
"Resource": "arn:aws:logs:*:*:log-group:/aws/rails/*"
}
]
}┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ CLI │───▶│ CloudWatch │───▶│ Analysis │
│ Layer │ │ Client │ │ Engine │
└─────────────┘ └──────────────┘ └─────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Config │ │ JSON Output │
│ System │ │ │
└─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ Time Utils │
│ (JST↔UTC) │
└─────────────┘
- Configuration: Loads exclusion rules from config files or uses defaults
- Parser: Extracts structured data from Rails log messages using regex patterns
- Normalizer: Converts dynamic paths to parameterized routes (e.g.,
/users/123→/users/:id) - Aggregator: Matches Started/Completed log pairs by session ID, applies exclusion filters, and calculates metrics
- Output: Generates JSON sorted by request count
Standard Rails Format:
Started GET "/users/123" for 127.0.0.1 at 2025-01-01 12:00:00 +0900
Completed 200 OK in 150ms (Views: 100.0ms | ActiveRecord: 50.0ms)
Production Format with Log Level:
I, [2025-07-10T17:28:13.282478 #7] INFO -- : [session-id] Started GET "/users/123" for 127.0.0.1 at 2025-07-10 17:28:13 +0900
I, [2025-07-10T17:28:13.321048 #7] INFO -- : [session-id] Completed 200 OK in 33ms (Views: 18.3ms | ActiveRecord: 8.0ms)
# Clone and setup
git clone https://github.com/kgrsutos/CW-RailsPathMetrics.git
cd CW-RailsPathMetrics
# Install development tools
make install-tools
# Download dependencies
make depsmake build # Build the binary
make test # Run tests with coverage report
make test-coverage # Run tests and display coverage percentage
make lint # Run linters
make clean # Clean build artifacts
make deps # Download and tidy dependenciesRun the full test suite with coverage:
make test- Interface-based Design: All external dependencies use interfaces for easy testing
- Session-based Matching: Uses session IDs from log messages for accurate request pairing
- Clean Architecture: Clear separation between CLI, CloudWatch client, configuration, and analysis layers
- Configuration Auto-discovery: Follows XDG Base Directory specification with graceful fallbacks
- Graceful Error Handling: Invalid logs are skipped rather than failing the entire analysis
- Follow standard Go conventions
- Use
gofmtfor formatting - Write comprehensive tests for new features
- Document public APIs with Go doc comments
- Use structured logging with
slog
- Built with Cobra for CLI functionality
- Uses AWS SDK for Go v2 for CloudWatch integration
- Structured logging with Go's standard slog package