mirror of
https://github.com/NotAShelf/watchdog.git
synced 2026-04-25 19:09:58 +00:00
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I0f429ef3345444c0c4bedbc80ee3d5e06a6a6964
140 lines
3.3 KiB
Go
140 lines
3.3 KiB
Go
package watchdog
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
"notashelf.dev/watchdog/internal/config"
|
|
)
|
|
|
|
var (
|
|
cfgFile string
|
|
cfg *config.Config
|
|
version string
|
|
commit string
|
|
buildDate string
|
|
)
|
|
|
|
type versionInfo struct {
|
|
Version string `json:"version"`
|
|
Commit string `json:"commit"`
|
|
BuildDate string `json:"buildDate"`
|
|
}
|
|
|
|
func getVersion() string {
|
|
if version != "" {
|
|
return version
|
|
}
|
|
data, err := os.ReadFile("version.json")
|
|
if err != nil {
|
|
return "dev"
|
|
}
|
|
var v versionInfo
|
|
if err := json.Unmarshal(data, &v); err != nil {
|
|
return "dev"
|
|
}
|
|
if v.Version != "" {
|
|
return v.Version
|
|
}
|
|
return "dev"
|
|
}
|
|
|
|
func getCommit() string {
|
|
if commit != "" {
|
|
return commit
|
|
}
|
|
data, err := os.ReadFile("version.json")
|
|
if err != nil {
|
|
return "none"
|
|
}
|
|
var v versionInfo
|
|
if err := json.Unmarshal(data, &v); err != nil {
|
|
return "none"
|
|
}
|
|
if v.Commit != "" {
|
|
return v.Commit
|
|
}
|
|
return "none"
|
|
}
|
|
|
|
var rootCmd = &cobra.Command{
|
|
Use: "watchdog",
|
|
Short: "Privacy-first web analytics with Prometheus metrics",
|
|
Long: `Watchdog is a lightweight, privacy-first analytics system that aggregates web traffic data.`,
|
|
Version: getVersion() + "\ncommit: " + getCommit(),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return Run(cfg)
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
cobra.OnInitialize(initConfig)
|
|
|
|
rootCmd.PersistentFlags().
|
|
StringVar(&cfgFile, "config", "", "config file (default: config.yaml)")
|
|
rootCmd.PersistentFlags().String("listen-addr", "", "server listen address (overrides config)")
|
|
rootCmd.PersistentFlags().String("metrics-path", "", "metrics endpoint path (overrides config)")
|
|
rootCmd.PersistentFlags().
|
|
String("ingestion-path", "", "ingestion endpoint path (overrides config)")
|
|
|
|
// Bind flags to viper
|
|
viper.BindPFlag("server.listen_addr", rootCmd.PersistentFlags().Lookup("listen-addr"))
|
|
viper.BindPFlag("server.metrics_path", rootCmd.PersistentFlags().Lookup("metrics-path"))
|
|
viper.BindPFlag("server.ingestion_path", rootCmd.PersistentFlags().Lookup("ingestion-path"))
|
|
}
|
|
|
|
func initConfig() {
|
|
if cfgFile != "" {
|
|
// Use config file from the flag
|
|
viper.SetConfigFile(cfgFile)
|
|
} else {
|
|
// Search for config in current directory
|
|
viper.AddConfigPath(".")
|
|
viper.AddConfigPath("/etc/watchdog")
|
|
viper.SetConfigName("config")
|
|
viper.SetConfigType("yaml")
|
|
}
|
|
|
|
// Environment variables
|
|
viper.SetEnvPrefix("WATCHDOG")
|
|
viper.AutomaticEnv()
|
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
|
|
// Read config file
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
|
fmt.Fprintf(
|
|
os.Stderr,
|
|
"Config file not found, using defaults and environment variables\n",
|
|
)
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "Error reading config file: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// Unmarshal into config struct
|
|
cfg = &config.Config{}
|
|
if err := viper.Unmarshal(cfg); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to parse config: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Validate config
|
|
if err := cfg.Validate(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Config validation failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func Main(v, c, bd string) {
|
|
version, commit, buildDate = v, c, bd
|
|
if err := rootCmd.Execute(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|