Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / mod_pagespeed / mod_pagespeed_metrics.cc
blob6ef2d29b84e029cf44d86900f41e2868d6e100f4
1 // Copyright 2015 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 "chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h"
7 #include <stdio.h>
9 #include <string>
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "net/http/http_response_headers.h"
14 #include "url/gurl.h"
16 namespace mod_pagespeed {
18 namespace {
20 const char kModPagespeedHeader[] = "X-Mod-Pagespeed";
21 const char kPageSpeedHeader[] = "X-Page-Speed";
23 // For historical reasons, mod_pagespeed usage metrics are named with a
24 // prerender prefix.
25 const char kPagespeedServerHistogram[] =
26 "Prerender.PagespeedHeader.ServerCounts";
27 const char kPagespeedVersionHistogram[] =
28 "Prerender.PagespeedHeader.VersionCounts";
30 enum PagespeedHeaderServerType {
31 PAGESPEED_TOTAL_RESPONSES = 0,
32 PAGESPEED_MOD_PAGESPEED_SERVER = 1,
33 PAGESPEED_NGX_PAGESPEED_SERVER = 2,
34 PAGESPEED_PAGESPEED_SERVICE_SERVER = 3,
35 PAGESPEED_UNKNOWN_SERVER = 4,
36 PAGESPEED_SERVER_MAXIMUM = 5
39 // Parse the PageSpeed version number and encodes it in buckets 2 through 99: if
40 // it is in the format MAJOR.MINOR.BRANCH.POINT-COMMIT the bucket will be 2 + 2
41 // * (max(BRANCH, 10) - 10) + (POINT > 1 ? 1 : 0); otherwise the bucket is
42 // zero.
43 int GetXModPagespeedBucketFromVersion(const std::string& version) {
44 int unused_major, unused_minor, branch, point, unused_commit;
45 int num_parsed = sscanf(version.c_str(), "%d.%d.%d.%d-%d", &unused_major,
46 &unused_minor, &branch, &point, &unused_commit);
47 int output = 0;
48 if (num_parsed == 5) {
49 output = 2;
50 if (branch > 10)
51 output += 2 * (branch - 10);
52 if (point > 1)
53 output++;
54 if (output < 2 || output > 99)
55 output = 0;
57 return output;
60 // Parse the X-Page-Speed header value and determine whether it is in the
61 // PageSpeed Service format, namely MAJOR_MINOR_AB were MAJOR_MINOR is a version
62 // number and AB is an encoded 2-character value.
63 bool IsPageSpeedServiceVersionNumber(const std::string& version) {
64 int major, minor;
65 // is_eol is to detect EOL as we check that it /isn't/ converted.
66 char a, b, is_eol;
67 int num_parsed =
68 sscanf(version.c_str(), "%d_%d_%c%c%c", &major, &minor, &a, &b, &is_eol);
69 return (num_parsed == 4);
72 } // namespace
74 void RecordMetrics(const content::ResourceType resource_type,
75 const GURL& request_url,
76 const net::HttpResponseHeaders* response_headers) {
77 if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME ||
78 !request_url.SchemeIsHTTPOrHTTPS()) {
79 return;
82 // Bucket 0 counts every response seen.
83 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram,
84 PAGESPEED_TOTAL_RESPONSES,
85 PAGESPEED_SERVER_MAXIMUM);
86 if (!response_headers)
87 return;
89 void* iter = nullptr;
90 std::string name;
91 std::string value;
92 while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) {
93 if (name == kModPagespeedHeader) {
94 // Bucket 1 counts occurrences of the X-Mod-Pagespeed header.
95 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram,
96 PAGESPEED_MOD_PAGESPEED_SERVER,
97 PAGESPEED_SERVER_MAXIMUM);
98 if (!value.empty()) {
99 // If the header value is in the X-Mod-Pagespeed version number format
100 // then increment the appropriate bucket, otherwise increment bucket 1,
101 // which is the catch-all "unknown version number" bucket.
102 int bucket = GetXModPagespeedBucketFromVersion(value);
103 if (bucket > 0) {
104 UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket);
105 } else {
106 UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, 1);
109 break;
110 } else if (name == kPageSpeedHeader) {
111 // X-Page-Speed header versions are either in the X-Mod-Pagespeed format,
112 // indicating an nginx installation, or they're in the PageSpeed Service
113 // format, indicating a PSS installation, or in some other format,
114 // indicating an unknown installation [possibly IISpeed].
115 if (!value.empty()) {
116 int bucket = GetXModPagespeedBucketFromVersion(value);
117 if (bucket > 0) {
118 // Bucket 2 counts occurences of the X-Page-Speed header with a
119 // value in the X-Mod-Pagespeed version number format. We also
120 // count these responses in the version histogram.
121 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram,
122 PAGESPEED_NGX_PAGESPEED_SERVER,
123 PAGESPEED_SERVER_MAXIMUM);
124 UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket);
125 } else if (IsPageSpeedServiceVersionNumber(value)) {
126 // Bucket 3 counts occurences of the X-Page-Speed header with a
127 // value in the PageSpeed Service version number format.
128 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram,
129 PAGESPEED_PAGESPEED_SERVICE_SERVER,
130 PAGESPEED_SERVER_MAXIMUM);
131 } else {
132 // Bucket 4 counts occurences of all other values.
133 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram,
134 PAGESPEED_UNKNOWN_SERVER,
135 PAGESPEED_SERVER_MAXIMUM);
138 break;
143 } // namespace mod_pagespeed