Skip to content

Commit e003116

Browse files
authored
Reduce number of buckets for auto-generated metrics (#780)
For the auto-generated histogram metrics, we use a large number of buckets. The largest bucket captures values up to 50 quintillion. However, having a large number of buckets results in a significant size for exported metrics, even if they carry 0 data (as most buckets will have 0 values). This leads to: (1) higher costs for the user (e.g., Google Cloud monitoring charges you based on the volume of metrics exported), and (2) increased system load due to handling large metrics data. This PR reduces the number of buckets to capture values up to 5 billion (5e9), which seems reasonable in practice. E.g., auto-generated metrics using these buckets: 1) http_request_latency_micros - even if this is 10 minutes, the value is still 6e7 2) http_request_bytes_received - http request size of more than 5 GB seem rare 3) http_request_bytes_returned - http response size of more than 5 GB seem rare 4) serviceweaver_method_latency_micros - component method execution of more than 1.3 hours seem rare 5) serviceweaver_method_bytes_request - request size of more than 5 GB seem rare 6) serviceweaver_method_bytes_reply - response size of more than 5 GB seem rare
1 parent 3701bd6 commit e003116

File tree

7 files changed

+92
-35
lines changed

7 files changed

+92
-35
lines changed

godeps.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ github.com/ServiceWeaver/weaver
44
errors
55
fmt
66
github.com/ServiceWeaver/weaver/internal/control
7+
github.com/ServiceWeaver/weaver/internal/metrics
78
github.com/ServiceWeaver/weaver/internal/reflection
89
github.com/ServiceWeaver/weaver/internal/weaver
910
github.com/ServiceWeaver/weaver/metrics
@@ -315,8 +316,7 @@ github.com/ServiceWeaver/weaver/internal/heap
315316
container/heap
316317
github.com/ServiceWeaver/weaver/internal/metrics
317318
context
318-
github.com/ServiceWeaver/weaver/runtime/codegen
319-
github.com/ServiceWeaver/weaver/runtime/logging
319+
fmt
320320
github.com/ServiceWeaver/weaver/runtime/metrics
321321
strings
322322
sync
@@ -386,8 +386,8 @@ github.com/ServiceWeaver/weaver/internal/status
386386
flag
387387
fmt
388388
github.com/ServiceWeaver/weaver/internal/files
389+
github.com/ServiceWeaver/weaver/internal/metrics
389390
github.com/ServiceWeaver/weaver/internal/traceio
390-
github.com/ServiceWeaver/weaver/runtime/codegen
391391
github.com/ServiceWeaver/weaver/runtime/colors
392392
github.com/ServiceWeaver/weaver/runtime/logging
393393
github.com/ServiceWeaver/weaver/runtime/metrics
@@ -742,6 +742,7 @@ github.com/ServiceWeaver/weaver/runtime/codegen
742742
errors
743743
fmt
744744
github.com/ServiceWeaver/weaver/internal/config
745+
github.com/ServiceWeaver/weaver/internal/metrics
745746
github.com/ServiceWeaver/weaver/metrics
746747
github.com/ServiceWeaver/weaver/runtime
747748
github.com/ServiceWeaver/weaver/runtime/protos
@@ -875,6 +876,7 @@ github.com/ServiceWeaver/weaver/runtime/protomsg
875876
encoding/binary
876877
errors
877878
fmt
879+
github.com/ServiceWeaver/weaver/internal/metrics
878880
github.com/ServiceWeaver/weaver/metrics
879881
github.com/ServiceWeaver/weaver/runtime/codegen
880882
google.golang.org/protobuf/proto

http.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"sync/atomic"
2222
"time"
2323

24+
imetrics "github.com/ServiceWeaver/weaver/internal/metrics"
2425
"github.com/ServiceWeaver/weaver/metrics"
2526
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
2627
)
@@ -58,17 +59,17 @@ var (
5859
httpRequestLatencyMicros = metrics.NewHistogramMap[httpLabels](
5960
"serviceweaver_http_request_latency_micros",
6061
"Duration, in microseconds, of HTTP request execution",
61-
metrics.NonNegativeBuckets,
62+
imetrics.GeneratedBuckets,
6263
)
6364
httpRequestBytesReceived = metrics.NewHistogramMap[httpLabels](
6465
"serviceweaver_http_request_bytes_received",
6566
"Number of bytes received by HTTP request handlers",
66-
metrics.NonNegativeBuckets,
67+
imetrics.GeneratedBuckets,
6768
)
6869
httpRequestBytesReturned = metrics.NewHistogramMap[httpLabels](
6970
"serviceweaver_http_request_bytes_returned",
7071
"Number of bytes returned by HTTP request handlers",
71-
metrics.NonNegativeBuckets,
72+
imetrics.GeneratedBuckets,
7273
)
7374
)
7475

