|
@@ -1,222 +0,0 @@
|
|
|
-package main
|
|
|
-
|
|
|
-import (
|
|
|
- "net/http"
|
|
|
-
|
|
|
- log "github.com/Sirupsen/logrus"
|
|
|
- "github.com/prometheus/client_golang/prometheus/promhttp"
|
|
|
- "github.com/prometheus/client_golang/prometheus"
|
|
|
-
|
|
|
- "flag"
|
|
|
- "fmt"
|
|
|
- "os"
|
|
|
- "io/ioutil"
|
|
|
- "strings"
|
|
|
- "regexp"
|
|
|
-
|
|
|
- "database/sql"
|
|
|
- _ "github.com/go-sql-driver/mysql"
|
|
|
-)
|
|
|
-
|
|
|
-//This is my collector metrics
|
|
|
-type wpCollector struct {
|
|
|
- numPostsMetric *prometheus.Desc
|
|
|
- numCommentsMetric *prometheus.Desc
|
|
|
- numUsersMetric *prometheus.Desc
|
|
|
-
|
|
|
- db_host string
|
|
|
- db_name string
|
|
|
- db_user string
|
|
|
- db_pass string
|
|
|
- db_table_prefix string
|
|
|
-}
|
|
|
-
|
|
|
-//This is a constructor for my wpCollector struct
|
|
|
-func newWordPressCollector(host string, dbname string, username string, pass string, table_prefix string) *wpCollector {
|
|
|
- return &wpCollector{
|
|
|
- numPostsMetric: prometheus.NewDesc("wp_num_posts_metric",
|
|
|
- "Shows the number of total posts in the WordPress site",
|
|
|
- nil, nil,
|
|
|
- ),
|
|
|
- numCommentsMetric: prometheus.NewDesc("wp_num_comments_metric",
|
|
|
- "Shows the number of total comments in the WordPress site",
|
|
|
- nil, nil,
|
|
|
- ),
|
|
|
- numUsersMetric: prometheus.NewDesc("wp_num_users_metric",
|
|
|
- "Shows the number of registered users in the WordPress site",
|
|
|
- nil, nil,
|
|
|
- ),
|
|
|
-
|
|
|
- db_host: host,
|
|
|
- db_name: dbname,
|
|
|
- db_user: username,
|
|
|
- db_pass: pass,
|
|
|
- db_table_prefix: table_prefix,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//Describe method is required for a prometheus.Collector type
|
|
|
-func (collector *wpCollector) Describe(ch chan<- *prometheus.Desc) {
|
|
|
-
|
|
|
- //We set the metrics
|
|
|
- ch <- collector.numPostsMetric
|
|
|
- ch <- collector.numCommentsMetric
|
|
|
- ch <- collector.numUsersMetric
|
|
|
-}
|
|
|
-
|
|
|
-//Collect method is required for a prometheus.Collector type
|
|
|
-func (collector *wpCollector) Collect(ch chan<- prometheus.Metric) {
|
|
|
-
|
|
|
- //We run DB queries here to retrieve the metrics we care about
|
|
|
- dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s", collector.db_user, collector.db_pass, collector.db_host, collector.db_name)
|
|
|
-
|
|
|
- db, err := sql.Open("mysql", dsn)
|
|
|
- if(err != nil){
|
|
|
- fmt.Fprintf(os.Stderr, "Error connecting to database: %s ...\n", err)
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
- defer db.Close()
|
|
|
-
|
|
|
- //select count(*) as num_users from wp_users;
|
|
|
- var num_users float64
|
|
|
- q1 := fmt.Sprintf("select count(*) as num_users from %susers;", collector.db_table_prefix)
|
|
|
- err = db.QueryRow(q1).Scan(&num_users)
|
|
|
- if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- //select count(*) as num_comments from wp_comments;
|
|
|
- var num_comments float64
|
|
|
- q2 := fmt.Sprintf("select count(*) as num_comments from %scomments;", collector.db_table_prefix)
|
|
|
- err = db.QueryRow(q2).Scan(&num_comments)
|
|
|
- if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- //select count(*) as num_posts from wp_posts WHERE post_type='post' AND post_status!='auto-draft';
|
|
|
- var num_posts float64
|
|
|
- q3 := fmt.Sprintf("select count(*) as num_posts from %sposts WHERE post_type='post' AND post_status!='auto-draft';", collector.db_table_prefix)
|
|
|
- err = db.QueryRow(q3).Scan(&num_posts)
|
|
|
- if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- //Write latest value for each metric in the prometheus metric channel.
|
|
|
- //Note that you can pass CounterValue, GaugeValue, or UntypedValue types here.
|
|
|
- ch <- prometheus.MustNewConstMetric(collector.numPostsMetric, prometheus.CounterValue, num_posts)
|
|
|
- ch <- prometheus.MustNewConstMetric(collector.numCommentsMetric, prometheus.CounterValue, num_comments)
|
|
|
- ch <- prometheus.MustNewConstMetric(collector.numUsersMetric, prometheus.CounterValue, num_users)
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-func main() {
|
|
|
-
|
|
|
- wpConfPtr := flag.String("wpconfig", "", "Path for wp-config.php file of the WordPress site you wish to monitor")
|
|
|
- wpHostPtr := flag.String("host", "127.0.0.1", "Hostname or Address for DB server")
|
|
|
- wpPortPtr := flag.String("port", "3306", "DB server port")
|
|
|
- wpNamePtr := flag.String("db", "", "DB name")
|
|
|
- wpUserPtr := flag.String("user", "", "DB user for connection")
|
|
|
- wpPassPtr := flag.String("pass", "", "DB password for connection")
|
|
|
- wpTablePrefixPtr := flag.String("tableprefix", "wp_", "Table prefix for WordPress tables")
|
|
|
-
|
|
|
- flag.Parse()
|
|
|
-
|
|
|
- if *wpConfPtr == "" {
|
|
|
- db_host := fmt.Sprintf("%s:%s", *wpHostPtr, *wpPortPtr)
|
|
|
- db_name := *wpNamePtr
|
|
|
- db_user := *wpUserPtr
|
|
|
- db_password := *wpPassPtr
|
|
|
- table_prefix := *wpTablePrefixPtr
|
|
|
-
|
|
|
- if db_name == "" {
|
|
|
- fmt.Fprintf(os.Stderr, "flag -db=dbname required!\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
-
|
|
|
- if db_user == "" {
|
|
|
- fmt.Fprintf(os.Stderr, "flag -user=username required!\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
-
|
|
|
- //We create the collector
|
|
|
- collector := newWordPressCollector(db_host, db_name, db_user, db_password, table_prefix)
|
|
|
- prometheus.MustRegister(collector)
|
|
|
-
|
|
|
- //no path supplied error
|
|
|
- //fmt.Fprintf(os.Stderr, "flag -wpconfig=/path/to/wp-config/ required!\n")
|
|
|
- //os.Exit(1)
|
|
|
- } else{
|
|
|
- var wpconfig_file strings.Builder
|
|
|
- wpconfig_file.WriteString(*wpConfPtr)
|
|
|
-
|
|
|
- if strings.HasSuffix(*wpConfPtr, "/") {
|
|
|
- wpconfig_file.WriteString("wp-config.php")
|
|
|
- }else{
|
|
|
- wpconfig_file.WriteString("/wp-config.php")
|
|
|
- }
|
|
|
-
|
|
|
- //try to read wp-config.php file from path
|
|
|
- dat, err := ioutil.ReadFile(wpconfig_file.String())
|
|
|
- if(err != nil){
|
|
|
- panic(err)
|
|
|
- }
|
|
|
- fmt.Printf("Read :%v bytes\n", len(dat))
|
|
|
-
|
|
|
- //We must locate with regular expressions the MySQL connection credentials and the table prefix
|
|
|
- //define('DB_HOST', 'xxxxxxx');
|
|
|
- r, _ := regexp.Compile(`define\(['"]DB_HOST['"].*?,.*?['"](.*?)['"].*?\);`)
|
|
|
- res := r.FindStringSubmatch(string(dat[:len(dat)]))
|
|
|
- if(res == nil){
|
|
|
- fmt.Fprintf(os.Stderr, "Error could not find DB_HOST in wp-config.php ...\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
- db_host := res[1]
|
|
|
-
|
|
|
- //define('DB_NAME', 'xxxxxxx');
|
|
|
- r, _ = regexp.Compile(`define\(['"]DB_NAME['"].*?,.*?['"](.*?)['"].*?\);`)
|
|
|
- res = r.FindStringSubmatch(string(dat[:len(dat)]))
|
|
|
- if(res == nil){
|
|
|
- fmt.Fprintf(os.Stderr, "Error could not find DB_NAME in wp-config.php ...\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
- db_name := res[1]
|
|
|
-
|
|
|
- //define('DB_USER', 'xxxxxxx');
|
|
|
- r, _ = regexp.Compile(`define\(['"]DB_USER['"].*?,.*?['"](.*?)['"].*?\);`)
|
|
|
- res = r.FindStringSubmatch(string(dat[:len(dat)]))
|
|
|
- if(res == nil){
|
|
|
- fmt.Fprintf(os.Stderr, "Error could not find DB_USER in wp-config.php ...\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
- db_user := res[1]
|
|
|
-
|
|
|
- //define('DB_PASSWORD', 'xxxxxxx');
|
|
|
- r, _ = regexp.Compile(`define\(['"]DB_PASSWORD['"].*?,.*?['"](.*?)['"].*?\);`)
|
|
|
- res = r.FindStringSubmatch(string(dat[:len(dat)]))
|
|
|
- if(res == nil){
|
|
|
- fmt.Fprintf(os.Stderr, "Error could not find DB_PASSWORD in wp-config.php ...\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
- db_password := res[1]
|
|
|
-
|
|
|
- //$table_prefix = 'wp_';
|
|
|
- r, _ = regexp.Compile(`\$table_prefix.*?=.*?['"](.*?)['"];`)
|
|
|
- res = r.FindStringSubmatch(string(dat[:len(dat)]))
|
|
|
- if(res == nil){
|
|
|
- fmt.Fprintf(os.Stderr, "Error could not find $table_prefix in wp-config.php ...\n")
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
- table_prefix := res[1]
|
|
|
-
|
|
|
- //We create the collector
|
|
|
- collector := newWordPressCollector(db_host, db_name, db_user, db_password, table_prefix)
|
|
|
- prometheus.MustRegister(collector)
|
|
|
- }
|
|
|
-
|
|
|
- //This section will start the HTTP server and expose
|
|
|
- //any metrics on the /metrics endpoint.
|
|
|
- http.Handle("/metrics", promhttp.Handler())
|
|
|
- log.Info("Beginning to serve on port :9117")
|
|
|
- log.Fatal(http.ListenAndServe(":9117", nil))
|
|
|
-}
|
|
|
-
|