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 }