-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: collect MV_ACTIVE_DISTRIBUTED_TRANSACTIONS
- add exception patterns when collect processlist
- Loading branch information
1 parent
8c72ec7
commit 39d8fdd
Showing
9 changed files
with
286 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package collector | ||
|
||
import ( | ||
"github.com/jmoiron/sqlx" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"singlestore_exporter/log" | ||
"strings" | ||
) | ||
|
||
type ActiveDistributedTransactionsView struct { | ||
TableSchema string `db:"TABLE_SCHEMA"` | ||
TableName string `db:"TABLE_NAME"` | ||
} | ||
|
||
type ActiveDistributedTransactions struct { | ||
PartitionName string `db:"PARTITION_NAME"` | ||
Count int `db:"COUNT"` | ||
TimeMax int `db:"TIME_MAX"` | ||
RowLocksTotal int `db:"ROW_LOCKS_TOTAL"` | ||
Database string | ||
} | ||
|
||
const ( | ||
activeTransaction = "active_transaction" | ||
|
||
infoSchemaActiveDistributedTransactionsViewExistsQuery = `SELECT TABLE_SCHEMA, TABLE_NAME | ||
FROM information_schema.TABLES | ||
WHERE TABLE_SCHEMA = 'information_schema' AND TABLE_NAME LIKE 'MV_ACTIVE_DISTRIBUTED_TRANSACTIONS'` | ||
|
||
infoSchemaActiveDistributedTransactionsQuery = `SELECT | ||
NVL(DATABASE_NAME, '') AS PARTITION_NAME, | ||
COUNT(*) AS COUNT, | ||
MAX(TIMESTAMPDIFF(SECOND, NVL(REAL_CLOCK_BEGIN_TIME_STAMP, NOW()), NOW()) ) AS TIME_MAX, | ||
SUM(ROW_LOCKS) AS ROW_LOCKS_TOTAL | ||
FROM information_schema.MV_ACTIVE_DISTRIBUTED_TRANSACTIONS | ||
WHERE PARTITION_NAME != '' | ||
GROUP BY PARTITION_NAME;` | ||
) | ||
|
||
var ( | ||
activeTransactionCountDesc = prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, activeTransaction, "count"), | ||
"The number of active transactions per partition", | ||
[]string{"database", "partition_name"}, | ||
nil, | ||
) | ||
|
||
activeTransactionTimeMaxDesc = prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, activeTransaction, "time_max"), | ||
"The max time in seconds since the transaction started", | ||
[]string{"database", "partition_name"}, | ||
nil, | ||
) | ||
|
||
activeTransactionRowLocksTotalDesc = prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, activeTransaction, "row_locks_total"), | ||
"The count of row locks per database", | ||
[]string{"database", "partition_name"}, | ||
nil, | ||
) | ||
) | ||
|
||
type ScrapeActiveTransactions struct{} | ||
|
||
func (s *ScrapeActiveTransactions) Help() string { | ||
return "Collect active transactions" | ||
} | ||
|
||
func (s *ScrapeActiveTransactions) Scrape(db *sqlx.DB, ch chan<- prometheus.Metric) { | ||
if db == nil { | ||
return | ||
} | ||
|
||
views := make([]ActiveDistributedTransactionsView, 0) | ||
if err := db.Select(&views, infoSchemaActiveDistributedTransactionsViewExistsQuery); err != nil { | ||
log.ErrorLogger.Errorf("checking existence view query failed: query=%s error=%v", infoSchemaActiveDistributedTransactionsViewExistsQuery, err) | ||
} else if len(views) == 0 { | ||
return | ||
} | ||
|
||
activeTransactionList := make([]ActiveDistributedTransactions, 0) | ||
if err := db.Select(&activeTransactionList, infoSchemaActiveDistributedTransactionsQuery); err != nil { | ||
log.ErrorLogger.Errorf("scraping query failed: query=%s error=%v", infoSchemaActiveDistributedTransactionsQuery, err) | ||
return | ||
} | ||
|
||
for i := range activeTransactionList { | ||
if postfix := strings.LastIndex(activeTransactionList[i].PartitionName, "_"); postfix != -1 { | ||
activeTransactionList[i].Database = activeTransactionList[i].PartitionName[:strings.LastIndex(activeTransactionList[i].PartitionName, "_")] | ||
} else { | ||
activeTransactionList[i].Database = activeTransactionList[i].PartitionName | ||
} | ||
} | ||
|
||
for _, activeTransaction := range activeTransactionList { | ||
ch <- prometheus.MustNewConstMetric( | ||
activeTransactionCountDesc, prometheus.GaugeValue, float64(activeTransaction.Count), | ||
activeTransaction.Database, | ||
activeTransaction.PartitionName, | ||
) | ||
|
||
ch <- prometheus.MustNewConstMetric( | ||
activeTransactionTimeMaxDesc, prometheus.GaugeValue, float64(activeTransaction.TimeMax), | ||
activeTransaction.Database, | ||
activeTransaction.PartitionName, | ||
) | ||
|
||
ch <- prometheus.MustNewConstMetric( | ||
activeTransactionRowLocksTotalDesc, prometheus.GaugeValue, float64(activeTransaction.RowLocksTotal), | ||
activeTransaction.Database, | ||
activeTransaction.PartitionName, | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package collector | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestNewScrapeProcessList(t *testing.T) { | ||
tt := []struct { | ||
threshold int | ||
hosts []string | ||
infoPatterns []string | ||
expectedThreshold int | ||
expectedQuery string | ||
}{ | ||
{ | ||
threshold: 1, | ||
expectedThreshold: 1, | ||
hosts: []string{}, | ||
infoPatterns: []string{}, | ||
expectedQuery: `SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, LEFT(INFO, 1000) AS INFO, RPC_INFO, PLAN_ID, TRANSACTION_STATE, ROW_LOCKS_HELD, PARTITION_LOCKS_HELD, EPOCH, LWPID, RESOURCE_POOL, STMT_VERSION, REASON_FOR_QUEUEING, DATE_SUB(now(), INTERVAL time SECOND) AS SUBMITTED_TIME | ||
FROM information_schema.PROCESSLIST`, | ||
}, | ||
{ | ||
threshold: 2, | ||
expectedThreshold: 2, | ||
hosts: []string{"host1", "host2"}, | ||
infoPatterns: []string{}, | ||
expectedQuery: `SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, LEFT(INFO, 1000) AS INFO, RPC_INFO, PLAN_ID, TRANSACTION_STATE, ROW_LOCKS_HELD, PARTITION_LOCKS_HELD, EPOCH, LWPID, RESOURCE_POOL, STMT_VERSION, REASON_FOR_QUEUEING, DATE_SUB(now(), INTERVAL time SECOND) AS SUBMITTED_TIME | ||
FROM information_schema.PROCESSLIST | ||
WHERE HOST NOT LIKE 'host1:%' AND HOST NOT LIKE 'host2:%'`, | ||
}, | ||
{ | ||
threshold: 3, | ||
expectedThreshold: 3, | ||
hosts: []string{}, | ||
infoPatterns: []string{"pattern1", "pattern2"}, | ||
expectedQuery: `SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, LEFT(INFO, 1000) AS INFO, RPC_INFO, PLAN_ID, TRANSACTION_STATE, ROW_LOCKS_HELD, PARTITION_LOCKS_HELD, EPOCH, LWPID, RESOURCE_POOL, STMT_VERSION, REASON_FOR_QUEUEING, DATE_SUB(now(), INTERVAL time SECOND) AS SUBMITTED_TIME | ||
FROM information_schema.PROCESSLIST | ||
WHERE NVL(INFO, '') NOT LIKE '%pattern1%' AND NVL(INFO, '') NOT LIKE '%pattern2%'`, | ||
}, | ||
{ | ||
threshold: 4, | ||
expectedThreshold: 4, | ||
hosts: []string{"host1", "host2"}, | ||
infoPatterns: []string{"pattern1", "pattern2"}, | ||
expectedQuery: `SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, LEFT(INFO, 1000) AS INFO, RPC_INFO, PLAN_ID, TRANSACTION_STATE, ROW_LOCKS_HELD, PARTITION_LOCKS_HELD, EPOCH, LWPID, RESOURCE_POOL, STMT_VERSION, REASON_FOR_QUEUEING, DATE_SUB(now(), INTERVAL time SECOND) AS SUBMITTED_TIME | ||
FROM information_schema.PROCESSLIST | ||
WHERE HOST NOT LIKE 'host1:%' AND HOST NOT LIKE 'host2:%' AND NVL(INFO, '') NOT LIKE '%pattern1%' AND NVL(INFO, '') NOT LIKE '%pattern2%'`, | ||
}, | ||
} | ||
|
||
for _, tc := range tt { | ||
scraper := NewScrapeProcessList(tc.threshold, tc.hosts, tc.infoPatterns) | ||
assert.Equal(t, tc.expectedThreshold, scraper.Threshold) | ||
assert.Equal(t, tc.expectedQuery, scraper.Query) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.