storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/logger/console.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     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 logger
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"os"
    23  	"strings"
    24  	"time"
    25  
    26  	"storj.io/minio/cmd/logger/message/log"
    27  	"storj.io/minio/pkg/color"
    28  	c "storj.io/minio/pkg/console"
    29  )
    30  
    31  // Logger interface describes the methods that need to be implemented to satisfy the interface requirements.
    32  type Logger interface {
    33  	json(msg string, args ...interface{})
    34  	quiet(msg string, args ...interface{})
    35  	pretty(msg string, args ...interface{})
    36  }
    37  
    38  func consoleLog(console Logger, msg string, args ...interface{}) {
    39  	switch {
    40  	case jsonFlag:
    41  		// Strip escape control characters from json message
    42  		msg = ansiRE.ReplaceAllLiteralString(msg, "")
    43  		console.json(msg, args...)
    44  	case quietFlag:
    45  		console.quiet(msg, args...)
    46  	default:
    47  		console.pretty(msg, args...)
    48  	}
    49  }
    50  
    51  // Fatal prints only fatal error message with no stack trace
    52  // it will be called for input validation failures
    53  func Fatal(err error, msg string, data ...interface{}) {
    54  	fatal(err, msg, data...)
    55  }
    56  
    57  func fatal(err error, msg string, data ...interface{}) {
    58  	var errMsg string
    59  	if msg != "" {
    60  		errMsg = errorFmtFunc(fmt.Sprintf(msg, data...), err, jsonFlag)
    61  	} else {
    62  		errMsg = err.Error()
    63  	}
    64  	consoleLog(fatalMessage, errMsg)
    65  }
    66  
    67  var fatalMessage fatalMsg
    68  
    69  type fatalMsg struct {
    70  }
    71  
    72  func (f fatalMsg) json(msg string, args ...interface{}) {
    73  	logJSON, err := json.Marshal(&log.Entry{
    74  		Level: FatalLvl.String(),
    75  		Time:  time.Now().UTC().Format(time.RFC3339Nano),
    76  		Trace: &log.Trace{Message: fmt.Sprintf(msg, args...), Source: []string{getSource(6)}},
    77  	})
    78  	if err != nil {
    79  		panic(err)
    80  	}
    81  	fmt.Println(string(logJSON))
    82  
    83  	os.Exit(1)
    84  
    85  }
    86  
    87  func (f fatalMsg) quiet(msg string, args ...interface{}) {
    88  	f.pretty(msg, args...)
    89  }
    90  
    91  var (
    92  	logTag      = "ERROR"
    93  	logBanner   = color.BgRed(color.FgWhite(color.Bold(logTag))) + " "
    94  	emptyBanner = color.BgRed(strings.Repeat(" ", len(logTag))) + " "
    95  	bannerWidth = len(logTag) + 1
    96  )
    97  
    98  func (f fatalMsg) pretty(msg string, args ...interface{}) {
    99  	// Build the passed error message
   100  	errMsg := fmt.Sprintf(msg, args...)
   101  
   102  	tagPrinted := false
   103  
   104  	// Print the error message: the following code takes care
   105  	// of splitting error text and always pretty printing the
   106  	// red banner along with the error message. Since the error
   107  	// message itself contains some colored text, we needed
   108  	// to use some ANSI control escapes to cursor color state
   109  	// and freely move in the screen.
   110  	for _, line := range strings.Split(errMsg, "\n") {
   111  		if len(line) == 0 {
   112  			// No more text to print, just quit.
   113  			break
   114  		}
   115  
   116  		for {
   117  			// Save the attributes of the current cursor helps
   118  			// us save the text color of the passed error message
   119  			ansiSaveAttributes()
   120  			// Print banner with or without the log tag
   121  			if !tagPrinted {
   122  				c.Print(logBanner)
   123  				tagPrinted = true
   124  			} else {
   125  				c.Print(emptyBanner)
   126  			}
   127  			// Restore the text color of the error message
   128  			ansiRestoreAttributes()
   129  			ansiMoveRight(bannerWidth)
   130  			// Continue  error message printing
   131  			c.Println(line)
   132  			break
   133  		}
   134  	}
   135  
   136  	// Exit because this is a fatal error message
   137  	os.Exit(1)
   138  }
   139  
   140  type infoMsg struct{}
   141  
   142  var info infoMsg
   143  
   144  func (i infoMsg) json(msg string, args ...interface{}) {
   145  	logJSON, err := json.Marshal(&log.Entry{
   146  		Level:   InformationLvl.String(),
   147  		Message: fmt.Sprintf(msg, args...),
   148  		Time:    time.Now().UTC().Format(time.RFC3339Nano),
   149  	})
   150  	if err != nil {
   151  		panic(err)
   152  	}
   153  	fmt.Println(string(logJSON))
   154  }
   155  
   156  func (i infoMsg) quiet(msg string, args ...interface{}) {
   157  	i.pretty(msg, args...)
   158  }
   159  
   160  func (i infoMsg) pretty(msg string, args ...interface{}) {
   161  	c.Printf(msg, args...)
   162  }
   163  
   164  // Info :
   165  func Info(msg string, data ...interface{}) {
   166  	consoleLog(info, msg+"\n", data...)
   167  }
   168  
   169  var startupMessage startUpMsg
   170  
   171  type startUpMsg struct {
   172  }
   173  
   174  func (s startUpMsg) json(msg string, args ...interface{}) {
   175  }
   176  
   177  func (s startUpMsg) quiet(msg string, args ...interface{}) {
   178  }
   179  
   180  func (s startUpMsg) pretty(msg string, args ...interface{}) {
   181  	c.Printf(msg, args...)
   182  }
   183  
   184  // StartupMessage :
   185  func StartupMessage(msg string, data ...interface{}) {
   186  	consoleLog(startupMessage, msg+"\n", data...)
   187  }