@@ -24,12 +24,16 @@ import (
2424 "strings"
2525 "time"
2626
27- "github.com/go-aah/forge"
27+ "github.com/go-aah/config"
28+ "github.com/go-aah/essentials"
2829)
2930
3031// Level type definition
3132type Level uint8
3233
34+ // FmtFlag type definition
35+ type FmtFlag uint8
36+
3337// Log Level definition
3438const (
3539 LevelError Level = iota
@@ -40,10 +44,60 @@ const (
4044 LevelUnknown
4145)
4246
47+ // Format flags used to define log message format for each log entry
48+ const (
49+ FmtFlagLevel FmtFlag = iota
50+ FmtFlagTime
51+ FmtFlagUTCTime
52+ FmtFlagLongfile
53+ FmtFlagShortfile
54+ FmtFlagLine
55+ FmtFlagMessage
56+ FmtFlagCustom
57+ FmtFlagUnknown
58+ )
59+
4360var (
61+ // FmtFlags is the list of log format flags supported by aah/log library
62+ // Usage of flag order is up to format composition.
63+ // level - outputs INFO, DEBUG, ERROR, so on
64+ // time - outputs local time as per format supplied
65+ // utctime - outputs UTC time as per format supplied
66+ // longfile - outputs full file name: /a/b/c/d.go
67+ // shortfile - outputs final file name element: d.go
68+ // line - outputs file line number: L23
69+ // message - outputs given message along supplied arguments if they present
70+ // custom - outputs string as-is into log entry
71+ FmtFlags = map [string ]FmtFlag {
72+ "level" : FmtFlagLevel ,
73+ "time" : FmtFlagTime ,
74+ "utctime" : FmtFlagUTCTime ,
75+ "longfile" : FmtFlagLongfile ,
76+ "shortfile" : FmtFlagShortfile ,
77+ "line" : FmtFlagLine ,
78+ "message" : FmtFlagMessage ,
79+ "custom" : FmtFlagCustom ,
80+ }
81+
82+ // DefaultPattern is default log entry pattern in aah/log
83+ // For e.g:
84+ // 2006-01-02 15:04:05.000 INFO - This is my message
85+ DefaultPattern = "%time:2006-01-02 15:04:05.000 %level:-5 %custom:- %message"
86+
87+ // BackupTimeFormat is used for timestamp with filename on rotation
88+ BackupTimeFormat = "2006-01-02-15-04-05.000"
89+
90+ // ErrFormatStringEmpty returned when log format parameter is empty
91+ ErrFormatStringEmpty = errors .New ("log format string is empty" )
92+
4493 // ErrWriterIsClosed returned when log writer is closed
4594 ErrWriterIsClosed = errors .New ("log writer is closed" )
4695
96+ flagSeparator = "%"
97+ flagValueSeparator = ":"
98+ defaultFormat = "%v"
99+ filePermission = os .FileMode (0755 )
100+
47101 levelNameToLevel = map [string ]Level {
48102 "ERROR" : LevelError ,
49103 "WARN" : LevelWarn ,
@@ -114,37 +168,29 @@ type Logger interface {
114168}
115169
116170// New creates the logger based config supplied
117- func New (config string ) (Logger , error ) {
118- if strIsEmpty ( config ) {
171+ func New (configStr string ) (Logger , error ) {
172+ if ess . StrIsEmpty ( configStr ) {
119173 return nil , errors .New ("logger config is empty" )
120174 }
121175
122- cfg , err := forge .ParseString (config )
176+ cfg , err := config .ParseString (configStr )
123177 if err != nil {
124178 return nil , err
125179 }
126180
127- receiverType , err := cfg .GetString ("receiver" )
128- if err != nil {
129- return nil , err
181+ receiverType , found := cfg .String ("receiver" )
182+ if ! found {
183+ return nil , errors . New ( "receiver configuration is required" )
130184 }
131185 receiverType = strings .ToUpper (receiverType )
132186
133- levelName , err := cfg .GetString ("level" )
134- if err != nil {
135- levelName = "DEBUG"
136- }
137-
187+ levelName := cfg .StringDefault ("level" , "DEBUG" )
138188 level := levelByName (levelName )
139189 if level == LevelUnknown {
140190 return nil , fmt .Errorf ("unrecognized log level: %v" , levelName )
141191 }
142192
143- pattern , err := cfg .GetString ("pattern" )
144- if err != nil {
145- pattern = DefaultPattern
146- }
147-
193+ pattern := cfg .StringDefault ("pattern" , DefaultPattern )
148194 flags , err := parseFlag (pattern )
149195 if err != nil {
150196 return nil , err
@@ -197,7 +243,7 @@ func fetchCallerInfo(calldepth int) (string, int) {
197243 return file , line
198244}
199245
200- func newConsoleReceiver (cfg * forge. Section , receiverType string , level Level , flags * []FlagPart ) (* Receiver , error ) {
246+ func newConsoleReceiver (cfg * config. Config , receiverType string , level Level , flags * []FlagPart ) (* Receiver , error ) {
201247 receiver := Receiver {
202248 Config : cfg ,
203249 Type : receiverType ,
@@ -214,7 +260,12 @@ func newConsoleReceiver(cfg *forge.Section, receiverType string, level Level, fl
214260 return & receiver , nil
215261}
216262
217- func newFileReceiver (cfg * forge.Section , receiverType string , level Level , flags * []FlagPart ) (* Receiver , error ) {
263+ func newFileReceiver (cfg * config.Config , receiverType string , level Level , flags * []FlagPart ) (* Receiver , error ) {
264+ maxSize := cfg .IntDefault ("rotate.size" , 100 )
265+ if maxSize > 2048 { // maximum 2GB file size
266+ return nil , errors .New ("maximum 2GB file size supported for rotation" )
267+ }
268+
218269 receiver := Receiver {
219270 Config : cfg ,
220271 Type : receiverType ,
@@ -232,16 +283,16 @@ func newFileReceiver(cfg *forge.Section, receiverType string, level Level, flags
232283 return nil , err
233284 }
234285
235- rotate , _ := cfg .GetSection ("rotate" )
236- receiver .rotate , _ = rotate .GetString ("mode" )
286+ receiver .rotate = cfg .StringDefault ("rotate.mode" , "daily" )
287+ // rotate, _ := cfg.GetSection("rotate")
288+ // receiver.rotate, _ = rotate.GetString("mode")
237289 switch receiver .rotate {
238290 case "daily" :
239291 receiver .setOpenDay ()
240292 case "lines" :
241- receiver .maxLines , _ = rotate . GetInteger ( " lines" )
293+ receiver .maxLines = int64 ( cfg . IntDefault ( "rotate. lines", 0 ) )
242294 case "size" :
243- receiver .maxSize , _ = rotate .GetInteger ("size" )
244- receiver .maxSize = receiver .maxSize * 1024 * 1024
295+ receiver .maxSize = int64 (maxSize * 1024 * 1024 )
245296 }
246297
247298 return & receiver , nil
0 commit comments