mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 09:37:02 +00:00
lua: Expose logger object (#407)
Allows Lua scripts to add entries to Inbuckets log Closes #327 Signed-off-by: James Hillyerd <james@hillyerd.com>
This commit is contained in:
3
go.mod
3
go.mod
@@ -4,6 +4,7 @@ go 1.20
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9
|
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9
|
||||||
|
github.com/cosmotek/loguago v1.0.0
|
||||||
github.com/google/subcommands v1.2.0
|
github.com/google/subcommands v1.2.0
|
||||||
github.com/gorilla/css v1.0.0
|
github.com/gorilla/css v1.0.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
@@ -29,11 +30,13 @@ require (
|
|||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
|
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 // indirect
|
||||||
golang.org/x/sys v0.13.0 // indirect
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -5,6 +5,8 @@ github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXO
|
|||||||
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9 h1:rdWOzitWlNYeUsXmz+IQfa9NkGEq3gA/qQ3mOEqBU6o=
|
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9 h1:rdWOzitWlNYeUsXmz+IQfa9NkGEq3gA/qQ3mOEqBU6o=
|
||||||
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9/go.mod h1:X97UjDTXp+7bayQSFZk2hPvCTmTZIicUjZQRtkwgAKY=
|
github.com/cjoudrey/gluahttp v0.0.0-20201111170219-25003d9adfa9/go.mod h1:X97UjDTXp+7bayQSFZk2hPvCTmTZIicUjZQRtkwgAKY=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/cosmotek/loguago v1.0.0 h1:cM6xoMPoIL1hRPicMenFNVohylundRIPz+OfpadJyY0=
|
||||||
|
github.com/cosmotek/loguago v1.0.0/go.mod h1:M/3wRiTLODLY6ufA9sVxOgSvnkYv53sYuDTQEqX0lZ4=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -49,6 +51,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
|
|||||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
|
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
|
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
@@ -68,6 +72,8 @@ github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cma
|
|||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 h1:noHsffKZsNfU38DwcXWEPldrTjIZ8FPNKx8mYMGnqjs=
|
||||||
|
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7/go.mod h1:bbMEM6aU1WDF1ErA5YJ0p91652pGv140gGw4Ww3RGp8=
|
||||||
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
|
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
|
||||||
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
|
|||||||
@@ -47,14 +47,13 @@ func New(conf config.Lua, extHost *extension.Host) (*Host, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewFromReader(extHost, bufio.NewReader(file), scriptPath)
|
return NewFromReader(logContext.Logger(), extHost, bufio.NewReader(file), scriptPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromReader constructs a new Lua Host, loading Lua source from the provided reader.
|
// NewFromReader constructs a new Lua Host, loading Lua source from the provided reader.
|
||||||
// The provided path is used in logging and error messages.
|
// The provided path is used in logging and error messages.
|
||||||
func NewFromReader(extHost *extension.Host, r io.Reader, path string) (*Host, error) {
|
func NewFromReader(logger zerolog.Logger, extHost *extension.Host, r io.Reader, path string) (*Host, error) {
|
||||||
logContext := log.With().Str("module", "lua")
|
startLogger := logger.With().Str("phase", "startup").Str("path", path).Logger()
|
||||||
logger := logContext.Str("phase", "startup").Str("path", path).Logger()
|
|
||||||
|
|
||||||
// Pre-parse, and compile script.
|
// Pre-parse, and compile script.
|
||||||
chunk, err := parse.Parse(r, path)
|
chunk, err := parse.Parse(r, path)
|
||||||
@@ -67,10 +66,10 @@ func NewFromReader(extHost *extension.Host, r io.Reader, path string) (*Host, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build the pool and confirm LState is retrievable.
|
// Build the pool and confirm LState is retrievable.
|
||||||
pool := newStatePool(proto)
|
pool := newStatePool(logger, proto)
|
||||||
h := &Host{extHost: extHost, pool: pool, logContext: logContext}
|
h := &Host{extHost: extHost, pool: pool, logContext: logger.With()}
|
||||||
if ls, err := pool.getState(); err == nil {
|
if ls, err := pool.getState(); err == nil {
|
||||||
h.wireFunctions(logger, ls)
|
h.wireFunctions(startLogger, ls)
|
||||||
|
|
||||||
// State creation works, put it back.
|
// State creation works, put it back.
|
||||||
pool.putState(ls)
|
pool.putState(ls)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/inbucket/inbucket/v3/pkg/extension"
|
"github.com/inbucket/inbucket/v3/pkg/extension"
|
||||||
"github.com/inbucket/inbucket/v3/pkg/extension/event"
|
"github.com/inbucket/inbucket/v3/pkg/extension/event"
|
||||||
"github.com/inbucket/inbucket/v3/pkg/extension/luahost"
|
"github.com/inbucket/inbucket/v3/pkg/extension/luahost"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
@@ -56,10 +58,26 @@ func TestEmptyScript(t *testing.T) {
|
|||||||
script := ""
|
script := ""
|
||||||
extHost := extension.NewHost()
|
extHost := extension.NewHost()
|
||||||
|
|
||||||
_, err := luahost.NewFromReader(extHost, strings.NewReader(script), "test.lua")
|
_, err := luahost.NewFromReader(zerolog.Nop(), extHost, strings.NewReader(script), "test.lua")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogger(t *testing.T) {
|
||||||
|
script := `
|
||||||
|
local logger = require("logger")
|
||||||
|
logger.info("_test log entry_", {})
|
||||||
|
`
|
||||||
|
|
||||||
|
extHost := extension.NewHost()
|
||||||
|
output := &strings.Builder{}
|
||||||
|
logger := zerolog.New(output)
|
||||||
|
|
||||||
|
_, err := luahost.NewFromReader(logger, extHost, strings.NewReader(script), "test.lua")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Contains(t, output.String(), "_test log entry_")
|
||||||
|
}
|
||||||
|
|
||||||
func TestAfterMessageDeleted(t *testing.T) {
|
func TestAfterMessageDeleted(t *testing.T) {
|
||||||
// Register lua event listener, setup notify channel.
|
// Register lua event listener, setup notify channel.
|
||||||
script := `
|
script := `
|
||||||
@@ -73,7 +91,7 @@ func TestAfterMessageDeleted(t *testing.T) {
|
|||||||
end
|
end
|
||||||
`
|
`
|
||||||
extHost := extension.NewHost()
|
extHost := extension.NewHost()
|
||||||
luaHost, err := luahost.NewFromReader(extHost, strings.NewReader(LuaInit+script), "test.lua")
|
luaHost, err := luahost.NewFromReader(zerolog.Nop(), extHost, strings.NewReader(LuaInit+script), "test.lua")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
notify := luaHost.CreateChannel("notify")
|
notify := luaHost.CreateChannel("notify")
|
||||||
|
|
||||||
@@ -104,7 +122,7 @@ func TestAfterMessageStored(t *testing.T) {
|
|||||||
end
|
end
|
||||||
`
|
`
|
||||||
extHost := extension.NewHost()
|
extHost := extension.NewHost()
|
||||||
luaHost, err := luahost.NewFromReader(extHost, strings.NewReader(LuaInit+script), "test.lua")
|
luaHost, err := luahost.NewFromReader(zerolog.Nop(), extHost, strings.NewReader(LuaInit+script), "test.lua")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
notify := luaHost.CreateChannel("notify")
|
notify := luaHost.CreateChannel("notify")
|
||||||
|
|
||||||
@@ -130,7 +148,7 @@ func TestBeforeMailAccepted(t *testing.T) {
|
|||||||
end
|
end
|
||||||
`
|
`
|
||||||
extHost := extension.NewHost()
|
extHost := extension.NewHost()
|
||||||
_, err := luahost.NewFromReader(extHost, strings.NewReader(script), "test.lua")
|
_, err := luahost.NewFromReader(zerolog.Nop(), extHost, strings.NewReader(script), "test.lua")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Send event to be accepted.
|
// Send event to be accepted.
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/cjoudrey/gluahttp"
|
"github.com/cjoudrey/gluahttp"
|
||||||
|
"github.com/cosmotek/loguago"
|
||||||
"github.com/inbucket/gopher-json"
|
"github.com/inbucket/gopher-json"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,12 +16,14 @@ type statePool struct {
|
|||||||
funcProto *lua.FunctionProto // Compiled lua.
|
funcProto *lua.FunctionProto // Compiled lua.
|
||||||
states []*lua.LState // Pool of available LStates.
|
states []*lua.LState // Pool of available LStates.
|
||||||
channels map[string]chan lua.LValue // Global interop channels.
|
channels map[string]chan lua.LValue // Global interop channels.
|
||||||
|
logger zerolog.Logger // Logger exported to Lua scripts.
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStatePool(funcProto *lua.FunctionProto) *statePool {
|
func newStatePool(logger zerolog.Logger, funcProto *lua.FunctionProto) *statePool {
|
||||||
return &statePool{
|
return &statePool{
|
||||||
funcProto: funcProto,
|
funcProto: funcProto,
|
||||||
channels: make(map[string]chan lua.LValue),
|
channels: make(map[string]chan lua.LValue),
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,9 +31,12 @@ func newStatePool(funcProto *lua.FunctionProto) *statePool {
|
|||||||
func (lp *statePool) newState() (*lua.LState, error) {
|
func (lp *statePool) newState() (*lua.LState, error) {
|
||||||
ls := lua.NewState()
|
ls := lua.NewState()
|
||||||
|
|
||||||
|
logger := loguago.NewLogger(lp.logger)
|
||||||
|
|
||||||
// Load supplemental native modules.
|
// Load supplemental native modules.
|
||||||
ls.PreloadModule("http", gluahttp.NewHttpModule(&http.Client{}).Loader)
|
ls.PreloadModule("http", gluahttp.NewHttpModule(&http.Client{}).Loader)
|
||||||
ls.PreloadModule("json", json.Loader)
|
ls.PreloadModule("json", json.Loader)
|
||||||
|
ls.PreloadModule("logger", logger.Loader)
|
||||||
|
|
||||||
// Setup channels.
|
// Setup channels.
|
||||||
for name, ch := range lp.channels {
|
for name, ch := range lp.channels {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
@@ -23,7 +24,7 @@ func makeEmptyPool() *statePool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newStatePool(proto)
|
return newStatePool(zerolog.Nop(), proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoolGetsDistinct(t *testing.T) {
|
func TestPoolGetsDistinct(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user