-
Notifications
You must be signed in to change notification settings - Fork 89
/
context.go
150 lines (134 loc) · 5.6 KB
/
context.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
package analytics
import (
"encoding/json"
"net"
"reflect"
)
// This type provides the representation of the `context` object as defined in
// https://segment.com/docs/spec/common/#context
type Context struct {
App AppInfo `json:"app,omitempty"`
Campaign CampaignInfo `json:"campaign,omitempty"`
Device DeviceInfo `json:"device,omitempty"`
Library LibraryInfo `json:"library,omitempty"`
Location LocationInfo `json:"location,omitempty"`
Network NetworkInfo `json:"network,omitempty"`
OS OSInfo `json:"os,omitempty"`
Page PageInfo `json:"page,omitempty"`
Referrer ReferrerInfo `json:"referrer,omitempty"`
Screen ScreenInfo `json:"screen,omitempty"`
IP net.IP `json:"ip,omitempty"`
Direct bool `json:"direct,omitempty"`
Locale string `json:"locale,omitempty"`
GroupID string `json:"groupId,omitempty"`
Timezone string `json:"timezone,omitempty"`
UserAgent string `json:"userAgent,omitempty"`
Traits Traits `json:"traits,omitempty"`
// This map is used to allow extensions to the context specifications that
// may not be documented or could be introduced in the future.
// The fields of this map are inlined in the serialized context object,
// there is no actual "extra" field in the JSON representation.
Extra map[string]interface{} `json:"-"`
}
// This type provides the representation of the `context.app` object as defined
// in https://segment.com/docs/spec/common/#context
type AppInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
Build string `json:"build,omitempty"`
Namespace string `json:"namespace,omitempty"`
}
// This type provides the representation of the `context.campaign` object as
// defined in https://segment.com/docs/spec/common/#context
type CampaignInfo struct {
Name string `json:"name,omitempty"`
Source string `json:"source,omitempty"`
Medium string `json:"medium,omitempty"`
Term string `json:"term,omitempty"`
Content string `json:"content,omitempty"`
}
// This type provides the representation of the `context.device` object as
// defined in https://segment.com/docs/spec/common/#context
type DeviceInfo struct {
Id string `json:"id,omitempty"`
Manufacturer string `json:"manufacturer,omitempty"`
Model string `json:"model,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Version string `json:"version,omitempty"`
AdvertisingID string `json:"advertisingId,omitempty"`
}
// This type provides the representation of the `context.library` object as
// defined in https://segment.com/docs/spec/common/#context
type LibraryInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
// This type provides the representation of the `context.location` object as
// defined in https://segment.com/docs/spec/common/#context
type LocationInfo struct {
City string `json:"city,omitempty"`
Country string `json:"country,omitempty"`
Region string `json:"region,omitempty"`
Latitude float64 `json:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty"`
Speed float64 `json:"speed,omitempty"`
}
// This type provides the representation of the `context.network` object as
// defined in https://segment.com/docs/spec/common/#context
type NetworkInfo struct {
Bluetooth bool `json:"bluetooth,omitempty"`
Cellular bool `json:"cellular,omitempty"`
WIFI bool `json:"wifi,omitempty"`
Carrier string `json:"carrier,omitempty"`
}
// This type provides the representation of the `context.os` object as defined
// in https://segment.com/docs/spec/common/#context
type OSInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
// This type provides the representation of the `context.page` object as
// defined in https://segment.com/docs/spec/common/#context
type PageInfo struct {
Hash string `json:"hash,omitempty"`
Path string `json:"path,omitempty"`
Referrer string `json:"referrer,omitempty"`
Search string `json:"search,omitempty"`
Title string `json:"title,omitempty"`
URL string `json:"url,omitempty"`
}
// This type provides the representation of the `context.referrer` object as
// defined in https://segment.com/docs/spec/common/#context
type ReferrerInfo struct {
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
Link string `json:"link,omitempty"`
}
// This type provides the representation of the `context.screen` object as
// defined in https://segment.com/docs/spec/common/#context
type ScreenInfo struct {
Density int `json:"density,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
}
// Satisfy the `json.Marshaler` interface. We have to flatten out the `Extra`
// field but the standard json package doesn't support it yet.
// Implementing this interface allows us to override the default marshaling of
// the context object and to the inlining ourselves.
//
// Related discussion: https://github.com/golang/go/issues/6213
func (ctx Context) MarshalJSON() ([]byte, error) {
v := reflect.ValueOf(ctx)
n := v.NumField()
m := make(map[string]interface{}, n+len(ctx.Extra))
// Copy the `Extra` map into the map representation of the context, it is
// important to do this operation before going through the actual struct
// fields so the latter take precendence and override duplicated values
// that would be set in the extensions.
for name, value := range ctx.Extra {
m[name] = value
}
return json.Marshal(structToMap(v, m))
}