[MM-23882] Include database server version in telemetry (#14258)

* Add database server version to telemetry

Also added a new query in the store to retrieve the database version

* Add test for the GetDbVersion function

* More drivers in the tests

Co-authored-by: mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Mario de Frutos Dieguez
2020-04-09 11:08:15 +02:00
коммит произвёл GitHub
родитель f6f025aeaa
Коммит 698b4b6934
8 изменённых файлов: 132 добавлений и 37 удалений

Просмотреть файл

@@ -802,6 +802,10 @@ func (a *App) trackServer() {
data["system_admins"] = scr data["system_admins"] = scr
} }
if scr, err := a.Srv().Store.GetDbVersion(); err == nil {
data["database_version"] = scr
}
a.SendDiagnostic(TRACK_SERVER, data) a.SendDiagnostic(TRACK_SERVER, data)
} }

Просмотреть файл

@@ -45,6 +45,7 @@ type SqlStore interface {
GetMaster() *gorp.DbMap GetMaster() *gorp.DbMap
GetSearchReplica() *gorp.DbMap GetSearchReplica() *gorp.DbMap
GetReplica() *gorp.DbMap GetReplica() *gorp.DbMap
GetDbVersion() (string, error)
TotalMasterDbConnections() int TotalMasterDbConnections() int
TotalReadDbConnections() int TotalReadDbConnections() int
TotalSearchDbConnections() int TotalSearchDbConnections() int

Просмотреть файл

@@ -301,6 +301,27 @@ func (ss *SqlSupplier) GetCurrentSchemaVersion() string {
return version return version
} }
func (ss *SqlSupplier) GetDbVersion() (string, error) {
var sqlVersion string
if ss.DriverName() == model.DATABASE_DRIVER_POSTGRES {
sqlVersion = `SHOW server_version`
} else if ss.DriverName() == model.DATABASE_DRIVER_MYSQL {
sqlVersion = `SELECT version()`
} else if ss.DriverName() == model.DATABASE_DRIVER_SQLITE {
sqlVersion = `SELECT sqlite_version()`
} else {
return "", errors.New("Not supported driver")
}
version, err := ss.GetReplica().SelectStr(sqlVersion)
if err != nil {
return "", err
}
return version, nil
}
func (ss *SqlSupplier) GetMaster() *gorp.DbMap { func (ss *SqlSupplier) GetMaster() *gorp.DbMap {
return ss.master return ss.master
} }

Просмотреть файл

