github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/logger/target/console/console.go (about)

     1  // Copyright (c) 2015-2021 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package console
    19  
    20  import (
    21  	"encoding/json"
    22  	"fmt"
    23  	"strconv"
    24  	"strings"
    25  
    26  	"github.com/minio/minio/internal/color"
    27  	"github.com/minio/minio/internal/logger"
    28  	"github.com/minio/pkg/v2/console"
    29  	"github.com/minio/pkg/v2/logger/message/log"
    30  )
    31  
    32  // Target implements loggerTarget to send log
    33  // in plain or json format to the standard output.
    34  type Target struct{}
    35  
    36  // Validate - validate if the tty can be written to
    37  func (c *Target) Validate() error {
    38  	return nil
    39  }
    40  
    41  // Endpoint returns the backend endpoint
    42  func (c *Target) Endpoint() string {
    43  	return ""
    44  }
    45  
    46  func (c *Target) String() string {
    47  	return "console"
    48  }
    49  
    50  // Send log message 'e' to console
    51  func (c *Target) Send(e interface{}) error {
    52  	entry, ok := e.(log.Entry)
    53  	if !ok {
    54  		return fmt.Errorf("Uexpected log entry structure %#v", e)
    55  	}
    56  	if logger.IsJSON() {
    57  		logJSON, err := json.Marshal(&entry)
    58  		if err != nil {
    59  			return err
    60  		}
    61  		fmt.Println(string(logJSON))
    62  		return nil
    63  	}
    64  
    65  	if entry.Level == logger.EventKind {
    66  		fmt.Println(entry.Message)
    67  		return nil
    68  	}
    69  
    70  	traceLength := len(entry.Trace.Source)
    71  	trace := make([]string, traceLength)
    72  
    73  	// Add a sequence number and formatting for each stack trace
    74  	// No formatting is required for the first entry
    75  	for i, element := range entry.Trace.Source {
    76  		trace[i] = fmt.Sprintf("%8v: %s", traceLength-i, element)
    77  	}
    78  
    79  	tagString := ""
    80  	for key, value := range entry.Trace.Variables {
    81  		if value != "" {
    82  			if tagString != "" {
    83  				tagString += ", "
    84  			}
    85  			tagString += fmt.Sprintf("%s=%#v", key, value)
    86  		}
    87  	}
    88  
    89  	var apiString string
    90  	if entry.API != nil {
    91  		apiString = "API: " + entry.API.Name + "("
    92  		if entry.API.Args != nil {
    93  			if entry.API.Args.Bucket != "" {
    94  				apiString = apiString + "bucket=" + entry.API.Args.Bucket
    95  			}
    96  			if entry.API.Args.Object != "" {
    97  				apiString = apiString + ", object=" + entry.API.Args.Object
    98  			}
    99  			if entry.API.Args.VersionID != "" {
   100  				apiString = apiString + ", versionId=" + entry.API.Args.VersionID
   101  			}
   102  			if len(entry.API.Args.Objects) > 0 {
   103  				apiString = apiString + ", multiObject=true, numberOfObjects=" + strconv.Itoa(len(entry.API.Args.Objects))
   104  			}
   105  		}
   106  		apiString += ")"
   107  	} else {
   108  		apiString = "INTERNAL"
   109  	}
   110  	timeString := "Time: " + entry.Time.Format(logger.TimeFormat)
   111  
   112  	var deploymentID string
   113  	if entry.DeploymentID != "" {
   114  		deploymentID = "\nDeploymentID: " + entry.DeploymentID
   115  	}
   116  
   117  	var requestID string
   118  	if entry.RequestID != "" {
   119  		requestID = "\nRequestID: " + entry.RequestID
   120  	}
   121  
   122  	var remoteHost string
   123  	if entry.RemoteHost != "" {
   124  		remoteHost = "\nRemoteHost: " + entry.RemoteHost
   125  	}
   126  
   127  	var host string
   128  	if entry.Host != "" {
   129  		host = "\nHost: " + entry.Host
   130  	}
   131  
   132  	var userAgent string
   133  	if entry.UserAgent != "" {
   134  		userAgent = "\nUserAgent: " + entry.UserAgent
   135  	}
   136  
   137  	if len(entry.Trace.Variables) > 0 {
   138  		tagString = "\n       " + tagString
   139  	}
   140  
   141  	msg := color.RedBold(entry.Trace.Message)
   142  	output := fmt.Sprintf("\n%s\n%s%s%s%s%s%s\nError: %s%s\n%s",
   143  		apiString, timeString, deploymentID, requestID, remoteHost, host, userAgent,
   144  		msg, tagString, strings.Join(trace, "\n"))
   145  
   146  	console.Println(output)
   147  	return nil
   148  }
   149  
   150  // New initializes a new logger target
   151  // which prints log directly in the standard
   152  // output.
   153  func New() *Target {
   154  	return &Target{}
   155  }