internal/metrics/generated.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package metrics
16+
17+
// Names of automatically populated metrics.
18+
const (
19+
MethodCountsName = "serviceweaver_method_count"
20+
MethodErrorsName = "serviceweaver_method_error_count"
21+
MethodLatenciesName = "serviceweaver_method_latency_micros"
22+
MethodBytesRequestName = "serviceweaver_method_bytes_request"
23+
MethodBytesReplyName = "serviceweaver_method_bytes_reply"
24+
)
25+
26+
// GeneratedBuckets provides rounded bucket boundaries for histograms
27+
// that will only store non-negative values.
28+
//
29+
// Note that these buckets are intended to be used only by the metrics generated
30+
// by the weaver runtime.
31+
var GeneratedBuckets = []float64{
32+
// Adjacent buckets differ from each other by 2x or 2.5x.
33+
1, 2, 5,
34+
10, 20, 50,
35+
100, 200, 500,
36+
1000, 2000, 5000,
37+
10000, 20000, 50000,
38+
100000, 200000, 500000,
39+
1000000, 2000000, 5000000,
40+
10000000, 20000000, 50000000,
41+
100000000, 200000000, 500000000,
42+
1000000000, 2000000000, 5000000000, // i.e., 5e9
43+
}

internal/metrics/stats.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@ package metrics
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"strings"
2021
"sync"
2122
"time"
2223

23-
"github.com/ServiceWeaver/weaver/runtime/codegen"
24-
"github.com/ServiceWeaver/weaver/runtime/logging"
2524
"github.com/ServiceWeaver/weaver/runtime/metrics"
2625
)
2726

