Chromium Code Reviews| Index: chrome/browser/mod_pagespeed_metrics.cc |
| diff --git a/chrome/browser/mod_pagespeed_metrics.cc b/chrome/browser/mod_pagespeed_metrics.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..443f7b2910f51e196f8e8259fb8f8bb363cf07a4 |
| --- /dev/null |
| +++ b/chrome/browser/mod_pagespeed_metrics.cc |
| @@ -0,0 +1,137 @@ |
| +// 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_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 { |
| + |
| +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 a.b.c.d-e the bucket will be 2 + 2 * (max(c, 10) - |
| +// 10) + (d > 1 ? 1 : 0); otherwise the bucket is zero. |
| +int GetXModPagespeedBucketFromVersion(const std::string& version) { |
| + int a, b, c, d, e; |
|
sky
2015/03/31 23:51:55
I realize you're just moving code, but since you'r
davidben
2015/04/08 21:07:46
Done.
|
| + int num_parsed = |
| + sscanf(version.c_str(), "%d.%d.%d.%d-%d", &a, &b, &c, &d, &e); |
| + int output = 0; |
| + if (num_parsed == 5) { |
| + output = 2; |
| + if (c > 10) |
| + output += 2 * (c - 10); |
| + if (d > 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 m_n_dc were m_n is a version number and dc |
| +// is an encoded 2-character value. |
| +bool IsPageSpeedServiceVersionNumber(const std::string& version) { |
| + int a, b; |
| + char c, d, e; // e is to detect EOL as we check that it /isn't/ converted. |
| + int num_parsed = sscanf(version.c_str(), "%d_%d_%c%c%c", &a, &b, &c, &d, &e); |
| + return (num_parsed == 4); |
| +} |
| + |
| +} // namespace |
| + |
| +void RecordModPagespeedMetrics( |
| + 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 = NULL; |
|
sky
2015/03/31 23:51:55
nullptr
davidben
2015/04/08 21:07:45
Done.
|
| + 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; |
| + } |
| + } |
| +} |