Merge pull request #11 from mautrix/segment-to-rudderstack
add generic analytics section for segment compatible api
This commit is contained in:
commit
15bb0f8d18
7 changed files with 53 additions and 40 deletions
|
@ -26,27 +26,26 @@ import (
|
|||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
const SegmentURL = "https://api.segment.io/v1/track"
|
||||
|
||||
type SegmentClient struct {
|
||||
type AnalyticsClient struct {
|
||||
url string
|
||||
key string
|
||||
userID string
|
||||
log zerolog.Logger
|
||||
client http.Client
|
||||
}
|
||||
|
||||
var Segment SegmentClient
|
||||
var Analytics AnalyticsClient
|
||||
|
||||
func (sc *SegmentClient) trackSync(userID id.UserID, event string, properties map[string]interface{}) error {
|
||||
func (ac *AnalyticsClient) trackSync(userID id.UserID, event string, properties map[string]interface{}) error {
|
||||
var buf bytes.Buffer
|
||||
var segmentUserID string
|
||||
if Segment.userID != "" {
|
||||
segmentUserID = Segment.userID
|
||||
var analyticsUserId string
|
||||
if Analytics.userID != "" {
|
||||
analyticsUserId = Analytics.userID
|
||||
} else {
|
||||
segmentUserID = userID.String()
|
||||
analyticsUserId = userID.String()
|
||||
}
|
||||
err := json.NewEncoder(&buf).Encode(map[string]interface{}{
|
||||
"userId": segmentUserID,
|
||||
"userId": analyticsUserId,
|
||||
"event": event,
|
||||
"properties": properties,
|
||||
})
|
||||
|
@ -54,12 +53,12 @@ func (sc *SegmentClient) trackSync(userID id.UserID, event string, properties ma
|
|||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", SegmentURL, &buf)
|
||||
req, err := http.NewRequest(http.MethodPost, ac.url, &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.SetBasicAuth(sc.key, "")
|
||||
resp, err := sc.client.Do(req)
|
||||
req.SetBasicAuth(ac.key, "")
|
||||
resp, err := ac.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -70,12 +69,12 @@ func (sc *SegmentClient) trackSync(userID id.UserID, event string, properties ma
|
|||
return nil
|
||||
}
|
||||
|
||||
func (sc *SegmentClient) IsEnabled() bool {
|
||||
return len(sc.key) > 0
|
||||
func (ac *AnalyticsClient) IsEnabled() bool {
|
||||
return len(ac.key) > 0
|
||||
}
|
||||
|
||||
func (sc *SegmentClient) Track(userID id.UserID, event string, properties ...map[string]interface{}) {
|
||||
if !sc.IsEnabled() {
|
||||
func (ac *AnalyticsClient) Track(userID id.UserID, event string, properties ...map[string]interface{}) {
|
||||
if !ac.IsEnabled() {
|
||||
return
|
||||
} else if len(properties) > 1 {
|
||||
panic("Track should be called with at most one property map")
|
||||
|
@ -87,11 +86,11 @@ func (sc *SegmentClient) Track(userID id.UserID, event string, properties ...map
|
|||
props = properties[0]
|
||||
}
|
||||
props["bridge"] = "gmessages"
|
||||
err := sc.trackSync(userID, event, props)
|
||||
err := ac.trackSync(userID, event, props)
|
||||
if err != nil {
|
||||
sc.log.Err(err).Str("event", event).Msg("Error tracking event")
|
||||
ac.log.Err(err).Str("event", event).Msg("Error tracking event")
|
||||
} else {
|
||||
sc.log.Debug().Str("event", event).Msg("Tracked event")
|
||||
ac.log.Debug().Str("event", event).Msg("Tracked event")
|
||||
}
|
||||
}()
|
||||
}
|
|
@ -24,8 +24,11 @@ import (
|
|||
type Config struct {
|
||||
*bridgeconfig.BaseConfig `yaml:",inline"`
|
||||
|
||||
SegmentKey string `yaml:"segment_key"`
|
||||
SegmentUserID string `yaml:"segment_user_id"`
|
||||
Analytics struct {
|
||||
Host string `yaml:"host"`
|
||||
Token string `yaml:"token"`
|
||||
UserID string `yaml:"user_id"`
|
||||
}
|
||||
|
||||
Metrics struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
|
|
|
@ -25,8 +25,9 @@ import (
|
|||
func DoUpgrade(helper *up.Helper) {
|
||||
bridgeconfig.Upgrader.DoUpgrade(helper)
|
||||
|
||||
helper.Copy(up.Str|up.Null, "segment_key")
|
||||
helper.Copy(up.Str|up.Null, "segment_user_id")
|
||||
helper.Copy(up.Str|up.Null, "analytics", "host")
|
||||
helper.Copy(up.Str|up.Null, "analytics", "token")
|
||||
helper.Copy(up.Str|up.Null, "analytics", "user_id")
|
||||
|
||||
helper.Copy(up.Bool, "metrics", "enabled")
|
||||
helper.Copy(up.Str, "metrics", "listen")
|
||||
|
@ -104,7 +105,7 @@ var SpacedBlocks = [][]string{
|
|||
{"appservice", "database"},
|
||||
{"appservice", "id"},
|
||||
{"appservice", "as_token"},
|
||||
{"segment_key"},
|
||||
{"analytics"},
|
||||
{"metrics"},
|
||||
{"google_messages"},
|
||||
{"bridge"},
|
||||
|
|
|
@ -76,10 +76,14 @@ appservice:
|
|||
as_token: "This value is generated when generating the registration"
|
||||
hs_token: "This value is generated when generating the registration"
|
||||
|
||||
# Segment API key to track some events, like provisioning API login and encryption errors.
|
||||
segment_key: null
|
||||
# Optional user_id to use when sending Segment events. If null, defaults to using mxID.
|
||||
segment_user_id: null
|
||||
# Segment-compatible analytics endpoint for tracking some events, like provisioning API login and encryption errors.
|
||||
analytics:
|
||||
# Hostname of the tracking server. The path is hardcoded to /v1/track
|
||||
host: api.segment.io
|
||||
# API key to send with tracking requests. Tracking is disabled if this is null.
|
||||
token: null
|
||||
# Optional user ID for tracking events. If null, defaults to using Matrix user ID.
|
||||
user_id: null
|
||||
|
||||
# Prometheus config.
|
||||
metrics:
|
||||
|
|
20
main.go
20
main.go
|
@ -18,6 +18,7 @@ package main
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"net/url"
|
||||
"sync"
|
||||
|
||||
"go.mau.fi/util/configupgrade"
|
||||
|
@ -81,13 +82,18 @@ func (br *GMBridge) Init() {
|
|||
util.BrowserDetailsMessage.DeviceType = gmproto.DeviceType(deviceVal)
|
||||
}
|
||||
|
||||
Segment.log = br.ZLog.With().Str("component", "segment").Logger()
|
||||
Segment.key = br.Config.SegmentKey
|
||||
Segment.userID = br.Config.SegmentUserID
|
||||
if Segment.IsEnabled() {
|
||||
Segment.log.Info().Msg("Segment metrics are enabled")
|
||||
if Segment.userID != "" {
|
||||
Segment.log.Info().Str("user_id", Segment.userID).Msg("Overriding Segment user ID")
|
||||
Analytics.log = br.ZLog.With().Str("component", "segment").Logger()
|
||||
Analytics.url = (&url.URL{
|
||||
Scheme: "https",
|
||||
Host: br.Config.Analytics.Host,
|
||||
Path: "/v1/track",
|
||||
}).String()
|
||||
Analytics.key = br.Config.Analytics.Token
|
||||
Analytics.userID = br.Config.Analytics.UserID
|
||||
if Analytics.IsEnabled() {
|
||||
Analytics.log.Info().Msg("Analytics are enabled")
|
||||
if Analytics.userID != "" {
|
||||
Analytics.log.Info().Str("user_id", Analytics.userID).Msg("Overriding Analytics user ID")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -359,11 +359,11 @@ Loop:
|
|||
switch {
|
||||
case item.qr != "":
|
||||
log.Debug().Msg("Got code in QR channel")
|
||||
Segment.Track(user.MXID, "$qrcode_retrieved")
|
||||
Analytics.Track(user.MXID, "$qrcode_retrieved")
|
||||
jsonResponse(w, http.StatusOK, LoginResponse{Status: "qr", Code: item.qr})
|
||||
case item.err != nil:
|
||||
log.Err(item.err).Msg("Got error in QR channel")
|
||||
Segment.Track(user.MXID, "$login_failure")
|
||||
Analytics.Track(user.MXID, "$login_failure")
|
||||
var resp LoginResponse
|
||||
switch {
|
||||
case errors.Is(item.err, ErrLoginTimeout):
|
||||
|
@ -375,7 +375,7 @@ Loop:
|
|||
jsonResponse(w, http.StatusOK, resp)
|
||||
case item.success:
|
||||
log.Debug().Msg("Got pair success in QR channel")
|
||||
Segment.Track(user.MXID, "$login_success")
|
||||
Analytics.Track(user.MXID, "$login_success")
|
||||
jsonResponse(w, http.StatusOK, LoginResponse{Status: "success"})
|
||||
default:
|
||||
log.Error().Any("item_data", item).Msg("Unknown item in QR channel")
|
||||
|
|
2
user.go
2
user.go
|
@ -403,7 +403,7 @@ func (user *User) Login(maxAttempts int) (<-chan qrChannelItem, error) {
|
|||
user.loginInProgress.Store(false)
|
||||
return nil, fmt.Errorf("failed to connect to Google Messages: %w", err)
|
||||
}
|
||||
Segment.Track(user.MXID, "$login_start")
|
||||
Analytics.Track(user.MXID, "$login_start")
|
||||
ch := make(chan qrChannelItem, maxAttempts+2)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
user.cancelLogin = cancel
|
||||
|
|
Loading…
Reference in a new issue