aboutsummaryrefslogtreecommitdiff
path: root/telemetry/server/main.go
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2025-06-28 14:11:55 -0700
committerGitHub <noreply@github.com>2025-06-28 14:11:55 -0700
commita1aab8a083111dd9357c7f35397fdf610f23cb6d (patch)
tree66b56b09bec60cd1962236b7aad43a37011450b9 /telemetry/server/main.go
parent29892c43ff95ad957c0f64ad5cd11e0d43e616e2 (diff)
downloadseaweedfs-a1aab8a083111dd9357c7f35397fdf610f23cb6d.tar.xz
seaweedfs-a1aab8a083111dd9357c7f35397fdf610f23cb6d.zip
add telemetry (#6926)
* add telemetry * fix go mod * add default telemetry server url * Update README.md * replace with broker count instead of s3 count * Update telemetry.pb.go * github action to deploy
Diffstat (limited to 'telemetry/server/main.go')
-rw-r--r--telemetry/server/main.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/telemetry/server/main.go b/telemetry/server/main.go
new file mode 100644
index 000000000..6cbae05c7
--- /dev/null
+++ b/telemetry/server/main.go
@@ -0,0 +1,111 @@
+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)
+ }
+ }
+}