Enable easy creation of independent profiling metrics.

When using conditionally compiled metrics there was only one go_tag to rule them
all. That's kind of a shame because when profiling something specific it's
nicer to know that only your metrics that you care about are compiled in and
metrics that you don't care about aren't.

This CL makes it easy to create new profiling go_tags, by abstracting the
profiling metric init functions under two builder structs: RealMetricBuilder
and FakeMetricBuilder; these builder structs are the only things that need
to change between the metrics-ON or OFF versions of conditional metric files
(aside from the go_tag controlling conditional compilation of course).
Ideally having to create these files manually wouldn't be necessary at all,
and we could use a go_template build rule instead, but that doesn't support
replacing go:build tags AFAIK.

PiperOrigin-RevId: 571153131
This commit is contained in:
Konstantin Bogomolov
2023-10-05 15:56:37 -07:00
committed by gVisor bot
parent dcfe2d169e
commit 4120841184
14 changed files with 284 additions and 279 deletions
+3 -3
View File
@@ -8,12 +8,12 @@ package(
go_library(
name = "metric",
srcs = [
"condmetric_profiling.go",
"condmetric_profiling_fake.go",
"fake_metric.go",
"condmetric.go",
"metric.go",
"metric_unsafe.go",
"profiling_metric.go",
"sentry_profiling.go",
"sentry_profiling_fake.go",
],
visibility = ["//:sandbox"],
deps = [
+155
View File
@@ -0,0 +1,155 @@
// Copyright 2022 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.
package metric
import (
"fmt"
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
)
// FakeUint64Metric is a type that implements all the methods of a Uint64Metric
// as a no-op.
type FakeUint64Metric struct{}
// FakeDistributionMetric is a type that implements all the methods of a
// DistributionMetric as a no-op.
type FakeDistributionMetric struct{}
// FakeTimerMetric is a type that implements all the methods of a TimerMetric
// as a no-op.
type FakeTimerMetric struct{}
// FakeTimedOperation is a type that implements all the methods of a
// TimedOperation as a no-op.
type FakeTimedOperation struct{}
// Value from a FakeUint64Metric always returns a meaningless value.
//
//go:nosplit
func (m *FakeUint64Metric) Value(fieldValues ...*FieldValue) uint64 {
return 0
}
// Increment on a FakeUint64Metric does nothing.
//
//go:nosplit
func (m *FakeUint64Metric) Increment(fieldValues ...*FieldValue) {}
// IncrementBy on a FakeUint64Metric does nothing.
//
//go:nosplit
func (m *FakeUint64Metric) IncrementBy(v uint64, fieldValues ...*FieldValue) {}
// AddSample on a FakeUint64Metric does nothing.
//
//go:nosplit
func (d *FakeDistributionMetric) AddSample(sample int64, fields ...*FieldValue) {}
// Start on a FakeUint64Metric returns a FakeTimedOperation struct, which does
// nothing and does not keep the time.
//
//go:nosplit
func (t *FakeTimerMetric) Start(fields ...*FieldValue) FakeTimedOperation {
return FakeTimedOperation{}
}
// Finish on a FakeTimedOperation does nothing.
//
//go:nosplit
func (o FakeTimedOperation) Finish(extraFields ...*FieldValue) {}
// FakeMetricBuilder is a type used to produce conditionally compiled metrics.
// Methods of this struct produce fake, inactive metrics.
type FakeMetricBuilder struct{}
// NewUint64Metric creates a fake Uint64 metric.
func (b *FakeMetricBuilder) NewUint64Metric(name string, sync bool, units pb.MetricMetadata_Units, description string, fields ...Field) (*FakeUint64Metric, error) {
return &FakeUint64Metric{}, nil
}
// MustCreateNewUint64Metric creates a fake Uint64 metric.
func (b *FakeMetricBuilder) MustCreateNewUint64Metric(name string, sync bool, description string, fields ...Field) *FakeUint64Metric {
return &FakeUint64Metric{}
}
// NewDistributionMetric creates a fake distribution metric.
func (b *FakeMetricBuilder) NewDistributionMetric(name string, sync bool, bucketer Bucketer, unit pb.MetricMetadata_Units, description string, fields ...Field) (*FakeDistributionMetric, error) {
return &FakeDistributionMetric{}, nil
}
// MustCreateNewDistributionMetric creates a fake distribution metric.
func (b *FakeMetricBuilder) MustCreateNewDistributionMetric(name string, sync bool, bucketer Bucketer, unit pb.MetricMetadata_Units, description string, fields ...Field) *FakeDistributionMetric {
return &FakeDistributionMetric{}
}
// NewTimerMetric creates a fake timer metric.
func (b *FakeMetricBuilder) NewTimerMetric(name string, nanoBucketer Bucketer, description string, fields ...Field) (*FakeTimerMetric, error) {
return &FakeTimerMetric{}, nil
}
// MustCreateNewTimerMetric creates a fake timer metric.
func (b *FakeMetricBuilder) MustCreateNewTimerMetric(name string, nanoBucketer Bucketer, description string, fields ...Field) *FakeTimerMetric {
return &FakeTimerMetric{}
}
// RealMetricBuilder is a type used to produce conditionally compiled metrics.
// Methods of this struct produce real active metrics.
type RealMetricBuilder struct{}
// NewUint64Metric calls the generic metric.NewUint64Metric to produce a real
// Uint64 metric.
func (b *RealMetricBuilder) NewUint64Metric(name string, sync bool, units pb.MetricMetadata_Units, description string, fields ...Field) (*Uint64Metric, error) {
m, err := NewUint64Metric(name, sync, units, description, fields...)
if err != nil {
return m, err
}
definedProfilingMetrics = append(definedProfilingMetrics, m.name)
return m, err
}
// MustCreateNewUint64Metric creates a real Uint64 metric or panics if unable to
// do so.
func (b *RealMetricBuilder) MustCreateNewUint64Metric(name string, sync bool, description string, fields ...Field) *Uint64Metric {
m, err := b.NewUint64Metric(name, sync, pb.MetricMetadata_UNITS_NONE, description, fields...)
if err != nil {
panic(fmt.Sprintf("Unable to create metric %q: %s", name, err))
}
return m
}
// NewDistributionMetric calls the generic metric.NewDistributionMetric to
// produce a real distribution metric.
func (b *RealMetricBuilder) NewDistributionMetric(name string, sync bool, bucketer Bucketer, unit pb.MetricMetadata_Units, description string, fields ...Field) (*DistributionMetric, error) {
return NewDistributionMetric(name, sync, bucketer, unit, description, fields...)
}
// MustCreateNewDistributionMetric creates a real distribution metric or panics
// if unable to do so.
func (b *RealMetricBuilder) MustCreateNewDistributionMetric(name string, sync bool, bucketer Bucketer, unit pb.MetricMetadata_Units, description string, fields ...Field) *DistributionMetric {
return MustCreateNewDistributionMetric(name, sync, bucketer, unit, description, fields...)
}
// NewTimerMetric calls the generic metric.NewTimerMetric to produce a real timer
// metric.
func (b *RealMetricBuilder) NewTimerMetric(name string, nanoBucketer Bucketer, description string, fields ...Field) (*TimerMetric, error) {
return NewTimerMetric(name, nanoBucketer, description, fields...)
}
// MustCreateNewTimerMetric creates a real timer metric or panics if unable to
// do so.
func (b *RealMetricBuilder) MustCreateNewTimerMetric(name string, nanoBucketer Bucketer, description string, fields ...Field) *TimerMetric {
return MustCreateNewTimerMetric(name, nanoBucketer, description, fields...)
}
-87
View File
@@ -1,87 +0,0 @@
// Copyright 2022 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.
//go:build condmetric_profiling
// +build condmetric_profiling
package metric
import (
"fmt"
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
)
// This file defines conditional metrics that are meant to be used when profiling
// runsc during benchmark tests.
// ProfilingUint64Metric is a metric type that is registered and used only when
// the "condmetric_profiling" go tag is specified for go build.
//
// Otherwise it is exactly like a Uint64Metric.
type ProfilingUint64Metric = Uint64Metric
// ProfilingDistributionMetric is a metric type that is registered and used only
// when the "condmetric_profiling" go tag is specified for go build.
//
// Otherwise it is exactly like a DistributionMetric.
type ProfilingDistributionMetric = DistributionMetric
// ProfilingTimerMetric is a metric type that is registered and used only when
// the "condmetric_profiling" go tag is specified for go build.
//
// Otherwise it is exactly like a TimerMetric.
type ProfilingTimerMetric = TimerMetric
// NewProfilingUint64Metric is equivalent to NewUint64Metric except it creates a
// ProfilingUint64Metric
var NewProfilingUint64Metric = newProfilingUint64Metric
// MustCreateNewProfilingUint64Metric is equivalent to MustCreateNewUint64Metric
// except it creates a ProfilingUint64Metric.
var MustCreateNewProfilingUint64Metric = mustCreateNewProfilingUint64Metric
// NewProfilingDistributionMetric is equivalent to NewDistributionMetric except
// it creates a ProfilingDistributionMetric.
var NewProfilingDistributionMetric = NewDistributionMetric
// MustCreateNewProfilingDistributionMetric is equivalent to
// MustCreateNewDistributionMetric except it creates a
// ProfilingDistributionMetric.
var MustCreateNewProfilingDistributionMetric = MustCreateNewDistributionMetric
// NewProfilingTimerMetric is equivalent to NewTimerMetric except it creates a
// ProfilingTimerMetric.
var NewProfilingTimerMetric = NewTimerMetric
// MustCreateNewProfilingTimerMetric is equivalent to MustCreateNewTimerMetric
// except it creates a ProfilingTimerMetric.
var MustCreateNewProfilingTimerMetric = MustCreateNewTimerMetric
func newProfilingUint64Metric(name string, sync bool, units pb.MetricMetadata_Units, description string, fields ...Field) (*Uint64Metric, error) {
m, err := NewUint64Metric(name, sync, units, description, fields...)
if err != nil {
return m, err
}
definedProfilingMetrics = append(definedProfilingMetrics, m.name)
return m, err
}
func mustCreateNewProfilingUint64Metric(name string, sync bool, description string, fields ...Field) *Uint64Metric {
m, err := newProfilingUint64Metric(name, sync, pb.MetricMetadata_UNITS_NONE, description, fields...)
if err != nil {
panic(fmt.Sprintf("Unable to create metric %q: %s", name, err))
}
return m
}
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !condmetric_profiling
// +build !condmetric_profiling
//go:build !sentry_profiling
// +build !sentry_profiling
package metric
@@ -26,20 +26,20 @@ import (
func TestProfilingMetricsDisabled(t *testing.T) {
defer resetTest()
_, err := NewProfilingUint64Metric("counterM", false, pb.MetricMetadata_UNITS_NONE, "One uint64 metric")
_, err := SentryProfiling.NewUint64Metric("/counterM", false, pb.MetricMetadata_UNITS_NONE, "One uint64 metric")
if err != nil {
t.Fatalf("NewProfilingUint64Metric got err %v want nil", err)
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
bucketer := NewExponentialBucketer(3, 2, 0, 1)
_, err = NewProfilingDistributionMetric("distribM", false, bucketer, pb.MetricMetadata_UNITS_NANOSECONDS, "One distribution metric")
_, err = SentryProfiling.NewDistributionMetric("/distribM", false, bucketer, pb.MetricMetadata_UNITS_NANOSECONDS, "One distribution metric")
if err != nil {
t.Fatalf("NewProfilingDistributionMetric got err %v want nil", err)
t.Fatalf("NewDistributionMetric got err %v want nil", err)
}
_, err = NewProfilingTimerMetric("timerM", bucketer, "One timer metric")
_, err = SentryProfiling.NewTimerMetric("/timerM", bucketer, "One timer metric")
if err != nil {
t.Fatalf("NewProfilingTimerMetric got err %v want nil", err)
t.Fatalf("NewTimerMetric got err %v want nil", err)
}
if err := Initialize(); err != nil {
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build condmetric_profiling
// +build condmetric_profiling
//go:build sentry_profiling
// +build sentry_profiling
package metric
@@ -26,20 +26,20 @@ import (
func TestProfilingMetricsEnabled(t *testing.T) {
defer resetTest()
_, err := NewProfilingUint64Metric("counterM", false, pb.MetricMetadata_UNITS_NONE, "One uint64 metric")
_, err := SentryProfiling.NewUint64Metric("/counterM", false, pb.MetricMetadata_UNITS_NONE, "One uint64 metric")
if err != nil {
t.Fatalf("NewProfilingUint64Metric got err %v want nil", err)
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
bucketer := NewExponentialBucketer(3, 2, 0, 1)
_, err = NewProfilingDistributionMetric("distribM", false, bucketer, pb.MetricMetadata_UNITS_NANOSECONDS, "One distribution metric")
_, err = SentryProfiling.NewDistributionMetric("/distribM", false, bucketer, pb.MetricMetadata_UNITS_NANOSECONDS, "One distribution metric")
if err != nil {
t.Fatalf("NewProfilingDistributionMetric got err %v want nil", err)
t.Fatalf("NewDistributionMetric got err %v want nil", err)
}
_, err = NewProfilingTimerMetric("timerM", bucketer, "One timer metric")
_, err = SentryProfiling.NewTimerMetric("/timerM", bucketer, "One timer metric")
if err != nil {
t.Fatalf("NewProfilingTimerMetric got err %v want nil", err)
t.Fatalf("NewTimerMetric got err %v want nil", err)
}
if err := Initialize(); err != nil {
-61
View File
@@ -1,61 +0,0 @@
// Copyright 2022 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.
//go:build !condmetric_profiling
// +build !condmetric_profiling
package metric
// ProfilingUint64Metric is a metric type that is registered and used only when
// the "condmetric_profiling" go tag is specified when building runsc.
//
// Otherwise it is exactly like a Uint64Metric.
type ProfilingUint64Metric = FakeUint64Metric
// ProfilingDistributionMetric is a metric type that is registered and used only
// when the "condmetric_profiling" go tag is specified when building runsc.
//
// Otherwise it is exactly like a DistributionMetric.
type ProfilingDistributionMetric = FakeDistributionMetric
// ProfilingTimerMetric is a metric type that is registered and used only when
// the "condmetric_profiling" go tag is specified when building runsc.
//
// Otherwise it is exactly like a TimerMetric.
type ProfilingTimerMetric = FakeTimerMetric
// NewProfilingUint64Metric is equivalent to NewUint64Metric except it creates a
// ProfilingUint64Metric
var NewProfilingUint64Metric = NewFakeUint64Metric
// MustCreateNewProfilingUint64Metric is equivalent to MustCreateNewUint64Metric
// except it creates a ProfilingUint64Metric.
var MustCreateNewProfilingUint64Metric = MustCreateNewFakeUint64Metric
// NewProfilingDistributionMetric is equivalent to NewDistributionMetric except
// it creates a ProfilingDistributionMetric.
var NewProfilingDistributionMetric = NewFakeDistributionMetric
// MustCreateNewProfilingDistributionMetric is equivalent to
// MustCreateNewDistributionMetric except it creates a
// ProfilingDistributionMetric.
var MustCreateNewProfilingDistributionMetric = MustCreateNewFakeDistributionMetric
// NewProfilingTimerMetric is equivalent to NewTimerMetric except it creates a
// ProfilingTimerMetric.
var NewProfilingTimerMetric = NewFakeTimerMetric
// MustCreateNewProfilingTimerMetric is equivalent to MustCreateNewTimerMetric
// except it creates a ProfilingTimerMetric.
var MustCreateNewProfilingTimerMetric = MustCreateNewFakeTimerMetric
-104
View File
@@ -1,104 +0,0 @@
// Copyright 2022 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.
package metric
import pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
// FakeUint64Metric is a type that implements all the methods of a Uint64Metric
// as a no-op.
type FakeUint64Metric struct{}
// FakeDistributionMetric is a type that implements all the methods of a
// DistributionMetric as a no-op.
type FakeDistributionMetric struct{}
// FakeTimerMetric is a type that implements all the methods of a TimerMetric
// as a no-op.
type FakeTimerMetric struct{}
// FakeTimedOperation is a type that implements all the methods of a
// TimedOperation as a no-op.
type FakeTimedOperation struct{}
// Value from a FakeUint64Metric always returns a meaningless value.
//
//go:nosplit
func (m *FakeUint64Metric) Value(fieldValues ...*FieldValue) uint64 {
return 0
}
// Increment on a FakeUint64Metric does nothing.
//
//go:nosplit
func (m *FakeUint64Metric) Increment(fieldValues ...*FieldValue) {}
// IncrementBy on a FakeUint64Metric does nothing.
//
//go:nosplit
func (m *FakeUint64Metric) IncrementBy(v uint64, fieldValues ...*FieldValue) {}
// AddSample on a FakeUint64Metric does nothing.
//
//go:nosplit
func (d *FakeDistributionMetric) AddSample(sample int64, fields ...*FieldValue) {}
// Start on a FakeUint64Metric returns a FakeTimedOperation struct, which does
// nothing and does not keep the time.
//
//go:nosplit
func (t *FakeTimerMetric) Start(fields ...*FieldValue) FakeTimedOperation {
return FakeTimedOperation{}
}
// Finish on a FakeTimedOperation does nothing.
//
//go:nosplit
func (o FakeTimedOperation) Finish(extraFields ...*FieldValue) {}
// NewFakeUint64Metric is equivalent to NewUint64Metric except it creates a
// FakeUint64Metric
func NewFakeUint64Metric(name string, sync bool, units pb.MetricMetadata_Units, description string, fields ...Field) (*FakeUint64Metric, error) {
return &FakeUint64Metric{}, nil
}
// MustCreateNewFakeUint64Metric is equivalent to MustCreateNewUint64Metric
// except it creates a FakeUint64Metric.
func MustCreateNewFakeUint64Metric(name string, sync bool, description string, fields ...Field) *FakeUint64Metric {
return &FakeUint64Metric{}
}
// NewFakeDistributionMetric is equivalent to NewDistributionMetric except
// it creates a FakeDistributionMetric.
func NewFakeDistributionMetric(name string, sync bool, bucketer Bucketer, unit pb.MetricMetadata_Units, description string, fields ...Field) (*FakeDistributionMetric, error) {
return &FakeDistributionMetric{}, nil
}
// MustCreateNewFakeDistributionMetric is equivalent to
// MustCreateNewDistributionMetric except it creates a FakeDistributionMetric.
func MustCreateNewFakeDistributionMetric(name string, sync bool, bucketer Bucketer, unit pb.MetricMetadata_Units, description string, fields ...Field) *FakeDistributionMetric {
return &FakeDistributionMetric{}
}
// NewFakeTimerMetric is equivalent to NewTimerMetric except it creates a
// FakeTimerMetric.
func NewFakeTimerMetric(name string, nanoBucketer Bucketer, description string, fields ...Field) (*FakeTimerMetric, error) {
return &FakeTimerMetric{}, nil
}
// MustCreateNewFakeTimerMetric is equivalent to MustCreateNewTimerMetric
// except it creates a FakeTimerMetric.
func MustCreateNewFakeTimerMetric(name string, nanoBucketer Bucketer, description string, fields ...Field) *FakeTimerMetric {
return &FakeTimerMetric{}
}
+23
View File
@@ -0,0 +1,23 @@
// Copyright 2023 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.
//go:build sentry_profiling
// +build sentry_profiling
package metric
// SentryProfiling is a builder that produces conditionally compiled metrics.
// Metrics made from this are compiled and active at runtime when the
// "sentry_profiling" go-tag is specified at compilation.
var SentryProfiling = RealMetricBuilder{}
+23
View File
@@ -0,0 +1,23 @@
// Copyright 2023 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.
//go:build !sentry_profiling
// +build !sentry_profiling
package metric
// SentryProfiling is a builder that produces conditionally compiled metrics.
// Metrics made from this are compiled and active at runtime when the
// "sentry_profiling" go-tag is specified at compilation.
var SentryProfiling = FakeMetricBuilder{}
+2 -2
View File
@@ -610,12 +610,12 @@ type Task struct {
var (
// syscallCounter is a metric that tracks how many syscalls the sentry has
// executed.
syscallCounter = metric.MustCreateNewProfilingUint64Metric(
syscallCounter = metric.SentryProfiling.MustCreateNewUint64Metric(
"/task/syscalls", false, "The number of syscalls the sentry has executed for the user.")
// faultCounter is a metric that tracks how many faults the sentry has had to
// handle.
faultCounter = metric.MustCreateNewProfilingUint64Metric(
faultCounter = metric.SentryProfiling.MustCreateNewUint64Metric(
"/task/faults", false, "The number of faults the sentry has handled.")
)
+2
View File
@@ -46,6 +46,8 @@ go_library(
"kvm_const.go",
"kvm_const_amd64.go",
"kvm_const_arm64.go",
"kvm_profiling.go",
"kvm_profiling_fake.go",
"machine.go",
"machine_amd64.go",
"machine_amd64_unsafe.go",
+27
View File
@@ -0,0 +1,27 @@
// Copyright 2023 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.
//go:build kvm_profiling
// +build kvm_profiling
package kvm
import (
"gvisor.dev/gvisor/pkg/metric"
)
// KVMProfiling is a builder that produces conditionally compiled metrics.
// Metrics made from this are compiled and active at runtime when the
// "kvm_profiling" go-tag is specified at compilation.
var KVMProfiling = metric.RealMetricBuilder{}
@@ -0,0 +1,27 @@
// Copyright 2023 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.
//go:build !kvm_profiling
// +build !kvm_profiling
package kvm
import (
"gvisor.dev/gvisor/pkg/metric"
)
// KVMProfiling is a builder that produces conditionally compiled metrics.
// Metrics made from this are compiled and active at runtime when the
// "kvm_profiling" go-tag is specified at compilation.
var KVMProfiling = metric.FakeMetricBuilder{}
+6 -6
View File
@@ -114,32 +114,32 @@ var (
var (
// hostExitCounter is a metric that tracks how many times the sentry
// performed a host to guest world switch.
hostExitCounter = metric.MustCreateNewProfilingUint64Metric(
hostExitCounter = KVMProfiling.MustCreateNewUint64Metric(
"/kvm/host_exits", false, "The number of times the sentry performed a host to guest world switch.")
// userExitCounter is a metric that tracks how many times the sentry has
// had an exit from userspace. Analogous to vCPU.userExits.
userExitCounter = metric.MustCreateNewProfilingUint64Metric(
userExitCounter = KVMProfiling.MustCreateNewUint64Metric(
"/kvm/user_exits", false, "The number of times the sentry has had an exit from userspace.")
// interruptCounter is a metric that tracks how many times execution returned
// to the KVM host to handle a pending signal.
interruptCounter = metric.MustCreateNewProfilingUint64Metric(
interruptCounter = KVMProfiling.MustCreateNewUint64Metric(
"/kvm/interrupts", false, "The number of times the signal handler was invoked.")
// mmapCallCounter is a metric that tracks how many times the function
// seccompMmapSyscall has been called.
mmapCallCounter = metric.MustCreateNewProfilingUint64Metric(
mmapCallCounter = KVMProfiling.MustCreateNewUint64Metric(
"/kvm/mmap_calls", false, "The number of times seccompMmapSyscall has been called.")
// getVCPUCounter is a metric that tracks how many times different paths of
// machine.Get() are triggered.
getVCPUCounter = metric.MustCreateNewProfilingUint64Metric(
getVCPUCounter = KVMProfiling.MustCreateNewUint64Metric(
"/kvm/get_vcpu", false, "The number of times that machine.Get() was called, split by path the function took.",
metric.NewField("acquisition_type", &getVCPUAcquisitionFastReused, &getVCPUAcquisitionReused, &getVCPUAcquisitionUnused, &getVCPUAcquisitionStolen))
// asInvalidateDuration are durations of calling addressSpace.invalidate().
asInvalidateDuration = metric.MustCreateNewProfilingTimerMetric("/kvm/address_space_invalidate",
asInvalidateDuration = KVMProfiling.MustCreateNewTimerMetric("/kvm/address_space_invalidate",
metric.NewExponentialBucketer(15, uint64(time.Nanosecond*100), 1, 2),
"Duration of calling addressSpace.invalidate().")
)