Files
qfixpt/main.go
Ramiro Paz ac285e662b fixes
2026-03-12 12:31:05 -03:00

207 lines
5.0 KiB
Go

// package qfixpt is a Micro service quantex base project
package main
import (
"embed"
"flag"
"fmt"
"log/slog"
"os"
"time"
"github.com/mitchellh/panicwrap"
"quantex.com/qfixpt/src/app"
"quantex.com/qfixpt/src/app/mode"
"quantex.com/qfixpt/src/app/version"
"quantex.com/qfixpt/src/client/config"
googlechat "quantex.com/qfixpt/src/client/notify/google"
"quantex.com/qfixpt/src/client/res"
"quantex.com/qfixpt/src/cmd"
"quantex.com/qfixpt/src/cmd/example"
"quantex.com/qfixpt/src/cmd/service"
"quantex.com/qfixpt/src/common/logger"
"quantex.com/qfixpt/src/common/logger/tint"
"quantex.com/qfixpt/src/domain"
)
// Embed the entire directory.
//go:embed res
var resources embed.FS
type flagsType struct {
runner, globalCfg, serviceCfg, logLevel, logFormat string
debug, version bool
}
func main() {
flags := parseFlags()
if len(os.Args) == 1 {
flag.Usage()
return
}
if flags.version {
fmt.Printf("%s version %s", version.AppName, version.Info())
return
}
cfg, err := config.Read([]string{flags.globalCfg, flags.serviceCfg})
if err != nil {
panic(fmt.Sprintf("Something went wrong reading the config. %s", err))
}
notify := googlechat.New(cfg.Notify.Google)
exitStatus, err := panicwrap.BasicWrap(func(output string) {
notify.SendMsg(domain.MessageChannelPanic, output, domain.MessageStatusStopper, nil)
os.Exit(1)
})
if err != nil {
// Something went wrong setting up the panic wrapper.
panic(fmt.Sprintf("Something went wrong setting up the panic wrapper. %s", err))
}
// If exitStatus >= 0, then we're the parent process and the panicwrap
// re-executed ourselves and completed. Just exit with the proper status.
if exitStatus >= 0 {
os.Exit(exitStatus)
}
handler, err := newLogHandler(flags)
if err != nil {
panic(err)
}
hook := logger.NewQuantexHandler(handler, []slog.Level{slog.LevelError, slog.LevelWarn})
slog.SetDefault(slog.New(hook))
slog.Info("New Run ----------------------------------------------------------------------------")
slog.Debug(fmt.Sprintf("flags: %+v", flags))
v := version.AppName + " version " + version.Info()
fmt.Println(v)
slog.Info(v)
setDebugMode(flags.debug)
startRunner(flags.runner, flags.globalCfg, flags.serviceCfg)
}
func parseFlags() (f flagsType) {
fmt.Println(f.runner)
flag.StringVar(&f.runner, "run", "", "run the specified service")
flag.StringVar(&f.globalCfg, "global-cfg", "../global_conf.toml", "set the config global file name")
flag.StringVar(&f.serviceCfg, "service-cfg", "conf.toml", "set the config service file name")
const u0 = "set the logs output format: text, json, tint1 (one line), tint2 (two lines)"
flag.StringVar(&f.logFormat, "logs-format", "json", u0)
flag.StringVar(&f.logFormat, "f", "json", u0+" (shorthand)")
const u1 = "set the debug mode"
flag.BoolVar(&f.debug, "debug", false, u1)
flag.BoolVar(&f.debug, "d", false, u1+" (shorthand)")
const u2 = "show the program version"
flag.BoolVar(&f.version, "version", false, u2)
flag.BoolVar(&f.version, "v", false, u2+" (shorthand)")
const u3 = "set the log level: debug, info, warn, error"
flag.StringVar(&f.logLevel, "level", "info", u3)
flag.StringVar(&f.logLevel, "l", "info", u3+" (shorthand)")
flag.Parse()
return f
}
func newLogHandler(flags flagsType) (slog.Handler, error) {
logLevel, err := parseLogLevel(flags.logLevel)
if err != nil {
return nil, err
}
switch flags.logFormat {
case "json":
return logger.NewJSONHandler(logLevel), nil
case "text":
return logger.NewTextHandler(logLevel), nil
case "tint1":
return logger.NewTextHandlerTint(logLevel, tint.OneLine), nil
case "tint2":
return logger.NewTextHandlerTint(logLevel, tint.TwoLines), nil
default:
flag.PrintDefaults()
return nil, fmt.Errorf("invalid log format option: \"%s\"", flags.logFormat)
}
}
func setDebugMode(debug bool) {
mode.Debug = debug
var msg string
if mode.Debug {
res.Set(os.DirFS("./"))
msg = fmt.Sprintf("Running %s in DEBUG mode!", version.AppName)
} else {
res.Set(resources)
msg = fmt.Sprintf("Running %s!", version.AppName)
}
slog.Info(msg)
}
func parseLogLevel(level string) (slog.Level, error) {
switch level {
case "debug":
return slog.LevelDebug, nil
case "info":
return slog.LevelInfo, nil
case "warn":
return slog.LevelWarn, nil
case "error":
return slog.LevelError, nil
default:
return 0, fmt.Errorf("invalid log level: %s", level)
}
}
func startRunner(runner, globalCfg, serviceCfg string) {
var fn func(cfg app.Config) error
if runner == "" {
runner = "service"
}
switch runner {
case "service":
fn = service.Runner
case "async":
fn = example.AsyncRunner
case "external":
fn = example.ExternalRunner
case "tracerr":
fn = example.TracerrRunner
case "logger":
fn = example.LogsRunner
default:
panic("Invalid runner option: \"" + runner + "\"")
}
if err := cmd.NewRunner(fn)(globalCfg, serviceCfg); err != nil {
slog.Error(err.Error())
// Time guard to allow to notify to send the message
time.Sleep(2 * time.Second)
}
}