blob: a5062f365557b89822d158b0e988dafd17dc221d [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/download/internal/background_service/stats.h"
#include <map>
#include "base/files/file_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "components/download/internal/background_service/startup_status.h"
namespace download {
namespace stats {
namespace {
// The maximum tracked file size in KB, larger files will fall into overflow
// bucket.
const int64_t kMaxFileSizeKB = 4 * 1024 * 1024; /* 4GB */
// Enum used by UMA metrics to track various reasons of pausing a download.
enum class PauseReason {
// The download was paused. The reason can be anything.
ANY = 0,
// The download was paused due to unsatisfied device criteria.
UNMET_DEVICE_CRITERIA = 1,
// The download was paused by client.
PAUSE_BY_CLIENT = 2,
// The download was paused due to external download.
EXTERNAL_DOWNLOAD = 3,
// The download was paused due to navigation.
EXTERNAL_NAVIGATION = 4,
// The count of entries for the enum.
COUNT = 5,
};
// Converts DownloadTaskType to histogram suffix.
// Should maps to suffix string in histograms.xml.
std::string TaskTypeToHistogramSuffix(DownloadTaskType task_type) {
switch (task_type) {
case DownloadTaskType::DOWNLOAD_TASK:
return "DownloadTask";
case DownloadTaskType::CLEANUP_TASK:
return "CleanUpTask";
case DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK:
return "DownloadAutoResumptionTask";
}
NOTREACHED();
return std::string();
}
// Converts Entry::State to histogram suffix.
// Should maps to suffix string in histograms.xml.
std::string EntryStateToHistogramSuffix(Entry::State state) {
std::string suffix;
switch (state) {
case Entry::State::NEW:
return "New";
case Entry::State::AVAILABLE:
return "Available";
case Entry::State::ACTIVE:
return "Active";
case Entry::State::PAUSED:
return "Paused";
case Entry::State::COMPLETE:
return "Complete";
case Entry::State::COUNT:
break;
}
NOTREACHED();
return std::string();
}
// Converts DownloadClient to histogram suffix.
// Should maps to suffix string in histograms.xml.
std::string ClientToHistogramSuffix(DownloadClient client) {
switch (client) {
case DownloadClient::TEST:
case DownloadClient::TEST_2:
case DownloadClient::TEST_3:
case DownloadClient::INVALID:
return "__Test__";
case DownloadClient::OFFLINE_PAGE_PREFETCH:
return "OfflinePage";
case DownloadClient::BACKGROUND_FETCH:
return "BackgroundFetch";
case DownloadClient::DEBUGGING:
return "Debugging";
case DownloadClient::MOUNTAIN_INTERNAL:
return "MountainInternal";
case DownloadClient::PLUGIN_VM_IMAGE:
return "PluginVmImage";
case DownloadClient::BOUNDARY:
NOTREACHED();
break;
}
NOTREACHED();
return std::string();
}
// Converts CompletionType to histogram suffix.
// Should maps to suffix string in histograms.xml.
std::string CompletionTypeToHistogramSuffix(CompletionType type) {
switch (type) {
case CompletionType::SUCCEED:
return "Succeed";
case CompletionType::FAIL:
return "Fail";
case CompletionType::ABORT:
return "Abort";
case CompletionType::TIMEOUT:
return "Timeout";
case CompletionType::UNKNOWN:
return "Unknown";
case CompletionType::CANCEL:
return "Cancel";
case CompletionType::OUT_OF_RETRIES:
return "OutOfRetries";
case CompletionType::OUT_OF_RESUMPTIONS:
return "OutOfResumptions";
case CompletionType::UPLOAD_TIMEOUT:
return "UploadTimeout";
case CompletionType::COUNT:
NOTREACHED();
}
NOTREACHED();
return std::string();
}
// Converts FileCleanupReason to histogram suffix.
// Should maps to suffix string in histograms.xml.
std::string FileCleanupReasonToHistogramSuffix(FileCleanupReason reason) {
switch (reason) {
case FileCleanupReason::TIMEOUT:
return "Timeout";
case FileCleanupReason::ORPHANED:
return "Orphaned";
case FileCleanupReason::UNKNOWN:
return "Unknown";
case FileCleanupReason::HARD_RECOVERY:
return "HardRecovery";
case FileCleanupReason::COUNT:
NOTREACHED();
}
NOTREACHED();
return std::string();
}
// Helper method to log StartUpResult.
void LogStartUpResult(bool in_recovery, StartUpResult result) {
if (in_recovery) {
base::UmaHistogramEnumeration("Download.Service.StartUpStatus.Recovery",
result, StartUpResult::COUNT);
} else {
base::UmaHistogramEnumeration(
"Download.Service.StartUpStatus.Initialization", result,
StartUpResult::COUNT);
}
}
// Helper method to log the number of entries under a particular state.
void LogDatabaseRecords(Entry::State state, uint32_t record_count) {
std::string name("Download.Service.Db.Records");
name.append(".").append(EntryStateToHistogramSuffix(state));
base::UmaHistogramCustomCounts(name, record_count, 1, 500, 50);
}
// Helper method to log the pause reason for a particular download.
void LogDownloadPauseReason(PauseReason reason, bool on_upload_data_received) {
std::string name(on_upload_data_received
? "Download.Service.OnUploadDataReceived.PauseReason"
: "Download.Service.PauseReason");
base::UmaHistogramEnumeration(name, reason, PauseReason::COUNT);
}
} // namespace
void LogControllerStartupStatus(bool in_recovery, const StartupStatus& status) {
DCHECK(status.Complete());
// Total counts for general success/failure rate.
LogStartUpResult(in_recovery, status.Ok() ? StartUpResult::SUCCESS
: StartUpResult::FAILURE);
// Failure reasons.
if (!status.driver_ok.value())
LogStartUpResult(in_recovery, StartUpResult::FAILURE_REASON_DRIVER);
if (!status.model_ok.value())
LogStartUpResult(in_recovery, StartUpResult::FAILURE_REASON_MODEL);
if (!status.file_monitor_ok.value())
LogStartUpResult(in_recovery, StartUpResult::FAILURE_REASON_FILE_MONITOR);
}
void LogServiceApiAction(DownloadClient client, ServiceApiAction action) {
// Total count for each action.
std::string name("Download.Service.Request.ClientAction");
base::UmaHistogramEnumeration(name, action, ServiceApiAction::COUNT);
// Total count for each action with client suffix.
name.append(".").append(ClientToHistogramSuffix(client));
base::UmaHistogramEnumeration(name, action, ServiceApiAction::COUNT);
}
void LogStartDownloadResult(DownloadClient client,
DownloadParams::StartResult result) {
// Total count for each start result.
std::string name("Download.Service.Request.StartResult");
base::UmaHistogramEnumeration(name, result,
DownloadParams::StartResult::COUNT);
// Total count for each client result with client suffix.
name.append(".").append(ClientToHistogramSuffix(client));
base::UmaHistogramEnumeration(name, result,
DownloadParams::StartResult::COUNT);
}
void LogStartDownloadResponse(DownloadClient client,
Client::ShouldDownload should_download) {
// Total count for each start response.
std::string name("Download.Service.Request.StartResponse");
base::UmaHistogramEnumeration(name, should_download,
Client::ShouldDownload::COUNT);
// Total count for each client response with client suffix.
name.append(".").append(ClientToHistogramSuffix(client));
base::UmaHistogramEnumeration(name, should_download,
Client::ShouldDownload::COUNT);
}
void LogDownloadParams(const DownloadParams& params) {
UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.BatteryRequirement",
params.scheduling_params.battery_requirements,
SchedulingParams::BatteryRequirements::COUNT);
UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.NetworkRequirement",
params.scheduling_params.network_requirements,
SchedulingParams::NetworkRequirements::COUNT);
UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.Priority",
params.scheduling_params.priority,
SchedulingParams::Priority::COUNT);
}
void LogRecoveryOperation(Entry::State to_state) {
UMA_HISTOGRAM_ENUMERATION("Download.Service.Recovery", to_state,
Entry::State::COUNT);
}
void LogDownloadCompletion(CompletionType type, uint64_t file_size_bytes) {
// Records completion type.
UMA_HISTOGRAM_ENUMERATION("Download.Service.Finish.Type", type,
CompletionType::COUNT);
// TODO(xingliu): Use DownloadItem::GetStartTime and DownloadItem::GetEndTime
// to record the completion time to histogram "Download.Service.Finish.Time".
// Also propagates and records the mime type here.
// Records the file size.
std::string name("Download.Service.Finish.FileSize");
uint64_t file_size_kb = file_size_bytes / 1024;
base::UmaHistogramCustomCounts(name, file_size_kb, 1, kMaxFileSizeKB, 50);
name.append(".").append(CompletionTypeToHistogramSuffix(type));
base::UmaHistogramCustomCounts(name, file_size_kb, 1, kMaxFileSizeKB, 50);
}
void LogDownloadPauseReason(const DownloadBlockageStatus& blockage_status,
bool currently_in_progress) {
LogDownloadPauseReason(PauseReason::ANY, currently_in_progress);
if (blockage_status.blocked_by_criteria)
LogDownloadPauseReason(PauseReason::UNMET_DEVICE_CRITERIA,
currently_in_progress);
if (blockage_status.entry_not_active)
LogDownloadPauseReason(PauseReason::PAUSE_BY_CLIENT, currently_in_progress);
if (blockage_status.blocked_by_navigation)
LogDownloadPauseReason(PauseReason::EXTERNAL_NAVIGATION,
currently_in_progress);
if (blockage_status.blocked_by_downloads)
LogDownloadPauseReason(PauseReason::EXTERNAL_DOWNLOAD,
currently_in_progress);
}
void LogModelOperationResult(ModelAction action, bool success) {
if (success) {
UMA_HISTOGRAM_ENUMERATION("Download.Service.Db.Operation.Success", action,
ModelAction::COUNT);
} else {
UMA_HISTOGRAM_ENUMERATION("Download.Service.Db.Operation.Failure", action,
ModelAction::COUNT);
}
}
void LogEntries(std::map<Entry::State, uint32_t>& entries_count) {
uint32_t total_records = 0;
for (const auto& entry_count : entries_count)
total_records += entry_count.second;
// Total number of records in database.
base::UmaHistogramCustomCounts("Download.Service.Db.Records", total_records,
1, 500, 50);
// Number of records for each Entry::State.
for (Entry::State state = Entry::State::NEW; state != Entry::State::COUNT;
state = (Entry::State)((int)(state) + 1)) {
LogDatabaseRecords(state, entries_count[state]);
}
}
void LogScheduledTaskStatus(DownloadTaskType task_type,
ScheduledTaskStatus status) {
std::string name("Download.Service.TaskScheduler.Status");
base::UmaHistogramEnumeration(name, status, ScheduledTaskStatus::COUNT);
name.append(".").append(TaskTypeToHistogramSuffix(task_type));
base::UmaHistogramEnumeration(name, status, ScheduledTaskStatus::COUNT);
}
void LogsFileDirectoryCreationError(base::File::Error error) {
// Maps to histogram enum PlatformFileError.
UMA_HISTOGRAM_ENUMERATION("Download.Service.Files.DirCreationError", -error,
-base::File::Error::FILE_ERROR_MAX);
}
void LogFileCleanupStatus(FileCleanupReason reason,
int succeeded_cleanups,
int failed_cleanups,
int external_cleanups) {
std::string name("Download.Service.Files.CleanUp.Success");
base::UmaHistogramCounts100(name, succeeded_cleanups);
name.append(".").append(FileCleanupReasonToHistogramSuffix(reason));
base::UmaHistogramCounts100(name, succeeded_cleanups);
name = "Download.Service.Files.CleanUp.Failure";
base::UmaHistogramCounts100(name, failed_cleanups);
name.append(".").append(FileCleanupReasonToHistogramSuffix(reason));
base::UmaHistogramCounts100(name, failed_cleanups);
name = "Download.Service.Files.CleanUp.External";
base::UmaHistogramCounts100(name, external_cleanups);
name.append(".").append(FileCleanupReasonToHistogramSuffix(reason));
base::UmaHistogramCounts100(name, external_cleanups);
}
void LogFileLifeTime(const base::TimeDelta& file_life_time,
int num_cleanup_attempts) {
UMA_HISTOGRAM_CUSTOM_TIMES("Download.Service.Files.LifeTime", file_life_time,
base::TimeDelta::FromSeconds(1),
base::TimeDelta::FromDays(8), 100);
base::UmaHistogramSparse("Download.Service.Files.Cleanup.Attempts",
num_cleanup_attempts);
}
void LogFileDirDiskUtilization(int64_t total_disk_space,
int64_t free_disk_space,
int64_t files_size) {
UMA_HISTOGRAM_PERCENTAGE("Download.Service.Files.FreeDiskSpace",
(free_disk_space * 100) / total_disk_space);
UMA_HISTOGRAM_PERCENTAGE("Download.Service.Files.DiskUsed",
(files_size * 100) / total_disk_space);
}
void LogFilePathRenamed(bool renamed) {
UMA_HISTOGRAM_BOOLEAN("Download.Service.Files.PathRenamed", renamed);
}
void LogEntryEvent(DownloadEvent event) {
UMA_HISTOGRAM_ENUMERATION("Download.Service.Entry.Event", event,
DownloadEvent::COUNT);
}
void LogEntryResumptionCount(uint32_t resume_count) {
UMA_HISTOGRAM_COUNTS_100("Download.Service.Entry.ResumptionCount",
resume_count);
}
void LogEntryRetryCount(uint32_t retry_count) {
UMA_HISTOGRAM_COUNTS_100("Download.Service.Entry.RetryCount", retry_count);
}
void LogEntryRemovedWhileWaitingForUploadResponse() {
UMA_HISTOGRAM_BOOLEAN("Download.Service.Upload.EntryNotFound", true);
}
void LogHasUploadData(DownloadClient client, bool has_upload_data) {
std::string name("Download.Service.Upload.HasUploadData");
name.append(".").append(ClientToHistogramSuffix(client));
base::UmaHistogramBoolean(name, has_upload_data);
}
void LogHashPresence(bool hash_exists) {
UMA_HISTOGRAM_BOOLEAN("Download.Service.Finish.ReportedHash", hash_exists);
}
} // namespace stats
} // namespace download