summaryrefslogtreecommitdiff
path: root/internal/log/log.go
blob: 2ab65497b009dfc8ba2f0a62487221fb25e2ec05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package log

import (
	"fmt"
	"io"
	"log"
	"os"
	"path"

	"github.com/eduvpn/eduvpn-common/internal/util"
	"github.com/eduvpn/eduvpn-common/types"
)

type FileLogger struct {
	Level LogLevel
	File  *os.File
}

type LogLevel int8

const (
	// No level set, not allowed
	LogNotSet LogLevel = iota
	// Log debug, this message is not an error but is there for debugging
	LogDebug
	// Log info, this message is not an error but is there for additional information
	LogInfo
	// Log only to provide a warning, the app still functions
	LogWarning
	// Log to provide a generic error, the app still functions but some functionality might not work
	LogError
	// Log to provide a fatal error, the app cannot function correctly when such an error occurs
	LogFatal
)

func (e LogLevel) String() string {
	switch e {
	case LogNotSet:
		return "NOTSET"
	case LogDebug:
		return "DEBUG"
	case LogInfo:
		return "INFO"
	case LogWarning:
		return "WARNING"
	case LogError:
		return "ERROR"
	case LogFatal:
		return "FATAL"
	default:
		return "UNKNOWN"
	}
}

func (logger *FileLogger) Init(level LogLevel, directory string) error {
	errorMessage := "failed creating log"

	configDirErr := util.EnsureDirectory(directory)
	if configDirErr != nil {
		return types.NewWrappedError(errorMessage, configDirErr)
	}
	logFile, logOpenErr := os.OpenFile(
		logger.getFilename(directory),
		os.O_RDWR|os.O_CREATE|os.O_APPEND,
		0o666,
	)
	if logOpenErr != nil {
		return types.NewWrappedError(errorMessage, logOpenErr)
	}
	multi := io.MultiWriter(os.Stdout, logFile)
	log.SetOutput(multi)
	logger.File = logFile
	logger.Level = level
	return nil
}

func (logger *FileLogger) Inherit(label string, err error) {
	level := types.GetErrorLevel(err)

	msg := fmt.Sprintf("%s with err: %s", label, types.GetErrorTraceback(err))
	switch level {
	case types.ErrInfo:
		logger.Info(msg)
	case types.ErrWarning:
		logger.Warning(msg)
	case types.ErrOther:
		logger.Error(msg)
	case types.ErrFatal:
		logger.Fatal(msg)
	}
}

func (logger *FileLogger) Debug(msg string, params ...interface{}) {
	logger.log(LogDebug, msg, params...)
}

func (logger *FileLogger) Info(msg string, params ...interface{}) {
	logger.log(LogInfo, msg, params...)
}

func (logger *FileLogger) Warning(msg string, params ...interface{}) {
	logger.log(LogWarning, msg, params...)
}

func (logger *FileLogger) Error(msg string, params ...interface{}) {
	logger.log(LogError, msg, params...)
}

func (logger *FileLogger) Fatal(msg string, params ...interface{}) {
	logger.log(LogFatal, msg, params...)
}

func (logger *FileLogger) Close() {
	logger.File.Close()
}

func (logger *FileLogger) getFilename(directory string) string {
	return path.Join(directory, "log")
}

func (logger *FileLogger) log(level LogLevel, msg string, params ...interface{}) {
	if level >= logger.Level && logger.Level != LogNotSet {
		formattedMsg := fmt.Sprintf(msg, params...)
		format := fmt.Sprintf("- Go - %s - %s", level.String(), formattedMsg)
		// To log file
		log.Println(format)
	}
}