Add better logging.
This commit is contained in:
		
							parent
							
								
									6b7c8d7316
								
							
						
					
					
						commit
						9b9160405e
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +1,3 @@
 | 
				
			|||||||
config.yaml
 | 
					config.yaml
 | 
				
			||||||
midi-request-trigger
 | 
					midi-request-trigger
 | 
				
			||||||
 | 
					midi-request-trigger.log
 | 
				
			||||||
							
								
								
									
										128
									
								
								config.go
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								config.go
									
									
									
									
									
								
							@ -1,13 +1,17 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"log"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/user"
 | 
						"os/user"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kkyr/fig"
 | 
						"github.com/kkyr/fig"
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
						"gopkg.in/natefinch/lumberjack.v2"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Configurations relating to HTTP server.
 | 
					// Configurations relating to HTTP server.
 | 
				
			||||||
@ -19,9 +23,127 @@ type HTTPConfig struct {
 | 
				
			|||||||
	Enabled  bool   `fig:"enabled"`
 | 
						Enabled  bool   `fig:"enabled"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Configuration for logging.
 | 
				
			||||||
 | 
					type LogConfig struct {
 | 
				
			||||||
 | 
						// Limit the log output by the log level.
 | 
				
			||||||
 | 
						Level string `fig:"level" yaml:"level" enum:"debug,info,warn,error" default:"info"`
 | 
				
			||||||
 | 
						// How should the log output be formatted.
 | 
				
			||||||
 | 
						Type string `fig:"type" yaml:"type" enum:"json,console" default:"console"`
 | 
				
			||||||
 | 
						// The outputs that the log should go to. Output of `console` will
 | 
				
			||||||
 | 
						// go to the stderr. An file path, will log to the file. Using `default-file`
 | 
				
			||||||
 | 
						// it'll either save to `/var/log/name.log`, or to the same directory as the
 | 
				
			||||||
 | 
						// executable if the path is not writable, or on Windows.
 | 
				
			||||||
 | 
						Outputs []string `fig:"outputs" yaml:"outputs" default:"[console,default-file]"`
 | 
				
			||||||
 | 
						// Maximum size of the log file in megabytes before it gets rotated.
 | 
				
			||||||
 | 
						MaxSize int `fig:"max_size" yaml:"max_size" default:"1"`
 | 
				
			||||||
 | 
						// Maximum number of backups to save.
 | 
				
			||||||
 | 
						MaxBackups int `fig:"max_backups" yaml:"max_backups" default:"3"`
 | 
				
			||||||
 | 
						// Maximum number of days to retain old log files.
 | 
				
			||||||
 | 
						MaxAge int `fig:"max_age" yaml:"max_age" default:"0"`
 | 
				
			||||||
 | 
						// Use the logal system time instead of UTC for file names of rotated backups.
 | 
				
			||||||
 | 
						LocalTime *bool `fig:"local_time" yaml:"local_time" default:"true"`
 | 
				
			||||||
 | 
						// Should the rotated logs be compressed.
 | 
				
			||||||
 | 
						Compress *bool `fig:"compress" yaml:"compress" default:"true"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Apply log config.
 | 
				
			||||||
 | 
					func (l *LogConfig) Apply() {
 | 
				
			||||||
 | 
						// Apply level.
 | 
				
			||||||
 | 
						switch l.Level {
 | 
				
			||||||
 | 
						case "debug":
 | 
				
			||||||
 | 
							log.SetLevel(log.DebugLevel)
 | 
				
			||||||
 | 
						case "info":
 | 
				
			||||||
 | 
							log.SetLevel(log.InfoLevel)
 | 
				
			||||||
 | 
						case "warn":
 | 
				
			||||||
 | 
							log.SetLevel(log.WarnLevel)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							log.SetLevel(log.ErrorLevel)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Apply type.
 | 
				
			||||||
 | 
						switch l.Type {
 | 
				
			||||||
 | 
						case "json":
 | 
				
			||||||
 | 
							log.SetFormatter(&log.JSONFormatter{})
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							log.SetFormatter(&log.TextFormatter{})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Change the outputs.
 | 
				
			||||||
 | 
						var outputs []io.Writer
 | 
				
			||||||
 | 
						for _, output := range l.Outputs {
 | 
				
			||||||
 | 
							// If output is console, add stderr and continue.
 | 
				
			||||||
 | 
							if output == "console" {
 | 
				
			||||||
 | 
								outputs = append(outputs, os.Stderr)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// If default-file defined, find the default file.
 | 
				
			||||||
 | 
							if output == "default-file" {
 | 
				
			||||||
 | 
								var f *os.File
 | 
				
			||||||
 | 
								var err error
 | 
				
			||||||
 | 
								var logDir, logPath string
 | 
				
			||||||
 | 
								logName := fmt.Sprintf("%s.log", serviceName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// On *nix, `/var/log/` should be default if writable.
 | 
				
			||||||
 | 
								if runtime.GOOS != "windows" {
 | 
				
			||||||
 | 
									logDir = "/var/log"
 | 
				
			||||||
 | 
									logPath = filepath.Join(logDir, logName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Verify we can write to log file.
 | 
				
			||||||
 | 
									f, err = os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If we could not open the file, then we should try the executable path.
 | 
				
			||||||
 | 
								if err != nil || f == nil {
 | 
				
			||||||
 | 
									exe, err := os.Executable()
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										log.Println("Unable to find an writable log path to save log to.")
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										logDir = filepath.Dir(exe)
 | 
				
			||||||
 | 
										logPath = filepath.Join(logDir, logName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Verify we can write to log file.
 | 
				
			||||||
 | 
										f, err = os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											log.Println("Unable to find an writable log path to save log to.")
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											f.Close()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// Close file.
 | 
				
			||||||
 | 
									f.Close()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Update the config log path.
 | 
				
			||||||
 | 
								output = logPath
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Setup lumberjack log rotate for the output, and add to the list.
 | 
				
			||||||
 | 
							logFile := &lumberjack.Logger{
 | 
				
			||||||
 | 
								Filename:   output,
 | 
				
			||||||
 | 
								MaxSize:    l.MaxSize,
 | 
				
			||||||
 | 
								MaxBackups: l.MaxBackups,
 | 
				
			||||||
 | 
								MaxAge:     l.MaxAge,
 | 
				
			||||||
 | 
								LocalTime:  *l.LocalTime,
 | 
				
			||||||
 | 
								Compress:   *l.Compress,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							outputs = append(outputs, logFile)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If there are outputs, set the outputs.
 | 
				
			||||||
 | 
						if len(outputs) != 0 {
 | 
				
			||||||
 | 
							mw := io.MultiWriter(outputs...)
 | 
				
			||||||
 | 
							log.SetOutput(mw)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Configuration Structure.
 | 
					// Configuration Structure.
 | 
				
			||||||
type Config struct {
 | 
					type Config struct {
 | 
				
			||||||
	HTTP        HTTPConfig    `fig:"http"`
 | 
						HTTP        HTTPConfig    `fig:"http"`
 | 
				
			||||||
 | 
						Log         *LogConfig    `fig:"log" yaml:"log"`
 | 
				
			||||||
	MidiRouters []*MidiRouter `fig:"midi_routers"`
 | 
						MidiRouters []*MidiRouter `fig:"midi_routers"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,6 +181,7 @@ func (a *App) ReadConfig() {
 | 
				
			|||||||
			Debug:    true,
 | 
								Debug:    true,
 | 
				
			||||||
			Enabled:  false,
 | 
								Enabled:  false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							Log: &LogConfig{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load configuration.
 | 
						// Load configuration.
 | 
				
			||||||
@ -81,6 +204,9 @@ func (a *App) ReadConfig() {
 | 
				
			|||||||
		config.HTTP.Port = app.flags.HTTPPort
 | 
							config.HTTP.Port = app.flags.HTTPPort
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Apply log configs.
 | 
				
			||||||
 | 
						config.Log.Apply()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set global config structure.
 | 
						// Set global config structure.
 | 
				
			||||||
	app.config = config
 | 
						app.config = config
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								go.mod
									
									
									
									
									
								
							@ -1,21 +1,27 @@
 | 
				
			|||||||
module github.com/GRMrGecko/midi-request-trigger
 | 
					module github.com/GRMrGecko/midi-request-trigger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.20
 | 
					go 1.24.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					toolchain go1.24.4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/eclipse/paho.mqtt.golang v1.5.0
 | 
						github.com/eclipse/paho.mqtt.golang v1.5.0
 | 
				
			||||||
	github.com/gorilla/handlers v1.5.1
 | 
						github.com/gorilla/handlers v1.5.2
 | 
				
			||||||
	github.com/gorilla/mux v1.8.0
 | 
						github.com/gorilla/mux v1.8.1
 | 
				
			||||||
	github.com/kkyr/fig v0.3.2
 | 
						github.com/kkyr/fig v0.5.0
 | 
				
			||||||
	gitlab.com/gomidi/midi/v2 v2.0.30
 | 
						github.com/sirupsen/logrus v1.9.3
 | 
				
			||||||
 | 
						gitlab.com/gomidi/midi/v2 v2.3.14
 | 
				
			||||||
 | 
						gopkg.in/natefinch/lumberjack.v2 v2.2.1
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/felixge/httpsnoop v1.0.1 // indirect
 | 
						github.com/felixge/httpsnoop v1.0.4 // indirect
 | 
				
			||||||
	github.com/gorilla/websocket v1.5.3 // indirect
 | 
						github.com/gorilla/websocket v1.5.3 // indirect
 | 
				
			||||||
	github.com/mitchellh/mapstructure v1.4.1 // indirect
 | 
						github.com/mitchellh/mapstructure v1.5.0 // indirect
 | 
				
			||||||
	github.com/pelletier/go-toml v1.9.3 // indirect
 | 
						github.com/pelletier/go-toml v1.9.5 // indirect
 | 
				
			||||||
	golang.org/x/net v0.27.0 // indirect
 | 
						github.com/pelletier/go-toml/v2 v2.2.4 // indirect
 | 
				
			||||||
	golang.org/x/sync v0.7.0 // indirect
 | 
						golang.org/x/net v0.41.0 // indirect
 | 
				
			||||||
 | 
						golang.org/x/sync v0.15.0 // indirect
 | 
				
			||||||
 | 
						golang.org/x/sys v0.33.0 // indirect
 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										38
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								go.sum
									
									
									
									
									
								
							@ -1,26 +1,64 @@
 | 
				
			|||||||
 | 
					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/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o=
 | 
					github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o=
 | 
				
			||||||
github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk=
 | 
					github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk=
 | 
				
			||||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
 | 
					github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
 | 
				
			||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 | 
					github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 | 
				
			||||||
 | 
					github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
 | 
				
			||||||
 | 
					github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 | 
				
			||||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
 | 
					github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
 | 
				
			||||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
 | 
					github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
 | 
				
			||||||
 | 
					github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
 | 
				
			||||||
 | 
					github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
 | 
				
			||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 | 
					github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 | 
				
			||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 | 
					github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 | 
				
			||||||
 | 
					github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
 | 
				
			||||||
 | 
					github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
 | 
				
			||||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 | 
					github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 | 
				
			||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 | 
					github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 | 
				
			||||||
github.com/kkyr/fig v0.3.2 h1:+vMj52FL6RJUxeKOBB6JXIMyyi1/2j1ERDrZXjoBjzM=
 | 
					github.com/kkyr/fig v0.3.2 h1:+vMj52FL6RJUxeKOBB6JXIMyyi1/2j1ERDrZXjoBjzM=
 | 
				
			||||||
github.com/kkyr/fig v0.3.2/go.mod h1:ItUILF8IIzgZOMhx5xpJ1W/bviQsWRKOwKXfE/tqUoA=
 | 
					github.com/kkyr/fig v0.3.2/go.mod h1:ItUILF8IIzgZOMhx5xpJ1W/bviQsWRKOwKXfE/tqUoA=
 | 
				
			||||||
 | 
					github.com/kkyr/fig v0.5.0 h1:D4ym5MYYScOSgqyx1HYQaqFn9dXKzIuSz8N6SZ4rzqM=
 | 
				
			||||||
 | 
					github.com/kkyr/fig v0.5.0/go.mod h1:U4Rq/5eUNJ8o5UvOEc9DiXtNf41srOLn2r/BfCyuc58=
 | 
				
			||||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
 | 
					github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
 | 
				
			||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
					github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
				
			||||||
 | 
					github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 | 
				
			||||||
 | 
					github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
				
			||||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
 | 
					github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
 | 
				
			||||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 | 
					github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
 | 
				
			||||||
 | 
					github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
				
			||||||
 | 
					github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
				
			||||||
 | 
					github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 | 
				
			||||||
 | 
					github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 | 
				
			||||||
 | 
					github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
				
			||||||
gitlab.com/gomidi/midi/v2 v2.0.30 h1:RgRYbQeQSab5ZaP1lqRcCTnTSBQroE3CE6V9HgMmOAc=
 | 
					gitlab.com/gomidi/midi/v2 v2.0.30 h1:RgRYbQeQSab5ZaP1lqRcCTnTSBQroE3CE6V9HgMmOAc=
 | 
				
			||||||
gitlab.com/gomidi/midi/v2 v2.0.30/go.mod h1:Y6IFFyABN415AYsFMPJb0/43TRIuVYDpGKp2gDYLTLI=
 | 
					gitlab.com/gomidi/midi/v2 v2.0.30/go.mod h1:Y6IFFyABN415AYsFMPJb0/43TRIuVYDpGKp2gDYLTLI=
 | 
				
			||||||
 | 
					gitlab.com/gomidi/midi/v2 v2.3.14 h1:BbTDExFlg0zm90AtyGDdO87jdKjn+eYqeSlSGGpFPzQ=
 | 
				
			||||||
 | 
					gitlab.com/gomidi/midi/v2 v2.3.14/go.mod h1:jDpP4O4skYi+7iVwt6Zyp18bd2M4hkjtMuw2cmgKgfw=
 | 
				
			||||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
 | 
					golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
 | 
				
			||||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
 | 
					golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
 | 
				
			||||||
 | 
					golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
 | 
				
			||||||
 | 
					golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
 | 
				
			||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
 | 
					golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
 | 
				
			||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
 | 
					gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
				
			||||||
 | 
					gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 | 
				
			||||||
 | 
					gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
					gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
					gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								http.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								http.go
									
									
									
									
									
								
							@ -4,13 +4,13 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gorilla/handlers"
 | 
						"github.com/gorilla/handlers"
 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Basic HTTP server structure.
 | 
					// Basic HTTP server structure.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							@ -3,11 +3,11 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/signal"
 | 
						"os/signal"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
	"gitlab.com/gomidi/midi/v2"
 | 
						"gitlab.com/gomidi/midi/v2"
 | 
				
			||||||
	_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
 | 
						_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -15,7 +15,7 @@ import (
 | 
				
			|||||||
const (
 | 
					const (
 | 
				
			||||||
	serviceName        = "midi-request-trigger"
 | 
						serviceName        = "midi-request-trigger"
 | 
				
			||||||
	serviceDescription = "Takes trigger MIDI messages by HTTP or MQTT requests and trigger HTTP or MQTT requests by MIDI messages"
 | 
						serviceDescription = "Takes trigger MIDI messages by HTTP or MQTT requests and trigger HTTP or MQTT requests by MIDI messages"
 | 
				
			||||||
	serviceVersion     = "0.3"
 | 
						serviceVersion     = "0.4.1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// App is the global application structure for communicating between servers and storing information.
 | 
					// App is the global application structure for communicating between servers and storing information.
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,6 @@ import (
 | 
				
			|||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
@ -14,6 +13,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mqtt "github.com/eclipse/paho.mqtt.golang"
 | 
						mqtt "github.com/eclipse/paho.mqtt.golang"
 | 
				
			||||||
 | 
						log "github.com/sirupsen/logrus"
 | 
				
			||||||
	"gitlab.com/gomidi/midi/v2"
 | 
						"gitlab.com/gomidi/midi/v2"
 | 
				
			||||||
	"gitlab.com/gomidi/midi/v2/drivers"
 | 
						"gitlab.com/gomidi/midi/v2/drivers"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -128,7 +128,7 @@ type RequestTrigger struct {
 | 
				
			|||||||
type MidiRouter struct {
 | 
					type MidiRouter struct {
 | 
				
			||||||
	// Used for human readable config.
 | 
						// Used for human readable config.
 | 
				
			||||||
	Name string `fig:"name"`
 | 
						Name string `fig:"name"`
 | 
				
			||||||
	// Midi device to connect.
 | 
						// Midi device to connect, accepts regular expression.
 | 
				
			||||||
	Device string `fig:"device"`
 | 
						Device string `fig:"device"`
 | 
				
			||||||
	// MQTT Connection if you are to integrate with MQTT.
 | 
						// MQTT Connection if you are to integrate with MQTT.
 | 
				
			||||||
	MQTT MQTTConfig `fig:"mqtt"`
 | 
						MQTT MQTTConfig `fig:"mqtt"`
 | 
				
			||||||
@ -480,10 +480,23 @@ func (r *MidiRouter) Connect() {
 | 
				
			|||||||
	// If request triggers defined, find the out port.
 | 
						// If request triggers defined, find the out port.
 | 
				
			||||||
	if len(r.RequestTriggers) != 0 {
 | 
						if len(r.RequestTriggers) != 0 {
 | 
				
			||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
 | 
								deviceRx, err := regexp.Compile(r.Device)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.Printf("Failed to compile regexp of '%s': %v", r.Device, err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			for {
 | 
								for {
 | 
				
			||||||
				out, err := midi.FindOutPort(r.Device)
 | 
									var out drivers.Out
 | 
				
			||||||
 | 
									for _, device := range midi.GetOutPorts() {
 | 
				
			||||||
 | 
										if deviceRx.MatchString(device.String()) {
 | 
				
			||||||
 | 
											err = device.Open()
 | 
				
			||||||
 | 
											out = device
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if out == nil {
 | 
				
			||||||
 | 
										err = fmt.Errorf("unable to find matching device")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					r.Log(ErrorLog, "Can't find output device: %s", r.Device)
 | 
										r.Log(ErrorLog, "Failed to find output device '%s': %v", r.Device, err)
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					r.MidiOut = out
 | 
										r.MidiOut = out
 | 
				
			||||||
					break
 | 
										break
 | 
				
			||||||
@ -498,12 +511,25 @@ func (r *MidiRouter) Connect() {
 | 
				
			|||||||
	// If listener is disabled, stop here.
 | 
						// If listener is disabled, stop here.
 | 
				
			||||||
	if !r.DisableListener {
 | 
						if !r.DisableListener {
 | 
				
			||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
 | 
								deviceRx, err := regexp.Compile(r.Device)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.Printf("Failed to compile regexp of '%s': %v", r.Device, err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			for {
 | 
								for {
 | 
				
			||||||
				// Try finding input port.
 | 
									// Try finding input port.
 | 
				
			||||||
				r.Log(InfoLog, "Connecting to input device: %s", r.Device)
 | 
									r.Log(InfoLog, "Connecting to input device: %s", r.Device)
 | 
				
			||||||
				in, err := midi.FindInPort(r.Device)
 | 
									var in drivers.In
 | 
				
			||||||
 | 
									for _, device := range midi.GetInPorts() {
 | 
				
			||||||
 | 
										if deviceRx.MatchString(device.String()) {
 | 
				
			||||||
 | 
											err = device.Open()
 | 
				
			||||||
 | 
											in = device
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if in == nil {
 | 
				
			||||||
 | 
										err = fmt.Errorf("unable to find matching device")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					r.Log(ErrorLog, "Can't find input device: %s", r.Device)
 | 
										r.Log(ErrorLog, "Can't find input device '%s': %v", r.Device, err)
 | 
				
			||||||
					r.Log(ErrorLog, "Retrying in 1 minute.")
 | 
										r.Log(ErrorLog, "Retrying in 1 minute.")
 | 
				
			||||||
					time.Sleep(time.Minute)
 | 
										time.Sleep(time.Minute)
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user