1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_metrics.h"
7 #include "base/metrics/histogram_macros.h"
8 #include "base/metrics/sparse_histogram.h"
9 #include "base/strings/string_util.h"
10 #include "content/common/service_worker/service_worker_types.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/content_browser_client.h"
13 #include "content/public/common/content_client.h"
19 void RecordURLMetricOnUI(const GURL
& url
) {
20 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
21 GetContentClient()->browser()->RecordURLMetric(
22 "ServiceWorker.ControlledPageUrl", url
);
25 ServiceWorkerMetrics::Site
SiteFromURL(const GURL
& gurl
) {
26 // UIThreadSearchTermsData::GoogleBaseURLValue() returns the google base
27 // URL, but not available in content layer.
28 static const char google_like_scope_prefix
[] = "https://www.google.";
29 static const char ntp_scope_path
[] = "/_/chrome/";
30 if (base::StartsWith(gurl
.spec(), google_like_scope_prefix
,
31 base::CompareCase::INSENSITIVE_ASCII
) &&
32 base::StartsWith(gurl
.path(), ntp_scope_path
,
33 base::CompareCase::SENSITIVE
)) {
34 return ServiceWorkerMetrics::Site::NEW_TAB_PAGE
;
37 return ServiceWorkerMetrics::Site::OTHER
;
40 bool ShouldExcludeForHistogram(const GURL
& scope
) {
41 // Exclude NTP scope from UMA for now as it tends to dominate the stats
42 // and makes the results largely skewed.
43 return SiteFromURL(scope
) == ServiceWorkerMetrics::Site::NEW_TAB_PAGE
;
46 enum EventHandledRatioType
{
50 NUM_EVENT_HANDLED_RATIO_TYPE
,
55 void ServiceWorkerMetrics::CountInitDiskCacheResult(bool result
) {
56 UMA_HISTOGRAM_BOOLEAN("ServiceWorker.DiskCache.InitResult", result
);
59 void ServiceWorkerMetrics::CountReadResponseResult(
60 ServiceWorkerMetrics::ReadResponseResult result
) {
61 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCache.ReadResponseResult",
62 result
, NUM_READ_RESPONSE_RESULT_TYPES
);
65 void ServiceWorkerMetrics::CountWriteResponseResult(
66 ServiceWorkerMetrics::WriteResponseResult result
) {
67 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCache.WriteResponseResult",
68 result
, NUM_WRITE_RESPONSE_RESULT_TYPES
);
71 void ServiceWorkerMetrics::CountOpenDatabaseResult(
72 ServiceWorkerDatabase::Status status
) {
73 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.OpenResult",
74 status
, ServiceWorkerDatabase::STATUS_ERROR_MAX
);
77 void ServiceWorkerMetrics::CountReadDatabaseResult(
78 ServiceWorkerDatabase::Status status
) {
79 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.ReadResult",
80 status
, ServiceWorkerDatabase::STATUS_ERROR_MAX
);
83 void ServiceWorkerMetrics::CountWriteDatabaseResult(
84 ServiceWorkerDatabase::Status status
) {
85 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.WriteResult",
86 status
, ServiceWorkerDatabase::STATUS_ERROR_MAX
);
89 void ServiceWorkerMetrics::RecordDestroyDatabaseResult(
90 ServiceWorkerDatabase::Status status
) {
91 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.DestroyDatabaseResult",
92 status
, ServiceWorkerDatabase::STATUS_ERROR_MAX
);
95 void ServiceWorkerMetrics::RecordPurgeResourceResult(int net_error
) {
96 UMA_HISTOGRAM_SPARSE_SLOWLY("ServiceWorker.Storage.PurgeResourceResult",
100 void ServiceWorkerMetrics::RecordDiskCacheMigrationResult(
101 DiskCacheMigrationResult result
) {
102 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Storage.DiskCacheMigrationResult",
103 result
, NUM_MIGRATION_RESULT_TYPES
);
106 void ServiceWorkerMetrics::RecordDeleteAndStartOverResult(
107 DeleteAndStartOverResult result
) {
108 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Storage.DeleteAndStartOverResult",
109 result
, NUM_DELETE_AND_START_OVER_RESULT_TYPES
);
112 void ServiceWorkerMetrics::CountControlledPageLoad(const GURL
& url
) {
113 Site site
= SiteFromURL(url
);
114 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.PageLoad", static_cast<int>(site
),
115 static_cast<int>(Site::NUM_TYPES
));
117 // Don't record NTP on RAPPOR since it would dominate the data.
118 if (site
== Site::NEW_TAB_PAGE
)
120 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
121 base::Bind(&RecordURLMetricOnUI
, url
));
124 void ServiceWorkerMetrics::RecordStartWorkerStatus(
125 ServiceWorkerStatusCode status
,
128 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status
,
129 SERVICE_WORKER_ERROR_MAX_VALUE
);
131 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartNewWorker.Status", status
,
132 SERVICE_WORKER_ERROR_MAX_VALUE
);
136 void ServiceWorkerMetrics::RecordStartWorkerTime(const base::TimeDelta
& time
,
139 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", time
);
141 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartNewWorker.Time", time
);
144 void ServiceWorkerMetrics::RecordStopWorkerStatus(StopWorkerStatus status
) {
145 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StopWorker.Status", status
,
146 NUM_STOP_STATUS_TYPES
);
149 void ServiceWorkerMetrics::RecordStopWorkerTime(const base::TimeDelta
& time
) {
150 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StopWorker.Time", time
);
153 void ServiceWorkerMetrics::RecordActivateEventStatus(
154 ServiceWorkerStatusCode status
) {
155 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus", status
,
156 SERVICE_WORKER_ERROR_MAX_VALUE
);
159 void ServiceWorkerMetrics::RecordInstallEventStatus(
160 ServiceWorkerStatusCode status
) {
161 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.InstallEventStatus", status
,
162 SERVICE_WORKER_ERROR_MAX_VALUE
);
165 void ServiceWorkerMetrics::RecordEventHandledRatio(const GURL
& scope
,
167 size_t handled_events
,
168 size_t fired_events
) {
169 if (!fired_events
|| ShouldExcludeForHistogram(scope
))
171 EventHandledRatioType type
= EVENT_HANDLED_SOME
;
172 if (fired_events
== handled_events
)
173 type
= EVENT_HANDLED_ALL
;
174 else if (handled_events
== 0)
175 type
= EVENT_HANDLED_NONE
;
176 // For now Fetch is the only type that is recorded.
177 DCHECK_EQ(EVENT_TYPE_FETCH
, event
);
178 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.EventHandledRatioType.Fetch", type
,
179 NUM_EVENT_HANDLED_RATIO_TYPE
);
182 void ServiceWorkerMetrics::RecordFetchEventStatus(
183 bool is_main_resource
,
184 ServiceWorkerStatusCode status
) {
185 if (is_main_resource
) {
186 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.FetchEvent.MainResource.Status",
187 status
, SERVICE_WORKER_ERROR_MAX_VALUE
);
189 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.FetchEvent.Subresource.Status",
190 status
, SERVICE_WORKER_ERROR_MAX_VALUE
);
194 void ServiceWorkerMetrics::RecordFetchEventTime(
195 ServiceWorkerFetchEventResult result
,
196 const base::TimeDelta
& time
) {
198 case ServiceWorkerFetchEventResult::
199 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK
:
200 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.Fallback.Time",
203 case ServiceWorkerFetchEventResult::
204 SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
:
205 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.HasResponse.Time",
211 void ServiceWorkerMetrics::RecordURLRequestJobResult(
212 bool is_main_resource
,
213 URLRequestJobResult result
) {
214 if (is_main_resource
) {
215 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.URLRequestJob.MainResource.Result",
216 result
, NUM_REQUEST_JOB_RESULT_TYPES
);
218 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.URLRequestJob.Subresource.Result",
219 result
, NUM_REQUEST_JOB_RESULT_TYPES
);
223 void ServiceWorkerMetrics::RecordStatusZeroResponseError(
224 bool is_main_resource
,
225 blink::WebServiceWorkerResponseError error
) {
226 if (is_main_resource
) {
227 UMA_HISTOGRAM_ENUMERATION(
228 "ServiceWorker.URLRequestJob.MainResource.StatusZeroError", error
,
229 blink::WebServiceWorkerResponseErrorLast
+ 1);
231 UMA_HISTOGRAM_ENUMERATION(
232 "ServiceWorker.URLRequestJob.Subresource.StatusZeroError", error
,
233 blink::WebServiceWorkerResponseErrorLast
+ 1);
237 void ServiceWorkerMetrics::RecordFallbackedRequestMode(FetchRequestMode mode
) {
238 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.URLRequestJob.FallbackedRequestMode",
239 mode
, FETCH_REQUEST_MODE_LAST
+ 1);
242 } // namespace content