fix(inputs.mysql): Parse boolean values in metric v1 correctly (#15063)
This commit is contained in:
parent
57ed9fd330
commit
8c4fd53bc0
|
|
@ -55,8 +55,9 @@ type Mysql struct {
|
||||||
|
|
||||||
Log telegraf.Logger `toml:"-"`
|
Log telegraf.Logger `toml:"-"`
|
||||||
tls.ClientConfig
|
tls.ClientConfig
|
||||||
lastT time.Time
|
lastT time.Time
|
||||||
getStatusQuery string
|
getStatusQuery string
|
||||||
|
loggedConvertFields map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -85,6 +86,8 @@ func (m *Mysql) Init() error {
|
||||||
m.Servers = append(m.Servers, &s)
|
m.Servers = append(m.Servers, &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.loggedConvertFields = make(map[string]bool)
|
||||||
|
|
||||||
// Register the TLS configuration. Due to the registry being a global
|
// Register the TLS configuration. Due to the registry being a global
|
||||||
// one for the mysql package, we need to define unique IDs to avoid
|
// one for the mysql package, we need to define unique IDs to avoid
|
||||||
// side effects and races between different plugin instances. Therefore,
|
// side effects and races between different plugin instances. Therefore,
|
||||||
|
|
@ -773,7 +776,24 @@ func (m *Mysql) gatherGlobalStatuses(db *sql.DB, servtag string, acc telegraf.Ac
|
||||||
for _, mapped := range v1.Mappings {
|
for _, mapped := range v1.Mappings {
|
||||||
if strings.HasPrefix(key, mapped.OnServer) {
|
if strings.HasPrefix(key, mapped.OnServer) {
|
||||||
// convert numeric values to integer
|
// convert numeric values to integer
|
||||||
i, _ := strconv.Atoi(string(val))
|
var i int
|
||||||
|
v := string(val)
|
||||||
|
switch v {
|
||||||
|
case "ON", "true":
|
||||||
|
i = 1
|
||||||
|
case "OFF", "false":
|
||||||
|
i = 0
|
||||||
|
default:
|
||||||
|
if i, err = strconv.Atoi(v); err != nil {
|
||||||
|
// Make the value a <nil> value to prevent adding
|
||||||
|
// the field containing nonsense values.
|
||||||
|
i = 0
|
||||||
|
if !m.loggedConvertFields[key] {
|
||||||
|
m.Log.Warnf("Cannot convert value %q for key %q to integer outputting zero...", v, key)
|
||||||
|
m.loggedConvertFields[key] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fields[mapped.InExport+key[len(mapped.OnServer):]] = i
|
fields[mapped.InExport+key[len(mapped.OnServer):]] = i
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,10 @@ func TestMysqlDefaultsToLocalIntegration(t *testing.T) {
|
||||||
|
|
||||||
dsn := fmt.Sprintf("root@tcp(%s:%s)/", container.Address, container.Ports[servicePort])
|
dsn := fmt.Sprintf("root@tcp(%s:%s)/", container.Address, container.Ports[servicePort])
|
||||||
s := config.NewSecret([]byte(dsn))
|
s := config.NewSecret([]byte(dsn))
|
||||||
|
defer s.Destroy()
|
||||||
m := &Mysql{
|
m := &Mysql{
|
||||||
Servers: []*config.Secret{&s},
|
Servers: []*config.Secret{&s},
|
||||||
|
Log: &testutil.Logger{},
|
||||||
}
|
}
|
||||||
require.NoError(t, m.Init())
|
require.NoError(t, m.Init())
|
||||||
|
|
||||||
|
|
@ -74,11 +76,13 @@ func TestMysqlMultipleInstancesIntegration(t *testing.T) {
|
||||||
|
|
||||||
dsn := fmt.Sprintf("root@tcp(%s:%s)/?tls=false", container.Address, container.Ports[servicePort])
|
dsn := fmt.Sprintf("root@tcp(%s:%s)/?tls=false", container.Address, container.Ports[servicePort])
|
||||||
s := config.NewSecret([]byte(dsn))
|
s := config.NewSecret([]byte(dsn))
|
||||||
|
defer s.Destroy()
|
||||||
m := &Mysql{
|
m := &Mysql{
|
||||||
Servers: []*config.Secret{&s},
|
Servers: []*config.Secret{&s},
|
||||||
IntervalSlow: config.Duration(30 * time.Second),
|
IntervalSlow: config.Duration(30 * time.Second),
|
||||||
GatherGlobalVars: true,
|
GatherGlobalVars: true,
|
||||||
MetricVersion: 2,
|
MetricVersion: 2,
|
||||||
|
Log: &testutil.Logger{},
|
||||||
}
|
}
|
||||||
require.NoError(t, m.Init())
|
require.NoError(t, m.Init())
|
||||||
|
|
||||||
|
|
@ -93,6 +97,7 @@ func TestMysqlMultipleInstancesIntegration(t *testing.T) {
|
||||||
m2 := &Mysql{
|
m2 := &Mysql{
|
||||||
Servers: []*config.Secret{&s2},
|
Servers: []*config.Secret{&s2},
|
||||||
MetricVersion: 2,
|
MetricVersion: 2,
|
||||||
|
Log: &testutil.Logger{},
|
||||||
}
|
}
|
||||||
require.NoError(t, m2.Init())
|
require.NoError(t, m2.Init())
|
||||||
|
|
||||||
|
|
@ -126,9 +131,11 @@ func TestPercona8Integration(t *testing.T) {
|
||||||
|
|
||||||
dsn := fmt.Sprintf("root:secret@tcp(%s:%s)/", container.Address, container.Ports[servicePort])
|
dsn := fmt.Sprintf("root:secret@tcp(%s:%s)/", container.Address, container.Ports[servicePort])
|
||||||
s := config.NewSecret([]byte(dsn))
|
s := config.NewSecret([]byte(dsn))
|
||||||
|
defer s.Destroy()
|
||||||
plugin := &Mysql{
|
plugin := &Mysql{
|
||||||
Servers: []*config.Secret{&s},
|
Servers: []*config.Secret{&s},
|
||||||
GatherUserStatistics: true,
|
GatherUserStatistics: true,
|
||||||
|
Log: &testutil.Logger{},
|
||||||
}
|
}
|
||||||
require.NoError(t, plugin.Init())
|
require.NoError(t, plugin.Init())
|
||||||
|
|
||||||
|
|
@ -141,6 +148,44 @@ func TestPercona8Integration(t *testing.T) {
|
||||||
require.True(t, acc.HasFloatField("mysql_user_stats", "busy_time"))
|
require.True(t, acc.HasFloatField("mysql_user_stats", "busy_time"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGaleraIntegration(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
container := testutil.Container{
|
||||||
|
Image: "bitnami/mariadb-galera",
|
||||||
|
Env: map[string]string{"ALLOW_EMPTY_PASSWORD": "yes"},
|
||||||
|
ExposedPorts: []string{servicePort},
|
||||||
|
WaitingFor: wait.ForAll(
|
||||||
|
wait.ForLog("Synchronized with group, ready for connections"),
|
||||||
|
wait.ForListeningPort(nat.Port(servicePort)),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
require.NoError(t, container.Start(), "failed to start container")
|
||||||
|
defer container.Terminate()
|
||||||
|
|
||||||
|
dsn := fmt.Sprintf("root@tcp(%s:%s)/", container.Address, container.Ports[servicePort])
|
||||||
|
s := config.NewSecret([]byte(dsn))
|
||||||
|
defer s.Destroy()
|
||||||
|
plugin := &Mysql{
|
||||||
|
Servers: []*config.Secret{&s},
|
||||||
|
Log: &testutil.Logger{},
|
||||||
|
}
|
||||||
|
require.NoError(t, plugin.Init())
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
require.NoError(t, plugin.Gather(&acc))
|
||||||
|
require.Empty(t, acc.Errors)
|
||||||
|
require.True(t, acc.HasIntField("mysql", "wsrep_ready"))
|
||||||
|
for _, m := range acc.GetTelegrafMetrics() {
|
||||||
|
if v, found := m.GetField("wsrep_ready"); found {
|
||||||
|
require.EqualValues(t, 1, v, "invalid value for field wsrep_ready")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMysqlGetDSNTag(t *testing.T) {
|
func TestMysqlGetDSNTag(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input string
|
input string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue