Skip to content

Commit

Permalink
fix(inputs.mysql): Use correct column-types for Percona 8 userstats (#…
Browse files Browse the repository at this point in the history
…15012)

(cherry picked from commit 13c786b)
  • Loading branch information
srebhan authored and powersj committed Apr 1, 2024
1 parent 03c1e88 commit 0536813
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 26 deletions.
55 changes: 29 additions & 26 deletions plugins/inputs/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
_ "embed"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -947,7 +948,7 @@ func (m *Mysql) gatherUserStatisticsStatuses(db *sql.DB, servtag string, acc tel
return err
}

read, err := getColSlice(len(cols))
read, err := getColSlice(rows)
if err != nil {
return err
}
Expand Down Expand Up @@ -995,7 +996,13 @@ func columnsToLower(s []string, e error) ([]string, error) {
}

// getColSlice returns an in interface slice that can be used in the row.Scan().
func getColSlice(l int) ([]interface{}, error) {
func getColSlice(rows *sql.Rows) ([]interface{}, error) {
columnTypes, err := rows.ColumnTypes()
if err != nil {
return nil, err
}
l := len(columnTypes)

// list of all possible column names
var (
user string
Expand Down Expand Up @@ -1111,30 +1118,26 @@ func getColSlice(l int) ([]interface{}, error) {
&emptyQueries,
}, nil
case 22: // percona
return []interface{}{
&user,
&totalConnections,
&concurrentConnections,
&connectedTime,
&busyTime,
&cpuTime,
&bytesReceived,
&bytesSent,
&binlogBytesWritten,
&rowsFetched,
&rowsUpdated,
&tableRowsRead,
&selectCommands,
&updateCommands,
&otherCommands,
&commitTransactions,
&rollbackTransactions,
&deniedConnections,
&lostConnections,
&accessDenied,
&emptyQueries,
&totalSslConnections,
}, nil
cols := make([]interface{}, 0, 22)
for i, ct := range columnTypes {
// The first column is the user and has to be a string
if i == 0 {
cols = append(cols, new(string))
continue
}

// Percona 8 has some special fields that are float instead of ints
// see: https://github.com/influxdata/telegraf/issues/7360
switch ct.ScanType().Kind() {
case reflect.Float32, reflect.Float64:
cols = append(cols, new(float64))
default:
// Keep old type for backward compatibility
cols = append(cols, new(int64))
}
}

return cols, nil
}

return nil, fmt.Errorf("not Supported - %d columns", l)
Expand Down
37 changes: 37 additions & 0 deletions plugins/inputs/mysql/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,43 @@ func TestMysqlMultipleInstancesIntegration(t *testing.T) {
require.False(t, acc2.HasMeasurement("mysql_variables"))
}

func TestPercona8Integration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}

container := testutil.Container{
Image: "percona:8",
Env: map[string]string{
"MYSQL_ROOT_PASSWORD": "secret",
},
Cmd: []string{"--userstat=ON"},
ExposedPorts: []string{servicePort},
WaitingFor: wait.ForAll(
wait.ForLog("/usr/sbin/mysqld: ready for connections").WithOccurrence(2),
wait.ForListeningPort(nat.Port(servicePort)),
),
}
require.NoError(t, container.Start(), "failed to start container")
defer container.Terminate()

dsn := fmt.Sprintf("root:secret@tcp(%s:%s)/", container.Address, container.Ports[servicePort])
s := config.NewSecret([]byte(dsn))
plugin := &Mysql{
Servers: []*config.Secret{&s},
GatherUserStatistics: true,
}
require.NoError(t, plugin.Init())

var acc testutil.Accumulator
require.NoError(t, plugin.Gather(&acc))
require.Empty(t, acc.Errors)
require.True(t, acc.HasMeasurement("mysql_user_stats"))
require.True(t, acc.HasFloatField("mysql_user_stats", "connected_time"))
require.True(t, acc.HasFloatField("mysql_user_stats", "cpu_time"))
require.True(t, acc.HasFloatField("mysql_user_stats", "busy_time"))
}

func TestMysqlGetDSNTag(t *testing.T) {
tests := []struct {
input string
Expand Down

0 comments on commit 0536813

Please sign in to comment.