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