forked from segmentio/analytics-go
-
Notifications
You must be signed in to change notification settings - Fork 2
/
context.go
127 lines (111 loc) · 4.11 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
package analytics
import (
"encoding/json"
"net"
"reflect"
)
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"`
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:"-"`
}
type AppInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
Build string `json:"build,omitempty"`
Namespace string `json:"namespace,omitempty"`
}
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"`
}
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"`
}
type LibraryInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
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"`
}
type NetworkInfo struct {
Bluetooth bool `json:"bluetooth,omitempty"`
Cellular bool `json:"cellular,omitempty"`
WIFI bool `json:"wifi,omitempty"`
Carrier string `json:"carrier,omitempty"`
}
type OSInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
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"`
}
type ReferrerInfo struct {
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
Link string `json:"link,omitempty"`
}
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))
}