func (m *Monitor) getTableUserStats(conn *sql.DB, c *mm.Collection, ignoreDb string) error { m.logger.Debug("getTableUserStats:call") defer m.logger.Debug("getTableUserStats:return") m.status.Update(m.name, "Getting userstat table metrics") /** * SELECT * FROM INFORMATION_SCHEMA.TABLE_STATISTICS; * +--------------+-------------+-----------+--------------+------------------------+ * | TABLE_SCHEMA | TABLE_NAME | ROWS_READ | ROWS_CHANGED | ROWS_CHANGED_X_INDEXES | */ sql := "SELECT TABLE_SCHEMA, TABLE_NAME, ROWS_READ, ROWS_CHANGED, ROWS_CHANGED_X_INDEXES" + " FROM INFORMATION_SCHEMA.TABLE_STATISTICS" if ignoreDb != "" { sql += " WHERE TABLE_SCHEMA NOT LIKE '" + ignoreDb + "'" } rows, err := conn.Query(sql) if err != nil { return err } defer rows.Close() for rows.Next() { var tableSchema string var tableName string var rowsRead int64 var rowsChanged int64 var rowsChangedIndexes int64 err = rows.Scan(&tableSchema, &tableName, &rowsRead, &rowsChanged, &rowsChangedIndexes) if err != nil { return err } c.Metrics = append(c.Metrics, mm.Metric{ Name: "mysql/db." + tableSchema + "/t." + tableName + "/rows_read", Type: "counter", Number: float64(rowsRead), }) c.Metrics = append(c.Metrics, mm.Metric{ Name: "mysql/db." + tableSchema + "/t." + tableName + "/rows_changed", Type: "counter", Number: float64(rowsChanged), }) c.Metrics = append(c.Metrics, mm.Metric{ Name: "mysql/db." + tableSchema + "/t." + tableName + "/rows_changed_x_indexes", Type: "counter", Number: float64(rowsChangedIndexes), }) } err = rows.Err() if err != nil { return err } return nil }
func (m *Monitor) GetShowStatusMetrics(conn *sql.DB, c *mm.Collection) error { m.logger.Debug("GetShowStatusMetrics:call") defer m.logger.Debug("GetShowStatusMetrics:return") m.status.Update(m.name, "Getting global status metrics") rows, err := conn.Query("SHOW /*!50002 GLOBAL */ STATUS") if err != nil { return err } defer rows.Close() for rows.Next() { var statName string var statValue string if err = rows.Scan(&statName, &statValue); err != nil { return err } statName = strings.ToLower(statName) metricType, ok := m.config.Status[statName] if !ok { continue // not collecting this stat } if statValue == "" { // Some values aren't set when not applicable, // e.g. slave_heartbeat_period on a master. continue } metricValue, err := strconv.ParseFloat(statValue, 64) if err != nil { m.logger.Warn(fmt.Sprintf("Cannot convert '%s' value '%s' to float: %s", statName, statValue, err)) delete(m.config.Status, statName) // stop collecting it continue } c.Metrics = append(c.Metrics, mm.Metric{"mysql/" + statName, metricType, metricValue, ""}) } err = rows.Err() if err != nil { return err } return nil }
func (m *Monitor) getIndexUserStats(conn *sql.DB, c *mm.Collection, ignoreDb string) error { m.logger.Debug("getIndexUserStats:call") defer m.logger.Debug("getIndexUserStats:return") m.status.Update(m.name, "Getting userstat index metrics") /** * SELECT * FROM INFORMATION_SCHEMA.INDEX_STATISTICS; * +--------------+-------------+------------+-----------+ * | TABLE_SCHEMA | TABLE_NAME | INDEX_NAME | ROWS_READ | * +--------------+-------------+------------+-----------+ */ sql := "SELECT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, ROWS_READ" + " FROM INFORMATION_SCHEMA.INDEX_STATISTICS" if ignoreDb != "" { sql = sql + " WHERE TABLE_SCHEMA NOT LIKE '" + ignoreDb + "'" } rows, err := conn.Query(sql) if err != nil { return err } defer rows.Close() for rows.Next() { var tableSchema string var tableName string var indexName string var rowsRead int64 err = rows.Scan(&tableSchema, &tableName, &indexName, &rowsRead) if err != nil { return err } metricName := "mysql/db." + tableSchema + "/t." + tableName + "/idx." + indexName + "/rows_read" metricValue := float64(rowsRead) c.Metrics = append(c.Metrics, mm.Metric{metricName, "counter", metricValue, ""}) } err = rows.Err() if err != nil { return err } return nil }
func (m *Monitor) GetInnoDBMetrics(conn *sql.DB, c *mm.Collection) error { m.logger.Debug("GetInnoDBMetrics:call") defer m.logger.Debug("GetInnoDBMetrics:return") m.status.Update(m.name, "Getting InnoDB metrics") rows, err := conn.Query("SELECT NAME, SUBSYSTEM, COUNT, TYPE FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE STATUS='enabled'") if err != nil { return err } defer rows.Close() for rows.Next() { var statName string var statSubsystem string var statCount string var statType string err = rows.Scan(&statName, &statSubsystem, &statCount, &statType) if err != nil { return err } metricName := "mysql/innodb/" + strings.ToLower(statSubsystem) + "/" + strings.ToLower(statName) metricValue, err := strconv.ParseFloat(statCount, 64) if err != nil { m.logger.Warn(fmt.Sprintf("Cannot convert '%s' value '%s' to float: %s", metricName, metricValue, err)) metricValue = 0.0 } var metricType string if statType == "value" { metricType = "gauge" } else { metricType = "counter" } c.Metrics = append(c.Metrics, mm.Metric{metricName, metricType, metricValue, ""}) } err = rows.Err() if err != nil { return err } return nil }
// @goroutine[2] func (m *Monitor) GetShowStatusMetrics(conn *sql.DB, c *mm.Collection) error { m.logger.Debug("GetShowStatusMetrics:call") defer m.logger.Debug("GetShowStatusMetrics:return") m.status.Update(m.name, "Getting global status metrics") rows, err := conn.Query("SHOW /*!50002 GLOBAL */ STATUS") if err != nil { return err } defer rows.Close() for rows.Next() { var statName string var statValue string if err = rows.Scan(&statName, &statValue); err != nil { return err } statName = strings.ToLower(statName) metricType, ok := m.config.Status[statName] if !ok { continue // not collecting this stat } metricName := statName metricValue, err := strconv.ParseFloat(statValue, 64) if err != nil { metricValue = 0.0 } c.Metrics = append(c.Metrics, mm.Metric{"mysql/" + metricName, metricType, metricValue, ""}) } err = rows.Err() if err != nil { return err } return nil }