From 8967084bf3a9122181999ec4b8916cf72e35bda7 Mon Sep 17 00:00:00 2001 From: Sven Rebhan Date: Tue, 26 Mar 2024 14:29:35 +0100 Subject: [PATCH 1/2] Add unit test for issue 6417 --- plugins/inputs/mysql/mysql_test.go | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/plugins/inputs/mysql/mysql_test.go b/plugins/inputs/mysql/mysql_test.go index 087bc4be76137..b71db7347c003 100644 --- a/plugins/inputs/mysql/mysql_test.go +++ b/plugins/inputs/mysql/mysql_test.go @@ -38,8 +38,10 @@ func TestMysqlDefaultsToLocalIntegration(t *testing.T) { dsn := fmt.Sprintf("root@tcp(%s:%s)/", container.Address, container.Ports[servicePort]) s := config.NewSecret([]byte(dsn)) + defer s.Destroy() m := &Mysql{ Servers: []*config.Secret{&s}, + Log: &testutil.Logger{}, } 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]) s := config.NewSecret([]byte(dsn)) + defer s.Destroy() m := &Mysql{ Servers: []*config.Secret{&s}, IntervalSlow: config.Duration(30 * time.Second), GatherGlobalVars: true, MetricVersion: 2, + Log: &testutil.Logger{}, } require.NoError(t, m.Init()) @@ -93,6 +97,7 @@ func TestMysqlMultipleInstancesIntegration(t *testing.T) { m2 := &Mysql{ Servers: []*config.Secret{&s2}, MetricVersion: 2, + Log: &testutil.Logger{}, } 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]) s := config.NewSecret([]byte(dsn)) + defer s.Destroy() plugin := &Mysql{ Servers: []*config.Secret{&s}, GatherUserStatistics: true, + Log: &testutil.Logger{}, } require.NoError(t, plugin.Init()) @@ -141,6 +148,44 @@ func TestPercona8Integration(t *testing.T) { 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) { tests := []struct { input string From 5fb047f706dcbc6055f76ae844c88b80e8066a5d Mon Sep 17 00:00:00 2001 From: Sven Rebhan Date: Tue, 26 Mar 2024 14:49:40 +0100 Subject: [PATCH 2/2] Fix parsing of boolean values in metric version 1 --- plugins/inputs/mysql/mysql.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/plugins/inputs/mysql/mysql.go b/plugins/inputs/mysql/mysql.go index 7af577ac184e1..0dd4febc7c82c 100644 --- a/plugins/inputs/mysql/mysql.go +++ b/plugins/inputs/mysql/mysql.go @@ -55,8 +55,9 @@ type Mysql struct { Log telegraf.Logger `toml:"-"` tls.ClientConfig - lastT time.Time - getStatusQuery string + lastT time.Time + getStatusQuery string + loggedConvertFields map[string]bool } const ( @@ -85,6 +86,8 @@ func (m *Mysql) Init() error { m.Servers = append(m.Servers, &s) } + m.loggedConvertFields = make(map[string]bool) + // Register the TLS configuration. Due to the registry being a global // one for the mysql package, we need to define unique IDs to avoid // 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 { if strings.HasPrefix(key, mapped.OnServer) { // 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 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 found = true }