mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Introduce conditionally-compiled metrics.
This change introduces metrics which are disabled at compile time by default, but can be enabled using a specified go tag. To demonstrate this, it replaces the metrics used to profile the KVM platform to these new ones. These profiling metrics can be enabled with the "condmetric_profiling" tag when building runsc. The motivation behind this is twofold: - We have observed that using metrics in hot-paths can be quite expensive (i.e. syscall counter, timer metrics on KVM platform machine.Get()). - There are classes of metrics that we generally care about using only on specific occasions, and don't need to have on by default. PiperOrigin-RevId: 464636315
This commit is contained in:
committed by
gVisor bot
parent
991841786a
commit
8d3ad7f293
+22
-1
@@ -5,6 +5,9 @@ package(licenses = ["notice"])
|
||||
go_library(
|
||||
name = "metric",
|
||||
srcs = [
|
||||
"condmetric_profiling.go",
|
||||
"condmetric_profiling_fake.go",
|
||||
"fake_metric.go",
|
||||
"metric.go",
|
||||
"metric_unsafe.go",
|
||||
],
|
||||
@@ -31,7 +34,10 @@ proto_library(
|
||||
|
||||
go_test(
|
||||
name = "metric_test",
|
||||
srcs = ["metric_test.go"],
|
||||
srcs = [
|
||||
"metric_test.go",
|
||||
"utils_test.go",
|
||||
],
|
||||
library = ":metric",
|
||||
deps = [
|
||||
":metric_go_proto",
|
||||
@@ -40,3 +46,18 @@ go_test(
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "condmetric_test",
|
||||
srcs = [
|
||||
"condmetric_profiling_disabled_test.go",
|
||||
"condmetric_profiling_enabled_test.go",
|
||||
"utils_test.go",
|
||||
],
|
||||
library = ":metric",
|
||||
deps = [
|
||||
":metric_go_proto",
|
||||
"//pkg/eventchannel",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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
|
||||
|
||||
// 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 = NewUint64Metric
|
||||
|
||||
// MustCreateNewProfilingUint64Metric is equivalent to MustCreateNewUint64Metric
|
||||
// except it creates a ProfilingUint64Metric.
|
||||
var MustCreateNewProfilingUint64Metric = MustCreateNewUint64Metric
|
||||
|
||||
// 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
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
|
||||
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
|
||||
)
|
||||
|
||||
func TestProfilingMetricsDisabled(t *testing.T) {
|
||||
defer resetTest()
|
||||
|
||||
_, err := NewProfilingUint64Metric("counterM", false, pb.MetricMetadata_UNITS_NONE, "One uint64 metric")
|
||||
if err != nil {
|
||||
t.Fatalf("NewProfilingUint64Metric got err %v want nil", err)
|
||||
}
|
||||
|
||||
bucketer := NewExponentialBucketer(3, 2, 0, 1)
|
||||
_, err = NewProfilingDistributionMetric("distribM", false, bucketer, pb.MetricMetadata_UNITS_NANOSECONDS, "One distribution metric")
|
||||
if err != nil {
|
||||
t.Fatalf("NewProfilingDistributionMetric got err %v want nil", err)
|
||||
}
|
||||
|
||||
_, err = NewProfilingTimerMetric("timerM", bucketer, "One timer metric")
|
||||
if err != nil {
|
||||
t.Fatalf("NewProfilingTimerMetric got err %v want nil", err)
|
||||
}
|
||||
|
||||
if err := Initialize(); err != nil {
|
||||
t.Fatalf("Initialize(): %s", err)
|
||||
}
|
||||
|
||||
if len(emitter) != 1 {
|
||||
t.Fatalf("Initialize emitted %d events want 1", len(emitter))
|
||||
}
|
||||
|
||||
mr, ok := emitter[0].(*pb.MetricRegistration)
|
||||
if !ok {
|
||||
t.Fatalf("emitter %v got %T want pb.MetricRegistration", emitter[0], emitter[0])
|
||||
}
|
||||
|
||||
if len(mr.Metrics) != 0 {
|
||||
t.Errorf("MetricRegistration got %d metrics want %d", len(mr.Metrics), 0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
|
||||
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
|
||||
)
|
||||
|
||||
func TestProfilingMetricsEnabled(t *testing.T) {
|
||||
defer resetTest()
|
||||
|
||||
_, err := NewProfilingUint64Metric("counterM", false, pb.MetricMetadata_UNITS_NONE, "One uint64 metric")
|
||||
if err != nil {
|
||||
t.Fatalf("NewProfilingUint64Metric got err %v want nil", err)
|
||||
}
|
||||
|
||||
bucketer := NewExponentialBucketer(3, 2, 0, 1)
|
||||
_, err = NewProfilingDistributionMetric("distribM", false, bucketer, pb.MetricMetadata_UNITS_NANOSECONDS, "One distribution metric")
|
||||
if err != nil {
|
||||
t.Fatalf("NewProfilingDistributionMetric got err %v want nil", err)
|
||||
}
|
||||
|
||||
_, err = NewProfilingTimerMetric("timerM", bucketer, "One timer metric")
|
||||
if err != nil {
|
||||
t.Fatalf("NewProfilingTimerMetric got err %v want nil", err)
|
||||
}
|
||||
|
||||
if err := Initialize(); err != nil {
|
||||
t.Fatalf("Initialize(): %s", err)
|
||||
}
|
||||
|
||||
if len(emitter) != 1 {
|
||||
t.Fatalf("Initialize emitted %d events want 1", len(emitter))
|
||||
}
|
||||
|
||||
mr, ok := emitter[0].(*pb.MetricRegistration)
|
||||
if !ok {
|
||||
t.Fatalf("emitter %v got %T want pb.MetricRegistration", emitter[0], emitter[0])
|
||||
}
|
||||
|
||||
if len(mr.Metrics) != 3 {
|
||||
t.Errorf("MetricRegistration got %d metrics want %d", len(mr.Metrics), 3)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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 ...string) uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Increment on a FakeUint64Metric does nothing.
|
||||
//
|
||||
//go:nosplit
|
||||
func (m *FakeUint64Metric) Increment(fieldValues ...string) {}
|
||||
|
||||
// IncrementBy on a FakeUint64Metric does nothing.
|
||||
//
|
||||
//go:nosplit
|
||||
func (m *FakeUint64Metric) IncrementBy(v uint64, fieldValues ...string) {}
|
||||
|
||||
// AddSample on a FakeUint64Metric does nothing.
|
||||
//
|
||||
//go:nosplit
|
||||
func (d *FakeDistributionMetric) AddSample(sample int64, fields ...string) {}
|
||||
|
||||
// Start on a FakeUint64Metric returns a FakeTimedOperation struct, which does
|
||||
// nothing and does not keep the time.
|
||||
//
|
||||
//go:nosplit
|
||||
func (t *FakeTimerMetric) Start(fields ...string) FakeTimedOperation {
|
||||
return FakeTimedOperation{}
|
||||
}
|
||||
|
||||
// Finish on a FakeTimedOperation does nothing.
|
||||
//
|
||||
//go:nosplit
|
||||
func (o FakeTimedOperation) Finish(extraFields ...string) {}
|
||||
|
||||
// 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{}
|
||||
}
|
||||
@@ -827,8 +827,8 @@ type metricSet struct {
|
||||
}
|
||||
|
||||
// makeMetricSet returns a new metricSet.
|
||||
func makeMetricSet() metricSet {
|
||||
return metricSet{
|
||||
func makeMetricSet() *metricSet {
|
||||
return &metricSet{
|
||||
uint64Metrics: make(map[string]customUint64Metric),
|
||||
distributionMetrics: make(map[string]*DistributionMetric),
|
||||
finished: make([]stageTiming, 0, len(allStages)),
|
||||
|
||||
@@ -22,49 +22,10 @@ import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
"gvisor.dev/gvisor/pkg/eventchannel"
|
||||
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
)
|
||||
|
||||
// sliceEmitter implements eventchannel.Emitter by appending all messages to a
|
||||
// slice.
|
||||
type sliceEmitter []proto.Message
|
||||
|
||||
// Emit implements eventchannel.Emitter.Emit.
|
||||
func (s *sliceEmitter) Emit(msg proto.Message) (bool, error) {
|
||||
*s = append(*s, msg)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Emit implements eventchannel.Emitter.Close.
|
||||
func (s *sliceEmitter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset clears all events in s.
|
||||
func (s *sliceEmitter) Reset() {
|
||||
*s = nil
|
||||
}
|
||||
|
||||
// emitter is the eventchannel.Emitter used for all tests. Package eventchannel
|
||||
// doesn't allow removing Emitters, so we must use one global emitter for all
|
||||
// test cases.
|
||||
var emitter sliceEmitter
|
||||
|
||||
func init() {
|
||||
reset()
|
||||
|
||||
eventchannel.AddEmitter(&emitter)
|
||||
}
|
||||
|
||||
// reset clears all global state in the metric package.
|
||||
func reset() {
|
||||
initialized = false
|
||||
allMetrics = makeMetricSet()
|
||||
emitter.Reset()
|
||||
}
|
||||
|
||||
const (
|
||||
fooDescription = "Foo!"
|
||||
barDescription = "Bar Baz"
|
||||
@@ -73,7 +34,7 @@ const (
|
||||
)
|
||||
|
||||
func TestInitialize(t *testing.T) {
|
||||
defer reset()
|
||||
defer resetTest()
|
||||
|
||||
_, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription)
|
||||
if err != nil {
|
||||
@@ -181,7 +142,7 @@ func TestInitialize(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDisable(t *testing.T) {
|
||||
defer reset()
|
||||
defer resetTest()
|
||||
|
||||
_, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription)
|
||||
if err != nil {
|
||||
@@ -217,7 +178,7 @@ func TestDisable(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEmitMetricUpdate(t *testing.T) {
|
||||
defer reset()
|
||||
defer resetTest()
|
||||
|
||||
foo, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription)
|
||||
if err != nil {
|
||||
@@ -411,7 +372,7 @@ func TestEmitMetricUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEmitMetricUpdateWithFields(t *testing.T) {
|
||||
defer reset()
|
||||
defer resetTest()
|
||||
|
||||
field := Field{
|
||||
name: "weirdness_type",
|
||||
@@ -498,7 +459,7 @@ func TestEmitMetricUpdateWithFields(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMetricUpdateStageTiming(t *testing.T) {
|
||||
defer reset()
|
||||
defer resetTest()
|
||||
|
||||
expectedTimings := map[InitStage]struct{ min, max time.Duration }{}
|
||||
measureStage := func(stage InitStage, body func()) {
|
||||
@@ -642,7 +603,7 @@ func TestMetricUpdateStageTiming(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTimerMetric(t *testing.T) {
|
||||
defer reset()
|
||||
defer resetTest()
|
||||
// This bucketer just has 2 finite buckets: [0, 500ms) and [500ms, 1s).
|
||||
bucketer := NewExponentialBucketer(2, uint64((500 * time.Millisecond).Nanoseconds()), 0, 1)
|
||||
field1 := NewField("field1", []string{"foo", "bar"})
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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 (
|
||||
"google.golang.org/protobuf/proto"
|
||||
"gvisor.dev/gvisor/pkg/eventchannel"
|
||||
)
|
||||
|
||||
// sliceEmitter implements eventchannel.Emitter by appending all messages to a
|
||||
// slice.
|
||||
type sliceEmitter []proto.Message
|
||||
|
||||
// Emit implements eventchannel.Emitter.Emit.
|
||||
func (s *sliceEmitter) Emit(msg proto.Message) (bool, error) {
|
||||
*s = append(*s, msg)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Emit implements eventchannel.Emitter.Close.
|
||||
func (s *sliceEmitter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset clears all events in s.
|
||||
func (s *sliceEmitter) Reset() {
|
||||
*s = nil
|
||||
}
|
||||
|
||||
// emitter is the eventchannel.Emitter used for all tests. Package eventchannel
|
||||
// doesn't allow removing Emitters, so we must use one global emitter for all
|
||||
// test cases.
|
||||
var emitter sliceEmitter
|
||||
|
||||
func init() {
|
||||
resetTest()
|
||||
|
||||
eventchannel.AddEmitter(&emitter)
|
||||
}
|
||||
|
||||
func resetTest() {
|
||||
initialized = false
|
||||
allMetrics = makeMetricSet()
|
||||
emitter.Reset()
|
||||
}
|
||||
@@ -600,12 +600,12 @@ type Task struct {
|
||||
var (
|
||||
// syscallCounter is a metric that tracks how many syscalls the sentry has
|
||||
// executed.
|
||||
syscallCounter = metric.MustCreateNewUint64Metric(
|
||||
syscallCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/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.MustCreateNewUint64Metric(
|
||||
faultCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/task/faults", false, "The number of faults the sentry has handled.")
|
||||
)
|
||||
|
||||
|
||||
@@ -106,32 +106,32 @@ const (
|
||||
var (
|
||||
// hostExitCounter is a metric that tracks how many times the sentry
|
||||
// performed a host to guest world switch.
|
||||
hostExitCounter = metric.MustCreateNewUint64Metric(
|
||||
hostExitCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/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.MustCreateNewUint64Metric(
|
||||
userExitCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/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.MustCreateNewUint64Metric(
|
||||
interruptCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/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.MustCreateNewUint64Metric(
|
||||
mmapCallCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/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.MustCreateNewUint64Metric(
|
||||
getVCPUCounter = metric.MustCreateNewProfilingUint64Metric(
|
||||
"/kvm/get_vcpu", false, "The number of times that machine.Get() was called, split by path the function took.",
|
||||
metric.NewField("acquisition_type", []string{"fast_reused", "reused", "unused", "stolen"}))
|
||||
|
||||
// asInvalidateDuration are durations of calling addressSpace.invalidate().
|
||||
asInvalidateDuration = metric.MustCreateNewTimerMetric("/kvm/address_space_invalidate",
|
||||
asInvalidateDuration = metric.MustCreateNewProfilingTimerMetric("/kvm/address_space_invalidate",
|
||||
metric.NewExponentialBucketer(15, uint64(time.Nanosecond*100), 1, 2),
|
||||
"Duration of calling addressSpace.invalidate().")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user