package main import ( "log" "net/http" "os" "os/signal" "syscall" apiv1 "git.ar21.de/yolokube/country-geo-locations/api/v1" "git.ar21.de/yolokube/country-geo-locations/internal/cache" "git.ar21.de/yolokube/country-geo-locations/internal/cmd" csvimporter "git.ar21.de/yolokube/country-geo-locations/internal/csv_importer" "git.ar21.de/yolokube/country-geo-locations/internal/database" "git.ar21.de/yolokube/country-geo-locations/internal/downloader" "git.ar21.de/yolokube/country-geo-locations/internal/exporter" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/render" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) func main() { cli := cmd.CLI{} queue := exporter.NewRequestDataQueue() appSettings, err := cli.Parse() if err != nil { log.Fatal(err) } handleGracefulShutdown() exporterMiddleware := exporter.NewMiddleware(queue) r := chi.NewRouter() r.Use(middleware.RequestID) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(exporterMiddleware) r.Use(render.SetContentType(render.ContentTypeJSON)) ctx := downloader.NewContext(appSettings.DataFile, appSettings.DataURL) if !ctx.FileExists() { if downloadErr := ctx.Download(); downloadErr != nil { log.Fatal(downloadErr) } log.Printf("saved file to %s\n", ctx.Filename) } cache := cache.NewCache(appSettings.CacheTTL) db, err := database.NewDatabase(appSettings) if err != nil { log.Fatal("database creation failed", err) } if appSettings.EnableExporter { go func() { err = enableExporter(appSettings, cache, db, queue) if err != nil { log.Panic(err) } }() log.Println("prometheus exporter started at", appSettings.ExporterAddress) } log.Println("importing data from file", appSettings.DataFile) err = csvimporter.ImportCSV(appSettings.DataFile, db) if err != nil { log.Fatal("data Import from file failed", err) } log.Println("imported data from file successful") lh := apiv1.NewLocationHandler(cache, db) r.Mount("/api/v1", apiv1.NewRouter(lh)) server := &http.Server{ Addr: appSettings.ServerAddress, Handler: r, ReadHeaderTimeout: appSettings.ReadHeaderTimeout, } log.Println("starting server at", server.Addr) if err = server.ListenAndServe(); err != nil { log.Panic(err) } } func enableExporter( settings *cmd.AppSettings, cache *cache.Cache, db *database.Database, queue *exporter.RequestDataQueue, ) error { prometheus.MustRegister(exporter.NewCollector(settings, cache, db, queue)) metricsServer := &http.Server{ Addr: settings.ExporterAddress, Handler: promhttp.Handler(), ReadHeaderTimeout: settings.ReadHeaderTimeout, } return metricsServer.ListenAndServe() } func handleGracefulShutdown() { var signals = make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT) go func() { sig := <-signals log.Printf("caught signal: %+v", sig) os.Exit(0) }() }