diff --git a/backend/cmd/config.toml b/backend/cmd/config.toml index 52915d2e6..f75149e79 100644 --- a/backend/cmd/config.toml +++ b/backend/cmd/config.toml @@ -19,10 +19,6 @@ boards = ["BCU", "BMSL", "HVSCU", "HVSCU-Cabinet", "LCU", "PCU", "VCU", "BLCU"] [adj] branch = "main" # Leave blank when using ADJ as a submodule (like this: "") -# Network Configuration -[network] -manual = false # Manual network device selection - # Transport Configuration [transport] propagate_fault = false diff --git a/backend/cmd/dev-config.toml b/backend/cmd/dev-config.toml index 633306e9f..876049230 100644 --- a/backend/cmd/dev-config.toml +++ b/backend/cmd/dev-config.toml @@ -20,9 +20,6 @@ boards = ["HVSCU", "HVSCU-Cabinet", "PCU", "LCU", "BCU", "BMSL"] [adj] branch = "software" # Leave blank when using ADJ as a submodule (like this: "") -# Network Configuration -[network] -manual = false # Manual network device selection # Transport Configuration [transport] @@ -77,11 +74,5 @@ upload_order_id = 0 # Order ID for upload operations (0 = use default) # Logging Configuration [logging] -level = "debug" # Logging level (trace, debug, info, warn, error, fatal) -console = true # Enable console output -file = "backend.log" # Log file path (empty to disable file logging) -max_size_mb = 100 # Maximum log file size in MB -max_backups = 3 # Number of backup files to keep -max_age_days = 7 # Maximum age of log files in days time_unit = "us" # Time unit for log timestamps (ns, us, ms, s) logging_path = "." \ No newline at end of file diff --git a/backend/cmd/main.go b/backend/cmd/main.go index e2a5c7701..107c92a7a 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -1,17 +1,16 @@ package main import ( - "flag" _ "net/http/pprof" "os" "os/signal" adj_module "github.com/HyperloopUPV-H8/h9-backend/internal/adj" "github.com/HyperloopUPV-H8/h9-backend/internal/config" + "github.com/HyperloopUPV-H8/h9-backend/internal/flags" "github.com/HyperloopUPV-H8/h9-backend/internal/pod_data" "github.com/HyperloopUPV-H8/h9-backend/internal/update_factory" vehicle_models "github.com/HyperloopUPV-H8/h9-backend/internal/vehicle/models" - "github.com/HyperloopUPV-H8/h9-backend/pkg/abstraction" "github.com/HyperloopUPV-H8/h9-backend/pkg/transport" "github.com/HyperloopUPV-H8/h9-backend/pkg/websocket" trace "github.com/rs/zerolog/log" @@ -29,25 +28,13 @@ const ( RemoveStateOrder = "remove_state_order" ) -var configFile = flag.String("config", "config.toml", "path to configuration file") -var traceLevel = flag.String("trace", "info", "set the trace level (\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\")") -var traceFile = flag.String("log", "", "set the trace log file") -var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") -var enableSNTP = flag.Bool("sntp", false, "enables a simple SNTP server on port 123") -var networkDevice = flag.Int("dev", -1, "index of the network device to use, overrides device prompt") -var blockprofile = flag.Int("blockprofile", 0, "number of block profiles to include") -var playbackFile = flag.String("playback", "", "") -var versionFlag = flag.Bool("version", false, "Show the backend version") - -type SubloggersMap map[abstraction.LoggerName]abstraction.Logger - func main() { // Parse command line flags - flag.Parse() + flags.Init() handleVersionFlag() // Configure trace - traceFile := initTrace(*traceLevel, *traceFile) + traceFile := initTrace(flags.TraceLevel, flags.TraceFile) if traceFile != nil { defer traceFile.Close() } @@ -57,7 +44,7 @@ func main() { defer cleanup() // <--- config ---> - config, err := config.GetConfig(*configFile) + config, err := config.GetConfig(flags.ConfigFile) if err != nil { trace.Fatal().Err(err).Msg("error unmarshaling toml file") } @@ -139,6 +126,14 @@ func main() { os.Exit(1) } + // Start logger + if flags.EnableLooger { + err = loggerHandler.Start() + if err != nil { + trace.Fatal().Err(err).Msg("starting logger") + } + } + // Open browser tabs openBrowserTabs(config) diff --git a/backend/cmd/orchestrator.go b/backend/cmd/orchestrator.go index e8ba68207..180b26c8d 100644 --- a/backend/cmd/orchestrator.go +++ b/backend/cmd/orchestrator.go @@ -9,6 +9,7 @@ import ( adj_module "github.com/HyperloopUPV-H8/h9-backend/internal/adj" "github.com/HyperloopUPV-H8/h9-backend/internal/config" + "github.com/HyperloopUPV-H8/h9-backend/internal/flags" "github.com/HyperloopUPV-H8/h9-backend/internal/pod_data" "github.com/HyperloopUPV-H8/h9-backend/pkg/abstraction" "github.com/HyperloopUPV-H8/h9-backend/pkg/logger" @@ -21,7 +22,7 @@ import ( // Handle version flag func handleVersionFlag() { - if *versionFlag { + if flags.Version { versionFile := "VERSION.txt" versionData, err := os.ReadFile(versionFile) if err == nil { @@ -43,8 +44,8 @@ func setupRuntimeCPU() func() { cleanup := func() {} runtime.GOMAXPROCS(runtime.NumCPU()) - if *cpuprofile != "" { - f, err := os.Create(*cpuprofile) + if flags.CPUProfile != "" { + f, err := os.Create(flags.CPUProfile) if err != nil { f.Close() trace.Fatal().Stack().Err(err).Msg("could not set up CPU profiling") @@ -57,7 +58,7 @@ func setupRuntimeCPU() func() { f.Close() } } - runtime.SetBlockProfileRate(*blockprofile) + runtime.SetBlockProfileRate(flags.BlockProfile) return cleanup } @@ -134,9 +135,9 @@ func createLookupTables( createBoardToPackets(podData) } -func setUpLogger(config config.Config) (*logger.Logger, SubloggersMap) { +func setUpLogger(config config.Config) (*logger.Logger, abstraction.SubloggersMap) { - var subloggers = SubloggersMap{ + var subloggers = abstraction.SubloggersMap{ data_logger.Name: data_logger.NewLogger(), order_logger.Name: order_logger.NewLogger(), } diff --git a/backend/cmd/setup_vehicle.go b/backend/cmd/setup_vehicle.go index d2f4cefcf..30a5b049d 100644 --- a/backend/cmd/setup_vehicle.go +++ b/backend/cmd/setup_vehicle.go @@ -7,6 +7,7 @@ import ( "os" "time" + "github.com/HyperloopUPV-H8/h9-backend/internal/flags" vehicle_models "github.com/HyperloopUPV-H8/h9-backend/internal/vehicle/models" h "github.com/HyperloopUPV-H8/h9-backend/pkg/http" "github.com/HyperloopUPV-H8/h9-backend/pkg/websocket" @@ -33,7 +34,7 @@ import ( trace "github.com/rs/zerolog/log" ) -func configureBroker(subloggers SubloggersMap, loggerHandler *logger.Logger, idToBoard map[abstraction.PacketId]string, connections chan *websocket.Client) (*broker.Broker, func()) { +func configureBroker(subloggers abstraction.SubloggersMap, loggerHandler *logger.Logger, idToBoard map[abstraction.PacketId]string, connections chan *websocket.Client) (*broker.Broker, func()) { broker := broker.New(trace.Logger) @@ -135,7 +136,7 @@ func configureVehicle( func configureSNTP(adj adj_module.ADJ) bool { - if *enableSNTP { + if flags.EnableSNTP { sntpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", adj.Info.Addresses[BACKEND], adj.Info.Ports[SNTP])) if err != nil { fmt.Fprintf(os.Stderr, "error resolving sntp address: %v\n", err) diff --git a/backend/go.mod b/backend/go.mod index b8dcb8938..2571668d5 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -7,13 +7,11 @@ require ( github.com/google/gopacket v1.1.19 github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.5.0 - github.com/hashicorp/go-version v1.7.0 github.com/jmaralo/sntp v0.0.0-20240116111937-45a0a3419272 github.com/pelletier/go-toml/v2 v2.0.7 github.com/pin/tftp/v3 v3.0.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/rs/zerolog v1.29.0 - github.com/stretchr/testify v1.9.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 ) @@ -23,7 +21,6 @@ require ( github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect @@ -34,7 +31,6 @@ require ( github.com/mattn/go-isatty v0.0.17 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect @@ -43,10 +39,8 @@ require ( golang.org/x/sys v0.31.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( - github.com/fatih/color v1.15.0 golang.org/x/net v0.38.0 // indirect ) diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index 930a68114..3be243de2 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -5,6 +5,7 @@ import ( "os" "strings" + "github.com/HyperloopUPV-H8/h9-backend/internal/flags" "github.com/pelletier/go-toml/v2" trace "github.com/rs/zerolog/log" ) @@ -22,8 +23,13 @@ func GetConfig(path string) (Config, error) { var config Config - // TODO: add strict mode (DisallowUnkownFields) - decodeErr := toml.NewDecoder(reader).Decode(&config) + decode := toml.NewDecoder(reader) + + // Set whether to disallow unknown fields based on the flag + if !flags.ConfigAllowUnknown { + decode.DisallowUnknownFields() + } + decodeErr := decode.Decode(&config) if decodeErr != nil { diff --git a/backend/internal/config/config_types.go b/backend/internal/config/config_types.go index f018f8af3..256ece881 100644 --- a/backend/internal/config/config_types.go +++ b/backend/internal/config/config_types.go @@ -14,10 +14,6 @@ type Adj struct { Branch string `toml:"branch"` } -type Network struct { - Manual bool `toml:"manual"` -} - type Transport struct { PropagateFault bool `toml:"propagate_fault"` } @@ -55,7 +51,6 @@ type Config struct { Vehicle vehicle.Config Server server.Config Adj Adj - Network Network Transport Transport TFTP TFTP TCP TCP diff --git a/backend/internal/flags/flags.go b/backend/internal/flags/flags.go new file mode 100644 index 000000000..1ed66bd67 --- /dev/null +++ b/backend/internal/flags/flags.go @@ -0,0 +1,43 @@ +// Package flags defines command-line flags for the backend application. +package flags + +import "flag" + +var ( + + // ConfigFile specifies the path to the configuration file. + ConfigFile string + // ConfigAllowUnknown enables non-strict mode for configuration parsing. + ConfigAllowUnknown bool + + // TraceLevel sets the logging level for tracing. + TraceLevel string + // TraceFile specifies the file to write trace logs to. + TraceFile string + + // CPUProfile specifies the file to write CPU profiling data to. + CPUProfile string + // EnableSNTP enables a simple SNTP server on port 123. + EnableSNTP bool + // BlockProfile sets the number of block profiles to include. + BlockProfile int + // Version shows the backend version when set. + Version bool + // EnableLooger enables logging (note: likely a typo for "Logger"). + EnableLooger bool +) + +// Init sets up the command-line flags with their default values and descriptions. +func Init() { + flag.StringVar(&ConfigFile, "config", "config.toml", "path to configuration file") + flag.BoolVar(&ConfigAllowUnknown, "config-allow-unknown", false, "allow unknown fields in configuration file") + flag.StringVar(&TraceLevel, "trace", "info", "set the trace level (\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\")") + flag.StringVar(&TraceFile, "log", "", "set the trace log file") + flag.StringVar(&CPUProfile, "cpuprofile", "", "write cpu profile to file") + flag.BoolVar(&EnableSNTP, "sntp", false, "enables a simple SNTP server on port 123") + flag.IntVar(&BlockProfile, "blockprofile", 0, "number of block profiles to include") + flag.BoolVar(&Version, "version", false, "Show the backend version") + flag.BoolVar(&EnableLooger, "L", false, "enable logging") + + flag.Parse() +} diff --git a/backend/pkg/abstraction/logger.go b/backend/pkg/abstraction/logger.go index df9d77391..a44ef1655 100644 --- a/backend/pkg/abstraction/logger.go +++ b/backend/pkg/abstraction/logger.go @@ -1,3 +1,4 @@ +// Package abstraction provides interfaces for logging functionality. package abstraction // LoggerName is the name of the logger that manages a piece of data @@ -23,3 +24,6 @@ type Logger interface { // PullRecord will retrieve a record from disk PullRecord(LoggerRequest) (LoggerRecord, error) } + +// SubloggersMap is a map of logger names to their respective loggers +type SubloggersMap map[LoggerName]Logger diff --git a/backend/pkg/logger/logger.go b/backend/pkg/logger/logger.go index 2dfd626ff..d1e9fd68d 100644 --- a/backend/pkg/logger/logger.go +++ b/backend/pkg/logger/logger.go @@ -1,3 +1,4 @@ +// Package logger provides logging functionality for the HyperLoop backend. package logger import ( @@ -12,7 +13,7 @@ import ( const ( Name = "loggerHandler" HandlerName = "logger" - TimestampFormat = "02-Jan-2006_15-04-05.000" + TimestampFormat = "2006-01-02T15-04-05" // ISO 8601 date for ensuring correct lexicographical order ) // Logger is a struct that implements the abstraction.Logger interface @@ -21,7 +22,7 @@ type Logger struct { running *atomic.Bool subloggersLock *sync.RWMutex // The subloggers are only the loggers selected at the start of the log - subloggers map[abstraction.LoggerName]abstraction.Logger + subloggers abstraction.SubloggersMap trace zerolog.Logger @@ -33,14 +34,14 @@ type Logger struct { ***************/ var _ abstraction.Logger = &Logger{} -// Used on subloggers to get the current timestamp for folder or file names +// Timestamp is used on subloggers to get the current timestamp for folder or file names var Timestamp = time.Now() var BasePath = "." func (Logger) HandlerName() string { return HandlerName } -func NewLogger(keys map[abstraction.LoggerName]abstraction.Logger, baseLogger zerolog.Logger) *Logger { +func NewLogger(keys abstraction.SubloggersMap, baseLogger zerolog.Logger) *Logger { trace := baseLogger.Sample(zerolog.LevelSampler{ TraceSampler: zerolog.RandomSampler(25000), DebugSampler: zerolog.RandomSampler(1), @@ -167,7 +168,7 @@ func (logger *Logger) Stop() error { return nil } -// Configures the logger atributes before inicialicing it +// ConfigureLogger configures the logger attributes before initializing it. func ConfigureLogger(unit TimeUnit, basePath string) { // Start the sublogger diff --git a/backend/pkg/logger/logger_test.go b/backend/pkg/logger/logger_test.go index ea89b33a6..729f89119 100644 --- a/backend/pkg/logger/logger_test.go +++ b/backend/pkg/logger/logger_test.go @@ -114,7 +114,7 @@ func TestLoggerGroup_Errors(t *testing.T) { _ = chdirTemp(t) // Change to a temporary directory // Logger with empty map → PushRecord should return error (no sublogger) - lEmpty := logger.NewLogger(map[abstraction.LoggerName]abstraction.Logger{}, zerolog.New(os.Stdout)) + lEmpty := logger.NewLogger(abstraction.SubloggersMap{}, zerolog.New(os.Stdout)) err := lEmpty.PushRecord(&mockRecord{n: abstraction.LoggerName("missing")}) if err == nil { t.Fatalf("expected error when PushRecord to non-existent sublogger, got nil") @@ -122,7 +122,7 @@ func TestLoggerGroup_Errors(t *testing.T) { // Logger whose sublogger returns error on Start → Start should propagate the error wantErr := os.ErrPermission - badMap := map[abstraction.LoggerName]abstraction.Logger{ + badMap := abstraction.SubloggersMap{ abstraction.LoggerName("bad"): &mockSublogger{startErr: wantErr}, } lBad := logger.NewLogger(badMap, zerolog.New(os.Stdout)) diff --git a/backend/pkg/transport/network/tftp/.gitignore b/backend/pkg/transport/network/tftp/.gitignore new file mode 100644 index 000000000..62c74bcbe --- /dev/null +++ b/backend/pkg/transport/network/tftp/.gitignore @@ -0,0 +1 @@ +testfile.txt \ No newline at end of file diff --git a/backend/pkg/transport/network/tftp/testfile.txt b/backend/pkg/transport/network/tftp/testfile.txt deleted file mode 100644 index b6fc4c620..000000000 --- a/backend/pkg/transport/network/tftp/testfile.txt +++ /dev/null @@ -1 +0,0 @@ -hello \ No newline at end of file