config.ini
[email]
to = [email protected]@email.com
main.go
package main
import (
"database/sql"
"crypto/tls"
"fmt"
"net/smtp"
"strings"
"github.com/go-ini/ini"
_ "github.com/go-sql-driver/mysql"
)
type QueryResult struct {
Checksum string
Fingerprint string
DBMax string
UserMax string
LastSeen string
TSCnt int
QueryTimeMin float64
QueryTimeMax float64
QueryTimeAvg float64
Sample string
}
func main() {
db, err := connectDB()
if err != nil {
panic(err)
}
defer db.Close()
results, err := executeQuery(db)
if err != nil {
panic(err)
}
emailContent := formatEmailContent(results)
err = sendEmail(emailContent)
if err != nil {
panic(err)
}
fmt.Println("Email sent successfully")
}
func connectDB() (*sql.DB, error) {
dsn := "slowquery:1qazxsw2@tcp(192.168.0.100:3307)/slowquery?charset=utf8&parseTime=True&loc=Local"
return sql.Open("mysql", dsn)
}
func executeQuery(db *sql.DB) ([]QueryResult, error) {
rows, err := db.Query(`
SELECT r.sample, h.db_max, h.user_max, r.last_seen, SUM(h.ts_cnt) AS ts_cnt,
ROUND(SUM(h.Query_time_sum)/SUM(h.ts_cnt), 3) AS Query_time_avg
FROM mysql_slow_query_review AS r
JOIN mysql_slow_query_review_history AS h ON r.checksum = h.checksum
WHERE r.last_seen >= SUBDATE(NOW(), INTERVAL 1 DAY)
GROUP BY r.checksum
ORDER BY r.last_seen DESC, ts_cnt DESC
LIMIT 100
`)
if err != nil {
return nil, err
}
defer rows.Close()
var results []QueryResult
for rows.Next() {
var result QueryResult
err := rows.Scan(&result.Sample, &result.DBMax, &result.UserMax, &result.LastSeen, &result.TSCnt, &result.QueryTimeAvg)
if err != nil {
return nil, err
}
results = append(results, result)
}
return results, nil
}
func formatEmailContent(results []QueryResult) string {
var emailContent strings.Builder
emailContent.WriteString("<html><head><meta charset=\"UTF-8\"><style>table {width:100%;border-collapse:collapse;background-color:white;} th,td{border:1px solid #ccc;} th{background-color:#00bfff;color:white;text-align:center;cursor:pointer;}</style></head><body>")
emailContent.WriteString("<table>")
emailContent.WriteString("<tr><th>SQL语句</th><th>数据库</th><th>用户</th><th>最近时间</th><th>次数</th><th>平均时间</th></tr>")
for _, r := range results {
emailContent.WriteString(fmt.Sprintf(
"<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%.3f</td></tr>",
r.Sample, r.DBMax, r.UserMax, r.LastSeen, r.TSCnt, r.QueryTimeAvg,
))
}
emailContent.WriteString("</table>")
emailContent.WriteString("</body></html>")
return emailContent.String()
}
func sendEmail(content string) error {
from := "[email protected]"
cfg, err := ini.Load("config.ini")
if err != nil {
panic(err)
}
toStr := cfg.Section("email").Key("to").String()
to := strings.Split(toStr, ",")
auth := smtp.PlainAuth("", from, "密码", "192.168.100.2")
smtpServer := "192.168.100.2:25"
client, err := smtp.Dial(smtpServer)
if err != nil {
return err
}
defer client.Close()
tlsConfig := &tls.Config{
InsecureSkipVerify: true,
}
if err := client.StartTLS(tlsConfig); err != nil {
return fmt.Errorf("failed to start TLS: %v", err)
}
if err := client.Auth(auth); err != nil {
return err
}
if err := client.Mail(from); err != nil {
return err
}
for _, addr := range to {
if err := client.Rcpt(addr); err != nil {
return err
}
}
w, err := client.Data()
if err != nil {
return err
}
msg := []byte(fmt.Sprintf("From: %s\r\nTo: %s\r\nSubject: mysql慢查询Top 100\r\nMIME-Version: 1.0;\r\nContent-Type: text/html; charset=UTF-8;\r\n\r\n%s",
from, strings.Join(to, ","), content))
_, err = w.Write(msg)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return nil
}