summaryrefslogtreecommitdiffstats
path: root/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc
blob: 6ef2d29b84e029cf44d86900f41e2868d6e100f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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