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
|
// 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 control
import (
"fmt"
"regexp"
"gvisor.dev/gvisor/pkg/metric"
pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
"gvisor.dev/gvisor/pkg/prometheus"
"gvisor.dev/gvisor/pkg/sync"
)
// Metrics includes metrics-related RPC stubs.
type Metrics struct{}
// GetRegisteredMetricsOpts contains metric registration query options.
type GetRegisteredMetricsOpts struct{}
// MetricsRegistrationResponse contains metric registration data.
type MetricsRegistrationResponse struct {
RegisteredMetrics *pb.MetricRegistration
}
// GetRegisteredMetrics sets `out` to the metric registration information.
// Meant to be called over the control channel, with `out` as return value.
// This should be called during Sentry boot before any container starts.
// Metric registration data is used by the processes querying sandbox metrics
// to ensure the integrity of metrics exported from the untrusted sandbox.
func (u *Metrics) GetRegisteredMetrics(_ *GetRegisteredMetricsOpts, out *MetricsRegistrationResponse) error {
registration, err := metric.GetMetricRegistration()
if err != nil {
return err
}
out.RegisteredMetrics = registration
return nil
}
// MetricsExportOpts contains metric exporting options.
type MetricsExportOpts struct {
// If set, this is a regular expression that is used to filter the set of
// exported metrics.
OnlyMetrics string `json:"only_metrics"`
}
var (
// lastOnlyMetricsMu protects the variables below.
lastOnlyMetricsMu sync.Mutex
// lastOnlyMetricsStr is the last value of the "only_metrics" parameter passed to
// MetricsExport. It is used to avoid re-compiling the regular expression on every
// request in the common case where a single metric scraper is scraping the sandbox
// metrics using the same filter in each request.
lastOnlyMetricsStr string
// lastOnlyMetrics is the compiled version of lastOnlyMetricsStr.
lastOnlyMetrics *regexp.Regexp
)
// filterFunc returns a filter function to filter relevant Prometheus metric names.
func (m *MetricsExportOpts) filterFunc() (func(*prometheus.Metric) bool, error) {
if m.OnlyMetrics == "" {
return nil, nil
}
lastOnlyMetricsMu.Lock()
defer lastOnlyMetricsMu.Unlock()
onlyMetricsReg := lastOnlyMetrics
if m.OnlyMetrics != lastOnlyMetricsStr {
reg, err := regexp.Compile(m.OnlyMetrics)
if err != nil {
return nil, fmt.Errorf("cannot compile regexp %q: %v", m.OnlyMetrics, err)
}
lastOnlyMetricsStr = m.OnlyMetrics
lastOnlyMetrics = reg
onlyMetricsReg = reg
}
return func(m *prometheus.Metric) bool {
return onlyMetricsReg.MatchString(m.Name)
}, nil
}
// Verify verifies that the given exported data is compliant with the export
// options. This should be run client-side to double-check results.
func (m *MetricsExportOpts) Verify(data *MetricsExportData) error {
filterFunc, err := m.filterFunc()
if err != nil {
return err
}
if filterFunc != nil && data.Snapshot != nil {
for _, data := range data.Snapshot.Data {
if !filterFunc(data.Metric) {
return fmt.Errorf("metric %v violated the filter set in export options", data.Metric)
}
}
}
return nil
}
// MetricsExportData contains data for all metrics being exported.
type MetricsExportData struct {
Snapshot *prometheus.Snapshot `json:"snapshot"`
}
// Export export metrics data into MetricsExportData.
func (u *Metrics) Export(opts *MetricsExportOpts, out *MetricsExportData) error {
filterFunc, err := opts.filterFunc()
if err != nil {
return err
}
snapshot, err := metric.GetSnapshot(metric.SnapshotOptions{
Filter: filterFunc,
})
if err != nil {
return err
}
out.Snapshot = snapshot
return nil
}
|