package main import ( "context" "log/slog" "os" "os/signal" "sync" "syscall" "time" ) var hostname string func init() { var err error hostname, err = os.Hostname() if err != nil { hostname = "unknown" } } func main() { cfg, err := LoadConfig() if err != nil { slog.Error("error loading configuration", "error", err) os.Exit(1) } es, err := NewElasticsearchClient(cfg.Elasticsearch) if err != nil { slog.Error("elasticsearch client error", "error", err) os.Exit(1) } if err := TestElasticsearchConnection(es); err != nil { slog.Error("elasticsearch connection test failed", "error", err) os.Exit(1) } slog.Info("TIXEL System Monitor started - Elasticsearch connection successful") logChan := make(chan LogEntry, 1000) ctx, cancel := context.WithCancel(context.Background()) defer cancel() var wg sync.WaitGroup for _, service := range cfg.Services { if !service.Enabled { slog.Info("Service deactivated, skipping...", "service", service.Name) continue } wg.Add(1) go func(s ServiceConfig) { defer wg.Done() monitor := NewServiceMonitor(s) if err := monitor.Start(ctx, logChan); err != nil { slog.Error("error watching service", "service", s.Name, "error", err) } }(service) slog.Info("started watching Service-Log", "service", service.Name) } for _, tool := range cfg.Tools { if !tool.Enabled { slog.Info("Tool is deactivated, skipping...", "tool", tool.Name) continue } wg.Add(1) go func(t ToolConfig) { defer wg.Done() monitor := NewFileMonitor(t) if err := monitor.Start(ctx, logChan); err != nil { slog.Error("error watching", "tool", t.Name, "error", err) } }(tool) slog.Info("started watching logs", "tool", tool.Name, "file", tool.LogFile) } if cfg.SystemMetrics.Enabled { wg.Add(1) go func() { defer wg.Done() collector := NewSystemMetricsCollector(cfg.SystemMetrics, cfg.PollIntervalSeconds) collector.Start(ctx, es, cfg.Elasticsearch.Index) }() slog.Info("Started collecting System-Metrics") } wg.Add(1) go func() { defer wg.Done() processor := NewLogProcessor(es, cfg.Elasticsearch.Index) processor.Start(ctx, logChan) }() if cfg.WebService.Enabled { wg.Add(1) go func() { defer wg.Done() webService := NewWebService(cfg, es) if err := webService.Start(ctx); err != nil { slog.Error("web service error", "error", err) } }() slog.Info("Web service started", "host", cfg.WebService.Host, "port", cfg.WebService.Port) } sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) <-sigCh slog.Info("Shutdown-Signal received, stopping threads...") cancel() close(logChan) done := make(chan struct{}) go func() { wg.Wait() close(done) }() select { case <-done: slog.Info("All threads closed") case <-time.After(10 * time.Second): slog.Info("Shutdown-Timeout reached, force quitting") } slog.Info("Program stopped") }