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:
|
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.
|
* 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.
|
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.
|
- [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
|
- [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.
|
- [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.
|
[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{
|
s.thread = &starlark.Thread{
|
||||||
Print: func(_ *starlark.Thread, msg string) { s.Log.Debug(msg) },
|
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{}
|
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 {
|
switch module {
|
||||||
case "json.star":
|
case "json.star":
|
||||||
return starlark.StringDict{
|
return starlark.StringDict{
|
||||||
"json": starlarkjson.Module,
|
"json": starlarkjson.Module,
|
||||||
}, nil
|
}, nil
|
||||||
|
case "logging.star":
|
||||||
|
return starlark.StringDict{
|
||||||
|
"log": LogModule(logger),
|
||||||
|
}, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("module " + module + " is not available")
|
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 {
|
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