Web Dashboard Guide¶
This guide covers the FinOps Optimizer web dashboard, including setup, usage, and customization.
📋 Overview¶
The FinOps Optimizer web dashboard provides a modern, interactive interface for cost monitoring, optimization, and reporting. Built with Flask and Bootstrap, it offers real-time insights into your multi-cloud infrastructure.
🚀 Quick Start¶
Installation¶
# Install web dependencies
pip install flask flask-login werkzeug
# Start dashboard
python -m web.app
# Or use CLI
python cli.py dashboard
Access Dashboard¶
- URL: http://localhost:5000
- Default Username:
admin
- Default Password:
admin123
🏗️ Architecture¶
Components¶
web/
├── app.py # Flask application
├── templates/ # HTML templates
│ ├── dashboard.html # Main dashboard
│ ├── login.html # Login page
│ └── components/ # Reusable components
├── static/ # Static assets
│ ├── css/ # Stylesheets
│ ├── js/ # JavaScript
│ └── images/ # Images
└── api/ # API endpoints
Technology Stack¶
- Backend: Flask (Python)
- Frontend: Bootstrap 5, Chart.js
- Authentication: Flask-Login
- Charts: Chart.js
- Styling: Bootstrap CSS
📊 Dashboard Features¶
1. Real-time Cost Monitoring¶
The dashboard provides real-time cost monitoring across all cloud providers:
- Cost Overview: Total costs and trends
- Provider Breakdown: Costs by cloud provider
- Service Analysis: Costs by service type
- Daily Trends: Cost trends over time
2. Interactive Charts¶
Cost Trend Chart¶
// Line chart showing daily costs
const costTrendChart = new Chart(ctx, {
type: 'line',
data: {
labels: dates,
datasets: [{
label: 'Daily Cost',
data: costs,
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)'
}]
}
});
Service Breakdown Chart¶
// Doughnut chart showing service costs
const serviceChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: services,
datasets: [{
data: serviceCosts,
backgroundColor: colors
}]
}
});
3. Provider Status Monitoring¶
Real-time status of cloud providers:
- Connection Status: Online/Offline indicators
- Credential Validation: Authentication status
- API Health: Service availability
- Performance Metrics: Response times
4. Optimization Recommendations¶
Interactive recommendations panel:
- Rightsizing: Instance optimization suggestions
- Autoscaling: Scaling policy recommendations
- Cost Allocation: Tagging and allocation suggestions
- Priority Levels: High/Medium/Low priority
5. Cost Forecasting¶
ML-powered cost forecasting:
- Forecast Periods: 30, 60, 90 days
- Confidence Intervals: Statistical confidence
- Optimization Impact: Savings projections
- Trend Analysis: Growth patterns
🔧 Setup and Configuration¶
1. Basic Setup¶
# Install dependencies
pip install flask flask-login werkzeug
# Configure environment
export FLASK_APP=web.app
export FLASK_ENV=development
# Start dashboard
python -m web.app
2. Production Setup¶
# Install production dependencies
pip install gunicorn
# Start with gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 web.app:app
# With SSL
gunicorn -w 4 -b 0.0.0.0:8000 --certfile cert.pem --keyfile key.pem web.app:app
3. Docker Setup¶
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "-m", "web.app"]
4. Configuration¶
Dashboard Configuration¶
# finops_config.yml
dashboard:
enabled: true
host: "0.0.0.0"
port: 5000
debug: false
# Authentication
auth:
enabled: true
session_timeout: 3600
max_login_attempts: 5
# Security
security:
secret_key: "your-secret-key"
ssl_enabled: false
ssl_cert: "/path/to/cert.pem"
ssl_key: "/path/to/key.pem"
# Features
features:
real_time_updates: true
interactive_charts: true
export_reports: true
notifications: true
User Management¶
# Custom user management
from web.app import User
# Add users
users = {
'admin': User(1, 'admin', generate_password_hash('admin123')),
'user1': User(2, 'user1', generate_password_hash('password123')),
'manager': User(3, 'manager', generate_password_hash('manager123'))
}
📱 User Interface¶
1. Login Page¶
<!-- login.html -->
<div class="login-card">
<div class="logo">
<h2>FinOps Optimizer</h2>
<p class="text-muted">Cost Optimization Dashboard</p>
</div>
<form method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
2. Main Dashboard¶
<!-- dashboard.html -->
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<nav class="col-md-3 col-lg-2 d-md-block sidebar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="#dashboard">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#costs">Cost Analysis</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#recommendations">Recommendations</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#forecast">Cost Forecast</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#reports">Reports</a>
</li>
</ul>
</nav>
<!-- Main content -->
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<!-- Dashboard content -->
</main>
</div>
</div>
3. Metrics Cards¶
<!-- Metrics cards -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card metric-card">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-white-50 text-uppercase mb-1">
Total Cost
</div>
<div class="h5 mb-0 font-weight-bold text-white" id="totalCost">$0</div>
</div>
<div class="col-auto">
<i class="fas fa-dollar-sign fa-2x text-white-50"></i>
</div>
</div>
</div>
</div>
</div>
</div>
🔌 API Endpoints¶
1. Cost Analysis¶
GET /api/costs
¶
Get cost analysis data.
Query Parameters: - days
(int): Number of days to analyze. Default: 30
Response:
{
"summary": {
"total_cost": 2450.75,
"providers_analyzed": ["aws", "azure", "gcp"],
"analysis_period": {
"start_date": "2024-01-01T00:00:00",
"end_date": "2024-01-31T23:59:59"
}
},
"aws": {
"total_cost": 1250.50,
"service_breakdown": {
"EC2": 750.25,
"S3": 350.00,
"RDS": 150.25
},
"daily_costs": [...]
},
"azure": {
"total_cost": 800.25,
"service_breakdown": {...},
"daily_costs": [...]
},
"gcp": {
"total_cost": 400.00,
"service_breakdown": {...},
"daily_costs": [...]
}
}
2. Recommendations¶
GET /api/recommendations
¶
Get optimization recommendations.
Response:
[
{
"type": "rightsizing",
"resource_id": "i-123456",
"description": "Downsize instance from t3.xlarge to t3.large",
"potential_savings": 200.00,
"priority": "high",
"provider": "aws",
"confidence": 0.9,
"implementation_effort": "low"
}
]
3. Cost Forecast¶
GET /api/forecast
¶
Get cost forecast.
Query Parameters: - days
(int): Days to forecast. Default: 30
Response:
{
"total_forecast": 2750.00,
"confidence_interval": [2500.00, 3000.00],
"forecast_period": 30,
"provider_forecasts": {
"aws": {
"total_forecast": 1375.00,
"trend_analysis": {
"trend_direction": "increasing",
"volatility": 0.1
}
}
},
"recommendations_impact": {
"base_forecast": 2750.00,
"optimized_forecast": 2300.00,
"total_savings": 450.00,
"savings_percentage": 16.4
}
}
4. Optimization¶
POST /api/optimize
¶
Run complete optimization.
Response:
{
"summary": {
"total_recommendations": 15,
"total_potential_savings": 450.75,
"providers_analyzed": ["aws", "azure", "gcp"]
},
"recommendations": [...],
"report_path": "/path/to/report.html"
}
5. Reports¶
POST /api/reports
¶
Generate report.
Request Body:
Response:
6. Provider Status¶
GET /api/status
¶
Get provider status.
Response:
7. Performance Metrics¶
GET /api/performance
¶
Get performance metrics.
Response:
{
"cache_hit_rate": 0.85,
"total_requests": 1250,
"average_response_time": 0.25,
"error_rate": 0.004,
"memory_usage": 0.45,
"cpu_usage": 0.15
}
🎨 Customization¶
1. Custom Themes¶
/* custom-theme.css */
:root {
--primary-color: #667eea;
--secondary-color: #764ba2;
--success-color: #28a745;
--warning-color: #ffc107;
--danger-color: #dc3545;
--dark-color: #343a40;
--light-color: #f8f9fa;
}
.sidebar {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
}
.metric-card {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
color: white;
}
2. Custom Components¶
<!-- custom-component.html -->
<div class="custom-widget">
<div class="widget-header">
<h5>Custom Widget</h5>
</div>
<div class="widget-content">
<!-- Custom content -->
</div>
</div>
3. Custom JavaScript¶
// custom-dashboard.js
class CustomDashboard {
constructor() {
this.initializeCharts();
this.setupEventListeners();
this.startRealTimeUpdates();
}
initializeCharts() {
// Custom chart initialization
}
setupEventListeners() {
// Custom event handling
}
startRealTimeUpdates() {
// Real-time data updates
setInterval(() => {
this.updateMetrics();
}, 30000); // Update every 30 seconds
}
updateMetrics() {
fetch('/api/costs')
.then(response => response.json())
.then(data => {
this.updateCharts(data);
this.updateMetrics(data);
});
}
}
// Initialize custom dashboard
document.addEventListener('DOMContentLoaded', () => {
new CustomDashboard();
});
🔒 Security Features¶
1. Authentication¶
# Authentication configuration
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
@login_manager.user_loader
def load_user(user_id):
return users.get(int(user_id))
2. Session Management¶
# Session configuration
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret-key')
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=1)
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
3. Rate Limiting¶
# Rate limiting
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/api/costs')
@limiter.limit("10 per minute")
@login_required
def get_costs():
# API endpoint with rate limiting
pass
📊 Monitoring and Analytics¶
1. Performance Monitoring¶
# Performance monitoring
import time
from functools import wraps
def monitor_performance(f):
@wraps(f)
def decorated_function(*args, **kwargs):
start_time = time.time()
result = f(*args, **kwargs)
duration = time.time() - start_time
# Log performance metrics
app.logger.info(f"API call {f.__name__} took {duration:.2f}s")
return result
return decorated_function
@app.route('/api/costs')
@monitor_performance
@login_required
def get_costs():
# API endpoint with performance monitoring
pass
2. Error Tracking¶
# Error tracking
@app.errorhandler(Exception)
def handle_error(error):
app.logger.error(f"Unhandled error: {error}")
return jsonify({
'error': 'Internal server error',
'message': str(error)
}), 500
3. Usage Analytics¶
# Usage analytics
@app.before_request
def track_usage():
if request.endpoint:
# Track API usage
track_api_usage(request.endpoint, request.method)
🚀 Deployment¶
1. Production Deployment¶
# Install production dependencies
pip install gunicorn
# Set environment variables
export FLASK_ENV=production
export SECRET_KEY=your-secret-key
# Start with gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 web.app:app
2. Docker Deployment¶
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "web.app:app"]
3. Kubernetes Deployment¶
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: finops-dashboard
spec:
replicas: 3
selector:
matchLabels:
app: finops-dashboard
template:
metadata:
labels:
app: finops-dashboard
spec:
containers:
- name: finops-dashboard
image: finops-dashboard:latest
ports:
- containerPort: 5000
env:
- name: FLASK_ENV
value: "production"
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: finops-secrets
key: secret-key
🔧 Troubleshooting¶
1. Common Issues¶
Dashboard Not Loading¶
# Check if Flask app is running
curl http://localhost:5000
# Check logs
tail -f logs/finops.log
# Check configuration
python cli.py validate-config
Authentication Issues¶
# Reset admin password
python -c "
from werkzeug.security import generate_password_hash
print('New password hash:', generate_password_hash('newpassword'))
"
# Check user database
python -c "
from web.app import users
for username, user in users.items():
print(f'{username}: {user.id}')
"
Performance Issues¶
# Check resource usage
python cli.py health
# Monitor performance
python cli.py metrics
# Optimize cache
python cli.py cleanup --cache
2. Debug Mode¶
# Enable debug mode
export FLASK_ENV=development
export FLASK_DEBUG=1
# Start with debug
python -m web.app
3. Log Analysis¶
# View application logs
tail -f logs/finops.log
# View error logs
tail -f logs/error.log
# View access logs
tail -f logs/access.log
📈 Performance Optimization¶
1. Caching¶
# Redis caching
import redis
from functools import wraps
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def cache_result(ttl=300):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = f"{f.__name__}:{hash(str(args) + str(kwargs))}"
result = redis_client.get(cache_key)
if result is None:
result = f(*args, **kwargs)
redis_client.setex(cache_key, ttl, result)
return result
return decorated_function
return decorator
@app.route('/api/costs')
@cache_result(ttl=300) # Cache for 5 minutes
@login_required
def get_costs():
# API endpoint with caching
pass
2. Database Optimization¶
# Database connection pooling
from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool
engine = create_engine(
'postgresql://user:pass@localhost/finops',
poolclass=QueuePool,
pool_size=10,
max_overflow=20,
pool_pre_ping=True
)
3. CDN Integration¶
<!-- CDN for static assets -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
🎯 Best Practices¶
1. Security¶
- Use HTTPS in production
- Implement proper authentication
- Set up rate limiting
- Regular security updates
- Input validation
2. Performance¶
- Enable caching
- Optimize database queries
- Use CDN for static assets
- Monitor resource usage
- Implement lazy loading
3. Monitoring¶
- Set up health checks
- Monitor error rates
- Track performance metrics
- Set up alerts
- Regular backups
4. Maintenance¶
- Regular updates
- Security patches
- Performance tuning
- Log rotation
- Database maintenance
Need help with the dashboard? Check our Tutorial Guide or open an issue.