Jelajahi Sumber

Implemented more structured way of working with analytics package

jnfrati 4 tahun lalu
induk
melakukan
d113c52fc2

+ 46 - 0
internal/analytics/identifiers.go

@@ -0,0 +1,46 @@
+package analytics
+
+import (
+	"fmt"
+
+	"github.com/porter-dev/porter/internal/models"
+	segment "gopkg.in/segmentio/analytics-go.v3"
+)
+
+type SegmentIdentifier interface {
+	getUserId() string
+	getTraits() segment.Traits
+}
+
+type SegmentIdentifyNewUser struct {
+	userId    string
+	userEmail string
+	isGithub  bool
+}
+
+func CreateSegmentIdentifyNewUser(user *models.User, registeredViaGithub bool) *SegmentIdentifyNewUser {
+	userId := fmt.Sprintf("%v", user.ID)
+	return &SegmentIdentifyNewUser{
+		userId:    userId,
+		userEmail: user.Email,
+		isGithub:  registeredViaGithub,
+	}
+}
+
+func (i SegmentIdentifyNewUser) getUserId() string {
+	return i.userId
+}
+
+func (i SegmentIdentifyNewUser) getTraits() segment.Traits {
+	var githubTrait string
+
+	if i.isGithub {
+		githubTrait = "true"
+	} else {
+		githubTrait = "false"
+	}
+
+	return segment.NewTraits().
+		SetEmail(i.userEmail).
+		Set("github", githubTrait)
+}

+ 36 - 17
internal/analytics/segment.go

@@ -1,63 +1,82 @@
 package analytics
 
 import (
-	"fmt"
-
+	"github.com/porter-dev/porter/internal/logger"
 	segment "gopkg.in/segmentio/analytics-go.v3"
 )
 
 type AnalyticsSegmentClient interface {
-	Identify(userId string, userEmail string, isGithub bool) error
-	Track(userId string, event string, properties segment.Properties) error
+	Identify(SegmentIdentifier) error
+	Track(SegmentTrack) error
 }
 
 type AnalyticsSegment struct {
 	segment.Client
 	isEnabled bool
+	logger    *logger.Logger
 }
 
