Skip to content

Commit

Permalink
expermient(logs) Add support for the Loggable interface
Browse files Browse the repository at this point in the history
  • Loading branch information
john-scalingo committed Dec 30, 2024
1 parent bbb7ca2 commit de0e638
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
18 changes: 16 additions & 2 deletions logger/loggable.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ import (
"github.com/sirupsen/logrus"
)

type Loggable interface {
ToLogrusFields() logrus.Fields
}

// FieldsFor extracts loggable fields from a struct based on the "log" tag.
// It returns a logrus.Fields map where the keys are the tag values prefixed
// with the provided prefix, and the values are the corresponding field values.
//
// If the struct implements the Loggable interface. The `log` tags are ignored
// and the ToLogrusFields method is used to extract the fields.
//
// If the struct has no fields with the "log" tag, it checks if the struct
// implements the fmt.Stringer interface. If it does, it adds a single field
// with the prefix as the key and the result of the String() method as the value.
Expand All @@ -25,10 +32,17 @@ import (
// Returns:
// - logrus.Fields: A map of loggable fields.
func FieldsFor(value interface{}, prefix string) logrus.Fields {
val := reflect.ValueOf(value)

fields := logrus.Fields{}

if loggableValue, ok := value.(Loggable); ok {
for k, v := range loggableValue.ToLogrusFields() {
fields[fmt.Sprintf("%s_%s", prefix, k)] = v
}
return fields
}

val := reflect.ValueOf(value)

for i := 0; i < val.NumField(); i++ {
name, found := val.Type().Field(i).Tag.Lookup("log")
if found {
Expand Down
29 changes: 29 additions & 0 deletions logger/loggable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ type StructWithTags struct {
Field3 string
}

type StructWithTagsAndLoggable struct {
Field1 string `log:"field1"`
Field2 string `log:"field2"`
Field3 string
}

func (s StructWithTagsAndLoggable) ToLogrusFields() logrus.Fields {
return logrus.Fields{
"another": "test",
}
}

type StructWithoutTagsButWithStringer struct {
Field1 string
Field2 string
Expand Down Expand Up @@ -46,6 +58,23 @@ func TestFieldsFor(t *testing.T) {
}, fields)
})

t.Run("when the struct has some tags and implements Loggable", func(t *testing.T) {
// Given a struct with tags and that implements Loggable
s := StructWithTagsAndLoggable{
Field1: "value1",
Field2: "value2",
Field3: "value3",
}

// When we try to add it to a logger
fields := FieldsFor(s, "prefix")

// Then it should be added as separate fields
assert.Equal(t, logrus.Fields{
"prefix_another": "test",
}, fields)
})

t.Run("when the struct has no tags but has a stringer", func(t *testing.T) {
// Given a struct without tags but with a stringer
s := StructWithoutTagsButWithStringer{
Expand Down

0 comments on commit de0e638

Please sign in to comment.