Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion cmd/gateway/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/SwissDataScienceCenter/renku-gateway/internal/config"
"github.com/SwissDataScienceCenter/renku-gateway/internal/db"
"github.com/SwissDataScienceCenter/renku-gateway/internal/login"
"github.com/SwissDataScienceCenter/renku-gateway/internal/metrics"
"github.com/SwissDataScienceCenter/renku-gateway/internal/revproxy"
"github.com/SwissDataScienceCenter/renku-gateway/internal/sessions"
"github.com/SwissDataScienceCenter/renku-gateway/internal/tokenstore"
Expand Down Expand Up @@ -124,7 +125,18 @@ func main() {
}
revproxy.RegisterHandlers(e, gwMiddlewares...)
// Initialize login server
loginServer, err := login.NewLoginServer(login.WithConfig(gwConfig.Login), login.WithSessionStore(sessionStore), login.WithTokenStore(tokenStore))
loginOptions := []login.LoginServerOption{login.WithConfig(gwConfig.Login), login.WithSessionStore(sessionStore), login.WithTokenStore(tokenStore)}

if gwConfig.Posthog.Enabled {
metricsClient, err := metrics.NewPosthogClient(gwConfig.Posthog.ApiKey, gwConfig.Posthog.Host, gwConfig.Posthog.Environment)
if err != nil {
slog.Error("posthog client initializtion failed", "error", err)
os.Exit(1)
}
loginOptions = append(loginOptions, login.WithMetricsClient(metricsClient))
defer metricsClient.Close()
}
loginServer, err := login.NewLoginServer(loginOptions...)
Comment thread
Panaetius marked this conversation as resolved.
Outdated
if err != nil {
slog.Error("login handlers initialization failed", "error", err)
os.Exit(1)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/oapi-codegen/runtime v1.1.1
github.com/oklog/ulid/v2 v2.1.0
github.com/posthog/posthog-go v1.3.3
github.com/redis/go-redis/v9 v9.4.0
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.8.4
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posthog/posthog-go v1.3.3 h1:0b1JlfPDMKXGRgbTtqkSG6hsrlj8yW2tv2HS6Dn7wFk=
github.com/posthog/posthog-go v1.3.3/go.mod h1:uYC2l1Yktc8E+9FAHJ9QZG4vQf/NHJPD800Hsm7DzoM=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
Expand Down
1 change: 1 addition & 0 deletions internal/config/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Config struct {
Revproxy RevproxyConfig
Login LoginConfig
Redis RedisConfig
Posthog PosthogConfig
Monitoring MonitoringConfig
}

Expand Down
7 changes: 7 additions & 0 deletions internal/config/other.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ type RateLimits struct {
Rate float64
Burst int
}

type PosthogConfig struct {
Enabled bool
ApiKey string
Comment thread
Panaetius marked this conversation as resolved.
Outdated
Host string
Environment string
}
8 changes: 8 additions & 0 deletions internal/login/login_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type LoginServer struct {
providerStore oidc.ClientStore
sessions *sessions.SessionStore
tokenStore models.TokenStoreInterface
metricsClient models.MetricsClientInterface
}

func (l *LoginServer) RegisterHandlers(server *echo.Echo, commonMiddlewares ...echo.MiddlewareFunc) {
Expand Down Expand Up @@ -58,6 +59,13 @@ func WithTokenStore(store models.TokenStoreInterface) LoginServerOption {
}
}

func WithMetricsClient(client models.MetricsClientInterface) LoginServerOption {
return func(l *LoginServer) error {
l.metricsClient = client
return nil
}
}

// NewLoginServer creates a new LoginServer that handles the callbacks from oauth2
// and initiates the login flow for users.
func NewLoginServer(options ...LoginServerOption) (*LoginServer, error) {
Expand Down
6 changes: 6 additions & 0 deletions internal/login/login_server_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ func (l *LoginServer) nextAuthStep(
slog.Info("login completed", "requestID", utils.GetRequestID(c), "appRedirectURL", url)
// Save the session: ensure we save the session before sending redirects
l.sessions.Save(c)
// send product metrics
if l.metricsClient != nil {
if session, err := l.sessions.Get(c); err == nil {
l.metricsClient.UserLoggedIn(session.UserID)
}
}
return c.Redirect(http.StatusFound, url)
}
providerID := session.LoginSequence[0]
Expand Down
40 changes: 40 additions & 0 deletions internal/metrics/posthog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package metrics

import (
"crypto/md5"
"encoding/hex"

"github.com/posthog/posthog-go"
)

type PosthogMetricsClient struct {
posthogClient posthog.Client
}

func (p *PosthogMetricsClient) anonymizeUser(userId string) string {
hash := md5.Sum([]byte(userId))
Comment thread
leafty marked this conversation as resolved.
return hex.EncodeToString(hash[:])
}

func (p *PosthogMetricsClient) UserLoggedIn(userId string) error {
return p.posthogClient.Enqueue(posthog.Capture{DistinctId: p.anonymizeUser(userId), Event: "user_logged_in"})
}

func (p *PosthogMetricsClient) Close() {
p.posthogClient.Close()
}

func NewPosthogClient(apiKey string, host string, environment string) (*PosthogMetricsClient, error) {
Comment thread
Panaetius marked this conversation as resolved.
Outdated
client, err := posthog.NewWithConfig(
apiKey,
posthog.Config{
Endpoint: host,
DefaultEventProperties: posthog.Properties{"environment": environment},
},
)
if err != nil {
return &PosthogMetricsClient{}, err
Comment thread
Panaetius marked this conversation as resolved.
Outdated
}

return &PosthogMetricsClient{posthogClient: client}, nil
}
5 changes: 5 additions & 0 deletions internal/models/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package models

type MetricsClientInterface interface {
UserLoggedIn(userId string) error
}