github.com/snowflakedb/gosnowflake@v1.9.0/log.go (about)

     1  // Copyright (c) 2017-2022 Snowflake Computing Inc. All rights reserved.
     2  
     3  package gosnowflake
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	rlog "github.com/sirupsen/logrus"
     9  	"io"
    10  	"os"
    11  	"path"
    12  	"runtime"
    13  	"strings"
    14  	"time"
    15  )
    16  
    17  // SFSessionIDKey is context key of session id
    18  const SFSessionIDKey contextKey = "LOG_SESSION_ID"
    19  
    20  // SFSessionUserKey is context key of  user id of a session
    21  const SFSessionUserKey contextKey = "LOG_USER"
    22  
    23  // LogKeys these keys in context should be included in logging messages when using logger.WithContext
    24  var LogKeys = [...]contextKey{SFSessionIDKey, SFSessionUserKey}
    25  
    26  // SFLogger Snowflake logger interface to expose FieldLogger defined in logrus
    27  type SFLogger interface {
    28  	rlog.Ext1FieldLogger
    29  	SetLogLevel(level string) error
    30  	GetLogLevel() string
    31  	WithContext(ctx context.Context) *rlog.Entry
    32  	SetOutput(output io.Writer)
    33  	CloseFileOnLoggerReplace(file *os.File) error
    34  	Replace(newLogger *SFLogger)
    35  }
    36  
    37  // SFCallerPrettyfier to provide base file name and function name from calling frame used in SFLogger
    38  func SFCallerPrettyfier(frame *runtime.Frame) (string, string) {
    39  	return path.Base(frame.Function), fmt.Sprintf("%s:%d", path.Base(frame.File), frame.Line)
    40  }
    41  
    42  type defaultLogger struct {
    43  	inner   *rlog.Logger
    44  	enabled bool
    45  	file    *os.File
    46  }
    47  
    48  // SetLogLevel set logging level for calling defaultLogger
    49  func (log *defaultLogger) SetLogLevel(level string) error {
    50  	newEnabled := strings.ToUpper(level) != "OFF"
    51  	log.enabled = newEnabled
    52  	if newEnabled {
    53  		actualLevel, err := rlog.ParseLevel(level)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		log.inner.SetLevel(actualLevel)
    58  	}
    59  	return nil
    60  }
    61  
    62  // GetLogLevel return current log level
    63  func (log *defaultLogger) GetLogLevel() string {
    64  	if !log.enabled {
    65  		return "OFF"
    66  	}
    67  	return log.inner.GetLevel().String()
    68  }
    69  
    70  // CloseFileOnLoggerReplace set a file to be closed when releasing resources occupied by the logger
    71  func (log *defaultLogger) CloseFileOnLoggerReplace(file *os.File) error {
    72  	if log.file != nil && log.file != file {
    73  		return fmt.Errorf("could not set a file to close on logger reset because there were already set one")
    74  	}
    75  	log.file = file
    76  	return nil
    77  }
    78  
    79  // Replace substitute logger by a given one
    80  func (log *defaultLogger) Replace(newLogger *SFLogger) {
    81  	SetLogger(newLogger)
    82  	closeLogFile(log.file)
    83  }
    84  
    85  func closeLogFile(file *os.File) {
    86  	if file != nil {
    87  		err := file.Close()
    88  		if err != nil {
    89  			logger.Errorf("failed to close log file: %s", err)
    90  		}
    91  	}
    92  }
    93  
    94  // WithContext return Entry to include fields in context
    95  func (log *defaultLogger) WithContext(ctx context.Context) *rlog.Entry {
    96  	fields := context2Fields(ctx)
    97  	return log.inner.WithFields(*fields)
    98  }
    99  
   100  // CreateDefaultLogger return a new instance of SFLogger with default config
   101  func CreateDefaultLogger() SFLogger {
   102  	var rLogger = rlog.New()
   103  	var formatter = rlog.TextFormatter{CallerPrettyfier: SFCallerPrettyfier}
   104  	rLogger.SetReportCaller(true)
   105  	rLogger.SetFormatter(&formatter)
   106  	var ret = defaultLogger{inner: rLogger, enabled: true}
   107  	return &ret //(&ret).(*SFLogger)
   108  }
   109  
   110  // WithField allocates a new entry and adds a field to it.
   111  // Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to
   112  // this new returned entry.
   113  // If you want multiple fields, use `WithFields`.
   114  func (log *defaultLogger) WithField(key string, value interface{}) *rlog.Entry {
   115  	return log.inner.WithField(key, value)
   116  
   117  }
   118  
   119  // Adds a struct of fields to the log entry. All it does is call `WithField` for
   120  // each `Field`.
   121  func (log *defaultLogger) WithFields(fields rlog.Fields) *rlog.Entry {
   122  	return log.inner.WithFields(fields)
   123  }
   124  
   125  // Add an error as single field to the log entry.  All it does is call
   126  // `WithError` for the given `error`.
   127  func (log *defaultLogger) WithError(err error) *rlog.Entry {
   128  	return log.inner.WithError(err)
   129  }
   130  
   131  // Overrides the time of the log entry.
   132  func (log *defaultLogger) WithTime(t time.Time) *rlog.Entry {
   133  	return log.inner.WithTime(t)
   134  }
   135  
   136  func (log *defaultLogger) Logf(level rlog.Level, format string, args ...interface{}) {
   137  	log.inner.Logf(level, format, args...)
   138  }
   139  
   140  func (log *defaultLogger) Tracef(format string, args ...interface{}) {
   141  	if log.enabled {
   142  		log.inner.Tracef(format, args...)
   143  	}
   144  }
   145  
   146  func (log *defaultLogger) Debugf(format string, args ...interface{}) {
   147  	if log.enabled {
   148  		log.inner.Debugf(format, args...)
   149  	}
   150  }
   151  
   152  func (log *defaultLogger) Infof(format string, args ...interface{}) {
   153  	if log.enabled {
   154  		log.inner.Infof(format, args...)
   155  	}
   156  }
   157  
   158  func (log *defaultLogger) Printf(format string, args ...interface{}) {
   159  	if log.enabled {
   160  		log.inner.Printf(format, args...)
   161  	}
   162  }
   163  
   164  func (log *defaultLogger) Warnf(format string, args ...interface{}) {
   165  	if log.enabled {
   166  		log.inner.Warnf(format, args...)
   167  	}
   168  }
   169  
   170  func (log *defaultLogger) Warningf(format string, args ...interface{}) {
   171  	if log.enabled {
   172  		log.inner.Warningf(format, args...)
   173  	}
   174  }
   175  
   176  func (log *defaultLogger) Errorf(format string, args ...interface{}) {
   177  	if log.enabled {
   178  		log.inner.Errorf(format, args...)
   179  	}
   180  }
   181  
   182  func (log *defaultLogger) Fatalf(format string, args ...interface{}) {
   183  	if log.enabled {
   184  		log.inner.Fatalf(format, args...)
   185  	}
   186  }
   187  
   188  func (log *defaultLogger) Panicf(format string, args ...interface{}) {
   189  	if log.enabled {
   190  		log.inner.Panicf(format, args...)
   191  	}
   192  }
   193  
   194  func (log *defaultLogger) Log(level rlog.Level, args ...interface{}) {
   195  	log.inner.Log(level, args...)
   196  }
   197  
   198  func (log *defaultLogger) LogFn(level rlog.Level, fn rlog.LogFunction) {
   199  	log.inner.LogFn(level, fn)
   200  }
   201  
   202  func (log *defaultLogger) Trace(args ...interface{}) {
   203  	if log.enabled {
   204  		log.inner.Trace(args...)
   205  	}
   206  }
   207  
   208  func (log *defaultLogger) Debug(args ...interface{}) {
   209  	if log.enabled {
   210  		log.inner.Debug(args...)
   211  	}
   212  }
   213  
   214  func (log *defaultLogger) Info(args ...interface{}) {
   215  	if log.enabled {
   216  		log.inner.Info(args...)
   217  	}
   218  }
   219  
   220  func (log *defaultLogger) Print(args ...interface{}) {
   221  	if log.enabled {
   222  		log.inner.Print(args...)
   223  	}
   224  }
   225  
   226  func (log *defaultLogger) Warn(args ...interface{}) {
   227  	if log.enabled {
   228  		log.inner.Warn(args...)
   229  	}
   230  }
   231  
   232  func (log *defaultLogger) Warning(args ...interface{}) {
   233  	if log.enabled {
   234  		log.inner.Warning(args...)
   235  	}
   236  }
   237  
   238  func (log *defaultLogger) Error(args ...interface{}) {
   239  	if log.enabled {
   240  		log.inner.Error(args...)
   241  	}
   242  }
   243  
   244  func (log *defaultLogger) Fatal(args ...interface{}) {
   245  	if log.enabled {
   246  		log.inner.Fatal(args...)
   247  	}
   248  }
   249  
   250  func (log *defaultLogger) Panic(args ...interface{}) {
   251  	if log.enabled {
   252  		log.inner.Panic(args...)
   253  	}
   254  }
   255  
   256  func (log *defaultLogger) TraceFn(fn rlog.LogFunction) {
   257  	if log.enabled {
   258  		log.inner.TraceFn(fn)
   259  	}
   260  }
   261  
   262  func (log *defaultLogger) DebugFn(fn rlog.LogFunction) {
   263  	if log.enabled {
   264  		log.inner.DebugFn(fn)
   265  	}
   266  }
   267  
   268  func (log *defaultLogger) InfoFn(fn rlog.LogFunction) {
   269  	if log.enabled {
   270  		log.inner.InfoFn(fn)
   271  	}
   272  }
   273  
   274  func (log *defaultLogger) PrintFn(fn rlog.LogFunction) {
   275  	if log.enabled {
   276  		log.inner.PrintFn(fn)
   277  	}
   278  }
   279  
   280  func (log *defaultLogger) WarnFn(fn rlog.LogFunction) {
   281  	if log.enabled {
   282  		log.inner.PrintFn(fn)
   283  	}
   284  }
   285  
   286  func (log *defaultLogger) WarningFn(fn rlog.LogFunction) {
   287  	if log.enabled {
   288  		log.inner.WarningFn(fn)
   289  	}
   290  }
   291  
   292  func (log *defaultLogger) ErrorFn(fn rlog.LogFunction) {
   293  	if log.enabled {
   294  		log.inner.ErrorFn(fn)
   295  	}
   296  }
   297  
   298  func (log *defaultLogger) FatalFn(fn rlog.LogFunction) {
   299  	if log.enabled {
   300  		log.inner.FatalFn(fn)
   301  	}
   302  }
   303  
   304  func (log *defaultLogger) PanicFn(fn rlog.LogFunction) {
   305  	if log.enabled {
   306  		log.inner.PanicFn(fn)
   307  	}
   308  }
   309  
   310  func (log *defaultLogger) Logln(level rlog.Level, args ...interface{}) {
   311  	log.inner.Logln(level, args...)
   312  }
   313  
   314  func (log *defaultLogger) Traceln(args ...interface{}) {
   315  	if log.enabled {
   316  		log.inner.Traceln(args...)
   317  	}
   318  }
   319  
   320  func (log *defaultLogger) Debugln(args ...interface{}) {
   321  	if log.enabled {
   322  		log.inner.Debugln(args...)
   323  	}
   324  }
   325  
   326  func (log *defaultLogger) Infoln(args ...interface{}) {
   327  	if log.enabled {
   328  		log.inner.Infoln(args...)
   329  	}
   330  }
   331  
   332  func (log *defaultLogger) Println(args ...interface{}) {
   333  	if log.enabled {
   334  		log.inner.Println(args...)
   335  	}
   336  }
   337  
   338  func (log *defaultLogger) Warnln(args ...interface{}) {
   339  	if log.enabled {
   340  		log.inner.Warnln(args...)
   341  	}
   342  }
   343  
   344  func (log *defaultLogger) Warningln(args ...interface{}) {
   345  	if log.enabled {
   346  		log.inner.Warningln(args...)
   347  	}
   348  }
   349  
   350  func (log *defaultLogger) Errorln(args ...interface{}) {
   351  	if log.enabled {
   352  		log.inner.Errorln(args...)
   353  	}
   354  }
   355  
   356  func (log *defaultLogger) Fatalln(args ...interface{}) {
   357  	if log.enabled {
   358  		log.inner.Fatalln(args...)
   359  	}
   360  }
   361  
   362  func (log *defaultLogger) Panicln(args ...interface{}) {
   363  	if log.enabled {
   364  		log.inner.Panicln(args...)
   365  	}
   366  }
   367  
   368  func (log *defaultLogger) Exit(code int) {
   369  	log.inner.Exit(code)
   370  }
   371  
   372  // SetLevel sets the logger level.
   373  func (log *defaultLogger) SetLevel(level rlog.Level) {
   374  	log.inner.SetLevel(level)
   375  }
   376  
   377  // GetLevel returns the logger level.
   378  func (log *defaultLogger) GetLevel() rlog.Level {
   379  	return log.inner.GetLevel()
   380  }
   381  
   382  // AddHook adds a hook to the logger hooks.
   383  func (log *defaultLogger) AddHook(hook rlog.Hook) {
   384  	log.inner.AddHook(hook)
   385  
   386  }
   387  
   388  // IsLevelEnabled checks if the log level of the logger is greater than the level param
   389  func (log *defaultLogger) IsLevelEnabled(level rlog.Level) bool {
   390  	return log.inner.IsLevelEnabled(level)
   391  }
   392  
   393  // SetFormatter sets the logger formatter.
   394  func (log *defaultLogger) SetFormatter(formatter rlog.Formatter) {
   395  	log.inner.SetFormatter(formatter)
   396  }
   397  
   398  // SetOutput sets the logger output.
   399  func (log *defaultLogger) SetOutput(output io.Writer) {
   400  	log.inner.SetOutput(output)
   401  }
   402  
   403  func (log *defaultLogger) SetReportCaller(reportCaller bool) {
   404  	log.inner.SetReportCaller(reportCaller)
   405  }
   406  
   407  // SetLogger set a new logger of SFLogger interface for gosnowflake
   408  func SetLogger(inLogger *SFLogger) {
   409  	logger = *inLogger //.(*defaultLogger)
   410  }
   411  
   412  // GetLogger return logger that is not public
   413  func GetLogger() SFLogger {
   414  	return logger
   415  }
   416  
   417  func context2Fields(ctx context.Context) *rlog.Fields {
   418  	var fields = rlog.Fields{}
   419  	if ctx == nil {
   420  		return &fields
   421  	}
   422  
   423  	for i := 0; i < len(LogKeys); i++ {
   424  		if ctx.Value(LogKeys[i]) != nil {
   425  			fields[string(LogKeys[i])] = ctx.Value(LogKeys[i])
   426  		}
   427  	}
   428  	return &fields
   429  }