1+ package logging
2+
3+ import (
4+ "encoding/json"
5+ "fmt"
6+ "os"
7+ "strings"
8+ "time"
9+ )
10+
11+ // LogLevel represents the severity level of a log message
12+ type LogLevel int
13+
14+ const (
15+ DEBUG LogLevel = iota
16+ INFO
17+ WARN
18+ ERROR
19+ )
20+
21+ func (l LogLevel ) String () string {
22+ switch l {
23+ case DEBUG :
24+ return "DEBUG"
25+ case INFO :
26+ return "INFO"
27+ case WARN :
28+ return "WARN"
29+ case ERROR :
30+ return "ERROR"
31+ default :
32+ return "UNKNOWN"
33+ }
34+ }
35+
36+ // Logger represents a structured logger
37+ type Logger struct {
38+ level LogLevel
39+ format string // "text" or "json"
40+ timestamp bool
41+ }
42+
43+ // NewLogger creates a new logger with the specified level and format
44+ func NewLogger (level LogLevel , format string ) * Logger {
45+ return & Logger {
46+ level : level ,
47+ format : format ,
48+ timestamp : true ,
49+ }
50+ }
51+
52+ // SetLevel sets the minimum log level
53+ func (l * Logger ) SetLevel (level LogLevel ) {
54+ l .level = level
55+ }
56+
57+ // SetFormat sets the output format ("text" or "json")
58+ func (l * Logger ) SetFormat (format string ) {
59+ l .format = format
60+ }
61+
62+ // EnableTimestamp enables or disables timestamp in logs
63+ func (l * Logger ) EnableTimestamp (enabled bool ) {
64+ l .timestamp = enabled
65+ }
66+
67+ // Log logs a message with the specified level and fields
68+ func (l * Logger ) Log (level LogLevel , message string , fields map [string ]interface {}) {
69+ if level < l .level {
70+ return
71+ }
72+
73+ switch l .format {
74+ case "json" :
75+ l .logJSON (level , message , fields )
76+ default :
77+ l .logText (level , message , fields )
78+ }
79+ }
80+
81+ // Debug logs a debug message
82+ func (l * Logger ) Debug (message string , fields map [string ]interface {}) {
83+ l .Log (DEBUG , message , fields )
84+ }
85+
86+ // Info logs an info message
87+ func (l * Logger ) Info (message string , fields map [string ]interface {}) {
88+ l .Log (INFO , message , fields )
89+ }
90+
91+ // Warn logs a warning message
92+ func (l * Logger ) Warn (message string , fields map [string ]interface {}) {
93+ l .Log (WARN , message , fields )
94+ }
95+
96+ // Error logs an error message
97+ func (l * Logger ) Error (message string , fields map [string ]interface {}) {
98+ l .Log (ERROR , message , fields )
99+ }
100+
101+ func (l * Logger ) logText (level LogLevel , message string , fields map [string ]interface {}) {
102+ var parts []string
103+
104+ if l .timestamp {
105+ parts = append (parts , time .Now ().Format ("2006-01-02T15:04:05Z07:00" ))
106+ }
107+
108+ parts = append (parts , fmt .Sprintf ("[%s]" , level .String ()))
109+
110+ parts = append (parts , message )
111+
112+ // Add fields
113+ for key , value := range fields {
114+ parts = append (parts , fmt .Sprintf ("%s=%v" , key , value ))
115+ }
116+
117+ fmt .Fprintln (os .Stderr , strings .Join (parts , " " ))
118+ }
119+
120+ func (l * Logger ) logJSON (level LogLevel , message string , fields map [string ]interface {}) {
121+ logEntry := map [string ]interface {}{
122+ "level" : level .String (),
123+ "message" : message ,
124+ }
125+
126+ if l .timestamp {
127+ logEntry ["timestamp" ] = time .Now ().Format (time .RFC3339 )
128+ }
129+
130+ // Add fields
131+ for key , value := range fields {
132+ logEntry [key ] = value
133+ }
134+
135+ jsonData , err := json .Marshal (logEntry )
136+ if err != nil {
137+ // Fallback to text logging if JSON marshaling fails
138+ l .logText (level , message , fields )
139+ return
140+ }
141+
142+ fmt .Fprintln (os .Stderr , string (jsonData ))
143+ }
144+
145+ // Global logger instance
146+ var globalLogger * Logger
147+
148+ func init () {
149+ // Initialize with INFO level and text format by default
150+ globalLogger = NewLogger (INFO , "text" )
151+ }
152+
153+ // SetGlobalLevel sets the level for the global logger
154+ func SetGlobalLevel (level LogLevel ) {
155+ globalLogger .SetLevel (level )
156+ }
157+
158+ // SetGlobalFormat sets the format for the global logger
159+ func SetGlobalFormat (format string ) {
160+ globalLogger .SetFormat (format )
161+ }
162+
163+ // Debug logs a debug message using the global logger
164+ func Debug (message string , fields map [string ]interface {}) {
165+ globalLogger .Debug (message , fields )
166+ }
167+
168+ // Info logs an info message using the global logger
169+ func Info (message string , fields map [string ]interface {}) {
170+ globalLogger .Info (message , fields )
171+ }
172+
173+ // Warn logs a warning message using the global logger
174+ func Warn (message string , fields map [string ]interface {}) {
175+ globalLogger .Warn (message , fields )
176+ }
177+
178+ // Error logs an error message using the global logger
179+ func Error (message string , fields map [string ]interface {}) {
180+ globalLogger .Error (message , fields )
181+ }
0 commit comments