Dashboard Extension
Production-ready health and metrics dashboard extension for Forge v2 with real-time monitoring, data export, and a modern web UI
Dashboard Extension
A production-ready health and metrics dashboard extension for Forge v2 with real-time monitoring, data export, and a modern web UI.
Features
Real-time Monitoring
- WebSocket-based Updates: Live updates of health checks and metrics without page refresh
- Configurable Refresh Intervals: Customize how often data is collected and updated
- Connection Status Indicator: Visual indicator showing WebSocket connection status
Health Monitoring
- Service Health Checks: Monitor all registered services with detailed status information
- Overall Health Status: Aggregated health status across all services
- Health History: Track health status changes over time
- Detailed Health Reports: View specific health check results and error messages
Metrics Visualization
- Interactive Charts: Visualize data with ApexCharts integration
- Metrics Report: Comprehensive breakdown of all metrics by type
- Historical Trends: View metrics data over time with configurable retention
- Performance Statistics: Track system performance metrics and trends
Modern Web UI
- Responsive Design: Works seamlessly on desktop, tablet, and mobile devices
- Dark Mode Support: Auto, light, and dark theme support with smooth transitions
- Beautiful Interface: Modern design built with Tailwind CSS
- Interactive Components: Clickable service cards, modal dialogs, and tabbed navigation
Data Export
- Multiple Formats: Export dashboard data in JSON, CSV, and Prometheus formats
- Complete Snapshots: Export comprehensive dashboard state for backup or analysis
- Prometheus Integration: Native Prometheus metrics format for monitoring systems
Zero Build Setup
- CDN Assets: Uses CDN for all external dependencies (Tailwind CSS, ApexCharts)
- No Compilation: Ready to use without any build process
- Self-contained: All templates and assets embedded in the extension
Installation
The dashboard extension is included in Forge v2. Simply import it:
import "github.com/xraph/forge/extensions/dashboard"Quick Start
Basic Setup
package main
import (
"context"
"log"
"github.com/xraph/forge"
"github.com/xraph/forge/extensions/dashboard"
)
func main() {
// Create Forge app
app := forge.NewApp(forge.AppConfig{
Name: "my-app",
Version: "1.0.0",
Environment: "production",
})
// Register dashboard extension
app.RegisterExtension(dashboard.NewExtension(
dashboard.WithPort(8080),
dashboard.WithTitle("My App Dashboard"),
))
// Start app
ctx := context.Background()
if err := app.Start(ctx); err != nil {
log.Fatal(err)
}
// Dashboard available at http://localhost:8080/dashboard
select {}
}With Multiple Services
package main
import (
"context"
"log"
"time"
"github.com/xraph/forge"
"github.com/xraph/forge/extensions/cache"
"github.com/xraph/forge/extensions/dashboard"
"github.com/xraph/forge/extensions/database"
)
func main() {
app := forge.NewApp(forge.AppConfig{
Name: "multi-service-app",
Version: "1.0.0",
Environment: "production",
})
// Register services to monitor
app.RegisterExtension(cache.NewExtension(
cache.WithDriver("redis"),
cache.WithDefaultTTL(5*time.Minute),
))
app.RegisterExtension(database.NewExtension(
database.WithDriver("postgres"),
database.WithDSN("postgres://user:pass@localhost/db"),
))
// Register dashboard to monitor all services
app.RegisterExtension(dashboard.NewExtension(
dashboard.WithPort(8080),
dashboard.WithBasePath("/admin/dashboard"),
dashboard.WithTitle("Multi-Service Dashboard"),
dashboard.WithTheme("dark"),
dashboard.WithRealtime(true),
dashboard.WithRefreshInterval(15*time.Second),
dashboard.WithExport(true),
dashboard.WithHistoryDuration(2*time.Hour),
))
ctx := context.Background()
if err := app.Start(ctx); err != nil {
log.Fatal(err)
}
log.Println("Dashboard available at: http://localhost:8080/admin/dashboard")
select {}
}Configuration
Programmatic Configuration
app.RegisterExtension(dashboard.NewExtension(
// Server settings
dashboard.WithPort(8080), // Server port
dashboard.WithBasePath("/dashboard"), // Base URL path
dashboard.WithReadTimeout(30*time.Second), // HTTP read timeout
dashboard.WithWriteTimeout(30*time.Second), // HTTP write timeout
dashboard.WithShutdownTimeout(10*time.Second), // Graceful shutdown timeout
// UI settings
dashboard.WithTitle("My Dashboard"), // Dashboard title
dashboard.WithTheme("auto"), // Theme: auto, light, dark
dashboard.WithMetaTags(map[string]string{ // Custom meta tags
"description": "Application monitoring dashboard",
"keywords": "monitoring, health, metrics",
}),
// Features
dashboard.WithRealtime(true), // Enable WebSocket updates
dashboard.WithExport(true), // Enable data export
dashboard.WithExportFormats([]string{ // Export formats
"json", "csv", "prometheus",
}),
// Data collection
dashboard.WithRefreshInterval(30*time.Second), // Data refresh interval
dashboard.WithHistoryDuration(1*time.Hour), // Data retention period
dashboard.WithMaxDataPoints(1000), // Max historical points
// Configuration loading
dashboard.WithRequireConfig(false), // Require config file
))YAML Configuration
Create a config.yaml:
extensions:
dashboard:
# Server settings
port: 8080
base_path: "/dashboard"
read_timeout: 30s
write_timeout: 30s
shutdown_timeout: 10s
# Features
enable_auth: false
enable_realtime: true
enable_export: true
export_formats:
- json
- csv
- prometheus
# Data collection
refresh_interval: 30s
history_duration: 1h
max_data_points: 1000
# UI settings
theme: "auto" # auto, light, dark
title: "My Application Dashboard"
meta_tags:
description: "Application monitoring dashboard"
keywords: "monitoring, health, metrics"
# Configuration
require_config: falseLoad configuration:
app.RegisterExtension(dashboard.NewExtension(
dashboard.WithRequireConfig(true),
))Environment Variables
# Server settings
FORGE_DASHBOARD_PORT=8080
FORGE_DASHBOARD_BASE_PATH="/dashboard"
# Features
FORGE_DASHBOARD_ENABLE_REALTIME=true
FORGE_DASHBOARD_ENABLE_EXPORT=true
# Data collection
FORGE_DASHBOARD_REFRESH_INTERVAL=30s
FORGE_DASHBOARD_HISTORY_DURATION=1h
FORGE_DASHBOARD_MAX_DATA_POINTS=1000
# UI settings
FORGE_DASHBOARD_THEME=auto
FORGE_DASHBOARD_TITLE="My Dashboard"UI Features
Overview Tab
The main dashboard view provides:
Summary Cards
- Overall Health: Aggregated health status with visual indicator
- Services: Count of healthy vs total services
- Metrics: Total number of tracked metrics
- Uptime: System uptime since startup
Interactive Charts
- Health Trends: Historical health status over time
- Service Count: Number of services tracked over time
- Metrics Growth: Metrics count trends
Health Checks Table
- Service Status: Real-time status of all services
- Last Check: Timestamp of last health check
- Duration: Time taken for health check
- Messages: Detailed health check messages
Services Grid
- Service Cards: Clickable cards for each registered service
- Status Indicators: Visual status indicators (healthy, degraded, unhealthy)
- Service Types: Display service type and category
Export Options
- One-click Export: Export data in JSON, CSV, or Prometheus format
- Complete Snapshots: Full dashboard state export
Service Detail Modal
Click any service card to open a detailed modal with:
- Service Information: Name, type, and current status
- Health Details: Last check time, duration, and messages
- Service Metrics: Metrics specific to the selected service
- Historical Data: Service-specific historical information
Metrics Report Tab
Comprehensive metrics analysis:
Statistics Overview
- Total Metrics: Count of all tracked metrics
- Type Breakdown: Counters, gauges, histograms, timers
- Active Collectors: Number of active metric collectors
Type Distribution Chart
- Pie Chart: Visual breakdown of metric types
- Interactive: Hover for detailed information
- Theme-aware: Adapts to light/dark mode
Active Collectors Table
- Collector Status: Status of all registered metrics collectors
- Collection Info: Last collection time and status
- Metrics Count: Number of metrics per collector
Top Metrics List
- Current Values: Real-time values of top 20 metrics
- Metric Names: Full metric names and types
- Value Formatting: Appropriate formatting for different metric types
Theme Support
Dark Mode
- Full Support: Complete dark mode for all UI elements
- Smooth Transitions: Animated color transitions between themes
- Chart Integration: Charts automatically adapt to theme changes
Theme Toggle
- Persistent Preference: Theme choice saved in localStorage
- Auto Detection: Respects system preference if not explicitly set
- Visual Indicator: Sun/moon icon shows current theme
Responsive Design
- Mobile Optimized: Works seamlessly on all screen sizes
- Touch Friendly: Optimized for touch interactions
- Adaptive Layout: Layout adjusts based on screen size
API Endpoints
Overview Data
GET /dashboard/api/overviewReturns overview of system health, services, metrics, and uptime.
Response:
{
"timestamp": "2025-01-22T10:30:00Z",
"overall_health": "healthy",
"total_services": 5,
"healthy_services": 5,
"total_metrics": 42,
"uptime": 3600000000000,
"version": "1.0.0",
"environment": "production"
}Health Checks
GET /dashboard/api/healthReturns detailed health check results for all services.
Response:
{
"timestamp": "2025-01-22T10:30:00Z",
"overall_status": "healthy",
"services": {
"cache": {
"status": "healthy",
"message": "Cache is operational",
"duration": 1500000,
"last_check": "2025-01-22T10:30:00Z"
},
"database": {
"status": "healthy",
"message": "Database connection active",
"duration": 2300000,
"last_check": "2025-01-22T10:30:00Z"
}
}
}Metrics
GET /dashboard/api/metricsReturns all current metrics.
Response:
{
"timestamp": "2025-01-22T10:30:00Z",
"metrics": {
"http_requests_total": 1234,
"http_request_duration_seconds": 0.045,
"memory_usage_bytes": 67108864,
"goroutines_count": 42
}
}Services
GET /dashboard/api/servicesReturns list of registered services.
Response:
[
{
"name": "cache",
"type": "cache",
"status": "healthy",
"last_check": "2025-01-22T10:30:00Z"
},
{
"name": "database",
"type": "database",
"status": "healthy",
"last_check": "2025-01-22T10:30:00Z"
}
]Service Detail
GET /dashboard/api/service-detail?name=cacheReturns detailed information about a specific service.
Response:
{
"name": "cache",
"type": "cache",
"status": "healthy",
"last_check": "2025-01-22T10:30:00Z",
"health": {
"status": "healthy",
"message": "Cache is operational",
"duration": 1500000
},
"metrics": {
"cache_hits_total": 1000,
"cache_misses_total": 50,
"cache_size_bytes": 1048576
}
}Metrics Report
GET /dashboard/api/metrics-reportReturns comprehensive metrics report.
Response:
{
"timestamp": "2025-01-22T10:30:00Z",
"statistics": {
"total_metrics": 42,
"counters": 15,
"gauges": 20,
"histograms": 5,
"timers": 2
},
"collectors": [
{
"name": "http_collector",
"status": "active",
"metrics_count": 10,
"last_collection": "2025-01-22T10:30:00Z"
}
],
"top_metrics": [
{
"name": "http_requests_total",
"type": "counter",
"value": 1234
}
]
}Historical Data
GET /dashboard/api/historyReturns time-series historical data.
Response:
{
"overview": [
{
"timestamp": "2025-01-22T10:25:00Z",
"overall_health": "healthy",
"total_services": 5,
"healthy_services": 5
}
],
"health": [
{
"timestamp": "2025-01-22T10:25:00Z",
"services": {
"cache": "healthy",
"database": "healthy"
}
}
]
}Data Export
JSON Export
GET /dashboard/export/jsonExports complete dashboard snapshot as JSON file.
Features:
- Complete system state
- All metrics and health data
- Historical information
- Downloadable file format
CSV Export
GET /dashboard/export/csvExports dashboard data as CSV file.
Features:
- Tabular format for spreadsheet analysis
- Separate sections for overview, health, and services
- Human-readable format
Prometheus Metrics
GET /dashboard/export/prometheusExports metrics in Prometheus text format for scraping.
Features:
- Standard Prometheus format
- Compatible with Prometheus monitoring
- Includes metric metadata
WebSocket API
Real-time Updates
Connect to real-time updates:
const ws = new WebSocket('ws://localhost:8080/dashboard/ws');
ws.onopen = () => {
console.log('Connected to dashboard');
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'overview':
console.log('Overview update:', message.data);
updateOverviewUI(message.data);
break;
case 'health':
console.log('Health update:', message.data);
updateHealthUI(message.data);
break;
case 'metrics':
console.log('Metrics update:', message.data);
updateMetricsUI(message.data);
break;
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('Disconnected from dashboard');
};Message Types
Ping/Pong
// Send ping to keep connection alive
ws.send(JSON.stringify({ type: 'ping' }));
// Server responds with pong
{
"type": "pong",
"timestamp": "2025-01-22T10:30:00Z"
}Data Updates
// Overview data update
{
"type": "overview",
"timestamp": "2025-01-22T10:30:00Z",
"data": {
"overall_health": "healthy",
"total_services": 5,
"healthy_services": 5,
"total_metrics": 42
}
}
// Health data update
{
"type": "health",
"timestamp": "2025-01-22T10:30:00Z",
"data": {
"overall_status": "healthy",
"services": {
"cache": {
"status": "healthy",
"message": "Cache is operational"
}
}
}
}Advanced Usage
Custom Dashboard Server
Access the dashboard server for advanced operations:
dashboard := dashboard.NewExtension()
app.RegisterExtension(dashboard)
// After app starts
server := dashboard.Server()
// Access collector
collector := server.GetCollector()
overview := collector.CollectOverview(ctx)
// Access history
history := server.GetHistory()
data := history.GetAll()
// Check if server is running
if server.IsRunning() {
log.Println("Dashboard server is running")
}Integration with DI Container
The dashboard server is registered in the DI container:
// Resolve dashboard from container
dashboardServer, err := forge.Resolve[*dashboard.DashboardServer](app.Container(), "dashboard")
if err != nil {
log.Fatal(err)
}
// Use dashboard server
collector := dashboardServer.GetCollector()
overview := collector.CollectOverview(ctx)
// Access WebSocket hub
if hub := dashboardServer.GetHub(); hub != nil {
clientCount := hub.ClientCount()
log.Printf("Active WebSocket clients: %d", clientCount)
}Custom Data Collection
// Create custom collector
collector := dashboard.NewDataCollector(
app.HealthManager(),
app.Metrics(),
app.Container(),
app.Logger(),
history,
)
// Collect specific data
overview := collector.CollectOverview(ctx)
health := collector.CollectHealth(ctx)
metrics := collector.CollectMetrics(ctx)
services := collector.CollectServices(ctx)
// Get service detail
serviceDetail := collector.CollectServiceDetail(ctx, "cache")
// Get metrics report
metricsReport := collector.CollectMetricsReport(ctx)Custom WebSocket Broadcasting
// Get dashboard server
dashboardServer, _ := forge.Resolve[*dashboard.DashboardServer](app.Container(), "dashboard")
// Get WebSocket hub
hub := dashboardServer.GetHub()
// Broadcast custom message
customData := map[string]interface{}{
"type": "custom",
"message": "Custom notification",
"data": someData,
}
if err := hub.Broadcast(customData); err != nil {
log.Printf("Failed to broadcast: %v", err)
}Best Practices
Performance Optimization
-
Adjust Refresh Intervals:
dashboard.WithRefreshInterval(60*time.Second) // Reduce frequency for better performance -
Limit Historical Data:
dashboard.WithHistoryDuration(30*time.Minute) // Reduce retention period dashboard.WithMaxDataPoints(500) // Limit data points -
Disable Features if Not Needed:
dashboard.WithRealtime(false) // Disable WebSocket if not needed dashboard.WithExport(false) // Disable export if not needed
Security Considerations
-
Network Access:
// Bind to localhost only in production dashboard.WithPort(8080) // Consider using reverse proxy -
Authentication (when available):
extensions: dashboard: enable_auth: true -
CORS Configuration:
- Default allows all origins for development
- Configure appropriately for production
Monitoring Best Practices
-
Service Health Checks:
- Implement comprehensive health checks in your services
- Include dependency checks (database, cache, external APIs)
- Provide meaningful error messages
-
Metrics Collection:
- Use descriptive metric names
- Include relevant labels/tags
- Monitor key business metrics
-
Dashboard Organization:
- Use meaningful service names
- Group related services
- Monitor critical services first
Deployment Considerations
-
Resource Usage:
- Dashboard uses minimal resources
- WebSocket connections consume memory
- Historical data storage grows over time
-
High Availability:
- Dashboard is stateless (except for historical data)
- Can be deployed behind load balancer
- Historical data is in-memory (consider external storage for persistence)
-
Scaling:
- Multiple dashboard instances can run independently
- WebSocket connections are per-instance
- Consider centralized metrics collection for large deployments
Troubleshooting
Common Issues
Dashboard Not Loading
Symptoms: Dashboard page doesn't load or shows errors
Solutions:
-
Check if the port is available:
netstat -an | grep :8080 -
Verify configuration:
dashboard.WithPort(8080) dashboard.WithBasePath("/dashboard") -
Check application logs for errors
WebSocket Connection Failed
Symptoms: "Connecting..." status never changes to "Live"
Solutions:
-
Verify WebSocket is enabled:
dashboard.WithRealtime(true) -
Check browser console for WebSocket errors
-
Verify firewall/proxy settings allow WebSocket connections
No Data Showing
Symptoms: Dashboard loads but shows no services or metrics
Solutions:
-
Ensure services are registered before dashboard:
app.RegisterExtension(cache.NewExtension()) // Register first app.RegisterExtension(dashboard.NewExtension()) // Register after -
Check if services implement health checks
-
Verify metrics are being collected
Theme Not Working
Symptoms: Theme toggle doesn't change appearance
Solutions:
- Clear browser cache and localStorage
- Check browser console for JavaScript errors
- Verify Tailwind CSS is loading from CDN
Debug Mode
Enable debug logging:
app := forge.NewApp(forge.AppConfig{
LogLevel: "debug",
})Check dashboard-specific logs:
- Extension registration
- Server startup
- WebSocket connections
- Data collection errors
Performance Issues
Slow Dashboard Loading
Solutions:
-
Reduce data collection frequency:
dashboard.WithRefreshInterval(60*time.Second) -
Limit historical data:
dashboard.WithHistoryDuration(15*time.Minute) dashboard.WithMaxDataPoints(100) -
Disable real-time updates:
dashboard.WithRealtime(false)
High Memory Usage
Solutions:
- Reduce historical data retention
- Limit maximum data points
- Monitor WebSocket connection count
Browser Compatibility
Supported Browsers:
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Known Issues:
- WebSocket support required for real-time features
- CSS Grid support required for layout
- JavaScript ES6+ features used
Migration Guide
From v1.x to v2.x
The Dashboard extension has been completely rewritten for v2. Key changes:
-
New Configuration API:
// Old (v1.x) dashboard.New(dashboard.Config{ Port: 8080, }) // New (v2.x) dashboard.NewExtension( dashboard.WithPort(8080), ) -
Enhanced UI: Complete redesign with modern interface
-
WebSocket Support: Real-time updates now available
-
Export Features: New data export capabilities
-
Better Integration: Improved DI container integration
Configuration Migration
# Old configuration (v1.x)
dashboard:
port: 8080
path: "/dashboard"
# New configuration (v2.x)
extensions:
dashboard:
port: 8080
base_path: "/dashboard"
enable_realtime: true
enable_export: trueExamples
See the examples directory for complete working examples:
- Basic Setup: Simple dashboard with minimal configuration
- Multi-Service: Dashboard monitoring multiple services
- Custom Configuration: Advanced configuration examples
- Integration Examples: Integration with other Forge extensions
Contributing
The Dashboard extension is part of the Forge project. Contributions are welcome:
- Bug Reports: Report issues on GitHub
- Feature Requests: Suggest new features
- Pull Requests: Submit improvements
- Documentation: Help improve documentation
License
The Dashboard extension is licensed under the same license as the Forge project.
How is this guide?
Last updated on