969cf76a1d0dfeb368b0ee115a83f27b954b4850

Author
Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
Committer
GitHub <noreply@github.com>
Date

Message

fix: metric cardinality et al (#315)

Diff

This diff is truncated to protect this page.

  1diff --git a/server/cmd/cmd.go b/server/cmd/cmd.go
  2index c30dd8b29c69a3cc6a284b4655cb1a78699a39ac..16d89d1639fd2153899a90da431e7e7fbe8fa448 100644
  3--- a/server/cmd/cmd.go
  4+++ b/server/cmd/cmd.go
  5@@ -15,13 +15,20 @@ import (
  6 	"github.com/charmbracelet/soft-serve/server/utils"
  7 	"github.com/charmbracelet/ssh"
  8 	"github.com/charmbracelet/wish"
  9+	"github.com/prometheus/client_golang/prometheus"
 10+	"github.com/prometheus/client_golang/prometheus/promauto"
 11 	"github.com/spf13/cobra"
 12 )
 13 
 14-var (
 15-	// sessionCtxKey is the key for the session in the context.
 16-	sessionCtxKey = &struct{ string }{"session"}
 17-)
 18+// sessionCtxKey is the key for the session in the context.
 19+var sessionCtxKey = &struct{ string }{"session"}
 20+
 21+var cliCommandCounter = promauto.NewCounterVec(prometheus.CounterOpts{
 22+	Namespace: "soft_serve",
 23+	Subsystem: "cli",
 24+	Name:      "commands_total",
 25+	Help:      "Total times each command was called",
 26+}, []string{"command"})
 27 
 28 var templateFuncs = template.FuncMap{
 29 	"trim":                    strings.TrimSpace,
 30@@ -75,8 +82,16 @@ func rpad(s string, padding int) string {
 31 	return fmt.Sprintf(template, s)
 32 }
 33 
 34+func cmdName(args []string) string {
 35+	if len(args) == 0 {
 36+		return ""
 37+	}
 38+	return args[0]
 39+}
 40+
 41 // rootCommand is the root command for the server.
 42 func rootCommand(cfg *config.Config, s ssh.Session) *cobra.Command {
 43+	cliCommandCounter.WithLabelValues(cmdName(s.Command())).Inc()
 44 	rootCmd := &cobra.Command{
 45 		Short:        "Soft Serve is a self-hostable Git server for the command line.",
 46 		SilenceUsage: true,
 47diff --git a/server/ssh/session.go b/server/ssh/session.go
 48index b39e15e24cc305c14eac1f59c777c0baa5f20f52..26ee3a5032b881c9f8f2670bd3daf7accc850bb1 100644
 49--- a/server/ssh/session.go
 50+++ b/server/ssh/session.go
 51@@ -2,6 +2,7 @@ package ssh
 52 
 53 import (
 54 	"strings"
 55+	"time"
 56 
 57 	tea "github.com/charmbracelet/bubbletea"
 58 	"github.com/charmbracelet/log"
 59@@ -19,19 +20,23 @@ import (
 60 	"github.com/prometheus/client_golang/prometheus/promauto"
 61 )
 62 
 63-var (
 64-	tuiSessionCounter = promauto.NewCounterVec(prometheus.CounterOpts{
 65-		Namespace: "soft_serve",
 66-		Subsystem: "ssh",
 67-		Name:      "tui_session_total",
 68-		Help:      "The total number of TUI sessions",
 69-	}, []string{"key", "user", "repo", "term"})
 70-)
 71+var tuiSessionCounter = promauto.NewCounterVec(prometheus.CounterOpts{
 72+	Namespace: "soft_serve",
 73+	Subsystem: "ssh",
 74+	Name:      "tui_session_total",
 75+	Help:      "The total number of TUI sessions",
 76+}, []string{"repo", "term"})
 77+
 78+var tuiSessionDuration = promauto.NewCounterVec(prometheus.CounterOpts{
 79+	Namespace: "soft_serve",
 80+	Subsystem: "ssh",
 81+	Name:      "tui_session_seconds_total",
 82+	Help:      "The total number of TUI sessions",
 83+}, []string{"repo", "term"})
 84 
 85 // SessionHandler is the soft-serve bubbletea ssh session handler.
 86 func SessionHandler(cfg *config.Config) bm.ProgramHandler {
 87 	return func(s ssh.Session) *tea.Program {
 88-		ak := backend.MarshalAuthorizedKey(s.PublicKey())
 89 		pty, _, active := s.Pty()
 90 		if !active {
 91 			return nil
 92@@ -61,9 +66,16 @@ func SessionHandler(cfg *config.Config) bm.ProgramHandler {
 93 			tea.WithAltScreen(),
 94 			tea.WithoutCatchPanics(),
 95 			tea.WithMouseCellMotion(),
 96+			tea.WithContext(ctx),
 97 		)
 98 
 99-		tuiSessionCounter.WithLabelValues(ak, s.User(), initialRepo, pty.Term).Inc()
100+		tuiSessionCounter.WithLabelValues(initialRepo, pty.Term).Inc()
101+
102+		start := time.Now()
103+		go func() {
104+			<-ctx.Done()
105+			tuiSessionDuration.WithLabelValues(initialRepo, pty.Term).Add(time.Since(start).Seconds())
106+		}()
107 
108 		return p
109 	}
110diff --git a/server/ssh/ssh.go b/server/ssh/ssh.go
111index 6e727fbd2431fa2d81631f44f025266e4808215f..42cd7f5f543044881d79af9725e9c4a55211d277 100644
112--- a/server/ssh/ssh.go
113+++ b/server/ssh/ssh.go
114@@ -35,42 +35,63 @@ var (
115 		Subsystem: "ssh",
116 		Name:      "public_key_auth_total",
117 		Help:      "The total number of public key auth requests",
118-	}, []string{"key", "user", "allowed"})
119+	}, []string{"allowed"})
120 
121 	keyboardInteractiveCounter = promauto.NewCounterVec(prometheus.CounterOpts{
122 		Namespace: "soft_serve",
123 		Subsystem: "ssh",
124 		Name:      "keyboard_interactive_auth_total",
125 		Help:      "The total number of keyboard interactive auth requests",
126-	}, []string{"user", "allowed"})
127+	}, []string{"allowed"})
128 
129 	uploadPackCounter = promauto.NewCounterVec(prometheus.CounterOpts{
130 		Namespace: "soft_serve",
131-		Subsystem: "ssh",
132-		Name:      "git_upload_pack_total",
133+		Subsystem: "git",
134+		Name:      "upload_pack_total",
135 		Help:      "The total number of git-upload-pack requests",
136-	}, []string{"key", "user", "repo"})
137+	}, []string{"repo"})
138 
139 	receivePackCounter = promauto.NewCounterVec(prometheus.CounterOpts{
140 		Namespace: "soft_serve",
141-		Subsystem: "ssh",
142-		Name:      "git_receive_pack_total",
143+		Subsystem: "git",
144+		Name:      "receive_pack_total",
145 		Help:      "The total number of git-receive-pack requests",
146-	}, []string{"key", "user", "repo"})
147+	}, []string{"repo"})
148 
149 	uploadArchiveCounter = promauto.NewCounterVec(prometheus.CounterOpts{
150 		Namespace: "soft_serve",
151-		Subsystem: "ssh",
152-		Name:      "git_upload_archive_total",
153+		Subsystem: "git",
154+		Name:      "upload_archive_total",
155 		Help:      "The total number of git-upload-archive requests",
156-	}, []string{"key", "user", "repo"})
157+	}, []string{"repo"})
158+
159+	uploadPackSeconds = promauto.NewCounterVec(prometheus.CounterOpts{
160+		Namespace: "soft_serve",
161+		Subsystem: "git",
162+		Name:      "upload_pack_seconds_total",
163+		Help:      "The total time spent on git-upload-pack requests",
164+	}, []string{"repo"})
165+
166+	receivePackSeconds = promauto.NewCounterVec(prometheus.CounterOpts{
167+		Namespace: "soft_serve",
168+		Subsystem: "git",
169+		Name:      "receive_pack_seconds_total",
170+		Help:      "The total time spent on git-receive-pack requests",
171+	}, []string{"repo"})
172+
173+	uploadArchiveSeconds = promauto.NewCounterVec(prometheus.CounterOpts{
174+		Namespace: "soft_serve",
175+		Subsystem: "git",
176+		Name:      "upload_archive_seconds_total",
177+		Help:      "The total time spent on git-upload-archive requests",
178+	}, []string{"repo"})
179 
180 	createRepoCounter = promauto.NewCounterVec(prometheus.CounterOpts{
181 		Namespace: "soft_serve",
182 		Subsystem: "ssh",
183 		Name:      "create_repo_total",
184 		Help:      "The total number of create repo requests",
185-	}, []string{"key", "user", "repo"})
186+	}, []string{"repo"})
187 )
188 
189 // SSHServer is a SSH server that implements the git protocol.
190@@ -168,7 +189,7 @@ func (s *SSHServer) PublicKeyHandler(ctx ssh.Context, pk ssh.PublicKey) (allowed
191 
192 	ak := backend.MarshalAuthorizedKey(pk)
193 	defer func(allowed *bool) {
194-		publicKeyCounter.WithLabelValues(ak, ctx.User(), strconv.FormatBool(*allowed)).Inc()
195+		publicKeyCounter.WithLabelValues(strconv.FormatBool(*allowed)).Inc()
196 	}(&allowed)
197 
198 	ac := s.cfg.Backend.AccessLevelByPublicKey("", pk)
199@@ -181,7 +202,7 @@ func (s *SSHServer) PublicKeyHandler(ctx ssh.Context, pk ssh.PublicKey) (allowed
200 // This is used after all public key authentication has failed.
201 func (s *SSHServer) KeyboardInteractiveHandler(ctx ssh.Context, _ gossh.KeyboardInteractiveChallenge) bool {
202 	ac := s.cfg.Backend.AllowKeyless()
203-	keyboardInteractiveCounter.WithLabelValues(ctx.User(), strconv.FormatBool(ac)).Inc()
204+	keyboardInteractiveCounter.WithLabelValues(strconv.FormatBool(ac)).Inc()
205 	return ac
206 }
207 
208@@ -194,6 +215,7 @@ func (ss *SSHServer) Middleware(cfg *config.Config) wish.Middleware {
209 	return func(sh ssh.Handler) ssh.Handler {
210 		return func(s ssh.Session) {
211 			func() {
212+				start := time.Now()
213 				cmd := s.Command()