Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] add new lib: log #53

Merged
merged 13 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/starlet/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ require (
github.com/muesli/termenv v0.13.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rodolfoag/gow32 v0.0.0-20160917004320-d95ff468acf8 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect
)

Expand Down
18 changes: 18 additions & 0 deletions cmd/starlet/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ github.com/1set/starlight v0.0.8 h1:s86EmbDySwEjFOZTCcDoiC6CCgCubxl19fICNrCJ/EM=
github.com/1set/starlight v0.0.8/go.mod h1:qdWUluPSV8w9jLWdh3CRinNCJovSL6TuPc+DB9CbeKM=
github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/gonutz/w32 v1.0.0 h1:3t1z6ZfkFvirjFYBx9pHeHBuKoN/VBVk9yHb/m2Ll/k=
github.com/gonutz/w32 v1.0.0/go.mod h1:Rc/YP5K9gv0FW4p6X9qL3E7Y56lfMflEol1fLElfMW4=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
Expand All @@ -25,17 +29,31 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rodolfoag/gow32 v0.0.0-20160917004320-d95ff468acf8 h1:p7tJTb+Rqvp8dS82oMnL1M1Yt9ersQyJU7E1C8Bl+7Q=
github.com/rodolfoag/gow32 v0.0.0-20160917004320-d95ff468acf8/go.mod h1:w/ebPUfAcyZMYjstwPIWTEGSahChHx5R3Y+xElrvxDc=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4=
go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
2 changes: 2 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
libhash "github.com/1set/starlet/lib/hashlib"
libhttp "github.com/1set/starlet/lib/http"
libjson "github.com/1set/starlet/lib/json"
liblog "github.com/1set/starlet/lib/log"
librand "github.com/1set/starlet/lib/random"
libre "github.com/1set/starlet/lib/re"
librt "github.com/1set/starlet/lib/runtime"
Expand Down Expand Up @@ -45,6 +46,7 @@ var allBuiltinModules = ModuleLoaderMap{
libjson.ModuleName: libjson.LoadModule,
libstr.ModuleName: libstr.LoadModule,
librt.ModuleName: librt.LoadModule,
liblog.ModuleName: liblog.LoadModule,
}

// GetAllBuiltinModuleNames returns a list of all builtin module names.
Expand Down
10 changes: 10 additions & 0 deletions dataconv/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ func Unmarshal(x starlark.Value) (val interface{}, err error) {
return
}

// check for cyclic reference
if dictVal == x {
err = fmt.Errorf("cyclic reference found")
return
}

