github.com/mmatczuk/gohan@v0.0.0-20170206152520-30e45d9bdb69/extension/otto/gohan_logging.go (about)

     1  // Copyright (C) 2016 NTT Innovation Institute, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package otto
    17  
    18  import (
    19  	"github.com/robertkrimen/otto"
    20  	//Import otto underscore lib
    21  	_ "github.com/robertkrimen/otto/underscore"
    22  
    23  	l "github.com/cloudwan/gohan/log"
    24  )
    25  
    26  const (
    27  	// e.g. {Log level} must be {an int}: "ERROR"
    28  	wrongTypeErrorMessageFormat = "%s must be %s: %v"
    29  )
    30  
    31  func init() {
    32  	gohanLoggingInit := func(env *Environment) {
    33  		vm := env.VM
    34  
    35  		builtins := map[string]interface{}{
    36  			"gohan_log": func(call otto.FunctionCall) otto.Value {
    37  				VerifyCallArguments(&call, "gohan_log", 3)
    38  
    39  				// TODO:
    40  				// Taking this as an argument is a workaround
    41  				// for Otto returning stale values of variables
    42  				// that have been changed in javascript.
    43  				// We can get this from LOG_MODULE javascript
    44  				// variable if we fix the problem.
    45  				module, err := GetString(call.Argument(0))
    46  				if err != nil {
    47  					ThrowOttoException(&call, "Log module: %v", err)
    48  				}
    49  				logger := l.NewLoggerForModule(module)
    50  
    51  				intLevel, err := GetInt64(call.Argument(1))
    52  				if err != nil {
    53  					ThrowOttoException(&call, "Log level: %v", err)
    54  				}
    55  				level := l.Level(intLevel)
    56  
    57  				message, err := GetString(call.Argument(2))
    58  				if err != nil {
    59  					ThrowOttoException(&call, "Message: %v", err)
    60  				}
    61  
    62  				logGeneral(logger, level, message)
    63  
    64  				return otto.Value{}
    65  			},
    66  		}
    67  		for name, object := range builtins {
    68  			vm.Set(name, object)
    69  		}
    70  
    71  		// op/go-logging/level.go has levelNames[], but it's unexported
    72  		logLevels := map[string]l.Level{
    73  			"CRITICAL": l.CRITICAL,
    74  			"ERROR":    l.ERROR,
    75  			"WARNING":  l.WARNING,
    76  			"NOTICE":   l.NOTICE,
    77  			"INFO":     l.INFO,
    78  			"DEBUG":    l.DEBUG,
    79  		}
    80  		vm.Set("LOG_LEVEL", logLevels)
    81  
    82  		vm.Set("LOG_MODULE", "gohan.extension."+env.Name)
    83  
    84  		err := env.Load("<Gohan logging built-ins>", `
    85  		function gohan_log_module_push(new_module){
    86  		    var old_module = LOG_MODULE;
    87  		    LOG_MODULE += "." + new_module;
    88  		    return old_module;
    89  		}
    90  
    91  		function gohan_log_module_restore(old_module){
    92  		    LOG_MODULE = old_module;
    93  		}
    94  
    95  		function gohan_log_critical(msg) {
    96  		    gohan_log(LOG_MODULE, LOG_LEVEL.CRITICAL, msg);
    97  		}
    98  
    99  		function gohan_log_error(msg) {
   100  		    gohan_log(LOG_MODULE, LOG_LEVEL.ERROR, msg);
   101  		}
   102  
   103  		function gohan_log_warning(msg) {
   104  		    gohan_log(LOG_MODULE, LOG_LEVEL.WARNING, msg);
   105  		}
   106  
   107  		function gohan_log_notice(msg) {
   108  		    gohan_log(LOG_MODULE, LOG_LEVEL.NOTICE, msg);
   109  		}
   110  
   111  		function gohan_log_info(msg) {
   112  		    gohan_log(LOG_MODULE, LOG_LEVEL.INFO, msg);
   113  		}
   114  
   115  		function gohan_log_debug(msg) {
   116  		    gohan_log(LOG_MODULE, LOG_LEVEL.DEBUG, msg);
   117  		}
   118  		`)
   119  		if err != nil {
   120  			log.Fatal(err)
   121  		}
   122  	}
   123  	RegisterInit(gohanLoggingInit)
   124  }
   125  
   126  // logGeneral can be replaced with logger.Log(level, format, args) when https://github.com/op/go-logging/issues/80 gets fixed.
   127  func logGeneral(logger l.Logger, level l.Level, format string, args ...interface{}) {
   128  	var logAction func(format string, args ...interface{})
   129  	switch level {
   130  	case l.CRITICAL:
   131  		logAction = logger.Critical
   132  	case l.ERROR:
   133  		logAction = logger.Error
   134  	case l.WARNING:
   135  		logAction = logger.Warning
   136  	case l.NOTICE:
   137  		logAction = logger.Notice
   138  	case l.INFO:
   139  		logAction = logger.Info
   140  	case l.DEBUG:
   141  		logAction = logger.Debug
   142  	}
   143  
   144  	logAction(format, args...)
   145  }
   146  
   147  // PushJSLogModule appends newModule to log module in env, returns a function that restores the original value
   148  func PushJSLogModule(env *Environment, newModule string) (restore func()) {
   149  	newModuleInVM, _ := env.VM.ToValue(newModule)
   150  	oldModule := pushJSLogModule(env, newModuleInVM)
   151  	return func() {
   152  		restoreJSLogModule(env, oldModule)
   153  	}
   154  }
   155  
   156  func restoreJSLogModule(env *Environment, oldModule otto.Value) {
   157  	_, err := env.VM.Call("gohan_log_module_restore", nil, oldModule)
   158  	if err != nil {
   159  		log.Error("Calling gohan_log_module_restore: " + err.Error())
   160  	}
   161  }
   162  
   163  func pushJSLogModule(env *Environment, newModule otto.Value) (oldModule otto.Value) {
   164  	oldModule, err := env.VM.Call("gohan_log_module_push", nil, newModule)
   165  	if err != nil {
   166  		log.Error("Calling gohan_log_module_push: " + err.Error())
   167  	}
   168  	return
   169  }