goatcounter-systemd/di/container.go
2024-09-28 16:20:24 -04:00

137 lines
2.9 KiB
Go

package di
import (
"errors"
"fmt"
"log/slog"
"os"
"strings"
"git.0xdad.com/tblyler/goatcounter-systemd/config"
"git.0xdad.com/tblyler/goatcounter-systemd/goatcounter"
"git.0xdad.com/tblyler/goatcounter-systemd/journald"
)
type Container struct {
config config.Config
journald *journald.Journald
goatcounterMultiSiteClient *goatcounter.MultiSiteClient
closers []func() error
}
func NewContainer() (*Container, error) {
container := &Container{}
sets := []func() error{
container.setSlog,
container.setConfig,
container.setJournald,
container.setGoatcounterMultiSiteClient,
}
for _, set := range sets {
err := set()
if err != nil {
return container, err
}
}
return container, nil
}
func (c *Container) Close() error {
errs := make([]error, 0, len(c.closers))
for _, closer := range c.closers {
errs = append(errs, closer())
}
return errors.Join(errs...)
}
func (c *Container) setSlog() error {
var logLevel slog.Level
switch strings.ToLower(strings.TrimSpace(os.Getenv("LOG_LEVEL"))) {
case "debug":
logLevel = slog.LevelDebug
case "info", "":
logLevel = slog.LevelInfo
case "warn":
logLevel = slog.LevelWarn
case "error":
logLevel = slog.LevelError
default:
return fmt.Errorf("invalid log level: %s", os.Getenv("LOG_LEVEL"))
}
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: logLevel <= slog.LevelDebug,
Level: logLevel,
}))
slog.SetDefault(logger)
slog.SetLogLoggerLevel(logLevel)
return nil
}
func (c *Container) Config() config.Config {
return c.config
}
func (c *Container) setConfig() error {
configPath := os.Getenv("CONFIG_FILE")
if configPath == "" {
configPath = "/etc/goatcounter-systemd/config.json"
}
config, err := config.FromFilePath(configPath)
if err != nil {
return fmt.Errorf("failed to set config: %w", err)
}
c.config = config
return nil
}
func (c *Container) Journald() *journald.Journald {
return c.journald
}
func (c *Container) setJournald() error {
config := c.Config()
journald, err := journald.NewJournald(config.LogIdentifier)
if err != nil {
return fmt.Errorf("failed to set journald: %w", err)
}
c.closers = append(c.closers, journald.Close)
c.journald = journald
return nil
}
func (c *Container) GoatcounterMultiSiteClient() *goatcounter.MultiSiteClient {
return c.goatcounterMultiSiteClient
}
func (c *Container) setGoatcounterMultiSiteClient() error {
config := c.Config()
siteToClient := map[string]goatcounter.SiteClient{}
for _, site := range config.Sites {
client, err := goatcounter.NewClient(site.URL, site.APIKey)
if err != nil {
return fmt.Errorf("failed to create client for site %s: %w", site.URL, err)
}
for _, host := range site.Hosts {
siteToClient[host] = client
}
}
c.goatcounterMultiSiteClient = goatcounter.NewMultiSiteClient(siteToClient, true)
return nil
}