mirrored from https://chromium.googlesource.com/infra/luci/luci-go
/
standard_metrics.go
145 lines (129 loc) · 5.42 KB
/
standard_metrics.go
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
144
145
// Copyright 2016 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package metric
import (
"context"
"strings"
"time"
"go.chromium.org/luci/common/tsmon"
"go.chromium.org/luci/common/tsmon/distribution"
"go.chromium.org/luci/common/tsmon/field"
"go.chromium.org/luci/common/tsmon/types"
)
// Metrics common to all tasks and devices.
var (
presenceMetric = NewBool(
"presence/up",
"Set to True when the program is running, missing otherwise.",
nil)
)
// Standard metrics for all requests to remote endpoints. These
// metrics should be consistent across all tsmon implementations,
// Python or Go.
var (
requestBytesMetric = NewCumulativeDistribution(
"http/request_bytes",
"Bytes sent per http request (body only).",
&types.MetricMetadata{Units: types.Bytes},
distribution.DefaultBucketer,
field.String("name"), // Usually the requested service name
field.String("client")) // http client used, e.g. urlfetch
responseBytesMetric = NewCumulativeDistribution(
"http/response_bytes",
"Bytes received per http request (content only).",
&types.MetricMetadata{Units: types.Bytes},
distribution.DefaultBucketer,
field.String("name"), // Usually the requested service name
field.String("client")) // http client used, e.g. urlfetch
requestDurationsMetric = NewCumulativeDistribution(
"http/durations",
"Time elapsed between sending a request and getting a response (including parsing) in milliseconds.",
&types.MetricMetadata{Units: types.Milliseconds},
distribution.DefaultBucketer,
field.String("name"), // Usually the requested service name
field.String("client")) // http client used, e.g. urlfetch
responseStatusMetric = NewCounter(
"http/response_status",
"Number of responses received by HTTP status code.",
nil,
field.Int("status"), // HTTP status code
field.String("name"), // Usually the requested service name
field.String("client")) // http client used, e.g. urlfetch
)
// Standard metrics for server-side request handlers. These metrics
// should be consistent across all tsmon implementations, Python or
// Go.
var (
serverRequestBytesMetric = NewCumulativeDistribution(
"http/server_request_bytes",
"Bytes received per http request (body only).",
&types.MetricMetadata{Units: types.Bytes},
distribution.DefaultBucketer,
field.Int("status"), // HTTP status code
field.String("name"), // URL template
field.Bool("is_robot")) // If request is made by a bot
serverResponseBytesMetric = NewCumulativeDistribution(
"http/server_response_bytes",
"Bytes sent per http request (body only).",
&types.MetricMetadata{Units: types.Bytes},
distribution.DefaultBucketer,
field.Int("status"), // HTTP status code
field.String("name"), // URL template
field.Bool("is_robot")) // If request is made by a bot
serverDurationsMetric = NewCumulativeDistribution(
"http/server_durations",
"Time elapsed between receiving a request and sending a response (including parsing) in milliseconds.",
&types.MetricMetadata{Units: types.Milliseconds},
distribution.DefaultBucketer,
field.Int("status"), // HTTP status code
field.String("name"), // URL template
field.Bool("is_robot")) // If request is made by a bot
serverResponseStatusMetric = NewCounter(
"http/server_response_status",
"Number of responses sent by HTTP status code.",
nil,
field.Int("status"), // HTTP status code
field.String("name"), // URL template
field.Bool("is_robot")) // If request is made by a bot
)
func init() {
registerCallbacks(context.Background())
}
func registerCallbacks(ctx context.Context) {
tsmon.RegisterCallbackIn(ctx, func(ctx context.Context) {
presenceMetric.Set(ctx, true)
})
}
// UpdateHTTPMetrics updates the metrics for a request to a remote server.
func UpdateHTTPMetrics(ctx context.Context, name string, client string,
code int, duration time.Duration, requestBytes int64, responseBytes int64) {
requestBytesMetric.Add(ctx, float64(requestBytes), name, client)
responseBytesMetric.Add(ctx, float64(responseBytes), name, client)
requestDurationsMetric.Add(ctx, float64(int64(duration)/int64(time.Millisecond)), name, client)
responseStatusMetric.Add(ctx, 1, code, name, client)
}
// UpdateServerMetrics updates the metrics for a handled request.
func UpdateServerMetrics(ctx context.Context, name string, code int,
duration time.Duration, requestBytes int64, responseBytes int64,
userAgent string) {
isRobot := (strings.Contains(userAgent, "GoogleBot") ||
strings.Contains(userAgent, "GoogleSecurityScanner") ||
strings.HasPrefix(userAgent, "kube-probe/") ||
strings.HasPrefix(userAgent, "GoogleHC/") ||
userAgent == "B3M/prober")
serverDurationsMetric.Add(ctx, float64(int64(duration)/int64(time.Millisecond)), code, name, isRobot)
serverResponseStatusMetric.Add(ctx, 1, code, name, isRobot)
serverRequestBytesMetric.Add(ctx, float64(requestBytes), code, name, isRobot)
serverResponseBytesMetric.Add(ctx, float64(responseBytes), code, name, isRobot)
}