mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-04-17 01:15:54 +02:00
Merge pull request #374 from ClusterCockpit/review_logging
Review logging
This commit is contained in:
commit
96977c6183
@ -12,7 +12,7 @@ var (
|
||||
)
|
||||
|
||||
func cliInit() {
|
||||
flag.BoolVar(&flagInit, "init", false, "Setup var directory, initialize swlite database file, config.json and .env")
|
||||
flag.BoolVar(&flagInit, "init", false, "Setup var directory, initialize sqlite database file, config.json and .env")
|
||||
flag.BoolVar(&flagReinitDB, "init-db", false, "Go through job-archive and re-initialize the 'job', 'tag', and 'jobtag' tables (all running jobs will be lost!)")
|
||||
flag.BoolVar(&flagSyncLDAP, "sync-ldap", false, "Sync the 'hpc_user' table with ldap")
|
||||
flag.BoolVar(&flagServer, "server", false, "Start a server, continues listening on port after initialization and argument handling")
|
||||
@ -24,10 +24,10 @@ func cliInit() {
|
||||
flag.BoolVar(&flagForceDB, "force-db", false, "Force database version, clear dirty flag and exit")
|
||||
flag.BoolVar(&flagLogDateTime, "logdate", false, "Set this flag to add date and time to log messages")
|
||||
flag.StringVar(&flagConfigFile, "config", "./config.json", "Specify alternative path to `config.json`")
|
||||
flag.StringVar(&flagNewUser, "add-user", "", "Add a new user. Argument format: `<username>:[admin,support,manager,api,user]:<password>`")
|
||||
flag.StringVar(&flagDelUser, "del-user", "", "Remove user by `username`")
|
||||
flag.StringVar(&flagNewUser, "add-user", "", "Add a new user. Argument format: <username>:[admin,support,manager,api,user]:<password>")
|
||||
flag.StringVar(&flagDelUser, "del-user", "", "Remove a existing user. Argument format: <username>")
|
||||
flag.StringVar(&flagGenJWT, "jwt", "", "Generate and print a JWT for the user specified by its `username`")
|
||||
flag.StringVar(&flagImportJob, "import-job", "", "Import a job. Argument format: `<path-to-meta.json>:<path-to-data.json>,...`")
|
||||
flag.StringVar(&flagLogLevel, "loglevel", "warn", "Sets the logging level: `[debug,info,warn (default),err,fatal,crit]`")
|
||||
flag.StringVar(&flagLogLevel, "loglevel", "warn", "Sets the logging level: `[debug, info (default), warn, err, crit]`")
|
||||
flag.Parse()
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ClusterCockpit/cc-backend/internal/repository"
|
||||
@ -62,24 +61,23 @@ const configString = `
|
||||
|
||||
func initEnv() {
|
||||
if util.CheckFileExists("var") {
|
||||
fmt.Print("Directory ./var already exists. Exiting!\n")
|
||||
os.Exit(0)
|
||||
log.Exit("Directory ./var already exists. Cautiously exiting application initialization.")
|
||||
}
|
||||
|
||||
if err := os.WriteFile("config.json", []byte(configString), 0o666); err != nil {
|
||||
log.Fatalf("Writing config.json failed: %s", err.Error())
|
||||
log.Abortf("Could not write default ./config.json with permissions '0o666'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if err := os.WriteFile(".env", []byte(envString), 0o666); err != nil {
|
||||
log.Fatalf("Writing .env failed: %s", err.Error())
|
||||
log.Abortf("Could not write default ./.env file with permissions '0o666'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if err := os.Mkdir("var", 0o777); err != nil {
|
||||
log.Fatalf("Mkdir var failed: %s", err.Error())
|
||||
log.Abortf("Could not create default ./var folder with permissions '0o777'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
err := repository.MigrateDB("sqlite3", "./var/job.db")
|
||||
if err != nil {
|
||||
log.Fatalf("Initialize job.db failed: %s", err.Error())
|
||||
log.Abortf("Could not initialize default sqlite3 database as './var/job.db'. Application initialization failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
@ -61,15 +61,23 @@ func main() {
|
||||
// Apply config flags for pkg/log
|
||||
log.Init(flagLogLevel, flagLogDateTime)
|
||||
|
||||
// If init flag set, run tasks here before any file dependencies cause errors
|
||||
if flagInit {
|
||||
initEnv()
|
||||
log.Exit("Successfully setup environment!\n" +
|
||||
"Please review config.json and .env and adjust it to your needs.\n" +
|
||||
"Add your job-archive at ./var/job-archive.")
|
||||
}
|
||||
|
||||
// See https://github.com/google/gops (Runtime overhead is almost zero)
|
||||
if flagGops {
|
||||
if err := agent.Listen(agent.Options{}); err != nil {
|
||||
log.Fatalf("gops/agent.Listen failed: %s", err.Error())
|
||||
log.Abortf("Could not start gops agent with 'gops/agent.Listen(agent.Options{})'. Application startup failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err := runtimeEnv.LoadEnv("./.env"); err != nil && !os.IsNotExist(err) {
|
||||
log.Fatalf("parsing './.env' file failed: %s", err.Error())
|
||||
log.Abortf("Could not parse existing .env file at location './.env'. Application startup failed, exited.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
// Initialize sub-modules and handle command line flags.
|
||||
@ -87,37 +95,29 @@ func main() {
|
||||
if flagMigrateDB {
|
||||
err := repository.MigrateDB(config.Keys.DBDriver, config.Keys.DB)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Abortf("MigrateDB Failed: Could not migrate '%s' database at location '%s' to version %d.\nError: %s\n", config.Keys.DBDriver, config.Keys.DB, repository.Version, err.Error())
|
||||
}
|
||||
os.Exit(0)
|
||||
log.Exitf("MigrateDB Success: Migrated '%s' database at location '%s' to version %d.\n", config.Keys.DBDriver, config.Keys.DB, repository.Version)
|
||||
}
|
||||
|
||||
if flagRevertDB {
|
||||
err := repository.RevertDB(config.Keys.DBDriver, config.Keys.DB)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Abortf("RevertDB Failed: Could not revert '%s' database at location '%s' to version %d.\nError: %s\n", config.Keys.DBDriver, config.Keys.DB, (repository.Version - 1), err.Error())
|
||||
}
|
||||
os.Exit(0)
|
||||
log.Exitf("RevertDB Success: Reverted '%s' database at location '%s' to version %d.\n", config.Keys.DBDriver, config.Keys.DB, (repository.Version - 1))
|
||||
}
|
||||
|
||||
if flagForceDB {
|
||||
err := repository.ForceDB(config.Keys.DBDriver, config.Keys.DB)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Abortf("ForceDB Failed: Could not force '%s' database at location '%s' to version %d.\nError: %s\n", config.Keys.DBDriver, config.Keys.DB, repository.Version, err.Error())
|
||||
}
|
||||
os.Exit(0)
|
||||
log.Exitf("ForceDB Success: Forced '%s' database at location '%s' to version %d.\n", config.Keys.DBDriver, config.Keys.DB, repository.Version)
|
||||
}
|
||||
|
||||
repository.Connect(config.Keys.DBDriver, config.Keys.DB)
|
||||
|
||||
if flagInit {
|
||||
initEnv()
|
||||
fmt.Print("Successfully setup environment!\n")
|
||||
fmt.Print("Please review config.json and .env and adjust it to your needs.\n")
|
||||
fmt.Print("Add your job-archive at ./var/job-archive.\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if !config.Keys.DisableAuthentication {
|
||||
|
||||
auth.Init()
|
||||
@ -125,20 +125,27 @@ func main() {
|
||||
if flagNewUser != "" {
|
||||
parts := strings.SplitN(flagNewUser, ":", 3)
|
||||
if len(parts) != 3 || len(parts[0]) == 0 {
|
||||
log.Fatal("invalid argument format for user creation")
|
||||
log.Abortf("Add User: Could not parse supplied argument format: No changes.\n"+
|
||||
"Want: <username>:[admin,support,manager,api,user]:<password>\n"+
|
||||
"Have: %s\n", flagNewUser)
|
||||
}
|
||||
|
||||
ur := repository.GetUserRepository()
|
||||
if err := ur.AddUser(&schema.User{
|
||||
Username: parts[0], Projects: make([]string, 0), Password: parts[2], Roles: strings.Split(parts[1], ","),
|
||||
}); err != nil {
|
||||
log.Fatalf("adding '%s' user authentication failed: %v", parts[0], err)
|
||||
log.Abortf("Add User: Could not add new user authentication for '%s' and roles '%s'.\nError: %s\n", parts[0], parts[1], err.Error())
|
||||
} else {
|
||||
log.Printf("Add User: Added new user '%s' with roles '%s'.\n", parts[0], parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
if flagDelUser != "" {
|
||||
ur := repository.GetUserRepository()
|
||||
if err := ur.DelUser(flagDelUser); err != nil {
|
||||
log.Fatalf("deleting user failed: %v", err)
|
||||
log.Abortf("Delete User: Could not delete user '%s' from DB.\nError: %s\n", flagDelUser, err.Error())
|
||||
} else {
|
||||
log.Printf("Delete User: Deleted user '%s' from DB.\n", flagDelUser)
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,60 +153,64 @@ func main() {
|
||||
|
||||
if flagSyncLDAP {
|
||||
if authHandle.LdapAuth == nil {
|
||||
log.Fatal("cannot sync: LDAP authentication is not configured")
|
||||
log.Abort("Sync LDAP: LDAP authentication is not configured, could not synchronize. No changes, exited.")
|
||||
}
|
||||
|
||||
if err := authHandle.LdapAuth.Sync(); err != nil {
|
||||
log.Fatalf("LDAP sync failed: %v", err)
|
||||
log.Abortf("Sync LDAP: Could not synchronize, failed with error.\nError: %s\n", err.Error())
|
||||
}
|
||||
log.Info("LDAP sync successfull")
|
||||
log.Print("Sync LDAP: LDAP synchronization successfull.")
|
||||
}
|
||||
|
||||
if flagGenJWT != "" {
|
||||
ur := repository.GetUserRepository()
|
||||
user, err := ur.GetUser(flagGenJWT)
|
||||
if err != nil {
|
||||
log.Fatalf("could not get user from JWT: %v", err)
|
||||
log.Abortf("JWT: Could not get supplied user '%s' from DB. No changes, exited.\nError: %s\n", flagGenJWT, err.Error())
|
||||
}
|
||||
|
||||
if !user.HasRole(schema.RoleApi) {
|
||||
log.Warnf("user '%s' does not have the API role", user.Username)
|
||||
log.Warnf("JWT: User '%s' does not have the role 'api'. REST API endpoints will return error!\n", user.Username)
|
||||
}
|
||||
|
||||
jwt, err := authHandle.JwtAuth.ProvideJWT(user)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to provide JWT to user '%s': %v", user.Username, err)
|
||||
log.Abortf("JWT: User '%s' found in DB, but failed to provide JWT.\nError: %s\n", user.Username, err.Error())
|
||||
}
|
||||
|
||||
fmt.Printf("MAIN > JWT for '%s': %s\n", user.Username, jwt)
|
||||
log.Printf("JWT: Successfully generated JWT for user '%s': %s\n", user.Username, jwt)
|
||||
}
|
||||
|
||||
} else if flagNewUser != "" || flagDelUser != "" {
|
||||
log.Fatal("arguments --add-user and --del-user can only be used if authentication is enabled")
|
||||
log.Abort("Error: Arguments '--add-user' and '--del-user' can only be used if authentication is enabled. No changes, exited.")
|
||||
}
|
||||
|
||||
if err := archive.Init(config.Keys.Archive, config.Keys.DisableArchive); err != nil {
|
||||
log.Fatalf("failed to initialize archive: %s", err.Error())
|
||||
log.Abortf("Init: Failed to initialize archive.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if err := metricdata.Init(); err != nil {
|
||||
log.Fatalf("failed to initialize metricdata repository: %s", err.Error())
|
||||
log.Abortf("Init: Failed to initialize metricdata repository.\nError %s\n", err.Error())
|
||||
}
|
||||
|
||||
if flagReinitDB {
|
||||
if err := importer.InitDB(); err != nil {
|
||||
log.Fatalf("failed to re-initialize repository DB: %s", err.Error())
|
||||
log.Abortf("Init DB: Failed to re-initialize repository DB.\nError: %s\n", err.Error())
|
||||
} else {
|
||||
log.Print("Init DB: Sucessfully re-initialized repository DB.")
|
||||
}
|
||||
}
|
||||
|
||||
if flagImportJob != "" {
|
||||
if err := importer.HandleImportFlag(flagImportJob); err != nil {
|
||||
log.Fatalf("job import failed: %s", err.Error())
|
||||
log.Abortf("Import Job: Job import failed.\nError: %s\n", err.Error())
|
||||
} else {
|
||||
log.Printf("Import Job: Imported Job '%s' into DB.\n", flagImportJob)
|
||||
}
|
||||
}
|
||||
|
||||
if !flagServer {
|
||||
return
|
||||
log.Exit("No errors, server flag not set. Exiting cc-backend.")
|
||||
}
|
||||
|
||||
archiver.Start(repository.GetJobRepository())
|
||||
|
@ -64,7 +64,7 @@ func serverInit() {
|
||||
case string:
|
||||
return fmt.Errorf("MAIN > Panic: %s", e)
|
||||
case error:
|
||||
return fmt.Errorf("MAIN > Panic caused by: %w", e)
|
||||
return fmt.Errorf("MAIN > Panic caused by: %s", e.Error())
|
||||
}
|
||||
|
||||
return errors.New("MAIN > Internal server error (panic)")
|
||||
@ -268,7 +268,7 @@ func serverStart() {
|
||||
// Start http or https server
|
||||
listener, err := net.Listen("tcp", config.Keys.Addr)
|
||||
if err != nil {
|
||||
log.Fatalf("starting http listener failed: %v", err)
|
||||
log.Abortf("Server Start: Starting http listener on '%s' failed.\nError: %s\n", config.Keys.Addr, err.Error())
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(config.Keys.Addr, ":80") && config.Keys.RedirectHttpTo != "" {
|
||||
@ -281,7 +281,7 @@ func serverStart() {
|
||||
cert, err := tls.LoadX509KeyPair(
|
||||
config.Keys.HttpsCertFile, config.Keys.HttpsKeyFile)
|
||||
if err != nil {
|
||||
log.Fatalf("loading X509 keypair failed: %v", err)
|
||||
log.Abortf("Server Start: Loading X509 keypair failed. Check options 'https-cert-file' and 'https-key-file' in 'config.json'.\nError: %s\n", err.Error())
|
||||
}
|
||||
listener = tls.NewListener(listener, &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
@ -292,20 +292,20 @@ func serverStart() {
|
||||
MinVersion: tls.VersionTLS12,
|
||||
PreferServerCipherSuites: true,
|
||||
})
|
||||
fmt.Printf("HTTPS server listening at %s...", config.Keys.Addr)
|
||||
log.Printf("HTTPS server listening at %s...\n", config.Keys.Addr)
|
||||
} else {
|
||||
fmt.Printf("HTTP server listening at %s...", config.Keys.Addr)
|
||||
log.Printf("HTTP server listening at %s...\n", config.Keys.Addr)
|
||||
}
|
||||
//
|
||||
// Because this program will want to bind to a privileged port (like 80), the listener must
|
||||
// be established first, then the user can be changed, and after that,
|
||||
// the actual http server can be started.
|
||||
if err := runtimeEnv.DropPrivileges(config.Keys.Group, config.Keys.User); err != nil {
|
||||
log.Fatalf("error while preparing server start: %s", err.Error())
|
||||
log.Abortf("Server Start: Error while preparing server start.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if err = server.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("starting server failed: %v", err)
|
||||
log.Abortf("Server Start: Starting server failed.\nError: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1423,8 +1423,6 @@ func (api *RestApi) updateConfiguration(rw http.ResponseWriter, r *http.Request)
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
key, value := r.FormValue("key"), r.FormValue("value")
|
||||
|
||||
// fmt.Printf("REST > KEY: %#v\nVALUE: %#v\n", key, value)
|
||||
|
||||
if err := repository.GetUserCfgRepo().UpdateConfig(key, value, repository.GetUserFromContext(r.Context())); err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusUnprocessableEntity)
|
||||
return
|
||||
|
@ -7,9 +7,9 @@ package config
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/ClusterCockpit/cc-backend/pkg/log"
|
||||
"github.com/ClusterCockpit/cc-backend/pkg/schema"
|
||||
)
|
||||
|
||||
@ -53,20 +53,20 @@ func Init(flagConfigFile string) {
|
||||
raw, err := os.ReadFile(flagConfigFile)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Fatalf("CONFIG ERROR: %v", err)
|
||||
log.Abortf("Config Init: Could not read config file '%s'.\nError: %s\n", flagConfigFile, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err := schema.Validate(schema.Config, bytes.NewReader(raw)); err != nil {
|
||||
log.Fatalf("Validate config: %v\n", err)
|
||||
log.Abortf("Config Init: Could not validate config file '%s'.\nError: %s\n", flagConfigFile, err.Error())
|
||||
}
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&Keys); err != nil {
|
||||
log.Fatalf("could not decode: %v", err)
|
||||
log.Abortf("Config Init: Could not decode config file '%s'.\nError: %s\n", flagConfigFile, err.Error())
|
||||
}
|
||||
|
||||
if Keys.Clusters == nil || len(Keys.Clusters) < 1 {
|
||||
log.Fatal("At least one cluster required in config!")
|
||||
log.Abort("Config Init: At least one cluster required in config. Exited with error.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,17 +59,15 @@ func Connect(driver string, db string) {
|
||||
} else {
|
||||
dbHandle, err = sqlx.Open("sqlite3", opts.URL)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
case "mysql":
|
||||
opts.URL += "?multiStatements=true"
|
||||
dbHandle, err = sqlx.Open("mysql", opts.URL)
|
||||
if err != nil {
|
||||
log.Fatalf("sqlx.Open() error: %v", err)
|
||||
}
|
||||
default:
|
||||
log.Fatalf("unsupported database driver: %s", driver)
|
||||
log.Abortf("DB Connection: Unsupported database driver '%s'.\n", driver)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Abortf("DB Connection: Could not connect to '%s' database with sqlx.Open().\nError: %s\n", driver, err.Error())
|
||||
}
|
||||
|
||||
dbHandle.SetMaxOpenConns(opts.MaxOpenConnections)
|
||||
@ -80,7 +78,7 @@ func Connect(driver string, db string) {
|
||||
dbConnInstance = &DBConnection{DB: dbHandle, Driver: driver}
|
||||
err = checkDBVersion(driver, dbHandle.DB)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Abortf("DB Connection: Failed DB version check.\nError: %s\n", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func checkDBVersion(backend string, db *sql.DB) error {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
log.Fatalf("unsupported database backend: %s", backend)
|
||||
log.Abortf("Migration: Unsupported database backend '%s'.\n", backend)
|
||||
}
|
||||
|
||||
v, dirty, err := m.Version()
|
||||
@ -102,7 +102,7 @@ func getMigrateInstance(backend string, db string) (m *migrate.Migrate, err erro
|
||||
return m, err
|
||||
}
|
||||
default:
|
||||
log.Fatalf("unsupported database backend: %s", backend)
|
||||
log.Abortf("Migration: Unsupported database backend '%s'.\n", backend)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
|
@ -35,7 +35,7 @@ func GetUserCfgRepo() *UserCfgRepo {
|
||||
|
||||
lookupConfigStmt, err := db.DB.Preparex(`SELECT confkey, value FROM configuration WHERE configuration.username = ?`)
|
||||
if err != nil {
|
||||
log.Fatalf("db.DB.Preparex() error: %v", err)
|
||||
log.Fatalf("User Config: Call 'db.DB.Preparex()' failed.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
userCfgRepoInstance = &UserCfgRepo{
|
||||
|
@ -40,7 +40,7 @@ func Start() {
|
||||
jobRepo = repository.GetJobRepository()
|
||||
s, err = gocron.NewScheduler()
|
||||
if err != nil {
|
||||
log.Fatalf("Error while creating gocron scheduler: %s", err.Error())
|
||||
log.Abortf("Taskmanager Start: Could not create gocron scheduler.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if config.Keys.StopJobsExceedingWalltime > 0 {
|
||||
|
236
pkg/log/log.go
236
pkg/log/log.go
@ -46,12 +46,12 @@ var loglevel string = "info"
|
||||
/* CONFIG */
|
||||
|
||||
func Init(lvl string, logdate bool) {
|
||||
|
||||
// Discard I/O for all writers below selected loglevel; <CRITICAL> is always written.
|
||||
switch lvl {
|
||||
case "crit":
|
||||
ErrWriter = io.Discard
|
||||
fallthrough
|
||||
case "err", "fatal":
|
||||
case "err":
|
||||
WarnWriter = io.Discard
|
||||
fallthrough
|
||||
case "warn":
|
||||
@ -63,8 +63,7 @@ func Init(lvl string, logdate bool) {
|
||||
// Nothing to do...
|
||||
break
|
||||
default:
|
||||
fmt.Printf("pkg/log: Flag 'loglevel' has invalid value %#v\npkg/log: Will use default loglevel 'debug'\n", lvl)
|
||||
//SetLogLevel("debug")
|
||||
fmt.Printf("pkg/log: Flag 'loglevel' has invalid value %#v\npkg/log: Will use default loglevel '%s'\n", lvl, loglevel)
|
||||
}
|
||||
|
||||
if !logdate {
|
||||
@ -84,109 +83,138 @@ func Init(lvl string, logdate bool) {
|
||||
loglevel = lvl
|
||||
}
|
||||
|
||||
/* PRINT */
|
||||
|
||||
// Private helper
|
||||
func printStr(v ...interface{}) string {
|
||||
return fmt.Sprint(v...)
|
||||
}
|
||||
|
||||
// Uses Info() -> If errorpath required at some point:
|
||||
// Will need own writer with 'Output(2, out)' to correctly render path
|
||||
func Print(v ...interface{}) {
|
||||
Info(v...)
|
||||
}
|
||||
|
||||
func Debug(v ...interface{}) {
|
||||
DebugLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
func Info(v ...interface{}) {
|
||||
InfoLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
func Warn(v ...interface{}) {
|
||||
WarnLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
func Error(v ...interface{}) {
|
||||
ErrLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
// Writes panic stacktrace, but keeps application alive
|
||||
func Panic(v ...interface{}) {
|
||||
ErrLog.Output(2, printStr(v...))
|
||||
panic("Panic triggered ...")
|
||||
}
|
||||
|
||||
func Crit(v ...interface{}) {
|
||||
CritLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
// Writes critical log, stops application
|
||||
func Fatal(v ...interface{}) {
|
||||
CritLog.Output(2, printStr(v...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
/* PRINT FORMAT*/
|
||||
|
||||
// Private helper
|
||||
func printfStr(format string, v ...interface{}) string {
|
||||
return fmt.Sprintf(format, v...)
|
||||
}
|
||||
|
||||
// Uses Infof() -> If errorpath required at some point:
|
||||
// Will need own writer with 'Output(2, out)' to correctly render path
|
||||
func Printf(format string, v ...interface{}) {
|
||||
Infof(format, v...)
|
||||
}
|
||||
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
DebugLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
func Infof(format string, v ...interface{}) {
|
||||
InfoLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
WarnLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
ErrLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
// Writes panic stacktrace, but keeps application alive
|
||||
func Panicf(format string, v ...interface{}) {
|
||||
ErrLog.Output(2, printfStr(format, v...))
|
||||
panic("Panic triggered ...")
|
||||
}
|
||||
|
||||
func Critf(format string, v ...interface{}) {
|
||||
CritLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
// Writes crit log, stops application
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
CritLog.Output(2, printfStr(format, v...))
|
||||
os.Exit(1)
|
||||
}
|
||||
/* HELPER */
|
||||
|
||||
func Loglevel() string {
|
||||
return loglevel
|
||||
}
|
||||
|
||||
/* SPECIAL */
|
||||
/* PRIVATE HELPER */
|
||||
|
||||
// func Finfof(w io.Writer, format string, v ...interface{}) {
|
||||
// if w != io.Discard {
|
||||
// if logDateTime {
|
||||
// currentTime := time.Now()
|
||||
// fmt.Fprintf(InfoWriter, currentTime.String()+InfoPrefix+format+"\n", v...)
|
||||
// } else {
|
||||
// fmt.Fprintf(InfoWriter, InfoPrefix+format+"\n", v...)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Return unformatted string
|
||||
func printStr(v ...interface{}) string {
|
||||
return fmt.Sprint(v...)
|
||||
}
|
||||
|
||||
// Return formatted string
|
||||
func printfStr(format string, v ...interface{}) string {
|
||||
return fmt.Sprintf(format, v...)
|
||||
}
|
||||
|
||||
/* PRINT */
|
||||
|
||||
// Prints to STDOUT without string formatting; application continues.
|
||||
// Used for special cases not requiring log information like date or location.
|
||||
func Print(v ...interface{}) {
|
||||
fmt.Fprintln(os.Stdout, v...)
|
||||
}
|
||||
|
||||
// Prints to STDOUT without string formatting; application exits with error code 0.
|
||||
// Used for exiting succesfully with message after expected outcome, e.g. successful single-call application runs.
|
||||
func Exit(v ...interface{}) {
|
||||
fmt.Fprintln(os.Stdout, v...)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Prints to STDOUT without string formatting; application exits with error code 1.
|
||||
// Used for terminating with message after to be expected errors, e.g. wrong arguments or during init().
|
||||
func Abort(v ...interface{}) {
|
||||
fmt.Fprintln(os.Stdout, v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Prints to DEBUG writer without string formatting; application continues.
|
||||
// Used for logging additional information, primarily for development.
|
||||
func Debug(v ...interface{}) {
|
||||
DebugLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
// Prints to INFO writer without string formatting; application continues.
|
||||
// Used for logging additional information, e.g. notable returns or common fail-cases.
|
||||
func Info(v ...interface{}) {
|
||||
InfoLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
// Prints to WARNING writer without string formatting; application continues.
|
||||
// Used for logging important information, e.g. uncommon edge-cases or administration related information.
|
||||
func Warn(v ...interface{}) {
|
||||
WarnLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
// Prints to ERROR writer without string formatting; application continues.
|
||||
// Used for logging errors, but code still can return default(s) or nil.
|
||||
func Error(v ...interface{}) {
|
||||
ErrLog.Output(2, printStr(v...))
|
||||
}
|
||||
|
||||
// Prints to CRITICAL writer without string formatting; application exits with error code 1.
|
||||
// Used for terminating on unexpected errors with date and code location.
|
||||
func Fatal(v ...interface{}) {
|
||||
CritLog.Output(2, printStr(v...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Prints to PANIC function without string formatting; application exits with panic.
|
||||
// Used for terminating on unexpected errors with stacktrace.
|
||||
func Panic(v ...interface{}) {
|
||||
panic(printStr(v...))
|
||||
}
|
||||
|
||||
/* PRINT FORMAT*/
|
||||
|
||||
// Prints to STDOUT with string formatting; application continues.
|
||||
// Used for special cases not requiring log information like date or location.
|
||||
func Printf(format string, v ...interface{}) {
|
||||
fmt.Fprintf(os.Stdout, format, v...)
|
||||
}
|
||||
|
||||
// Prints to STDOUT with string formatting; application exits with error code 0.
|
||||
// Used for exiting succesfully with message after expected outcome, e.g. successful single-call application runs.
|
||||
func Exitf(format string, v ...interface{}) {
|
||||
fmt.Fprintf(os.Stdout, format, v...)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Prints to STDOUT with string formatting; application exits with error code 1.
|
||||
// Used for terminating with message after to be expected errors, e.g. wrong arguments or during init().
|
||||
func Abortf(format string, v ...interface{}) {
|
||||
fmt.Fprintf(os.Stdout, format, v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Prints to DEBUG writer with string formatting; application continues.
|
||||
// Used for logging additional information, primarily for development.
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
DebugLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
// Prints to INFO writer with string formatting; application continues.
|
||||
// Used for logging additional information, e.g. notable returns or common fail-cases.
|
||||
func Infof(format string, v ...interface{}) {
|
||||
InfoLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
// Prints to WARNING writer with string formatting; application continues.
|
||||
// Used for logging important information, e.g. uncommon edge-cases or administration related information.
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
WarnLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
// Prints to ERROR writer with string formatting; application continues.
|
||||
// Used for logging errors, but code still can return default(s) or nil.
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
ErrLog.Output(2, printfStr(format, v...))
|
||||
}
|
||||
|
||||
// Prints to CRITICAL writer with string formatting; application exits with error code 1.
|
||||
// Used for terminating on unexpected errors with date and code location.
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
CritLog.Output(2, printfStr(format, v...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Prints to PANIC function with string formatting; application exits with panic.
|
||||
// Used for terminating on unexpected errors with stacktrace.
|
||||
func Panicf(format string, v ...interface{}) {
|
||||
panic(printfStr(format, v...))
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ func parseDate(in string) int64 {
|
||||
if in != "" {
|
||||
t, err := time.ParseInLocation(shortForm, in, loc)
|
||||
if err != nil {
|
||||
fmt.Printf("date parse error %v", err)
|
||||
os.Exit(0)
|
||||
log.Abortf("Archive Manager Main: Date parse failed with input: '%s'\nError: %s\n", in, err.Error())
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
@ -26,8 +26,7 @@ var frontendFiles embed.FS
|
||||
func ServeFiles() http.Handler {
|
||||
publicFiles, err := fs.Sub(frontendFiles, "frontend/public")
|
||||
if err != nil {
|
||||
log.Fatalf("WEB/WEB > cannot find frontend public files")
|
||||
panic(err)
|
||||
log.Abortf("Serve Files: Could not find 'frontend/public' file directory.\nError: %s\n", err.Error())
|
||||
}
|
||||
return http.FileServer(http.FS(publicFiles))
|
||||
}
|
||||
@ -75,8 +74,7 @@ func init() {
|
||||
templates[strings.TrimPrefix(path, "templates/")] = template.Must(template.Must(base.Clone()).ParseFS(templateFiles, path))
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Fatalf("WEB/WEB > cannot find frontend template files")
|
||||
panic(err)
|
||||
log.Abortf("Web init(): Could not find frontend template files.\nError: %s\n", err.Error())
|
||||
}
|
||||
|
||||
_ = base
|
||||
|
Loading…
x
Reference in New Issue
Block a user