aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go90
1 files changed, 75 insertions, 15 deletions
diff --git a/main.go b/main.go
index 945b30b..b9bed96 100644
--- a/main.go
+++ b/main.go
@@ -8,28 +8,52 @@ import (
"io"
"net/http"
"regexp"
+ "strconv"
"strings"
+ "time"
"github.com/beevik/etree"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
)
type ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error
-var RegexCollection = map[string]string{
- "nerdcast": "NerdCast [0-9]+[a-c]* -",
- "empreendedor": "Empreendedor [0-9]+ -",
- "mamicas": "Caneca de Mamicas [0-9]+ -",
- "english": "Speak English [0-9]+ -",
- "nerdcash": "NerdCash [0-9]+ -",
- "bunker": "Lá do Bunker [0-9]+ -",
- "tech": "NerdTech [0-9]+ -",
- "genera": "Generacast [0-9]+ -",
-}
-
const (
FeedUrl = "https://api.jovemnerd.com.br/feed-nerdcast/"
)
+var (
+ RegexCollection = map[string]string{
+ "nerdcast": "NerdCast [0-9]+[a-c]* -",
+ "empreendedor": "Empreendedor [0-9]+ -",
+ "mamicas": "Caneca de Mamicas [0-9]+ -",
+ "english": "Speak English [0-9]+ -",
+ "nerdcash": "NerdCash [0-9]+ -",
+ "bunker": "Lá do Bunker [0-9]+ -",
+ "tech": "NerdTech [0-9]+ -",
+ "genera": "Generacast [0-9]+ -",
+ }
+
+ feedRequest = promauto.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "feed_request",
+ Help: "How long jovemnerd takes to answer",
+ Buckets: []float64{.01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
+ }, []string{"status_code"})
+
+ httpRequest = promauto.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "http_request",
+ Help: "How long the application takes to complete the request",
+ Buckets: []float64{.01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
+ }, []string{"status_code", "user_agent"})
+
+ seriesCount = promauto.NewCounterVec(prometheus.CounterOpts{
+ Name: "serie_count",
+ Help: "How often a serie is called",
+ }, []string{"serie"})
+)
+
func getSeries(r *http.Request) []string {
query := r.URL.Query().Get("q")
@@ -59,13 +83,24 @@ func match(title string, series []string) bool {
}
func fetchXML(_ context.Context) ([]byte, error) {
+ t := time.Now()
+ c := http.StatusInternalServerError
+
+ defer func() {
+ since := time.Since(t).Seconds()
+ code := strconv.Itoa(c)
+ feedRequest.WithLabelValues(code).Observe(since)
+ }()
+
res, err := http.Get(FeedUrl)
if err != nil {
return nil, err
}
defer res.Body.Close()
- if res.StatusCode == http.StatusOK {
+ c = res.StatusCode
+
+ if c == http.StatusOK {
return io.ReadAll(res.Body)
}
@@ -109,7 +144,7 @@ func filterBySeries(series []string, xml []byte, temper bool) ([]byte, error) {
return doc.WriteToBytes()
}
-func wrap(next ErrorRequestHandler) http.HandlerFunc {
+func handleError(next ErrorRequestHandler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := next(w, r); err != nil {
w.WriteHeader(http.StatusInternalServerError)
@@ -117,6 +152,30 @@ func wrap(next ErrorRequestHandler) http.HandlerFunc {
}
}
+func observe(next http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ t := time.Now()
+
+ next(w, r)
+
+ rw := w.(*responseWriter)
+ since := time.Since(t).Seconds()
+ code := strconv.Itoa(rw.Status())
+ userAgent := r.Header.Get("user-agent")
+ httpRequest.WithLabelValues(code, userAgent).Observe(float64(since))
+
+ for _, s := range getSeries(r) {
+ seriesCount.WithLabelValues(s).Inc()
+ }
+ }
+}
+
+func wrap(next http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ next(NewResponseWriter(w), r)
+ }
+}
+
func titles(w http.ResponseWriter, r *http.Request) error {
xml, err := fetchXML(r.Context())
if err != nil {
@@ -173,8 +232,9 @@ func main() {
flag.Parse()
mux := http.NewServeMux()
- mux.HandleFunc("/titles", wrap(titles))
- mux.HandleFunc("/", wrap(podcast))
+ mux.Handle("/metrics", promhttp.Handler())
+ mux.HandleFunc("/titles", wrap(handleError(titles)))
+ mux.HandleFunc("/", wrap(observe(handleError(podcast))))
server := http.Server{
Handler: mux,