2020-01-02 18:05:42 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
2020-08-02 16:16:40 +01:00
|
|
|
"flag"
|
2020-01-02 18:05:42 +00:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
func probeTwitter(ctx context.Context, target string, registry *prometheus.Registry) (success bool) {
|
|
|
|
followersGauge := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
|
|
|
Name: "twitter_followers",
|
|
|
|
Help: "The number of followers of the twitter account.",
|
|
|
|
},
|
|
|
|
[]string{"screen_name"})
|
|
|
|
|
|
|
|
registry.MustRegister(followersGauge)
|
|
|
|
|
|
|
|
res, err := http.Get(fmt.Sprintf("https://cdn.syndication.twimg.com/widgets/followbutton/info.json?screen_names=%s", url.QueryEscape(target)))
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("fetching url: %s", err)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
data := []struct {
|
|
|
|
FollowersCount int `json:"followers_count"`
|
|
|
|
}{}
|
|
|
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
|
|
|
log.Errorf("decoding json: %s", err)
|
|
|
|
return false
|
|
|
|
}
|
2022-08-04 00:04:16 +01:00
|
|
|
switch l := len(data); {
|
|
|
|
case l == 0:
|
|
|
|
log.Errorf("No data returned. Does screen name exist?")
|
|
|
|
return false
|
|
|
|
case l > 1:
|
|
|
|
log.Errorf("Unexpected (>1) results returned. WTF twitter??")
|
|
|
|
return false
|
|
|
|
}
|
2020-01-02 18:05:42 +00:00
|
|
|
followersGauge.With(prometheus.Labels{"screen_name": target}).Set(float64(data[0].FollowersCount))
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func twitterHandler(w http.ResponseWriter, r *http.Request) {
|
2022-08-04 00:05:24 +01:00
|
|
|
screenName := r.URL.Query().Get("screen_name")
|
|
|
|
if screenName == "" {
|
|
|
|
http.Error(w, "screen_name parameter is missing", http.StatusBadRequest)
|
2020-01-02 18:05:42 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
reg := prometheus.NewRegistry()
|
|
|
|
|
|
|
|
ctx, cancel := context.WithTimeout(r.Context(), time.Duration(5*time.Second))
|
|
|
|
defer cancel()
|
|
|
|
|
2022-08-04 00:05:24 +01:00
|
|
|
if success := probeTwitter(ctx, screenName, reg); !success {
|
2020-01-02 18:05:42 +00:00
|
|
|
log.Error("Probe failed!")
|
|
|
|
}
|
|
|
|
|
|
|
|
h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
|
|
|
|
}
|
2022-08-04 00:04:16 +01:00
|
|
|
|
|
|
|
func bail(err error) {
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-02 18:05:42 +00:00
|
|
|
func main() {
|
2020-08-02 16:16:40 +01:00
|
|
|
var listenAddr string
|
|
|
|
flag.StringVar(&listenAddr, "listen", "0.0.0.0:9700", "Address to listen on")
|
|
|
|
flag.Parse()
|
2020-01-02 18:05:42 +00:00
|
|
|
http.Handle("/metrics", promhttp.Handler())
|
|
|
|
http.HandleFunc("/probe", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
twitterHandler(w, r)
|
|
|
|
})
|
2020-08-02 16:16:40 +01:00
|
|
|
log.Infof("Listening on %s", listenAddr)
|
2022-08-04 00:04:16 +01:00
|
|
|
bail(http.ListenAndServe(listenAddr, nil))
|
2020-01-02 18:05:42 +00:00
|
|
|
}
|