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

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

Issue 2940983003: [autofill] Add UKM for field type prediction quality and autofill outcome. (Closed)
Patch Set: 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 const char kUKMFieldTypeGroupMetricName[] = "FieldTypeGroup"; 42 const char kUKMFieldTypeGroupMetricName[] = "FieldTypeGroup";
43 const char kUKMHeuristicTypeMetricName[] = "HeuristicType"; 43 const char kUKMHeuristicTypeMetricName[] = "HeuristicType";
44 const char kUKMServerTypeMetricName[] = "ServerType"; 44 const char kUKMServerTypeMetricName[] = "ServerType";
45 const char kUKMHtmlFieldTypeMetricName[] = "HtmlFieldType"; 45 const char kUKMHtmlFieldTypeMetricName[] = "HtmlFieldType";
46 const char kUKMHtmlFieldModeMetricName[] = "HtmlFieldMode"; 46 const char kUKMHtmlFieldModeMetricName[] = "HtmlFieldMode";
47 const char kUKMIsAutofilledMetricName[] = "IsAutofilled"; 47 const char kUKMIsAutofilledMetricName[] = "IsAutofilled";
48 const char kUKMIsEmptyMetricName[] = "IsEmpty"; 48 const char kUKMIsEmptyMetricName[] = "IsEmpty";
49 const char kUKMFormSubmittedEntryName[] = "Autofill.AutofillFormSubmitted"; 49 const char kUKMFormSubmittedEntryName[] = "Autofill.AutofillFormSubmitted";
50 const char kUKMAutofillFormSubmittedStateMetricName[] = 50 const char kUKMAutofillFormSubmittedStateMetricName[] =
51 "AutofillFormSubmittedState"; 51 "AutofillFormSubmittedState";
52 // |UkmEntry| for capturing field type prediction quality.
53 const char kUKMFieldTypeEntryName[] = "Autofill.FieldTypeValidation";
54 const char kUKMFieldFillStatusEntryName[] = "Autofill.FieldFillStatus";
55 const char kUKMFormSignatureMetricName[] = "FormSignature";
56 const char kUKMFieldSignatureMetricName[] = "FieldSignature";
57 const char kUKMValidationEventMetricName[] = "ValidationEvent";
58 const char kUKMPredictionSourceMetricName[] = "PredictionSource";
59 const char kUKMPredictedTypeMetricName[] = "PredictedType";
60 const char kUKMActualTypeMetricName[] = "ActualType";
61 const char kUKMWasSuggestionShownMetricName[] = "WasSuggestionShown";
62 const char kUKMWasPreviouslyAutofilledMetricName[] = "WasPreviouslyAutofilled";
63
52 } // namespace internal 64 } // namespace internal
53 65
54 namespace autofill { 66 namespace autofill {
55 67
56 namespace { 68 namespace {
57 69
58 // Note: if adding an enum value here, update the corresponding description for 70 // Note: if adding an enum value here, update the corresponding description for
59 // AutofillTypeQualityByFieldType in histograms.xml. 71 // AutofillTypeQualityByFieldType in histograms.xml.
60 enum FieldTypeGroupForMetrics { 72 enum FieldTypeGroupForMetrics {
61 GROUP_AMBIGUOUS = 0, 73 GROUP_AMBIGUOUS = 0,
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 base::HistogramBase* histogram = 282 base::HistogramBase* histogram =
271 base::Histogram::FactoryTimeGet( 283 base::Histogram::FactoryTimeGet(
272 name, 284 name,
273 base::TimeDelta::FromMilliseconds(1), 285 base::TimeDelta::FromMilliseconds(1),
274 base::TimeDelta::FromHours(1), 286 base::TimeDelta::FromHours(1),
275 50, 287 50,
276 base::HistogramBase::kUmaTargetedHistogramFlag); 288 base::HistogramBase::kUmaTargetedHistogramFlag);
277 histogram->AddTime(duration); 289 histogram->AddTime(duration);
278 } 290 }
279 291
292 const char* GetQualityMetricPredictionSource(
293 AutofillMetrics::QualityMetricPredictionSource source) {
294 switch (source) {
295 default:
296 case AutofillMetrics::PREDICTION_SOURCE_UNKNOWN:
297 NOTREACHED();
298 return "Unknown";
299
300 case AutofillMetrics::PREDICTION_SOURCE_HEURISTIC:
301 return "Heuristic";
302 case AutofillMetrics::PREDICTION_SOURCE_SERVER:
303 return "Server";
304 case AutofillMetrics::PREDICTION_SOURCE_OVERALL:
305 return "Overall";
306 }
307 }
308
280 const char* GetQualityMetricTypeSuffix( 309 const char* GetQualityMetricTypeSuffix(
281 AutofillMetrics::QualityMetricType metric_type) { 310 AutofillMetrics::QualityMetricType metric_type) {
282 switch (metric_type) { 311 switch (metric_type) {
283 default: 312 default:
284 NOTREACHED(); 313 NOTREACHED();
285 // Fall through... 314 // Fall through...
286 315
287 case AutofillMetrics::TYPE_SUBMISSION: 316 case AutofillMetrics::TYPE_SUBMISSION:
288 return ""; 317 return "";
289 case AutofillMetrics::TYPE_NO_SUBMISSION: 318 case AutofillMetrics::TYPE_NO_SUBMISSION:
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 DVLOG(2) << "Inferred Type: " << AutofillType(actual_type).ToString(); 366 DVLOG(2) << "Inferred Type: " << AutofillType(actual_type).ToString();
338 return actual_type; 367 return actual_type;
339 } 368 }
340 369
341 // Logs field type prediction quality metrics. The primary histogram name is 370 // Logs field type prediction quality metrics. The primary histogram name is
342 // constructed based on |source| The field-specific histogram name also factors 371 // constructed based on |source| The field-specific histogram name also factors
343 // possible and predicted field types (|possible_types| and |predicted_type|, 372 // possible and predicted field types (|possible_types| and |predicted_type|,
344 // respectively). May log a suffixed version of the metric depending on 373 // respectively). May log a suffixed version of the metric depending on
345 // |metric_type|. 374 // |metric_type|.
346 void LogPredictionQualityMetrics( 375 void LogPredictionQualityMetrics(
347 const base::StringPiece& source, 376 AutofillMetrics::QualityMetricPredictionSource prediction_source,
348 const ServerFieldTypeSet& possible_types,
349 ServerFieldType predicted_type, 377 ServerFieldType predicted_type,
378 AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger,
379 const FormStructure& form,
380 const AutofillField& field,
350 AutofillMetrics::QualityMetricType metric_type) { 381 AutofillMetrics::QualityMetricType metric_type) {
351 // Generate histogram names. 382 // Generate histogram names.
352 const char* const suffix = GetQualityMetricTypeSuffix(metric_type); 383 const char* source = GetQualityMetricPredictionSource(prediction_source);
384 const char* suffix = GetQualityMetricTypeSuffix(metric_type);
353 std::string raw_data_histogram = 385 std::string raw_data_histogram =
354 base::JoinString({"Autofill.FieldPrediction.", source, suffix}, ""); 386 base::JoinString({"Autofill.FieldPrediction.", source, suffix}, "");
355 std::string aggregate_histogram = base::JoinString( 387 std::string aggregate_histogram = base::JoinString(
356 {"Autofill.FieldPredictionQuality.Aggregate.", source, suffix}, ""); 388 {"Autofill.FieldPredictionQuality.Aggregate.", source, suffix}, "");
357 std::string type_specific_histogram = base::JoinString( 389 std::string type_specific_histogram = base::JoinString(
358 {"Autofill.FieldPredictionQuality.ByFieldType.", source, suffix}, ""); 390 {"Autofill.FieldPredictionQuality.ByFieldType.", source, suffix}, "");
359 391
392 const ServerFieldTypeSet& possible_types =
393 metric_type == AutofillMetrics::TYPE_AUTOCOMPLETE_BASED
394 ? ServerFieldTypeSet{AutofillType(field.html_type(),
395 field.html_mode())
396 .GetStorableType()}
397 : field.possible_types();
398
360 // Get the best type classification we can for the field. 399 // Get the best type classification we can for the field.
361 ServerFieldType actual_type = 400 ServerFieldType actual_type =
362 GetActualFieldType(possible_types, predicted_type); 401 GetActualFieldType(possible_types, predicted_type);
363 402
364 DVLOG(2) << "Predicted: " << AutofillType(predicted_type).ToString() << "; " 403 DVLOG(2) << "Predicted: " << AutofillType(predicted_type).ToString() << "; "
365 << "Actual: " << AutofillType(actual_type).ToString(); 404 << "Actual: " << AutofillType(actual_type).ToString();
366 405
367 DCHECK_LE(predicted_type, UINT16_MAX); 406 DCHECK_LE(predicted_type, UINT16_MAX);
368 DCHECK_LE(actual_type, UINT16_MAX); 407 DCHECK_LE(actual_type, UINT16_MAX);
369 UMA_HISTOGRAM_SPARSE_SLOWLY(raw_data_histogram, 408 UMA_HISTOGRAM_SPARSE_SLOWLY(raw_data_histogram,
370 (predicted_type << 16) | actual_type); 409 (predicted_type << 16) | actual_type);
371 410
411 form_interactions_ukm_logger->LogFieldType(
412 form.form_signature(), field.GetFieldSignature(), prediction_source,
413 metric_type, predicted_type, actual_type);
414
372 // NO_SERVER_DATA is the equivalent of predicting UNKNOWN. 415 // NO_SERVER_DATA is the equivalent of predicting UNKNOWN.
373 if (predicted_type == NO_SERVER_DATA) 416 if (predicted_type == NO_SERVER_DATA)
374 predicted_type = UNKNOWN_TYPE; 417 predicted_type = UNKNOWN_TYPE;
375 418
376 // The actual type being EMPTY_TYPE is the same as UNKNOWN_TYPE for comparison 419 // The actual type being EMPTY_TYPE is the same as UNKNOWN_TYPE for comparison
377 // purposes, but remember whether or not it was empty for more precise logging 420 // purposes, but remember whether or not it was empty for more precise logging
378 // later. 421 // later.
379 bool is_empty = (actual_type == EMPTY_TYPE); 422 bool is_empty = (actual_type == EMPTY_TYPE);
380 bool is_ambiguous = (actual_type == AMBIGUOUS_TYPE); 423 bool is_ambiguous = (actual_type == AMBIGUOUS_TYPE);
381 if (is_empty || is_ambiguous) 424 if (is_empty || is_ambiguous)
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 700
658 // static 701 // static
659 void AutofillMetrics::LogDeveloperEngagementMetric( 702 void AutofillMetrics::LogDeveloperEngagementMetric(
660 DeveloperEngagementMetric metric) { 703 DeveloperEngagementMetric metric) {
661 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS); 704 DCHECK_LT(metric, NUM_DEVELOPER_ENGAGEMENT_METRICS);
662 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric, 705 UMA_HISTOGRAM_ENUMERATION("Autofill.DeveloperEngagement", metric,
663 NUM_DEVELOPER_ENGAGEMENT_METRICS); 706 NUM_DEVELOPER_ENGAGEMENT_METRICS);
664 } 707 }
665 708
666 void AutofillMetrics::LogHeuristicPredictionQualityMetrics( 709 void AutofillMetrics::LogHeuristicPredictionQualityMetrics(
667 const ServerFieldTypeSet& possible_types, 710 FormInteractionsUkmLogger* form_interactions_ukm_logger,
668 ServerFieldType predicted_type, 711 const FormStructure& form,
669 AutofillMetrics::QualityMetricType metric_type) { 712 const AutofillField& field,
670 LogPredictionQualityMetrics("Heuristic", possible_types, predicted_type, 713 QualityMetricType metric_type) {
671 metric_type); 714 LogPredictionQualityMetrics(
715 PREDICTION_SOURCE_HEURISTIC,
716 AutofillType(field.heuristic_type()).GetStorableType(),
717 form_interactions_ukm_logger, form, field, metric_type);
672 } 718 }
673 719
674 void AutofillMetrics::LogServerPredictionQualityMetrics( 720 void AutofillMetrics::LogServerPredictionQualityMetrics(
675 const ServerFieldTypeSet& possible_types, 721 FormInteractionsUkmLogger* form_interactions_ukm_logger,
676 ServerFieldType predicted_type, 722 const FormStructure& form,
677 AutofillMetrics::QualityMetricType metric_type) { 723 const AutofillField& field,
678 LogPredictionQualityMetrics("Server", possible_types, predicted_type, 724 QualityMetricType metric_type) {
679 metric_type); 725 LogPredictionQualityMetrics(
726 PREDICTION_SOURCE_SERVER,
727 AutofillType(field.server_type()).GetStorableType(),
728 form_interactions_ukm_logger, form, field, metric_type);
680 } 729 }
681 730
682 void AutofillMetrics::LogOverallPredictionQualityMetrics( 731 void AutofillMetrics::LogOverallPredictionQualityMetrics(
683 const ServerFieldTypeSet& possible_types, 732 FormInteractionsUkmLogger* form_interactions_ukm_logger,
684 ServerFieldType predicted_type, 733 const FormStructure& form,
685 AutofillMetrics::QualityMetricType metric_type) { 734 const AutofillField& field,
686 LogPredictionQualityMetrics("Overall", possible_types, predicted_type, 735 QualityMetricType metric_type) {
687 metric_type); 736 LogPredictionQualityMetrics(
737 PREDICTION_SOURCE_OVERALL, field.Type().GetStorableType(),
738 form_interactions_ukm_logger, form, field, metric_type);
688 } 739 }
689 740
690 // static 741 // static
691 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) { 742 void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) {
692 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS); 743 DCHECK_LT(metric, NUM_SERVER_QUERY_METRICS);
693 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric, 744 UMA_HISTOGRAM_ENUMERATION("Autofill.ServerQueryResponse", metric,
694 NUM_SERVER_QUERY_METRICS); 745 NUM_SERVER_QUERY_METRICS);
695 } 746 }
696 747
697 // static 748 // static
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 builder->AddMetric(internal::kUKMHtmlFieldTypeMetricName, 1348 builder->AddMetric(internal::kUKMHtmlFieldTypeMetricName,
1298 static_cast<int>(field.html_type())); 1349 static_cast<int>(field.html_type()));
1299 builder->AddMetric(internal::kUKMHtmlFieldModeMetricName, 1350 builder->AddMetric(internal::kUKMHtmlFieldModeMetricName,
1300 static_cast<int>(field.html_mode())); 1351 static_cast<int>(field.html_mode()));
1301 builder->AddMetric(internal::kUKMIsAutofilledMetricName, field.is_autofilled); 1352 builder->AddMetric(internal::kUKMIsAutofilledMetricName, field.is_autofilled);
1302 builder->AddMetric(internal::kUKMIsEmptyMetricName, field.IsEmpty()); 1353 builder->AddMetric(internal::kUKMIsEmptyMetricName, field.IsEmpty());
1303 builder->AddMetric(internal::kUKMMillisecondsSinceFormParsedMetricName, 1354 builder->AddMetric(internal::kUKMMillisecondsSinceFormParsedMetricName,
1304 MillisecondsSinceFormParsed()); 1355 MillisecondsSinceFormParsed());
1305 } 1356 }
1306 1357
1358 void AutofillMetrics::FormInteractionsUkmLogger::LogFieldFillStatus(
1359 const FormStructure& form,
1360 const AutofillField& field,
1361 QualityMetricType metric_type) {
1362 if (!CanLog())
1363 return;
1364
1365 if (source_id_ == -1)
1366 GetNewSourceID();
1367
1368 std::unique_ptr<ukm::UkmEntryBuilder> builder =
1369 ukm_recorder_->GetEntryBuilder(source_id_,
1370 internal::kUKMFieldFillStatusEntryName);
1371 builder->AddMetric(internal::kUKMMillisecondsSinceFormParsedMetricName,
1372 MillisecondsSinceFormParsed());
1373 builder->AddMetric(internal::kUKMFormSignatureMetricName,
1374 static_cast<int64_t>(form.form_signature()));
1375 builder->AddMetric(internal::kUKMFieldSignatureMetricName,
1376 static_cast<int64_t>(field.GetFieldSignature()));
1377 builder->AddMetric(internal::kUKMValidationEventMetricName,
1378 static_cast<int64_t>(metric_type));
1379 builder->AddMetric(internal::kUKMIsAutofilledMetricName,
1380 static_cast<int64_t>(field.is_autofilled));
1381 builder->AddMetric(internal::kUKMWasPreviouslyAutofilledMetricName,
1382 static_cast<int64_t>(field.previously_autofilled()));
1383 }
1384
1385 void AutofillMetrics::FormInteractionsUkmLogger::LogFieldType(
1386 FormSignature form_signature,
1387 FieldSignature field_signature,
1388 QualityMetricPredictionSource prediction_source,
1389 QualityMetricType metric_type,
1390 ServerFieldType predicted_type,
1391 ServerFieldType actual_type) {
1392 if (!CanLog())
1393 return;
1394
1395 if (source_id_ == -1)
1396 GetNewSourceID();
1397
1398 std::unique_ptr<ukm::UkmEntryBuilder> builder =
1399 ukm_recorder_->GetEntryBuilder(source_id_,
1400 internal::kUKMFieldTypeEntryName);
1401 builder->AddMetric(internal::kUKMMillisecondsSinceFormParsedMetricName,
1402 MillisecondsSinceFormParsed());
1403 builder->AddMetric(internal::kUKMFormSignatureMetricName,
1404 static_cast<int64_t>(form_signature));
1405 builder->AddMetric(internal::kUKMFieldSignatureMetricName,
1406 static_cast<int64_t>(field_signature));
1407 builder->AddMetric(internal::kUKMValidationEventMetricName,
1408 static_cast<int64_t>(metric_type));
1409 builder->AddMetric(internal::kUKMPredictionSourceMetricName,
1410 static_cast<int64_t>(prediction_source));
1411 builder->AddMetric(internal::kUKMPredictedTypeMetricName,
1412 static_cast<int64_t>(predicted_type));
1413 builder->AddMetric(internal::kUKMActualTypeMetricName,
1414 static_cast<int64_t>(actual_type));
1415 }
1416
1307 void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted( 1417 void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted(
1308 AutofillFormSubmittedState state) { 1418 AutofillFormSubmittedState state) {
1309 if (!CanLog()) 1419 if (!CanLog())
1310 return; 1420 return;
1311 1421
1312 if (source_id_ == -1) 1422 if (source_id_ == -1)
1313 GetNewSourceID(); 1423 GetNewSourceID();
1314 1424
1315 std::unique_ptr<ukm::UkmEntryBuilder> builder = 1425 std::unique_ptr<ukm::UkmEntryBuilder> builder =
1316 ukm_recorder_->GetEntryBuilder(source_id_, 1426 ukm_recorder_->GetEntryBuilder(source_id_,
(...skipping 17 matching lines...) Expand all
1334 } 1444 }
1335 1445
1336 bool AutofillMetrics::FormInteractionsUkmLogger::CanLog() const { 1446 bool AutofillMetrics::FormInteractionsUkmLogger::CanLog() const {
1337 return ukm_recorder_ && url_.is_valid(); 1447 return ukm_recorder_ && url_.is_valid();
1338 } 1448 }
1339 1449
1340 int64_t 1450 int64_t
1341 AutofillMetrics::FormInteractionsUkmLogger::MillisecondsSinceFormParsed() 1451 AutofillMetrics::FormInteractionsUkmLogger::MillisecondsSinceFormParsed()
1342 const { 1452 const {
1343 DCHECK(!form_parsed_timestamp_.is_null()); 1453 DCHECK(!form_parsed_timestamp_.is_null());
1344 return (base::TimeTicks::Now() - form_parsed_timestamp_).InMilliseconds(); 1454 // Use the pinned timestamp as the current time if it's set.
1455 base::TimeTicks now =
1456 pinned_timestamp_.is_null() ? base::TimeTicks::Now() : pinned_timestamp_;
1457 return (now - form_parsed_timestamp_).InMilliseconds();
1345 } 1458 }
1346 1459
1347 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() { 1460 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() {
1348 source_id_ = ukm_recorder_->GetNewSourceID(); 1461 source_id_ = ukm_recorder_->GetNewSourceID();
1349 ukm_recorder_->UpdateSourceURL(source_id_, url_); 1462 ukm_recorder_->UpdateSourceURL(source_id_, url_);
1350 } 1463 }
1351 1464
1352 } // namespace autofill 1465 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698