Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: components/autofill/core/browser/autofill_metrics.cc

Issue 2870163003: Log Autofill.Quality.*.ByFieldType by predicted type for unknown data. (Closed)
Patch Set: fix comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/autofill/core/browser/autofill_metrics.h" 5 #include "components/autofill/core/browser/autofill_metrics.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 GROUP_CREDIT_CARD_DATE, 73 GROUP_CREDIT_CARD_DATE,
74 GROUP_CREDIT_CARD_TYPE, 74 GROUP_CREDIT_CARD_TYPE,
75 GROUP_PASSWORD, 75 GROUP_PASSWORD,
76 GROUP_ADDRESS_LINE_3, 76 GROUP_ADDRESS_LINE_3,
77 GROUP_USERNAME, 77 GROUP_USERNAME,
78 GROUP_STREET_ADDRESS, 78 GROUP_STREET_ADDRESS,
79 GROUP_CREDIT_CARD_VERIFICATION, 79 GROUP_CREDIT_CARD_VERIFICATION,
80 NUM_FIELD_TYPE_GROUPS_FOR_METRICS 80 NUM_FIELD_TYPE_GROUPS_FOR_METRICS
81 }; 81 };
82 82
83 const int KMaxFieldTypeGroupMetric =
84 NUM_FIELD_TYPE_GROUPS_FOR_METRICS *
85 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS;
86
83 std::string PreviousSaveCreditCardPromptUserDecisionToString( 87 std::string PreviousSaveCreditCardPromptUserDecisionToString(
84 int previous_save_credit_card_prompt_user_decision) { 88 int previous_save_credit_card_prompt_user_decision) {
85 DCHECK_LT(previous_save_credit_card_prompt_user_decision, 89 DCHECK_LT(previous_save_credit_card_prompt_user_decision,
86 prefs::NUM_PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISIONS); 90 prefs::NUM_PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISIONS);
87 std::string previous_response; 91 std::string previous_response;
88 if (previous_save_credit_card_prompt_user_decision == 92 if (previous_save_credit_card_prompt_user_decision ==
89 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED) 93 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED)
90 previous_response = ".PreviouslyAccepted"; 94 previous_response = ".PreviouslyAccepted";
91 else if (previous_save_credit_card_prompt_user_decision == 95 else if (previous_save_credit_card_prompt_user_decision ==
92 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED) 96 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED)
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 base::HistogramBase* histogram = 265 base::HistogramBase* histogram =
262 base::Histogram::FactoryTimeGet( 266 base::Histogram::FactoryTimeGet(
263 name, 267 name,
264 base::TimeDelta::FromMilliseconds(1), 268 base::TimeDelta::FromMilliseconds(1),
265 base::TimeDelta::FromHours(1), 269 base::TimeDelta::FromHours(1),
266 50, 270 50,
267 base::HistogramBase::kUmaTargetedHistogramFlag); 271 base::HistogramBase::kUmaTargetedHistogramFlag);
268 histogram->AddTime(duration); 272 histogram->AddTime(duration);
269 } 273 }
270 274
275 const char* GetQualityMetricTypeSuffix(
276 AutofillMetrics::QualityMetricType metric_type) {
277 switch (metric_type) {
278 default:
279 NOTREACHED();
280 // Fall through...
281
282 case AutofillMetrics::TYPE_SUBMISSION:
283 return "";
284 case AutofillMetrics::TYPE_NO_SUBMISSION:
285 return ".NoSubmission";
286 case AutofillMetrics::TYPE_AUTOCOMPLETE_BASED:
287 return ".BasedOnAutocomplete";
288 }
289 }
290
291 ServerFieldType GetFieldType(const ServerFieldTypeSet field_types,
Mathieu 2017/05/29 14:00:19 GetFieldType is a little vague, can we find a more
Roger McFarlane (Chromium) 2017/05/30 21:43:22 Done.
292 ServerFieldType predicted_type) {
293 if (field_types.count(predicted_type))
294 return predicted_type;
295
296 if (field_types.count(EMPTY_TYPE))
297 return EMPTY_TYPE;
298
299 if (field_types.count(UNKNOWN_TYPE))
300 return UNKNOWN_TYPE;
301
302 // Collapse field types that Chrome treats as identical, e.g. home and
303 // billing address fields.
304 ServerFieldTypeSet collapsed_field_types;
305 for (const auto& type : field_types) {
306 // Since we currently only support US phone numbers, the (city code + main
307 // digits) number is almost always identical to the whole phone number.
308 // TODO(isherman): Improve this logic once we add support for
Mathieu 2017/05/29 14:00:19 hmm...
Roger McFarlane (Chromium) 2017/05/30 21:43:22 Indeed. It's not clear to me that we need to do th
309 // international numbers.
310 if (type == PHONE_HOME_CITY_AND_NUMBER)
311 collapsed_field_types.insert(PHONE_HOME_WHOLE_NUMBER);
312 else
313 collapsed_field_types.insert(AutofillType(type).GetStorableType());
314 }
315
316 // Capture the field's type, if it is unambiguous.
317 ServerFieldType actual_type = UNKNOWN_TYPE;
318 if (collapsed_field_types.size() == 1)
319 actual_type = *collapsed_field_types.begin();
320
321 DVLOG(2) << "Inferred Type: " << AutofillType(actual_type).ToString();
322 return actual_type;
323 }
324
271 // Logs a type quality metric. The primary histogram name is constructed based 325 // Logs a type quality metric. The primary histogram name is constructed based
272 // on |base_name|. The field-specific histogram name also factors in the 326 // on |base_name|. The field-specific histogram name also factors in the
273 // |field_type|. Logs a sample of |metric|, which should be in the range 327 // |field_type|. Logs a sample of |metric|, which should be in the range
274 // [0, |num_possible_metrics|). May log a suffixed version of the metric 328 // [0, |num_possible_metrics|). May log a suffixed version of the metric
275 // depending on |metric_type|. 329 // depending on |metric_type|.
276 void LogTypeQualityMetric(const std::string& base_name, 330 AutofillMetrics::FieldTypeQualityMetric LogTypeQualityMetric(
277 AutofillMetrics::FieldTypeQualityMetric metric, 331 const std::string& base_name,
278 ServerFieldType field_type, 332 ServerFieldTypeSet possible_types,
279 AutofillMetrics::QualityMetricType metric_type) { 333 ServerFieldType predicted_type,
280 DCHECK_LT(metric, AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); 334 AutofillMetrics::QualityMetricType metric_type) {
335 // NO_SERVER_DATA is the equivalent of predicting UNKNOWN.
336 if (predicted_type == NO_SERVER_DATA)
337 predicted_type = UNKNOWN_TYPE;
281 338
282 std::string suffix; 339 // Get the best type classification we can for the field. EMPTY is the same
283 switch (metric_type) { 340 // as UNKNOWN for our purposes, but remember whether or not it was empty for
284 case AutofillMetrics::TYPE_SUBMISSION: 341 // later.
285 break; 342 ServerFieldType actual_type = GetFieldType(possible_types, predicted_type);
Mathieu 2017/05/29 14:00:19 GetActualFieldType perhaps?
Roger McFarlane (Chromium) 2017/05/30 21:43:22 Done.
286 case AutofillMetrics::TYPE_NO_SUBMISSION: 343 bool is_empty = (actual_type == EMPTY_TYPE);
287 suffix = ".NoSubmission"; 344 if (is_empty)
288 break; 345 actual_type = UNKNOWN_TYPE;
289 case AutofillMetrics::TYPE_AUTOCOMPLETE_BASED: 346
290 suffix = ".BasedOnAutocomplete"; 347 // Capture the aggregate quality metric.
291 break; 348 const char* const suffix = GetQualityMetricTypeSuffix(metric_type);
292 default: 349 std::string aggregate_histogram = base_name + suffix;
293 NOTREACHED(); 350 std::string type_specific_histogram = base_name + ".ByFieldType" + suffix;
351
352 DVLOG(2) << "Predicted: " << AutofillType(predicted_type).ToString() << "; "
353 << "Actual: " << AutofillType(actual_type).ToString();
354
355 // If the predicted and actual types match then it's either a true positive
356 // or a true negative (if they are both unknown). Do not log type specific
357 // true negatives (instead log a true positive for the "Ambiguous" type).
358 if (predicted_type == actual_type) {
359 if (actual_type == UNKNOWN_TYPE) {
360 // Only log aggregate true negative; do not log type specific metrics
361 // for UNKNOWN/EMPTY.
362 DVLOG(2) << "TRUE NEGATIVE";
363 auto empty_or_unknown = is_empty ? AutofillMetrics::TRUE_NEGATIVE_EMPTY
364 : AutofillMetrics::TRUE_NEGATIVE_UNKNOWN;
365 LogUMAHistogramEnumeration(
366 aggregate_histogram, empty_or_unknown,
367 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
368 return empty_or_unknown;
369 }
370
371 DVLOG(2) << "TRUE POSITIVE";
372 // Log both aggregate and type specific true positive if we correctly
373 // predict that type with which the field was filled.
374 LogUMAHistogramEnumeration(aggregate_histogram,
375 AutofillMetrics::TRUE_POSITIVE,
376 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
377 LogUMAHistogramEnumeration(
378 type_specific_histogram,
379 GetFieldTypeGroupMetric(actual_type, AutofillMetrics::TRUE_POSITIVE),
380 KMaxFieldTypeGroupMetric);
381 return AutofillMetrics::TRUE_POSITIVE;
294 } 382 }
295 LogUMAHistogramEnumeration(base_name + suffix, metric, 383
384 // Note: At this point predicted_type != actual type
385 // If actual type is UNKNOWN_TYPE then the prediction is a false positive.
386 // Further specialize the type of false positive by whether the field was
387 // empty or contained an unknown value.
388 if (actual_type == UNKNOWN_TYPE) {
389 DVLOG(2) << "FALSE POSITIVE";
390 auto empty_or_unknown = is_empty ? AutofillMetrics::FALSE_POSITIVE_EMPTY
391 : AutofillMetrics::FALSE_POSITIVE_UNKNOWN;
392 LogUMAHistogramEnumeration(aggregate_histogram, empty_or_unknown,
393 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
394 LogUMAHistogramEnumeration(
395 type_specific_histogram,
396 GetFieldTypeGroupMetric(predicted_type, empty_or_unknown),
397 KMaxFieldTypeGroupMetric);
398 return empty_or_unknown;
399 }
400
401 // Note: At this point predicted_type != actual type, actual_type != UNKNOWN.
402 // If predicted type is UNKNOWN_TYPE then the prediction is a false negative
403 // unknown.
404 if (predicted_type == UNKNOWN_TYPE) {
405 DVLOG(2) << "FALSE NEGATIVE";
406 LogUMAHistogramEnumeration(aggregate_histogram,
407 AutofillMetrics::FALSE_NEGATIVE_UNKNOWN,
408 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
409 LogUMAHistogramEnumeration(
410 type_specific_histogram,
411 GetFieldTypeGroupMetric(actual_type,
412 AutofillMetrics::FALSE_NEGATIVE_UNKNOWN),
413 KMaxFieldTypeGroupMetric);
414 return AutofillMetrics::FALSE_NEGATIVE_UNKNOWN;
415 }
416
417 DVLOG(2) << "MISMATCH";
418
419 // Note: At this point predicted_type != actual type, actual_type != UNKNOWN,
420 // predicted_type != UNKNOWN.
421 // This is a mismatch. From the reference of the actual type, this is a false
422 // negative (it was T, but predicted U). From the reference of the prediction,
423 // this is a false positive (predicted it was T, but it was U).
424 LogUMAHistogramEnumeration(aggregate_histogram,
425 AutofillMetrics::FALSE_NEGATIVE_MISMATCH,
296 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS); 426 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS);
427 LogUMAHistogramEnumeration(
Mathieu 2017/05/29 14:00:19 Is it weird two log the same histograms for both r
Roger McFarlane (Chromium) 2017/05/30 21:43:22 It's impossible to do some analyses if you don't (
428 type_specific_histogram,
429 GetFieldTypeGroupMetric(actual_type,
430 AutofillMetrics::FALSE_NEGATIVE_MISMATCH),
431 KMaxFieldTypeGroupMetric);
432 LogUMAHistogramEnumeration(
433 type_specific_histogram,
434 GetFieldTypeGroupMetric(predicted_type,
435 AutofillMetrics::FALSE_POSITIVE_MISMATCH),
436 KMaxFieldTypeGroupMetric);
297 437
298 int field_type_group_metric = GetFieldTypeGroupMetric(field_type, metric); 438 // Return the aggregate finding.
299 int num_field_type_group_metrics = 439 return AutofillMetrics::FALSE_NEGATIVE_MISMATCH;
300 AutofillMetrics::NUM_FIELD_TYPE_QUALITY_METRICS *
301 NUM_FIELD_TYPE_GROUPS_FOR_METRICS;
302 LogUMAHistogramEnumeration(base_name + ".ByFieldType" + suffix,
303 field_type_group_metric,
304 num_field_type_group_metrics);
305 } 440 }
306 441
307 } // namespace 442 } // namespace
308 443
309 // static 444 // static
310 void AutofillMetrics::LogCardUploadDecisionMetrics( 445 void AutofillMetrics::LogCardUploadDecisionMetrics(
311 int upload_decision_metrics) { 446 int upload_decision_metrics) {
312 DCHECK(upload_decision_metrics); 447 DCHECK(upload_decision_metrics);
313 DCHECK_LT(upload_decision_metrics, 1 << kNumCardUploadDecisionMetrics); 448 DCHECK_LT(upload_decision_metrics, 1 << kNumCardUploadDecisionMetrics);
314 449
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 // static 630 // static
496 void AutofillMetrics::LogDeveloperEngagementMetric( 631 void AutofillMetrics::LogDeveloperEngagementMetric(
497 DeveloperEngagementMetric metric) { 632 DeveloperEngagementMetric metric) {
498 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); 633 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS);
499 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, 634 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric,
500 NUM_DEVELOPER_ENGAGEMENT_METRICS); 635 NUM_DEVELOPER_ENGAGEMENT_METRICS);
501 } 636 }
502 637
503 // static 638 // static
504 void AutofillMetrics::LogHeuristicTypePrediction( 639 void AutofillMetrics::LogHeuristicTypePrediction(
505 FieldTypeQualityMetric metric, 640 ServerFieldTypeSet possible_types,
506 ServerFieldType field_type, 641 ServerFieldType predicted_type,
507 QualityMetricType metric_type) { 642 QualityMetricType metric_type) {
508 LogTypeQualityMetric("Autofill.Quality.HeuristicType", metric, field_type, 643 LogTypeQualityMetric("Autofill.Quality.HeuristicType", possible_types,
509 metric_type); 644 predicted_type, metric_type);
510 } 645 }
511 646
512 // static 647 // static
513 void AutofillMetrics::LogOverallTypePrediction(FieldTypeQualityMetric metric, 648 void AutofillMetrics::LogOverallTypePrediction(
514 ServerFieldType field_type, 649 ServerFieldTypeSet possible_types,
515 QualityMetricType metric_type) { 650 ServerFieldType predicted_type,
516 LogTypeQualityMetric("Autofill.Quality.PredictedType", metric, field_type, 651 QualityMetricType metric_type) {
517 metric_type); 652 LogTypeQualityMetric("Autofill.Quality.PredictedType", possible_types,
653 predicted_type, metric_type);
518 } 654 }
519 655
520 // static 656 // static
521 void AutofillMetrics::LogServerTypePrediction(FieldTypeQualityMetric metric, 657 void AutofillMetrics::LogServerTypePrediction(ServerFieldTypeSet possible_types,
522 ServerFieldType field_type, 658 ServerFieldType predicted_type,
523 QualityMetricType metric_type) { 659 QualityMetricType metric_type) {
524 LogTypeQualityMetric("Autofill.Quality.ServerType", metric, field_type, 660 LogTypeQualityMetric("Autofill.Quality.ServerType", possible_types,
525 metric_type); 661 predicted_type, metric_type);
526 } 662 }
527 663
528 // static 664 // static
529 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) { 665 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) {
530 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); 666 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS);
531 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 667 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric,
532 NUM_SERVER_QUERY_METRICS); 668 NUM_SERVER_QUERY_METRICS);
533 } 669 }
534 670
535 // static 671 // static
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 DCHECK(!form_parsed_timestamp_.is_null()); 1309 DCHECK(!form_parsed_timestamp_.is_null());
1174 return (base::TimeTicks::Now() - form_parsed_timestamp_).InMilliseconds(); 1310 return (base::TimeTicks::Now() - form_parsed_timestamp_).InMilliseconds();
1175 } 1311 }
1176 1312
1177 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() { 1313 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() {
1178 source_id_ = ukm_recorder_->GetNewSourceID(); 1314 source_id_ = ukm_recorder_->GetNewSourceID();
1179 ukm_recorder_->UpdateSourceURL(source_id_, url_); 1315 ukm_recorder_->UpdateSourceURL(source_id_, url_);
1180 } 1316 }
1181 1317
1182 } // namespace autofill 1318 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698