github.com/wiselike/revel-cmd@v1.2.1/logger/init.go (about) 1 package logger 2 3 // Get all handlers based on the Config (if available). 4 import ( 5 "fmt" 6 "log" 7 "os" 8 "path/filepath" 9 "strings" 10 11 "github.com/revel/config" 12 ) 13 14 func InitializeFromConfig(basePath string, config *config.Context) (c *CompositeMultiHandler) { 15 // If running in test mode suppress anything that is not an error 16 if config != nil && config.BoolDefault(TestModeFlag, false) { 17 // Preconfigure all the options 18 config.SetOption("log.info.output", "none") 19 config.SetOption("log.debug.output", "none") 20 config.SetOption("log.warn.output", "none") 21 config.SetOption("log.error.output", "stderr") 22 config.SetOption("log.crit.output", "stderr") 23 } 24 25 // If the configuration has an all option we can skip some 26 c, _ = NewCompositeMultiHandler() 27 28 // Filters are assigned first, non filtered items override filters 29 if config != nil && !config.BoolDefault(TestModeFlag, false) { 30 initAllLog(c, basePath, config) 31 } 32 initLogLevels(c, basePath, config) 33 if c.CriticalHandler == nil && c.ErrorHandler != nil { 34 c.CriticalHandler = c.ErrorHandler 35 } 36 if config != nil && !config.BoolDefault(TestModeFlag, false) { 37 initFilterLog(c, basePath, config) 38 if c.CriticalHandler == nil && c.ErrorHandler != nil { 39 c.CriticalHandler = c.ErrorHandler 40 } 41 initRequestLog(c, basePath, config) 42 } 43 44 return c 45 } 46 47 // Init the log.all configuration options. 48 func initAllLog(c *CompositeMultiHandler, basePath string, config *config.Context) { 49 if config != nil { 50 extraLogFlag := config.BoolDefault(SpecialUseFlag, false) 51 if output, found := config.String("log.all.output"); found { 52 // Set all output for the specified handler 53 if extraLogFlag { 54 log.Printf("Adding standard handler for levels to >%s< ", output) 55 } 56 initHandlerFor(c, output, basePath, NewLogOptions(config, true, nil, LvlAllList...)) 57 } 58 } 59 } 60 61 // Init the filter options 62 // log.all.filter .... 63 // log.error.filter .... 64 func initFilterLog(c *CompositeMultiHandler, basePath string, config *config.Context) { 65 if config != nil { 66 extraLogFlag := config.BoolDefault(SpecialUseFlag, false) 67 68 for _, logFilter := range logFilterList { 69 // Init for all filters 70 for _, name := range []string{ 71 "all", "debug", "info", "warn", "error", "crit", 72 "trace", // TODO trace is deprecated 73 } { 74 optionList := config.Options(logFilter.LogPrefix + name + logFilter.LogSuffix) 75 for _, option := range optionList { 76 splitOptions := strings.Split(option, ".") 77 keyMap := map[string]interface{}{} 78 for x := 3; x < len(splitOptions); x += 2 { 79 keyMap[splitOptions[x]] = splitOptions[x+1] 80 } 81 phandler := logFilter.parentHandler(keyMap) 82 if extraLogFlag { 83 log.Printf("Adding key map handler %s %s output %s", option, name, config.StringDefault(option, "")) 84 fmt.Printf("Adding key map handler %s %s output %s matching %#v\n", option, name, config.StringDefault(option, ""), keyMap) 85 } 86 87 if name == "all" { 88 initHandlerFor(c, config.StringDefault(option, ""), basePath, NewLogOptions(config, false, phandler)) 89 } else { 90 initHandlerFor(c, config.StringDefault(option, ""), basePath, NewLogOptions(config, false, phandler, toLevel[name])) 91 } 92 } 93 } 94 } 95 } 96 } 97 98 // Init the log.error, log.warn etc configuration options. 99 func initLogLevels(c *CompositeMultiHandler, basePath string, config *config.Context) { 100 for _, name := range []string{ 101 "debug", "info", "warn", "error", "crit", 102 "trace", // TODO trace is deprecated 103 } { 104 if config != nil { 105 extraLogFlag := config.BoolDefault(SpecialUseFlag, false) 106 output, found := config.String("log." + name + ".output") 107 if found { 108 if extraLogFlag { 109 log.Printf("Adding standard handler %s output %s", name, output) 110 } 111 initHandlerFor(c, output, basePath, NewLogOptions(config, true, nil, toLevel[name])) 112 } 113 // Gets the list of options with said prefix 114 } else { 115 initHandlerFor(c, "stderr", basePath, NewLogOptions(config, true, nil, toLevel[name])) 116 } 117 } 118 } 119 120 // Init the request log options. 121 func initRequestLog(c *CompositeMultiHandler, basePath string, config *config.Context) { 122 // Request logging to a separate output handler 123 // This takes the InfoHandlers and adds a MatchAbHandler handler to it to direct 124 // context with the word "section=requestlog" to that handler. 125 // Note if request logging is not enabled the MatchAbHandler will not be added and the 126 // request log messages will be sent out the INFO handler 127 outputRequest := "stdout" 128 if config != nil { 129 outputRequest = config.StringDefault("log.request.output", "") 130 } 131 oldInfo := c.InfoHandler 132 c.InfoHandler = nil 133 if outputRequest != "" { 134 initHandlerFor(c, outputRequest, basePath, NewLogOptions(config, false, nil, LvlInfo)) 135 } 136 if c.InfoHandler != nil || oldInfo != nil { 137 if c.InfoHandler == nil { 138 c.InfoHandler = oldInfo 139 } else { 140 c.InfoHandler = MatchAbHandler("section", "requestlog", c.InfoHandler, oldInfo) 141 } 142 } 143 } 144 145 // Returns a handler for the level using the output string 146 // Accept formats for output string are 147 // LogFunctionMap[value] callback function 148 // `stdout` `stderr` `full/file/path/to/location/app.log` `full/file/path/to/location/app.json`. 149 func initHandlerFor(c *CompositeMultiHandler, output, basePath string, options *LogOptions) { 150 if options.Ctx != nil { 151 options.SetExtendedOptions( 152 "noColor", !options.Ctx.BoolDefault("log.colorize", true), 153 "smallDate", options.Ctx.BoolDefault("log.smallDate", true), 154 "maxSize", options.Ctx.IntDefault("log.maxsize", 1024*10), 155 "maxAge", options.Ctx.IntDefault("log.maxage", 14), 156 "maxBackups", options.Ctx.IntDefault("log.maxbackups", 14), 157 "compressBackups", !options.Ctx.BoolDefault("log.compressBackups", true), 158 ) 159 } 160 161 output = strings.TrimSpace(output) 162 if funcHandler, found := LogFunctionMap[output]; found { 163 funcHandler(c, options) 164 } else { 165 switch output { 166 case "": 167 fallthrough 168 case "off": 169 // No handler, discard data 170 default: 171 // Write to file specified 172 if !filepath.IsAbs(output) { 173 output = filepath.Join(basePath, output) 174 } 175 176 if err := os.MkdirAll(filepath.Dir(output), 0755); err != nil { 177 log.Panic(err) 178 } 179 180 if strings.HasSuffix(output, "json") { 181 c.SetJSONFile(output, options) 182 } else { 183 // Override defaults for a terminal file 184 options.SetExtendedOptions("noColor", true) 185 options.SetExtendedOptions("smallDate", false) 186 c.SetTerminalFile(output, options) 187 } 188 } 189 } 190 }