@@ -32,6 +32,7 @@ use sha2::Digest;
32
32
33
33
use crate :: json_ext:: Object ;
34
34
use crate :: json_ext:: Value as JsonValue ;
35
+ use crate :: plugins:: telemetry:: apollo_exporter:: proto:: reports:: QueryMetadata ;
35
36
use crate :: plugins:: telemetry:: config:: ApolloSignatureNormalizationAlgorithm ;
36
37
use crate :: spec:: Fragments ;
37
38
use crate :: spec:: Query ;
@@ -162,35 +163,50 @@ impl AddAssign<ReferencedEnums> for AggregatedExtendedReferenceStats {
162
163
}
163
164
}
164
165
165
- /// UsageReporting fields, that will be used to send stats to uplink/studio
166
166
#[ derive( Deserialize , Serialize , Debug , PartialEq , Eq , Clone , Default ) ]
167
167
#[ serde( rename_all = "camelCase" ) ]
168
- pub ( crate ) struct UsageReporting {
168
+ pub ( crate ) struct UsageReportingOperationDetails {
169
169
/// The operation name, or None if there is no operation name
170
170
operation_name : Option < String > ,
171
171
/// The normalized operation signature, or None if there is no valid signature
172
172
operation_signature : Option < String > ,
173
- /// The error key to use for the stats report, or None if there is no error
174
- error_key : Option < String > ,
175
- /// The persisted query ID used to request this operation, or None if the query was not requested via PQ ID
176
- pq_id : Option < String > ,
177
173
/// a list of all types and fields referenced in the query
178
174
#[ serde( default ) ]
179
- pub ( crate ) referenced_fields_by_type : HashMap < String , ReferencedFieldsForType > ,
175
+ referenced_fields_by_type : HashMap < String , ReferencedFieldsForType > ,
176
+ }
177
+
178
+ /// UsageReporting fields, that will be used to send stats to uplink/studio
179
+ #[ derive( Deserialize , Serialize , Debug , PartialEq , Eq , Clone ) ]
180
+ #[ serde( rename_all = "camelCase" ) ]
181
+ pub ( crate ) enum UsageReporting {
182
+ Operation ( UsageReportingOperationDetails ) ,
183
+ PersistedQuery {
184
+ operation_details : UsageReportingOperationDetails ,
185
+ persisted_query_id : String ,
186
+ } ,
187
+ Error ( String ) ,
180
188
}
181
189
182
190
impl UsageReporting {
183
191
pub ( crate ) fn for_error ( error_key : String ) -> UsageReporting {
184
- UsageReporting {
185
- error_key : Some ( error_key) ,
186
- ..Default :: default ( )
187
- }
192
+ UsageReporting :: Error ( error_key)
188
193
}
189
194
190
- pub ( crate ) fn with_pq_id ( & self , pq_id : Option < String > ) -> UsageReporting {
191
- UsageReporting {
192
- pq_id,
193
- ..self . clone ( )
195
+ pub ( crate ) fn with_pq_id ( & self , maybe_pq_id : Option < String > ) -> UsageReporting {
196
+ match self {
197
+ UsageReporting :: Operation ( op_details)
198
+ | UsageReporting :: PersistedQuery {
199
+ operation_details : op_details,
200
+ ..
201
+ } => match maybe_pq_id {
202
+ Some ( pq_id) => UsageReporting :: PersistedQuery {
203
+ operation_details : op_details. clone ( ) ,
204
+ persisted_query_id : pq_id,
205
+ } ,
206
+ None => UsageReporting :: Operation ( op_details. clone ( ) ) ,
207
+ } ,
208
+ // PQ ID has no effect on errors
209
+ UsageReporting :: Error { .. } => self . clone ( ) ,
194
210
}
195
211
}
196
212
@@ -203,52 +219,90 @@ impl UsageReporting {
203
219
/// Note that this combination of operation name and signature is sometimes referred to in code as
204
220
/// "operation signature" even though it also contains the operation name as the first line.
205
221
pub ( crate ) fn get_stats_report_key ( & self ) -> String {
206
- if let Some ( error_key) = & self . error_key {
207
- format ! ( "## {}\n " , error_key)
208
- } else if let Some ( persisted_query_id) = & self . pq_id {
209
- format ! ( "pq# {}" , persisted_query_id)
210
- } else {
211
- let stats_report_key_op_name =
212
- self . operation_name . as_deref ( ) . unwrap_or ( "-" ) . to_string ( ) ;
213
- format ! (
214
- "# {}\n {}" ,
215
- stats_report_key_op_name,
216
- self . get_operation_signature( )
217
- )
222
+ match self {
223
+ UsageReporting :: Operation ( operation_details) => {
224
+ let stats_report_key_op_name = operation_details
225
+ . operation_name
226
+ . as_deref ( )
227
+ . unwrap_or ( "-" )
228
+ . to_string ( ) ;
229
+ format ! (
230
+ "# {}\n {}" ,
231
+ stats_report_key_op_name,
232
+ self . get_operation_signature( ) ,
233
+ )
234
+ }
235
+ UsageReporting :: PersistedQuery {
236
+ persisted_query_id, ..
237
+ } => {
238
+ format ! ( "pq# {}" , persisted_query_id)
239
+ }
240
+ UsageReporting :: Error ( error_key) => format ! ( "## {}\n " , error_key) ,
218
241
}
219
242
}
220
243
221
244
pub ( crate ) fn get_operation_signature ( & self ) -> String {
222
- self . operation_signature
223
- . as_deref ( )
224
- . unwrap_or ( "" )
225
- . to_string ( )
245
+ match self {
246
+ UsageReporting :: Operation ( operation_details)
247
+ | UsageReporting :: PersistedQuery {
248
+ operation_details, ..
249
+ } => operation_details
250
+ . operation_signature
251
+ . clone ( )
252
+ . unwrap_or ( "" . to_string ( ) ) ,
253
+ UsageReporting :: Error { .. } => "" . to_string ( ) ,
254
+ }
226
255
}
227
256
228
257
pub ( crate ) fn get_operation_id ( & self ) -> String {
229
- let sig_to_hash = match & self . error_key {
230
- Some ( err_key) => format ! ( "# # {}\n " , err_key) ,
231
- None => self . get_stats_report_key ( ) ,
258
+ let string_to_hash = match self {
259
+ UsageReporting :: Operation { .. } | UsageReporting :: PersistedQuery { .. } => {
260
+ self . get_stats_report_key ( )
261
+ }
262
+ UsageReporting :: Error ( error_key) => format ! ( "# # {}\n " , error_key) ,
232
263
} ;
233
264
234
265
let mut hasher = sha1:: Sha1 :: new ( ) ;
235
- hasher. update ( sig_to_hash . as_bytes ( ) ) ;
266
+ hasher. update ( string_to_hash . as_bytes ( ) ) ;
236
267
let result = hasher. finalize ( ) ;
237
268
hex:: encode ( result)
238
269
}
239
270
240
271
pub ( crate ) fn get_operation_name ( & self ) -> String {
241
- if let Some ( op_name) = & self . operation_name {
242
- op_name. clone ( )
243
- } else if let Some ( err_key) = & self . error_key {
244
- format ! ( "# {}" , err_key)
245
- } else {
246
- "" . to_string ( )
272
+ match self {
273
+ UsageReporting :: Operation ( operation_details)
274
+ | UsageReporting :: PersistedQuery {
275
+ operation_details, ..
276
+ } => operation_details
277
+ . operation_name
278
+ . clone ( )
279
+ . unwrap_or ( "" . to_string ( ) ) ,
280
+ UsageReporting :: Error ( error_key) => format ! ( "# {}" , error_key) ,
247
281
}
248
282
}
249
283
250
- pub ( crate ) fn is_error ( & self ) -> bool {
251
- self . error_key . is_some ( )
284
+ pub ( crate ) fn get_referenced_fields ( & self ) -> HashMap < String , ReferencedFieldsForType > {
285
+ match self {
286
+ UsageReporting :: Operation ( operation_details)
287
+ | UsageReporting :: PersistedQuery {
288
+ operation_details, ..
289
+ } => operation_details. referenced_fields_by_type . clone ( ) ,
290
+ UsageReporting :: Error { .. } => HashMap :: default ( ) ,
291
+ }
292
+ }
293
+
294
+ pub ( crate ) fn get_query_metadata ( & self ) -> Option < QueryMetadata > {
295
+ match self {
296
+ UsageReporting :: PersistedQuery {
297
+ persisted_query_id, ..
298
+ } => Some ( QueryMetadata {
299
+ name : self . get_operation_name ( ) ,
300
+ signature : self . get_operation_signature ( ) ,
301
+ pq_id : persisted_query_id. clone ( ) ,
302
+ } ) ,
303
+ // For now we only want to populate query metadata for PQ operations
304
+ _ => None ,
305
+ }
252
306
}
253
307
}
254
308
@@ -440,13 +494,11 @@ struct UsageGenerator<'a> {
440
494
441
495
impl UsageGenerator < ' _ > {
442
496
fn generate_usage_reporting ( & mut self ) -> UsageReporting {
443
- UsageReporting {
497
+ UsageReporting :: Operation ( UsageReportingOperationDetails {
444
498
operation_name : self . get_operation_name ( ) ,
445
499
operation_signature : self . generate_normalized_signature ( ) ,
446
- error_key : None ,
447
- pq_id : None ,
448
500
referenced_fields_by_type : self . generate_apollo_reporting_refs ( ) ,
449
- }
501
+ } )
450
502
}
451
503
452
504
fn get_operation_name ( & self ) -> Option < String > {
0 commit comments