@@ -154,7 +153,7 @@ func (s *StatsProcessor) getSnapshot(snapshot []*metrics.MetricSnapshot) {
154153
var comp, method string
155154
for k, v := range m.Labels {
156155
if k == "component" {
157-
comp = logging.ShortenComponent(v)
156+
comp = shortenComponent(v)
158157
} else if k == "method" {
159158
method = v
160159
}
@@ -176,13 +175,13 @@ func (s *StatsProcessor) getSnapshot(snapshot []*metrics.MetricSnapshot) {
176175
// Aggregate stats within a bucket, based on metric values from different
177176
// replicas for the method.
178177
switch m.Name {
179-
case codegen.MethodCountsName:
178+
case MethodCountsName:
180179
bucket.calls += m.Value
181-
case codegen.MethodBytesReplyName:
180+
case MethodBytesReplyName:
182181
bucket.kbSent += m.Value / 1024 // B to KB
183-
case codegen.MethodBytesRequestName:
182+
case MethodBytesRequestName:
184183
bucket.kbRecvd += m.Value / 1024 // B to KB
185-
case codegen.MethodLatenciesName:
184+
case MethodLatenciesName:
186185
bucket.latencyMs += m.Value / 1000 // µs to ms
187186

188187
var count uint64
@@ -293,3 +292,22 @@ func (s *statsMethod) computeStatsStatusz(startTime time.Time) methodStatuszInfo
293292
}
294293
return result
295294
}
295+
296+
// shortenComponent shortens the given component name to be of the format
297+
// <pkg>.<IfaceType>. (Recall that the full component name is of the format
298+
// <path1>/<path2>/.../<pathN>/<IfaceType>.)
299+
//
300+
// TODO(rgrandl): To avoid cyclic dependencies, we have created a local copy of the
301+
// logging.ShortenComponent method. Consider moving logging.ShortenComponent to a
302+
// different package instead.
303+
func shortenComponent(component string) string {
304+
parts := strings.Split(component, "/")
305+
switch len(parts) {
306+
case 0: // should never happen
307+
return "nil"
308+
case 1:
309+
return parts[0]
310+
default:
311+
return fmt.Sprintf("%s.%s", parts[len(parts)-2], parts[len(parts)-1])
312+
}
313+
}

internal/status/dashboard.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import (
2828
"strings"
2929
"time"
3030

31+
metrics2 "github.com/ServiceWeaver/weaver/internal/metrics"
3132
"github.com/ServiceWeaver/weaver/internal/traceio"
32-
"github.com/ServiceWeaver/weaver/runtime/codegen"
3333
"github.com/ServiceWeaver/weaver/runtime/logging"
3434
"github.com/ServiceWeaver/weaver/runtime/metrics"
3535
"github.com/ServiceWeaver/weaver/runtime/perfetto"
@@ -267,7 +267,7 @@ func computeTraffic(status *Status, metrics []*protos.MetricSnapshot) []edge {
267267
}
268268
byPair := map[pair]int{}
269269
for _, metric := range metrics {
270-
if metric.Name != codegen.MethodCountsName {
270+
if metric.Name != metrics2.MethodCountsName {
271271
continue
272272
}
273273
call := pair{

runtime/codegen/metrics.go

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,34 @@ package codegen
1717
import (
1818
"time"
1919

20+
imetrics "github.com/ServiceWeaver/weaver/internal/metrics"
2021
"github.com/ServiceWeaver/weaver/metrics"
2122
)
2223

23-
// Names of automatically populated metrics.
24-
const (
25-
MethodCountsName = "serviceweaver_method_count"
26-
MethodErrorsName = "serviceweaver_method_error_count"
27-
MethodLatenciesName = "serviceweaver_method_latency_micros"
28-
MethodBytesRequestName = "serviceweaver_method_bytes_request"
29-
MethodBytesReplyName = "serviceweaver_method_bytes_reply"
30-
)
31-
3224
var (
3325
// The following metrics are automatically populated for the user.
3426
methodCounts = metrics.NewCounterMap[MethodLabels](
35-
MethodCountsName,
27+
imetrics.MethodCountsName,
3628
"Count of Service Weaver component method invocations",
3729
)
3830
methodErrors = metrics.NewCounterMap[MethodLabels](
39-
MethodErrorsName,
31+
imetrics.MethodErrorsName,
4032
"Count of Service Weaver component method invocations that result in an error",
4133
)
4234
methodLatencies = metrics.NewHistogramMap[MethodLabels](
43-
MethodLatenciesName,
35+
imetrics.MethodLatenciesName,
4436
"Duration, in microseconds, of Service Weaver component method execution",
45-
metrics.NonNegativeBuckets,
37+
imetrics.GeneratedBuckets,
4638
)
4739
methodBytesRequest = metrics.NewHistogramMap[MethodLabels](
48-
MethodBytesRequestName,
40+
imetrics.MethodBytesRequestName,
4941
"Number of bytes in Service Weaver component method requests",
50-
metrics.NonNegativeBuckets,
42+
imetrics.GeneratedBuckets,
5143
)
5244
methodBytesReply = metrics.NewHistogramMap[MethodLabels](
53-
MethodBytesReplyName,
45+
imetrics.MethodBytesReplyName,
5446
"Number of bytes in Service Weaver component method replies",
55-
metrics.NonNegativeBuckets,
47+
imetrics.GeneratedBuckets,
5648
)
5749
)
5850

runtime/protomsg/handler.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"runtime/debug"
2525
"time"
2626

27+
imetrics "github.com/ServiceWeaver/weaver/internal/metrics"
2728
"github.com/ServiceWeaver/weaver/metrics"
2829
"google.golang.org/protobuf/proto"
2930
)
@@ -40,17 +41,17 @@ var (
4041
httpRequestLatencyMicros = metrics.NewHistogramMap[handlerLabels](
4142
"serviceweaver_system_http_request_latency_micros",
4243
"Duration, in microseconds, of Service Weaver HTTP request execution",
43-
metrics.NonNegativeBuckets,
44+
imetrics.GeneratedBuckets,
4445
)
4546
httpRequestBytesReceived = metrics.NewHistogramMap[handlerLabels](
4647
"serviceweaver_system_http_request_bytes_received",
4748
"Number of bytes received by Service Weaver HTTP request handlers",
48-
metrics.NonNegativeBuckets,
49+
imetrics.GeneratedBuckets,
4950
)
5051
httpRequestBytesReturned = metrics.NewHistogramMap[handlerLabels](
5152
"serviceweaver_system_http_request_bytes_returned",
5253
"Number of bytes returned by Service Weaver HTTP request handlers",
53-
metrics.NonNegativeBuckets,
54+
imetrics.GeneratedBuckets,
5455
)
5556
)
5657

0 commit comments

Comments
 (0)