-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathevents.go
191 lines (170 loc) · 4.97 KB
/
events.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package ldclient
import (
"time"
)
// An Event represents an analytics event generated by the client, which will be passed to
// the EventProcessor. The event data that the EventProcessor actually sends to LaunchDarkly
// may be slightly different.
type Event interface {
GetBase() BaseEvent
}
// BaseEvent provides properties common to all events.
type BaseEvent struct {
CreationDate uint64
User User
}
// FeatureRequestEvent is generated by evaluating a feature flag or one of a flag's prerequisites.
type FeatureRequestEvent struct {
BaseEvent
Key string
Variation *int
Value interface{}
Default interface{}
Version *int
PrereqOf *string
Reason EvaluationReasonContainer
// Note, we need to use EvaluationReasonContainer here because FeatureRequestEvent can be
// deserialized by ld-relay.
TrackEvents bool
Debug bool
DebugEventsUntilDate *uint64
}
// CustomEvent is generated by calling the client's Track method.
type CustomEvent struct {
BaseEvent
Key string
Data interface{}
MetricValue *float64
}
// IdentifyEvent is generated by calling the client's Identify method.
type IdentifyEvent struct {
BaseEvent
}
// IndexEvent is generated internally to capture user details from other events.
type IndexEvent struct {
BaseEvent
}
// NewFeatureRequestEvent creates a feature request event. Normally, you don't need to call this;
// the event is created and queued automatically during feature flag evaluation.
//
// Deprecated: This function will be removed in a later release.
func NewFeatureRequestEvent(key string, flag *FeatureFlag, user User, variation *int, value, defaultVal interface{}, prereqOf *string) FeatureRequestEvent {
fre := FeatureRequestEvent{
BaseEvent: BaseEvent{
CreationDate: now(),
User: user,
},
Key: key,
Variation: variation,
Value: value,
Default: defaultVal,
PrereqOf: prereqOf,
}
if flag != nil {
fre.Version = &flag.Version
fre.TrackEvents = flag.TrackEvents
fre.DebugEventsUntilDate = flag.DebugEventsUntilDate
}
return fre
}
func newUnknownFlagEvent(key string, user User, defaultVal interface{}, reason EvaluationReason,
includeReason bool) FeatureRequestEvent {
fre := FeatureRequestEvent{
BaseEvent: BaseEvent{
CreationDate: now(),
User: user,
},
Key: key,
Value: defaultVal,
Default: defaultVal,
}
if includeReason {
fre.Reason.Reason = reason
}
return fre
}
func newSuccessfulEvalEvent(flag *FeatureFlag, user User, variation *int, value, defaultVal interface{},
reason EvaluationReason, includeReason bool, prereqOf *string) FeatureRequestEvent {
requireExperimentData := isExperiment(flag, reason)
fre := FeatureRequestEvent{
BaseEvent: BaseEvent{
CreationDate: now(),
User: user,
},
Key: flag.Key,
Version: &flag.Version,
Variation: variation,
Value: value,
Default: defaultVal,
PrereqOf: prereqOf,
TrackEvents: requireExperimentData || flag.TrackEvents,
DebugEventsUntilDate: flag.DebugEventsUntilDate,
}
if includeReason || requireExperimentData {
fre.Reason.Reason = reason
}
return fre
}
func isExperiment(flag *FeatureFlag, reason EvaluationReason) bool {
if reason == nil {
return false
}
switch r := reason.(type) {
case EvaluationReasonFallthrough:
return flag.TrackEventsFallthrough
case EvaluationReasonRuleMatch:
if r.RuleIndex >= 0 && r.RuleIndex < len(flag.Rules) {
return flag.Rules[r.RuleIndex].TrackEvents
}
}
return false
}
// GetBase returns the BaseEvent
func (evt FeatureRequestEvent) GetBase() BaseEvent {
return evt.BaseEvent
}
// NewCustomEvent constructs a new custom event, but does not send it. Typically, Track should be used to both create the
// event and send it to LaunchDarkly.
func NewCustomEvent(key string, user User, data interface{}) CustomEvent {
return newCustomEvent(key, user, data, nil)
}
func newCustomEvent(key string, user User, data interface{}, metricValue *float64) CustomEvent {
return CustomEvent{
BaseEvent: BaseEvent{
CreationDate: now(),
User: user,
},
Key: key,
Data: data,
MetricValue: metricValue,
}
}
// GetBase returns the BaseEvent
func (evt CustomEvent) GetBase() BaseEvent {
return evt.BaseEvent
}
// NewIdentifyEvent constructs a new identify event, but does not send it. Typically, Identify should be used to both create the
// event and send it to LaunchDarkly.
func NewIdentifyEvent(user User) IdentifyEvent {
return IdentifyEvent{
BaseEvent: BaseEvent{
CreationDate: now(),
User: user,
},
}
}
// GetBase returns the BaseEvent
func (evt IdentifyEvent) GetBase() BaseEvent {
return evt.BaseEvent
}
// GetBase returns the BaseEvent
func (evt IndexEvent) GetBase() BaseEvent {
return evt.BaseEvent
}
func now() uint64 {
return toUnixMillis(time.Now())
}
func toUnixMillis(t time.Time) uint64 {
ms := time.Duration(t.UnixNano()) / time.Millisecond
return uint64(ms)
}