Skip to content

Commit

Permalink
Merge pull request #2085 from urso/enh/fmtstr-cfg
Browse files Browse the repository at this point in the history
EventFormatString unpack for use with configurations
  • Loading branch information
ruflin authored Jul 25, 2016
2 parents 805114f + 1d60a99 commit e579bf2
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 5 deletions.
52 changes: 47 additions & 5 deletions libbeat/common/fmtstr/formatevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ var (
errConvertString = errors.New("can not convert to string")
)

// MustCompileEvent copmiles an event format string into an runnable
// EventFormatString. Generates a panic if compilation fails.
func MustCompileEvent(in string) *EventFormatString {
fs, err := CompileEvent(in)
if err != nil {
panic(err)
}
return fs
}

// CompileEvent compiles an event format string into an runnable
// EventFormatString. Returns error if parsing or compilation fails.
func CompileEvent(in string) (*EventFormatString, error) {
Expand Down Expand Up @@ -95,6 +105,26 @@ func CompileEvent(in string) (*EventFormatString, error) {
return efs, nil
}

// Unpack tries to initialize the EventFormatString from provided value
// (which must be a string). Unpack method satisfies go-ucfg.Unpacker interface
// required by common.Config, in order to use EventFormatString with
// `common.(*Config).Unpack()`.
func (fs *EventFormatString) Unpack(v interface{}) error {
s, err := tryConvString(v)
if err != nil {
return err
}

tmp, err := CompileEvent(s)
if err != nil {
return err
}

// init fs from tmp
*fs = *tmp
return nil
}

// NumFields returns number of unique event fields used by the format string.
func (fs *EventFormatString) NumFields() int {
return len(fs.fields)
Expand Down Expand Up @@ -243,22 +273,35 @@ func parseEventPath(field string) (string, error) {

// TODO: move to libbeat/common?
func fieldString(event common.MapStr, field string) (string, error) {
type stringer interface {
String() string
}

v, err := event.GetValue(field)
if err != nil {
return "", err
}

s, err := tryConvString(v)
if err != nil {
logp.Warn("Can not convert key '%v' value to string", v)
}
return s, err
}

func tryConvString(v interface{}) (string, error) {
type stringer interface {
String() string
}

switch s := v.(type) {
case string:
return s, nil
case []byte:
return string(s), nil
case stringer:
return s.String(), nil
case bool:
if s {
return "true", nil
}
return "false", nil
case int8, int16, int32, int64, int:
i := reflect.ValueOf(s).Int()
return strconv.FormatInt(i, 10), nil
Expand All @@ -270,7 +313,6 @@ func fieldString(event common.MapStr, field string) (string, error) {
case float64:
return strconv.FormatFloat(s, 'g', -1, 64), nil
default:
logp.Warn("Can not convert key '%v' value to string", v)
return "", errConvertString
}
}
58 changes: 58 additions & 0 deletions libbeat/common/fmtstr/formatevents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,61 @@ func TestEventFormatStringErrors(t *testing.T) {
assert.Error(t, err)
}
}

func TestEventFormatStringFromConfig(t *testing.T) {
tests := []struct {
v interface{}
event common.MapStr
expected string
}{
{
"plain string",
common.MapStr{},
"plain string",
},
{
100,
common.MapStr{},
"100",
},
{
true,
common.MapStr{},
"true",
},
{
"%{[key]}",
common.MapStr{"key": "value"},
"value",
},
}

for i, test := range tests {
t.Logf("run (%v): %v -> %v", i, test.v, test.expected)

config, err := common.NewConfigFrom(common.MapStr{
"test": test.v,
})
if err != nil {
t.Error(err)
continue
}

testConfig := struct {
Test *EventFormatString `config:"test"`
}{}
err = config.Unpack(&testConfig)
if err != nil {
t.Error(err)
continue
}

actual, err := testConfig.Test.Run(test.event)
if err != nil {
t.Error(err)
continue
}

assert.Equal(t, test.expected, actual)
}
}

0 comments on commit e579bf2

Please sign in to comment.