From 7de3c5af4a2e355088d2320bf19c4c72ac00fcd0 Mon Sep 17 00:00:00 2001 From: Etienne Perot Date: Mon, 10 Oct 2022 17:18:26 -0700 Subject: [PATCH] Add small tool to print distribution metric bucket sizes conveniently. Useful to search for decent bucket sizes interactively. PiperOrigin-RevId: 480214658 --- pkg/metric/buckettool/BUILD | 13 ++++++ pkg/metric/buckettool/buckettool.go | 68 +++++++++++++++++++++++++++++ runsc/flag/flag.go | 3 ++ 3 files changed, 84 insertions(+) create mode 100644 pkg/metric/buckettool/BUILD create mode 100644 pkg/metric/buckettool/buckettool.go diff --git a/pkg/metric/buckettool/BUILD b/pkg/metric/buckettool/BUILD new file mode 100644 index 000000000..b51016805 --- /dev/null +++ b/pkg/metric/buckettool/BUILD @@ -0,0 +1,13 @@ +load("//tools:defs.bzl", "go_binary") + +package(licenses = ["notice"]) + +go_binary( + name = "buckettool", + srcs = ["buckettool.go"], + deps = [ + "//pkg/log", + "//pkg/metric", + "//runsc/flag", + ], +) diff --git a/pkg/metric/buckettool/buckettool.go b/pkg/metric/buckettool/buckettool.go new file mode 100644 index 000000000..348ba5674 --- /dev/null +++ b/pkg/metric/buckettool/buckettool.go @@ -0,0 +1,68 @@ +// Copyright 2019 The gVisor 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. + +// buckettool prints buckets for distribution metrics. +package main + +import ( + "fmt" + "os" + "time" + + "gvisor.dev/gvisor/pkg/log" + "gvisor.dev/gvisor/pkg/metric" + "gvisor.dev/gvisor/runsc/flag" +) + +var ( + typeFlag = flag.String("type", "duration", "Type of the bucketer: 'duration' or 'exponential'") + numFiniteBucketsFlag = flag.Int("num_finite_buckets", 8, "Number of finite buckets") + minDurationFlag = flag.Duration("min_duration", 5*time.Millisecond, "For -type=duration: Minimum duration") + maxDurationFlag = flag.Duration("max_duration", 10*time.Minute, "For -type=duration: Maximum duration") + widthFlag = flag.Uint64("exponential_width", 5, "For -type=exponential: Initial bucket width") + scaleFlag = flag.Float64("exponential_scale", 10, "For -type=exponential: Scaling factor") + growthFlag = flag.Float64("exponential_growth", 4, "For -type=exponential: Exponential growth factor") +) + +func exitf(format string, values ...any) { + log.Warningf(format, values...) + os.Exit(1) +} + +func main() { + flag.Parse() + var bucketer metric.Bucketer + var formatVal func(int64) string + switch *typeFlag { + case "duration": + bucketer = metric.NewDurationBucketer(*numFiniteBucketsFlag, *minDurationFlag, *maxDurationFlag) + formatVal = func(val int64) string { + return time.Duration(val).String() + } + case "exponential": + bucketer = metric.NewExponentialBucketer(*numFiniteBucketsFlag, *widthFlag, *scaleFlag, *growthFlag) + formatVal = func(val int64) string { + return fmt.Sprintf("%v", val) + } + default: + exitf("Invalid -type: %s", *typeFlag) + } + fmt.Printf("Number of finite buckets: %d\n", bucketer.NumFiniteBuckets()) + fmt.Printf("Number of total buckets: %d\n", bucketer.NumFiniteBuckets()+2) + fmt.Printf("> Underflow bucket: (-inf; %s)\n", formatVal(bucketer.LowerBound(0))) + for b := 0; b < bucketer.NumFiniteBuckets(); b++ { + fmt.Printf("> Bucket index %d: [%s, %s). (Middle: %s)\n", b, formatVal(bucketer.LowerBound(b)), formatVal(bucketer.LowerBound(b+1)), formatVal((bucketer.LowerBound(b)+bucketer.LowerBound(b+1))/2)) + } + fmt.Printf("> Overflow bucket: [%s; +inf)\n", formatVal(bucketer.LowerBound(bucketer.NumFiniteBuckets()))) +} diff --git a/runsc/flag/flag.go b/runsc/flag/flag.go index 1c4df5b98..20d1984d1 100644 --- a/runsc/flag/flag.go +++ b/runsc/flag/flag.go @@ -29,6 +29,8 @@ type FlagSet = flag.FlagSet var ( Bool = flag.Bool CommandLine = flag.CommandLine + Duration = flag.Duration + Float64 = flag.Float64 Int = flag.Int Int64 = flag.Int64 NewFlagSet = flag.NewFlagSet @@ -36,6 +38,7 @@ var ( String = flag.String StringVar = flag.StringVar Uint = flag.Uint + Uint64 = flag.Uint64 Var = flag.Var )