From b69097e2a42e4a1aeb658ef094e55f41e1ec7e7c Mon Sep 17 00:00:00 2001 From: Valentin Boulanger Date: Sun, 29 Dec 2024 13:09:46 +0100 Subject: [PATCH] improved log system --- .../src/components/Settings/Settings.svelte | 1 - go.mod | 1 + go.sum | 6 ++ hardware/FTDIDriver.go | 39 ++++++--- hardware/FTDIPeripheral.go | 85 ++++++++++--------- hardware/MIDIDriver.go | 31 +++++-- hardware/MIDIPeripheral.go | 3 + hardware/OS2LDriver.go | 14 ++- hardware/OS2LPeripheral.go | 13 +-- hardware/hardware.go | 55 +++++++++--- main.go | 21 ++++- peripherals.go | 17 +++- project.go | 72 +++++++++++----- 13 files changed, 247 insertions(+), 111 deletions(-) diff --git a/frontend/src/components/Settings/Settings.svelte b/frontend/src/components/Settings/Settings.svelte index 941be9d..8404cd0 100644 --- a/frontend/src/components/Settings/Settings.svelte +++ b/frontend/src/components/Settings/Settings.svelte @@ -72,7 +72,6 @@ - diff --git a/go.mod b/go.mod index 5df50d3..cb0683f 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.21.3 require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/mattrtaylor/go-rtmidi v0.0.0-20220428034745-af795b1c1a79 + github.com/rs/zerolog v1.33.0 github.com/wailsapp/wails/v2 v2.9.1 golang.org/x/sys v0.20.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 068125d..9d1a0a3 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,12 @@ github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -48,6 +50,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -85,6 +90,7 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/hardware/FTDIDriver.go b/hardware/FTDIDriver.go index c7bac99..ec84f82 100644 --- a/hardware/FTDIDriver.go +++ b/hardware/FTDIDriver.go @@ -11,6 +11,8 @@ import ( "strconv" "strings" "time" + + "github.com/rs/zerolog/log" ) const ( @@ -24,6 +26,7 @@ type FTDIDriver struct { // NewFTDIDriver creates a new FTDI finder func NewFTDIDriver() *FTDIDriver { + log.Trace().Str("file", "FTDIDriver").Msg("FTDI driver created") return &FTDIDriver{ peripherals: make(map[string]Peripheral), } @@ -32,9 +35,10 @@ func NewFTDIDriver() *FTDIDriver { // Initialize initializes the FTDI driver func (d *FTDIDriver) Initialize() error { if goRuntime.GOOS != "windows" { + log.Error().Str("file", "FTDIDriver").Str("platform", goRuntime.GOOS).Msg("FTDI driver not compatible with your platform") return fmt.Errorf(" The FTDI driver is not compatible with your platform yet (%s)", goRuntime.GOOS) } - fmt.Println("FTDI driver initialized") + log.Trace().Str("file", "FTDIDriver").Msg("FTDI driver initialized") return nil } @@ -48,11 +52,10 @@ func (d *FTDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) { // Return the specified peripheral peripheral := d.peripherals[peripheralID] if peripheral == nil { - fmt.Println("Unable to get the peripheral with the driver") + log.Error().Str("file", "FTDIDriver").Str("peripheralID", peripheralID).Msg("unable to get this peripheral from the FTDI driver") return nil, false } - fmt.Println("Peripheral found by the FTDI driver") - + log.Debug().Str("file", "FTDIDriver").Str("peripheralID", peripheralID).Msg("peripheral found by the FTDI driver") return peripheral, true } @@ -61,6 +64,7 @@ var findFTDI []byte // Scan scans the FTDI peripherals func (d *FTDIDriver) Scan(ctx context.Context) error { + log.Trace().Str("file", "FTDIDriver").Msg("FTDI scan triggered") time.Sleep(scanDelay) // Create a temporary file @@ -69,61 +73,68 @@ func (d *FTDIDriver) Scan(ctx context.Context) error { return err } defer os.Remove(tempFile.Name()) + log.Trace().Str("file", "FTDIDriver").Msg("has created the FIND executable temp") // Write the embedded executable to the temp file if _, err := tempFile.Write(findFTDI); err != nil { return err } tempFile.Close() + log.Trace().Str("file", "FTDIDriver").Msg("has written the FIND executable") ftdiPeripherals := make(map[string]Peripheral) finder := exec.Command(tempFile.Name()) + log.Trace().Str("file", "FTDIDriver").Msg("has executed the FIND executable") stdout, err := finder.StdoutPipe() if err != nil { - return fmt.Errorf("Unable to create the stdout pipe: %s", err) + return fmt.Errorf("unable to create the stdout pipe: %s", err) } stderr, err := finder.StderrPipe() if err != nil { - return fmt.Errorf("Unable to create the stderr pipe: %s", err) + return fmt.Errorf("unable to create the stderr pipe: %s", err) } err = finder.Start() if err != nil { - return fmt.Errorf("Unable to find FTDI devices: %s", err) + return fmt.Errorf("unable to find FTDI devices: %s", err) } scannerErr := bufio.NewScanner(stderr) for scannerErr.Scan() { - return fmt.Errorf("Unable to find FTDI devices: %s", scannerErr.Text()) + return fmt.Errorf("unable to find FTDI devices: %s", scannerErr.Text()) } scanner := bufio.NewScanner(stdout) for scanner.Scan() { - deviceString := scanner.Text() + peripheralString := scanner.Text() // The program output is like '0:1:2' where 0 is the location, 1 is the S/N and 2 is the name - deviceInfo := strings.Split(deviceString, ":") + peripheralInfo := strings.Split(peripheralString, ":") - fmt.Println("FTDI device: " + deviceString) + log.Debug().Str("file", "FTDIDriver").Str("peripheralName", peripheralInfo[2]).Str("peripheralSN", peripheralInfo[1]).Msg("new FTDI peripheral detected") // Convert the location to an integer - location, err := strconv.Atoi(deviceInfo[0]) + location, err := strconv.Atoi(peripheralInfo[0]) if err != nil { + log.Warn().Str("file", "FTDIDriver").Str("peripheralName", peripheralInfo[2]).Msg("no location provided for this FTDI peripheral") location = -1 } // Add the peripheral to the temporary list - peripheral, err := NewFTDIPeripheral(deviceInfo[2], deviceInfo[1], location) + peripheral, err := NewFTDIPeripheral(peripheralInfo[2], peripheralInfo[1], location) if err != nil { return fmt.Errorf("Unable to create the FTDI peripheral: %v", err) } - ftdiPeripherals[deviceInfo[1]] = peripheral + ftdiPeripherals[peripheralInfo[1]] = peripheral + log.Trace().Str("file", "FTDIDriver").Str("peripheralName", peripheralInfo[2]).Msg("successfully added the FTDI peripheral to the driver") } // Compare with the current peripherals to detect arrivals/removals removedList, addedList := comparePeripherals(d.peripherals, ftdiPeripherals) // Emit the events emitPeripheralsEvents(ctx, removedList, PeripheralRemoval) + log.Info().Str("file", "FTDIDriver").Msg("FTDI remove list emitted to the front") emitPeripheralsEvents(ctx, addedList, PeripheralArrival) + log.Info().Str("file", "FTDIDriver").Msg("FTDI add list emitted to the front") // Store the new peripherals list d.peripherals = ftdiPeripherals return nil diff --git a/hardware/FTDIPeripheral.go b/hardware/FTDIPeripheral.go index bb01147..5649bc1 100644 --- a/hardware/FTDIPeripheral.go +++ b/hardware/FTDIPeripheral.go @@ -5,7 +5,9 @@ import ( _ "embed" "fmt" "io" - "log" + + "github.com/rs/zerolog/log" + "os" "os/exec" "sync" @@ -38,16 +40,19 @@ type FTDIPeripheral struct { // NewFTDIPeripheral creates a new FTDI peripheral func NewFTDIPeripheral(name string, serialNumber string, location int) (*FTDIPeripheral, error) { + log.Info().Str("file", "FTDIPeripheral").Str("name", name).Str("s/n", serialNumber).Int("location", location).Msg("FTDI peripheral created") // Create a temporary file tempFile, err := os.CreateTemp("", "dmxSender*.exe") if err != nil { return nil, err } + log.Trace().Str("file", "FTDIPeripheral").Str("s/n", serialNumber).Msg("FTDI sender temp created") // Write the embedded executable to the temp file if _, err := tempFile.Write(dmxSender); err != nil { return nil, err } + log.Trace().Str("file", "FTDIPeripheral").Str("s/n", serialNumber).Msg("FTDI sender written") tempFile.Close() @@ -65,35 +70,40 @@ func NewFTDIPeripheral(name string, serialNumber string, location int) (*FTDIPer // Connect connects the FTDI peripheral func (p *FTDIPeripheral) Connect() error { // Connect if no connection is already running - fmt.Println(p.dmxSender) + log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("connecting FTDI peripheral...") if p.dmxSender == nil { + log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("no instance of dmxSender for this FTDI") + // Executing the command p.dmxSender = exec.Command(p.programName, fmt.Sprintf("%d", p.location)) + log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("no instance of dmxSender for this FTDI") var err error p.stdout, err = p.dmxSender.StdoutPipe() if err != nil { - log.Fatalf("Unable to create the stdout pipe: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to create the stdout pipe") + return fmt.Errorf("unable to create the stdout pipe: %v", err) } - p.stdin, err = p.dmxSender.StdinPipe() if err != nil { - log.Fatalf("Unable to create the stdin pipe: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to create the stdin pipe") + return fmt.Errorf("unable to create the stdin pipe: %v", err) } p.stderr, err = p.dmxSender.StderrPipe() if err != nil { - log.Fatalf("Unable to create the stderr pipe: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to create the stderr pipe") + return fmt.Errorf("unable to create the stderr pipe: %v", err) } go func() { scanner := bufio.NewScanner(p.stderr) for scanner.Scan() { // Traitez chaque ligne lue depuis stderr - fmt.Printf("Erreur : %s\n", scanner.Text()) + log.Err(fmt.Errorf(scanner.Text())).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error detected in dmx sender") } if err := scanner.Err(); err != nil { - log.Printf("Error reading from stderr: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error reading from stderr") } }() @@ -102,17 +112,12 @@ func (p *FTDIPeripheral) Connect() error { defer p.wg.Done() err = p.dmxSender.Run() if err != nil { - // Affiche l'erreur (cela inclut également les erreurs de retour du programme) - fmt.Printf("Erreur lors de l'exécution : %v\n", err) - - // Vérifie si l'erreur est liée au code de retour + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while execution of dmw sender") if exitError, ok := err.(*exec.ExitError); ok { - // Récupère et affiche le code de retour - fmt.Printf("Le programme s'est terminé avec le code : %d\n", exitError.ExitCode()) - fmt.Println(p.stderr) + log.Warn().Str("file", "FTDIPeripheral").Int("exitCode", exitError.ExitCode()).Str("s/n", p.serialNumber).Msg("dmx sender exited with code") } } else { - fmt.Println("Le programme s'est terminé avec succès.") + log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmx sender exited successfully") } }() } @@ -121,74 +126,72 @@ func (p *FTDIPeripheral) Connect() error { // Disconnect disconnects the FTDI peripheral func (p *FTDIPeripheral) Disconnect() error { + log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("disconnecting FTDI peripheral...") if p.dmxSender != nil { + log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI") _, err := io.WriteString(p.stdin, string([]byte{0x04, 0x00, 0x00, 0x00})) if err != nil { - return fmt.Errorf("Unable to disconnect: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender") + return fmt.Errorf("unable to disconnect: %v", err) } p.stdin.Close() p.stdout.Close() p.dmxSender = nil err = os.Remove(p.programName) if err != nil { - return fmt.Errorf("Unable to delete the temporary file: %v", err) + log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to delete the dmx sender temporary file") + return fmt.Errorf("unable to delete the temporary file: %v", err) } return nil } - return fmt.Errorf("Unable to disconnect: not connected") - // if p.dmxSender != nil { - // err := p.dmxSender.Process.Kill() - // if err != nil { - // return fmt.Errorf("Unable to disconnect: %v", err) - // } - // p.stdin.Close() - // p.stdout.Close() - // p.dmxSender = nil - // err = os.Remove(p.programName) - // if err != nil { - // return fmt.Errorf("Unable to delete the temporary file: %v", err) - // } - // return nil - // } - // return fmt.Errorf("Unable to disconnect: not connected") + log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while disconnecting: not connected") + return fmt.Errorf("unable to disconnect: not connected") } // Activate activates the FTDI peripheral func (p *FTDIPeripheral) Activate() error { if p.dmxSender != nil { + log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI") _, err := io.WriteString(p.stdin, string([]byte{0x01, 0x00, 0x00, 0x00})) if err != nil { - return fmt.Errorf("Unable to activate: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender") + return fmt.Errorf("unable to activate: %v", err) } return nil } - return fmt.Errorf("Unable to activate: not connected") + log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while activating: not connected") + return fmt.Errorf("unable to activate: not connected") } // Deactivate deactivates the FTDI peripheral func (p *FTDIPeripheral) Deactivate() error { if p.dmxSender != nil { + log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI") _, err := io.WriteString(p.stdin, string([]byte{0x02, 0x00, 0x00, 0x00})) if err != nil { - return fmt.Errorf("Unable to deactivate: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender") + return fmt.Errorf("unable to deactivate: %v", err) } return nil } - return fmt.Errorf("Unable to deactivate: not connected") + log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while deactivating: not connected") + return fmt.Errorf("unable to deactivate: not connected") } // SetDeviceProperty sends a command to the specified device func (p *FTDIPeripheral) SetDeviceProperty(uint32, channelNumber uint32, channelValue byte) error { if p.dmxSender != nil { - fmt.Println(channelValue) + log.Debug().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("dmxsender is defined for this FTDI") commandString := []byte{0x03, 0x01, 0x00, 0xff, 0x03, 0x02, 0x00, channelValue} _, err := io.WriteString(p.stdin, string(commandString)) if err != nil { - return fmt.Errorf("Unable to set device property: %v", err) + log.Err(err).Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("unable to write command to sender") + return fmt.Errorf("unable to set device property: %v", err) } return nil } - return fmt.Errorf("Unable to set device property: not connected") + log.Warn().Str("file", "FTDIPeripheral").Str("s/n", p.serialNumber).Msg("error while setting device property: not connected") + return fmt.Errorf("unable to set device property: not connected") } // GetInfo gets all the peripheral information diff --git a/hardware/MIDIDriver.go b/hardware/MIDIDriver.go index b9e4018..7137334 100644 --- a/hardware/MIDIDriver.go +++ b/hardware/MIDIDriver.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/mattrtaylor/go-rtmidi" + "github.com/rs/zerolog/log" ) // MIDIDriver represents how the protocol is defined @@ -17,6 +18,7 @@ type MIDIDriver struct { // NewMIDIDriver creates a new DMXUSB protocol func NewMIDIDriver() *MIDIDriver { + log.Trace().Str("file", "MIDIDriver").Msg("MIDI driver created") return &MIDIDriver{ peripherals: make(map[string]Peripheral), } @@ -24,7 +26,7 @@ func NewMIDIDriver() *MIDIDriver { // Initialize initializes the MIDI driver func (d *MIDIDriver) Initialize() error { - fmt.Println("MIDI driver initialized") + log.Trace().Str("file", "MIDIDriver").Msg("MIDI driver initialized") return nil } @@ -36,10 +38,12 @@ func (d *MIDIDriver) GetName() string { // GetPeripheral gets the peripheral that correspond to the specified ID func (d *MIDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) { // Return the specified peripheral - peripheral := d.peripherals[peripheralID] - if peripheral == nil { + peripheral, found := d.peripherals[peripheralID] + if !found { + log.Error().Str("file", "MIDIDriver").Str("peripheralID", peripheralID).Msg("unable to get this peripheral in the MIDI driver") return nil, false } + log.Trace().Str("file", "MIDIDriver").Str("peripheralID", peripheralID).Msg("MIDI peripheral found in the driver") return peripheral, true } @@ -67,28 +71,35 @@ func splitStringAndNumber(input string) (string, int, error) { // Scan scans the interfaces compatible with the MIDI protocol func (d *MIDIDriver) Scan(ctx context.Context) error { midiPeripherals := make(map[string]Peripheral) - fmt.Println("Opening MIDI scanner port...") + log.Trace().Str("file", "MIDIDriver").Msg("opening MIDI scanner port...") midiScanner, err := rtmidi.NewMIDIInDefault() if err != nil { - return fmt.Errorf("Error when opening the MIDI scanner: %s", err) + log.Err(err).Str("file", "MIDIDriver").Msg("unable to open the MIDI scanner port...") + return fmt.Errorf("unable to open the MIDI scanner: %s", err) } defer midiScanner.Close() - fmt.Println("Scanning MIDI devices...") + midiScanner.SetCallback(func(m rtmidi.MIDIIn, b []byte, f float64) { + + }) + log.Trace().Str("file", "MIDIDriver").Msg("scanning MIDI peripherals...") devicesCount, err := midiScanner.PortCount() if err != nil { - return fmt.Errorf("Error when scanning MIDI devices: %s", err) + log.Err(err).Str("file", "MIDIDriver").Msg("unable to scan MIDI peripherals...") + return fmt.Errorf("unable to scan MIDI peripherals: %s", err) } for i := 0; i < devicesCount; i++ { portName, err := midiScanner.PortName(i) if err != nil { + log.Warn().Str("file", "MIDIPeripheral").Msg("found peripheral without a correct name, set it to unknown") portName = "Unknown device 0" } // Separate data name, location, err := splitStringAndNumber(portName) if err != nil { - return fmt.Errorf("Unable to get information from the string: %s", err) + log.Err(err).Str("file", "MIDIDriver").Str("description", portName).Msg("invalid peripheral description") + return fmt.Errorf("invalid pripheral description: %s", err) } - fmt.Printf("New MIDI device found: %s on %i\n", name, location) + log.Info().Str("file", "MIDIDriver").Str("name", name).Int("location", location).Msg("MIDI peripheral found") // Add the peripheral to the temporary list sn := strings.ToLower(strings.Replace(name, " ", "_", -1)) midiPeripherals[sn] = NewMIDIPeripheral(name, location, sn) @@ -97,7 +108,9 @@ func (d *MIDIDriver) Scan(ctx context.Context) error { removedList, addedList := comparePeripherals(d.peripherals, midiPeripherals) // Emit the events emitPeripheralsEvents(ctx, removedList, PeripheralRemoval) + log.Info().Str("file", "MIDIDriver").Msg("MIDI remove list emitted to the front") emitPeripheralsEvents(ctx, addedList, PeripheralArrival) + log.Info().Str("file", "MIDIDriver").Msg("MIDI add list emitted to the front") // Store the new peripherals list d.peripherals = midiPeripherals return nil diff --git a/hardware/MIDIPeripheral.go b/hardware/MIDIPeripheral.go index 8d9e073..92f95d5 100644 --- a/hardware/MIDIPeripheral.go +++ b/hardware/MIDIPeripheral.go @@ -1,5 +1,7 @@ package hardware +import "github.com/rs/zerolog/log" + // MIDIPeripheral contains the data of a MIDI peripheral type MIDIPeripheral struct { name string // The name of the peripheral @@ -9,6 +11,7 @@ type MIDIPeripheral struct { // NewMIDIPeripheral creates a new MIDI peripheral func NewMIDIPeripheral(name string, location int, serialNumber string) *MIDIPeripheral { + log.Trace().Str("file", "MIDIPeripheral").Str("name", name).Str("s/n", serialNumber).Int("location", location).Msg("MIDI peripheral created") return &MIDIPeripheral{ name: name, location: location, diff --git a/hardware/OS2LDriver.go b/hardware/OS2LDriver.go index b7fc7ea..8362b49 100644 --- a/hardware/OS2LDriver.go +++ b/hardware/OS2LDriver.go @@ -5,6 +5,8 @@ import ( "fmt" "math/rand" "strings" + + "github.com/rs/zerolog/log" ) // OS2LDriver represents how the protocol is defined @@ -14,6 +16,7 @@ type OS2LDriver struct { // NewOS2LDriver creates a new OS2L driver func NewOS2LDriver() *OS2LDriver { + log.Trace().Str("file", "OS2LDriver").Msg("OS2L driver created") return &OS2LDriver{ peripherals: make(map[string]Peripheral), } @@ -21,7 +24,7 @@ func NewOS2LDriver() *OS2LDriver { // Initialize initializes the MIDI driver func (d *OS2LDriver) Initialize() error { - fmt.Println("OS2L driver initialized") + log.Trace().Str("file", "OS2LDriver").Msg("OS2L driver initialized") return nil } @@ -29,14 +32,17 @@ func (d *OS2LDriver) Initialize() error { func (d *OS2LDriver) CreatePeripheral(ctx context.Context) (Peripheral, error) { // Create a random serial number for this peripheral randomSerialNumber := strings.ToUpper(fmt.Sprintf("%08x", rand.Intn(1<<32))) + log.Trace().Str("file", "OS2LDriver").Str("serialNumber", randomSerialNumber).Msg("OS2L peripheral created") peripheral := NewOS2LPeripheral("OS2L", randomSerialNumber) d.peripherals[randomSerialNumber] = peripheral + log.Info().Str("file", "OS2LDriver").Str("serialNumber", randomSerialNumber).Msg("OS2L peripheral created and registered") return peripheral, nil } // RemovePeripheral removes an OS2L dev func (d *OS2LDriver) RemovePeripheral(serialNumber string) error { delete(d.peripherals, serialNumber) + log.Info().Str("file", "OS2LDriver").Str("serialNumber", serialNumber).Msg("OS2L peripheral removed") return nil } @@ -48,10 +54,12 @@ func (d *OS2LDriver) GetName() string { // GetPeripheral gets the peripheral that correspond to the specified ID func (d *OS2LDriver) GetPeripheral(peripheralID string) (Peripheral, bool) { // Return the specified peripheral - peripheral := d.peripherals[peripheralID] - if peripheral == nil { + peripheral, found := d.peripherals[peripheralID] + if !found { + log.Error().Str("file", "OS2LDriver").Str("peripheralID", peripheralID).Msg("unable to get this peripheral in the OS2L driver") return nil, false } + log.Trace().Str("file", "OS2LDriver").Str("peripheralID", peripheralID).Msg("OS2L peripheral found in the driver") return peripheral, true } diff --git a/hardware/OS2LPeripheral.go b/hardware/OS2LPeripheral.go index 4d62703..222b7e4 100644 --- a/hardware/OS2LPeripheral.go +++ b/hardware/OS2LPeripheral.go @@ -1,6 +1,8 @@ package hardware -import "fmt" +import ( + "github.com/rs/zerolog/log" +) // OS2LPeripheral contains the data of an OS2L peripheral type OS2LPeripheral struct { @@ -10,6 +12,7 @@ type OS2LPeripheral struct { // NewOS2LPeripheral creates a new OS2L peripheral func NewOS2LPeripheral(name string, serialNumber string) *OS2LPeripheral { + log.Trace().Str("file", "OS2LPeripheral").Str("name", name).Str("s/n", serialNumber).Msg("OS2L peripheral created") return &OS2LPeripheral{ name: name, serialNumber: serialNumber, @@ -18,25 +21,25 @@ func NewOS2LPeripheral(name string, serialNumber string) *OS2LPeripheral { // Connect connects the MIDI peripheral func (p *OS2LPeripheral) Connect() error { - fmt.Println("OS2L peripheral connected") + log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral connected") return nil } // Disconnect disconnects the MIDI peripheral func (p *OS2LPeripheral) Disconnect() error { - fmt.Println("OS2L peripheral disconnected") + log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral disconnected") return nil } // Activate activates the MIDI peripheral func (p *OS2LPeripheral) Activate() error { - fmt.Println("OS2L peripheral activated") + log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral activated") return nil } // Deactivate deactivates the MIDI peripheral func (p *OS2LPeripheral) Deactivate() error { - fmt.Println("OS2L peripheral deactivated") + log.Info().Str("file", "OS2LPeripheral").Msg("OS2L peripheral deactivated") return nil } diff --git a/hardware/hardware.go b/hardware/hardware.go index 71b63c5..a540d56 100644 --- a/hardware/hardware.go +++ b/hardware/hardware.go @@ -7,6 +7,8 @@ import ( "time" "unsafe" + "github.com/rs/zerolog/log" + "github.com/lxn/win" "github.com/wailsapp/wails/v2/pkg/runtime" "golang.org/x/sys/windows" @@ -37,6 +39,7 @@ type HardwareManager struct { // NewHardwareManager creates a new HardwareManager func NewHardwareManager() *HardwareManager { + log.Trace().Str("package", "hardware").Msg("Hardware instance created") return &HardwareManager{ drivers: make(map[string]PeripheralDriver), peripherals: make([]Peripheral, 0), @@ -44,13 +47,17 @@ func NewHardwareManager() *HardwareManager { } } -// Start starts to finding new device events +// Start starts to find new peripheral events func (h *HardwareManager) Start(ctx context.Context) error { cb := windows.NewCallback(h.wndProc) + log.Trace().Str("file", "hardware").Msg("wndProc callback set") inst := win.GetModuleHandle(nil) - cn, err := syscall.UTF16PtrFromString("DMXConnect device watcher") + log.Trace().Str("file", "hardware").Msg("got windows API instance") + + cn, err := syscall.UTF16PtrFromString("DMXConnect peripheral watcher") if err != nil { + log.Err(err).Str("file", "hardware").Msg("failed to convert window class name to UTF16") return fmt.Errorf("failed to convert window class name to UTF16: %w", err) } wc := win.WNDCLASSEX{ @@ -58,12 +65,18 @@ func (h *HardwareManager) Start(ctx context.Context) error { LpfnWndProc: cb, LpszClassName: cn, } + log.Trace().Str("file", "hardware").Msg("windows API class created") + wc.CbSize = uint32(unsafe.Sizeof(wc)) if win.RegisterClassEx(&wc) == 0 { + log.Err(syscall.GetLastError()).Str("file", "hardware").Msg("failed to register window class") return fmt.Errorf("failed to register window class: %w", syscall.GetLastError()) } + log.Trace().Str("file", "hardware").Msg("window class registered") + wName, err := syscall.UTF16PtrFromString("usbevent.exe") if err != nil { + log.Err(err).Str("file", "hardware").Msg("failed to convert window class name to UTF16") return fmt.Errorf("failed to convert window name to UTF16: %w", err) } wdw := win.CreateWindowEx( @@ -80,14 +93,18 @@ func (h *HardwareManager) Start(ctx context.Context) error { wc.HInstance, nil) if wdw == 0 { + log.Err(syscall.GetLastError()).Str("file", "hardware").Msg("failed to create window") return fmt.Errorf("failed to create window: %w", syscall.GetLastError()) } + log.Trace().Str("file", "hardware").Msg("window created successfully") _ = win.ShowWindow(wdw, win.SW_HIDE) win.UpdateWindow(wdw) + log.Trace().Str("file", "hardware").Msg("window shown and updated") // To continuously get the devices events from Windows go func() { + defer log.Debug().Str("file", "hardware").Msg("peripheral watcher goroutine exited") for { select { case <-ctx.Done(): @@ -105,13 +122,17 @@ func (h *HardwareManager) Start(ctx context.Context) error { // To handle the peripheral changed go func() { + defer log.Debug().Str("file", "hardware").Msg("peripheral getter goroutine exited") for { select { case <-ctx.Done(): return case <-h.deviceChangedEvent: - fmt.Println("This is the list of devices") - h.Scan(ctx) + log.Debug().Str("file", "hardware").Msg("peripheral change event, triggering scan...") + err := h.Scan(ctx) + if err != nil { + log.Err(err).Str("file", "hardware").Msg("unable to scan peripherals") + } } } }() @@ -122,26 +143,29 @@ func (h *HardwareManager) Start(ctx context.Context) error { func (h *HardwareManager) GetDriver(driverName string) (PeripheralDriver, error) { driver, exists := h.drivers[driverName] if !exists { + log.Error().Str("file", "hardware").Str("driverName", driverName).Msg("unable to get the driver") return nil, fmt.Errorf("Unable to locate the '%s' driver", driverName) } + log.Debug().Str("file", "hardware").Str("driverName", driverName).Msg("got driver") return driver, nil } // RegisterDriver registers a new peripherals driver func (h *HardwareManager) RegisterDriver(driver PeripheralDriver) { h.drivers[driver.GetName()] = driver - fmt.Printf("Success registered the %s driver\n", driver.GetName()) + log.Info().Str("file", "hardware").Str("driverName", driver.GetName()).Msg("driver registered") } // GetPeripheral gets the peripheral object from the parent driver func (h *HardwareManager) GetPeripheral(driverName string, peripheralID string) (Peripheral, bool) { // Get the driver - parentDriver := h.drivers[driverName] + parentDriver, found := h.drivers[driverName] // If no driver found, return false - if parentDriver == nil { - fmt.Println("Unable to get the driver") + if !found { + log.Error().Str("file", "hardware").Str("driverName", driverName).Msg("unable to get the driver") return nil, false } + log.Trace().Str("file", "hardware").Str("driverName", parentDriver.GetName()).Msg("driver got") // Contact the driver to get the device return parentDriver.GetPeripheral(peripheralID) } @@ -149,14 +173,15 @@ func (h *HardwareManager) GetPeripheral(driverName string, peripheralID string) // Scan scans all the peripherals for the registered finders func (h *HardwareManager) Scan(ctx context.Context) error { if len(h.drivers) == 0 { - return fmt.Errorf("No peripherals driver registered") + log.Warn().Str("file", "hardware").Msg("no driver registered") + return fmt.Errorf("no driver registered") } for _, driver := range h.drivers { driverCopy := driver go func() { err := driverCopy.Scan(ctx) if err != nil { - fmt.Printf("Unable to scan peripherals with the %s driver: %s\n", driverCopy.GetName(), err) + log.Err(err).Str("file", "hardware").Str("driverName", driverCopy.GetName()).Msg("unable to scan peripheral") return } }() @@ -170,9 +195,10 @@ func (h *HardwareManager) wndProc(hwnd windows.HWND, msg uint32, wParam, lParam // Trigger the devices scan when the last DEVICE_CHANGE event is received if debounceTimer != nil { debounceTimer.Stop() + log.Trace().Str("file", "hardware").Msg("scan debounce timer stopped") } debounceTimer = time.AfterFunc(debounceDuration, func() { - fmt.Printf("Devices list has changed, refresh the devices list\n") + log.Debug().Str("file", "hardware").Msg("peripheral changed") h.deviceChangedEvent <- struct{}{} }) } @@ -183,6 +209,7 @@ func (h *HardwareManager) wndProc(hwnd windows.HWND, msg uint32, wParam, lParam func emitPeripheralsEvents(ctx context.Context, peripheralsList map[string]Peripheral, peripheralEvent PeripheralEvent) { for _, peripheral := range peripheralsList { runtime.EventsEmit(ctx, string(peripheralEvent), peripheral.GetInfo()) + log.Trace().Str("file", "hardware").Str("event", string(peripheralEvent)).Msg("emit peripheral event") } } @@ -195,9 +222,11 @@ func comparePeripherals(oldPeripherals map[string]Peripheral, newPeripherals map for key, value := range oldPeripherals { oldList[key] = value } + log.Trace().Str("file", "hardware").Any("oldList", oldList).Msg("peripheral oldList comparison") for key, value := range newPeripherals { newList[key] = value } + log.Trace().Str("file", "hardware").Any("newList", newList).Msg("peripheral newList comparison") // Remove in these lists all the commons peripherals for key := range newList { if _, exists := oldList[key]; exists { @@ -206,7 +235,7 @@ func comparePeripherals(oldPeripherals map[string]Peripheral, newPeripherals map } } // Now the old list contains the removed peripherals, and the new list contains the added peripherals - fmt.Printf("%s\n", oldList) - fmt.Printf("%s\n", newList) + log.Trace().Str("file", "hardware").Any("oldList", oldList).Msg("peripheral oldList computed") + log.Trace().Str("file", "hardware").Any("newList", newList).Msg("peripheral newList computed") return oldList, newList } diff --git a/main.go b/main.go index ae86fa3..d5783a3 100644 --- a/main.go +++ b/main.go @@ -2,8 +2,14 @@ package main import ( "embed" + "time" + "os" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/logger" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" ) @@ -12,6 +18,16 @@ import ( var assets embed.FS func main() { + // Configure the logger + log.Logger = log.Output(zerolog.ConsoleWriter{ + Out: os.Stderr, + TimeFormat: "2006-01-02 15:04:05", + }) + zerolog.TimestampFunc = func() time.Time { + return time.Now().Local() + } + zerolog.SetGlobalLevel(zerolog.TraceLevel) + // Create an instance of the app structure app := NewApp() @@ -28,9 +44,10 @@ func main() { Bind: []interface{}{ app, }, + LogLevel: logger.ERROR, }) if err != nil { - println("Error:", err.Error()) + log.Err(err).Str("file", "main").Msg("unable to start the application") } -} \ No newline at end of file +} diff --git a/peripherals.go b/peripherals.go index d944aec..a5ffce3 100644 --- a/peripherals.go +++ b/peripherals.go @@ -3,10 +3,13 @@ package main import ( "changeme/hardware" "fmt" + + "github.com/rs/zerolog/log" ) // GetPeripherals gets all the peripherals connected func (a *App) GetPeripherals() error { + log.Debug().Str("file", "peripherals").Msg("getting peripherals...") return a.hardwareManager.Scan(a.ctx) } @@ -15,10 +18,13 @@ func (a *App) AddPeripheral(protocolName string, peripheralID string) error { // Get the device from its finder p, found := a.hardwareManager.GetPeripheral(protocolName, peripheralID) if !found { - return fmt.Errorf("Unable to localize the peripheral %s", peripheralID) + log.Error().Str("file", "peripheral").Str("protocolName", protocolName).Str("periphID", peripheralID).Msg("unable to found the specified peripheral") + return fmt.Errorf("unable to found the peripheral ID '%s'", peripheralID) } // Add the peripheral ID to the project a.projectInfo.PeripheralsInfo[peripheralID] = p.GetInfo() + log.Info().Str("file", "peripheral").Str("protocolName", protocolName).Str("periphID", peripheralID).Msg("peripheral added to project") + // TODO: Connect the peripheral return nil } @@ -28,6 +34,7 @@ func (a *App) RemovePeripheral(protocolName string, peripheralID string) error { // TODO: Disconnect the peripheral // Remove the peripheral ID from the project delete(a.projectInfo.PeripheralsInfo, peripheralID) + log.Info().Str("file", "peripheral").Str("protocolName", protocolName).Str("periphID", peripheralID).Msg("peripheral removed from project") return nil } @@ -36,14 +43,20 @@ func (a *App) AddOS2LPeripheral() (hardware.PeripheralInfo, error) { // Get the OS2L driver os2lDriver, err := a.hardwareManager.GetDriver("OS2L") if err != nil { + log.Err(err).Str("file", "peripheral").Msg("unable to found the OS2L driver") return hardware.PeripheralInfo{}, err } + log.Trace().Str("file", "peripheral").Msg("OS2L driver got") + // Create a new OS2L peripheral with this driver os2lPeripheral, err := os2lDriver.CreatePeripheral(a.ctx) if err != nil { - return hardware.PeripheralInfo{}, nil + log.Err(err).Str("file", "peripheral").Msg("unable to create the OS2L peripheral") + return hardware.PeripheralInfo{}, err } + os2lInfo := os2lPeripheral.GetInfo() + log.Info().Str("file", "peripheral").Str("s/n", os2lInfo.SerialNumber).Msg("OS2L peripheral created, adding to project") // Add this new peripheral to the project return os2lInfo, a.AddPeripheral(os2lDriver.GetName(), os2lInfo.SerialNumber) } diff --git a/project.go b/project.go index dbcd539..7b51a73 100644 --- a/project.go +++ b/project.go @@ -3,7 +3,9 @@ package main import ( "changeme/hardware" "fmt" - "log" + + "github.com/rs/zerolog/log" + "os" "path/filepath" "time" @@ -24,31 +26,42 @@ func (a *App) GetProjects() ([]ProjectMetaData, error) { f, err := os.Open(projectsDirectory) if err != nil { - log.Fatalf("Unable to open the projects directory: %v", err) - return nil, err + log.Err(err).Str("file", "project").Msg("unable to open the projects directory") + return nil, fmt.Errorf("unable to open the projects directory: %v", err) } + log.Trace().Str("file", "project").Str("projectsDirectory", projectsDirectory).Msg("projects directory opened") files, err := f.Readdir(0) if err != nil { - log.Fatalf("Unable to read the projects directory: %v", err) - return nil, err + log.Err(err).Str("file", "project").Msg("unable to read the projects directory") + return nil, fmt.Errorf("unable to read the projects directory: %v", err) } + log.Trace().Str("file", "project").Any("projectsFiles", files).Msg("project files got") for _, fileInfo := range files { // Open the file and get the show name fileData, err := os.ReadFile(filepath.Join(projectsDirectory, fileInfo.Name())) - if err == nil { - projectObject := ProjectInfo{} - err = yaml.Unmarshal(fileData, &projectObject) - if err == nil { - // Add the SaveFile property - projects = append(projects, ProjectMetaData{ - Name: projectObject.ShowInfo.Name, - Save: fileInfo.Name(), - }) - } + if err != nil { + log.Warn().Str("file", "project").Str("projectFile", fileInfo.Name()).Msg("unable to open the project file") + continue } + log.Trace().Str("file", "project").Str("projectFile", fileInfo.Name()).Any("fileData", fileData).Msg("project file read") + + projectObject := ProjectInfo{} + err = yaml.Unmarshal(fileData, &projectObject) + if err != nil { + log.Warn().Str("file", "project").Str("projectFile", fileInfo.Name()).Msg("project has invalid format") + continue + } + log.Trace().Str("file", "project").Str("projectFile", fileInfo.Name()).Msg("project file unmarshalled") + + // Add the SaveFile property + projects = append(projects, ProjectMetaData{ + Name: projectObject.ShowInfo.Name, + Save: fileInfo.Name(), + }) } + log.Info().Str("file", "project").Any("projectsList", projects).Msg("got the projects list") return projects, nil } @@ -62,6 +75,7 @@ func (a *App) CreateProject() ShowInfo { Avatar: "appicon.png", Comments: "Write your comments here", } + log.Info().Str("file", "project").Any("showInfo", a.projectInfo.ShowInfo).Msg("project has been created") return a.projectInfo.ShowInfo } @@ -69,20 +83,24 @@ func (a *App) CreateProject() ShowInfo { func (a *App) GetProjectInfo(projectFile string) (ProjectInfo, error) { // Open the project file projectPath := filepath.Join(projectsDirectory, projectFile) + log.Trace().Str("file", "project").Str("projectPath", projectPath).Msg("project path is created") content, err := os.ReadFile(projectPath) if err != nil { - log.Fatalf("Unable to read the project file: %v", err) - return ProjectInfo{}, err + log.Err(err).Str("file", "project").Str("projectFile", projectFile).Msg("Unable to read the project file") + return ProjectInfo{}, fmt.Errorf("unable to read the project file: %v", err) } + log.Trace().Str("file", "project").Str("projectPath", projectPath).Msg("project file read") a.projectInfo = ProjectInfo{} err = yaml.Unmarshal(content, &a.projectInfo) if err != nil { - log.Fatalf("Unable to get the project information: %v", err) - return ProjectInfo{}, err + log.Err(err).Str("file", "project").Str("projectFile", projectFile).Msg("Unable to get the project information") + return ProjectInfo{}, fmt.Errorf("unable to get the project information: %v", err) } + log.Trace().Str("file", "project").Str("projectPath", projectPath).Msg("project information got") // Load it into the app a.projectSave = projectFile // Return the show information + log.Info().Str("file", "project").Any("projectInfo", a.projectInfo).Msg("got the project information") return a.projectInfo, nil } @@ -99,44 +117,56 @@ func (a *App) ChooseAvatarPath() (string, error) { }, }) if err != nil { + log.Err(err).Str("file", "project").Msg("unable to open the avatar dialog") return "", err } + log.Debug().Str("file", "project").Msg("avatar dialog is opened") // Copy the avatar to the application avatars path avatarPath := filepath.Join(avatarsDirectory, filepath.Base(filePath)) + log.Trace().Str("file", "project").Str("avatarPath", avatarPath).Msg("avatar path is created") _, err = copy(filePath, avatarPath) if err != nil { + log.Err(err).Str("file", "project").Str("avatarsDirectory", avatarsDirectory).Str("fileBase", filepath.Base(filePath)).Msg("unable to copy the avatar file") return "", err } + log.Info().Str("file", "project").Str("avatarFileName", filepath.Base(filePath)).Msg("got the new avatar file") return filepath.Base(filePath), nil } // UpdateShowInfo updates the show information func (a *App) UpdateShowInfo(showInfo ShowInfo) { - fmt.Printf("%s\n", showInfo) a.projectInfo.ShowInfo = showInfo + log.Info().Str("file", "project").Any("showInfo", showInfo).Msg("show information was updated") } // SaveProject saves the project func (a *App) SaveProject() (string, error) { - log.Printf("Saving the project %s to %s", a.projectInfo.ShowInfo.Name, a.projectSave) // If there is no save file, create a new one with the show name if a.projectSave == "" { date := time.Now() a.projectSave = fmt.Sprintf("%04d%02d%02d%02d%02d%02d%s", date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), projectExtension) + log.Debug().Str("file", "project").Str("newProjectSave", a.projectSave).Msg("projectSave is null, getting a new one") } data, err := yaml.Marshal(a.projectInfo) if err != nil { + log.Err(err).Str("file", "project").Any("projectInfo", a.projectInfo).Msg("unable to format the project information") return "", err } + log.Trace().Str("file", "project").Any("projectInfo", a.projectInfo).Msg("projectInfo has been marshalled") // Create the project directory if not exists err = os.MkdirAll(projectsDirectory, os.ModePerm) if err != nil { + log.Err(err).Str("file", "project").Str("projectsDirectory", projectsDirectory).Msg("unable to create the projects directory") return "", err } + log.Trace().Str("file", "project").Str("projectsDirectory", projectsDirectory).Msg("projects directory has been created") + err = os.WriteFile(filepath.Join(projectsDirectory, a.projectSave), data, os.ModePerm) if err != nil { + log.Err(err).Str("file", "project").Str("projectsDirectory", projectsDirectory).Str("projectSave", a.projectSave).Msg("unable to save the project") return "", err } + log.Info().Str("file", "project").Str("projectFileName", a.projectSave).Msg("project has been saved") return a.projectSave, nil }