-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
lagra.go
215 lines (177 loc) · 5.28 KB
/
lagra.go
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package lagra
import (
"context" //Import the necessary packages:
"fmt"
"os"
"strings"
"sync"
"time"
"sync/atomic"
"github.com/BurntSushi/toml"
"github.com/fatih/color"
)
type LogType string
const ( //Defines log levels/intensities
Info LogType = "INFO"
Warn LogType = "WARN"
Error LogType = "ERROR"
)
type Lagra struct { //The main structure of LAGRA
logFile *os.File
logMutex sync.Mutex
config *LagraConfig
logBuffer []string
logCounter int32
}
type LagraConfig struct { //Define the settings
LogFile string `toml:"log_file"`
LogLevel string `toml:"log_level"`
}
// New creates a new Lagra logger instance with optional TOML configuration.
func New(tomlConfig string) (*Lagra, error) {
var config LagraConfig
if tomlConfig != "" {
if _, err := toml.Decode(tomlConfig, &config); err != nil {
return nil, err
}
}
l := &Lagra{
config: &config,
logBuffer: make([]string, 0, 100),
}
if l.config.LogFile != "" {
l.SetLogFile(l.config.LogFile)
}
if l.config.LogLevel != "" {
l.SetLogLevel(l.config.LogLevel)
}
go l.flushLogBuffer()
return l, nil
}
// send logs a message with the specified log type and an optional custom log file path.
func (l *Lagra) send(logType LogType, message string, customLogPath ...string) error {
l.logMutex.Lock()
defer l.logMutex.Unlock()
logMessage := fmt.Sprintf("%s - %s - %s\n", time.Now().Format("15:04.05.9 - 02/01/2006"), logType, message)
var textColor *color.Color
switch logType {
case Info:
textColor = color.New(color.FgGreen)
case Warn:
textColor = color.New(color.FgYellow)
case Error:
textColor = color.New(color.FgRed)
default:
textColor = color.New(color.Reset)
}
logMessageColored := textColor.SprintFunc()(logMessage)
fmt.Print(logMessageColored) // Print with colors
// Use custom log file path if provided, otherwise use the configured log file
logFilePath := l.config.LogFile
if len(customLogPath) > 0 && customLogPath[0] != "" {
logFilePath = customLogPath[0]
}
if logFilePath != "" {
if l.logFile != nil {
l.logBuffer = append(l.logBuffer, logMessage)
atomic.AddInt32(&l.logCounter, 1)
if l.logCounter >= 100 {
l.flushLogBuffer()
}
} else {
fmt.Println("Log file is not set. Message will not be logged to a file.")
}
}
return nil // No error
}
// Info logs an informational message with optional custom log file path.
func (l *Lagra) Info(ctx context.Context, message string, customLogPath ...string) error {
return l.send(Info, message, customLogPath...)
}
// Warn logs a warning message with optional custom log file path.
func (l *Lagra) Warn(ctx context.Context, message string, customLogPath ...string) error {
return l.send(Warn, message, customLogPath...)
}
// Error logs an error message with optional custom log file path.
func (l *Lagra) Error(ctx context.Context, message string, customLogPath ...string) error {
return l.send(Error, message, customLogPath...)
}
// SetLogFile sets the log file path.
func (l *Lagra) SetLogFile(filePath string) {
l.logMutex.Lock()
defer l.logMutex.Unlock()
if l.logFile != nil {
_ = l.logFile.Close()
}
file, err := os.Create(filePath)
if err != nil {
fmt.Printf("Failed to create log file: %v\n", err)
return
}
l.logFile = file
}
// SetLogLevel sets the log level (INFO, WARN, ERROR).
func (l *Lagra) SetLogLevel(level string) {
switch level {
case "INFO":
// Set log level to INFO
case "WARN":
// Set log level to WARN
case "ERROR":
// Set log level to ERROR
default:
level = "INFO" // Default log level
}
fmt.Printf("Log level set to %s\n", level)
}
// flushLogBuffer writes the log buffer to the log file and resets the buffer and counter.
func (l *Lagra) flushLogBuffer() {
l.logMutex.Lock()
defer l.logMutex.Unlock()
if l.logFile != nil && len(l.logBuffer) > 0 {
_, err := l.logFile.WriteString(strings.Join(l.logBuffer, ""))
if err != nil {
fmt.Printf("Failed to write to log file: %v\n", err)
}
l.logBuffer = l.logBuffer[:0]
atomic.StoreInt32(&l.logCounter, 0)
}
}
type ErrorCollector struct { //The main structure of LAGRER
errors []error
}
func Tracker() *ErrorCollector { //LAGRER's "New()" function, responsible for creating a new instance
return &ErrorCollector{}
}
func (ec *ErrorCollector) N(err error) {
if err != nil {
ec.errors = append(ec.errors, err)
}
}
func (ec *ErrorCollector) Handle() bool {
return len(ec.errors) > 0
}
func (ec *ErrorCollector) Errors() []error {
return ec.errors
}
type StrSelect struct { //The main structure of the LAGRA String Selector
strMap map[string]string
}
func NewStrSelect() *StrSelect {
return &StrSelect{
strMap: make(map[string]string),
}
}
func (s *StrSelect) SetStr(strName, value string) {
s.strMap[strName] = value
}
func (s *StrSelect) SelectStr(strName, delimiter string) string {
if str, ok := s.strMap[strName]; ok {
startIdx := strings.Index(str, delimiter)
endIdx := strings.LastIndex(str, delimiter)
if startIdx != -1 && endIdx != -1 && startIdx < endIdx {
return str[startIdx+len(delimiter) : endIdx]
}
}
return ""
}