add viper configuration & logger

This commit is contained in:
gilex-dev 2023-09-01 23:42:19 +02:00
parent 911df36eb2
commit 422ee93b44
4 changed files with 103 additions and 41 deletions

3
.YetAnotherToDoList.yaml Normal file
View File

@ -0,0 +1,3 @@
log_file: "YetAnotherToDoList.log"
log_UTC: false
port: 4242

View File

@ -18,24 +18,26 @@ package cmd
import ( import (
"fmt" "fmt"
"log"
"os" "os"
"path/filepath"
"strings"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var cfgFile string var cfgFile string
var logger *log.Logger
// rootCmd represents the base command when called without any subcommands // rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "YetAnotherToDoList", Use: "YetAnotherToDoList",
Short: "A brief description of your application", Short: "A simple To Do List Web Application with Go backend, Vue.js frontend and a GraphQL API",
Long: `A longer description that spans multiple lines and likely contains Long: `YetAnotherToDoList 2023 by gilex-dev
examples and usage of using your application. For example: A simple To Do List Web Application with Go backend, Vue.js frontend and a GraphQL API
`,
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
// Uncomment the following line if your bare application // Uncomment the following line if your bare application
// has an action associated with it: // has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { }, // Run: func(cmd *cobra.Command, args []string) { },
@ -51,17 +53,18 @@ func Execute() {
} }
func init() { func init() {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig, initLog)
// Here you will define your flags and configuration settings. // Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here, // Cobra supports persistent flags, which, if defined here,
// will be global for your application. // will be global for your application.
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.YetAnotherToDoList.yaml)") rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.YetAnotherToDoList.yaml)")
rootCmd.PersistentFlags().String("log_file", "", "Path to log file")
// Cobra also supports local flags, which will only run // Cobra also supports local flags, which will only run
// when this action is called directly. // when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") // rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
} }
// initConfig reads in config file and ENV variables if set. // initConfig reads in config file and ENV variables if set.
@ -74,8 +77,13 @@ func initConfig() {
home, err := os.UserHomeDir() home, err := os.UserHomeDir()
cobra.CheckErr(err) cobra.CheckErr(err)
wd, err := os.Getwd()
cobra.CheckErr(err)
// Search config in home directory with name ".YetAnotherToDoList" (without extension). // Search config in home directory with name ".YetAnotherToDoList" (without extension).
viper.AddConfigPath(home) viper.AddConfigPath(home)
// Search config in working directory with name ".YetAnotherToDoList" (without extension).
viper.AddConfigPath(wd)
viper.SetConfigType("yaml") viper.SetConfigType("yaml")
viper.SetConfigName(".YetAnotherToDoList") viper.SetConfigName(".YetAnotherToDoList")
} }
@ -85,5 +93,64 @@ func initConfig() {
// If a config file is found, read it in. // If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil { if err := viper.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
} else {
fmt.Fprintln(os.Stderr, "Unable to read in", viper.ConfigFileUsed(), err)
} }
} }
func initLog() {
var utc = 0
var time_zone_use, time_zone_alt string
time_zone_local, _ := time.Now().Zone()
time_zone_offset := strings.Split(time.Now().In(time.Local).String(), " ")[2]
if viper.GetBool("log_UTC") {
utc = log.LUTC
time_zone_use = "UTC"
time_zone_alt = time_zone_local
time_zone_offset_rune := []rune(time_zone_offset)
if time_zone_offset_rune[0] == '+' {
time_zone_offset_rune[0] = '-'
}
time_zone_offset = string(time_zone_offset_rune)
} else {
time_zone_use = time_zone_local
time_zone_alt = "UTC"
}
logger_flags := log.Ldate | log.Ltime | utc
logger = log.New(os.Stdout, "", logger_flags)
if err := viper.BindPFlag("log_file", rootCmd.Flags().Lookup("log_file")); err != nil {
fmt.Println("Unable to bind flag:", err)
}
if viper.GetString("log_file") != "" {
log_path, err := filepath.Abs(viper.GetString("log_file"))
logger.SetOutput(os.Stdout)
if err != nil {
logger.Println("Invalid path for log file", log_path)
}
log_file, err := os.OpenFile(log_path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
fmt.Println("Failed to write to log file:", err)
} else {
logger.Println("Switching to log file", log_path)
logger.SetOutput(log_file)
}
}
logger.SetFlags(0)
logger.Println()
logger.SetFlags(logger_flags)
logger.Printf("Started YetAnotherToDoList with pid: %v\n", os.Getpid())
logger.Printf("Using %v (%v %v) in logs", time_zone_use, time_zone_alt, time_zone_offset)
}

View File

@ -1,36 +1,33 @@
/* /*
YetAnotherToDoList Copyright © 2023 NAME HERE <EMAIL ADDRESS>
Copyright © 2023 gilex-dev gilex-dev@proton.me
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package cmd package cmd
import ( import (
"fmt" "fmt"
"github.com/spf13/cobra"
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/server" "somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// serverCmd represents the server command // serverCmd represents the server command
var serverCmd = &cobra.Command{ var serverCmd = &cobra.Command{
Use: "server", Use: "server",
Short: "Start web server", Short: "Start the http server",
Long: `Start the web server with a GraphQL playground`, Long: ``,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fmt.Println("server called")
server.StartServer() if err := viper.BindPFlag("debug", cmd.Flags().Lookup("debug")); err != nil {
fmt.Println("Unable to bind flag:", err)
}
if err := viper.BindPFlag("port", cmd.Flags().Lookup("port")); err != nil {
fmt.Println("Unable to bind flag:", err)
}
logger.Println("starting http server...")
server.StartServer(logger, viper.GetInt("port"))
}, },
} }
@ -46,4 +43,6 @@ func init() {
// Cobra supports local flags which will only run when this command // Cobra supports local flags which will only run when this command
// is called directly, e.g.: // is called directly, e.g.:
// serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") // serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
serverCmd.Flags().BoolP("debug", "d", false, "Enable debugging")
serverCmd.Flags().IntP("port", "p", 4242, "The port to listen on")
} }

View File

@ -19,26 +19,19 @@ package server
import ( import (
"log" "log"
"net/http" "net/http"
"os" "strconv"
"github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground" "github.com/99designs/gqlgen/graphql/playground"
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph" "somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph"
) )
const defaultPort = "8080" func StartServer(logger *log.Logger, port int) {
func StartServer() {
port := os.Getenv("PORT")
if port == "" {
port = defaultPort
}
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}})) srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
http.Handle("/", playground.Handler("GraphQL playground", "/query")) http.Handle("/", playground.Handler("GraphQL playground", "/api"))
http.Handle("/query", srv)
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) http.Handle("/api", srv)
log.Fatal(http.ListenAndServe(":"+port, nil)) logger.Printf("connect to http://localhost:%v/ for GraphQL playground", port)
logger.Fatal(http.ListenAndServe(":"+strconv.FormatInt(int64(port), 10), nil))
} }