-func Initialize(segmentClientKey string) AnalyticsSegmentClient {
+//
+/*
+	Initialize the segment client and return a superset of it, the AnalyticsSegmentClient will handle cases when
+	the segment client failed on initialization or not enabled
+*/
+func Initialize(segmentClientKey string, logger *logger.Logger) AnalyticsSegmentClient {
 	if segmentClientKey != "" {
 
 		client := segment.New(segmentClientKey)
 
+		if client == nil {
+			return &AnalyticsSegment{
+				isEnabled: false,
+				logger:    logger,
+			}
+		}
+
 		return &AnalyticsSegment{
 			Client:    client,
 			isEnabled: true,
+			logger:    logger,
 		}
 	}
 
 	return &AnalyticsSegment{
 		isEnabled: false,
+		logger:    logger,
 	}
 }
 
-func (c *AnalyticsSegment) Identify(userId string, userEmail string, isGithub bool) error {
-
+/*
+	Superset of segment client identify function, this will accept analytics defined identifiers only
+	and will log an error if the client is not initialized
+*/
+func (c *AnalyticsSegment) Identify(identifier SegmentIdentifier) error {
 	if !c.isEnabled {
-		fmt.Println("Analytics not enabled")
+		c.logger.Error().Msg("Analytics not enabled")
 		return nil
 	}
 
 	err := c.Enqueue(segment.Identify{
-		UserId: userId,
-		Traits: segment.NewTraits().
-			SetEmail(userEmail).
-			Set("github", isGithub),
+		UserId: identifier.getUserId(),
+		Traits: identifier.getTraits(),
 	})
 	return err
 }
 
-func (c *AnalyticsSegment) Track(userId string, event string, properties segment.Properties) error {
+/*
+	Superset of segment client track function, this will accept analytics defined tracks only
+	and will log an error if the client is not initialized
+*/
+func (c *AnalyticsSegment) Track(track SegmentTrack) error {
 	if !c.isEnabled {
-		fmt.Println("Analytics not enabled")
+		c.logger.Error().Msg("Analytics not enabled")
 		return nil
 	}
 
 	err := c.Enqueue(segment.Track{
-		UserId:     userId,
-		Event:      event,
-		Properties: properties,
+		UserId:     track.getUserId(),
+		Event:      string(track.getEvent()),
+		Properties: track.getProperties(),
 	})
 
 	return err

+ 8 - 0
internal/analytics/track_events.go

@@ -0,0 +1,8 @@
+package analytics
+
+type SegmentEvent string
+
+const (
+	NewUser            SegmentEvent = "New User"
+	RedeployViaWebhook SegmentEvent = "Triggered Re-deploy via Webhook"
+)

+ 64 - 0
internal/analytics/tracks.go

@@ -0,0 +1,64 @@
+package analytics
+
+import (
+	"fmt"
+
+	"github.com/porter-dev/porter/internal/models"
+	segment "gopkg.in/segmentio/analytics-go.v3"
+)
+
+type SegmentTrack interface {
+	getUserId() string
+	getEvent() SegmentEvent
+	getProperties() segment.Properties
+}
+
+type SegmentNewUserTrack struct {
+	userId    string
+	userEmail string
+}
+
+func CreateSegmentNewUserTrack(user *models.User) *SegmentNewUserTrack {
+	userId := fmt.Sprintf("%v", user.ID)
+
+	return &SegmentNewUserTrack{
+		userId:    userId,
+		userEmail: user.Email,
+	}
+}
+
+func (t *SegmentNewUserTrack) getUserId() string {
+	return t.userId
+}
+
+func (t *SegmentNewUserTrack) getEvent() SegmentEvent {
+	return NewUser
+}
+
+func (t *SegmentNewUserTrack) getProperties() segment.Properties {
+	return segment.NewProperties().Set("email", t.userEmail)
+}
+
+type SegmentRedeployViaWebhookTrack struct {
+	userId     string
+	repository interface{}
+}
+
+func CreateSegmentRedeployViaWebhookTrack(userId string, repository interface{}) *SegmentRedeployViaWebhookTrack {
+	return &SegmentRedeployViaWebhookTrack{
+		userId:     userId,
+		repository: repository,
+	}
+}
+
+func (t *SegmentRedeployViaWebhookTrack) getUserId() string {
+	return t.userId
+}
+
+func (t *SegmentRedeployViaWebhookTrack) getEvent() SegmentEvent {
+	return RedeployViaWebhook
+}
+
+func (t *SegmentRedeployViaWebhookTrack) getProperties() segment.Properties {
+	return segment.NewProperties().Set("repository", t.repository)
+}

+ 7 - 7
server/api/api.go

@@ -87,11 +87,11 @@ type App struct {
 	DOConf            *oauth2.Config
 	GoogleUserConf    *oauth2.Config
 
-	db            *gorm.DB
-	validator     *vr.Validate
-	translator    *ut.Translator
-	tokenConf     *token.TokenGeneratorConf
-	segmentClient analytics.AnalyticsSegmentClient
+	db              *gorm.DB
+	validator       *vr.Validate
+	translator      *ut.Translator
+	tokenConf       *token.TokenGeneratorConf
+	analyticsClient analytics.AnalyticsSegmentClient
 }
 
 type AppCapabilities struct {
@@ -211,8 +211,8 @@ func New(conf *AppConfig) (*App, error) {
 		TokenSecret: conf.ServerConf.TokenGeneratorSecret,
 	}
 
-	newSegmentClient := analytics.Initialize(sc.SegmentClientKey)
-	app.segmentClient = newSegmentClient
+	newSegmentClient := analytics.Initialize(sc.SegmentClientKey, app.Logger)
+	app.analyticsClient = newSegmentClient
 
 	return app, nil
 }

+ 3 - 4
server/api/oauth_github_handler.go

@@ -8,6 +8,7 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/porter-dev/porter/internal/analytics"
 	"github.com/porter-dev/porter/internal/models"
 	"gorm.io/gorm"
 
@@ -17,7 +18,6 @@ import (
 	"golang.org/x/oauth2"
 
 	"github.com/porter-dev/porter/internal/models/integrations"
-	segment "gopkg.in/segmentio/analytics-go.v3"
 )
 
 // HandleGithubOAuthStartUser starts the oauth2 flow for a user login request.
@@ -131,9 +131,8 @@ func (app *App) HandleGithubOAuthCallback(w http.ResponseWriter, r *http.Request
 		}
 
 		// send to segment
-		userId := fmt.Sprintf("%v", user.ID)
-		app.segmentClient.Identify(userId, user.Email, true)
-		app.segmentClient.Track(userId, "New User", segment.NewProperties().Set("email", user.Email))
+		app.analyticsClient.Identify(analytics.CreateSegmentIdentifyNewUser(user, true))
+		app.analyticsClient.Track(analytics.CreateSegmentNewUserTrack(user))
 
 		// log the user in
 		app.Logger.Info().Msgf("New user created: %d", user.ID)

+ 4 - 5
server/api/oauth_google_handler.go

@@ -8,13 +8,12 @@ import (
 	"net/url"
 	"strings"
 
+	"github.com/porter-dev/porter/internal/analytics"
 	"github.com/porter-dev/porter/internal/models"
 	"gorm.io/gorm"
 
 	"github.com/porter-dev/porter/internal/oauth"
 	"golang.org/x/oauth2"
-
-	segment "gopkg.in/segmentio/analytics-go.v3"
 )
 
 // HandleGoogleStartUser starts the oauth2 flow for a user login request.
@@ -96,9 +95,9 @@ func (app *App) HandleGoogleOAuthCallback(w http.ResponseWriter, r *http.Request
 	}
 
 	// send to segment
-	userId := fmt.Sprintf("%v", user.ID)
-	app.segmentClient.Identify(userId, user.Email, true)
-	app.segmentClient.Track(userId, "New User", segment.NewProperties().Set("email", user.Email))
+	app.analyticsClient.Identify(analytics.CreateSegmentIdentifyNewUser(user, true))
+
+	app.analyticsClient.Track(analytics.CreateSegmentNewUserTrack(user))
 
 	// log the user in
 	app.Logger.Info().Msgf("New user created: %d", user.ID)

+ 2 - 6
server/api/release_handler.go

@@ -9,6 +9,7 @@ import (
 	"strings"
 	"sync"
 
+	"github.com/porter-dev/porter/internal/analytics"
 	"github.com/porter-dev/porter/internal/kubernetes/prometheus"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/templater/parser"
@@ -24,7 +25,6 @@ import (
 	"github.com/porter-dev/porter/internal/integrations/ci/actions"
 	"github.com/porter-dev/porter/internal/kubernetes"
 	"github.com/porter-dev/porter/internal/repository"
-	segment "gopkg.in/segmentio/analytics-go.v3"
 	"gopkg.in/yaml.v2"
 )
 
@@ -1087,11 +1087,7 @@ func (app *App) HandleReleaseDeployWebhook(w http.ResponseWriter, r *http.Reques
 		return
 	}
 
-	app.segmentClient.Track(
-		"anonymous",
-		"Triggered Re-deploy via Webhook",
-		segment.NewProperties().Set("repository", repository),
-	)
+	app.analyticsClient.Track(analytics.CreateSegmentRedeployViaWebhookTrack("anonymous", repository))
 
 	w.WriteHeader(http.StatusOK)
 }

+ 3 - 4
server/api/user_handler.go

@@ -15,12 +15,12 @@ import (
 	"gorm.io/gorm"
 
 	"github.com/go-chi/chi"
+	"github.com/porter-dev/porter/internal/analytics"
 	"github.com/porter-dev/porter/internal/auth/token"
 	"github.com/porter-dev/porter/internal/forms"
 	"github.com/porter-dev/porter/internal/integrations/email"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/repository"
-	segment "gopkg.in/segmentio/analytics-go.v3"
 )
 
 // Enumeration of user API error codes, represented as int64
@@ -51,9 +51,8 @@ func (app *App) HandleCreateUser(w http.ResponseWriter, r *http.Request) {
 
 	if err == nil {
 		// send to segment
-		userId := fmt.Sprintf("%v", user.ID)
-		app.segmentClient.Identify(userId, user.Email, false)
-		app.segmentClient.Track(userId, "New User", segment.NewProperties().Set("email", user.Email))
+		app.analyticsClient.Identify(analytics.CreateSegmentIdentifyNewUser(user, false))
+		app.analyticsClient.Track(analytics.CreateSegmentNewUserTrack(user))
 
 		app.Logger.Info().Msgf("New user created: %d", user.ID)
 		var redirect string