Support logging in starlark (#8408)
This commit is contained in:
parent
dc782805da
commit
0c15569174
|
|
@ -96,6 +96,7 @@ While Starlark is similar to Python, there are important differences to note:
|
|||
The ability to load external scripts other than your own is pretty limited. The following libraries are available for loading:
|
||||
|
||||
* json: `load("json.star", "json")` provides the following functions: `json.encode()`, `json.decode()`, `json.indent()`. See [json.star](/plugins/processors/starlark/testdata/json.star) for an example.
|
||||
* log: `load("logging.star", "log")` provides the following functions: `log.debug()`, `log.info()`, `log.warn()`, `log.error()`. See [logging.star](/plugins/processors/starlark/testdata/logging.star) for an example.
|
||||
|
||||
If you would like to see support for something else here, please open an issue.
|
||||
|
||||
|
|
@ -185,6 +186,7 @@ def failing(metric):
|
|||
- [rename](/plugins/processors/starlark/testdata/rename.star) - Rename tags or fields using a name mapping.
|
||||
- [scale](/plugins/processors/starlark/testdata/scale.star) - Multiply any field by a number
|
||||
- [value filter](/plugins/processors/starlark/testdata/value_filter.star) - remove a metric based on a field value.
|
||||
- [logging](/plugins/processors/starlark/testdata/logging.star) - Log messages with the logger of Telegraf
|
||||
|
||||
[All examples](/plugins/processors/starlark/testdata) are in the testdata folder.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
package starlark
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"go.starlark.net/starlark"
|
||||
"go.starlark.net/starlarkstruct"
|
||||
)
|
||||
|
||||
// Builds a module that defines all the supported logging functions which will log using the provided logger
|
||||
func LogModule(logger telegraf.Logger) *starlarkstruct.Module {
|
||||
var logFunc = func(t *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||
return log(t, b, args, kwargs, logger)
|
||||
}
|
||||
return &starlarkstruct.Module{
|
||||
Name: "log",
|
||||
Members: starlark.StringDict{
|
||||
"debug": starlark.NewBuiltin("log.debug", logFunc),
|
||||
"info": starlark.NewBuiltin("log.info", logFunc),
|
||||
"warn": starlark.NewBuiltin("log.warn", logFunc),
|
||||
"error": starlark.NewBuiltin("log.error", logFunc),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Logs the provided message according to the level chosen
|
||||
func log(t *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple, logger telegraf.Logger) (starlark.Value, error) {
|
||||
var msg starlark.String
|
||||
if err := starlark.UnpackPositionalArgs(b.Name(), args, kwargs, 1, &msg); err != nil {
|
||||
return starlark.None, fmt.Errorf("%s: %v", b.Name(), err)
|
||||
}
|
||||
switch b.Name() {
|
||||
case "log.debug":
|
||||
logger.Debug(string(msg))
|
||||
case "log.info":
|
||||
logger.Info(string(msg))
|
||||
case "log.warn":
|
||||
logger.Warn(string(msg))
|
||||
case "log.error":
|
||||
logger.Error(string(msg))
|
||||
default:
|
||||
return nil, errors.New("method " + b.Name() + " is unknown")
|
||||
}
|
||||
return starlark.None, nil
|
||||
}
|
||||
|
|
@ -52,7 +52,9 @@ func (s *Starlark) Init() error {
|
|||
|
||||
s.thread = &starlark.Thread{
|
||||
Print: func(_ *starlark.Thread, msg string) { s.Log.Debug(msg) },
|
||||
Load: loadFunc,
|
||||
Load: func(thread *starlark.Thread, module string) (starlark.StringDict, error) {
|
||||
return loadFunc(thread, module, s.Log)
|
||||
},
|
||||
}
|
||||
|
||||
builtins := starlark.StringDict{}
|
||||
|
|
@ -217,12 +219,16 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
func loadFunc(thread *starlark.Thread, module string) (starlark.StringDict, error) {
|
||||
func loadFunc(thread *starlark.Thread, module string, logger telegraf.Logger) (starlark.StringDict, error) {
|
||||
switch module {
|
||||
case "json.star":
|
||||
return starlark.StringDict{
|
||||
"json": starlarkjson.Module,
|
||||
}, nil
|
||||
case "logging.star":
|
||||
return starlark.StringDict{
|
||||
"log": LogModule(logger),
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.New("module " + module + " is not available")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2535,6 +2535,31 @@ func TestScript(t *testing.T) {
|
|||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "logging",
|
||||
plugin: &Starlark{
|
||||
Script: "testdata/logging.star",
|
||||
Log: testutil.Logger{},
|
||||
},
|
||||
input: []telegraf.Metric{
|
||||
testutil.MustMetric("log",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"debug": "a debug message",
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric("log",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"debug": "a debug message",
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# Example of the way to log a message with all the supported levels
|
||||
# using the logger of Telegraf.
|
||||
#
|
||||
# Example Input:
|
||||
# log debug="a debug message" 1465839830100400201
|
||||
#
|
||||
# Example Output:
|
||||
# log debug="a debug message" 1465839830100400201
|
||||
|
||||
load("logging.star", "log")
|
||||
# loads log.debug(), log.info(), log.warn(), log.error()
|
||||
|
||||
def apply(metric):
|
||||
log.debug("debug: {}".format(metric.fields["debug"]))
|
||||
log.info("an info message")
|
||||
log.warn("a warning message")
|
||||
log.error("an error message")
|
||||
return metric
|
||||
|
||||
Loading…
Reference in New Issue