[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>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f6f025aeaa
Коммит
698b4b6934
@@ -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 }
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user