From a64565a10cfa39b09b5f9699f409f198ffdfdc3e Mon Sep 17 00:00:00 2001
From: gjahn <gregor.jahn@bht-berlin.de>
Date: Wed, 20 Dec 2023 00:40:52 +0100
Subject: [PATCH] Add /metrics path supporting Prometheus-compatible Exposition
 format

See https://github.com/prometheus/docs/blob/496a6ee5ffea8a08f42f98cc7208256d300be015/content/docs/instrumenting/exposition_formats.md
---
 routing/routes.go    | 34 ++++++++++++++++++++++++++++++++++
 routing/templates.go | 11 +++++++++++
 2 files changed, 45 insertions(+)

diff --git a/routing/routes.go b/routing/routes.go
index 3611c33..72ebb06 100644
--- a/routing/routes.go
+++ b/routing/routes.go
@@ -25,6 +25,11 @@ func SetRoutes( router *f.App, config *configuration.Config, store state.Store,
         return err
     }
 
+    metricsTextTemplate, err := template.New( "metrics" ).Parse( metricsText )
+    if err != nil {
+        return err
+    }
+
     if config.LogLevel == "debug" {
         router.All( "*", func( c *f.Ctx ) error {
             log.Printf( "%s %s  mime:%s  agent:%s",
@@ -90,6 +95,35 @@ func SetRoutes( router *f.App, config *configuration.Config, store state.Store,
     })
 
 
+    router.Get( "/metrics", func( c *f.Ctx ) error {
+        headers := c.GetReqHeaders()
+        acceptHeader := strings.Join( headers[ "Accept" ], " " )
+        buffer := &bytes.Buffer{}
+
+        if strings.Contains( acceptHeader , "json" ) {
+            // FUTUREWORK: implement https://opentelemetry.io/docs/specs/otlp/#otlphttp
+            return c.SendStatus( http.StatusNotAcceptable )
+        } else {
+            names, err := store.List()
+            if err != nil {
+                return c.SendStatus( http.StatusInternalServerError )
+            }
+
+            data := metricsTextData{
+                Count: len( names ),
+            }
+
+            err = metricsTextTemplate.Execute( buffer, data )
+            if err != nil {
+                return err
+            }
+
+            c.Set( "Content-Type", "text/plain; charset=utf-8" )
+            return c.Send( buffer.Bytes() )
+        }
+    })
+
+
     router.Get( "/env", func( c *f.Ctx ) error {
         c.Type( "txt", "utf-8" )
 
diff --git a/routing/templates.go b/routing/templates.go
index 5e06f29..dd99caa 100644
--- a/routing/templates.go
+++ b/routing/templates.go
@@ -20,3 +20,14 @@ type indexHtmlData struct {
     Version string
     Color   string
 }
+
+
+const metricsText = `
+    # HELP state_entries_quantity The current number of state entries being stored
+    # TYPE state_entries_quantity gauge
+    state_entries_quantity {{ .Count }}
+`
+
+type metricsTextData struct {
+    Count int
+}
-- 
GitLab