109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
)
|
|
|
|
const (
|
|
period = 5 * time.Minute
|
|
timeout = 10 * time.Second
|
|
api = "https://quota.aa.net.uk"
|
|
)
|
|
|
|
var (
|
|
cl *http.Client
|
|
bind = flag.String("bind", ":9100", "[host]:port to bind to.")
|
|
|
|
monthlyQuotaBytes = promauto.NewGauge(prometheus.GaugeOpts{
|
|
Name: "aaisp_quota_monthly_bytes",
|
|
Help: "Monthly quota provided by AAISP.",
|
|
})
|
|
quotaRemainingBytes = promauto.NewGauge(prometheus.GaugeOpts{
|
|
Name: "aaisp_quota_remaining_bytes",
|
|
Help: "Number of bytes remaining on this month's AAISP quota.",
|
|
})
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
cl = &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
MinVersion: tls.VersionTLS12,
|
|
},
|
|
},
|
|
Timeout: timeout,
|
|
}
|
|
|
|
go collect()
|
|
|
|
http.Handle("/metrics", promhttp.Handler())
|
|
err := http.ListenAndServe(*bind, nil)
|
|
switch {
|
|
case errors.Is(err, http.ErrServerClosed), err == nil:
|
|
// clean shutdown
|
|
default:
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func collect() {
|
|
for {
|
|
quota, err := getQuota()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
} else {
|
|
monthlyQuotaBytes.Set(quota.MonthlyQuotaBytes)
|
|
quotaRemainingBytes.Set(quota.QuotaRemainingBytes)
|
|
}
|
|
|
|
now := time.Now()
|
|
align := now.Truncate(period).Add(period)
|
|
s := align.Sub(now)
|
|
if s > 0 {
|
|
time.Sleep(s)
|
|
}
|
|
}
|
|
}
|
|
|
|
type quotaResponse struct {
|
|
MonthlyQuotaBytes float64 `json:"monthly_quota"`
|
|
QuotaRemainingBytes float64 `json:"quota_remaining"`
|
|
}
|
|
|
|
func getQuota() (quotaResponse, error) {
|
|
req, err := http.NewRequest(http.MethodGet, api, nil)
|
|
if err != nil {
|
|
return quotaResponse{}, err
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("User-Agent", "src.lwithers.me.uk/go/aaisp-quota-exporter v1.0")
|
|
|
|
resp, err := cl.Do(req)
|
|
if err != nil {
|
|
return quotaResponse{}, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
var q quotaResponse
|
|
dec := json.NewDecoder(resp.Body)
|
|
if err := dec.Decode(&q); err != nil {
|
|
return quotaResponse{}, fmt.Errorf("%s: could not decode response: %w", api, err)
|
|
}
|
|
|
|
return q, nil
|
|
}
|