-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathdata_collection.go
More file actions
217 lines (190 loc) · 6.64 KB
/
Copy pathdata_collection.go
File metadata and controls
217 lines (190 loc) · 6.64 KB
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package sentry
import "slices"
// CollectionMode controls how key-value data (headers, cookies, query params) is collected.
//
// Defaults to CollectionDenyList.
type CollectionMode int
const (
// CollectionDenyList keeps all keys and filters denied values.
CollectionDenyList CollectionMode = iota
// CollectionOff disables collection of the category entirely.
CollectionOff
// CollectionAllowList keeps all keys and sends real values only for allowed keys.
CollectionAllowList
)
// KeyValueCollectionBehavior configures how key-value data is collected and filtered.
type KeyValueCollectionBehavior struct {
// Mode controls the collection strategy.
Mode CollectionMode
// Terms is a list of additional terms used by the active mode.
Terms []string
}
// HeaderCollectionConfig configures how HTTP headers are collected for
// requests and responses independently.
type HeaderCollectionConfig struct {
// Request configures collection of HTTP request headers.
Request *KeyValueCollectionBehavior
// Response configures collection of HTTP response headers.
Response *KeyValueCollectionBehavior
}
// BodyType identifies a category of HTTP body to collect.
type BodyType string
const (
// BodyIncomingRequest collects bodies from incoming HTTP requests
// (server-side).
BodyIncomingRequest BodyType = "incomingRequest"
// BodyOutgoingRequest collects bodies from outgoing HTTP requests
// (client-side).
BodyOutgoingRequest BodyType = "outgoingRequest"
// BodyIncomingResponse collects bodies from incoming HTTP responses
// (client-side).
BodyIncomingResponse BodyType = "incomingResponse"
)
// DataCollection configures what data the SDK collects automatically.
// All fields are optional. nil or zero-value fields use the documented
// defaults, which collect rich context for debugging while scrubbing sensitive
// values via a built-in denylist.
//
// See https://docs.sentry.io/platforms/go/configuration/options/#DataCollection
type DataCollection struct {
// UserInfo controls automatic population of user.* fields from auto-instrumentation.
//
// This does NOT gate data explicitly set via Scope.SetUser(); that is
// always attached. Defaults to true.
UserInfo Option[bool]
// Cookies configures collection of HTTP cookies.
//
// Defaults to using the built-in DenyList.
Cookies *KeyValueCollectionBehavior
// HTTPHeaders configures collection of HTTP request and response headers
// independently.
//
// Defaults to both request and response using the built-in DenyList.
HTTPHeaders *HeaderCollectionConfig
// HTTPBodies controls which HTTP body types are collected.
//
// Defaults to collecting all valid body types.
HTTPBodies []BodyType
// QueryParams configures collection of URL query parameters.
//
// Defaults to using the built-in DenyList.
QueryParams *KeyValueCollectionBehavior
// sensitiveTerms is the deny-list used for built-in sensitive-key
// scrubbing.
sensitiveTerms []string
}
// cloneKeyValueCollectionBehavior returns a deep copy of b.
func cloneKeyValueCollectionBehavior(b *KeyValueCollectionBehavior) *KeyValueCollectionBehavior {
if b == nil {
return nil
}
cloned := &KeyValueCollectionBehavior{Mode: b.Mode}
if b.Terms != nil {
cloned.Terms = slices.Clone(b.Terms)
}
return cloned
}
// cloneHeaderCollectionConfig returns a deep copy of c.
func cloneHeaderCollectionConfig(c *HeaderCollectionConfig) *HeaderCollectionConfig {
if c == nil {
return nil
}
return &HeaderCollectionConfig{
Request: cloneKeyValueCollectionBehavior(c.Request),
Response: cloneKeyValueCollectionBehavior(c.Response),
}
}
// cloneDataCollection returns a deep copy of dc.
func cloneDataCollection(dc *DataCollection) *DataCollection {
if dc == nil {
return nil
}
cloned := &DataCollection{
UserInfo: dc.UserInfo,
Cookies: cloneKeyValueCollectionBehavior(dc.Cookies),
HTTPHeaders: cloneHeaderCollectionConfig(dc.HTTPHeaders),
QueryParams: cloneKeyValueCollectionBehavior(dc.QueryParams),
sensitiveTerms: dc.sensitiveTerms,
}
if dc.HTTPBodies != nil {
cloned.HTTPBodies = slices.Clone(dc.HTTPBodies)
}
return cloned
}
// allBodyTypes returns all valid body types.
func allBodyTypes() []BodyType {
return []BodyType{
BodyIncomingRequest,
BodyOutgoingRequest,
BodyIncomingResponse,
}
}
// snapshotDataCollection builds a fully-populated DataCollection based on given options.
// It handles any unspecified values by applying the defaults. If the given opts are nil, this
// provides a best-effort snapshot to align with sendDefaultPII for backwards compatibility.
func snapshotDataCollection(opts *DataCollection, sendDefaultPII bool) DataCollection {
if opts == nil {
return legacyDataCollection(sendDefaultPII)
}
return resolveDataCollection(opts)
}
func resolveDataCollection(dc *DataCollection) DataCollection {
var resolved DataCollection
if cloned := cloneDataCollection(dc); cloned != nil {
resolved = *cloned
}
if !resolved.UserInfo.IsSet {
resolved.UserInfo = Set(true)
}
if resolved.Cookies == nil {
resolved.Cookies = &KeyValueCollectionBehavior{}
}
if resolved.HTTPHeaders == nil {
resolved.HTTPHeaders = &HeaderCollectionConfig{}
}
if resolved.HTTPHeaders.Request == nil {
resolved.HTTPHeaders.Request = &KeyValueCollectionBehavior{}
}
if resolved.HTTPHeaders.Response == nil {
resolved.HTTPHeaders.Response = &KeyValueCollectionBehavior{}
}
if resolved.HTTPBodies == nil {
resolved.HTTPBodies = allBodyTypes()
}
if resolved.QueryParams == nil {
resolved.QueryParams = &KeyValueCollectionBehavior{}
}
return resolved
}
func legacyDataCollection(sendDefaultPII bool) DataCollection {
if sendDefaultPII {
return resolveDataCollection(&DataCollection{
UserInfo: Set(true),
Cookies: &KeyValueCollectionBehavior{},
HTTPHeaders: &HeaderCollectionConfig{Request: &KeyValueCollectionBehavior{}, Response: &KeyValueCollectionBehavior{}},
HTTPBodies: allBodyTypes(),
QueryParams: &KeyValueCollectionBehavior{},
})
}
return resolveDataCollection(&DataCollection{
UserInfo: Set(false),
HTTPBodies: []BodyType{},
Cookies: &KeyValueCollectionBehavior{Mode: CollectionOff},
HTTPHeaders: &HeaderCollectionConfig{
Request: &KeyValueCollectionBehavior{Mode: CollectionDenyList},
Response: &KeyValueCollectionBehavior{Mode: CollectionDenyList},
},
QueryParams: &KeyValueCollectionBehavior{Mode: CollectionDenyList},
sensitiveTerms: extendedSensitiveTerms,
})
}
// extendedSensitiveTerms are additional privacy terms that cover
// user-identifying data such as IP forwarding headers and user IDs. Used for
// backwards compatibility with SendDefaultPII=false.
var extendedSensitiveTerms = []string{
"forwarded",
"-ip",
"remote-",
"via",
"-user",
}