diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 6714fb3..fd0c777 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -18,53 +18,8 @@ For example, the page parses the contents of a file and parses out the andrew me # Metric Names Andrew exposes [prometheus](https://prometheus.io/docs/guides/go-application/) metrics, serving on /metrics. -The naming scheme is case-preserving. +They're fairly simple metrics; all errors are coalesced into a single "errors" path, but broken down by non-200 http codes. -The scheme is: +All requests are counted. -```mermaid -flowchart TD - A[packagename_] --> B{Is there a type that owns the function?} - B -->|yes| C[typename_] - B -->|no| D[functionname_] - C --> D[functionname_] - D --> F[conceptname] - F --> |sorted by labels| G[bylabel] -``` - -## definitions -packagename_ : the name of the package containing the function, followed by an underscore e.g. andrew_ -typename_ : the name of the type which owns the function being instrumented e.g. AndrewServer_. If the function is owned by a package without an associated type, skip this. -functionname_ : the name of the function being instrumented, followed by an underscore e.g. Serve_ -conceptname: what conceptually are we instrumenting here? For example, in the code below we are instrumenting noises. -bylabel: -``` -package roflcopter - -import ( - "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/prometheus/client_golang/prometheus" -) - -func noise(noiseType string) { - switch noiseType { - case "soisoisoi": - promauto.NewCounter(prometheus.CounterOpts{ - Name: "roflcopter_noise_soisoisoi", - Help: "The total number of soisoisoi noises the roflcopter made", - }).Inc() - case "explosion" - promauto.NewCounter(prometheus.CounterOpts{ - Name: "roflcopter_noise_explosion", - Help: "The total number of explosion noises the roflcopter made", - }).Inc() - default: - // Handle unknown noise types if needed - promauto.NewCounter(prometheus.CounterOpts{ - Name: "roflcopter_noise_unknownnoise", - Help: "The total number of unknown noises the roflcopter made", - }).Inc() - } -} - -``` \ No newline at end of file +All http 200 requests are broken down by path. diff --git a/andrew_server.go b/andrew_server.go index 974989e..2a7b003 100644 --- a/andrew_server.go +++ b/andrew_server.go @@ -31,25 +31,29 @@ type Server struct { HTTPServer *http.Server } -// allRequestsByPathCounter creates a new prometheus counter for use in the Serve function, tracking all requests made, segregated by path. -// Note there can be many requests for a single page, as css etc is served. -var allRequestsByPathCounter = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "andrew_server_serve_allrequestsbypath", - Help: "The total number of all requests received by the andrew server, segregated by path", -}, []string{"allrequests"}) -// allRequestsCounter creates a new prometheus counter for use in the Serve function, tracking all requests made. + +// allRequestsCounter creates a new prometheus counter, intended to track the count of all requests made. // Note there can be many requests for a single page, as css etc is served. var allRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{ Name: "andrew_server_serve_allrequests", Help: "The total number of all requests received by the andrew server", }) -// allRequestsErrorsByPathCounter creates a new prometheus counter for use in the Serve function, tracking all of the error codes generated, -// organised by the path that generates the error. -var allRequestsErrorsByPathCounter = promauto.NewCounterVec(prometheus.CounterOpts{ +// allRequestsErrorsAggregatedCounter creates a new prometheus counter, tracking all of the error codes generated, +// aggregated into one path. The aggregation is to reduce the cardinality of the metrics in Prometheus, which can +// get fairly gnarly as bots and scammers try downloading random URLs from the website. +var allRequestsErrorsAggregatedCounter = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "andrew_server_serve_allrequests_errorsbypath", - Help: "The total number of all requests received by the andrew server, segregated by path", + Help: "The total number of all non-http 200 requests received by the andrew server, segregated by path", +}, []string{"path", "status"}) + +// allHttp200RequestsByPathCounter creates a new prometheus counter, tracking all of the http 200 paths served, +// organised by the path that is successfully served. +// Note there can be many requests for a single page, as css etc is served. +var allHttp200RequestsByPathCounter = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "andrew_server_serve_allrequests_200bypath", + Help: "The total number of all http 200 requests received by the andrew server, segregated by path", }, []string{"path", "status"}) // NewServer builds your web server. @@ -89,7 +93,6 @@ func NewServer(contentRoot fs.FS, address, baseUrl string, rssInfo RssInfo) *Ser func (a Server) Serve(w http.ResponseWriter, r *http.Request) { pagePath := path.Clean(r.RequestURI) - allRequestsByPathCounter.WithLabelValues(pagePath).Inc() allRequestsCounter.Inc() // Ensure the pagePath is relative to the root of a.SiteFiles. @@ -118,11 +121,10 @@ func (a Server) Serve(w http.ResponseWriter, r *http.Request) { message, status := CheckPageErrors(err) w.WriteHeader(status) fmt.Fprint(w, message) - allRequestsErrorsByPathCounter.WithLabelValues(pagePath, strconv.Itoa(status)).Inc() + allRequestsErrorsAggregatedCounter.WithLabelValues("404", strconv.Itoa(status)).Inc() return } - allRequestsErrorsByPathCounter.WithLabelValues(pagePath, "200").Inc() a.serve(w, page) } @@ -161,6 +163,7 @@ func (a Server) serve(w http.ResponseWriter, page Page) { } w.WriteHeader(200) + allHttp200RequestsByPathCounter.WithLabelValues(page.UrlPath, strconv.Itoa(200)).Inc() fmt.Fprint(w, page.Content) } diff --git a/justfile b/justfile new file mode 100644 index 0000000..006a8ab --- /dev/null +++ b/justfile @@ -0,0 +1,2 @@ +test: + go test -v ./...