You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							111 lines
						
					
					
						
							3.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							111 lines
						
					
					
						
							3.4 KiB
						
					
					
				| package main | |
| 
 | |
| import ( | |
| 	"encoding/json" | |
| 	"flag" | |
| 	"fmt" | |
| 	"log" | |
| 	"net/http" | |
| 	"time" | |
| 
 | |
| 	"github.com/prometheus/client_golang/prometheus/promhttp" | |
| 	"github.com/seaweedfs/seaweedfs/telemetry/server/api" | |
| 	"github.com/seaweedfs/seaweedfs/telemetry/server/dashboard" | |
| 	"github.com/seaweedfs/seaweedfs/telemetry/server/storage" | |
| ) | |
| 
 | |
| var ( | |
| 	port            = flag.Int("port", 8080, "HTTP server port") | |
| 	enableCORS      = flag.Bool("cors", true, "Enable CORS for dashboard") | |
| 	logRequests     = flag.Bool("log", true, "Log incoming requests") | |
| 	enableDashboard = flag.Bool("dashboard", true, "Enable built-in dashboard (optional when using Grafana)") | |
| 	cleanupInterval = flag.Duration("cleanup", 24*time.Hour, "Cleanup interval for old instances") | |
| 	maxInstanceAge  = flag.Duration("max-age", 30*24*time.Hour, "Maximum age for instances before cleanup") | |
| ) | |
| 
 | |
| func main() { | |
| 	flag.Parse() | |
| 
 | |
| 	// Create Prometheus storage instance | |
| 	store := storage.NewPrometheusStorage() | |
| 
 | |
| 	// Start cleanup routine | |
| 	go func() { | |
| 		ticker := time.NewTicker(*cleanupInterval) | |
| 		defer ticker.Stop() | |
| 		for range ticker.C { | |
| 			store.CleanupOldInstances(*maxInstanceAge) | |
| 		} | |
| 	}() | |
| 
 | |
| 	// Setup HTTP handlers | |
| 	mux := http.NewServeMux() | |
| 
 | |
| 	// Prometheus metrics endpoint | |
| 	mux.Handle("/metrics", promhttp.Handler()) | |
| 
 | |
| 	// API endpoints | |
| 	apiHandler := api.NewHandler(store) | |
| 	mux.HandleFunc("/api/collect", corsMiddleware(logMiddleware(apiHandler.CollectTelemetry))) | |
| 	mux.HandleFunc("/api/stats", corsMiddleware(logMiddleware(apiHandler.GetStats))) | |
| 	mux.HandleFunc("/api/instances", corsMiddleware(logMiddleware(apiHandler.GetInstances))) | |
| 	mux.HandleFunc("/api/metrics", corsMiddleware(logMiddleware(apiHandler.GetMetrics))) | |
| 
 | |
| 	// Dashboard (optional) | |
| 	if *enableDashboard { | |
| 		dashboardHandler := dashboard.NewHandler() | |
| 		mux.HandleFunc("/", corsMiddleware(dashboardHandler.ServeIndex)) | |
| 		mux.HandleFunc("/dashboard", corsMiddleware(dashboardHandler.ServeIndex)) | |
| 		mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static")))) | |
| 	} | |
| 
 | |
| 	// Health check | |
| 	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { | |
| 		w.Header().Set("Content-Type", "application/json") | |
| 		json.NewEncoder(w).Encode(map[string]string{ | |
| 			"status": "ok", | |
| 			"time":   time.Now().UTC().Format(time.RFC3339), | |
| 		}) | |
| 	}) | |
| 
 | |
| 	addr := fmt.Sprintf(":%d", *port) | |
| 	log.Printf("Starting telemetry server on %s", addr) | |
| 	log.Printf("Prometheus metrics: http://localhost%s/metrics", addr) | |
| 	if *enableDashboard { | |
| 		log.Printf("Dashboard: http://localhost%s/dashboard", addr) | |
| 	} | |
| 	log.Printf("Cleanup interval: %v, Max instance age: %v", *cleanupInterval, *maxInstanceAge) | |
| 
 | |
| 	if err := http.ListenAndServe(addr, mux); err != nil { | |
| 		log.Fatalf("Server failed: %v", err) | |
| 	} | |
| } | |
| 
 | |
| func corsMiddleware(next http.HandlerFunc) http.HandlerFunc { | |
| 	return func(w http.ResponseWriter, r *http.Request) { | |
| 		if *enableCORS { | |
| 			w.Header().Set("Access-Control-Allow-Origin", "*") | |
| 			w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") | |
| 			w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") | |
| 		} | |
| 
 | |
| 		if r.Method == "OPTIONS" { | |
| 			w.WriteHeader(http.StatusOK) | |
| 			return | |
| 		} | |
| 
 | |
| 		next(w, r) | |
| 	} | |
| } | |
| 
 | |
| func logMiddleware(next http.HandlerFunc) http.HandlerFunc { | |
| 	return func(w http.ResponseWriter, r *http.Request) { | |
| 		if *logRequests { | |
| 			start := time.Now() | |
| 			next(w, r) | |
| 			log.Printf("%s %s %s %v", r.Method, r.URL.Path, r.RemoteAddr, time.Since(start)) | |
| 		} else { | |
| 			next(w, r) | |
| 		} | |
| 	} | |
| }
 |