feat: Implement deprecation infrastructure (#10200)
This commit is contained in:
parent
b4ef429302
commit
df6bf48f8d
|
|
@ -1,3 +1,6 @@
|
||||||
{
|
{
|
||||||
"MD013": false
|
"MD013": false,
|
||||||
|
"MD033": {
|
||||||
|
"allowed_elements": ["br"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
Makefile
23
Makefile
|
|
@ -44,6 +44,8 @@ HOSTGO := env -u GOOS -u GOARCH -u GOARM -- go
|
||||||
LDFLAGS := $(LDFLAGS) -X main.commit=$(commit) -X main.branch=$(branch) -X main.goos=$(GOOS) -X main.goarch=$(GOARCH)
|
LDFLAGS := $(LDFLAGS) -X main.commit=$(commit) -X main.branch=$(branch) -X main.goos=$(GOOS) -X main.goarch=$(GOARCH)
|
||||||
ifneq ($(tag),)
|
ifneq ($(tag),)
|
||||||
LDFLAGS += -X main.version=$(version)
|
LDFLAGS += -X main.version=$(version)
|
||||||
|
else
|
||||||
|
LDFLAGS += -X main.version=$(version)-$(commit)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Go built-in race detector works only for 64 bits architectures.
|
# Go built-in race detector works only for 64 bits architectures.
|
||||||
|
|
@ -148,19 +150,18 @@ lint-install:
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
@which golangci-lint >/dev/null 2>&1 || { \
|
ifeq (, $(shell which golangci-lint))
|
||||||
echo "golangci-lint not found, please run: make lint-install"; \
|
$(info golangci-lint can't be found, please run: make lint-install)
|
||||||
exit 1; \
|
exit 1
|
||||||
}
|
endif
|
||||||
|
|
||||||
golangci-lint run
|
golangci-lint run
|
||||||
|
|
||||||
@which markdownlint >/dev/null 2>&1 || { \
|
ifeq (, $(shell which markdownlint-cli))
|
||||||
echo "markdownlint not found, please run: make lint-install"; \
|
$(info markdownlint-cli can't be found, please run: make lint-install)
|
||||||
exit 1; \
|
exit 1
|
||||||
}
|
endif
|
||||||
|
markdownlint-cli
|
||||||
markdownlint .
|
|
||||||
|
|
||||||
.PHONY: lint-branch
|
.PHONY: lint-branch
|
||||||
lint-branch:
|
lint-branch:
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ var fVersion = flag.Bool("version", false, "display the version and exit")
|
||||||
var fSampleConfig = flag.Bool("sample-config", false,
|
var fSampleConfig = flag.Bool("sample-config", false,
|
||||||
"print out full sample configuration")
|
"print out full sample configuration")
|
||||||
var fPidfile = flag.String("pidfile", "", "file to write our pid to")
|
var fPidfile = flag.String("pidfile", "", "file to write our pid to")
|
||||||
|
var fDeprecationList = flag.Bool("deprecation-list", false,
|
||||||
|
"print all deprecated plugins or plugin options.")
|
||||||
var fSectionFilters = flag.String("section-filter", "",
|
var fSectionFilters = flag.String("section-filter", "",
|
||||||
"filter the sections to print, separator is ':'. Valid values are 'agent', 'global_tags', 'outputs', 'processors', 'aggregators' and 'inputs'")
|
"filter the sections to print, separator is ':'. Valid values are 'agent', 'global_tags', 'outputs', 'processors', 'aggregators' and 'inputs'")
|
||||||
var fInputFilters = flag.String("input-filter", "",
|
var fInputFilters = flag.String("input-filter", "",
|
||||||
|
|
@ -270,6 +272,19 @@ func runAgent(ctx context.Context,
|
||||||
log.Printf("I! Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
|
log.Printf("I! Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
|
||||||
log.Printf("I! Tags enabled: %s", c.ListTags())
|
log.Printf("I! Tags enabled: %s", c.ListTags())
|
||||||
|
|
||||||
|
if count, found := c.Deprecations["inputs"]; found && (count[0] > 0 || count[1] > 0) {
|
||||||
|
log.Printf("W! Deprecated inputs: %d and %d options", count[0], count[1])
|
||||||
|
}
|
||||||
|
if count, found := c.Deprecations["aggregators"]; found && (count[0] > 0 || count[1] > 0) {
|
||||||
|
log.Printf("W! Deprecated aggregators: %d and %d options", count[0], count[1])
|
||||||
|
}
|
||||||
|
if count, found := c.Deprecations["processors"]; found && (count[0] > 0 || count[1] > 0) {
|
||||||
|
log.Printf("W! Deprecated processors: %d and %d options", count[0], count[1])
|
||||||
|
}
|
||||||
|
if count, found := c.Deprecations["outputs"]; found && (count[0] > 0 || count[1] > 0) {
|
||||||
|
log.Printf("W! Deprecated outputs: %d and %d options", count[0], count[1])
|
||||||
|
}
|
||||||
|
|
||||||
if *fPidfile != "" {
|
if *fPidfile != "" {
|
||||||
f, err := os.OpenFile(*fPidfile, os.O_CREATE|os.O_WRONLY, 0644)
|
f, err := os.OpenFile(*fPidfile, os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -348,6 +363,11 @@ func main() {
|
||||||
|
|
||||||
logger.SetupLogging(logger.LogConfig{})
|
logger.SetupLogging(logger.LogConfig{})
|
||||||
|
|
||||||
|
// Configure version
|
||||||
|
if err := internal.SetVersion(version); err != nil {
|
||||||
|
log.Println("Telegraf version already configured to: " + internal.Version())
|
||||||
|
}
|
||||||
|
|
||||||
// Load external plugins, if requested.
|
// Load external plugins, if requested.
|
||||||
if *fPlugins != "" {
|
if *fPlugins != "" {
|
||||||
log.Printf("I! Loading external plugins from: %s", *fPlugins)
|
log.Printf("I! Loading external plugins from: %s", *fPlugins)
|
||||||
|
|
@ -392,6 +412,27 @@ func main() {
|
||||||
|
|
||||||
// switch for flags which just do something and exit immediately
|
// switch for flags which just do something and exit immediately
|
||||||
switch {
|
switch {
|
||||||
|
case *fDeprecationList:
|
||||||
|
c := config.NewConfig()
|
||||||
|
infos := c.CollectDeprecationInfos(
|
||||||
|
inputFilters,
|
||||||
|
outputFilters,
|
||||||
|
aggregatorFilters,
|
||||||
|
processorFilters,
|
||||||
|
)
|
||||||
|
//nolint:revive // We will notice if Println fails
|
||||||
|
fmt.Println("Deprecated Input Plugins: ")
|
||||||
|
c.PrintDeprecationList(infos["inputs"])
|
||||||
|
//nolint:revive // We will notice if Println fails
|
||||||
|
fmt.Println("Deprecated Output Plugins: ")
|
||||||
|
c.PrintDeprecationList(infos["outputs"])
|
||||||
|
//nolint:revive // We will notice if Println fails
|
||||||
|
fmt.Println("Deprecated Processor Plugins: ")
|
||||||
|
c.PrintDeprecationList(infos["processors"])
|
||||||
|
//nolint:revive // We will notice if Println fails
|
||||||
|
fmt.Println("Deprecated Aggregator Plugins: ")
|
||||||
|
c.PrintDeprecationList(infos["aggregators"])
|
||||||
|
return
|
||||||
case *fOutputList:
|
case *fOutputList:
|
||||||
fmt.Println("Available Output Plugins: ")
|
fmt.Println("Available Output Plugins: ")
|
||||||
names := make([]string, 0, len(outputs.Outputs))
|
names := make([]string, 0, len(outputs.Outputs))
|
||||||
|
|
@ -435,16 +476,6 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shortVersion := version
|
|
||||||
if shortVersion == "" {
|
|
||||||
shortVersion = "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure version
|
|
||||||
if err := internal.SetVersion(shortVersion); err != nil {
|
|
||||||
log.Println("Telegraf version already configured to: " + internal.Version())
|
|
||||||
}
|
|
||||||
|
|
||||||
run(
|
run(
|
||||||
inputFilters,
|
inputFilters,
|
||||||
outputFilters,
|
outputFilters,
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/coreos/go-semver/semver"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
"github.com/influxdata/telegraf/internal/choice"
|
"github.com/influxdata/telegraf/internal/choice"
|
||||||
|
|
@ -77,6 +79,9 @@ type Config struct {
|
||||||
// Processors have a slice wrapper type because they need to be sorted
|
// Processors have a slice wrapper type because they need to be sorted
|
||||||
Processors models.RunningProcessors
|
Processors models.RunningProcessors
|
||||||
AggProcessors models.RunningProcessors
|
AggProcessors models.RunningProcessors
|
||||||
|
|
||||||
|
Deprecations map[string][]int64
|
||||||
|
version *semver.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig creates a new struct to hold the Telegraf config.
|
// NewConfig creates a new struct to hold the Telegraf config.
|
||||||
|
|
@ -102,8 +107,16 @@ func NewConfig() *Config {
|
||||||
AggProcessors: make([]*models.RunningProcessor, 0),
|
AggProcessors: make([]*models.RunningProcessor, 0),
|
||||||
InputFilters: make([]string, 0),
|
InputFilters: make([]string, 0),
|
||||||
OutputFilters: make([]string, 0),
|
OutputFilters: make([]string, 0),
|
||||||
|
Deprecations: make(map[string][]int64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle unknown version
|
||||||
|
version := internal.Version()
|
||||||
|
if version == "" || version == "unknown" {
|
||||||
|
version = "0.0.0-unknown"
|
||||||
|
}
|
||||||
|
c.version = semver.New(version)
|
||||||
|
|
||||||
tomlCfg := &toml.Config{
|
tomlCfg := &toml.Config{
|
||||||
NormFieldName: toml.DefaultConfig.NormFieldName,
|
NormFieldName: toml.DefaultConfig.NormFieldName,
|
||||||
FieldToKey: toml.DefaultConfig.FieldToKey,
|
FieldToKey: toml.DefaultConfig.FieldToKey,
|
||||||
|
|
@ -1009,6 +1022,11 @@ func parseConfig(contents []byte) (*ast.Table, error) {
|
||||||
func (c *Config) addAggregator(name string, table *ast.Table) error {
|
func (c *Config) addAggregator(name string, table *ast.Table) error {
|
||||||
creator, ok := aggregators.Aggregators[name]
|
creator, ok := aggregators.Aggregators[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// Handle removed, deprecated plugins
|
||||||
|
if di, deprecated := aggregators.Deprecations[name]; deprecated {
|
||||||
|
printHistoricPluginDeprecationNotice("aggregators", name, di)
|
||||||
|
return fmt.Errorf("plugin deprecated")
|
||||||
|
}
|
||||||
return fmt.Errorf("Undefined but requested aggregator: %s", name)
|
return fmt.Errorf("Undefined but requested aggregator: %s", name)
|
||||||
}
|
}
|
||||||
aggregator := creator()
|
aggregator := creator()
|
||||||
|
|
@ -1022,6 +1040,10 @@ func (c *Config) addAggregator(name string, table *ast.Table) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.printUserDeprecation("aggregators", name, aggregator); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
c.Aggregators = append(c.Aggregators, models.NewRunningAggregator(aggregator, conf))
|
c.Aggregators = append(c.Aggregators, models.NewRunningAggregator(aggregator, conf))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1029,6 +1051,11 @@ func (c *Config) addAggregator(name string, table *ast.Table) error {
|
||||||
func (c *Config) addProcessor(name string, table *ast.Table) error {
|
func (c *Config) addProcessor(name string, table *ast.Table) error {
|
||||||
creator, ok := processors.Processors[name]
|
creator, ok := processors.Processors[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// Handle removed, deprecated plugins
|
||||||
|
if di, deprecated := processors.Deprecations[name]; deprecated {
|
||||||
|
printHistoricPluginDeprecationNotice("processors", name, di)
|
||||||
|
return fmt.Errorf("plugin deprecated")
|
||||||
|
}
|
||||||
return fmt.Errorf("Undefined but requested processor: %s", name)
|
return fmt.Errorf("Undefined but requested processor: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1070,6 +1097,10 @@ func (c *Config) newRunningProcessor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.printUserDeprecation("processors", processorConfig.Name, processor); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
rf := models.NewRunningProcessor(processor, processorConfig)
|
rf := models.NewRunningProcessor(processor, processorConfig)
|
||||||
return rf, nil
|
return rf, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1080,6 +1111,11 @@ func (c *Config) addOutput(name string, table *ast.Table) error {
|
||||||
}
|
}
|
||||||
creator, ok := outputs.Outputs[name]
|
creator, ok := outputs.Outputs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// Handle removed, deprecated plugins
|
||||||
|
if di, deprecated := outputs.Deprecations[name]; deprecated {
|
||||||
|
printHistoricPluginDeprecationNotice("outputs", name, di)
|
||||||
|
return fmt.Errorf("plugin deprecated")
|
||||||
|
}
|
||||||
return fmt.Errorf("Undefined but requested output: %s", name)
|
return fmt.Errorf("Undefined but requested output: %s", name)
|
||||||
}
|
}
|
||||||
output := creator()
|
output := creator()
|
||||||
|
|
@ -1104,6 +1140,10 @@ func (c *Config) addOutput(name string, table *ast.Table) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.printUserDeprecation("outputs", name, output); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
ro := models.NewRunningOutput(output, outputConfig, c.Agent.MetricBatchSize, c.Agent.MetricBufferLimit)
|
ro := models.NewRunningOutput(output, outputConfig, c.Agent.MetricBatchSize, c.Agent.MetricBufferLimit)
|
||||||
c.Outputs = append(c.Outputs, ro)
|
c.Outputs = append(c.Outputs, ro)
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -1113,13 +1153,23 @@ func (c *Config) addInput(name string, table *ast.Table) error {
|
||||||
if len(c.InputFilters) > 0 && !sliceContains(name, c.InputFilters) {
|
if len(c.InputFilters) > 0 && !sliceContains(name, c.InputFilters) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy support renaming io input to diskio
|
// Legacy support renaming io input to diskio
|
||||||
if name == "io" {
|
if name == "io" {
|
||||||
|
if err := c.printUserDeprecation("inputs", name, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
name = "diskio"
|
name = "diskio"
|
||||||
}
|
}
|
||||||
|
|
||||||
creator, ok := inputs.Inputs[name]
|
creator, ok := inputs.Inputs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
// Handle removed, deprecated plugins
|
||||||
|
if di, deprecated := inputs.Deprecations[name]; deprecated {
|
||||||
|
printHistoricPluginDeprecationNotice("inputs", name, di)
|
||||||
|
return fmt.Errorf("plugin deprecated")
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Undefined but requested input: %s", name)
|
return fmt.Errorf("Undefined but requested input: %s", name)
|
||||||
}
|
}
|
||||||
input := creator()
|
input := creator()
|
||||||
|
|
@ -1153,6 +1203,10 @@ func (c *Config) addInput(name string, table *ast.Table) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.printUserDeprecation("inputs", name, input); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
rp := models.NewRunningInput(input, pluginConfig)
|
rp := models.NewRunningInput(input, pluginConfig)
|
||||||
rp.SetDefaultTags(c.Tags)
|
rp.SetDefaultTags(c.Tags)
|
||||||
c.Inputs = append(c.Inputs, rp)
|
c.Inputs = append(c.Inputs, rp)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,378 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log" //nolint:revive // log is ok here as the logging facility is not set-up yet
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/go-semver/semver"
|
||||||
|
"github.com/fatih/color"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/aggregators"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
"github.com/influxdata/telegraf/plugins/outputs"
|
||||||
|
"github.com/influxdata/telegraf/plugins/processors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Escalation level for the plugin or option
|
||||||
|
type Escalation int
|
||||||
|
|
||||||
|
func (e Escalation) String() string {
|
||||||
|
switch e {
|
||||||
|
case Warn:
|
||||||
|
return "WARN"
|
||||||
|
case Error:
|
||||||
|
return "ERROR"
|
||||||
|
}
|
||||||
|
return "NONE"
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// None means no deprecation
|
||||||
|
None Escalation = iota
|
||||||
|
// Warn means deprecated but still within the grace period
|
||||||
|
Warn
|
||||||
|
// Error means deprecated and beyond grace period
|
||||||
|
Error
|
||||||
|
)
|
||||||
|
|
||||||
|
// deprecationInfo contains all important information to describe a deprecated entity
|
||||||
|
type deprecationInfo struct {
|
||||||
|
// Name of the plugin or plugin option
|
||||||
|
Name string
|
||||||
|
// LogLevel is the level of deprecation which currently corresponds to a log-level
|
||||||
|
LogLevel Escalation
|
||||||
|
info telegraf.DeprecationInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (di *deprecationInfo) determineEscalation(telegrafVersion *semver.Version) error {
|
||||||
|
di.LogLevel = None
|
||||||
|
if di.info.Since == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
since, err := semver.NewVersion(di.info.Since)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot parse 'since' version %q: %v", di.info.Since, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var removal *semver.Version
|
||||||
|
if di.info.RemovalIn != "" {
|
||||||
|
removal, err = semver.NewVersion(di.info.RemovalIn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot parse 'removal' version %q: %v", di.info.RemovalIn, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removal = &semver.Version{Major: since.Major}
|
||||||
|
removal.BumpMajor()
|
||||||
|
di.info.RemovalIn = removal.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop potential pre-release tags
|
||||||
|
version := semver.Version{
|
||||||
|
Major: telegrafVersion.Major,
|
||||||
|
Minor: telegrafVersion.Minor,
|
||||||
|
Patch: telegrafVersion.Patch,
|
||||||
|
}
|
||||||
|
if !version.LessThan(*removal) {
|
||||||
|
di.LogLevel = Error
|
||||||
|
} else if !version.LessThan(*since) {
|
||||||
|
di.LogLevel = Warn
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluginDeprecationInfo holds all information about a deprecated plugin or it's options
|
||||||
|
type pluginDeprecationInfo struct {
|
||||||
|
deprecationInfo
|
||||||
|
|
||||||
|
// Options deprecated for this plugin
|
||||||
|
Options []deprecationInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) incrementPluginDeprecations(category string) {
|
||||||
|
newcounts := []int64{1, 0}
|
||||||
|
if counts, found := c.Deprecations[category]; found {
|
||||||
|
newcounts = []int64{counts[0] + 1, counts[1]}
|
||||||
|
}
|
||||||
|
c.Deprecations[category] = newcounts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) incrementPluginOptionDeprecations(category string) {
|
||||||
|
newcounts := []int64{0, 1}
|
||||||
|
if counts, found := c.Deprecations[category]; found {
|
||||||
|
newcounts = []int64{counts[0], counts[1] + 1}
|
||||||
|
}
|
||||||
|
c.Deprecations[category] = newcounts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) collectDeprecationInfo(category, name string, plugin interface{}, all bool) pluginDeprecationInfo {
|
||||||
|
info := pluginDeprecationInfo{
|
||||||
|
deprecationInfo: deprecationInfo{
|
||||||
|
Name: category + "." + name,
|
||||||
|
LogLevel: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// First check if the whole plugin is deprecated
|
||||||
|
switch category {
|
||||||
|
case "aggregators":
|
||||||
|
if pi, deprecated := aggregators.Deprecations[name]; deprecated {
|
||||||
|
info.deprecationInfo.info = pi
|
||||||
|
}
|
||||||
|
case "inputs":
|
||||||
|
if pi, deprecated := inputs.Deprecations[name]; deprecated {
|
||||||
|
info.deprecationInfo.info = pi
|
||||||
|
}
|
||||||
|
case "outputs":
|
||||||
|
if pi, deprecated := outputs.Deprecations[name]; deprecated {
|
||||||
|
info.deprecationInfo.info = pi
|
||||||
|
}
|
||||||
|
case "processors":
|
||||||
|
if pi, deprecated := processors.Deprecations[name]; deprecated {
|
||||||
|
info.deprecationInfo.info = pi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := info.determineEscalation(c.version); err != nil {
|
||||||
|
panic(fmt.Errorf("plugin %q: %v", info.Name, err))
|
||||||
|
}
|
||||||
|
if info.LogLevel != None {
|
||||||
|
c.incrementPluginDeprecations(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow checking for names only.
|
||||||
|
if plugin == nil {
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for deprecated options
|
||||||
|
walkPluginStruct(reflect.ValueOf(plugin), func(field reflect.StructField, value reflect.Value) {
|
||||||
|
// Try to report only those fields that are set
|
||||||
|
if !all && value.IsZero() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tags := strings.SplitN(field.Tag.Get("deprecated"), ";", 3)
|
||||||
|
if len(tags) < 1 || tags[0] == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
optionInfo := deprecationInfo{Name: field.Name}
|
||||||
|
optionInfo.info.Since = tags[0]
|
||||||
|
|
||||||
|
if len(tags) > 1 {
|
||||||
|
optionInfo.info.Notice = tags[len(tags)-1]
|
||||||
|
}
|
||||||
|
if len(tags) > 2 {
|
||||||
|
optionInfo.info.RemovalIn = tags[1]
|
||||||
|
}
|
||||||
|
if err := optionInfo.determineEscalation(c.version); err != nil {
|
||||||
|
panic(fmt.Errorf("plugin %q option %q: %v", info.Name, field.Name, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if optionInfo.LogLevel != None {
|
||||||
|
c.incrementPluginOptionDeprecations(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the toml field name
|
||||||
|
option := field.Tag.Get("toml")
|
||||||
|
if option != "" {
|
||||||
|
optionInfo.Name = option
|
||||||
|
}
|
||||||
|
info.Options = append(info.Options, optionInfo)
|
||||||
|
})
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) printUserDeprecation(category, name string, plugin interface{}) error {
|
||||||
|
info := c.collectDeprecationInfo(category, name, plugin, false)
|
||||||
|
|
||||||
|
switch info.LogLevel {
|
||||||
|
case Warn:
|
||||||
|
prefix := "W! " + color.YellowString("DeprecationWarning")
|
||||||
|
printPluginDeprecationNotice(prefix, info.Name, info.info)
|
||||||
|
// We will not check for any deprecated options as the whole plugin is deprecated anyway.
|
||||||
|
return nil
|
||||||
|
case Error:
|
||||||
|
prefix := "E! " + color.RedString("DeprecationError")
|
||||||
|
printPluginDeprecationNotice(prefix, info.Name, info.info)
|
||||||
|
// We are past the grace period
|
||||||
|
return fmt.Errorf("plugin deprecated")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print deprecated options
|
||||||
|
deprecatedOptions := make([]string, 0)
|
||||||
|
for _, option := range info.Options {
|
||||||
|
switch option.LogLevel {
|
||||||
|
case Warn:
|
||||||
|
prefix := "W! " + color.YellowString("DeprecationWarning")
|
||||||
|
printOptionDeprecationNotice(prefix, info.Name, option.Name, option.info)
|
||||||
|
case Error:
|
||||||
|
prefix := "E! " + color.RedString("DeprecationError")
|
||||||
|
printOptionDeprecationNotice(prefix, info.Name, option.Name, option.info)
|
||||||
|
deprecatedOptions = append(deprecatedOptions, option.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(deprecatedOptions) > 0 {
|
||||||
|
return fmt.Errorf("plugin options %q deprecated", strings.Join(deprecatedOptions, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFilter []string) map[string][]pluginDeprecationInfo {
|
||||||
|
infos := make(map[string][]pluginDeprecationInfo)
|
||||||
|
|
||||||
|
infos["inputs"] = make([]pluginDeprecationInfo, 0)
|
||||||
|
for name, creator := range inputs.Inputs {
|
||||||
|
if len(inFilter) > 0 && !sliceContains(name, inFilter) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin := creator()
|
||||||
|
info := c.collectDeprecationInfo("inputs", name, plugin, true)
|
||||||
|
|
||||||
|
if info.LogLevel != None || len(info.Options) > 0 {
|
||||||
|
infos["inputs"] = append(infos["inputs"], info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infos["outputs"] = make([]pluginDeprecationInfo, 0)
|
||||||
|
for name, creator := range outputs.Outputs {
|
||||||
|
if len(outFilter) > 0 && !sliceContains(name, outFilter) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin := creator()
|
||||||
|
info := c.collectDeprecationInfo("outputs", name, plugin, true)
|
||||||
|
|
||||||
|
if info.LogLevel != None || len(info.Options) > 0 {
|
||||||
|
infos["outputs"] = append(infos["outputs"], info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infos["processors"] = make([]pluginDeprecationInfo, 0)
|
||||||
|
for name, creator := range processors.Processors {
|
||||||
|
if len(procFilter) > 0 && !sliceContains(name, procFilter) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin := creator()
|
||||||
|
info := c.collectDeprecationInfo("processors", name, plugin, true)
|
||||||
|
|
||||||
|
if info.LogLevel != None || len(info.Options) > 0 {
|
||||||
|
infos["processors"] = append(infos["processors"], info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infos["aggregators"] = make([]pluginDeprecationInfo, 0)
|
||||||
|
for name, creator := range aggregators.Aggregators {
|
||||||
|
if len(aggFilter) > 0 && !sliceContains(name, aggFilter) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin := creator()
|
||||||
|
info := c.collectDeprecationInfo("aggregators", name, plugin, true)
|
||||||
|
|
||||||
|
if info.LogLevel != None || len(info.Options) > 0 {
|
||||||
|
infos["aggregators"] = append(infos["aggregators"], info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return infos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) PrintDeprecationList(plugins []pluginDeprecationInfo) {
|
||||||
|
sort.Slice(plugins, func(i, j int) bool { return plugins[i].Name < plugins[j].Name })
|
||||||
|
|
||||||
|
for _, plugin := range plugins {
|
||||||
|
switch plugin.LogLevel {
|
||||||
|
case Warn, Error:
|
||||||
|
_, _ = fmt.Printf(
|
||||||
|
" %-40s %-5s since %-5s removal in %-5s %s\n",
|
||||||
|
plugin.Name, plugin.LogLevel, plugin.info.Since, plugin.info.RemovalIn, plugin.info.Notice,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(plugin.Options) < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sort.Slice(plugin.Options, func(i, j int) bool { return plugin.Options[i].Name < plugin.Options[j].Name })
|
||||||
|
for _, option := range plugin.Options {
|
||||||
|
_, _ = fmt.Printf(
|
||||||
|
" %-40s %-5s since %-5s removal in %-5s %s\n",
|
||||||
|
plugin.Name+"/"+option.Name, option.LogLevel, option.info.Since, option.info.RemovalIn, option.info.Notice,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printHistoricPluginDeprecationNotice(category, name string, info telegraf.DeprecationInfo) {
|
||||||
|
prefix := "E! " + color.RedString("DeprecationError")
|
||||||
|
log.Printf(
|
||||||
|
"%s: Plugin %q deprecated since version %s and removed: %s",
|
||||||
|
prefix, category+"."+name, info.Since, info.Notice,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPluginDeprecationNotice(prefix, name string, info telegraf.DeprecationInfo) {
|
||||||
|
log.Printf(
|
||||||
|
"%s: Plugin %q deprecated since version %s and will be removed in %s: %s",
|
||||||
|
prefix, name, info.Since, info.RemovalIn, info.Notice,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printOptionDeprecationNotice(prefix, plugin, option string, info telegraf.DeprecationInfo) {
|
||||||
|
log.Printf(
|
||||||
|
"%s: Option %q of plugin %q deprecated since version %s and will be removed in %s: %s",
|
||||||
|
prefix, option, plugin, info.Since, info.RemovalIn, info.Notice,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// walkPluginStruct iterates over the fields of a structure in depth-first search (to cover nested structures)
|
||||||
|
// and calls the given function for every visited field.
|
||||||
|
func walkPluginStruct(value reflect.Value, fn func(f reflect.StructField, fv reflect.Value)) {
|
||||||
|
v := reflect.Indirect(value)
|
||||||
|
t := v.Type()
|
||||||
|
|
||||||
|
// Only works on structs
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk over the struct fields and call the given function. If we encounter more complex embedded
|
||||||
|
// elements (stucts, slices/arrays, maps) we need to descend into those elements as they might
|
||||||
|
// contain structures nested in the current structure.
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
fieldValue := v.Field(i)
|
||||||
|
|
||||||
|
if field.PkgPath != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
walkPluginStruct(fieldValue, fn)
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
for j := 0; j < fieldValue.Len(); j++ {
|
||||||
|
element := fieldValue.Index(j)
|
||||||
|
// The array might contain structs
|
||||||
|
walkPluginStruct(element, fn)
|
||||||
|
fn(field, element)
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
iter := fieldValue.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
element := iter.Value()
|
||||||
|
// The map might contain structs
|
||||||
|
walkPluginStruct(element, fn)
|
||||||
|
fn(field, element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn(field, fieldValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ telegraf [flags]
|
||||||
|`--watch-config` |Telegraf will restart on local config changes. Monitor changes using either fs notifications or polling. Valid values: `inotify` or `poll`. Monitoring is off by default.|
|
|`--watch-config` |Telegraf will restart on local config changes. Monitor changes using either fs notifications or polling. Valid values: `inotify` or `poll`. Monitoring is off by default.|
|
||||||
|`--plugin-directory` |directory containing *.so files, this directory will be searched recursively. Any Plugin found will be loaded and namespaced.|
|
|`--plugin-directory` |directory containing *.so files, this directory will be searched recursively. Any Plugin found will be loaded and namespaced.|
|
||||||
|`--debug` |turn on debug logging|
|
|`--debug` |turn on debug logging|
|
||||||
|
|`--deprecation-list` |print all deprecated plugins or plugin options|
|
||||||
|`--input-filter <filter>` |filter the inputs to enable, separator is `:`|
|
|`--input-filter <filter>` |filter the inputs to enable, separator is `:`|
|
||||||
|`--input-list` |print available input plugins.|
|
|`--input-list` |print available input plugins.|
|
||||||
|`--output-filter <filter>` |filter the outputs to enable, separator is `:`|
|
|`--output-filter <filter>` |filter the outputs to enable, separator is `:`|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ following works:
|
||||||
- github.com/cespare/xxhash [MIT License](https://github.com/cespare/xxhash/blob/master/LICENSE.txt)
|
- github.com/cespare/xxhash [MIT License](https://github.com/cespare/xxhash/blob/master/LICENSE.txt)
|
||||||
- github.com/cisco-ie/nx-telemetry-proto [Apache License 2.0](https://github.com/cisco-ie/nx-telemetry-proto/blob/master/LICENSE)
|
- github.com/cisco-ie/nx-telemetry-proto [Apache License 2.0](https://github.com/cisco-ie/nx-telemetry-proto/blob/master/LICENSE)
|
||||||
- github.com/containerd/containerd [Apache License 2.0](https://github.com/containerd/containerd/blob/master/LICENSE)
|
- github.com/containerd/containerd [Apache License 2.0](https://github.com/containerd/containerd/blob/master/LICENSE)
|
||||||
|
- github.com/coreos/go-semver [Apache License 2.0](https://github.com/coreos/go-semver/blob/main/LICENSE)
|
||||||
- github.com/couchbase/go-couchbase [MIT License](https://github.com/couchbase/go-couchbase/blob/master/LICENSE)
|
- github.com/couchbase/go-couchbase [MIT License](https://github.com/couchbase/go-couchbase/blob/master/LICENSE)
|
||||||
- github.com/couchbase/gomemcached [MIT License](https://github.com/couchbase/gomemcached/blob/master/LICENSE)
|
- github.com/couchbase/gomemcached [MIT License](https://github.com/couchbase/gomemcached/blob/master/LICENSE)
|
||||||
- github.com/couchbase/goutils [Apache License 2.0](https://github.com/couchbase/goutils/blob/master/LICENSE.md)
|
- github.com/couchbase/goutils [Apache License 2.0](https://github.com/couchbase/goutils/blob/master/LICENSE.md)
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -78,7 +78,7 @@ require (
|
||||||
github.com/cisco-ie/nx-telemetry-proto v0.0.0-20190531143454-82441e232cf6
|
github.com/cisco-ie/nx-telemetry-proto v0.0.0-20190531143454-82441e232cf6
|
||||||
github.com/containerd/cgroups v1.0.1 // indirect
|
github.com/containerd/cgroups v1.0.1 // indirect
|
||||||
github.com/containerd/containerd v1.5.7 // indirect
|
github.com/containerd/containerd v1.5.7 // indirect
|
||||||
github.com/coreos/go-semver v0.3.0 // indirect
|
github.com/coreos/go-semver v0.3.0
|
||||||
github.com/couchbase/go-couchbase v0.1.0
|
github.com/couchbase/go-couchbase v0.1.0
|
||||||
github.com/couchbase/gomemcached v0.1.3 // indirect
|
github.com/couchbase/gomemcached v0.1.3 // indirect
|
||||||
github.com/couchbase/goutils v0.1.0 // indirect
|
github.com/couchbase/goutils v0.1.0 // indirect
|
||||||
|
|
@ -98,7 +98,7 @@ require (
|
||||||
github.com/eapache/queue v1.1.0 // indirect
|
github.com/eapache/queue v1.1.0 // indirect
|
||||||
github.com/echlebek/timeproxy v1.0.0 // indirect
|
github.com/echlebek/timeproxy v1.0.0 // indirect
|
||||||
github.com/eclipse/paho.mqtt.golang v1.3.0
|
github.com/eclipse/paho.mqtt.golang v1.3.0
|
||||||
github.com/fatih/color v1.10.0 // indirect
|
github.com/fatih/color v1.10.0
|
||||||
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
|
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
|
||||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
|
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
|
||||||
github.com/go-logfmt/logfmt v0.5.0
|
github.com/go-logfmt/logfmt v0.5.0
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ func SetVersion(v string) error {
|
||||||
return ErrorVersionAlreadySet
|
return ErrorVersionAlreadySet
|
||||||
}
|
}
|
||||||
version = v
|
version = v
|
||||||
|
if version == "" {
|
||||||
|
version = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ The commands & flags are:
|
||||||
searched recursively. Any Plugin found will be loaded
|
searched recursively. Any Plugin found will be loaded
|
||||||
and namespaced.
|
and namespaced.
|
||||||
--debug turn on debug logging
|
--debug turn on debug logging
|
||||||
|
--deprecation-list print all deprecated plugins or plugin options.
|
||||||
--input-filter <filter> filter the inputs to enable, separator is :
|
--input-filter <filter> filter the inputs to enable, separator is :
|
||||||
--input-list print available input plugins.
|
--input-list print available input plugins.
|
||||||
--output-filter <filter> filter the outputs to enable, separator is :
|
--output-filter <filter> filter the outputs to enable, separator is :
|
||||||
|
|
|
||||||
10
plugin.go
10
plugin.go
|
|
@ -2,6 +2,16 @@ package telegraf
|
||||||
|
|
||||||
var Debug bool
|
var Debug bool
|
||||||
|
|
||||||
|
// DeprecationInfo contains information for marking a plugin deprecated.
|
||||||
|
type DeprecationInfo struct {
|
||||||
|
// Since specifies the version since when the plugin is deprecated
|
||||||
|
Since string
|
||||||
|
// RemovalIn optionally specifies the version when the plugin is scheduled for removal
|
||||||
|
RemovalIn string
|
||||||
|
// Notice for the user on suggested replacements etc.
|
||||||
|
Notice string
|
||||||
|
}
|
||||||
|
|
||||||
// Initializer is an interface that all plugin types: Inputs, Outputs,
|
// Initializer is an interface that all plugin types: Inputs, Outputs,
|
||||||
// Processors, and Aggregators can optionally implement to initialize the
|
// Processors, and Aggregators can optionally implement to initialize the
|
||||||
// plugin.
|
// plugin.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package aggregators
|
||||||
|
|
||||||
|
import "github.com/influxdata/telegraf"
|
||||||
|
|
||||||
|
// Deprecations lists the deprecated plugins
|
||||||
|
var Deprecations = map[string]telegraf.DeprecationInfo{}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package inputs
|
||||||
|
|
||||||
|
import "github.com/influxdata/telegraf"
|
||||||
|
|
||||||
|
// Deprecations lists the deprecated plugins
|
||||||
|
var Deprecations = map[string]telegraf.DeprecationInfo{
|
||||||
|
"cassandra": {
|
||||||
|
Since: "1.7.0",
|
||||||
|
Notice: "use 'inputs.jolokia2' with the 'cassandra.conf' example configuration instead",
|
||||||
|
},
|
||||||
|
"io": {
|
||||||
|
Since: "0.10.0",
|
||||||
|
RemovalIn: "2.0.0",
|
||||||
|
Notice: "use 'inputs.diskio' instead",
|
||||||
|
},
|
||||||
|
"http_listener_v2": {
|
||||||
|
Since: "1.9.0",
|
||||||
|
Notice: "has been renamed to 'influxdb_listener', use 'inputs.influxdb_listener' or 'inputs.influxdb_listener_v2' instead",
|
||||||
|
},
|
||||||
|
"httpjson": {
|
||||||
|
Since: "1.6.0",
|
||||||
|
Notice: "use 'inputs.http' instead",
|
||||||
|
},
|
||||||
|
"jolokia": {
|
||||||
|
Since: "1.5.0",
|
||||||
|
Notice: "use 'inputs.jolokia2' instead",
|
||||||
|
},
|
||||||
|
"kafka_consumer_legacy": {
|
||||||
|
Since: "1.4.0",
|
||||||
|
Notice: "use 'inputs.kafka_consumer' instead, NOTE: 'kafka_consumer' only supports Kafka v0.8+",
|
||||||
|
},
|
||||||
|
"logparser": {
|
||||||
|
Since: "1.15.0",
|
||||||
|
Notice: "use 'inputs.tail' with 'grok' data format instead",
|
||||||
|
},
|
||||||
|
"snmp_legacy": {
|
||||||
|
Since: "1.0.0",
|
||||||
|
Notice: "use 'inputs.snmp' instead",
|
||||||
|
},
|
||||||
|
"tcp_listener": {
|
||||||
|
Since: "1.3.0",
|
||||||
|
Notice: "use 'inputs.socket_listener' instead",
|
||||||
|
},
|
||||||
|
"udp_listener": {
|
||||||
|
Since: "1.3.0",
|
||||||
|
Notice: "use 'inputs.socket_listener' instead",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -28,7 +28,7 @@ const (
|
||||||
|
|
||||||
// HTTPResponse struct
|
// HTTPResponse struct
|
||||||
type HTTPResponse struct {
|
type HTTPResponse struct {
|
||||||
Address string // deprecated in 1.12
|
Address string `toml:"address" deprecated:"1.12.0;use 'urls' instead"`
|
||||||
URLs []string `toml:"urls"`
|
URLs []string `toml:"urls"`
|
||||||
HTTPProxy string `toml:"http_proxy"`
|
HTTPProxy string `toml:"http_proxy"`
|
||||||
Body string
|
Body string
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package outputs
|
||||||
|
|
||||||
|
import "github.com/influxdata/telegraf"
|
||||||
|
|
||||||
|
// Deprecations lists the deprecated plugins
|
||||||
|
var Deprecations = map[string]telegraf.DeprecationInfo{
|
||||||
|
"riemann_legacy": {
|
||||||
|
Since: "1.3.0",
|
||||||
|
Notice: "use 'outputs.riemann' instead (see https://github.com/influxdata/telegraf/issues/1878)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package processors
|
||||||
|
|
||||||
|
import "github.com/influxdata/telegraf"
|
||||||
|
|
||||||
|
// Deprecations lists the deprecated plugins
|
||||||
|
var Deprecations = map[string]telegraf.DeprecationInfo{}
|
||||||
Loading…
Reference in New Issue