@@ -4,14 +4,17 @@
package sqlstore_test package sqlstore_test
import ( import (
"regexp"
"testing" "testing"
"github.com/mattermost/gorp" "github.com/mattermost/gorp"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/store/sqlstore" "github.com/mattermost/mattermost-server/v5/store/sqlstore"
"github.com/mattermost/mattermost-server/v5/store/storetest"
) )
func TestGetReplica(t *testing.T) { func TestGetReplica(t *testing.T) {
@@ -73,24 +76,10 @@ func TestGetReplica(t *testing.T) {
t.Run(testCase.Description, func(t *testing.T) { t.Run(testCase.Description, func(t *testing.T) {
t.Parallel() t.Parallel()
driverName := model.DATABASE_DRIVER_SQLITE settings := makeSqlSettings(model.DATABASE_DRIVER_SQLITE)
dataSource := ":memory:" settings.DataSourceReplicas = testCase.DataSourceReplicas
maxIdleConns := 1 settings.DataSourceSearchReplicas = testCase.DataSourceSearchReplicas
connMaxLifetimeMilliseconds := 3600000 supplier := sqlstore.NewSqlSupplier(*settings, nil)
maxOpenConns := 1
queryTimeout := 5
settings := model.SqlSettings{
DriverName: &driverName,
DataSource: &dataSource,
MaxIdleConns: &maxIdleConns,
ConnMaxLifetimeMilliseconds: &connMaxLifetimeMilliseconds,
MaxOpenConns: &maxOpenConns,
QueryTimeout: &queryTimeout,
DataSourceReplicas: testCase.DataSourceReplicas,
DataSourceSearchReplicas: testCase.DataSourceSearchReplicas,
}
supplier := sqlstore.NewSqlSupplier(settings, nil)
replicas := make(map[*gorp.DbMap]bool) replicas := make(map[*gorp.DbMap]bool)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
@@ -142,6 +131,26 @@ func TestGetReplica(t *testing.T) {
} }
} }
func TestGetDbVersion(t *testing.T) {
testDrivers := []string{
model.DATABASE_DRIVER_POSTGRES,
model.DATABASE_DRIVER_MYSQL,
model.DATABASE_DRIVER_SQLITE,
}
for _, driver := range testDrivers {
t.Run("Should return db version for "+driver, func(t *testing.T) {
t.Parallel()
settings := makeSqlSettings(driver)
supplier := sqlstore.NewSqlSupplier(*settings, nil)
version, err := supplier.GetDbVersion()
require.Nil(t, err)
require.Regexp(t, regexp.MustCompile(`\d+\.\d+(\.\d+)?`), version)
})
}
}
func TestGetAllConns(t *testing.T) { func TestGetAllConns(t *testing.T) {
t.Parallel() t.Parallel()
testCases := []struct { testCases := []struct {
@@ -210,27 +219,43 @@ func TestGetAllConns(t *testing.T) {
testCase := testCase testCase := testCase
t.Run(testCase.Description, func(t *testing.T) { t.Run(testCase.Description, func(t *testing.T) {
t.Parallel() t.Parallel()
settings := makeSqlSettings(model.DATABASE_DRIVER_SQLITE)
driverName := model.DATABASE_DRIVER_SQLITE settings.DataSourceReplicas = testCase.DataSourceReplicas
dataSource := ":memory:" settings.DataSourceSearchReplicas = testCase.DataSourceSearchReplicas
maxIdleConns := 1 supplier := sqlstore.NewSqlSupplier(*settings, nil)
connMaxLifetimeMilliseconds := 3600000
maxOpenConns := 1
queryTimeout := 5
settings := model.SqlSettings{
DriverName: &driverName,
DataSource: &dataSource,
MaxIdleConns: &maxIdleConns,
ConnMaxLifetimeMilliseconds: &connMaxLifetimeMilliseconds,
MaxOpenConns: &maxOpenConns,
QueryTimeout: &queryTimeout,
DataSourceReplicas: testCase.DataSourceReplicas,
DataSourceSearchReplicas: testCase.DataSourceSearchReplicas,
}
supplier := sqlstore.NewSqlSupplier(settings, nil)
assert.Len(t, supplier.GetAllConns(), testCase.ExpectedNumConnections) assert.Len(t, supplier.GetAllConns(), testCase.ExpectedNumConnections)
}) })
} }
} }
func makeSqlSettings(driver string) *model.SqlSettings {
switch driver {
case model.DATABASE_DRIVER_POSTGRES:
return storetest.MakeSqlSettings(driver)
case model.DATABASE_DRIVER_MYSQL:
return storetest.MakeSqlSettings(driver)
case model.DATABASE_DRIVER_SQLITE:
return makeSqliteSettings()
}
return nil
}
func makeSqliteSettings() *model.SqlSettings {
driverName := model.DATABASE_DRIVER_SQLITE
dataSource := ":memory:"
maxIdleConns := 1
connMaxLifetimeMilliseconds := 3600000
maxOpenConns := 1
queryTimeout := 5
return &model.SqlSettings{
DriverName: &driverName,
DataSource: &dataSource,
MaxIdleConns: &maxIdleConns,
ConnMaxLifetimeMilliseconds: &connMaxLifetimeMilliseconds,
MaxOpenConns: &maxOpenConns,
QueryTimeout: &queryTimeout,
}
}

Просмотреть файл

@@ -54,6 +54,7 @@ type Store interface {
UnlockFromMaster() UnlockFromMaster()
DropAllTables() DropAllTables()
GetCurrentSchemaVersion() string GetCurrentSchemaVersion() string
GetDbVersion() (string, error)
TotalMasterDbConnections() int TotalMasterDbConnections() int
TotalReadDbConnections() int TotalReadDbConnections() int
TotalSearchDbConnections() int TotalSearchDbConnections() int

Просмотреть файл

@@ -379,6 +379,27 @@ func (_m *SqlStore) GetCurrentSchemaVersion() string {
return r0 return r0
} }
// GetDbVersion provides a mock function with given fields:
func (_m *SqlStore) GetDbVersion() (string, error) {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetMaster provides a mock function with given fields: // GetMaster provides a mock function with given fields:
func (_m *SqlStore) GetMaster() *gorp.DbMap { func (_m *SqlStore) GetMaster() *gorp.DbMap {
ret := _m.Called() ret := _m.Called()

Просмотреть файл

@@ -232,6 +232,27 @@ func (_m *Store) GetCurrentSchemaVersion() string {
return r0 return r0
} }
// GetDbVersion provides a mock function with given fields:
func (_m *Store) GetDbVersion() (string, error) {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Group provides a mock function with given fields: // Group provides a mock function with given fields:
func (_m *Store) Group() store.GroupStore { func (_m *Store) Group() store.GroupStore {
ret := _m.Called() ret := _m.Called()

Просмотреть файл

@@ -87,6 +87,7 @@ func (s *Store) Close() { /* do nothing */ }
func (s *Store) LockToMaster() { /* do nothing */ } func (s *Store) LockToMaster() { /* do nothing */ }
func (s *Store) UnlockFromMaster() { /* do nothing */ } func (s *Store) UnlockFromMaster() { /* do nothing */ }
func (s *Store) DropAllTables() { /* do nothing */ } func (s *Store) DropAllTables() { /* do nothing */ }
func (s *Store) GetDbVersion() (string, error) { return "", nil }
func (s *Store) TotalMasterDbConnections() int { return 1 } func (s *Store) TotalMasterDbConnections() int { return 1 }
func (s *Store) TotalReadDbConnections() int { return 1 } func (s *Store) TotalReadDbConnections() int { return 1 }
func (s *Store) TotalSearchDbConnections() int { return 1 } func (s *Store) TotalSearchDbConnections() int { return 1 }