summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/client.go28
-rw-r--r--client/client_test.go6
-rw-r--r--cmd/eduvpn-cli/main.go1
-rw-r--r--exports/exports.go1
-rw-r--r--internal/log/log.go22
5 files changed, 42 insertions, 16 deletions
diff --git a/client/client.go b/client/client.go
index d986fa6..e3f40aa 100644
--- a/client/client.go
+++ b/client/client.go
@@ -50,6 +50,17 @@ func CalculateGateway(cidr string) (string, error) {
return ret.String(), nil
}
+// Logger is used by Client to control its logging. Client uses slog for all
+// logging which can be configured by implementations of this interface.
+type Logger interface {
+ // Init initializes the logging through slog. The given directory can
+ // be used to store the log files.
+ Init(dir string) (*slog.Logger, error)
+ // Close is called after logging has ended and should release all
+ // resources from Init.
+ Close() error
+}
+
// Client is the main struct for the VPN client.
type Client struct {
// The name of the client
@@ -70,8 +81,8 @@ type Client struct {
// tokenCacher
tokCacher TokenCacher
- // logr is the log file rotater
- logr *log.FileRotater
+ // logr is the logger
+ logr Logger
// cfg is the config
cfg *config.Config
@@ -137,10 +148,10 @@ func (c *Client) goTransition(id fsm.StateID) error {
// - name: the name of the client
// - directory: the directory where the config files are stored. Absolute or relative
// - stateCallback: the callback function for the FSM that takes two states (old and new) and the data as an interface
-// - debug: whether or not we want to enable debugging
+// - logger: the logger interface to use, if nil the default logger is used which logs to files in directory
//
// It returns an error if initialization failed, for example when discovery cannot be obtained and when there are no servers.
-func New(name string, version string, directory string, stateCallback func(FSMStateID, FSMStateID, any) bool) (c *Client, err error) {
+func New(name string, version string, directory string, stateCallback func(FSMStateID, FSMStateID, any) bool, logger Logger) (c *Client, err error) {
// We create the client by filling fields one by one
c = &Client{}
@@ -152,11 +163,16 @@ func New(name string, version string, directory string, stateCallback func(FSMSt
return nil, i18nerr.NewInternalf("The client registered with an invalid version: '%v'", version)
}
- logr, err := log.Init(slog.LevelDebug, directory)
+ // Initialize provided logger or use default
+ if logger == nil {
+ logger = &log.Logger{}
+ }
+ c.logr = logger
+ slogger, err := c.logr.Init(directory)
if err != nil {
return nil, i18nerr.WrapInternalf(err, "The log file with directory: '%s' failed to initialize", directory)
}
- c.logr = logr
+ slog.SetDefault(slogger)
// set client name
c.Name = name
diff --git a/client/client_test.go b/client/client_test.go
index 3ae5775..372c6c3 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -169,6 +169,7 @@ func TestServer(t *testing.T) {
go stateCallback(ck, oldState, newState, data)
return true
},
+ nil,
)
if err != nil {
t.Fatalf("Creating client error: %v", err)
@@ -216,6 +217,7 @@ func TestTokenExpired(t *testing.T) {
go stateCallback(ck, oldState, newState, data)
return true
},
+ nil,
)
if err != nil {
t.Fatalf("Creating client error: %v", err)
@@ -274,6 +276,7 @@ func TestInvalidProfileCorrected(t *testing.T) {
go stateCallback(ck, oldState, newState, data)
return true
},
+ nil,
)
if err != nil {
t.Fatalf("Creating client error: %v", err)
@@ -330,6 +333,7 @@ func TestConfigStartup(t *testing.T) {
go stateCallback(ck, oldState, newState, data)
return true
},
+ nil,
)
if err != nil {
t.Fatalf("Creating client error: %v", err)
@@ -390,6 +394,7 @@ func TestPreferTCP(t *testing.T) {
go stateCallback(ck, oldState, newState, data)
return true
},
+ nil,
)
if err != nil {
t.Fatalf("Creating client error: %v", err)
@@ -453,6 +458,7 @@ func TestInvalidClientID(t *testing.T) {
func(_ FSMStateID, _ FSMStateID, _ any) bool {
return true
},
+ nil,
)
if v {
if err != nil {
diff --git a/cmd/eduvpn-cli/main.go b/cmd/eduvpn-cli/main.go
index d0457b5..2a8ffc1 100644
--- a/cmd/eduvpn-cli/main.go
+++ b/cmd/eduvpn-cli/main.go
@@ -154,6 +154,7 @@ func printConfig(url string, cc string, srvType srvtypes.Type, prof string) erro
stateCallback(oldState, newState, data, prof, dir)
return true
},
+ nil,
)
if err != nil {
return err
diff --git a/exports/exports.go b/exports/exports.go
index 3ef6781..05a77c2 100644
--- a/exports/exports.go
+++ b/exports/exports.go
@@ -163,6 +163,7 @@ func Register(
func(oldState client.FSMStateID, newState client.FSMStateID, data interface{}) bool {
return stateCallback(cb, oldState, newState, data)
},
+ nil,
)
// Only update the state if we get no error
if err == nil {
diff --git a/internal/log/log.go b/internal/log/log.go
index 6a48ad7..91eaed8 100644
--- a/internal/log/log.go
+++ b/internal/log/log.go
@@ -9,12 +9,11 @@ import (
"path"
)
-// Init initializes the logger by setting a max level 'level' and a directory 'directory' where the log should be stored
-// internally, it uses slog, so any package just imports slog
-// This can be done as this function sets the logger as the default logger in slog
-// It returns the log file and the error
-// This log file should be closed at the end
-func Init(lvl slog.Level, dir string) (*FileRotater, error) {
+type Logger struct {
+ fr *FileRotater
+}
+
+func (l *Logger) Init(dir string) (*slog.Logger, error) {
err := os.MkdirAll(dir, 0o700)
if err != nil {
return nil, err
@@ -25,11 +24,14 @@ func Init(lvl slog.Level, dir string) (*FileRotater, error) {
if err != nil {
return nil, fmt.Errorf("failed creating log rotater: %w", err)
}
+ l.fr = fr
multi := io.MultiWriter(os.Stdout, fr)
handler := slog.NewTextHandler(multi, &slog.HandlerOptions{
- Level: lvl,
+ Level: slog.LevelDebug,
})
- logger := slog.New(handler)
- slog.SetDefault(logger)
- return fr, nil
+ return slog.New(handler), nil
+}
+
+func (l *Logger) Close() error {
+ return l.fr.Close()
}