-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.go
108 lines (102 loc) · 3.3 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"flag"
"fmt"
"os"
"runtime"
"slices"
cache "github.com/Code-Hex/go-generics-cache"
"github.com/Code-Hex/go-generics-cache/policy/lru"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
myhttp "github.com/tedpearson/ForecastMetrics/v3/http"
"github.com/tedpearson/ForecastMetrics/v3/source"
)
var (
version = "development"
goVersion = "unknown"
buildDate = "unknown"
)
func main() {
// parse flags
configFile := flag.String("config", "forecastmetrics.yaml", "Config file")
locationsFile := flag.String("locations", "locations.yaml", "Locations file")
versionFlag := flag.Bool("v", false, "Show version and exit")
flag.Parse()
fmt.Printf("ForecastMetrics version %s built on %s with %s\n", version, buildDate, goVersion)
if *versionFlag {
os.Exit(0)
}
configService := NewConfigService(*configFile, *locationsFile)
config := configService.Config
locationService := LocationService{
AzureSharedKey: config.AzureSharedKey,
cache: cache.New(cache.AsLRU[string, LocationResult](lru.WithCapacity(200))),
}
forecasters := MakeForecasters(config.Sources.Enabled, config.HttpCacheDir, config.Sources.VisualCrossing.Key)
c := influxdb2.NewClient(config.InfluxDB.Host, config.InfluxDB.AuthToken)
writeApi := c.WriteAPIBlocking(config.InfluxDB.Org, config.InfluxDB.Bucket)
metricUpdater := MetricUpdater{
writeApi: writeApi,
overwrite: config.OverwriteData,
weatherMeasurement: config.ForecastMeasurementName,
astroMeasurement: config.AstronomyMeasurementName,
precipProbability: config.PrecipProbability,
}
scheduler := Scheduler{
ConfigService: configService,
MetricUpdater: metricUpdater,
Forecasters: forecasters,
}
scheduler.Start()
if config.ServerConfig.Port == 0 {
// no port specified, keep other goroutines running
runtime.Goexit()
} else {
// only start server if port is specified
dispatcher := NewDispatcher(forecasters, configService, scheduler, config.AdHocCacheEntries)
promConverter := PromConverter{
ForecastMeasurementName: config.ForecastMeasurementName,
AstronomyMeasurementName: config.AstronomyMeasurementName,
PrecipProbability: config.PrecipProbability,
}
server := Server{
LocationService: locationService,
Dispatcher: dispatcher,
PromConverter: promConverter,
AuthToken: config.InfluxDB.AuthToken,
AllowedMetricNames: []string{
config.ForecastMeasurementName,
config.AstronomyMeasurementName,
"accumulated_precip",
},
}
server.Start(config.ServerConfig)
}
}
// MakeForecasters creates the forecasters with an exponential backoff retrying http client.
// Only enabled forecasters are returned.
func MakeForecasters(enabled []string, cacheDir string, vcKey string) map[string]source.Forecaster {
// create retryer
client := httpcache.NewTransport(diskcache.New(cacheDir)).Client()
retryer := myhttp.Retryer{
Client: client,
}
forecasters := map[string]source.Forecaster{
"nws": &source.NWS{
Retryer: retryer,
},
"visualcrossing": &source.VisualCrossing{
Retryer: retryer,
Key: vcKey,
},
}
// only return enabled forecasters
for name := range forecasters {
if !slices.Contains(enabled, name) {
delete(forecasters, name)
}
}
return forecasters
}