pval, err = Unmarshal(dictVal)
if err != nil {
err = fmt.Errorf("unmarshaling starlark value: %w", err)
Expand Down Expand Up @@ -182,6 +188,10 @@ func Unmarshal(x starlark.Value) (val interface{}, err error) {

defer iter.Done()
for iter.Next(&listVal) {
if listVal == x {
err = fmt.Errorf("cyclic reference found")
return
}
value[i], err = Unmarshal(listVal)
if err != nil {
return
Expand Down
14 changes: 14 additions & 0 deletions dataconv/marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ func TestUnmarshal(t *testing.T) {
if err := nilDict.SetKey(starlark.String("foo"), nil); err != nil {
t.Fatal(err)
}
cycDict := starlark.NewDict(2)
if err := cycDict.SetKey(starlark.String("foo"), starlark.MakeInt(42)); err != nil {
t.Fatal(err)
}
if err := cycDict.SetKey(starlark.String("bar"), cycDict); err != nil {
t.Fatal(err)
}

cycList := starlark.NewList([]starlark.Value{starlark.MakeInt(42)})
if err := cycList.Append(cycList); err != nil {
t.Fatal(err)
}

ct, _ := (&customType{42}).MarshalStarlark()
strDictCT := starlark.NewDict(2)
Expand Down Expand Up @@ -213,6 +225,8 @@ func TestUnmarshal(t *testing.T) {
{ct, &customType{42}, ""},
{act, &customType{43}, ""},
{strDictCT, map[string]interface{}{"foo": 42, "bar": &customType{42}}, ""},
{cycDict, nil, "cyclic reference found"},
{cycList, nil, "cyclic reference found"},
{starlark.NewList([]starlark.Value{starlark.MakeInt(42), ct}), []interface{}{42, &customType{42}}, ""},
{starlark.Tuple{starlark.String("foo"), starlark.MakeInt(42)}, []interface{}{"foo", 42}, ""},
{ss, []interface{}{"Hello", "World"}, ""},
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ require (
github.com/1set/starlight v0.0.8
github.com/google/uuid v1.6.0
go.starlark.net v0.0.0-20231121155337-90ade8b19d09
go.uber.org/zap v1.24.0
)

require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
)
18 changes: 18 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
github.com/1set/starlight v0.0.8 h1:s86EmbDySwEjFOZTCcDoiC6CCgCubxl19fICNrCJ/EM=
github.com/1set/starlight v0.0.8/go.mod h1:qdWUluPSV8w9jLWdh3CRinNCJovSL6TuPc+DB9CbeKM=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4=
go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
123 changes: 123 additions & 0 deletions lib/log/zaplog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package log

import (
"errors"
"fmt"
"sync"

"github.com/1set/starlet/dataconv"
"go.starlark.net/starlark"
"go.starlark.net/starlarkstruct"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// ModuleName defines the expected name for this Module when used
// in starlark's load() function, eg: load('log', 'info')
const ModuleName = "log"

var (
once sync.Once
logModule starlark.StringDict
logger *zap.SugaredLogger
)

// LoadModule loads the time module. It is concurrency-safe and idempotent.
func LoadModule() (starlark.StringDict, error) {
once.Do(func() {
// If logger is nil, create a new development logger.
if logger == nil {
lg, _ := zap.NewDevelopment()
logger = lg.Sugar()
}

// Create the log module
logModule = starlark.StringDict{
ModuleName: &starlarkstruct.Module{
Name: ModuleName,
Members: starlark.StringDict{
"debug": genLoggerBuiltin("debug", zap.DebugLevel),
"info": genLoggerBuiltin("info", zap.InfoLevel),
"warn": genLoggerBuiltin("warn", zap.WarnLevel),
"error": genLoggerBuiltin("error", zap.ErrorLevel),
"fatal": genLoggerBuiltin("fatal", zap.FatalLevel),
},
},
}
})
return logModule, nil
}

// SetLog sets the logger from outside the package.
func SetLog(l *zap.SugaredLogger) {
if l == nil {
logger = zap.NewNop().Sugar()
return
}
logger = l
}

// genLoggerBuiltin is a helper function to generate a starlark Builtin function that logs a message at a given level.
func genLoggerBuiltin(name string, level zapcore.Level) starlark.Callable {
return starlark.NewBuiltin(ModuleName+"."+name, func(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var msg string
if len(args) <= 0 {
return nil, fmt.Errorf("%s: expected at least 1 argument, got 0", fn.Name())
} else if s, ok := args[0].(starlark.String); ok {
msg = string(s)
} else {
return nil, fmt.Errorf("%s: expected string as first argument, got %s", fn.Name(), args[0].Type())
}

// find the correct log function
var (
logFn func(msg string, keysAndValues ...interface{})
retErr bool
)
switch level {
case zap.DebugLevel:
logFn = logger.Debugw
case zap.InfoLevel:
logFn = logger.Infow
case zap.WarnLevel:
logFn = logger.Warnw
case zap.ErrorLevel:
logFn = logger.Errorw
case zap.FatalLevel:
logFn = logger.Errorw
retErr = true
default:
return nil, fmt.Errorf("unsupported log level: %v", level)

Check warning on line 90 in lib/log/zaplog.go

View check run for this annotation

Codecov / codecov/patch

lib/log/zaplog.go#L89-L90

Added lines #L89 - L90 were not covered by tests
}

// convert args to key-value pairs
var kvp []interface{}
for i := range args {
if i == 0 {
continue
}
if i%2 == 1 {
// for keys, try to interpret as string, or use String() as fallback
if s, ok := args[i].(starlark.String); ok {
kvp = append(kvp, s.GoString())
} else {
kvp = append(kvp, args[i].String())
}
} else {
// for values, try to unmarshal to Go types, or use String() as fallback
if v, e := dataconv.Unmarshal(args[i]); e == nil {
kvp = append(kvp, v)
} else {
kvp = append(kvp, args[i].String())
}
}
}

// log the message
logFn(msg, kvp...)
if retErr {
return starlark.None, errors.New(msg)
}
return starlark.None, nil
})
}
Loading
Loading