Skip to content

Commit

Permalink
formatting for directory logs (resolves #202)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nauman-S committed Dec 27, 2024
1 parent 77cbf9e commit 3fcdd13
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 94 deletions.
99 changes: 5 additions & 94 deletions turbo/logging/logging.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
package logging

import (
"encoding/json"
"flag"
"fmt"
"github.com/ledgerwatch/erigon-lib/common/metrics"
"github.com/ledgerwatch/log/v3"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
"gopkg.in/natefinch/lumberjack.v2"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"

"github.com/ledgerwatch/erigon-lib/common/metrics"
)

const timeFormat = "2006-01-02T15:04:05-0700"
Expand Down Expand Up @@ -204,8 +198,10 @@ func initSeparatedLogging(

var consoleHandler log.Handler

okLogFormatFunc := log.FormatFunc(OkLogV1Format)

if consoleJson {
consoleHandler = log.LvlFilterHandler(consoleLevel, log.StreamHandler(os.Stderr, JsonFormatEx(true, true)))
consoleHandler = log.LvlFilterHandler(consoleLevel, log.StreamHandler(os.Stderr, okLogFormatFunc))
} else {
consoleHandler = log.LvlFilterHandler(consoleLevel, log.StderrHandler)
}
Expand All @@ -223,7 +219,7 @@ func initSeparatedLogging(
}
dirFormat := log.TerminalFormatNoColor()
if dirJson {
dirFormat = JsonFormatEx(true, true)
dirFormat = okLogFormatFunc
}

lumberjack := &lumberjack.Logger{
Expand All @@ -239,91 +235,6 @@ func initSeparatedLogging(
logger.Info("logging to file system", "log dir", dirPath, "file prefix", filePrefix, "log level", dirLevel, "json", dirJson)
}

func JsonFormatEx(pretty, lineSeparated bool) log.Format {
jsonMarshal := json.Marshal
if pretty {
jsonMarshal = func(v interface{}) ([]byte, error) {
return json.MarshalIndent(v, "", " ")
}
}

return log.FormatFunc(func(r *log.Record) []byte {

r.KeyNames = log.RecordKeyNames{
Time: "time",
Msg: "content",
Lvl: "level",
}

props := make(map[string]interface{})

props[r.KeyNames.Time] = r.Time
props[r.KeyNames.Lvl] = strings.ToUpper(r.Lvl.String())
props[r.KeyNames.Msg] = r.Msg

for i := 0; i < len(r.Ctx); i += 2 {
k, ok := r.Ctx[i].(string)
if !ok {
props[errorKey] = fmt.Sprintf("%+v is not a string key", r.Ctx[i])
}
props[k] = formatJSONValue(r.Ctx[i+1])
}

b, err := jsonMarshal(props)
if err != nil {
b, _ = jsonMarshal(map[string]string{
errorKey: err.Error(),
})
return b
}

if lineSeparated {
b = append(b, '\n')
}

return b
})
}

func formatJSONValue(value interface{}) interface{} {
value = formatShared(value)

switch value.(type) {
case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string:
return value
case interface{}, map[string]interface{}, []interface{}:
return value
default:
return fmt.Sprintf("%+v", value)
}
}

func formatShared(value interface{}) (result interface{}) {
defer func() {
if err := recover(); err != nil {
if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr && v.IsNil() {
result = "nil"
} else {
panic(err)
}
}
}()

switch v := value.(type) {
case time.Time:
return v.Format(timeFormat)

case error:
return v.Error()

case fmt.Stringer:
return v.String()

default:
return v
}
}

func tryGetLogLevel(s string) (log.Lvl, error) {
lvl, err := log.LvlFromString(s)
if err != nil {
Expand Down
88 changes: 88 additions & 0 deletions turbo/logging/oklogformat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package logging

import (
"encoding/json"
"fmt"
"github.com/ledgerwatch/log/v3"
"path/filepath"
"reflect"
"strings"
"time"
)

func OkLogV1Format(r *log.Record) []byte {
r.KeyNames = log.RecordKeyNames{
Time: "t",
Msg: "content",
Lvl: "level",
}
props := make(map[string]interface{})

callFrame := r.Call.Frame()

props["time"] = r.Time.UnixMilli()
props[r.KeyNames.Time] = r.Time
props[r.KeyNames.Lvl] = strings.ToUpper(r.Lvl.String())
props[r.KeyNames.Msg] = r.Msg
props["line_num"] = callFrame.Line
props["class_name"] = filepath.Base(callFrame.File)

for i := 0; i < len(r.Ctx); i += 2 {
k, ok := r.Ctx[i].(string)
if !ok {
props[errorKey] = fmt.Sprintf("%+v is not a string key", r.Ctx[i])
}
props[k] = formatJSONValue(r.Ctx[i+1])
}

b, err := json.MarshalIndent(props, "", " ")
if err != nil {
b, _ = json.MarshalIndent(map[string]string{
errorKey: err.Error(),
}, "", " ")
return b
}

b = append(b, '\n')

return b
}

func formatJSONValue(value interface{}) interface{} {
value = formatShared(value)

switch value.(type) {
case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string:
return value
case interface{}, map[string]interface{}, []interface{}:
return value
default:
return fmt.Sprintf("%+v", value)
}
}

func formatShared(value interface{}) (result interface{}) {
defer func() {
if err := recover(); err != nil {
if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr && v.IsNil() {
result = "nil"
} else {
panic(err)
}
}
}()

switch v := value.(type) {
case time.Time:
return v.Format(timeFormat)

case error:
return v.Error()

case fmt.Stringer:
return v.String()

default:
return v
}
}

0 comments on commit 3fcdd13

Please sign in to comment.