mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-11 19:06:43 +00:00
feat(metrics): add metrics for successful logins and logouts
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/loginstatus"
|
||||
"github.com/nais/wonderwall/pkg/metrics"
|
||||
logentry "github.com/nais/wonderwall/pkg/middleware"
|
||||
"github.com/nais/wonderwall/pkg/openid"
|
||||
"github.com/nais/wonderwall/pkg/openid/client"
|
||||
@@ -120,4 +121,5 @@ func logSuccessfulLogin(r *http.Request, tokens *openid.Tokens, referer string)
|
||||
}
|
||||
|
||||
logentry.LogEntry(r).WithFields(fields).Info("callback: successful login")
|
||||
metrics.ObserveLogin()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/cookie"
|
||||
"github.com/nais/wonderwall/pkg/metrics"
|
||||
logentry "github.com/nais/wonderwall/pkg/middleware"
|
||||
)
|
||||
|
||||
@@ -31,14 +32,19 @@ func (h *Handler) FrontChannelLogout(w http.ResponseWriter, r *http.Request) {
|
||||
sessionData, err := h.getSession(r, sessionID)
|
||||
if err != nil {
|
||||
logger.Infof("front-channel logout: getting session (user might already be logged out): %+v", err)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.destroySession(w, r, sessionID)
|
||||
if err != nil {
|
||||
logger.Warnf("front-channel logout: destroying session: %+v", err)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
return
|
||||
} else if sessionData != nil {
|
||||
logger.WithField("jti", sessionData.IDTokenJwtID).Infof("front-channel logout: successful logout")
|
||||
}
|
||||
|
||||
metrics.ObserveLogout(metrics.LogoutOperationFrontChannel)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/nais/wonderwall/pkg/cookie"
|
||||
"github.com/nais/wonderwall/pkg/metrics"
|
||||
logentry "github.com/nais/wonderwall/pkg/middleware"
|
||||
"github.com/nais/wonderwall/pkg/session"
|
||||
)
|
||||
@@ -46,5 +47,6 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
logger.Info("logout: redirecting to identity provider")
|
||||
metrics.ObserveLogout(metrics.LogoutOperationSelfInitiated)
|
||||
http.Redirect(w, r, logout.SingleLogoutURL(idToken), http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,29 @@ import (
|
||||
const (
|
||||
Namespace = "wonderwall"
|
||||
|
||||
RedisOperationLabel = "operation"
|
||||
LabelOperation = "operation"
|
||||
LabelHpa = "hpa"
|
||||
)
|
||||
|
||||
type Hpa = string
|
||||
|
||||
const (
|
||||
HpaRate = "rate"
|
||||
)
|
||||
|
||||
type LogoutOperation = string
|
||||
|
||||
const (
|
||||
LogoutOperationSelfInitiated = "self_initiated"
|
||||
LogoutOperationFrontChannel = "front_channel"
|
||||
)
|
||||
|
||||
type RedisOperation = string
|
||||
|
||||
const (
|
||||
RedisOperationRead = "Read"
|
||||
RedisOperationWrite = "Write"
|
||||
RedisOperationDelete = "Delete"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -20,11 +42,51 @@ var (
|
||||
Namespace: Namespace,
|
||||
Help: "latency in redis operations",
|
||||
Buckets: prometheus.ExponentialBuckets(0.02, 2, 14),
|
||||
}, []string{RedisOperationLabel})
|
||||
}, []string{LabelOperation})
|
||||
|
||||
Logins = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "logins",
|
||||
Namespace: Namespace,
|
||||
Help: "cumulative number of successful logins",
|
||||
},
|
||||
[]string{
|
||||
LabelHpa,
|
||||
},
|
||||
)
|
||||
|
||||
Logouts = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "logouts",
|
||||
Namespace: Namespace,
|
||||
Help: "cumulative number of successful logouts",
|
||||
},
|
||||
[]string{
|
||||
LabelOperation,
|
||||
LabelHpa,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
// InitLabels zeroes out all possible label combinations
|
||||
func InitLabels() {
|
||||
logoutOperations := []LogoutOperation{LogoutOperationSelfInitiated, LogoutOperationFrontChannel}
|
||||
|
||||
for _, operation := range logoutOperations {
|
||||
Logouts.With(prometheus.Labels{
|
||||
LabelOperation: operation,
|
||||
LabelHpa: HpaRate,
|
||||
})
|
||||
}
|
||||
|
||||
Logins.With(prometheus.Labels{
|
||||
LabelHpa: HpaRate,
|
||||
})
|
||||
}
|
||||
|
||||
func Handle(address string) error {
|
||||
Register(prometheus.DefaultRegisterer)
|
||||
InitLabels()
|
||||
handler := promhttp.Handler()
|
||||
return http.ListenAndServe(address, handler)
|
||||
}
|
||||
@@ -32,6 +94,8 @@ func Handle(address string) error {
|
||||
func Register(registry prometheus.Registerer) {
|
||||
registry.MustRegister(
|
||||
RedisLatency,
|
||||
Logins,
|
||||
Logouts,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,7 +104,20 @@ func ObserveRedisLatency(operation string, fun func() error) error {
|
||||
err := fun()
|
||||
used := time.Now().Sub(timer)
|
||||
RedisLatency.With(prometheus.Labels{
|
||||
RedisOperationLabel: operation,
|
||||
LabelOperation: operation,
|
||||
}).Observe(used.Seconds())
|
||||
return err
|
||||
}
|
||||
|
||||
func ObserveLogin() {
|
||||
Logins.With(prometheus.Labels{
|
||||
LabelHpa: HpaRate,
|
||||
}).Inc()
|
||||
}
|
||||
|
||||
func ObserveLogout(operation LogoutOperation) {
|
||||
Logouts.With(prometheus.Labels{
|
||||
LabelOperation: operation,
|
||||
LabelHpa: HpaRate,
|
||||
}).Inc()
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func NewRedis(client redis.Cmdable) Store {
|
||||
|
||||
func (s *redisSessionStore) Read(ctx context.Context, key string) (*EncryptedData, error) {
|
||||
encryptedData := &EncryptedData{}
|
||||
err := metrics.ObserveRedisLatency("Read", func() error {
|
||||
err := metrics.ObserveRedisLatency(metrics.RedisOperationRead, func() error {
|
||||
return s.client.Get(ctx, key).Scan(encryptedData)
|
||||
})
|
||||
if err == nil {
|
||||
@@ -40,13 +40,13 @@ func (s *redisSessionStore) Read(ctx context.Context, key string) (*EncryptedDat
|
||||
}
|
||||
|
||||
func (s *redisSessionStore) Write(ctx context.Context, key string, value *EncryptedData, expiration time.Duration) error {
|
||||
return metrics.ObserveRedisLatency("Write", func() error {
|
||||
return metrics.ObserveRedisLatency(metrics.RedisOperationWrite, func() error {
|
||||
return s.client.Set(ctx, key, value, expiration).Err()
|
||||
})
|
||||
}
|
||||
|
||||
func (s *redisSessionStore) Delete(ctx context.Context, keys ...string) error {
|
||||
err := metrics.ObserveRedisLatency("Delete", func() error {
|
||||
err := metrics.ObserveRedisLatency(metrics.RedisOperationDelete, func() error {
|
||||
return s.client.Del(ctx, keys...).Err()
|
||||
})
|
||||
if err == nil {
|
||||
|
||||
Reference in New Issue
Block a user