Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/common-go/analytics/analytics.go
2498 views
1
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package analytics
6
7
import (
8
"os"
9
"time"
10
11
"github.com/gitpod-io/gitpod/common-go/log"
12
segment "gopkg.in/segmentio/analytics-go.v3"
13
)
14
15
// Identity identifies a user
16
type Identity struct {
17
UserID string
18
AnonymousID string
19
}
20
21
// IdentifyMessage parametrises the Identify call
22
type IdentifyMessage struct {
23
Identity
24
25
Traits map[string]interface{}
26
Timestamp time.Time
27
}
28
29
// TrackMessage parametrises the Track call
30
type TrackMessage struct {
31
Identity
32
33
Event string
34
Properties map[string]interface{}
35
Timestamp time.Time
36
}
37
38
// NewFromEnvironment creates a new analytics writer based on the GITPOD_ANALYTICS_WRITER
39
// environment variable. This function never returns nil and callers are expected to call
40
// Close() on the received writer.
41
func NewFromEnvironment() Writer {
42
switch os.Getenv("GITPOD_ANALYTICS_WRITER") {
43
case "log":
44
log.Debug("log analytics")
45
return &logAnalyticsWriter{}
46
case "segment":
47
log.Debug("segment analytics")
48
client, err := segment.NewWithConfig(os.Getenv("GITPOD_ANALYTICS_SEGMENT_KEY"), segment.Config{
49
Endpoint: os.Getenv("GITPOD_ANALYTICS_SEGMENT_ENDPOINT"),
50
})
51
if err != nil {
52
log.WithError(err).Error("cannot create segment client")
53
return &noAnalyticsWriter{}
54
}
55
return &segmentAnalyticsWriter{client}
56
default:
57
log.Debug("no analytics")
58
return &noAnalyticsWriter{}
59
}
60
}
61
62
// Writer can write analytics
63
type Writer interface {
64
Identify(IdentifyMessage)
65
Track(TrackMessage)
66
Close() error
67
}
68
69
type logAnalyticsWriter struct{}
70
71
func (s *logAnalyticsWriter) Identify(m IdentifyMessage) {
72
log.WithField("message", m).Debug("analytics identify")
73
}
74
75
func (s *logAnalyticsWriter) Track(m TrackMessage) {
76
log.WithField("message", m).Debug("analytics track")
77
}
78
79
func (s *logAnalyticsWriter) Close() error { return nil }
80
81
type noAnalyticsWriter struct{}
82
83
func (s *noAnalyticsWriter) Identify(m IdentifyMessage) {}
84
func (s *noAnalyticsWriter) Track(m TrackMessage) {}
85
func (s *noAnalyticsWriter) Close() error { return nil }
86
87
type segmentAnalyticsWriter struct {
88
Client segment.Client
89
}
90
91
func (s *segmentAnalyticsWriter) Identify(m IdentifyMessage) {
92
defer recover()
93
94
_ = s.Client.Enqueue(segment.Identify{
95
AnonymousId: m.AnonymousID,
96
UserId: m.UserID,
97
Timestamp: m.Timestamp,
98
Traits: m.Traits,
99
})
100
}
101
102
func (s *segmentAnalyticsWriter) Track(m TrackMessage) {
103
defer recover()
104
105
_ = s.Client.Enqueue(segment.Track{
106
AnonymousId: m.AnonymousID,
107
UserId: m.UserID,
108
Event: m.Event,
109
Timestamp: m.Timestamp,
110
Properties: m.Properties,
111
})
112
}
113
114
func (s *segmentAnalyticsWriter) Close() error {
115
defer recover()
116
117
return s.Client.Close()
118
}
119
120