-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathextractor_lua.go
95 lines (85 loc) · 2.07 KB
/
extractor_lua.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package logpeck
import (
"encoding/json"
"errors"
log "github.com/Sirupsen/logrus"
lua "github.com/yuin/gopher-lua"
luajson "layeh.com/gopher-json"
)
// LuaExtractorConfig .
type LuaExtractorConfig struct {
LuaString string
Fields []PeckField
}
// LuaExtractor .
type LuaExtractor struct {
state *lua.LState
fields map[string]bool
}
var luaExtractorFuncName = "extract"
// NewLuaExtractorConfig .
func NewLuaExtractorConfig(configStr []byte) (LuaExtractorConfig, error) {
c := LuaExtractorConfig{}
err := json.Unmarshal(configStr, &c)
if err != nil {
return c, err
}
return c, nil
}
// NewLuaExtractor .
func NewLuaExtractor(config interface{}) (LuaExtractor, error) {
c, ok := config.(LuaExtractorConfig)
if !ok {
return LuaExtractor{}, errors.New("LuaExtractor config error")
}
l := LuaExtractor{
state: lua.NewState(),
fields: make(map[string]bool),
}
c.LuaString = "json = require(\"luajson.json\") " + c.LuaString
l.state.PreloadModule("luajson.json", luajson.Loader)
if err := l.state.DoString(c.LuaString); err != nil {
return l, err
}
for _, f := range c.Fields {
l.fields[f.Name] = true
}
log.Infof("[LuoExtractor] Init extractor finished %#v", l)
return l, nil
}
// Extract .
func (le LuaExtractor) Extract(content string) (map[string]interface{}, error) {
param := lua.P{
Fn: le.state.GetGlobal(luaExtractorFuncName),
NRet: 1,
Protect: true,
}
if err := le.state.CallByParam(param, lua.LString(content)); err != nil {
return nil, err
}
lRet := le.state.Get(-1)
lT, ok := lRet.(*lua.LTable)
if !ok {
return nil, errors.New("lua return type error " + lRet.String())
}
le.state.Pop(1)
log.Debugf("[LuaExtractor] %s %#v", content, lT)
ret := make(map[string]interface{})
enable := true
key := ""
lT.ForEach(func(k, v lua.LValue) {
if _, ok := le.fields[k.String()]; !ok {
enable = false
key = k.String()
}
ret[k.String()] = v.String()
})
if !enable {
return map[string]interface{}{}, errors.New(key + " is not in Fields")
}
return ret, nil
}
// Close .
func (le LuaExtractor) Close() {
le.state.Close()
}