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  }