138 lines
3.0 KiB
Go
138 lines
3.0 KiB
Go
package pipelinex
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Entry struct {
|
|
Time time.Time
|
|
LevelName string
|
|
LoggerName string
|
|
Thread string
|
|
File string
|
|
Line int
|
|
Func string
|
|
Message string
|
|
Error string
|
|
Fields map[string]interface{}
|
|
}
|
|
|
|
type TextOptions struct {
|
|
IncludeTimestamp bool
|
|
IncludeLevel bool
|
|
IncludeSource bool
|
|
IncludeThread bool
|
|
IncludeLogger bool
|
|
}
|
|
|
|
func cloneFields(fields map[string]interface{}) map[string]interface{} {
|
|
if len(fields) == 0 {
|
|
return nil
|
|
}
|
|
cloned := make(map[string]interface{}, len(fields))
|
|
for key, value := range fields {
|
|
cloned[key] = value
|
|
}
|
|
return cloned
|
|
}
|
|
|
|
func renderFields(fields map[string]interface{}) string {
|
|
if len(fields) == 0 {
|
|
return ""
|
|
}
|
|
keys := make([]string, 0, len(fields))
|
|
for key := range fields {
|
|
keys = append(keys, key)
|
|
}
|
|
sort.Strings(keys)
|
|
pairs := make([]string, 0, len(keys))
|
|
for _, key := range keys {
|
|
pairs = append(pairs, fmt.Sprintf("%s=%v", key, fields[key]))
|
|
}
|
|
return strings.Join(pairs, " ")
|
|
}
|
|
|
|
func FormatText(entry Entry, options TextOptions) ([]byte, error) {
|
|
parts := make([]string, 0, 6)
|
|
if options.IncludeTimestamp {
|
|
if !entry.Time.IsZero() {
|
|
parts = append(parts, entry.Time.Format("2006-01-02 15:04:05.000000"))
|
|
}
|
|
}
|
|
if options.IncludeSource {
|
|
source := ""
|
|
if entry.File != "" {
|
|
source = fmt.Sprintf("%s:%d", entry.File, entry.Line)
|
|
}
|
|
if entry.Func != "" {
|
|
if source != "" {
|
|
source += " "
|
|
}
|
|
source += "<" + entry.Func + ">"
|
|
}
|
|
if source != "" {
|
|
parts = append(parts, source)
|
|
}
|
|
}
|
|
if options.IncludeThread && entry.Thread != "" {
|
|
parts = append(parts, "|"+entry.Thread+"|")
|
|
}
|
|
if options.IncludeLevel {
|
|
if entry.LevelName != "" {
|
|
parts = append(parts, "["+entry.LevelName+"]")
|
|
}
|
|
}
|
|
if options.IncludeLogger && entry.LoggerName != "" {
|
|
parts = append(parts, "logger="+entry.LoggerName)
|
|
}
|
|
|
|
messageParts := make([]string, 0, 3)
|
|
if entry.Message != "" {
|
|
messageParts = append(messageParts, entry.Message)
|
|
}
|
|
if entry.Error != "" {
|
|
messageParts = append(messageParts, "error="+entry.Error)
|
|
}
|
|
fieldText := renderFields(entry.Fields)
|
|
if fieldText != "" {
|
|
messageParts = append(messageParts, fieldText)
|
|
}
|
|
if len(messageParts) > 0 {
|
|
parts = append(parts, strings.Join(messageParts, " "))
|
|
}
|
|
return []byte(strings.Join(parts, " ")), nil
|
|
}
|
|
|
|
func FormatJSON(entry Entry, pretty bool) ([]byte, error) {
|
|
payload := map[string]interface{}{
|
|
"time": entry.Time.Format(time.RFC3339Nano),
|
|
"level": entry.LevelName,
|
|
"msg": entry.Message,
|
|
"logger": entry.LoggerName,
|
|
"thread": entry.Thread,
|
|
}
|
|
if entry.File != "" {
|
|
payload["file"] = entry.File
|
|
}
|
|
if entry.Line > 0 {
|
|
payload["line"] = entry.Line
|
|
}
|
|
if entry.Func != "" {
|
|
payload["func"] = entry.Func
|
|
}
|
|
if entry.Error != "" {
|
|
payload["error"] = entry.Error
|
|
}
|
|
if len(entry.Fields) > 0 {
|
|
payload["fields"] = cloneFields(entry.Fields)
|
|
}
|
|
if pretty {
|
|
return json.MarshalIndent(payload, "", " ")
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|