github.com/minio/console@v1.4.1/pkg/logger/console.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package logger
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"os"
    23  	"strings"
    24  	"time"
    25  
    26  	"github.com/minio/console/pkg/logger/color"
    27  	"github.com/minio/console/pkg/logger/message/log"
    28  	c "github.com/minio/pkg/v3/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+"\n", args...)
    46  	default:
    47  		console.pretty(msg+"\n", args...)
    48  	}
    49  }
    50  
    51  // Fatal prints only fatal errors 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  func (f fatalMsg) json(msg string, args ...interface{}) {
    72  	var message string
    73  	if msg != "" {
    74  		message = fmt.Sprintf(msg, args...)
    75  	} else {
    76  		message = fmt.Sprint(args...)
    77  	}
    78  	logJSON, err := json.Marshal(&log.Entry{
    79  		Level:   FatalLvl.String(),
    80  		Message: message,
    81  		Time:    time.Now().UTC(),
    82  		Trace:   &log.Trace{Message: message, Source: []string{getSource(6)}},
    83  	})
    84  	if err != nil {
    85  		panic(err)
    86  	}
    87  	fmt.Println(string(logJSON))
    88  
    89  	os.Exit(1)
    90  }
    91  
    92  func (f fatalMsg) quiet(msg string, args ...interface{}) {
    93  	f.pretty(msg, args...)
    94  }
    95  
    96  var (
    97  	logTag      = "ERROR"
    98  	logBanner   = color.BgRed(color.FgWhite(color.Bold(logTag))) + " "
    99  	emptyBanner = color.BgRed(strings.Repeat(" ", len(logTag))) + " "
   100  	bannerWidth = len(logTag) + 1
   101  )
   102  
   103  func (f fatalMsg) pretty(msg string, args ...interface{}) {
   104  	// Build the passed errors message
   105  	errMsg := fmt.Sprintf(msg, args...)
   106  
   107  	tagPrinted := false
   108  
   109  	// Print the errors message: the following code takes care
   110  	// of splitting errors text and always pretty printing the
   111  	// red banner along with the errors message. Since the errors
   112  	// message itself contains some colored text, we needed
   113  	// to use some ANSI control escapes to cursor color state
   114  	// and freely move in the screen.
   115  	for _, line := range strings.Split(errMsg, "\n") {
   116  		if len(line) == 0 {
   117  			// No more text to print, just quit.
   118  			break
   119  		}
   120  
   121  		for {
   122  			// Save the attributes of the current cursor helps
   123  			// us save the text color of the passed errors message
   124  			ansiSaveAttributes()
   125  			// Print banner with or without the log tag
   126  			if !tagPrinted {
   127  				c.Print(logBanner)
   128  				tagPrinted = true
   129  			} else {
   130  				c.Print(emptyBanner)
   131  			}
   132  			// Restore the text color of the errors message
   133  			ansiRestoreAttributes()
   134  			ansiMoveRight(bannerWidth)
   135  			// Continue  errors message printing
   136  			c.Println(line)
   137  			break
   138  		}
   139  	}
   140  
   141  	// Exit because this is a fatal errors message
   142  	os.Exit(1)
   143  }
   144  
   145  type infoMsg struct{}
   146  
   147  var info infoMsg
   148  
   149  func (i infoMsg) json(msg string, args ...interface{}) {
   150  	var message string
   151  	if msg != "" {
   152  		message = fmt.Sprintf(msg, args...)
   153  	} else {
   154  		message = fmt.Sprint(args...)
   155  	}
   156  	logJSON, err := json.Marshal(&log.Entry{
   157  		Level:   InformationLvl.String(),
   158  		Message: message,
   159  		Time:    time.Now().UTC(),
   160  	})
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  	fmt.Println(string(logJSON))
   165  }
   166  
   167  func (i infoMsg) quiet(_ string, _ ...interface{}) {
   168  }
   169  
   170  func (i infoMsg) pretty(msg string, args ...interface{}) {
   171  	if msg == "" {
   172  		c.Println(args...)
   173  	}
   174  	c.Printf(msg, args...)
   175  }
   176  
   177  type errorMsg struct{}
   178  
   179  var errorm errorMsg
   180  
   181  func (i errorMsg) json(msg string, args ...interface{}) {
   182  	var message string
   183  	if msg != "" {
   184  		message = fmt.Sprintf(msg, args...)
   185  	} else {
   186  		message = fmt.Sprint(args...)
   187  	}
   188  	logJSON, err := json.Marshal(&log.Entry{
   189  		Level:   ErrorLvl.String(),
   190  		Message: message,
   191  		Time:    time.Now().UTC(),
   192  		Trace:   &log.Trace{Message: message, Source: []string{getSource(6)}},
   193  	})
   194  	if err != nil {
   195  		panic(err)
   196  	}
   197  	fmt.Println(string(logJSON))
   198  }
   199  
   200  func (i errorMsg) quiet(msg string, args ...interface{}) {
   201  	i.pretty(msg, args...)
   202  }
   203  
   204  func (i errorMsg) pretty(msg string, args ...interface{}) {
   205  	if msg == "" {
   206  		c.Println(args...)
   207  	}
   208  	c.Printf(msg, args...)
   209  	c.Printf("\n")
   210  }
   211  
   212  // Error :
   213  func Error(msg string, data ...interface{}) {
   214  	consoleLog(errorm, msg, data...)
   215  }
   216  
   217  // Info :
   218  func Info(msg string, data ...interface{}) {
   219  	consoleLog(info, msg, data...)
   220  }