Use state_change for measuring elapsed time
This commit is contained in:
parent
bb7ddf2bc5
commit
3a89201a94
3 changed files with 35 additions and 40 deletions
|
@ -42,7 +42,7 @@ func (db *Db) Disconnect() {
|
||||||
|
|
||||||
// Sessions connects to the database and returns current sessions
|
// Sessions connects to the database and returns current sessions
|
||||||
func (db *Db) Sessions() (sessions []Session) {
|
func (db *Db) Sessions() (sessions []Session) {
|
||||||
query := `select pid as pid, usename as user, datname as db, host(client_addr)::text || ':' || client_port::text as client, state as state, substring(query from 1 for ` + strconv.Itoa(maxQueryLength) + `) as query, coalesce(extract(epoch from now() - backend_start), 0) as "backendDuration", coalesce(extract(epoch from now() - xact_start), 0) as "xactDuration", coalesce(extract(epoch from now() - query_start), 0) as "queryDuration" from pg_catalog.pg_stat_activity where pid <> pg_backend_pid();`
|
query := `select pid as pid, usename as user, datname as db, host(client_addr)::text || ':' || client_port::text as client, state as state, substring(query from 1 for ` + strconv.Itoa(maxQueryLength) + `) as query, coalesce(extract(epoch from now() - state_change), 0) as "stateDuration" from pg_catalog.pg_stat_activity where pid <> pg_backend_pid();`
|
||||||
rows, err := db.conn.Query(query)
|
rows, err := db.conn.Query(query)
|
||||||
Panic(err)
|
Panic(err)
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
@ -50,12 +50,12 @@ func (db *Db) Sessions() (sessions []Session) {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var pid sql.NullInt64
|
var pid sql.NullInt64
|
||||||
var user, db, client, state, query sql.NullString
|
var user, db, client, state, query sql.NullString
|
||||||
var backendDuration, xactDuration, queryDuration float64
|
var stateDuration float64
|
||||||
err := rows.Scan(&pid, &user, &db, &client, &state, &query, &backendDuration, &xactDuration, &queryDuration)
|
err := rows.Scan(&pid, &user, &db, &client, &state, &query, &stateDuration)
|
||||||
Panic(err)
|
Panic(err)
|
||||||
|
|
||||||
if pid.Valid && user.Valid && db.Valid && client.Valid && state.Valid && query.Valid {
|
if pid.Valid && user.Valid && db.Valid && client.Valid && state.Valid && query.Valid {
|
||||||
sessions = append(sessions, NewSession(pid.Int64, user.String, db.String, client.String, state.String, query.String, backendDuration, xactDuration, queryDuration))
|
sessions = append(sessions, NewSession(pid.Int64, user.String, db.String, client.String, state.String, query.String, stateDuration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,29 +7,25 @@ import (
|
||||||
|
|
||||||
// Session represents a PostgreSQL backend
|
// Session represents a PostgreSQL backend
|
||||||
type Session struct {
|
type Session struct {
|
||||||
Pid int64
|
Pid int64
|
||||||
User string
|
User string
|
||||||
Db string
|
Db string
|
||||||
Client string
|
Client string
|
||||||
State string
|
State string
|
||||||
Query string
|
Query string
|
||||||
BackendDuration float64
|
StateDuration float64
|
||||||
XactDuration float64
|
|
||||||
QueryDuration float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSession instanciates a Session
|
// NewSession instanciates a Session
|
||||||
func NewSession(pid int64, user string, db string, client string, state string, query string, backendDuration float64, xactDuration float64, queryDuration float64) Session {
|
func NewSession(pid int64, user string, db string, client string, state string, query string, stateDuration float64) Session {
|
||||||
return Session{
|
return Session{
|
||||||
Pid: pid,
|
Pid: pid,
|
||||||
User: user,
|
User: user,
|
||||||
Db: db,
|
Db: db,
|
||||||
Client: client,
|
Client: client,
|
||||||
State: state,
|
State: state,
|
||||||
Query: query,
|
Query: query,
|
||||||
BackendDuration: backendDuration,
|
StateDuration: stateDuration,
|
||||||
XactDuration: xactDuration,
|
|
||||||
QueryDuration: queryDuration,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,17 +47,19 @@ func (s Session) String() string {
|
||||||
if s.State != "" {
|
if s.State != "" {
|
||||||
output = append(output, fmt.Sprintf("state=%s", s.State))
|
output = append(output, fmt.Sprintf("state=%s", s.State))
|
||||||
}
|
}
|
||||||
if s.BackendDuration != 0 {
|
if s.StateDuration != 0 {
|
||||||
output = append(output, fmt.Sprintf("backend_duration=%f", s.BackendDuration))
|
output = append(output, fmt.Sprintf("state_duration=%f", s.StateDuration))
|
||||||
}
|
}
|
||||||
if s.XactDuration != 0 {
|
if s.Query != "" && !s.IsIdle() {
|
||||||
output = append(output, fmt.Sprintf("xact_duration=%f", s.XactDuration))
|
|
||||||
}
|
|
||||||
if s.QueryDuration != 0 {
|
|
||||||
output = append(output, fmt.Sprintf("query_duration=%f", s.QueryDuration))
|
|
||||||
}
|
|
||||||
if s.Query != "" {
|
|
||||||
output = append(output, fmt.Sprintf("query=%s", s.Query))
|
output = append(output, fmt.Sprintf("query=%s", s.Query))
|
||||||
}
|
}
|
||||||
return strings.Join(output, " ")
|
return strings.Join(output, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsIdle returns true when a session is doing nothing
|
||||||
|
func (s Session) IsIdle() bool {
|
||||||
|
if s.State == "idle" || s.State == "idle in transaction" || s.State == "idle in transaction (aborted)" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -67,11 +67,11 @@ func (t *Terminator) terminate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// activeSessions returns a list of active sessions
|
// activeSessions returns a list of active sessions
|
||||||
// A session is active when state is "active" and backend has started before elapsed
|
// A session is active when state is "active" and state has changed before elapsed seconds
|
||||||
// seconds
|
// seconds
|
||||||
func activeSessions(sessions []base.Session, elapsed float64) (result []base.Session) {
|
func activeSessions(sessions []base.Session, elapsed float64) (result []base.Session) {
|
||||||
for _, session := range sessions {
|
for _, session := range sessions {
|
||||||
if session.State == "active" && session.QueryDuration > elapsed {
|
if session.State == "active" && session.StateDuration > elapsed {
|
||||||
result = append(result, session)
|
result = append(result, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,14 +79,11 @@ func activeSessions(sessions []base.Session, elapsed float64) (result []base.Ses
|
||||||
}
|
}
|
||||||
|
|
||||||
// idleSessions returns a list of idle sessions
|
// idleSessions returns a list of idle sessions
|
||||||
// A sessions is idle when state is "idle" and backend has started before elapsed seconds
|
// A sessions is idle when state is "idle", "idle in transaction" or "idle in transaction
|
||||||
// and when state is "idle in transaction" or "idle in transaction (aborted)" and
|
// (aborted)"and state has changed before elapsed seconds
|
||||||
// transaction has started before elapsed seconds
|
|
||||||
func idleSessions(sessions []base.Session, elapsed float64) (result []base.Session) {
|
func idleSessions(sessions []base.Session, elapsed float64) (result []base.Session) {
|
||||||
for _, session := range sessions {
|
for _, session := range sessions {
|
||||||
if session.State == "idle" && session.BackendDuration > elapsed {
|
if session.IsIdle() && session.StateDuration > elapsed {
|
||||||
result = append(result, session)
|
|
||||||
} else if (session.State == "idle in transaction" || session.State == "idle in transaction (aborted)") && session.XactDuration > elapsed {
|
|
||||||
result = append(result, session)
|
result = append(result, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue