mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-01 03:03:10 -06:00
More GH comments changes
- Move comments to SQL statements - Shrink interface, add struct for stats - No fatal errors, use defaults
This commit is contained in:
parent
5bb0b56029
commit
27c76e3f89
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/dendrite/userapi/storage/tables"
|
||||
"github.com/matrix-org/dendrite/userapi/types"
|
||||
)
|
||||
|
||||
type Profile interface {
|
||||
|
|
@ -34,6 +35,7 @@ type Profile interface {
|
|||
|
||||
type Database interface {
|
||||
Profile
|
||||
Statistics
|
||||
GetAccountByPassword(ctx context.Context, localpart, plaintextPassword string) (*api.Account, error)
|
||||
// CreateAccount makes a new account with the given login name and password, and creates an empty profile
|
||||
// for this account. If no password is supplied, the account will be a passwordless account. If the
|
||||
|
|
@ -107,14 +109,10 @@ type Database interface {
|
|||
GetPushers(ctx context.Context, localpart string) ([]api.Pusher, error)
|
||||
RemovePusher(ctx context.Context, appid, pushkey, localpart string) error
|
||||
RemovePushers(ctx context.Context, appid, pushkey string) error
|
||||
}
|
||||
|
||||
AllUsers(ctx context.Context) (result int64, err error)
|
||||
NonBridgedUsers(ctx context.Context) (result int64, err error)
|
||||
RegisteredUserByType(ctx context.Context) (map[string]int64, error)
|
||||
DailyUsers(ctx context.Context) (result int64, err error)
|
||||
MonthlyUsers(ctx context.Context) (result int64, err error)
|
||||
R30Users(ctx context.Context) (map[string]int64, error)
|
||||
R30UsersV2(ctx context.Context) (map[string]int64, error)
|
||||
type Statistics interface {
|
||||
UserStatistics(ctx context.Context) (*types.UserStatistics, *types.DatabaseEngine, error)
|
||||
}
|
||||
|
||||
// Err3PIDInUse is the error returned when trying to save an association involving
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ import (
|
|||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/userapi/storage/tables"
|
||||
"github.com/matrix-org/dendrite/userapi/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
|
@ -48,6 +48,12 @@ const countUsersLastSeenAfterSQL = "" +
|
|||
" GROUP BY localpart" +
|
||||
" ) u"
|
||||
|
||||
/*
|
||||
R30Users counts the number of 30 day retained users, defined as:
|
||||
- Users who have created their accounts more than 30 days ago
|
||||
- Where last seen at most 30 days ago
|
||||
- Where account creation and last_seen are > 30 days apart
|
||||
*/
|
||||
const countR30UsersSQL = `
|
||||
SELECT platform, COUNT(*) FROM (
|
||||
SELECT users.localpart, platform, users.created_ts, MAX(uip.last_seen_ts)
|
||||
|
|
@ -75,6 +81,11 @@ SELECT platform, COUNT(*) FROM (
|
|||
) u GROUP BY PLATFORM
|
||||
`
|
||||
|
||||
/*
|
||||
R30UsersV2 counts the number of 30 day retained users, defined as users that:
|
||||
- Appear more than once in the past 60 days
|
||||
- Have more than 30 days between the most and least recent appearances that occurred in the past 60 days.
|
||||
*/
|
||||
const countR30UsersV2SQL = `
|
||||
SELECT
|
||||
client_type,
|
||||
|
|
@ -140,6 +151,8 @@ ON CONFLICT (localpart, device_id, timestamp) DO NOTHING
|
|||
;
|
||||
`
|
||||
|
||||
const queryDBEngineVersion = "SHOW server_version;"
|
||||
|
||||
type statsStatements struct {
|
||||
serverName gomatrixserverlib.ServerName
|
||||
lastUpdate time.Time
|
||||
|
|
@ -149,6 +162,7 @@ type statsStatements struct {
|
|||
updateUserDailyVisitsStmt *sql.Stmt
|
||||
countUserByAccountTypeStmt *sql.Stmt
|
||||
countRegisteredUserByTypeStmt *sql.Stmt
|
||||
dbEngineVersionStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func NewPostgresStatsTable(db *sql.DB, serverName gomatrixserverlib.ServerName) (tables.StatsTable, error) {
|
||||
|
|
@ -169,6 +183,7 @@ func NewPostgresStatsTable(db *sql.DB, serverName gomatrixserverlib.ServerName)
|
|||
{&s.updateUserDailyVisitsStmt, updateUserDailyVisitsSQL},
|
||||
{&s.countUserByAccountTypeStmt, countUserByAccountTypeSQL},
|
||||
{&s.countRegisteredUserByTypeStmt, countRegisteredUserByTypeStmt},
|
||||
{&s.dbEngineVersionStmt, queryDBEngineVersion},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +199,7 @@ func (s *statsStatements) startTimers() {
|
|||
time.AfterFunc(time.Minute*5, updateStatsFunc)
|
||||
}
|
||||
|
||||
func (s *statsStatements) AllUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) allUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countUserByAccountTypeStmt)
|
||||
err = stmt.QueryRowContext(ctx,
|
||||
pq.Int64Array{1, 2, 3, 4},
|
||||
|
|
@ -192,7 +207,7 @@ func (s *statsStatements) AllUsers(ctx context.Context, txn *sql.Tx) (result int
|
|||
return
|
||||
}
|
||||
|
||||
func (s *statsStatements) NonBridgedUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) nonBridgedUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countUserByAccountTypeStmt)
|
||||
err = stmt.QueryRowContext(ctx,
|
||||
pq.Int64Array{1, 2, 3},
|
||||
|
|
@ -200,7 +215,7 @@ func (s *statsStatements) NonBridgedUsers(ctx context.Context, txn *sql.Tx) (res
|
|||
return
|
||||
}
|
||||
|
||||
func (s *statsStatements) RegisteredUserByType(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
func (s *statsStatements) registeredUserByType(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countRegisteredUserByTypeStmt)
|
||||
registeredAfter := time.Now().AddDate(0, 0, -1)
|
||||
|
||||
|
|
@ -225,7 +240,7 @@ func (s *statsStatements) RegisteredUserByType(ctx context.Context, txn *sql.Tx)
|
|||
return result, rows.Err()
|
||||
}
|
||||
|
||||
func (s *statsStatements) DailyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) dailyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countUsersLastSeenAfterStmt)
|
||||
lastSeenAfter := time.Now().AddDate(0, 0, -1)
|
||||
err = stmt.QueryRowContext(ctx,
|
||||
|
|
@ -234,7 +249,7 @@ func (s *statsStatements) DailyUsers(ctx context.Context, txn *sql.Tx) (result i
|
|||
return
|
||||
}
|
||||
|
||||
func (s *statsStatements) MonthlyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) monthlyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countUsersLastSeenAfterStmt)
|
||||
lastSeenAfter := time.Now().AddDate(0, 0, -30)
|
||||
err = stmt.QueryRowContext(ctx,
|
||||
|
|
@ -243,12 +258,13 @@ func (s *statsStatements) MonthlyUsers(ctx context.Context, txn *sql.Tx) (result
|
|||
return
|
||||
}
|
||||
|
||||
/* R30Users counts the number of 30 day retained users, defined as:
|
||||
/*
|
||||
R30Users counts the number of 30 day retained users, defined as:
|
||||
- Users who have created their accounts more than 30 days ago
|
||||
- Where last seen at most 30 days ago
|
||||
- Where account creation and last_seen are > 30 days apart
|
||||
*/
|
||||
func (s *statsStatements) R30Users(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
func (s *statsStatements) r30Users(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countR30UsersStmt)
|
||||
lastSeenAfter := time.Now().AddDate(0, 0, -30)
|
||||
diff := time.Hour * 24 * 30
|
||||
|
|
@ -279,11 +295,12 @@ func (s *statsStatements) R30Users(ctx context.Context, txn *sql.Tx) (map[string
|
|||
return result, rows.Err()
|
||||
}
|
||||
|
||||
/* R30UsersV2 counts the number of 30 day retained users, defined as users that:
|
||||
/*
|
||||
R30UsersV2 counts the number of 30 day retained users, defined as users that:
|
||||
- Appear more than once in the past 60 days
|
||||
- Have more than 30 days between the most and least recent appearances that occurred in the past 60 days.
|
||||
*/
|
||||
func (s *statsStatements) R30UsersV2(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
func (s *statsStatements) r30UsersV2(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countR30UsersV2Stmt)
|
||||
sixtyDaysAgo := time.Now().AddDate(0, 0, -60)
|
||||
thirtyDaysAgo := time.Now().AddDate(0, 0, -30)
|
||||
|
|
@ -322,6 +339,59 @@ func (s *statsStatements) R30UsersV2(ctx context.Context, txn *sql.Tx) (map[stri
|
|||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// UserStatistics collects some information about users on this instance.
|
||||
// Returns the stats itself as well as the database engine version and type.
|
||||
// On error, returns the stats collected up to the error.
|
||||
func (s *statsStatements) UserStatistics(ctx context.Context, txn *sql.Tx) (*types.UserStatistics, *types.DatabaseEngine, error) {
|
||||
var (
|
||||
stats = &types.UserStatistics{
|
||||
R30UsersV2: map[string]int64{
|
||||
"ios": 0,
|
||||
"android": 0,
|
||||
"web": 0,
|
||||
"electron": 0,
|
||||
"all": 0,
|
||||
},
|
||||
R30Users: map[string]int64{},
|
||||
RegisteredUsersByType: map[string]int64{},
|
||||
}
|
||||
dbEngine = &types.DatabaseEngine{Engine: "Postgres", Version: "unknown"}
|
||||
err error
|
||||
)
|
||||
stats.AllUsers, err = s.allUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.DailyUsers, err = s.dailyUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.MonthlyUsers, err = s.monthlyUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.R30Users, err = s.r30Users(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.R30UsersV2, err = s.r30UsersV2(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.NonBridgedUsers, err = s.nonBridgedUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.RegisteredUsersByType, err = s.registeredUserByType(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
|
||||
stmt := sqlutil.TxStmt(txn, s.dbEngineVersionStmt)
|
||||
err = stmt.QueryRowContext(ctx).Scan(&dbEngine.Version)
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
|
||||
func (s *statsStatements) updateUserDailyVisits(ctx context.Context, txn *sql.Tx) error {
|
||||
stmt := sqlutil.TxStmt(txn, s.updateUserDailyVisitsStmt)
|
||||
_ = stmt
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/userapi/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
|
|
@ -773,24 +774,7 @@ func (d *Database) RemovePushers(
|
|||
})
|
||||
}
|
||||
|
||||
func (d *Database) AllUsers(ctx context.Context) (result int64, err error) {
|
||||
return d.Stats.AllUsers(ctx, nil)
|
||||
}
|
||||
func (d *Database) NonBridgedUsers(ctx context.Context) (result int64, err error) {
|
||||
return d.Stats.NonBridgedUsers(ctx, nil)
|
||||
}
|
||||
func (d *Database) RegisteredUserByType(ctx context.Context) (map[string]int64, error) {
|
||||
return d.Stats.RegisteredUserByType(ctx, nil)
|
||||
}
|
||||
func (d *Database) DailyUsers(ctx context.Context) (result int64, err error) {
|
||||
return d.Stats.DailyUsers(ctx, nil)
|
||||
}
|
||||
func (d *Database) MonthlyUsers(ctx context.Context) (result int64, err error) {
|
||||
return d.Stats.MonthlyUsers(ctx, nil)
|
||||
}
|
||||
func (d *Database) R30Users(ctx context.Context) (map[string]int64, error) {
|
||||
return d.Stats.R30Users(ctx, nil)
|
||||
}
|
||||
func (d *Database) R30UsersV2(ctx context.Context) (map[string]int64, error) {
|
||||
return d.Stats.R30UsersV2(ctx, nil)
|
||||
// UserStatistics populates types.UserStatistics, used in reports.
|
||||
func (d *Database) UserStatistics(ctx context.Context) (*types.UserStatistics, *types.DatabaseEngine, error) {
|
||||
return d.Stats.UserStatistics(ctx, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/userapi/storage/tables"
|
||||
"github.com/matrix-org/dendrite/userapi/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
|
@ -47,6 +48,12 @@ const countUsersLastSeenAfterSQL = "" +
|
|||
" GROUP BY localpart" +
|
||||
" ) u"
|
||||
|
||||
/*
|
||||
R30Users counts the number of 30 day retained users, defined as:
|
||||
- Users who have created their accounts more than 30 days ago
|
||||
- Where last seen at most 30 days ago
|
||||
- Where account creation and last_seen are > 30 days apart
|
||||
*/
|
||||
const countR30UsersSQL = `
|
||||
SELECT platform, COUNT(*) FROM (
|
||||
SELECT users.localpart, platform, users.created_ts, MAX(uip.last_seen_ts)
|
||||
|
|
@ -74,6 +81,11 @@ SELECT platform, COUNT(*) FROM (
|
|||
) u GROUP BY PLATFORM
|
||||
`
|
||||
|
||||
/*
|
||||
R30UsersV2 counts the number of 30 day retained users, defined as users that:
|
||||
- Appear more than once in the past 60 days
|
||||
- Have more than 30 days between the most and least recent appearances that occurred in the past 60 days.
|
||||
*/
|
||||
const countR30UsersV2SQL = `
|
||||
SELECT
|
||||
client_type,
|
||||
|
|
@ -139,6 +151,8 @@ ON CONFLICT (localpart, device_id, timestamp) DO NOTHING
|
|||
;
|
||||
`
|
||||
|
||||
const queryDBEngineVersion = "select sqlite_version();"
|
||||
|
||||
type statsStatements struct {
|
||||
serverName gomatrixserverlib.ServerName
|
||||
db *sql.DB
|
||||
|
|
@ -149,6 +163,7 @@ type statsStatements struct {
|
|||
updateUserDailyVisitsStmt *sql.Stmt
|
||||
countUserByAccountTypeStmt *sql.Stmt
|
||||
countRegisteredUserByTypeStmt *sql.Stmt
|
||||
dbEngineVersionStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func NewSQLiteStatsTable(db *sql.DB, serverName gomatrixserverlib.ServerName) (tables.StatsTable, error) {
|
||||
|
|
@ -170,6 +185,7 @@ func NewSQLiteStatsTable(db *sql.DB, serverName gomatrixserverlib.ServerName) (t
|
|||
{&s.updateUserDailyVisitsStmt, updateUserDailyVisitsSQL},
|
||||
{&s.countUserByAccountTypeStmt, countUserByAccountTypeSQL},
|
||||
{&s.countRegisteredUserByTypeStmt, countRegisteredUserByTypeStmt},
|
||||
{&s.dbEngineVersionStmt, queryDBEngineVersion},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +201,7 @@ func (s *statsStatements) startTimers() {
|
|||
time.AfterFunc(time.Minute*5, updateStatsFunc)
|
||||
}
|
||||
|
||||
func (s *statsStatements) AllUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) allUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
query := strings.Replace(countUserByAccountTypeSQL, "($1)", sqlutil.QueryVariadic(4), 1)
|
||||
queryStmt, err := s.db.Prepare(query)
|
||||
if err != nil {
|
||||
|
|
@ -198,7 +214,7 @@ func (s *statsStatements) AllUsers(ctx context.Context, txn *sql.Tx) (result int
|
|||
return
|
||||
}
|
||||
|
||||
func (s *statsStatements) NonBridgedUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) nonBridgedUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
query := strings.Replace(countUserByAccountTypeSQL, "($1)", sqlutil.QueryVariadic(3), 1)
|
||||
queryStmt, err := s.db.Prepare(query)
|
||||
if err != nil {
|
||||
|
|
@ -211,7 +227,7 @@ func (s *statsStatements) NonBridgedUsers(ctx context.Context, txn *sql.Tx) (res
|
|||
return
|
||||
}
|
||||
|
||||
func (s *statsStatements) RegisteredUserByType(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
func (s *statsStatements) registeredUserByType(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countRegisteredUserByTypeStmt)
|
||||
registeredAfter := time.Now().AddDate(0, 0, -1)
|
||||
|
||||
|
|
@ -236,7 +252,7 @@ func (s *statsStatements) RegisteredUserByType(ctx context.Context, txn *sql.Tx)
|
|||
return result, rows.Err()
|
||||
}
|
||||
|
||||
func (s *statsStatements) DailyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) dailyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countUsersLastSeenAfterStmt)
|
||||
lastSeenAfter := time.Now().AddDate(0, 0, -1)
|
||||
err = stmt.QueryRowContext(ctx,
|
||||
|
|
@ -245,7 +261,7 @@ func (s *statsStatements) DailyUsers(ctx context.Context, txn *sql.Tx) (result i
|
|||
return
|
||||
}
|
||||
|
||||
func (s *statsStatements) MonthlyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
func (s *statsStatements) monthlyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countUsersLastSeenAfterStmt)
|
||||
lastSeenAfter := time.Now().AddDate(0, 0, -30)
|
||||
err = stmt.QueryRowContext(ctx,
|
||||
|
|
@ -259,7 +275,7 @@ func (s *statsStatements) MonthlyUsers(ctx context.Context, txn *sql.Tx) (result
|
|||
- Where last seen at most 30 days ago
|
||||
- Where account creation and last_seen are > 30 days apart
|
||||
*/
|
||||
func (s *statsStatements) R30Users(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
func (s *statsStatements) r30Users(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countR30UsersStmt)
|
||||
lastSeenAfter := time.Now().AddDate(0, 0, -30)
|
||||
diff := time.Hour * 24 * 30
|
||||
|
|
@ -295,7 +311,7 @@ func (s *statsStatements) R30Users(ctx context.Context, txn *sql.Tx) (map[string
|
|||
- Appear more than once in the past 60 days
|
||||
- Have more than 30 days between the most and least recent appearances that occurred in the past 60 days.
|
||||
*/
|
||||
func (s *statsStatements) R30UsersV2(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
func (s *statsStatements) r30UsersV2(ctx context.Context, txn *sql.Tx) (map[string]int64, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.countR30UsersV2Stmt)
|
||||
sixtyDaysAgo := time.Now().AddDate(0, 0, -60)
|
||||
thirtyDaysAgo := time.Now().AddDate(0, 0, -30)
|
||||
|
|
@ -334,6 +350,59 @@ func (s *statsStatements) R30UsersV2(ctx context.Context, txn *sql.Tx) (map[stri
|
|||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// UserStatistics collects some information about users on this instance.
|
||||
// Returns the stats itself as well as the database engine version and type.
|
||||
// On error, returns the stats collected up to the error.
|
||||
func (s *statsStatements) UserStatistics(ctx context.Context, txn *sql.Tx) (*types.UserStatistics, *types.DatabaseEngine, error) {
|
||||
var (
|
||||
stats = &types.UserStatistics{
|
||||
R30UsersV2: map[string]int64{
|
||||
"ios": 0,
|
||||
"android": 0,
|
||||
"web": 0,
|
||||
"electron": 0,
|
||||
"all": 0,
|
||||
},
|
||||
R30Users: map[string]int64{},
|
||||
RegisteredUsersByType: map[string]int64{},
|
||||
}
|
||||
dbEngine = &types.DatabaseEngine{Engine: "SQLite", Version: "unknown"}
|
||||
err error
|
||||
)
|
||||
stats.AllUsers, err = s.allUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.DailyUsers, err = s.dailyUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.MonthlyUsers, err = s.monthlyUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.R30Users, err = s.r30Users(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.R30UsersV2, err = s.r30UsersV2(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.NonBridgedUsers, err = s.nonBridgedUsers(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
stats.RegisteredUsersByType, err = s.registeredUserByType(ctx, txn)
|
||||
if err != nil {
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
|
||||
stmt := sqlutil.TxStmt(txn, s.dbEngineVersionStmt)
|
||||
err = stmt.QueryRowContext(ctx).Scan(&dbEngine.Version)
|
||||
return stats, dbEngine, err
|
||||
}
|
||||
|
||||
func (s *statsStatements) updateUserDailyVisits(ctx context.Context, txn *sql.Tx) error {
|
||||
stmt := sqlutil.TxStmt(txn, s.updateUserDailyVisitsStmt)
|
||||
_ = stmt
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/dendrite/userapi/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
|
|
@ -113,13 +114,7 @@ type NotificationTable interface {
|
|||
}
|
||||
|
||||
type StatsTable interface {
|
||||
AllUsers(ctx context.Context, txn *sql.Tx) (result int64, err error)
|
||||
NonBridgedUsers(ctx context.Context, txn *sql.Tx) (result int64, err error)
|
||||
RegisteredUserByType(ctx context.Context, txn *sql.Tx) (map[string]int64, error)
|
||||
DailyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error)
|
||||
MonthlyUsers(ctx context.Context, txn *sql.Tx) (result int64, err error)
|
||||
R30Users(ctx context.Context, txn *sql.Tx) (map[string]int64, error)
|
||||
R30UsersV2(ctx context.Context, txn *sql.Tx) (map[string]int64, error)
|
||||
UserStatistics(ctx context.Context, txn *sql.Tx) (*types.UserStatistics, *types.DatabaseEngine, error)
|
||||
}
|
||||
|
||||
type NotificationFilter uint32
|
||||
|
|
|
|||
30
userapi/types/statistics.go
Normal file
30
userapi/types/statistics.go
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
type UserStatistics struct {
|
||||
RegisteredUsersByType map[string]int64
|
||||
R30Users map[string]int64
|
||||
R30UsersV2 map[string]int64
|
||||
AllUsers int64
|
||||
NonBridgedUsers int64
|
||||
DailyUsers int64
|
||||
MonthlyUsers int64
|
||||
}
|
||||
|
||||
type DatabaseEngine struct {
|
||||
Engine string
|
||||
Version string
|
||||
}
|
||||
|
|
@ -25,7 +25,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/storage"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -38,7 +37,7 @@ type phoneHomeStats struct {
|
|||
serverName gomatrixserverlib.ServerName
|
||||
startTime time.Time
|
||||
cfg *config.Dendrite
|
||||
db storage.Database
|
||||
db storage.Statistics
|
||||
isMonolith bool
|
||||
client *http.Client
|
||||
}
|
||||
|
|
@ -48,13 +47,13 @@ type timestampToRUUsage struct {
|
|||
usage syscall.Rusage
|
||||
}
|
||||
|
||||
func StartPhoneHomeCollector(startTime time.Time, cfg *config.Dendrite, userDB storage.Database) {
|
||||
func StartPhoneHomeCollector(startTime time.Time, cfg *config.Dendrite, statsDB storage.Statistics) {
|
||||
|
||||
p := phoneHomeStats{
|
||||
startTime: startTime,
|
||||
serverName: cfg.Global.ServerName,
|
||||
cfg: cfg,
|
||||
db: userDB,
|
||||
db: statsDB,
|
||||
isMonolith: cfg.IsMonolith,
|
||||
client: &http.Client{
|
||||
Timeout: time.Second * 30,
|
||||
|
|
@ -91,8 +90,7 @@ func (p *phoneHomeStats) collect() {
|
|||
// cpu and memory usage information
|
||||
err := getMemoryStats(p)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to get memory/cpu stats")
|
||||
return
|
||||
logrus.WithError(err).Error("unable to get memory/cpu stats, using defaults")
|
||||
}
|
||||
|
||||
// configuration information
|
||||
|
|
@ -109,35 +107,6 @@ func (p *phoneHomeStats) collect() {
|
|||
p.stats["log_level"] = "info"
|
||||
}
|
||||
|
||||
// database configuration
|
||||
db, err := sqlutil.Open(&p.cfg.UserAPI.AccountDatabase)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to connect to database")
|
||||
return
|
||||
}
|
||||
defer internal.CloseAndLogIfError(context.Background(), db, "phoneHomeStats.collect(): failed to close database connection")
|
||||
|
||||
dbVersion := "unknown"
|
||||
dbEngine := "unknown"
|
||||
switch {
|
||||
case p.cfg.UserAPI.AccountDatabase.ConnectionString.IsSQLite():
|
||||
dbEngine = "SQLite"
|
||||
row := db.QueryRow("select sqlite_version();")
|
||||
if err = row.Scan(&dbVersion); err != nil {
|
||||
logrus.WithError(err).Error("unable to query version")
|
||||
return
|
||||
}
|
||||
case p.cfg.UserAPI.AccountDatabase.ConnectionString.IsPostgres():
|
||||
dbEngine = "Postgres"
|
||||
row := db.QueryRow("SHOW server_version;")
|
||||
if err = row.Scan(&dbVersion); err != nil {
|
||||
logrus.WithError(err).Error("unable to query version")
|
||||
return
|
||||
}
|
||||
}
|
||||
p.stats["database_engine"] = dbEngine
|
||||
p.stats["database_server_version"] = dbVersion
|
||||
|
||||
// message and room stats
|
||||
// TODO: Find a solution to actually set these values
|
||||
p.stats["total_room_count"] = 0
|
||||
|
|
@ -146,57 +115,24 @@ func (p *phoneHomeStats) collect() {
|
|||
p.stats["daily_e2ee_messages"] = 0
|
||||
p.stats["daily_sent_e2ee_messages"] = 0
|
||||
|
||||
count, err := p.db.AllUsers(ctx)
|
||||
// user stats and DB engine
|
||||
userStats, db, err := p.db.UserStatistics(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query AllUsers")
|
||||
return
|
||||
logrus.WithError(err).Error("unable to query userstats, using default values")
|
||||
}
|
||||
p.stats["total_users"] = count
|
||||
|
||||
count, err = p.db.NonBridgedUsers(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query NonBridgedUsers")
|
||||
return
|
||||
}
|
||||
p.stats["total_nonbridged_users"] = count
|
||||
|
||||
count, err = p.db.DailyUsers(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query DailyUsers")
|
||||
return
|
||||
}
|
||||
p.stats["daily_active_users"] = count
|
||||
|
||||
count, err = p.db.MonthlyUsers(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query MonthlyUsers")
|
||||
return
|
||||
}
|
||||
p.stats["monthly_active_users"] = count
|
||||
|
||||
res, err := p.db.RegisteredUserByType(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query RegisteredUserByType")
|
||||
return
|
||||
}
|
||||
for t, c := range res {
|
||||
p.stats["database_engine"] = db.Engine
|
||||
p.stats["database_server_version"] = db.Version
|
||||
p.stats["total_users"] = userStats.AllUsers
|
||||
p.stats["total_nonbridged_users"] = userStats.NonBridgedUsers
|
||||
p.stats["daily_active_users"] = userStats.DailyUsers
|
||||
p.stats["monthly_active_users"] = userStats.MonthlyUsers
|
||||
for t, c := range userStats.RegisteredUsersByType {
|
||||
p.stats["daily_user_type_"+t] = c
|
||||
}
|
||||
|
||||
res, err = p.db.R30Users(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query R30Users")
|
||||
return
|
||||
}
|
||||
for t, c := range res {
|
||||
for t, c := range userStats.R30Users {
|
||||
p.stats["r30_users_"+t] = c
|
||||
}
|
||||
res, err = p.db.R30UsersV2(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("unable to query R30UsersV2")
|
||||
return
|
||||
}
|
||||
for t, c := range res {
|
||||
for t, c := range userStats.R30UsersV2 {
|
||||
p.stats["r30v2_users_"+t] = c
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue