This repository has been archived by the owner on Jul 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreports.proto
488 lines (416 loc) · 18.2 KB
/
reports.proto
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
syntax = "proto3";
// package mdg.engine.proto;
import "google/protobuf/timestamp.proto";
message Trace {
message CachePolicy {
enum Scope {
UNKNOWN = 0;
PUBLIC = 1;
PRIVATE = 2;
}
Scope scope = 1;
int64 max_age_ns = 2; // use 0 for absent, -1 for 0
}
message Details {
// The variables associated with this query (unless the reporting agent is
// configured to keep them all private). Values are JSON: ie, strings are
// enclosed in double quotes, etc. The value of a private variable is
// the empty string.
map<string, string> variables_json = 4;
// Deprecated. Engineproxy did not encode variable values as JSON, so you
// couldn't tell numbers from numeric strings. Send variables_json instead.
map<string, bytes> variables = 1;
// Optional: this is the original full query before the signature algorithm
// is applied. Engineproxy always sent this in all traces, which meant that
// literal-masking done by the signature algorithm didn't fully hide
// sensitive data from Engine servers. apollo-engine-reporting does not
// include this by default. (The Engine frontend does not currently show
// this field.)
string raw_query = 2;
// Don't include this in traces inside a FullTracesReport; the operation
// name for these traces comes from the key of the traces_per_query map.
string operation_name = 3;
}
message Error {
string message = 1; // required
repeated Location location = 2;
uint64 time_ns = 3;
string json = 4;
}
message HTTP {
message Values {
repeated string value = 1;
}
enum Method {
UNKNOWN = 0;
OPTIONS = 1;
GET = 2;
HEAD = 3;
POST = 4;
PUT = 5;
DELETE = 6;
TRACE = 7;
CONNECT = 8;
PATCH = 9;
}
Method method = 1;
string host = 2;
string path = 3;
// Should exclude manual blacklist ("Auth" by default)
map<string, Values> request_headers = 4;
map<string, Values> response_headers = 5;
uint32 status_code = 6;
bool secure = 8; // TLS was used
string protocol = 9; // by convention "HTTP/1.0", "HTTP/1.1", "HTTP/2" or "h2"
}
message Location {
uint32 line = 1;
uint32 column = 2;
}
// We store information on each resolver execution as a Node on a tree.
// The structure of the tree corresponds to the structure of the GraphQL
// response; it does not indicate the order in which resolvers were
// invoked. Note that nodes representing indexes (and the root node)
// don't contain all Node fields (eg types and times).
message Node {
// The name of the field (for Nodes representing a resolver call) or the
// index in a list (for intermediate Nodes representing elements of a list).
// field_name is the name of the field as it appears in the GraphQL
// response: ie, it may be an alias. (In that case, the original_field_name
// field holds the actual field name from the schema.) In any context where
// we're building up a path, we use the response_name rather than the
// original_field_name.
oneof id {
string response_name = 1;
uint32 index = 2;
}
string original_field_name = 14;
// The field's return type; e.g. "String!" for User.email:String!
string type = 3;
// The field's parent type; e.g. "User" for User.email:String!
string parent_type = 13;
CachePolicy cache_policy = 5;
// relative to the trace's start_time, in ns
uint64 start_time = 8;
// relative to the trace's start_time, in ns
uint64 end_time = 9;
repeated Error error = 11;
repeated Node child = 12;
reserved 4;
}
// represents a node in the query plan, under which there is a trace tree for that service fetch.
// In particular, each fetch node represents a call to an implementing service, and calls to implementing
// services may not be unique. See https://github.com/apollographql/apollo-server/blob/master/packages/apollo-gateway/src/QueryPlan.ts
// for more information and details.
message QueryPlanNode {
// This represents a set of nodes to be executed sequentially by the Gateway executor
message SequenceNode {
repeated QueryPlanNode nodes = 1;
}
// This represents a set of nodes to be executed in parallel by the Gateway executor
message ParallelNode {
repeated QueryPlanNode nodes = 1;
}
// This represents a node to send an operation to an implementing service
message FetchNode {
// XXX When we want to include more details about the sub-operation that was
// executed against this service, we should include that here in each fetch node.
// This might include an operation signature, requires directive, reference resolutions, etc.
string serviceName = 1;
bool traceParsingFailed = 2;
// This Trace only contains start_time, end_time, duration_ns, and root;
// all timings were calculated **on the federated service**, and clock skew
// will be handled by the ingress server.
Trace trace = 3;
// relative to the outer trace's start_time, in ns, measured in the gateway.
uint64 sent_time_offset = 4;
// Wallclock times measured in the gateway for when this operation was
// sent and received.
google.protobuf.Timestamp sent_time = 5;
google.protobuf.Timestamp received_time = 6;
}
// This node represents a way to reach into the response path and attach related entities.
// XXX Flatten is really not the right name and this node may be renamed in the query planner.
message FlattenNode {
repeated ResponsePathElement response_path = 1;
QueryPlanNode node = 2;
}
message ResponsePathElement {
oneof id {
string field_name = 1;
uint32 index = 2;
}
}
oneof node {
SequenceNode sequence = 1;
ParallelNode parallel = 2;
FetchNode fetch = 3;
FlattenNode flatten = 4;
}
}
// Wallclock time when the trace began.
google.protobuf.Timestamp start_time = 4; // required
// Wallclock time when the trace ended.
google.protobuf.Timestamp end_time = 3; // required
// High precision duration of the trace; may not equal end_time-start_time
// (eg, if your machine's clock changed during the trace).
uint64 duration_ns = 11; // required
// A tree containing information about all resolvers run directly by this
// service, including errors.
Node root = 14;
// -------------------------------------------------------------------------
// Fields below this line are *not* included in federated traces (the traces
// sent from federated services to the gateway).
// In addition to details.raw_query, we include a "signature" of the query,
// which can be normalized: for example, you may want to discard aliases, drop
// unused operations and fragments, sort fields, etc. The most important thing
// here is that the signature match the signature in StatsReports. In
// StatsReports signatures show up as the key in the per_query map (with the
// operation name prepended). The signature should be a valid GraphQL query.
// All traces must have a signature; if this Trace is in a FullTracesReport
// that signature is in the key of traces_per_query rather than in this field.
// Engineproxy provides the signature in legacy_signature_needs_resigning
// instead.
string signature = 19;
Details details = 6;
// Note: engineproxy always sets client_name, client_version, and client_address to "none".
// apollo-engine-reporting allows for them to be set by the user.
string client_name = 7;
string client_version = 8;
string client_address = 9;
string client_reference_id = 23;
HTTP http = 10;
CachePolicy cache_policy = 18;
// If this Trace was created by a gateway, this is the query plan, including
// sub-Traces for federated services. Note that the 'root' tree on the
// top-level Trace won't contain any resolvers (though it could contain errors
// that occurred in the gateway itself).
QueryPlanNode query_plan = 26;
// Was this response served from a full query response cache? (In that case
// the node tree will have no resolvers.)
bool full_query_cache_hit = 20;
// Was this query specified successfully as a persisted query hash?
bool persisted_query_hit = 21;
// Did this query contain both a full query string and a persisted query hash?
// (This typically means that a previous request was rejected as an unknown
// persisted query.)
bool persisted_query_register = 22;
// Was this operation registered and a part of the safelist?
bool registered_operation = 24;
// Was this operation forbidden due to lack of safelisting?
bool forbidden_operation = 25;
// --------------------------------------------------------------
// Fields below this line are only set by the old Go engineproxy.
google.protobuf.Timestamp origin_reported_start_time = 15;
google.protobuf.Timestamp origin_reported_end_time = 16;
uint64 origin_reported_duration_ns = 17;
// Older agents (eg the Go engineproxy) relied to some degree on the Engine
// backend to run their own semi-compatible implementation of a specific
// variant of query signatures. The backend does not do this for new agents (which
// set the above 'signature' field). It used to still "re-sign" signatures
// from engineproxy, but we've now simplified the backend to no longer do this.
// Deprecated and ignored in FullTracesReports.
string legacy_signature_needs_resigning = 5;
// removed: Node parse = 12; Node validate = 13;
// Id128 server_id = 1; Id128 client_id = 2;
reserved 12, 13, 1, 2;
}
// The `service` value embedded within the header key is not guaranteed to contain an actual service,
// and, in most cases, the service information is trusted to come from upstream processing. If the
// service _is_ specified in this header, then it is checked to match the context that is reporting it.
// Otherwise, the service information is deduced from the token context of the reporter and then sent
// along via other mechanisms (in Kafka, the `ReportKafkaKey). The other information (hostname,
// agent_version, etc.) is sent by the Apollo Engine Reporting agent, but we do not currently save that
// information to any of our persistent storage.
message ReportHeader {
string service = 3;
// eg "host-01.example.com"
string hostname = 5;
// eg "engineproxy 0.1.0"
string agent_version = 6; // required
// eg "prod-4279-20160804T065423Z-5-g3cf0aa8" (taken from `git describe --tags`)
string service_version = 7;
// eg "node v4.6.0"
string runtime_version = 8;
// eg "Linux box 4.6.5-1-ec2 #1 SMP Mon Aug 1 02:31:38 PDT 2016 x86_64 GNU/Linux"
string uname = 9;
// eg "current", "prod"
string schema_tag = 10;
// The hex representation of the sha512 of the introspection response
string schema_hash = 11;
}
message PathErrorStats {
map<string, PathErrorStats> children = 1;
uint64 errors_count = 4;
uint64 requests_with_errors_count = 5;
}
message ClientNameStats {
// Duration histogram for non-cache-hit queries.
// (See docs/histograms.md for the histogram format.)
repeated int64 latency_count = 1;
reserved 2; // removed: repeated uint64 error_count = 2;
// These per-version fields were used to understand what versions contributed to this sample
// when we were implementing the aggregation of this information ourselves using BigTable.
// However, since the per-version stats don't separate out latency, it makes more sense to
// have stats reported with contextual information so we can have the specific breakdown we're
// looking for. These fields are somewhat misleading as we never actually do any per-version
// awareness with anything reporting in the legacy "per_client_name" stats, and instead use
// "query_stats_with_context" to have more contextual information.
map<string, uint64> requests_count_per_version = 3; // required
map<string, uint64> cache_hits_per_version = 4;
map<string, uint64> persisted_query_hits_per_version = 10;
map<string, uint64> persisted_query_misses_per_version = 11;
map<string, uint64> registered_operation_count_per_version = 12;
map<string, uint64> forbidden_operation_count_per_version = 13;
repeated int64 cache_latency_count = 5; // Duration histogram; see docs/histograms.md
PathErrorStats root_error_stats = 6;
uint64 requests_with_errors_count = 7;
// TTL histograms for cache misses for the public cache.
repeated int64 public_cache_ttl_count = 8;
// TTL histograms for cache misses for the private cache.
repeated int64 private_cache_ttl_count = 9;
}
message QueryLatencyStats {
repeated int64 latency_count = 1;
uint64 request_count = 2;
uint64 cache_hits = 3;
uint64 persisted_query_hits = 4;
uint64 persisted_query_misses = 5;
repeated int64 cache_latency_count = 6;
PathErrorStats root_error_stats = 7;
uint64 requests_with_errors_count = 8;
repeated int64 public_cache_ttl_count = 9;
repeated int64 private_cache_ttl_count = 10;
uint64 registered_operation_count = 11;
uint64 forbidden_operation_count = 12;
}
message StatsContext {
string client_reference_id = 1;
string client_name = 2;
string client_version = 3;
}
message ContextualizedQueryLatencyStats {
QueryLatencyStats query_latency_stats = 1;
StatsContext context = 2;
}
message ContextualizedTypeStats {
StatsContext context = 1;
map<string, TypeStat> per_type_stat = 2;
}
message FieldStat {
string name = 2; // deprecated; only set when stored in TypeStat.field
string return_type = 3; // required; eg "String!" for User.email:String!
uint64 errors_count = 4;
uint64 count = 5;
uint64 requests_with_errors_count = 6;
repeated int64 latency_count = 8; // Duration histogram; see docs/histograms.md
}
message TypeStat {
string name = 1; // deprecated; only set when stored in QueryStats.per_type
repeated FieldStat field = 2; // deprecated; use per_field_stat instead
// Key is (eg) "email" for User.email:String!
map<string, FieldStat> per_field_stat = 3;
}
message QueryStats {
// Either per_client_name (for back-compat) or query_stats_with_context must be specified. If both are
// specified, then query_stats_with_context will be used and per_client_name will be ignored. Although
// the fields in ClientNameStats mention things "per-version," the information in the "per-version"
// fields will only ever be over the default version, the empty String: "", if arrived at via the
// FullTracesAggregator.
map<string, ClientNameStats> per_client_name = 1; // deprecated; use stats_with_context instead
repeated ContextualizedQueryLatencyStats query_stats_with_context = 4;
repeated TypeStat per_type = 2; // deprecated; use type_stats_with_context instead
// Key is the parent type, e.g. "User" for User.email:String!
map<string, TypeStat> per_type_stat = 3; // deprecated; use type_stats_with_context instead
repeated ContextualizedTypeStats type_stats_with_context = 5;
}
// Top-level message type for the server-side traces endpoint
message TracesReport {
ReportHeader header = 1; // required
repeated Trace trace = 2; // required
}
message Field {
string name = 2; // required; eg "email" for User.email:String!
string return_type = 3; // required; eg "String!" for User.email:String!
}
message Type {
string name = 1; // required; eg "User" for User.email:String!
repeated Field field = 2;
}
message MemStats {
uint64 total_bytes = 1; // MemStats.Sys
uint64 stack_bytes = 2; // MemStats.StackSys
uint64 heap_bytes = 3; // MemStats.HeapSys
uint64 heap_released_bytes = 13; // MemStats.HeapReleased
uint64 gc_overhead_bytes = 4; // MemStats.GCSys
uint64 stack_used_bytes = 5; // MemStats.StackInuse
uint64 heap_allocated_bytes = 6; // MemStats.HeapAlloc
uint64 heap_allocated_objects = 7; // MemStats.HeapObjects
uint64 heap_allocated_bytes_delta = 8; // MemStats.TotalAlloc delta
uint64 heap_allocated_objects_delta = 9; // MemStats.Mallocs delta
uint64 heap_freed_objects_delta = 10; // MemStats.Frees delta
uint64 gc_stw_ns_delta = 11; // MemStats.PauseTotalNs delta
uint64 gc_count_delta = 12; // MemStats.NumGC delta
}
message TimeStats {
uint64 uptime_ns = 1;
uint64 real_ns_delta = 2;
uint64 user_ns_delta = 3;
uint64 sys_ns_delta = 4;
}
// Top-level message type for the server-side stats endpoint
message StatsReport {
ReportHeader header = 1; // required
// These fields are about properties of the engineproxy and are not generated
// from FullTracesReports.
MemStats mem_stats = 2;
TimeStats time_stats = 3;
// Beginning of the period over which stats are collected.
google.protobuf.Timestamp start_time = 8;
// End of the period of which stats are collected.
google.protobuf.Timestamp end_time = 9;
// Only used to interpret mem_stats and time_stats; not generated from
// FullTracesReports.
uint64 realtime_duration = 10;
// Maps from query descriptor to QueryStats. Required unless
// legacy_per_query_missing_operation_name is set. The keys are strings of the
// form `# operationName\nsignature` (literal hash and space), with
// operationName - if there is no operation name.
map<string, QueryStats> per_query = 14;
// Older agents (Go engineproxy) didn't explicitly include the operation name
// in the key of this map, and the server had to parse it out (after a
// re-signing operation which is no longer performed). The key here is just the query
// signature. Deprecated.
map<string, QueryStats> legacy_per_query_implicit_operation_name = 12;
// Deprecated: it was useful in Optics where we had access to the whole schema
// but has not been ever used in Engine. apollo-engine-reporting will not
// send it.
repeated Type type = 13;
}
// This is the top-level message used by the new traces ingress. This
// is designed for the apollo-engine-reporting TypeScript agent and will
// eventually be documented as a public ingress API. This message consists
// solely of traces; the equivalent of the StatsReport is automatically
// generated server-side from this message. Agents should send traces
// for all requests in this report. Generally, buffering up until a large
// size has been reached (say, 4MB) or 5-10 seconds has passed is appropriate.
message FullTracesReport {
ReportHeader header = 1;
// key is statsReportKey (# operationName\nsignature) Note that the nested
// traces will *not* have a signature or details.operationName (because the
// key is adequate).
//
// We also assume that traces don't have
// legacy_per_query_implicit_operation_name, and we don't require them to have
// details.raw_query (which would consume a lot of space and has privacy/data
// access issues, and isn't currently exposed by our app anyway).
map<string, Traces> traces_per_query = 5;
}
// Just a sequence of traces with the same statsReportKey.
message Traces {
repeated Trace trace = 1;
}
message TraceV1 {
ReportHeader header = 1;
Trace trace = 2;
}