Skip to content

Commit

Permalink
optimize output
Browse files Browse the repository at this point in the history
Signed-off-by: Pavel Okhlopkov <[email protected]>
  • Loading branch information
Pavel Okhlopkov committed Oct 29, 2024
1 parent 8ef9a52 commit 7858d17
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 38 deletions.
2 changes: 1 addition & 1 deletion pkg/unilogger/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (h *SlogHandler) Handle(ctx context.Context, r slog.Record) error {
return err
}

logOutput.Fields = b
logOutput.FieldsJSON = b[1 : len(b)-1]
}

buf := bytes.NewBuffer([]byte{})
Expand Down
149 changes: 112 additions & 37 deletions pkg/unilogger/output.go
Original file line number Diff line number Diff line change
@@ -1,64 +1,139 @@
package unilogger

import (
"bytes"
"encoding/json"
)

type LogOutput struct {
Level string
Name string
Message string
Source string
Fields []byte
Stacktrace string
Time string
Level string `json:"level"`
Name string `json:"logger"`
Message string `json:"msg"`
Source string `json:"source"`
FieldsJSON []byte `json:"-"`
Stacktrace string `json:"stacktrace"`
Time string `json:"time"`
}

func (a *LogOutput) MarshalJSON() ([]byte, error) {
fields := [][]byte{
formJSONKeyValue("level", a.Level),
}
render := Render{}
render.buf = append(render.buf, '{')

render.JSONKeyValue("level", a.Level)

render.buf = append(render.buf, ',')

if a.Name != "" {
fields = append(fields, formJSONKeyValue("logger", a.Name))
render.JSONKeyValue("logger", a.Name)
render.buf = append(render.buf, ',')
}

fields = append(fields, formJSONKeyValue("msg", a.Message))
render.JSONKeyValue("msg", a.Message)
render.buf = append(render.buf, ',')

if a.Source != "" {
fields = append(fields, formJSONKeyValue("source", a.Source))
render.JSONKeyValue("source", a.Source)
render.buf = append(render.buf, ',')
}

if len(a.Fields) > 0 {
fields = append(fields, a.Fields[1:len(a.Fields)-1])
if len(a.FieldsJSON) > 0 {
render.buf = append(render.buf, a.FieldsJSON...)
render.buf = append(render.buf, ',')
}

if a.Stacktrace != "" {
fields = append(fields, formJSONKeyValue("stacktrace", a.Stacktrace))
render.JSONKeyValue("stacktrace", a.Stacktrace)
render.buf = append(render.buf, ',')
}

fields = append(fields, formJSONKeyValue("time", a.Time))
render.JSONKeyValue("time", a.Time)

b := []byte{}
b = append(b, '{')
b = append(b, bytes.Join(fields, []byte{','})...)
b = append(b, '}')
render.buf = append(render.buf, '}')

return b, nil
return render.buf, nil
}

func formJSONKeyValue(key, value string) []byte {
b := bytes.NewBuffer([]byte{})
type Render struct {
buf []byte
}

if len(key) == 0 && len(value) == 0 {
return nil
}
var escapes = [256]bool{
'"': true,
'<': true,
// do not escape ' character
// '\'': true,
'\\': true,
'\b': true,
'\f': true,
'\n': true,
'\r': true,
'\t': true,
}

_ = json.NewEncoder(b).Encode(map[string]string{
key: value,
})
func (r *Render) JSONKeyValue(key, value string) {
r.buf = append(r.buf, '"')
r.string(key)
r.buf = append(r.buf, '"', ':', '"')
r.string(value)
r.buf = append(r.buf, '"')
}

func (e *Render) string(s string) {
for _, c := range []byte(s) {
if escapes[c] {
e.escapes(s)
return
}
}
e.buf = append(e.buf, s...)
}

// remove {} and \n
return b.Bytes()[1 : b.Len()-2]
func (e *Render) escapes(s string) {
n := len(s)
j := 0
if n > 0 {
// Hint the compiler to remove bounds checks in the loop below.
_ = s[n-1]
}
for i := 0; i < n; i++ {
switch s[i] {
case '"':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', '"')
j = i + 1
case '\\':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', '\\')
j = i + 1
case '\n':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 'n')
j = i + 1
case '\r':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 'r')
j = i + 1
case '\t':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 't')
j = i + 1
case '\f':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 'u', '0', '0', '0', 'c')
j = i + 1
case '\b':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 'u', '0', '0', '0', '8')
j = i + 1
case '<':
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 'u', '0', '0', '3', 'c')
j = i + 1
// do not escape ' character
// case '\'':
// e.buf = append(e.buf, s[j:i]...)
// e.buf = append(e.buf, '\\', 'u', '0', '0', '2', '7')
// j = i + 1
case 0:
e.buf = append(e.buf, s[j:i]...)
e.buf = append(e.buf, '\\', 'u', '0', '0', '0', '0')
j = i + 1
}
}
e.buf = append(e.buf, s[j:]...)
}

0 comments on commit 7858d17

Please sign in to comment.