space.highport.manage.getSiteTraffic
Schema Diff
+81 -14
Compatibility Analysis
Breaking Changes Detected
5 breaking changes, 17 non-breaking changes.
Breaking Changes (5)
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals", src: "space.highport.manage.getSiteTraffic:output.refusals", tgt: "space.highport.manage.getSiteTraffic:output.refusals.requests", kind: "prop", name: Some("requests") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.requests", kind: "prop", name: Some("requests") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.firstSeen", kind: "prop", name: Some("firstSeen") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.bytesBilled", kind: "prop", name: Some("bytesBilled") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.recordCid", kind: "prop", name: Some("recordCid") }
Non-Breaking Changes (17)
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.bytesBilled" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.firstSeen" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.lastSeen" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.recordCid" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.requests" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals.estimatedBytes" }
- AddedVertex AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals.requests" }
- AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output", tgt: "space.highport.manage.getSiteTraffic:output.records", kind: "prop", name: Some("records") }
- AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output", tgt: "space.highport.manage.getSiteTraffic:output.refusals", kind: "prop", name: Some("refusals") }
- AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output.buckets:items", tgt: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests", kind: "prop", name: Some("botRequests") }
- AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output.records", tgt: "space.highport.manage.getSiteTraffic:output.records:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.lastSeen", kind: "prop", name: Some("lastSeen") }
- AddedEdge AddedEdge { src: "space.highport.manage.getSiteTraffic:output.refusals", tgt: "space.highport.manage.getSiteTraffic:output.refusals.estimatedBytes", kind: "prop", name: Some("estimatedBytes") }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.bytesBilled" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.firstSeen" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.lastSeen" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.recordCid" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items.requests" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals.estimatedBytes" }AddedVertex { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals.requests" }
Additional Notes
- Breaking: RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.refusals", src: "space.highport.manage.getSiteTraffic:output.refusals", tgt: "space.highport.manage.getSiteTraffic:output.refusals.requests", kind: "prop", name: Some("requests") }
- Breaking: RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.requests", kind: "prop", name: Some("requests") }
- Breaking: RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.firstSeen", kind: "prop", name: Some("firstSeen") }
- Breaking: RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.bytesBilled", kind: "prop", name: Some("bytesBilled") }
- Breaking: RequiredEdgeAdded { vertex_id: "space.highport.manage.getSiteTraffic:output.records:items", src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.recordCid", kind: "prop", name: Some("recordCid") }
- Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output", tgt: "space.highport.manage.getSiteTraffic:output.records", kind: "prop", name: Some("records") }
- Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output", tgt: "space.highport.manage.getSiteTraffic:output.refusals", kind: "prop", name: Some("refusals") }
- Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output.buckets:items", tgt: "space.highport.manage.getSiteTraffic:output.buckets:items.botRequests", kind: "prop", name: Some("botRequests") }
- Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output.records", tgt: "space.highport.manage.getSiteTraffic:output.records:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output.records:items", tgt: "space.highport.manage.getSiteTraffic:output.records:items.lastSeen", kind: "prop", name: Some("lastSeen") }
- Non-breaking: AddedEdge { src: "space.highport.manage.getSiteTraffic:output.refusals", tgt: "space.highport.manage.getSiteTraffic:output.refusals.estimatedBytes", kind: "prop", name: Some("estimatedBytes") }
1
1
{
2
2
"id": "space.highport.manage.getSiteTraffic",
3
3
"defs": {
4
4
"main": {
5
5
"type": "query",
6
6
"errors": [
7
7
{
8
8
"name": "InvalidDomain",
9
-
"description": "Not a syntactically valid, non-reserved, public-suffix-safe domain. Distinct from DomainNotFound: the string is not a hostname at all."
9
+
"description": "Not a valid, non-reserved, public-suffix-safe domain. Unlike DomainNotFound, the input is not a hostname at all."
10
10
},
11
11
{
12
12
"name": "DomainNotFound",
13
-
"description": "No such domain, or it is not registered to the calling identity. The two are one answer so the method is not an existence oracle."
13
+
"description": "No such domain, or it does not belong to the caller. Both cases get the same error, so it cannot be used to check whether a domain exists."
14
14
},
15
15
{
16
16
"name": "AnalyticsDisabled",
17
-
"description": "This deployment has no analytics store configured, so no traffic was ever recorded."
17
+
"description": "No analytics store is configured, so no traffic was recorded."
18
18
}
19
19
],
20
20
"output": {
21
21
"schema": {
22
22
"type": "object",
23
23
"required": [
24
24
"domain",
25
25
"bytesBilled",
26
26
"bytesBilledToVisitors",
27
27
"headerEstimateBytes",
28
28
"buckets",
29
29
"topPaths",
30
30
"statuses"
31
31
],
32
32
"properties": {
33
33
"domain": {
34
34
"type": "string"
35
35
},
36
36
"buckets": {
37
37
"type": "array",
38
38
"items": {
39
39
"type": "object",
40
40
"required": [
41
41
"bucket",
42
42
"requests",
43
43
"bytesBody",
44
44
"bytesBilled"
45
45
],
46
46
"properties": {
47
47
"bucket": {
48
48
"type": "string",
49
49
"format": "datetime",
50
-
"description": "The hour this bucket starts."
50
+
"description": "Start of the hour."
51
51
},
52
52
"requests": {
53
53
"type": "integer",
54
54
"description": "Responses in the hour."
55
55
},
56
56
"bytesBody": {
57
57
"type": "integer",
58
-
"description": "Response body bytes, as the edge logged them."
58
+
"description": "Response body bytes, as logged by the edge."
59
+
},
60
+
"botRequests": {
61
+
"type": "integer",
62
+
"description": "How many of requests came from crawlers. This is part of requests, not added to it. Bytes are not split this way. Absent if the deployment does not report it; show that as unknown, not as zero."
59
63
},
60
64
"bytesBilled": {
61
65
"type": "integer",
62
66
"description": "Body bytes plus the per-response header estimate."
63
67
}
64
68
},
65
69
"description": "One hour of a domain's traffic."
66
70
},
67
71
"description": "Hourly buckets, oldest first."
68
72
},
73
+
"records": {
74
+
"type": "array",
75
+
"items": {
76
+
"type": "object",
77
+
"required": [
78
+
"recordCid",
79
+
"firstSeen",
80
+
"requests",
81
+
"bytesBilled"
82
+
],
83
+
"properties": {
84
+
"lastSeen": {
85
+
"type": "string",
86
+
"format": "datetime",
87
+
"description": "The last response in the range served from this version. With firstSeen, it shows how long the version served, so byte figures can be compared across versions. Absent when unknown; show that as still serving."
88
+
},
89
+
"requests": {
90
+
"type": "integer",
91
+
"description": "Responses."
92
+
},
93
+
"firstSeen": {
94
+
"type": "string",
95
+
"format": "datetime",
96
+
"description": "The first response in the range served from this version."
97
+
},
98
+
"recordCid": {
99
+
"type": "string",
100
+
"format": "cid",
101
+
"description": "The site record the serving snapshot was built from."
102
+
},
103
+
"bytesBilled": {
104
+
"type": "integer",
105
+
"description": "Billed bytes."
106
+
}
107
+
},
108
+
"description": "One published version and the traffic it served."
109
+
},
110
+
"description": "Which versions of the site record served the traffic, heaviest first. Limited to topRecords, so a frequently republished domain may have versions not listed. Absent if the deployment does not report it."
111
+
},
112
+
"refusals": {
113
+
"type": "object",
114
+
"required": [
115
+
"requests"
116
+
],
117
+
"properties": {
118
+
"requests": {
119
+
"type": "integer",
120
+
"description": "Responses refused because the payer's allowance for the period ran out. Matches the 402 count in statuses."
121
+
},
122
+
"estimatedBytes": {
123
+
"type": "integer",
124
+
"description": "What serving those responses would have cost the owner. Absent unless the deployment records it, because a refused response has no logged body size."
125
+
}
126
+
},
127
+
"description": "What the bandwidth allowance refused over the range, and what serving it would have cost. Absent if the deployment does not report it."
128
+
},
69
129
"statuses": {
70
130
"type": "array",
71
131
"items": {
72
132
"type": "object",
73
133
"required": [
74
134
"status",
75
135
"requests",
76
136
"bytesBilled",
77
137
"botRequests"
78
138
],
79
139
"properties": {
80
140
"status": {
81
141
"type": "integer",
82
142
"description": "The HTTP status."
83
143
},
84
144
"requests": {
85
145
"type": "integer",
86
146
"description": "Responses with this status."
87
147
},
88
148
"botRequests": {
89
149
"type": "integer",
90
-
"description": "How many of those came from a client classified as a crawler. Crawler traffic is billed, because it is real egress and the alternative rewards user-agent spoofing."
150
+
"description": "How many of those came from crawlers. Crawler traffic is billed: it is real egress, and not billing it would reward faking a user agent."
91
151
},
92
152
"bytesBilled": {
93
153
"type": "integer",
94
154
"description": "Billed bytes."
95
155
}
96
156
},
97
-
"description": "One status code's share of the requests and of the bytes."
157
+
"description": "One status code's share of requests and bytes."
98
158
},
99
-
"description": "The status mix, with the crawler share alongside it."
159
+
"description": "Requests by status code, with the crawler share."
100
160
},
101
161
"topPaths": {
102
162
"type": "array",
103
163
"items": {
104
164
"type": "object",
105
165
"required": [
106
166
"path",
107
167
"requests",
108
168
"bytesBilled"
109
169
],
110
170
"properties": {
111
171
"path": {
112
172
"type": "string",
113
173
"description": "The request path."
114
174
},
115
175
"requests": {
116
176
"type": "integer",
117
177
"description": "Responses."
118
178
},
119
179
"bytesBilled": {
120
180
"type": "integer",
121
181
"description": "Billed bytes."
122
182
}
123
183
},
124
-
"description": "One path and what it cost."
184
+
"description": "One path and its traffic."
125
185
},
126
186
"description": "The busiest paths over the range."
127
187
},
128
188
"bytesBilled": {
129
189
"type": "integer",
130
-
"description": "Total billed bytes over the range."
190
+
"description": "Total bytes billed over the range."
131
191
},
132
192
"headerEstimateBytes": {
133
193
"type": "integer",
134
-
"description": "The flat per-response constant added to every logged body size. Every byte figure here is an estimate by this much per response."
194
+
"description": "The fixed per-response header estimate added to each logged body size. Every byte figure here is estimated by this much per response."
135
195
},
136
196
"bytesBilledToVisitors": {
137
197
"type": "integer",
138
-
"description": "How much of bytesBilled an authenticated visitor paid for rather than the owner. Zero unless the domain is on the sender-pays policy."
198
+
"description": "The part of bytesBilled that signed-in visitors paid instead of the owner. Zero unless the domain uses the visitor payer policy."
139
199
}
140
200
}
141
201
},
142
202
"encoding": "application/json"
143
203
},
144
204
"parameters": {
145
205
"type": "params",
146
206
"required": [
147
207
"domain"
148
208
],
149
209
"properties": {
150
210
"to": {
151
211
"type": "string",
152
212
"format": "datetime",
153
213
"description": "Exclusive upper bound. Defaults to now."
154
214
},
155
215
"from": {
156
216
"type": "string",
157
217
"format": "datetime",
158
218
"description": "Inclusive lower bound. Defaults to 30 days ago."
159
219
},
160
220
"domain": {
161
221
"type": "string",
162
222
"maxLength": 253,
163
-
"description": "The registered hostname. Must be registered to the calling identity."
223
+
"description": "The registered hostname. Must belong to the caller."
164
224
},
165
225
"topPaths": {
166
226
"type": "integer",
167
227
"default": 20,
168
228
"maximum": 100,
169
229
"minimum": 0,
170
230
"description": "How many of the busiest paths to return."
231
+
},
232
+
"topRecords": {
233
+
"type": "integer",
234
+
"default": 20,
235
+
"maximum": 100,
236
+
"minimum": 0,
237
+
"description": "How many record versions to return. A domain republished often has many, so this is a top N, not the full history."
171
238
}
172
239
}
173
240
},
174
-
"description": "Traffic to one domain the caller owns, over a range: requests and bytes per hour, the busiest paths, and the status mix. Byte figures include a flat per-response header estimate, because the edge's access log records the response body only."
241
+
"description": "Traffic to one of the caller's domains over a time range: hourly requests and bytes, the busiest paths, and status codes. Byte figures include a fixed per-response header estimate, since the edge logs only response bodies."
175
242
}
176
243
},
177
244
"$type": "com.atproto.lexicon.schema",
178
245
"lexicon": 1
179
246
}