Skip to content
80 changes: 80 additions & 0 deletions mchlogcommon/mchlogcommon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package mchlogcommon

import (
"encoding/json"
"errors"
"fmt"
"reflect"

"github.com/rs/zerolog"
)

// GetJSONLogger retorna o evento de log correspondente
// pronto para ser persistido no arquivo.
func GetJSONLogger(logger *zerolog.Logger, content any) (*zerolog.Event, error) {
var err error
var event *zerolog.Event
var ok bool

v := reflect.ValueOf(content)
switch v.Kind() {
case reflect.Map:
var m map[string]any
if m, ok = content.(map[string]any); !ok {
m = make(map[string]any)
keys := v.MapKeys()
for _, k := range keys {
va := v.MapIndex(k)
switch va.Kind() {
case reflect.String:
m[k.String()] = va.String()
case reflect.Int, reflect.Int64, reflect.Int32:
m[k.String()] = va.Int()
case reflect.Float64, reflect.Float32:
m[k.String()] = va.Float()
}
}
}
event = logger.Log().Fields(m)

case reflect.Slice, reflect.Array:
var arrb []byte
if arrb, ok = content.([]byte); ok {
var m map[string]any
if err = json.Unmarshal(arrb, &m); err == nil {
event = logger.Log().Fields(m)
}
} else {
var arr []any
if arr, ok = content.([]any); !ok {
tam := v.Len()
for i := 0; i < tam; i++ {
va := v.Index(i)
switch va.Kind() {
case reflect.String:
arr = append(arr, va.String())
case reflect.Int, reflect.Int64, reflect.Int32:
arr = append(arr, va.Int())
case reflect.Float64, reflect.Float32:
arr = append(arr, va.Float())
}
}
}
event = logger.Log().Fields(arr)
Comment on lines +48 to +63
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current logic for handling reflect.Slice or reflect.Array types (when not []byte or []any interpreted as key-value pairs) can lead to incorrect JSON output. If content is a strongly typed slice (e.g., []int{1, 2, 3}), it is converted to []any{1, 2, 3}. Passing this to logger.Log().Fields(arr) will cause zerolog to misinterpret the array elements as alternating keys and values, which is likely not the intended behavior and can result in malformed log entries.

To ensure correct JSON formatting, consider marshaling such slices/arrays to JSON and then unmarshaling them into a map[string]any if they represent a JSON object, or logging them as a single array field if they represent a JSON array of primitives. If the content cannot be converted to a valid JSON object, it should be explicitly treated as an invalid type.

Suggested change
var arr []any
if arr, ok = content.([]any); !ok {
tam := v.Len()
for i := 0; i < tam; i++ {
va := v.Index(i)
switch va.Kind() {
case reflect.String:
arr = append(arr, va.String())
case reflect.Int, reflect.Int64, reflect.Int32:
arr = append(arr, va.Int())
case reflect.Float64, reflect.Float32:
arr = append(arr, va.Float())
}
}
}
event = logger.Log().Fields(arr)
var arr []any
if arr, ok = content.([]any); ok { // If content is already []any, assume it's key-value pairs
event = logger.Log().Fields(arr)
} else {
// For other slice/array types (e.g., []int, []string), try to marshal to JSON
// and then unmarshal to a map. If it's a simple array of primitives,
// unmarshaling to a map will fail, correctly triggering the error.
var tempBytes []byte
tempBytes, err = json.Marshal(content)
if err == nil {
var m map[string]any
if err = json.Unmarshal(tempBytes, &m); err == nil {
event = logger.Log().Fields(m)
}
}
}

}
case reflect.String:
s := content.(string)
var m map[string]any
if err = json.Unmarshal([]byte(s), &m); err == nil {
event = logger.Log().Fields(m)
}
default:
err = errors.New("")
Comment on lines +71 to +72
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The default error message errors.New("") is not descriptive and makes debugging difficult. It's important to provide clear and informative error messages to help identify the root cause of issues.

Please provide a more specific error message that indicates the type of content that was not handled.

Suggested change
default:
err = errors.New("")
default:
err = fmt.Errorf("unsupported reflect kind: %s", v.Kind().String())

}

if err != nil {
err = fmt.Errorf("tipo inválido do conteúdo do log: %v.\nEsperados map, json em formato de string ou []byte", v.Type())
}

return event, err
}
Loading