github.com/go-spring/spring-base@v1.1.3/log/log_entry.go (about)

     1  /*
     2   * Copyright 2012-2019 the original author or authors.
     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   *      https://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 log
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"github.com/go-spring/spring-base/clock"
    24  	"github.com/go-spring/spring-base/log/internal"
    25  	"github.com/go-spring/spring-base/util"
    26  )
    27  
    28  type T = func() []interface{}
    29  
    30  func W(fn func() []Field) Field {
    31  	return Field{Key: "", Val: funcValue(fn)}
    32  }
    33  
    34  type funcValue func() []Field
    35  
    36  func (v funcValue) Encode(enc Encoder) error {
    37  	panic(util.ForbiddenMethod)
    38  }
    39  
    40  // publisher will drop a log message when the filter method returns true.
    41  type publisher interface {
    42  	enableLevel(level Level) bool
    43  	publish(e *Event)
    44  }
    45  
    46  // Entry is an Entry implementation that has context and errno.
    47  type Entry struct {
    48  	ctx  context.Context
    49  	pub  publisher
    50  	tag  string
    51  	skip int
    52  }
    53  
    54  func (e *Entry) WithSkip(n int) *Entry {
    55  	e.skip = n
    56  	return e
    57  }
    58  
    59  func (e *Entry) WithTag(tag string) *Entry {
    60  	e.tag = tag
    61  	return e
    62  }
    63  
    64  func (e *Entry) WithContext(ctx context.Context) *Entry {
    65  	e.ctx = ctx
    66  	return e
    67  }
    68  
    69  // Trace outputs log with level TraceLevel.
    70  func (e *Entry) Trace(args ...interface{}) *Event {
    71  	return publish(e.pub, TraceLevel, e.skip, e, "", args, nil)
    72  }
    73  
    74  // Tracef outputs log with level TraceLevel.
    75  func (e *Entry) Tracef(format string, args ...interface{}) *Event {
    76  	return publish(e.pub, TraceLevel, e.skip, e, format, args, nil)
    77  }
    78  
    79  // Tracew outputs log with level TraceLevel.
    80  func (e *Entry) Tracew(fields ...Field) *Event {
    81  	return publish(e.pub, TraceLevel, e.skip, e, "", nil, fields)
    82  }
    83  
    84  // Debug outputs log with level DebugLevel.
    85  func (e *Entry) Debug(args ...interface{}) *Event {
    86  	return publish(e.pub, DebugLevel, e.skip, e, "", args, nil)
    87  }
    88  
    89  // Debugf outputs log with level DebugLevel.
    90  func (e *Entry) Debugf(format string, args ...interface{}) *Event {
    91  	return publish(e.pub, DebugLevel, e.skip, e, format, args, nil)
    92  }
    93  
    94  // Debugw outputs log with level DebugLevel.
    95  func (e *Entry) Debugw(fields ...Field) *Event {
    96  	return publish(e.pub, DebugLevel, e.skip, e, "", nil, fields)
    97  }
    98  
    99  // Info outputs log with level InfoLevel.
   100  func (e *Entry) Info(args ...interface{}) *Event {
   101  	return publish(e.pub, InfoLevel, e.skip, e, "", args, nil)
   102  }
   103  
   104  // Infof outputs log with level InfoLevel.
   105  func (e *Entry) Infof(format string, args ...interface{}) *Event {
   106  	return publish(e.pub, InfoLevel, e.skip, e, format, args, nil)
   107  }
   108  
   109  // Infow outputs log with level InfoLevel.
   110  func (e *Entry) Infow(fields ...Field) *Event {
   111  	return publish(e.pub, InfoLevel, e.skip, e, "", nil, fields)
   112  }
   113  
   114  // Warn outputs log with level WarnLevel.
   115  func (e *Entry) Warn(args ...interface{}) *Event {
   116  	return publish(e.pub, WarnLevel, e.skip, e, "", args, nil)
   117  }
   118  
   119  // Warnf outputs log with level WarnLevel.
   120  func (e *Entry) Warnf(format string, args ...interface{}) *Event {
   121  	return publish(e.pub, WarnLevel, e.skip, e, format, args, nil)
   122  }
   123  
   124  // Warnw outputs log with level WarnLevel.
   125  func (e *Entry) Warnw(fields ...Field) *Event {
   126  	return publish(e.pub, WarnLevel, e.skip, e, "", nil, fields)
   127  }
   128  
   129  // Error outputs log with level ErrorLevel.
   130  func (e *Entry) Error(args ...interface{}) *Event {
   131  	return publish(e.pub, ErrorLevel, e.skip, e, "", args, nil)
   132  }
   133  
   134  // Errorf outputs log with level ErrorLevel.
   135  func (e *Entry) Errorf(format string, args ...interface{}) *Event {
   136  	return publish(e.pub, ErrorLevel, e.skip, e, format, args, nil)
   137  }
   138  
   139  // Errorw outputs log with level ErrorLevel.
   140  func (e *Entry) Errorw(fields ...Field) *Event {
   141  	return publish(e.pub, ErrorLevel, e.skip, e, "", nil, fields)
   142  }
   143  
   144  // Panic outputs log with level PanicLevel.
   145  func (e *Entry) Panic(args ...interface{}) *Event {
   146  	return publish(e.pub, PanicLevel, e.skip, e, "", args, nil)
   147  }
   148  
   149  // Panicf outputs log with level PanicLevel.
   150  func (e *Entry) Panicf(format string, args ...interface{}) *Event {
   151  	return publish(e.pub, PanicLevel, e.skip, e, format, args, nil)
   152  }
   153  
   154  // Panicw outputs log with level PanicLevel.
   155  func (e *Entry) Panicw(fields ...Field) *Event {
   156  	return publish(e.pub, PanicLevel, e.skip, e, "", nil, fields)
   157  }
   158  
   159  // Fatal outputs log with level FatalLevel.
   160  func (e *Entry) Fatal(args ...interface{}) *Event {
   161  	return publish(e.pub, FatalLevel, e.skip, e, "", args, nil)
   162  }
   163  
   164  // Fatalf outputs log with level FatalLevel.
   165  func (e *Entry) Fatalf(format string, args ...interface{}) *Event {
   166  	return publish(e.pub, FatalLevel, e.skip, e, format, args, nil)
   167  }
   168  
   169  // Fatalw outputs log with level FatalLevel.
   170  func (e *Entry) Fatalw(fields ...Field) *Event {
   171  	return publish(e.pub, FatalLevel, e.skip, e, "", nil, fields)
   172  }
   173  
   174  func getMessage(format string, args []interface{}) string {
   175  	if len(args) == 0 {
   176  		return format
   177  	}
   178  	if len(args) == 1 {
   179  		fn, ok := args[0].(func() []interface{})
   180  		if ok {
   181  			args = fn()
   182  		}
   183  	}
   184  	if format == "" {
   185  		return fmt.Sprint(args...)
   186  	}
   187  	return fmt.Sprintf(format, args...)
   188  }
   189  
   190  func publish(p publisher, level Level, skip int, e *Entry, format string, args []interface{}, fields []Field) *Event {
   191  	if !p.enableLevel(level) {
   192  		return nil
   193  	}
   194  	if len(fields) == 1 {
   195  		v, ok := fields[0].Val.(funcValue)
   196  		if ok {
   197  			fields = v()
   198  		}
   199  	}
   200  	message := getMessage(format, args)
   201  	file, line, _ := internal.Caller(skip+2, true)
   202  	event := &Event{
   203  		Tag:     e.tag,
   204  		Time:    clock.Now(e.ctx),
   205  		Context: e.ctx,
   206  		File:    file,
   207  		Line:    line,
   208  		Level:   level,
   209  		Fields:  fields,
   210  		Message: message,
   211  	}
   212  	p.publish(event)
   213  	return event
   214  }