Index: chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc |
diff --git a/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6ef2d29b84e029cf44d86900f41e2868d6e100f4 |
--- /dev/null |
+++ b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc |
@@ -0,0 +1,143 @@ |
+// Copyright 2015 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 "chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h" |
+ |
+#include <stdio.h> |
+ |
+#include <string> |
+ |
+#include "base/metrics/histogram.h" |
+#include "base/metrics/sparse_histogram.h" |
+#include "net/http/http_response_headers.h" |
+#include "url/gurl.h" |
+ |
+namespace mod_pagespeed { |
+ |
+namespace { |
+ |
+const char kModPagespeedHeader[] = "X-Mod-Pagespeed"; |
+const char kPageSpeedHeader[] = "X-Page-Speed"; |
+ |
+// For historical reasons, mod_pagespeed usage metrics are named with a |
+// prerender prefix. |
+const char kPagespeedServerHistogram[] = |
+ "Prerender.PagespeedHeader.ServerCounts"; |
+const char kPagespeedVersionHistogram[] = |
+ "Prerender.PagespeedHeader.VersionCounts"; |
+ |
+enum PagespeedHeaderServerType { |
+ PAGESPEED_TOTAL_RESPONSES = 0, |
+ PAGESPEED_MOD_PAGESPEED_SERVER = 1, |
+ PAGESPEED_NGX_PAGESPEED_SERVER = 2, |
+ PAGESPEED_PAGESPEED_SERVICE_SERVER = 3, |
+ PAGESPEED_UNKNOWN_SERVER = 4, |
+ PAGESPEED_SERVER_MAXIMUM = 5 |
+}; |
+ |
+// Parse the PageSpeed version number and encodes it in buckets 2 through 99: if |
+// it is in the format MAJOR.MINOR.BRANCH.POINT-COMMIT the bucket will be 2 + 2 |
+// * (max(BRANCH, 10) - 10) + (POINT > 1 ? 1 : 0); otherwise the bucket is |
+// zero. |
+int GetXModPagespeedBucketFromVersion(const std::string& version) { |
+ int unused_major, unused_minor, branch, point, unused_commit; |
+ int num_parsed = sscanf(version.c_str(), "%d.%d.%d.%d-%d", &unused_major, |
+ &unused_minor, &branch, &point, &unused_commit); |
+ int output = 0; |
+ if (num_parsed == 5) { |
+ output = 2; |
+ if (branch > 10) |
+ output += 2 * (branch - 10); |
+ if (point > 1) |
+ output++; |
+ if (output < 2 || output > 99) |
+ output = 0; |
+ } |
+ return output; |
+} |
+ |
+// Parse the X-Page-Speed header value and determine whether it is in the |
+// PageSpeed Service format, namely MAJOR_MINOR_AB were MAJOR_MINOR is a version |
+// number and AB is an encoded 2-character value. |
+bool IsPageSpeedServiceVersionNumber(const std::string& version) { |
+ int major, minor; |
+ // is_eol is to detect EOL as we check that it /isn't/ converted. |
+ char a, b, is_eol; |
+ int num_parsed = |
+ sscanf(version.c_str(), "%d_%d_%c%c%c", &major, &minor, &a, &b, &is_eol); |
+ return (num_parsed == 4); |
+} |
+ |
+} // namespace |
+ |
+void RecordMetrics(const content::ResourceType resource_type, |
+ const GURL& request_url, |
+ const net::HttpResponseHeaders* response_headers) { |
+ if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME || |
+ !request_url.SchemeIsHTTPOrHTTPS()) { |
+ return; |
+ } |
+ |
+ // Bucket 0 counts every response seen. |
+ UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, |
+ PAGESPEED_TOTAL_RESPONSES, |
+ PAGESPEED_SERVER_MAXIMUM); |
+ if (!response_headers) |
+ return; |
+ |
+ void* iter = nullptr; |
+ std::string name; |
+ std::string value; |
+ while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) { |
+ if (name == kModPagespeedHeader) { |
+ // Bucket 1 counts occurrences of the X-Mod-Pagespeed header. |
+ UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, |
+ PAGESPEED_MOD_PAGESPEED_SERVER, |
+ PAGESPEED_SERVER_MAXIMUM); |
+ if (!value.empty()) { |
+ // If the header value is in the X-Mod-Pagespeed version number format |
+ // then increment the appropriate bucket, otherwise increment bucket 1, |
+ // which is the catch-all "unknown version number" bucket. |
+ int bucket = GetXModPagespeedBucketFromVersion(value); |
+ if (bucket > 0) { |
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); |
+ } else { |
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, 1); |
+ } |
+ } |
+ break; |
+ } else if (name == kPageSpeedHeader) { |
+ // X-Page-Speed header versions are either in the X-Mod-Pagespeed format, |
+ // indicating an nginx installation, or they're in the PageSpeed Service |
+ // format, indicating a PSS installation, or in some other format, |
+ // indicating an unknown installation [possibly IISpeed]. |
+ if (!value.empty()) { |
+ int bucket = GetXModPagespeedBucketFromVersion(value); |
+ if (bucket > 0) { |
+ // Bucket 2 counts occurences of the X-Page-Speed header with a |
+ // value in the X-Mod-Pagespeed version number format. We also |
+ // count these responses in the version histogram. |
+ UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, |
+ PAGESPEED_NGX_PAGESPEED_SERVER, |
+ PAGESPEED_SERVER_MAXIMUM); |
+ UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); |
+ } else if (IsPageSpeedServiceVersionNumber(value)) { |
+ // Bucket 3 counts occurences of the X-Page-Speed header with a |
+ // value in the PageSpeed Service version number format. |
+ UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, |
+ PAGESPEED_PAGESPEED_SERVICE_SERVER, |
+ PAGESPEED_SERVER_MAXIMUM); |
+ } else { |
+ // Bucket 4 counts occurences of all other values. |
+ UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, |
+ PAGESPEED_UNKNOWN_SERVER, |
+ PAGESPEED_SERVER_MAXIMUM); |
+ } |
+ } |
+ break; |
+ } |
+ } |
+} |
+ |
+} // namespace mod_pagespeed |