main.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package main
  2. import (
  3. "encoding/json"
  4. "flag"
  5. "fmt"
  6. "log"
  7. "net/http"
  8. "time"
  9. "github.com/prometheus/client_golang/prometheus/promhttp"
  10. "github.com/seaweedfs/seaweedfs/telemetry/server/api"
  11. "github.com/seaweedfs/seaweedfs/telemetry/server/dashboard"
  12. "github.com/seaweedfs/seaweedfs/telemetry/server/storage"
  13. )
  14. var (
  15. port = flag.Int("port", 8080, "HTTP server port")
  16. enableCORS = flag.Bool("cors", true, "Enable CORS for dashboard")
  17. logRequests = flag.Bool("log", true, "Log incoming requests")
  18. enableDashboard = flag.Bool("dashboard", true, "Enable built-in dashboard (optional when using Grafana)")
  19. cleanupInterval = flag.Duration("cleanup", 24*time.Hour, "Cleanup interval for old instances")
  20. maxInstanceAge = flag.Duration("max-age", 30*24*time.Hour, "Maximum age for instances before cleanup")
  21. )
  22. func main() {
  23. flag.Parse()
  24. // Create Prometheus storage instance
  25. store := storage.NewPrometheusStorage()
  26. // Start cleanup routine
  27. go func() {
  28. ticker := time.NewTicker(*cleanupInterval)
  29. defer ticker.Stop()
  30. for range ticker.C {
  31. store.CleanupOldInstances(*maxInstanceAge)
  32. }
  33. }()
  34. // Setup HTTP handlers
  35. mux := http.NewServeMux()
  36. // Prometheus metrics endpoint
  37. mux.Handle("/metrics", promhttp.Handler())
  38. // API endpoints
  39. apiHandler := api.NewHandler(store)
  40. mux.HandleFunc("/api/collect", corsMiddleware(logMiddleware(apiHandler.CollectTelemetry)))
  41. mux.HandleFunc("/api/stats", corsMiddleware(logMiddleware(apiHandler.GetStats)))
  42. mux.HandleFunc("/api/instances", corsMiddleware(logMiddleware(apiHandler.GetInstances)))
  43. mux.HandleFunc("/api/metrics", corsMiddleware(logMiddleware(apiHandler.GetMetrics)))
  44. // Dashboard (optional)
  45. if *enableDashboard {
  46. dashboardHandler := dashboard.NewHandler()
  47. mux.HandleFunc("/", corsMiddleware(dashboardHandler.ServeIndex))
  48. mux.HandleFunc("/dashboard", corsMiddleware(dashboardHandler.ServeIndex))
  49. mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
  50. }
  51. // Health check
  52. mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
  53. w.Header().Set("Content-Type", "application/json")
  54. json.NewEncoder(w).Encode(map[string]string{
  55. "status": "ok",
  56. "time": time.Now().UTC().Format(time.RFC3339),
  57. })
  58. })
  59. addr := fmt.Sprintf(":%d", *port)
  60. log.Printf("Starting telemetry server on %s", addr)
  61. log.Printf("Prometheus metrics: http://localhost%s/metrics", addr)
  62. if *enableDashboard {
  63. log.Printf("Dashboard: http://localhost%s/dashboard", addr)
  64. }
  65. log.Printf("Cleanup interval: %v, Max instance age: %v", *cleanupInterval, *maxInstanceAge)
  66. if err := http.ListenAndServe(addr, mux); err != nil {
  67. log.Fatalf("Server failed: %v", err)
  68. }
  69. }
  70. func corsMiddleware(next http.HandlerFunc) http.HandlerFunc {
  71. return func(w http.ResponseWriter, r *http.Request) {
  72. if *enableCORS {
  73. w.Header().Set("Access-Control-Allow-Origin", "*")
  74. w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
  75. w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
  76. }
  77. if r.Method == "OPTIONS" {
  78. w.WriteHeader(http.StatusOK)
  79. return
  80. }
  81. next(w, r)
  82. }
  83. }
  84. func logMiddleware(next http.HandlerFunc) http.HandlerFunc {
  85. return func(w http.ResponseWriter, r *http.Request) {
  86. if *logRequests {
  87. start := time.Now()
  88. next(w, r)
  89. log.Printf("%s %s %s %v", r.Method, r.URL.Path, r.RemoteAddr, time.Since(start))
  90. } else {
  91. next(w, r)
  92. }
  93. }
  94. }