github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/common/flogging/logging.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package flogging 18 19 import ( 20 "io" 21 "os" 22 "strings" 23 24 "github.com/op/go-logging" 25 "github.com/spf13/viper" 26 ) 27 28 // A logger to log logging logs! 29 var logger = logging.MustGetLogger("logging") 30 31 var defaultFormat = "%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}" 32 var defaultOutput = os.Stderr 33 34 // The default logging level, in force until LoggingInit() is called or in 35 // case of configuration errors. 36 var fallbackDefaultLevel = logging.INFO 37 38 // LoggingInitFromViper is a 'hook' called at the beginning of command processing to 39 // parse logging-related options specified either on the command-line or in 40 // config files. Command-line options take precedence over config file 41 // options, and can also be passed as suitably-named environment variables. To 42 // change module logging levels at runtime call `logging.SetLevel(level, 43 // module)`. To debug this routine include logging=debug as the first 44 // term of the logging specification. 45 // TODO this initialization is specific to the peer config format. The viper 46 // references should be removed, and this path should be moved into the peer 47 func InitFromViper(command string) { 48 spec := viper.GetString("logging_level") 49 if spec == "" { 50 spec = viper.GetString("logging." + command) 51 } 52 defaultLevel := InitFromSpec(spec) 53 logger.Debugf("Setting default logging level to %s for command '%s'", defaultLevel, command) 54 } 55 56 // LoggingInit initializes the logging based on the supplied spec, it is exposed externally 57 // so that consumers of the flogging package who do not wish to use the default config structure 58 // may parse their own logging specification 59 func InitFromSpec(spec string) logging.Level { 60 // Parse the logging specification in the form 61 // [<module>[,<module>...]=]<level>[:[<module>[,<module>...]=]<level>...] 62 defaultLevel := fallbackDefaultLevel 63 var err error 64 if spec != "" { 65 fields := strings.Split(spec, ":") 66 for _, field := range fields { 67 split := strings.Split(field, "=") 68 switch len(split) { 69 case 1: 70 // Default level 71 defaultLevel, err = logging.LogLevel(field) 72 if err != nil { 73 logger.Warningf("Logging level '%s' not recognized, defaulting to %s : %s", field, defaultLevel, err) 74 defaultLevel = fallbackDefaultLevel // NB - 'defaultLevel' was overwritten 75 } 76 case 2: 77 // <module>[,<module>...]=<level> 78 if level, err := logging.LogLevel(split[1]); err != nil { 79 logger.Warningf("Invalid logging level in '%s' ignored", field) 80 } else if split[0] == "" { 81 logger.Warningf("Invalid logging override specification '%s' ignored - no module specified", field) 82 } else { 83 modules := strings.Split(split[0], ",") 84 for _, module := range modules { 85 logging.SetLevel(level, module) 86 logger.Debugf("Setting logging level for module '%s' to %s", module, level) 87 } 88 } 89 default: 90 logger.Warningf("Invalid logging override '%s' ignored; Missing ':' ?", field) 91 } 92 } 93 } 94 // Set the default logging level for all modules 95 logging.SetLevel(defaultLevel, "") 96 return defaultLevel 97 } 98 99 // DefaultLevel returns the fallback value for loggers to use if parsing fails 100 func DefaultLevel() logging.Level { 101 return fallbackDefaultLevel 102 } 103 104 // Initiate 'leveled' logging using the default format and output location 105 func init() { 106 SetLoggingFormat(defaultFormat, defaultOutput) 107 } 108 109 // SetLoggingFormat sets the logging format and the location of the log output 110 func SetLoggingFormat(formatString string, output io.Writer) { 111 if formatString == "" { 112 formatString = defaultFormat 113 } 114 format := logging.MustStringFormatter(formatString) 115 116 initLoggingBackend(format, output) 117 } 118 119 // initialize the logging backend based on the provided logging formatter 120 // and I/O writer 121 func initLoggingBackend(logFormatter logging.Formatter, output io.Writer) { 122 backend := logging.NewLogBackend(output, "", 0) 123 backendFormatter := logging.NewBackendFormatter(backend, logFormatter) 124 logging.SetBackend(backendFormatter).SetLevel(fallbackDefaultLevel, "") 125 } 126 127 // GetModuleLevel gets the current logging level for the specified module 128 func GetModuleLevel(module string) (string, error) { 129 // logging.GetLevel() returns the logging level for the module, if defined. 130 // otherwise, it returns the default logging level, as set by 131 // flogging/logging.go 132 level := logging.GetLevel(module).String() 133 134 logger.Debugf("Module '%s' logger enabled for log level: %s", module, level) 135 136 return level, nil 137 } 138 139 // SetModuleLevel sets the logging level for the specified module. This is 140 // currently only called from admin.go but can be called from anywhere in the 141 // code on a running peer to dynamically change the log level for the module. 142 func SetModuleLevel(module string, logLevel string) (string, error) { 143 level, err := logging.LogLevel(logLevel) 144 145 if err != nil { 146 logger.Warningf("Invalid logging level: %s - ignored", logLevel) 147 } else { 148 logging.SetLevel(logging.Level(level), module) 149 logger.Debugf("Module '%s' logger enabled for log level: %s", module, level) 150 } 151 152 logLevelString := level.String() 153 154 return logLevelString, err 155 }