forked from segmentio/analytics-go
-
Notifications
You must be signed in to change notification settings - Fork 1
/
context.go
148 lines (132 loc) · 5.52 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
package analytics
import (
"encoding/json"
"net"
"reflect"
)
// Context 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"`
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:"-"`
}
// AppInfo 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"`
}
// CampaignInfo 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"`
}
// DeviceInfo 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"`
}
// LibraryInfo 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"`
}
// LocationInfo 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"`
}
// NetworkInfo 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"`
}
// OSInfo 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"`
}
// PageInfo 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"`
}
// ReferrerInfo 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"`
}
// ScreenInfo 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"`
}
// MarshalJSON satisfies 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))
}