github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/control/metrics.go (about) 1 // Copyright 2022 The gVisor Authors. 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 control 16 17 import ( 18 "fmt" 19 "regexp" 20 21 "github.com/nicocha30/gvisor-ligolo/pkg/metric" 22 pb "github.com/nicocha30/gvisor-ligolo/pkg/metric/metric_go_proto" 23 "github.com/nicocha30/gvisor-ligolo/pkg/prometheus" 24 "github.com/nicocha30/gvisor-ligolo/pkg/sync" 25 ) 26 27 // Metrics includes metrics-related RPC stubs. 28 type Metrics struct{} 29 30 // GetRegisteredMetricsOpts contains metric registration query options. 31 type GetRegisteredMetricsOpts struct{} 32 33 // MetricsRegistrationResponse contains metric registration data. 34 type MetricsRegistrationResponse struct { 35 RegisteredMetrics *pb.MetricRegistration 36 } 37 38 // GetRegisteredMetrics sets `out` to the metric registration information. 39 // Meant to be called over the control channel, with `out` as return value. 40 // This should be called during Sentry boot before any container starts. 41 // Metric registration data is used by the processes querying sandbox metrics 42 // to ensure the integrity of metrics exported from the untrusted sandbox. 43 func (u *Metrics) GetRegisteredMetrics(_ *GetRegisteredMetricsOpts, out *MetricsRegistrationResponse) error { 44 registration, err := metric.GetMetricRegistration() 45 if err != nil { 46 return err 47 } 48 out.RegisteredMetrics = registration 49 return nil 50 } 51 52 // MetricsExportOpts contains metric exporting options. 53 type MetricsExportOpts struct { 54 // If set, this is a regular expression that is used to filter the set of 55 // exported metrics. 56 OnlyMetrics string `json:"only_metrics"` 57 } 58 59 var ( 60 // lastOnlyMetricsMu protects the variables below. 61 lastOnlyMetricsMu sync.Mutex 62 63 // lastOnlyMetricsStr is the last value of the "only_metrics" parameter passed to 64 // MetricsExport. It is used to avoid re-compiling the regular expression on every 65 // request in the common case where a single metric scraper is scraping the sandbox 66 // metrics using the same filter in each request. 67 lastOnlyMetricsStr string 68 69 // lastOnlyMetrics is the compiled version of lastOnlyMetricsStr. 70 lastOnlyMetrics *regexp.Regexp 71 ) 72 73 // filterFunc returns a filter function to filter relevant Prometheus metric names. 74 func (m *MetricsExportOpts) filterFunc() (func(*prometheus.Metric) bool, error) { 75 if m.OnlyMetrics == "" { 76 return nil, nil 77 } 78 lastOnlyMetricsMu.Lock() 79 defer lastOnlyMetricsMu.Unlock() 80 onlyMetricsReg := lastOnlyMetrics 81 if m.OnlyMetrics != lastOnlyMetricsStr { 82 reg, err := regexp.Compile(m.OnlyMetrics) 83 if err != nil { 84 return nil, fmt.Errorf("cannot compile regexp %q: %v", m.OnlyMetrics, err) 85 } 86 lastOnlyMetricsStr = m.OnlyMetrics 87 lastOnlyMetrics = reg 88 onlyMetricsReg = reg 89 } 90 return func(m *prometheus.Metric) bool { 91 return onlyMetricsReg.MatchString(m.Name) 92 }, nil 93 } 94 95 // Verify verifies that the given exported data is compliant with the export 96 // options. This should be run client-side to double-check results. 97 func (m *MetricsExportOpts) Verify(data *MetricsExportData) error { 98 filterFunc, err := m.filterFunc() 99 if err != nil { 100 return err 101 } 102 if filterFunc != nil && data.Snapshot != nil { 103 for _, data := range data.Snapshot.Data { 104 if !filterFunc(data.Metric) { 105 return fmt.Errorf("metric %v violated the filter set in export options", data.Metric) 106 } 107 } 108 } 109 return nil 110 } 111 112 // MetricsExportData contains data for all metrics being exported. 113 type MetricsExportData struct { 114 Snapshot *prometheus.Snapshot `json:"snapshot"` 115 } 116 117 // Export export metrics data into MetricsExportData. 118 func (u *Metrics) Export(opts *MetricsExportOpts, out *MetricsExportData) error { 119 filterFunc, err := opts.filterFunc() 120 if err != nil { 121 return err 122 } 123 snapshot, err := metric.GetSnapshot(metric.SnapshotOptions{ 124 Filter: filterFunc, 125 }) 126 if err != nil { 127 return err 128 } 129 out.Snapshot = snapshot 130 return nil 131 }