github.com/goravel/framework@v1.13.9/log/formatter/general.go (about)

     1  package formatter
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/sirupsen/logrus"
    10  	"github.com/spf13/cast"
    11  
    12  	"github.com/goravel/framework/contracts/config"
    13  	"github.com/goravel/framework/support/json"
    14  )
    15  
    16  type General struct {
    17  	config config.Config
    18  }
    19  
    20  func NewGeneral(config config.Config) *General {
    21  	return &General{
    22  		config: config,
    23  	}
    24  }
    25  
    26  func (general *General) Format(entry *logrus.Entry) ([]byte, error) {
    27  	var b *bytes.Buffer
    28  	if entry.Buffer != nil {
    29  		b = entry.Buffer
    30  	} else {
    31  		b = &bytes.Buffer{}
    32  	}
    33  
    34  	cstSh, err := time.LoadLocation(general.config.GetString("app.timezone"))
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	timestamp := entry.Time.In(cstSh).Format("2006-01-02 15:04:05")
    40  	b.WriteString(fmt.Sprintf("[%s] %s.%s: %s\n", timestamp, general.config.GetString("app.env"), entry.Level, entry.Message))
    41  	data := entry.Data
    42  	if len(data) > 0 {
    43  		formattedData, err := formatData(data)
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  		b.WriteString(formattedData)
    48  	}
    49  
    50  	return b.Bytes(), nil
    51  }
    52  
    53  func formatData(data logrus.Fields) (string, error) {
    54  	var builder strings.Builder
    55  
    56  	if len(data) > 0 {
    57  		removedData := deleteKey(data, "root")
    58  		if len(removedData) > 0 {
    59  			removedDataBytes, err := json.Marshal(removedData)
    60  			if err != nil {
    61  				return "", err
    62  			}
    63  
    64  			builder.WriteString(fmt.Sprintf("fields: %s\n", string(removedDataBytes)))
    65  		}
    66  
    67  		root, err := cast.ToStringMapE(data["root"])
    68  		if err != nil {
    69  			return "", err
    70  		}
    71  
    72  		for _, key := range []string{"code", "context", "domain", "hint", "owner", "request", "response", "tags", "user"} {
    73  			if value, exists := root[key]; exists && value != nil {
    74  				v, err := json.Marshal(value)
    75  				if err != nil {
    76  					return "", err
    77  				}
    78  
    79  				builder.WriteString(fmt.Sprintf("%s: %v\n", key, string(v)))
    80  			}
    81  		}
    82  
    83  		if stackTraceValue, exists := root["stacktrace"]; exists && stackTraceValue != nil {
    84  			traces, err := formatStackTraces(stackTraceValue)
    85  			if err != nil {
    86  				return "", err
    87  			}
    88  
    89  			builder.WriteString(traces)
    90  		}
    91  	}
    92  
    93  	return builder.String(), nil
    94  }
    95  
    96  func deleteKey(data logrus.Fields, keyToDelete string) logrus.Fields {
    97  	dataCopy := make(logrus.Fields)
    98  	for key, value := range data {
    99  		if key != keyToDelete {
   100  			dataCopy[key] = value
   101  		}
   102  	}
   103  
   104  	return dataCopy
   105  }
   106  
   107  type StackTrace struct {
   108  	Root struct {
   109  		Message string   `json:"message"`
   110  		Stack   []string `json:"stack"`
   111  	} `json:"root"`
   112  	Wrap []struct {
   113  		Message string `json:"message"`
   114  		Stack   string `json:"stack"`
   115  	} `json:"wrap"`
   116  }
   117  
   118  func formatStackTraces(stackTraces any) (string, error) {
   119  	var formattedTraces strings.Builder
   120  	data, err := json.Marshal(stackTraces)
   121  
   122  	if err != nil {
   123  		return "", err
   124  	}
   125  	var traces StackTrace
   126  	err = json.Unmarshal(data, &traces)
   127  	if err != nil {
   128  		return "", err
   129  	}
   130  	formattedTraces.WriteString("trace:\n")
   131  	root := traces.Root
   132  	if len(root.Stack) > 0 {
   133  		for _, stackStr := range root.Stack {
   134  			formattedTraces.WriteString(fmt.Sprintf("\t%s\n", stackStr))
   135  		}
   136  	}
   137  
   138  	return formattedTraces.String(), nil
   139  }