Skip to content

Commit

Permalink
Merge pull request #8 from Roshick/handleroptions
Browse files Browse the repository at this point in the history
Adjust handleroptions.Config
  • Loading branch information
Roshick authored Dec 13, 2023
2 parents ed95544 + 9251b68 commit 677a1c2
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 58 deletions.
69 changes: 33 additions & 36 deletions pkg/handleroptions/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package handleroptions

import (
"encoding/json"
"fmt"
"log/slog"
"time"

Expand All @@ -16,83 +15,81 @@ const (
DefaultKeyLogAttributeKeyMappings = "LOG_ATTRIBUTE_KEY_MAPPINGS"
)

type TimestampTransformer func(time.Time) time.Time

type DefaultConfigImpl struct {
VLogLevel slog.Level
VLogAttributeKeyMappings map[string]string
VTimestampTransformer func(time.Time) time.Time
vLogLevel slog.Level
vLogAttributeKeyMappings map[string]string
vTimestampTransformer TimestampTransformer
}

func NewDefaultConfig() *DefaultConfigImpl {
return &DefaultConfigImpl{
vTimestampTransformer: func(timestamp time.Time) time.Time {
return timestamp.UTC()
},
}
}

func (c *DefaultConfigImpl) SetTimestampTransformer(transformer TimestampTransformer) {
c.vTimestampTransformer = transformer
}

func (c *DefaultConfigImpl) HandlerOptions() *slog.HandlerOptions {
replaceAttr := func(_ []string, attr slog.Attr) slog.Attr {
if attr.Key == slog.TimeKey {
attr.Value = slog.TimeValue(c.VTimestampTransformer(attr.Value.Time()))
attr.Value = slog.TimeValue(c.vTimestampTransformer(attr.Value.Time()))
}
if attr.Key == slog.LevelKey {
logLevel := attr.Value.Any().(slog.Level)
attr.Value = slog.StringValue(level.LevelToString(logLevel))

}
if mappedKey, ok := c.VLogAttributeKeyMappings[attr.Key]; ok {
if mappedKey, ok := c.vLogAttributeKeyMappings[attr.Key]; ok {
attr.Key = mappedKey
}
return attr
}

return &slog.HandlerOptions{
ReplaceAttr: replaceAttr,
Level: c.VLogLevel,
Level: c.vLogLevel,
}
}

func DefaultConfigItems() []auconfigapi.ConfigItem {
func (c *DefaultConfigImpl) ConfigItems() []auconfigapi.ConfigItem {
return []auconfigapi.ConfigItem{
{
Key: DefaultKeyLogLevel,
EnvName: DefaultKeyLogLevel,
Default: "INFO",
Description: "Minimum level of all logs.",
Validate: validateIsLogLevel,
Validate: auconfigapi.ConfigNeedsNoValidation,
}, {
Key: DefaultKeyLogAttributeKeyMappings,
EnvName: DefaultKeyLogAttributeKeyMappings,
Default: "{}",
Description: "Mappings for attribute keys of all logs. " +
"Example: The entry [error: error.message] maps every attribute with key \"error\" to use the key \"error.message\" instead.",
Validate: validateIsLogAttributeKeyMappings,
Validate: auconfigapi.ConfigNeedsNoValidation,
},
}
}

type ValuesProvider interface {
ObtainValues(configItems []auconfigapi.ConfigItem) (map[string]string, error)
}

func ObtainDefaultConfig(provider ValuesProvider) (*DefaultConfigImpl, error) {
values, err := provider.ObtainValues(DefaultConfigItems())
if err != nil {
return nil, fmt.Errorf("failed to obtain configuration values: %s", err.Error())
func (c *DefaultConfigImpl) ObtainValues(getter func(string) string) error {
if vLogLevel, err := level.ParseLogLevel(getter(DefaultKeyLogLevel)); err != nil {
return err
} else {
c.vLogLevel = vLogLevel
}

vLogLevel, _ := level.ParseLogLevel(values[DefaultKeyLogLevel])
vLogAttributeKeyMappings, _ := parseLogAttributeKeyMappings(values[DefaultKeyLogAttributeKeyMappings])
vTimestampTransformer := func(timestamp time.Time) time.Time {
return timestamp.UTC()
if vLogAttributeKeyMappings, err := parseLogAttributeKeyMappings(getter(DefaultKeyLogAttributeKeyMappings)); err != nil {
return err
} else {
c.vLogAttributeKeyMappings = vLogAttributeKeyMappings
}
return &DefaultConfigImpl{
VLogLevel: vLogLevel,
VLogAttributeKeyMappings: vLogAttributeKeyMappings,
VTimestampTransformer: vTimestampTransformer,
}, nil
}

func validateIsLogLevel(value string) error {
_, err := level.ParseLogLevel(value)
return err
}

func validateIsLogAttributeKeyMappings(value string) error {
_, err := parseLogAttributeKeyMappings(value)
return err
return nil
}

func parseLogAttributeKeyMappings(value string) (map[string]string, error) {
Expand Down
40 changes: 18 additions & 22 deletions pkg/handleroptions/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,50 @@ import (

"github.com/Roshick/go-autumn-slog/pkg/handleroptions"
"github.com/Roshick/go-autumn-slog/pkg/level"
auconfigapi "github.com/StephanHCB/go-autumn-config-api"
"github.com/stretchr/testify/assert"
)

type testProvider struct{}

func (p *testProvider) ObtainValues(_ []auconfigapi.ConfigItem) (map[string]string, error) {
return map[string]string{
func getter(key string) string {
values := map[string]string{
handleroptions.DefaultKeyLogLevel: "FATAL",
handleroptions.DefaultKeyLogAttributeKeyMappings: `
{
"time": "@timestamp"
}
`,
}, nil
}

func newTestHandler() handleroptions.ValuesProvider {
return &testProvider{}
}
return values[key]
}

func TestObtainDefaultConfig_TextHandler(t *testing.T) {
provider := newTestHandler()
configuration, err := handleroptions.ObtainDefaultConfig(provider)
config := handleroptions.NewDefaultConfig()

err := config.ObtainValues(getter)
assert.NoError(t, err)
assert.Equal(t, level.Fatal, configuration.VLogLevel)
assert.Equal(t, level.Fatal, config.HandlerOptions().Level.Level())

configuration.VTimestampTransformer = func(timestamp time.Time) time.Time {
config.SetTimestampTransformer(func(timestamp time.Time) time.Time {
return time.Time{}
}
})
result := bytes.NewBuffer(nil)
handler := slog.NewTextHandler(result, configuration.HandlerOptions())
handler := slog.NewTextHandler(result, config.HandlerOptions())
logger := slog.New(handler)
logger.Log(nil, level.Panic, "this is a test")
assert.Equal(t, "@timestamp=0001-01-01T00:00:00.000Z level=PANIC msg=\"this is a test\"\n", result.String())
}

func TestObtainDefaultConfig_JSONHandler(t *testing.T) {
provider := newTestHandler()
configuration, err := handleroptions.ObtainDefaultConfig(provider)
config := handleroptions.NewDefaultConfig()

err := config.ObtainValues(getter)
assert.NoError(t, err)
assert.Equal(t, level.Fatal, configuration.VLogLevel)
assert.Equal(t, level.Fatal, config.HandlerOptions().Level.Level())

configuration.VTimestampTransformer = func(timestamp time.Time) time.Time {
config.SetTimestampTransformer(func(timestamp time.Time) time.Time {
return time.Time{}
}
})
result := bytes.NewBuffer(nil)
handler := slog.NewJSONHandler(result, configuration.HandlerOptions())
handler := slog.NewJSONHandler(result, config.HandlerOptions())
logger := slog.New(handler)
logger.Log(nil, level.Panic, "this is a test")
assert.Equal(t, "{\"@timestamp\":\"0001-01-01T00:00:00Z\",\"level\":\"PANIC\",\"msg\":\"this is a test\"}\n", result.String())
Expand Down

0 comments on commit 677a1c2

Please sign in to comment.