Issues (1)

alog.go (1 issue)

Severity
1
////////////////////////////////////////////////////////////////////////////////
2
// Author:   Nikita Koryabkin
3
// Email:    [email protected]
4
// Telegram: https://t.me/Apologiz
5
////////////////////////////////////////////////////////////////////////////////
6
7
package alog
8
9
import (
10
	"fmt"
11
	"io"
12
	"log"
13
	"os"
14
	"runtime"
15
	"runtime/debug"
16
	"time"
17
18
	"github.com/mylockerteam/alog/strategy/file"
19
	"github.com/mylockerteam/alog/strategy/standart"
20
)
21
22
const (
23
	messageFormatDefault      = "%s;%s\n"
24
	messageFormatErrorDebug   = "%s\n%s\n---\n\n"
25
	messageFormatWithFileLine = "%s;%s:%d;%s\n"
26
)
27
28
// Config contains settings and registered loggers
29
type Config struct {
30
	Loggers        Map
31
	TimeFormat     string
32
	IgnoreFileLine bool
33
}
34
35
// Log logger himself
36
type Log struct {
37
	_      Writer
38
	config *Config
39
}
40
41
// Create creates an instance of the logger
42
func Create(config *Config) Writer {
43
	for _, l := range config.Loggers {
44
		go l.Reader()
45
	}
46
	return &Log{config: config}
47
}
48
49
// Default created standart logger. Writes to stdout and stderr
50
func Default(chanBuffer uint) Writer {
51
	config := &Config{
52
		TimeFormat: time.RFC3339Nano,
53
		Loggers:    getDefaultLoggerMap(chanBuffer),
54
	}
55
	for _, l := range config.Loggers {
56
		go l.Reader()
57
	}
58
	return &Log{config: config}
59
}
60
61
func getDefaultLoggerMap(chanBuffer uint) Map {
62
	return Map{
63
		Info: &Logger{
64
			Channel: make(chan string, chanBuffer),
65
			Strategies: []io.Writer{
66
				&file.Strategy{File: os.Stdout},
67
			},
68
		},
69
		Wrn: &Logger{
70
			Channel: make(chan string, chanBuffer),
71
			Strategies: []io.Writer{
72
				&file.Strategy{File: os.Stdout},
73
			},
74
		},
75
		Err: &Logger{
76
			Channel: make(chan string, chanBuffer),
77
			Strategies: []io.Writer{
78
				&file.Strategy{File: os.Stderr},
79
			},
80
		},
81
	}
82
}
83
84
func printNotConfiguredMessage(code uint, skip int) {
85
	if _, fileName, fileLine, ok := runtime.Caller(skip); ok {
86
		log.Println(fmt.Sprintf("%s:%d Logger %s not configured", fileName, fileLine, Name(code)))
87
		return
88
	}
89
	log.Println(fmt.Sprintf("Logger %s not configured", Name(code)))
90
}
91
92
// GetLoggerInterfaceByType returns io.Writer interface for logging in third-party libraries
93
func (a *Log) GetLoggerInterfaceByType(loggerType uint) io.Writer {
94
	if l := a.config.Loggers[loggerType]; l != nil {
95
		return l
96
	}
97
	printNotConfiguredMessage(loggerType, 2)
98
	return &standart.Strategy{}
99
}
100
101
// Info method for recording informational messages
102
func (a *Log) Info(msg string) *Log {
103
	if l := a.config.Loggers[Info]; l != nil {
104
		prepareLog := a.prepareLog(time.Now(), msg, 2)
105
		l.Channel <- fmt.Sprintf("[%s] %s", Name(Info), prepareLog)
106
	} else {
107
		printNotConfiguredMessage(Info, 2)
108
	}
109
	return a
110
}
111
112
// Infof method of recording formatted informational messages
113
func (a *Log) Infof(format string, p ...interface{}) *Log {
114
	if l := a.config.Loggers[Info]; l != nil {
115
		prepareLog := a.prepareLog(time.Now(), fmt.Sprintf(format, p...), 2)
0 ignored issues
show
can't check non-constant format in call to Sprintf
Loading history...
116
		l.Channel <- fmt.Sprintf("[%s] %s", Name(Info), prepareLog)
117
	} else {
118
		printNotConfiguredMessage(Info, 2)
119
	}
120
	return a
121
}
122
123
// Warning method for recording warning messages
124
func (a *Log) Warning(msg string) *Log {
125
	if a.config.Loggers[Wrn] != nil {
126
		prepareLog := a.prepareLog(time.Now(), msg, 2)
127
		a.config.Loggers[Wrn].Channel <- fmt.Sprintf("[%s] %s", Name(Wrn), prepareLog)
128
	} else {
129
		printNotConfiguredMessage(Wrn, 2)
130
	}
131
	return a
132
}
133
134
// Method for recording errors without stack
135
func (a *Log) Error(err error) *Log {
136
	if a.config.Loggers[Err] != nil {
137
		if err != nil {
138
			prepareLog := a.prepareLog(time.Now(), err.Error(), 2)
139
			a.config.Loggers[Err].Channel <- fmt.Sprintf("[%s] %s", Name(Err), prepareLog)
140
		}
141
	} else {
142
		printNotConfiguredMessage(Err, 2)
143
	}
144
	return a
145
}
146
147
// ErrorDebug method for recording errors with stack
148
func (a *Log) ErrorDebug(err error) *Log {
149
	if a.config.Loggers[Err] != nil {
150
		if err != nil {
151
			msg := fmt.Sprintf(messageFormatErrorDebug, a.prepareLog(time.Now(), err.Error(), 2), string(debug.Stack()))
152
			a.config.Loggers[Err].Channel <- fmt.Sprintf("[%s] %s", Name(Err), msg)
153
		}
154
	} else {
155
		printNotConfiguredMessage(Err, 2)
156
	}
157
	return a
158
}
159
160
func (a *Log) getTimeFormat() string {
161
	if format := a.config.TimeFormat; format != "" {
162
		return format
163
	}
164
	return time.RFC3339Nano
165
}
166
167
func (a *Log) prepareLog(time time.Time, msg string, skip int) string {
168
	if _, fileName, fileLine, ok := runtime.Caller(skip); ok && !a.config.IgnoreFileLine {
169
		return fmt.Sprintf(
170
			messageFormatWithFileLine,
171
			time.Format(a.getTimeFormat()),
172
			fileName,
173
			fileLine,
174
			msg,
175
		)
176
	}
177
	return fmt.Sprintf(
178
		messageFormatDefault,
179
		time.Format(a.getTimeFormat()),
180
		msg,
181
	)
182
}
183