full diffs:
- https://github.com/prometheus/client_golang/compare/v1.14.0...v1.17.0
- https://github.com/prometheus/client_model/compare/v0.3.0...v0.5.0
- https://github.com/prometheus/common/compare/v0.42.0...v0.44.0
- https://github.com/prometheus/procfs/compare/v0.9.0...v0.11.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -81,7 +81,7 @@ require ( |
| 81 | 81 |
github.com/opencontainers/selinux v1.11.0 |
| 82 | 82 |
github.com/pelletier/go-toml v1.9.5 |
| 83 | 83 |
github.com/pkg/errors v0.9.1 |
| 84 |
- github.com/prometheus/client_golang v1.14.0 |
|
| 84 |
+ github.com/prometheus/client_golang v1.17.0 |
|
| 85 | 85 |
github.com/rootless-containers/rootlesskit/v2 v2.0.1 |
| 86 | 86 |
github.com/sirupsen/logrus v1.9.3 |
| 87 | 87 |
github.com/spf13/cobra v1.8.0 |
| ... | ... |
@@ -173,9 +173,9 @@ require ( |
| 173 | 173 |
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect |
| 174 | 174 |
github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 // indirect |
| 175 | 175 |
github.com/philhofer/fwd v1.1.2 // indirect |
| 176 |
- github.com/prometheus/client_model v0.3.0 // indirect |
|
| 177 |
- github.com/prometheus/common v0.42.0 // indirect |
|
| 178 |
- github.com/prometheus/procfs v0.9.0 // indirect |
|
| 176 |
+ github.com/prometheus/client_model v0.5.0 // indirect |
|
| 177 |
+ github.com/prometheus/common v0.44.0 // indirect |
|
| 178 |
+ github.com/prometheus/procfs v0.11.1 // indirect |
|
| 179 | 179 |
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect |
| 180 | 180 |
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect |
| 181 | 181 |
github.com/shibumi/go-pathspec v1.3.0 // indirect |
| ... | ... |
@@ -1056,16 +1056,16 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ |
| 1056 | 1056 |
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= |
| 1057 | 1057 |
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= |
| 1058 | 1058 |
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= |
| 1059 |
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= |
|
| 1060 |
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= |
|
| 1059 |
+github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= |
|
| 1060 |
+github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= |
|
| 1061 | 1061 |
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= |
| 1062 | 1062 |
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= |
| 1063 | 1063 |
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= |
| 1064 | 1064 |
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= |
| 1065 | 1065 |
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= |
| 1066 | 1066 |
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= |
| 1067 |
-github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= |
|
| 1068 |
-github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= |
|
| 1067 |
+github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= |
|
| 1068 |
+github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= |
|
| 1069 | 1069 |
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= |
| 1070 | 1070 |
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= |
| 1071 | 1071 |
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= |
| ... | ... |
@@ -1076,8 +1076,8 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+ |
| 1076 | 1076 |
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= |
| 1077 | 1077 |
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= |
| 1078 | 1078 |
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= |
| 1079 |
-github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= |
|
| 1080 |
-github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= |
|
| 1079 |
+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= |
|
| 1080 |
+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= |
|
| 1081 | 1081 |
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= |
| 1082 | 1082 |
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= |
| 1083 | 1083 |
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= |
| ... | ... |
@@ -1090,8 +1090,8 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa |
| 1090 | 1090 |
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= |
| 1091 | 1091 |
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= |
| 1092 | 1092 |
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= |
| 1093 |
-github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= |
|
| 1094 |
-github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= |
|
| 1093 |
+github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= |
|
| 1094 |
+github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= |
|
| 1095 | 1095 |
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= |
| 1096 | 1096 |
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= |
| 1097 | 1097 |
github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8/go.mod h1:CGFX09Ci3pq9QZdj86B+VGIdNj4VyCo2iPOGS9esB/k= |
| ... | ... |
@@ -20,6 +20,7 @@ import ( |
| 20 | 20 |
"time" |
| 21 | 21 |
|
| 22 | 22 |
dto "github.com/prometheus/client_model/go" |
| 23 |
+ "google.golang.org/protobuf/types/known/timestamppb" |
|
| 23 | 24 |
) |
| 24 | 25 |
|
| 25 | 26 |
// Counter is a Metric that represents a single numerical value that only ever |
| ... | ... |
@@ -59,6 +60,18 @@ type ExemplarAdder interface {
|
| 59 | 59 |
// CounterOpts is an alias for Opts. See there for doc comments. |
| 60 | 60 |
type CounterOpts Opts |
| 61 | 61 |
|
| 62 |
+// CounterVecOpts bundles the options to create a CounterVec metric. |
|
| 63 |
+// It is mandatory to set CounterOpts, see there for mandatory fields. VariableLabels |
|
| 64 |
+// is optional and can safely be left to its default value. |
|
| 65 |
+type CounterVecOpts struct {
|
|
| 66 |
+ CounterOpts |
|
| 67 |
+ |
|
| 68 |
+ // VariableLabels are used to partition the metric vector by the given set |
|
| 69 |
+ // of labels. Each label value will be constrained with the optional Constraint |
|
| 70 |
+ // function, if provided. |
|
| 71 |
+ VariableLabels ConstrainableLabels |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 62 | 74 |
// NewCounter creates a new Counter based on the provided CounterOpts. |
| 63 | 75 |
// |
| 64 | 76 |
// The returned implementation also implements ExemplarAdder. It is safe to |
| ... | ... |
@@ -78,8 +91,12 @@ func NewCounter(opts CounterOpts) Counter {
|
| 78 | 78 |
nil, |
| 79 | 79 |
opts.ConstLabels, |
| 80 | 80 |
) |
| 81 |
- result := &counter{desc: desc, labelPairs: desc.constLabelPairs, now: time.Now}
|
|
| 81 |
+ if opts.now == nil {
|
|
| 82 |
+ opts.now = time.Now |
|
| 83 |
+ } |
|
| 84 |
+ result := &counter{desc: desc, labelPairs: desc.constLabelPairs, now: opts.now}
|
|
| 82 | 85 |
result.init(result) // Init self-collection. |
| 86 |
+ result.createdTs = timestamppb.New(opts.now()) |
|
| 83 | 87 |
return result |
| 84 | 88 |
} |
| 85 | 89 |
|
| ... | ... |
@@ -94,10 +111,12 @@ type counter struct {
|
| 94 | 94 |
selfCollector |
| 95 | 95 |
desc *Desc |
| 96 | 96 |
|
| 97 |
+ createdTs *timestamppb.Timestamp |
|
| 97 | 98 |
labelPairs []*dto.LabelPair |
| 98 | 99 |
exemplar atomic.Value // Containing nil or a *dto.Exemplar. |
| 99 | 100 |
|
| 100 |
- now func() time.Time // To mock out time.Now() for testing. |
|
| 101 |
+ // now is for testing purposes, by default it's time.Now. |
|
| 102 |
+ now func() time.Time |
|
| 101 | 103 |
} |
| 102 | 104 |
|
| 103 | 105 |
func (c *counter) Desc() *Desc {
|
| ... | ... |
@@ -147,8 +166,7 @@ func (c *counter) Write(out *dto.Metric) error {
|
| 147 | 147 |
exemplar = e.(*dto.Exemplar) |
| 148 | 148 |
} |
| 149 | 149 |
val := c.get() |
| 150 |
- |
|
| 151 |
- return populateMetric(CounterValue, val, c.labelPairs, exemplar, out) |
|
| 150 |
+ return populateMetric(CounterValue, val, c.labelPairs, exemplar, out, c.createdTs) |
|
| 152 | 151 |
} |
| 153 | 152 |
|
| 154 | 153 |
func (c *counter) updateExemplar(v float64, l Labels) {
|
| ... | ... |
@@ -174,19 +192,31 @@ type CounterVec struct {
|
| 174 | 174 |
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and |
| 175 | 175 |
// partitioned by the given label names. |
| 176 | 176 |
func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
| 177 |
- desc := NewDesc( |
|
| 177 |
+ return V2.NewCounterVec(CounterVecOpts{
|
|
| 178 |
+ CounterOpts: opts, |
|
| 179 |
+ VariableLabels: UnconstrainedLabels(labelNames), |
|
| 180 |
+ }) |
|
| 181 |
+} |
|
| 182 |
+ |
|
| 183 |
+// NewCounterVec creates a new CounterVec based on the provided CounterVecOpts. |
|
| 184 |
+func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec {
|
|
| 185 |
+ desc := V2.NewDesc( |
|
| 178 | 186 |
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), |
| 179 | 187 |
opts.Help, |
| 180 |
- labelNames, |
|
| 188 |
+ opts.VariableLabels, |
|
| 181 | 189 |
opts.ConstLabels, |
| 182 | 190 |
) |
| 191 |
+ if opts.now == nil {
|
|
| 192 |
+ opts.now = time.Now |
|
| 193 |
+ } |
|
| 183 | 194 |
return &CounterVec{
|
| 184 | 195 |
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
| 185 |
- if len(lvs) != len(desc.variableLabels) {
|
|
| 186 |
- panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) |
|
| 196 |
+ if len(lvs) != len(desc.variableLabels.names) {
|
|
| 197 |
+ panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, lvs)) |
|
| 187 | 198 |
} |
| 188 |
- result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now}
|
|
| 199 |
+ result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: opts.now}
|
|
| 189 | 200 |
result.init(result) // Init self-collection. |
| 201 |
+ result.createdTs = timestamppb.New(opts.now()) |
|
| 190 | 202 |
return result |
| 191 | 203 |
}), |
| 192 | 204 |
} |
| ... | ... |
@@ -14,20 +14,16 @@ |
| 14 | 14 |
package prometheus |
| 15 | 15 |
|
| 16 | 16 |
import ( |
| 17 |
- "errors" |
|
| 18 | 17 |
"fmt" |
| 19 | 18 |
"sort" |
| 20 | 19 |
"strings" |
| 21 | 20 |
|
| 22 | 21 |
"github.com/cespare/xxhash/v2" |
| 23 |
- |
|
| 24 |
- "github.com/prometheus/client_golang/prometheus/internal" |
|
| 25 |
- |
|
| 26 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 27 |
- "github.com/golang/protobuf/proto" |
|
| 22 |
+ dto "github.com/prometheus/client_model/go" |
|
| 28 | 23 |
"github.com/prometheus/common/model" |
| 24 |
+ "google.golang.org/protobuf/proto" |
|
| 29 | 25 |
|
| 30 |
- dto "github.com/prometheus/client_model/go" |
|
| 26 |
+ "github.com/prometheus/client_golang/prometheus/internal" |
|
| 31 | 27 |
) |
| 32 | 28 |
|
| 33 | 29 |
// Desc is the descriptor used by every Prometheus Metric. It is essentially |
| ... | ... |
@@ -54,9 +50,9 @@ type Desc struct {
|
| 54 | 54 |
// constLabelPairs contains precalculated DTO label pairs based on |
| 55 | 55 |
// the constant labels. |
| 56 | 56 |
constLabelPairs []*dto.LabelPair |
| 57 |
- // variableLabels contains names of labels for which the metric |
|
| 58 |
- // maintains variable values. |
|
| 59 |
- variableLabels []string |
|
| 57 |
+ // variableLabels contains names of labels and normalization function for |
|
| 58 |
+ // which the metric maintains variable values. |
|
| 59 |
+ variableLabels *compiledLabels |
|
| 60 | 60 |
// id is a hash of the values of the ConstLabels and fqName. This |
| 61 | 61 |
// must be unique among all registered descriptors and can therefore be |
| 62 | 62 |
// used as an identifier of the descriptor. |
| ... | ... |
@@ -80,10 +76,24 @@ type Desc struct {
|
| 80 | 80 |
// For constLabels, the label values are constant. Therefore, they are fully |
| 81 | 81 |
// specified in the Desc. See the Collector example for a usage pattern. |
| 82 | 82 |
func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc {
|
| 83 |
+ return V2.NewDesc(fqName, help, UnconstrainedLabels(variableLabels), constLabels) |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc |
|
| 87 |
+// and will be reported on registration time. variableLabels and constLabels can |
|
| 88 |
+// be nil if no such labels should be set. fqName must not be empty. |
|
| 89 |
+// |
|
| 90 |
+// variableLabels only contain the label names and normalization functions. Their |
|
| 91 |
+// label values are variable and therefore not part of the Desc. (They are managed |
|
| 92 |
+// within the Metric.) |
|
| 93 |
+// |
|
| 94 |
+// For constLabels, the label values are constant. Therefore, they are fully |
|
| 95 |
+// specified in the Desc. See the Collector example for a usage pattern. |
|
| 96 |
+func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc {
|
|
| 83 | 97 |
d := &Desc{
|
| 84 | 98 |
fqName: fqName, |
| 85 | 99 |
help: help, |
| 86 |
- variableLabels: variableLabels, |
|
| 100 |
+ variableLabels: variableLabels.compile(), |
|
| 87 | 101 |
} |
| 88 | 102 |
if !model.IsValidMetricName(model.LabelValue(fqName)) {
|
| 89 | 103 |
d.err = fmt.Errorf("%q is not a valid metric name", fqName)
|
| ... | ... |
@@ -93,7 +103,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * |
| 93 | 93 |
// their sorted label names) plus the fqName (at position 0). |
| 94 | 94 |
labelValues := make([]string, 1, len(constLabels)+1) |
| 95 | 95 |
labelValues[0] = fqName |
| 96 |
- labelNames := make([]string, 0, len(constLabels)+len(variableLabels)) |
|
| 96 |
+ labelNames := make([]string, 0, len(constLabels)+len(d.variableLabels.names)) |
|
| 97 | 97 |
labelNameSet := map[string]struct{}{}
|
| 98 | 98 |
// First add only the const label names and sort them... |
| 99 | 99 |
for labelName := range constLabels {
|
| ... | ... |
@@ -118,16 +128,16 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * |
| 118 | 118 |
// Now add the variable label names, but prefix them with something that |
| 119 | 119 |
// cannot be in a regular label name. That prevents matching the label |
| 120 | 120 |
// dimension with a different mix between preset and variable labels. |
| 121 |
- for _, labelName := range variableLabels {
|
|
| 122 |
- if !checkLabelName(labelName) {
|
|
| 123 |
- d.err = fmt.Errorf("%q is not a valid label name for metric %q", labelName, fqName)
|
|
| 121 |
+ for _, label := range d.variableLabels.names {
|
|
| 122 |
+ if !checkLabelName(label) {
|
|
| 123 |
+ d.err = fmt.Errorf("%q is not a valid label name for metric %q", label, fqName)
|
|
| 124 | 124 |
return d |
| 125 | 125 |
} |
| 126 |
- labelNames = append(labelNames, "$"+labelName) |
|
| 127 |
- labelNameSet[labelName] = struct{}{}
|
|
| 126 |
+ labelNames = append(labelNames, "$"+label) |
|
| 127 |
+ labelNameSet[label] = struct{}{}
|
|
| 128 | 128 |
} |
| 129 | 129 |
if len(labelNames) != len(labelNameSet) {
|
| 130 |
- d.err = errors.New("duplicate label names")
|
|
| 130 |
+ d.err = fmt.Errorf("duplicate label names in constant and variable labels for metric %q", fqName)
|
|
| 131 | 131 |
return d |
| 132 | 132 |
} |
| 133 | 133 |
|
| ... | ... |
@@ -179,11 +189,19 @@ func (d *Desc) String() string {
|
| 179 | 179 |
fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()),
|
| 180 | 180 |
) |
| 181 | 181 |
} |
| 182 |
+ vlStrings := make([]string, 0, len(d.variableLabels.names)) |
|
| 183 |
+ for _, vl := range d.variableLabels.names {
|
|
| 184 |
+ if fn, ok := d.variableLabels.labelConstraints[vl]; ok && fn != nil {
|
|
| 185 |
+ vlStrings = append(vlStrings, fmt.Sprintf("c(%s)", vl))
|
|
| 186 |
+ } else {
|
|
| 187 |
+ vlStrings = append(vlStrings, vl) |
|
| 188 |
+ } |
|
| 189 |
+ } |
|
| 182 | 190 |
return fmt.Sprintf( |
| 183 |
- "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: %v}",
|
|
| 191 |
+ "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: {%s}}",
|
|
| 184 | 192 |
d.fqName, |
| 185 | 193 |
d.help, |
| 186 | 194 |
strings.Join(lpStrings, ","), |
| 187 |
- d.variableLabels, |
|
| 195 |
+ strings.Join(vlStrings, ","), |
|
| 188 | 196 |
) |
| 189 | 197 |
} |
| ... | ... |
@@ -37,35 +37,35 @@ |
| 37 | 37 |
// |
| 38 | 38 |
// type metrics struct {
|
| 39 | 39 |
// cpuTemp prometheus.Gauge |
| 40 |
-// hdFailures *prometheus.CounterVec |
|
| 40 |
+// hdFailures *prometheus.CounterVec |
|
| 41 | 41 |
// } |
| 42 | 42 |
// |
| 43 | 43 |
// func NewMetrics(reg prometheus.Registerer) *metrics {
|
| 44 |
-// m := &metrics{
|
|
| 45 |
-// cpuTemp: prometheus.NewGauge(prometheus.GaugeOpts{
|
|
| 46 |
-// Name: "cpu_temperature_celsius", |
|
| 47 |
-// Help: "Current temperature of the CPU.", |
|
| 48 |
-// }), |
|
| 49 |
-// hdFailures: prometheus.NewCounterVec( |
|
| 50 |
-// prometheus.CounterOpts{
|
|
| 51 |
-// Name: "hd_errors_total", |
|
| 52 |
-// Help: "Number of hard-disk errors.", |
|
| 53 |
-// }, |
|
| 54 |
-// []string{"device"},
|
|
| 55 |
-// ), |
|
| 56 |
-// } |
|
| 57 |
-// reg.MustRegister(m.cpuTemp) |
|
| 58 |
-// reg.MustRegister(m.hdFailures) |
|
| 59 |
-// return m |
|
| 44 |
+// m := &metrics{
|
|
| 45 |
+// cpuTemp: prometheus.NewGauge(prometheus.GaugeOpts{
|
|
| 46 |
+// Name: "cpu_temperature_celsius", |
|
| 47 |
+// Help: "Current temperature of the CPU.", |
|
| 48 |
+// }), |
|
| 49 |
+// hdFailures: prometheus.NewCounterVec( |
|
| 50 |
+// prometheus.CounterOpts{
|
|
| 51 |
+// Name: "hd_errors_total", |
|
| 52 |
+// Help: "Number of hard-disk errors.", |
|
| 53 |
+// }, |
|
| 54 |
+// []string{"device"},
|
|
| 55 |
+// ), |
|
| 56 |
+// } |
|
| 57 |
+// reg.MustRegister(m.cpuTemp) |
|
| 58 |
+// reg.MustRegister(m.hdFailures) |
|
| 59 |
+// return m |
|
| 60 | 60 |
// } |
| 61 | 61 |
// |
| 62 | 62 |
// func main() {
|
| 63 |
-// // Create a non-global registry. |
|
| 64 |
-// reg := prometheus.NewRegistry() |
|
| 63 |
+// // Create a non-global registry. |
|
| 64 |
+// reg := prometheus.NewRegistry() |
|
| 65 | 65 |
// |
| 66 |
-// // Create new metrics and register them using the custom registry. |
|
| 67 |
-// m := NewMetrics(reg) |
|
| 68 |
-// // Set values for the new created metrics. |
|
| 66 |
+// // Create new metrics and register them using the custom registry. |
|
| 67 |
+// m := NewMetrics(reg) |
|
| 68 |
+// // Set values for the new created metrics. |
|
| 69 | 69 |
// m.cpuTemp.Set(65.3) |
| 70 | 70 |
// m.hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc()
|
| 71 | 71 |
// |
| ... | ... |
@@ -48,7 +48,7 @@ func (e *expvarCollector) Collect(ch chan<- Metric) {
|
| 48 | 48 |
continue |
| 49 | 49 |
} |
| 50 | 50 |
var v interface{}
|
| 51 |
- labels := make([]string, len(desc.variableLabels)) |
|
| 51 |
+ labels := make([]string, len(desc.variableLabels.names)) |
|
| 52 | 52 |
if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil {
|
| 53 | 53 |
ch <- NewInvalidMetric(desc, err) |
| 54 | 54 |
continue |
| ... | ... |
@@ -55,6 +55,18 @@ type Gauge interface {
|
| 55 | 55 |
// GaugeOpts is an alias for Opts. See there for doc comments. |
| 56 | 56 |
type GaugeOpts Opts |
| 57 | 57 |
|
| 58 |
+// GaugeVecOpts bundles the options to create a GaugeVec metric. |
|
| 59 |
+// It is mandatory to set GaugeOpts, see there for mandatory fields. VariableLabels |
|
| 60 |
+// is optional and can safely be left to its default value. |
|
| 61 |
+type GaugeVecOpts struct {
|
|
| 62 |
+ GaugeOpts |
|
| 63 |
+ |
|
| 64 |
+ // VariableLabels are used to partition the metric vector by the given set |
|
| 65 |
+ // of labels. Each label value will be constrained with the optional Constraint |
|
| 66 |
+ // function, if provided. |
|
| 67 |
+ VariableLabels ConstrainableLabels |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 58 | 70 |
// NewGauge creates a new Gauge based on the provided GaugeOpts. |
| 59 | 71 |
// |
| 60 | 72 |
// The returned implementation is optimized for a fast Set method. If you have a |
| ... | ... |
@@ -123,7 +135,7 @@ func (g *gauge) Sub(val float64) {
|
| 123 | 123 |
|
| 124 | 124 |
func (g *gauge) Write(out *dto.Metric) error {
|
| 125 | 125 |
val := math.Float64frombits(atomic.LoadUint64(&g.valBits)) |
| 126 |
- return populateMetric(GaugeValue, val, g.labelPairs, nil, out) |
|
| 126 |
+ return populateMetric(GaugeValue, val, g.labelPairs, nil, out, nil) |
|
| 127 | 127 |
} |
| 128 | 128 |
|
| 129 | 129 |
// GaugeVec is a Collector that bundles a set of Gauges that all share the same |
| ... | ... |
@@ -138,16 +150,24 @@ type GaugeVec struct {
|
| 138 | 138 |
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and |
| 139 | 139 |
// partitioned by the given label names. |
| 140 | 140 |
func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
| 141 |
- desc := NewDesc( |
|
| 141 |
+ return V2.NewGaugeVec(GaugeVecOpts{
|
|
| 142 |
+ GaugeOpts: opts, |
|
| 143 |
+ VariableLabels: UnconstrainedLabels(labelNames), |
|
| 144 |
+ }) |
|
| 145 |
+} |
|
| 146 |
+ |
|
| 147 |
+// NewGaugeVec creates a new GaugeVec based on the provided GaugeVecOpts. |
|
| 148 |
+func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec {
|
|
| 149 |
+ desc := V2.NewDesc( |
|
| 142 | 150 |
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), |
| 143 | 151 |
opts.Help, |
| 144 |
- labelNames, |
|
| 152 |
+ opts.VariableLabels, |
|
| 145 | 153 |
opts.ConstLabels, |
| 146 | 154 |
) |
| 147 | 155 |
return &GaugeVec{
|
| 148 | 156 |
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
| 149 |
- if len(lvs) != len(desc.variableLabels) {
|
|
| 150 |
- panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) |
|
| 157 |
+ if len(lvs) != len(desc.variableLabels.names) {
|
|
| 158 |
+ panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, lvs)) |
|
| 151 | 159 |
} |
| 152 | 160 |
result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
|
| 153 | 161 |
result.init(result) // Init self-collection. |
| ... | ... |
@@ -23,11 +23,10 @@ import ( |
| 23 | 23 |
"strings" |
| 24 | 24 |
"sync" |
| 25 | 25 |
|
| 26 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 27 |
- "github.com/golang/protobuf/proto" |
|
| 28 |
- dto "github.com/prometheus/client_model/go" |
|
| 29 |
- |
|
| 30 | 26 |
"github.com/prometheus/client_golang/prometheus/internal" |
| 27 |
+ |
|
| 28 |
+ dto "github.com/prometheus/client_model/go" |
|
| 29 |
+ "google.golang.org/protobuf/proto" |
|
| 31 | 30 |
) |
| 32 | 31 |
|
| 33 | 32 |
const ( |
| ... | ... |
@@ -22,10 +22,10 @@ import ( |
| 22 | 22 |
"sync/atomic" |
| 23 | 23 |
"time" |
| 24 | 24 |
|
| 25 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 26 |
- "github.com/golang/protobuf/proto" |
|
| 27 |
- |
|
| 28 | 25 |
dto "github.com/prometheus/client_model/go" |
| 26 |
+ |
|
| 27 |
+ "google.golang.org/protobuf/proto" |
|
| 28 |
+ "google.golang.org/protobuf/types/known/timestamppb" |
|
| 29 | 29 |
) |
| 30 | 30 |
|
| 31 | 31 |
// nativeHistogramBounds for the frac of observed values. Only relevant for |
| ... | ... |
@@ -392,7 +392,7 @@ type HistogramOpts struct {
|
| 392 | 392 |
// zero, it is replaced by default buckets. The default buckets are |
| 393 | 393 |
// DefBuckets if no buckets for a native histogram (see below) are used, |
| 394 | 394 |
// otherwise the default is no buckets. (In other words, if you want to |
| 395 |
- // use both reguler buckets and buckets for a native histogram, you have |
|
| 395 |
+ // use both regular buckets and buckets for a native histogram, you have |
|
| 396 | 396 |
// to define the regular buckets here explicitly.) |
| 397 | 397 |
Buckets []float64 |
| 398 | 398 |
|
| ... | ... |
@@ -402,7 +402,7 @@ type HistogramOpts struct {
|
| 402 | 402 |
// Histogram by a Prometheus server with that feature enabled (requires |
| 403 | 403 |
// Prometheus v2.40+). Sparse buckets are exponential buckets covering |
| 404 | 404 |
// the whole float64 range (with the exception of the “zero” bucket, see |
| 405 |
- // SparseBucketsZeroThreshold below). From any one bucket to the next, |
|
| 405 |
+ // NativeHistogramZeroThreshold below). From any one bucket to the next, |
|
| 406 | 406 |
// the width of the bucket grows by a constant |
| 407 | 407 |
// factor. NativeHistogramBucketFactor provides an upper bound for this |
| 408 | 408 |
// factor (exception see below). The smaller |
| ... | ... |
@@ -414,8 +414,8 @@ type HistogramOpts struct {
|
| 414 | 414 |
// and 2, same as between 2 and 4, and 4 and 8, etc.). |
| 415 | 415 |
// |
| 416 | 416 |
// Details about the actually used factor: The factor is calculated as |
| 417 |
- // 2^(2^n), where n is an integer number between (and including) -8 and |
|
| 418 |
- // 4. n is chosen so that the resulting factor is the largest that is |
|
| 417 |
+ // 2^(2^-n), where n is an integer number between (and including) -4 and |
|
| 418 |
+ // 8. n is chosen so that the resulting factor is the largest that is |
|
| 419 | 419 |
// still smaller or equal to NativeHistogramBucketFactor. Note that the |
| 420 | 420 |
// smallest possible factor is therefore approx. 1.00271 (i.e. 2^(2^-8) |
| 421 | 421 |
// ). If NativeHistogramBucketFactor is greater than 1 but smaller than |
| ... | ... |
@@ -429,12 +429,12 @@ type HistogramOpts struct {
|
| 429 | 429 |
// a major version bump. |
| 430 | 430 |
NativeHistogramBucketFactor float64 |
| 431 | 431 |
// All observations with an absolute value of less or equal |
| 432 |
- // NativeHistogramZeroThreshold are accumulated into a “zero” |
|
| 433 |
- // bucket. For best results, this should be close to a bucket |
|
| 434 |
- // boundary. This is usually the case if picking a power of two. If |
|
| 432 |
+ // NativeHistogramZeroThreshold are accumulated into a “zero” bucket. |
|
| 433 |
+ // For best results, this should be close to a bucket boundary. This is |
|
| 434 |
+ // usually the case if picking a power of two. If |
|
| 435 | 435 |
// NativeHistogramZeroThreshold is left at zero, |
| 436 |
- // DefSparseBucketsZeroThreshold is used as the threshold. To configure |
|
| 437 |
- // a zero bucket with an actual threshold of zero (i.e. only |
|
| 436 |
+ // DefNativeHistogramZeroThreshold is used as the threshold. To |
|
| 437 |
+ // configure a zero bucket with an actual threshold of zero (i.e. only |
|
| 438 | 438 |
// observations of precisely zero will go into the zero bucket), set |
| 439 | 439 |
// NativeHistogramZeroThreshold to the NativeHistogramZeroThresholdZero |
| 440 | 440 |
// constant (or any negative float value). |
| ... | ... |
@@ -447,26 +447,46 @@ type HistogramOpts struct {
|
| 447 | 447 |
// Histogram are sufficiently wide-spread. In particular, this could be |
| 448 | 448 |
// used as a DoS attack vector. Where the observed values depend on |
| 449 | 449 |
// external inputs, it is highly recommended to set a |
| 450 |
- // NativeHistogramMaxBucketNumber.) Once the set |
|
| 450 |
+ // NativeHistogramMaxBucketNumber.) Once the set |
|
| 451 | 451 |
// NativeHistogramMaxBucketNumber is exceeded, the following strategy is |
| 452 |
- // enacted: First, if the last reset (or the creation) of the histogram |
|
| 453 |
- // is at least NativeHistogramMinResetDuration ago, then the whole |
|
| 454 |
- // histogram is reset to its initial state (including regular |
|
| 455 |
- // buckets). If less time has passed, or if |
|
| 456 |
- // NativeHistogramMinResetDuration is zero, no reset is |
|
| 457 |
- // performed. Instead, the zero threshold is increased sufficiently to |
|
| 458 |
- // reduce the number of buckets to or below |
|
| 459 |
- // NativeHistogramMaxBucketNumber, but not to more than |
|
| 460 |
- // NativeHistogramMaxZeroThreshold. Thus, if |
|
| 461 |
- // NativeHistogramMaxZeroThreshold is already at or below the current |
|
| 462 |
- // zero threshold, nothing happens at this step. After that, if the |
|
| 463 |
- // number of buckets still exceeds NativeHistogramMaxBucketNumber, the |
|
| 464 |
- // resolution of the histogram is reduced by doubling the width of the |
|
| 465 |
- // sparse buckets (up to a growth factor between one bucket to the next |
|
| 466 |
- // of 2^(2^4) = 65536, see above). |
|
| 452 |
+ // enacted: |
|
| 453 |
+ // - First, if the last reset (or the creation) of the histogram is at |
|
| 454 |
+ // least NativeHistogramMinResetDuration ago, then the whole |
|
| 455 |
+ // histogram is reset to its initial state (including regular |
|
| 456 |
+ // buckets). |
|
| 457 |
+ // - If less time has passed, or if NativeHistogramMinResetDuration is |
|
| 458 |
+ // zero, no reset is performed. Instead, the zero threshold is |
|
| 459 |
+ // increased sufficiently to reduce the number of buckets to or below |
|
| 460 |
+ // NativeHistogramMaxBucketNumber, but not to more than |
|
| 461 |
+ // NativeHistogramMaxZeroThreshold. Thus, if |
|
| 462 |
+ // NativeHistogramMaxZeroThreshold is already at or below the current |
|
| 463 |
+ // zero threshold, nothing happens at this step. |
|
| 464 |
+ // - After that, if the number of buckets still exceeds |
|
| 465 |
+ // NativeHistogramMaxBucketNumber, the resolution of the histogram is |
|
| 466 |
+ // reduced by doubling the width of the sparse buckets (up to a |
|
| 467 |
+ // growth factor between one bucket to the next of 2^(2^4) = 65536, |
|
| 468 |
+ // see above). |
|
| 469 |
+ // - Any increased zero threshold or reduced resolution is reset back |
|
| 470 |
+ // to their original values once NativeHistogramMinResetDuration has |
|
| 471 |
+ // passed (since the last reset or the creation of the histogram). |
|
| 467 | 472 |
NativeHistogramMaxBucketNumber uint32 |
| 468 | 473 |
NativeHistogramMinResetDuration time.Duration |
| 469 | 474 |
NativeHistogramMaxZeroThreshold float64 |
| 475 |
+ |
|
| 476 |
+ // now is for testing purposes, by default it's time.Now. |
|
| 477 |
+ now func() time.Time |
|
| 478 |
+} |
|
| 479 |
+ |
|
| 480 |
+// HistogramVecOpts bundles the options to create a HistogramVec metric. |
|
| 481 |
+// It is mandatory to set HistogramOpts, see there for mandatory fields. VariableLabels |
|
| 482 |
+// is optional and can safely be left to its default value. |
|
| 483 |
+type HistogramVecOpts struct {
|
|
| 484 |
+ HistogramOpts |
|
| 485 |
+ |
|
| 486 |
+ // VariableLabels are used to partition the metric vector by the given set |
|
| 487 |
+ // of labels. Each label value will be constrained with the optional Constraint |
|
| 488 |
+ // function, if provided. |
|
| 489 |
+ VariableLabels ConstrainableLabels |
|
| 470 | 490 |
} |
| 471 | 491 |
|
| 472 | 492 |
// NewHistogram creates a new Histogram based on the provided HistogramOpts. It |
| ... | ... |
@@ -488,11 +508,11 @@ func NewHistogram(opts HistogramOpts) Histogram {
|
| 488 | 488 |
} |
| 489 | 489 |
|
| 490 | 490 |
func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram {
|
| 491 |
- if len(desc.variableLabels) != len(labelValues) {
|
|
| 492 |
- panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) |
|
| 491 |
+ if len(desc.variableLabels.names) != len(labelValues) {
|
|
| 492 |
+ panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, labelValues)) |
|
| 493 | 493 |
} |
| 494 | 494 |
|
| 495 |
- for _, n := range desc.variableLabels {
|
|
| 495 |
+ for _, n := range desc.variableLabels.names {
|
|
| 496 | 496 |
if n == bucketLabel {
|
| 497 | 497 |
panic(errBucketLabelNotAllowed) |
| 498 | 498 |
} |
| ... | ... |
@@ -503,6 +523,10 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr |
| 503 | 503 |
} |
| 504 | 504 |
} |
| 505 | 505 |
|
| 506 |
+ if opts.now == nil {
|
|
| 507 |
+ opts.now = time.Now |
|
| 508 |
+ } |
|
| 509 |
+ |
|
| 506 | 510 |
h := &histogram{
|
| 507 | 511 |
desc: desc, |
| 508 | 512 |
upperBounds: opts.Buckets, |
| ... | ... |
@@ -510,8 +534,8 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr |
| 510 | 510 |
nativeHistogramMaxBuckets: opts.NativeHistogramMaxBucketNumber, |
| 511 | 511 |
nativeHistogramMaxZeroThreshold: opts.NativeHistogramMaxZeroThreshold, |
| 512 | 512 |
nativeHistogramMinResetDuration: opts.NativeHistogramMinResetDuration, |
| 513 |
- lastResetTime: time.Now(), |
|
| 514 |
- now: time.Now, |
|
| 513 |
+ lastResetTime: opts.now(), |
|
| 514 |
+ now: opts.now, |
|
| 515 | 515 |
} |
| 516 | 516 |
if len(h.upperBounds) == 0 && opts.NativeHistogramBucketFactor <= 1 {
|
| 517 | 517 |
h.upperBounds = DefBuckets |
| ... | ... |
@@ -544,16 +568,12 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr |
| 544 | 544 |
} |
| 545 | 545 |
// Finally we know the final length of h.upperBounds and can make buckets |
| 546 | 546 |
// for both counts as well as exemplars: |
| 547 |
- h.counts[0] = &histogramCounts{
|
|
| 548 |
- buckets: make([]uint64, len(h.upperBounds)), |
|
| 549 |
- nativeHistogramZeroThresholdBits: math.Float64bits(h.nativeHistogramZeroThreshold), |
|
| 550 |
- nativeHistogramSchema: h.nativeHistogramSchema, |
|
| 551 |
- } |
|
| 552 |
- h.counts[1] = &histogramCounts{
|
|
| 553 |
- buckets: make([]uint64, len(h.upperBounds)), |
|
| 554 |
- nativeHistogramZeroThresholdBits: math.Float64bits(h.nativeHistogramZeroThreshold), |
|
| 555 |
- nativeHistogramSchema: h.nativeHistogramSchema, |
|
| 556 |
- } |
|
| 547 |
+ h.counts[0] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))}
|
|
| 548 |
+ atomic.StoreUint64(&h.counts[0].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) |
|
| 549 |
+ atomic.StoreInt32(&h.counts[0].nativeHistogramSchema, h.nativeHistogramSchema) |
|
| 550 |
+ h.counts[1] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))}
|
|
| 551 |
+ atomic.StoreUint64(&h.counts[1].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) |
|
| 552 |
+ atomic.StoreInt32(&h.counts[1].nativeHistogramSchema, h.nativeHistogramSchema) |
|
| 557 | 553 |
h.exemplars = make([]atomic.Value, len(h.upperBounds)+1) |
| 558 | 554 |
|
| 559 | 555 |
h.init(h) // Init self-collection. |
| ... | ... |
@@ -632,8 +652,8 @@ func (hc *histogramCounts) observe(v float64, bucket int, doSparse bool) {
|
| 632 | 632 |
if frac == 0.5 {
|
| 633 | 633 |
key-- |
| 634 | 634 |
} |
| 635 |
- div := 1 << -schema |
|
| 636 |
- key = (key + div - 1) / div |
|
| 635 |
+ offset := (1 << -schema) - 1 |
|
| 636 |
+ key = (key + offset) >> -schema |
|
| 637 | 637 |
} |
| 638 | 638 |
if isInf {
|
| 639 | 639 |
key++ |
| ... | ... |
@@ -694,9 +714,11 @@ type histogram struct {
|
| 694 | 694 |
nativeHistogramMaxZeroThreshold float64 |
| 695 | 695 |
nativeHistogramMaxBuckets uint32 |
| 696 | 696 |
nativeHistogramMinResetDuration time.Duration |
| 697 |
- lastResetTime time.Time // Protected by mtx. |
|
| 697 |
+ // lastResetTime is protected by mtx. It is also used as created timestamp. |
|
| 698 |
+ lastResetTime time.Time |
|
| 698 | 699 |
|
| 699 |
- now func() time.Time // To mock out time.Now() for testing. |
|
| 700 |
+ // now is for testing purposes, by default it's time.Now. |
|
| 701 |
+ now func() time.Time |
|
| 700 | 702 |
} |
| 701 | 703 |
|
| 702 | 704 |
func (h *histogram) Desc() *Desc {
|
| ... | ... |
@@ -735,9 +757,10 @@ func (h *histogram) Write(out *dto.Metric) error {
|
| 735 | 735 |
waitForCooldown(count, coldCounts) |
| 736 | 736 |
|
| 737 | 737 |
his := &dto.Histogram{
|
| 738 |
- Bucket: make([]*dto.Bucket, len(h.upperBounds)), |
|
| 739 |
- SampleCount: proto.Uint64(count), |
|
| 740 |
- SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), |
|
| 738 |
+ Bucket: make([]*dto.Bucket, len(h.upperBounds)), |
|
| 739 |
+ SampleCount: proto.Uint64(count), |
|
| 740 |
+ SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), |
|
| 741 |
+ CreatedTimestamp: timestamppb.New(h.lastResetTime), |
|
| 741 | 742 |
} |
| 742 | 743 |
out.Histogram = his |
| 743 | 744 |
out.Label = h.labelPairs |
| ... | ... |
@@ -775,6 +798,16 @@ func (h *histogram) Write(out *dto.Metric) error {
|
| 775 | 775 |
his.ZeroCount = proto.Uint64(zeroBucket) |
| 776 | 776 |
his.NegativeSpan, his.NegativeDelta = makeBuckets(&coldCounts.nativeHistogramBucketsNegative) |
| 777 | 777 |
his.PositiveSpan, his.PositiveDelta = makeBuckets(&coldCounts.nativeHistogramBucketsPositive) |
| 778 |
+ |
|
| 779 |
+ // Add a no-op span to a histogram without observations and with |
|
| 780 |
+ // a zero threshold of zero. Otherwise, a native histogram would |
|
| 781 |
+ // look like a classic histogram to scrapers. |
|
| 782 |
+ if *his.ZeroThreshold == 0 && *his.ZeroCount == 0 && len(his.PositiveSpan) == 0 && len(his.NegativeSpan) == 0 {
|
|
| 783 |
+ his.PositiveSpan = []*dto.BucketSpan{{
|
|
| 784 |
+ Offset: proto.Int32(0), |
|
| 785 |
+ Length: proto.Uint32(0), |
|
| 786 |
+ }} |
|
| 787 |
+ } |
|
| 778 | 788 |
} |
| 779 | 789 |
addAndResetCounts(hotCounts, coldCounts) |
| 780 | 790 |
return nil |
| ... | ... |
@@ -810,7 +843,7 @@ func (h *histogram) observe(v float64, bucket int) {
|
| 810 | 810 |
} |
| 811 | 811 |
} |
| 812 | 812 |
|
| 813 |
-// limitSparsebuckets applies a strategy to limit the number of populated sparse |
|
| 813 |
+// limitBuckets applies a strategy to limit the number of populated sparse |
|
| 814 | 814 |
// buckets. It's generally best effort, and there are situations where the |
| 815 | 815 |
// number can go higher (if even the lowest resolution isn't enough to reduce |
| 816 | 816 |
// the number sufficiently, or if the provided counts aren't fully updated yet |
| ... | ... |
@@ -847,20 +880,23 @@ func (h *histogram) limitBuckets(counts *histogramCounts, value float64, bucket |
| 847 | 847 |
h.doubleBucketWidth(hotCounts, coldCounts) |
| 848 | 848 |
} |
| 849 | 849 |
|
| 850 |
-// maybeReset resests the whole histogram if at least h.nativeHistogramMinResetDuration |
|
| 850 |
+// maybeReset resets the whole histogram if at least h.nativeHistogramMinResetDuration |
|
| 851 | 851 |
// has been passed. It returns true if the histogram has been reset. The caller |
| 852 | 852 |
// must have locked h.mtx. |
| 853 |
-func (h *histogram) maybeReset(hot, cold *histogramCounts, coldIdx uint64, value float64, bucket int) bool {
|
|
| 853 |
+func (h *histogram) maybeReset( |
|
| 854 |
+ hot, cold *histogramCounts, coldIdx uint64, value float64, bucket int, |
|
| 855 |
+) bool {
|
|
| 854 | 856 |
// We are using the possibly mocked h.now() rather than |
| 855 | 857 |
// time.Since(h.lastResetTime) to enable testing. |
| 856 |
- if h.nativeHistogramMinResetDuration == 0 || h.now().Sub(h.lastResetTime) < h.nativeHistogramMinResetDuration {
|
|
| 858 |
+ if h.nativeHistogramMinResetDuration == 0 || |
|
| 859 |
+ h.now().Sub(h.lastResetTime) < h.nativeHistogramMinResetDuration {
|
|
| 857 | 860 |
return false |
| 858 | 861 |
} |
| 859 | 862 |
// Completely reset coldCounts. |
| 860 | 863 |
h.resetCounts(cold) |
| 861 | 864 |
// Repeat the latest observation to not lose it completely. |
| 862 | 865 |
cold.observe(value, bucket, true) |
| 863 |
- // Make coldCounts the new hot counts while ressetting countAndHotIdx. |
|
| 866 |
+ // Make coldCounts the new hot counts while resetting countAndHotIdx. |
|
| 864 | 867 |
n := atomic.SwapUint64(&h.countAndHotIdx, (coldIdx<<63)+1) |
| 865 | 868 |
count := n & ((1 << 63) - 1) |
| 866 | 869 |
waitForCooldown(count, hot) |
| ... | ... |
@@ -1034,15 +1070,23 @@ type HistogramVec struct {
|
| 1034 | 1034 |
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and |
| 1035 | 1035 |
// partitioned by the given label names. |
| 1036 | 1036 |
func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
| 1037 |
- desc := NewDesc( |
|
| 1037 |
+ return V2.NewHistogramVec(HistogramVecOpts{
|
|
| 1038 |
+ HistogramOpts: opts, |
|
| 1039 |
+ VariableLabels: UnconstrainedLabels(labelNames), |
|
| 1040 |
+ }) |
|
| 1041 |
+} |
|
| 1042 |
+ |
|
| 1043 |
+// NewHistogramVec creates a new HistogramVec based on the provided HistogramVecOpts. |
|
| 1044 |
+func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec {
|
|
| 1045 |
+ desc := V2.NewDesc( |
|
| 1038 | 1046 |
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), |
| 1039 | 1047 |
opts.Help, |
| 1040 |
- labelNames, |
|
| 1048 |
+ opts.VariableLabels, |
|
| 1041 | 1049 |
opts.ConstLabels, |
| 1042 | 1050 |
) |
| 1043 | 1051 |
return &HistogramVec{
|
| 1044 | 1052 |
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
| 1045 |
- return newHistogram(desc, opts, lvs...) |
|
| 1053 |
+ return newHistogram(desc, opts.HistogramOpts, lvs...) |
|
| 1046 | 1054 |
}), |
| 1047 | 1055 |
} |
| 1048 | 1056 |
} |
| ... | ... |
@@ -1161,6 +1205,7 @@ type constHistogram struct {
|
| 1161 | 1161 |
sum float64 |
| 1162 | 1162 |
buckets map[float64]uint64 |
| 1163 | 1163 |
labelPairs []*dto.LabelPair |
| 1164 |
+ createdTs *timestamppb.Timestamp |
|
| 1164 | 1165 |
} |
| 1165 | 1166 |
|
| 1166 | 1167 |
func (h *constHistogram) Desc() *Desc {
|
| ... | ... |
@@ -1168,7 +1213,9 @@ func (h *constHistogram) Desc() *Desc {
|
| 1168 | 1168 |
} |
| 1169 | 1169 |
|
| 1170 | 1170 |
func (h *constHistogram) Write(out *dto.Metric) error {
|
| 1171 |
- his := &dto.Histogram{}
|
|
| 1171 |
+ his := &dto.Histogram{
|
|
| 1172 |
+ CreatedTimestamp: h.createdTs, |
|
| 1173 |
+ } |
|
| 1172 | 1174 |
|
| 1173 | 1175 |
buckets := make([]*dto.Bucket, 0, len(h.buckets)) |
| 1174 | 1176 |
|
| ... | ... |
@@ -1215,7 +1262,7 @@ func NewConstHistogram( |
| 1215 | 1215 |
if desc.err != nil {
|
| 1216 | 1216 |
return nil, desc.err |
| 1217 | 1217 |
} |
| 1218 |
- if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
|
| 1218 |
+ if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
|
| 1219 | 1219 |
return nil, err |
| 1220 | 1220 |
} |
| 1221 | 1221 |
return &constHistogram{
|
| ... | ... |
@@ -1309,7 +1356,7 @@ func makeBuckets(buckets *sync.Map) ([]*dto.BucketSpan, []int64) {
|
| 1309 | 1309 |
// Multiple spans with only small gaps in between are probably |
| 1310 | 1310 |
// encoded more efficiently as one larger span with a few empty |
| 1311 | 1311 |
// buckets. Needs some research to find the sweet spot. For now, |
| 1312 |
- // we assume that gaps of one ore two buckets should not create |
|
| 1312 |
+ // we assume that gaps of one or two buckets should not create |
|
| 1313 | 1313 |
// a new span. |
| 1314 | 1314 |
iDelta := int32(i - nextI) |
| 1315 | 1315 |
if n == 0 || iDelta > 2 {
|
| ... | ... |
@@ -14,7 +14,7 @@ |
| 14 | 14 |
// It provides tools to compare sequences of strings and generate textual diffs. |
| 15 | 15 |
// |
| 16 | 16 |
// Maintaining `GetUnifiedDiffString` here because original repository |
| 17 |
-// (https://github.com/pmezard/go-difflib) is no loger maintained. |
|
| 17 |
+// (https://github.com/pmezard/go-difflib) is no longer maintained. |
|
| 18 | 18 |
package internal |
| 19 | 19 |
|
| 20 | 20 |
import ( |
| ... | ... |
@@ -32,6 +32,104 @@ import ( |
| 32 | 32 |
// create a Desc. |
| 33 | 33 |
type Labels map[string]string |
| 34 | 34 |
|
| 35 |
+// LabelConstraint normalizes label values. |
|
| 36 |
+type LabelConstraint func(string) string |
|
| 37 |
+ |
|
| 38 |
+// ConstrainedLabels represents a label name and its constrain function |
|
| 39 |
+// to normalize label values. This type is commonly used when constructing |
|
| 40 |
+// metric vector Collectors. |
|
| 41 |
+type ConstrainedLabel struct {
|
|
| 42 |
+ Name string |
|
| 43 |
+ Constraint LabelConstraint |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+// ConstrainableLabels is an interface that allows creating of labels that can |
|
| 47 |
+// be optionally constrained. |
|
| 48 |
+// |
|
| 49 |
+// prometheus.V2().NewCounterVec(CounterVecOpts{
|
|
| 50 |
+// CounterOpts: {...}, // Usual CounterOpts fields
|
|
| 51 |
+// VariableLabels: []ConstrainedLabels{
|
|
| 52 |
+// {Name: "A"},
|
|
| 53 |
+// {Name: "B", Constraint: func(v string) string { ... }},
|
|
| 54 |
+// }, |
|
| 55 |
+// }) |
|
| 56 |
+type ConstrainableLabels interface {
|
|
| 57 |
+ compile() *compiledLabels |
|
| 58 |
+ labelNames() []string |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// ConstrainedLabels represents a collection of label name -> constrain function |
|
| 62 |
+// to normalize label values. This type is commonly used when constructing |
|
| 63 |
+// metric vector Collectors. |
|
| 64 |
+type ConstrainedLabels []ConstrainedLabel |
|
| 65 |
+ |
|
| 66 |
+func (cls ConstrainedLabels) compile() *compiledLabels {
|
|
| 67 |
+ compiled := &compiledLabels{
|
|
| 68 |
+ names: make([]string, len(cls)), |
|
| 69 |
+ labelConstraints: map[string]LabelConstraint{},
|
|
| 70 |
+ } |
|
| 71 |
+ |
|
| 72 |
+ for i, label := range cls {
|
|
| 73 |
+ compiled.names[i] = label.Name |
|
| 74 |
+ if label.Constraint != nil {
|
|
| 75 |
+ compiled.labelConstraints[label.Name] = label.Constraint |
|
| 76 |
+ } |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ return compiled |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func (cls ConstrainedLabels) labelNames() []string {
|
|
| 83 |
+ names := make([]string, len(cls)) |
|
| 84 |
+ for i, label := range cls {
|
|
| 85 |
+ names[i] = label.Name |
|
| 86 |
+ } |
|
| 87 |
+ return names |
|
| 88 |
+} |
|
| 89 |
+ |
|
| 90 |
+// UnconstrainedLabels represents collection of label without any constraint on |
|
| 91 |
+// their value. Thus, it is simply a collection of label names. |
|
| 92 |
+// |
|
| 93 |
+// UnconstrainedLabels([]string{ "A", "B" })
|
|
| 94 |
+// |
|
| 95 |
+// is equivalent to |
|
| 96 |
+// |
|
| 97 |
+// ConstrainedLabels {
|
|
| 98 |
+// { Name: "A" },
|
|
| 99 |
+// { Name: "B" },
|
|
| 100 |
+// } |
|
| 101 |
+type UnconstrainedLabels []string |
|
| 102 |
+ |
|
| 103 |
+func (uls UnconstrainedLabels) compile() *compiledLabels {
|
|
| 104 |
+ return &compiledLabels{
|
|
| 105 |
+ names: uls, |
|
| 106 |
+ } |
|
| 107 |
+} |
|
| 108 |
+ |
|
| 109 |
+func (uls UnconstrainedLabels) labelNames() []string {
|
|
| 110 |
+ return uls |
|
| 111 |
+} |
|
| 112 |
+ |
|
| 113 |
+type compiledLabels struct {
|
|
| 114 |
+ names []string |
|
| 115 |
+ labelConstraints map[string]LabelConstraint |
|
| 116 |
+} |
|
| 117 |
+ |
|
| 118 |
+func (cls *compiledLabels) compile() *compiledLabels {
|
|
| 119 |
+ return cls |
|
| 120 |
+} |
|
| 121 |
+ |
|
| 122 |
+func (cls *compiledLabels) labelNames() []string {
|
|
| 123 |
+ return cls.names |
|
| 124 |
+} |
|
| 125 |
+ |
|
| 126 |
+func (cls *compiledLabels) constrain(labelName, value string) string {
|
|
| 127 |
+ if fn, ok := cls.labelConstraints[labelName]; ok && fn != nil {
|
|
| 128 |
+ return fn(value) |
|
| 129 |
+ } |
|
| 130 |
+ return value |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 35 | 133 |
// reservedLabelPrefix is a prefix which is not legal in user-supplied |
| 36 | 134 |
// label names. |
| 37 | 135 |
const reservedLabelPrefix = "__" |
| ... | ... |
@@ -20,11 +20,9 @@ import ( |
| 20 | 20 |
"strings" |
| 21 | 21 |
"time" |
| 22 | 22 |
|
| 23 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 24 |
- "github.com/golang/protobuf/proto" |
|
| 25 |
- "github.com/prometheus/common/model" |
|
| 26 |
- |
|
| 27 | 23 |
dto "github.com/prometheus/client_model/go" |
| 24 |
+ "github.com/prometheus/common/model" |
|
| 25 |
+ "google.golang.org/protobuf/proto" |
|
| 28 | 26 |
) |
| 29 | 27 |
|
| 30 | 28 |
var separatorByteSlice = []byte{model.SeparatorByte} // For convenient use with xxhash.
|
| ... | ... |
@@ -94,6 +92,9 @@ type Opts struct {
|
| 94 | 94 |
// machine_role metric). See also |
| 95 | 95 |
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels |
| 96 | 96 |
ConstLabels Labels |
| 97 |
+ |
|
| 98 |
+ // now is for testing purposes, by default it's time.Now. |
|
| 99 |
+ now func() time.Time |
|
| 97 | 100 |
} |
| 98 | 101 |
|
| 99 | 102 |
// BuildFQName joins the given three name components by "_". Empty name |
| ... | ... |
@@ -37,6 +37,7 @@ import ( |
| 37 | 37 |
"fmt" |
| 38 | 38 |
"io" |
| 39 | 39 |
"net/http" |
| 40 |
+ "strconv" |
|
| 40 | 41 |
"strings" |
| 41 | 42 |
"sync" |
| 42 | 43 |
"time" |
| ... | ... |
@@ -47,9 +48,10 @@ import ( |
| 47 | 47 |
) |
| 48 | 48 |
|
| 49 | 49 |
const ( |
| 50 |
- contentTypeHeader = "Content-Type" |
|
| 51 |
- contentEncodingHeader = "Content-Encoding" |
|
| 52 |
- acceptEncodingHeader = "Accept-Encoding" |
|
| 50 |
+ contentTypeHeader = "Content-Type" |
|
| 51 |
+ contentEncodingHeader = "Content-Encoding" |
|
| 52 |
+ acceptEncodingHeader = "Accept-Encoding" |
|
| 53 |
+ processStartTimeHeader = "Process-Start-Time-Unix" |
|
| 53 | 54 |
) |
| 54 | 55 |
|
| 55 | 56 |
var gzipPool = sync.Pool{
|
| ... | ... |
@@ -121,6 +123,9 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO |
| 121 | 121 |
} |
| 122 | 122 |
|
| 123 | 123 |
h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
|
| 124 |
+ if !opts.ProcessStartTime.IsZero() {
|
|
| 125 |
+ rsp.Header().Set(processStartTimeHeader, strconv.FormatInt(opts.ProcessStartTime.Unix(), 10)) |
|
| 126 |
+ } |
|
| 124 | 127 |
if inFlightSem != nil {
|
| 125 | 128 |
select {
|
| 126 | 129 |
case inFlightSem <- struct{}{}: // All good, carry on.
|
| ... | ... |
@@ -366,6 +371,14 @@ type HandlerOpts struct {
|
| 366 | 366 |
// (which changes the identity of the resulting series on the Prometheus |
| 367 | 367 |
// server). |
| 368 | 368 |
EnableOpenMetrics bool |
| 369 |
+ // ProcessStartTime allows setting process start timevalue that will be exposed |
|
| 370 |
+ // with "Process-Start-Time-Unix" response header along with the metrics |
|
| 371 |
+ // payload. This allow callers to have efficient transformations to cumulative |
|
| 372 |
+ // counters (e.g. OpenTelemetry) or generally _created timestamp estimation per |
|
| 373 |
+ // scrape target. |
|
| 374 |
+ // NOTE: This feature is experimental and not covered by OpenMetrics or Prometheus |
|
| 375 |
+ // exposition format. |
|
| 376 |
+ ProcessStartTime time.Time |
|
| 369 | 377 |
} |
| 370 | 378 |
|
| 371 | 379 |
// gzipAccepted returns whether the client will accept gzip-encoded content. |
| ... | ... |
@@ -68,16 +68,17 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou |
| 68 | 68 |
o.apply(rtOpts) |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
- code, method := checkLabels(counter) |
|
| 71 |
+ // Curry the counter with dynamic labels before checking the remaining labels. |
|
| 72 |
+ code, method := checkLabels(counter.MustCurryWith(rtOpts.emptyDynamicLabels())) |
|
| 72 | 73 |
|
| 73 | 74 |
return func(r *http.Request) (*http.Response, error) {
|
| 74 | 75 |
resp, err := next.RoundTrip(r) |
| 75 | 76 |
if err == nil {
|
| 76 |
- addWithExemplar( |
|
| 77 |
- counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)), |
|
| 78 |
- 1, |
|
| 79 |
- rtOpts.getExemplarFn(r.Context()), |
|
| 80 |
- ) |
|
| 77 |
+ l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) |
|
| 78 |
+ for label, resolve := range rtOpts.extraLabelsFromCtx {
|
|
| 79 |
+ l[label] = resolve(resp.Request.Context()) |
|
| 80 |
+ } |
|
| 81 |
+ addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r.Context())) |
|
| 81 | 82 |
} |
| 82 | 83 |
return resp, err |
| 83 | 84 |
} |
| ... | ... |
@@ -110,17 +111,18 @@ func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundT |
| 110 | 110 |
o.apply(rtOpts) |
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 |
- code, method := checkLabels(obs) |
|
| 113 |
+ // Curry the observer with dynamic labels before checking the remaining labels. |
|
| 114 |
+ code, method := checkLabels(obs.MustCurryWith(rtOpts.emptyDynamicLabels())) |
|
| 114 | 115 |
|
| 115 | 116 |
return func(r *http.Request) (*http.Response, error) {
|
| 116 | 117 |
start := time.Now() |
| 117 | 118 |
resp, err := next.RoundTrip(r) |
| 118 | 119 |
if err == nil {
|
| 119 |
- observeWithExemplar( |
|
| 120 |
- obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)), |
|
| 121 |
- time.Since(start).Seconds(), |
|
| 122 |
- rtOpts.getExemplarFn(r.Context()), |
|
| 123 |
- ) |
|
| 120 |
+ l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) |
|
| 121 |
+ for label, resolve := range rtOpts.extraLabelsFromCtx {
|
|
| 122 |
+ l[label] = resolve(resp.Request.Context()) |
|
| 123 |
+ } |
|
| 124 |
+ observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r.Context())) |
|
| 124 | 125 |
} |
| 125 | 126 |
return resp, err |
| 126 | 127 |
} |
| ... | ... |
@@ -87,7 +87,8 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op |
| 87 | 87 |
o.apply(hOpts) |
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 |
- code, method := checkLabels(obs) |
|
| 90 |
+ // Curry the observer with dynamic labels before checking the remaining labels. |
|
| 91 |
+ code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) |
|
| 91 | 92 |
|
| 92 | 93 |
if code {
|
| 93 | 94 |
return func(w http.ResponseWriter, r *http.Request) {
|
| ... | ... |
@@ -95,23 +96,22 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op |
| 95 | 95 |
d := newDelegator(w, nil) |
| 96 | 96 |
next.ServeHTTP(d, r) |
| 97 | 97 |
|
| 98 |
- observeWithExemplar( |
|
| 99 |
- obs.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)), |
|
| 100 |
- time.Since(now).Seconds(), |
|
| 101 |
- hOpts.getExemplarFn(r.Context()), |
|
| 102 |
- ) |
|
| 98 |
+ l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) |
|
| 99 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 100 |
+ l[label] = resolve(r.Context()) |
|
| 101 |
+ } |
|
| 102 |
+ observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) |
|
| 103 | 103 |
} |
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 | 106 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 107 | 107 |
now := time.Now() |
| 108 | 108 |
next.ServeHTTP(w, r) |
| 109 |
- |
|
| 110 |
- observeWithExemplar( |
|
| 111 |
- obs.With(labels(code, method, r.Method, 0, hOpts.extraMethods...)), |
|
| 112 |
- time.Since(now).Seconds(), |
|
| 113 |
- hOpts.getExemplarFn(r.Context()), |
|
| 114 |
- ) |
|
| 109 |
+ l := labels(code, method, r.Method, 0, hOpts.extraMethods...) |
|
| 110 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 111 |
+ l[label] = resolve(r.Context()) |
|
| 112 |
+ } |
|
| 113 |
+ observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) |
|
| 115 | 114 |
} |
| 116 | 115 |
} |
| 117 | 116 |
|
| ... | ... |
@@ -138,28 +138,30 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, |
| 138 | 138 |
o.apply(hOpts) |
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 |
- code, method := checkLabels(counter) |
|
| 141 |
+ // Curry the counter with dynamic labels before checking the remaining labels. |
|
| 142 |
+ code, method := checkLabels(counter.MustCurryWith(hOpts.emptyDynamicLabels())) |
|
| 142 | 143 |
|
| 143 | 144 |
if code {
|
| 144 | 145 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 145 | 146 |
d := newDelegator(w, nil) |
| 146 | 147 |
next.ServeHTTP(d, r) |
| 147 | 148 |
|
| 148 |
- addWithExemplar( |
|
| 149 |
- counter.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)), |
|
| 150 |
- 1, |
|
| 151 |
- hOpts.getExemplarFn(r.Context()), |
|
| 152 |
- ) |
|
| 149 |
+ l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) |
|
| 150 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 151 |
+ l[label] = resolve(r.Context()) |
|
| 152 |
+ } |
|
| 153 |
+ addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) |
|
| 153 | 154 |
} |
| 154 | 155 |
} |
| 155 | 156 |
|
| 156 | 157 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 157 | 158 |
next.ServeHTTP(w, r) |
| 158 |
- addWithExemplar( |
|
| 159 |
- counter.With(labels(code, method, r.Method, 0, hOpts.extraMethods...)), |
|
| 160 |
- 1, |
|
| 161 |
- hOpts.getExemplarFn(r.Context()), |
|
| 162 |
- ) |
|
| 159 |
+ |
|
| 160 |
+ l := labels(code, method, r.Method, 0, hOpts.extraMethods...) |
|
| 161 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 162 |
+ l[label] = resolve(r.Context()) |
|
| 163 |
+ } |
|
| 164 |
+ addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) |
|
| 163 | 165 |
} |
| 164 | 166 |
} |
| 165 | 167 |
|
| ... | ... |
@@ -191,16 +193,17 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha |
| 191 | 191 |
o.apply(hOpts) |
| 192 | 192 |
} |
| 193 | 193 |
|
| 194 |
- code, method := checkLabels(obs) |
|
| 194 |
+ // Curry the observer with dynamic labels before checking the remaining labels. |
|
| 195 |
+ code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) |
|
| 195 | 196 |
|
| 196 | 197 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 197 | 198 |
now := time.Now() |
| 198 | 199 |
d := newDelegator(w, func(status int) {
|
| 199 |
- observeWithExemplar( |
|
| 200 |
- obs.With(labels(code, method, r.Method, status, hOpts.extraMethods...)), |
|
| 201 |
- time.Since(now).Seconds(), |
|
| 202 |
- hOpts.getExemplarFn(r.Context()), |
|
| 203 |
- ) |
|
| 200 |
+ l := labels(code, method, r.Method, status, hOpts.extraMethods...) |
|
| 201 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 202 |
+ l[label] = resolve(r.Context()) |
|
| 203 |
+ } |
|
| 204 |
+ observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) |
|
| 204 | 205 |
}) |
| 205 | 206 |
next.ServeHTTP(d, r) |
| 206 | 207 |
} |
| ... | ... |
@@ -231,28 +234,32 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, |
| 231 | 231 |
o.apply(hOpts) |
| 232 | 232 |
} |
| 233 | 233 |
|
| 234 |
- code, method := checkLabels(obs) |
|
| 234 |
+ // Curry the observer with dynamic labels before checking the remaining labels. |
|
| 235 |
+ code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) |
|
| 236 |
+ |
|
| 235 | 237 |
if code {
|
| 236 | 238 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 237 | 239 |
d := newDelegator(w, nil) |
| 238 | 240 |
next.ServeHTTP(d, r) |
| 239 | 241 |
size := computeApproximateRequestSize(r) |
| 240 |
- observeWithExemplar( |
|
| 241 |
- obs.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)), |
|
| 242 |
- float64(size), |
|
| 243 |
- hOpts.getExemplarFn(r.Context()), |
|
| 244 |
- ) |
|
| 242 |
+ |
|
| 243 |
+ l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) |
|
| 244 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 245 |
+ l[label] = resolve(r.Context()) |
|
| 246 |
+ } |
|
| 247 |
+ observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) |
|
| 245 | 248 |
} |
| 246 | 249 |
} |
| 247 | 250 |
|
| 248 | 251 |
return func(w http.ResponseWriter, r *http.Request) {
|
| 249 | 252 |
next.ServeHTTP(w, r) |
| 250 | 253 |
size := computeApproximateRequestSize(r) |
| 251 |
- observeWithExemplar( |
|
| 252 |
- obs.With(labels(code, method, r.Method, 0, hOpts.extraMethods...)), |
|
| 253 |
- float64(size), |
|
| 254 |
- hOpts.getExemplarFn(r.Context()), |
|
| 255 |
- ) |
|
| 254 |
+ |
|
| 255 |
+ l := labels(code, method, r.Method, 0, hOpts.extraMethods...) |
|
| 256 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 257 |
+ l[label] = resolve(r.Context()) |
|
| 258 |
+ } |
|
| 259 |
+ observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) |
|
| 256 | 260 |
} |
| 257 | 261 |
} |
| 258 | 262 |
|
| ... | ... |
@@ -281,16 +288,18 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler |
| 281 | 281 |
o.apply(hOpts) |
| 282 | 282 |
} |
| 283 | 283 |
|
| 284 |
- code, method := checkLabels(obs) |
|
| 284 |
+ // Curry the observer with dynamic labels before checking the remaining labels. |
|
| 285 |
+ code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) |
|
| 285 | 286 |
|
| 286 | 287 |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
| 287 | 288 |
d := newDelegator(w, nil) |
| 288 | 289 |
next.ServeHTTP(d, r) |
| 289 |
- observeWithExemplar( |
|
| 290 |
- obs.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)), |
|
| 291 |
- float64(d.Written()), |
|
| 292 |
- hOpts.getExemplarFn(r.Context()), |
|
| 293 |
- ) |
|
| 290 |
+ |
|
| 291 |
+ l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) |
|
| 292 |
+ for label, resolve := range hOpts.extraLabelsFromCtx {
|
|
| 293 |
+ l[label] = resolve(r.Context()) |
|
| 294 |
+ } |
|
| 295 |
+ observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r.Context())) |
|
| 294 | 296 |
}) |
| 295 | 297 |
} |
| 296 | 298 |
|
| ... | ... |
@@ -380,15 +389,12 @@ func isLabelCurried(c prometheus.Collector, label string) bool {
|
| 380 | 380 |
return true |
| 381 | 381 |
} |
| 382 | 382 |
|
| 383 |
-// emptyLabels is a one-time allocation for non-partitioned metrics to avoid |
|
| 384 |
-// unnecessary allocations on each request. |
|
| 385 |
-var emptyLabels = prometheus.Labels{}
|
|
| 386 |
- |
|
| 387 | 383 |
func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels {
|
| 384 |
+ labels := prometheus.Labels{}
|
|
| 385 |
+ |
|
| 388 | 386 |
if !(code || method) {
|
| 389 |
- return emptyLabels |
|
| 387 |
+ return labels |
|
| 390 | 388 |
} |
| 391 |
- labels := prometheus.Labels{}
|
|
| 392 | 389 |
|
| 393 | 390 |
if code {
|
| 394 | 391 |
labels["code"] = sanitizeCode(status) |
| ... | ... |
@@ -24,14 +24,32 @@ type Option interface {
|
| 24 | 24 |
apply(*options) |
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 |
+// LabelValueFromCtx are used to compute the label value from request context. |
|
| 28 |
+// Context can be filled with values from request through middleware. |
|
| 29 |
+type LabelValueFromCtx func(ctx context.Context) string |
|
| 30 |
+ |
|
| 27 | 31 |
// options store options for both a handler or round tripper. |
| 28 | 32 |
type options struct {
|
| 29 |
- extraMethods []string |
|
| 30 |
- getExemplarFn func(requestCtx context.Context) prometheus.Labels |
|
| 33 |
+ extraMethods []string |
|
| 34 |
+ getExemplarFn func(requestCtx context.Context) prometheus.Labels |
|
| 35 |
+ extraLabelsFromCtx map[string]LabelValueFromCtx |
|
| 31 | 36 |
} |
| 32 | 37 |
|
| 33 | 38 |
func defaultOptions() *options {
|
| 34 |
- return &options{getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil }}
|
|
| 39 |
+ return &options{
|
|
| 40 |
+ getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil },
|
|
| 41 |
+ extraLabelsFromCtx: map[string]LabelValueFromCtx{},
|
|
| 42 |
+ } |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+func (o *options) emptyDynamicLabels() prometheus.Labels {
|
|
| 46 |
+ labels := prometheus.Labels{}
|
|
| 47 |
+ |
|
| 48 |
+ for label := range o.extraLabelsFromCtx {
|
|
| 49 |
+ labels[label] = "" |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ return labels |
|
| 35 | 53 |
} |
| 36 | 54 |
|
| 37 | 55 |
type optionApplyFunc func(*options) |
| ... | ... |
@@ -48,11 +66,19 @@ func WithExtraMethods(methods ...string) Option {
|
| 48 | 48 |
}) |
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 |
-// WithExemplarFromContext adds allows to put a hook to all counter and histogram metrics. |
|
| 52 |
-// If the hook function returns non-nil labels, exemplars will be added for that request, otherwise metric |
|
| 53 |
-// will get instrumented without exemplar. |
|
| 51 |
+// WithExemplarFromContext allows to inject function that will get exemplar from context that will be put to counter and histogram metrics. |
|
| 52 |
+// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but |
|
| 53 |
+// metric will continue to observe/increment. |
|
| 54 | 54 |
func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option {
|
| 55 | 55 |
return optionApplyFunc(func(o *options) {
|
| 56 | 56 |
o.getExemplarFn = getExemplarFn |
| 57 | 57 |
}) |
| 58 | 58 |
} |
| 59 |
+ |
|
| 60 |
+// WithLabelFromCtx registers a label for dynamic resolution with access to context. |
|
| 61 |
+// See the example for ExampleInstrumentHandlerWithLabelResolver for example usage |
|
| 62 |
+func WithLabelFromCtx(name string, valueFn LabelValueFromCtx) Option {
|
|
| 63 |
+ return optionApplyFunc(func(o *options) {
|
|
| 64 |
+ o.extraLabelsFromCtx[name] = valueFn |
|
| 65 |
+ }) |
|
| 66 |
+} |
| ... | ... |
@@ -21,18 +21,17 @@ import ( |
| 21 | 21 |
"path/filepath" |
| 22 | 22 |
"runtime" |
| 23 | 23 |
"sort" |
| 24 |
+ "strconv" |
|
| 24 | 25 |
"strings" |
| 25 | 26 |
"sync" |
| 26 | 27 |
"unicode/utf8" |
| 27 | 28 |
|
| 28 |
- "github.com/cespare/xxhash/v2" |
|
| 29 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 30 |
- "github.com/golang/protobuf/proto" |
|
| 31 |
- "github.com/prometheus/common/expfmt" |
|
| 29 |
+ "github.com/prometheus/client_golang/prometheus/internal" |
|
| 32 | 30 |
|
| 31 |
+ "github.com/cespare/xxhash/v2" |
|
| 33 | 32 |
dto "github.com/prometheus/client_model/go" |
| 34 |
- |
|
| 35 |
- "github.com/prometheus/client_golang/prometheus/internal" |
|
| 33 |
+ "github.com/prometheus/common/expfmt" |
|
| 34 |
+ "google.golang.org/protobuf/proto" |
|
| 36 | 35 |
) |
| 37 | 36 |
|
| 38 | 37 |
const ( |
| ... | ... |
@@ -549,7 +548,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
| 549 | 549 |
goroutineBudget-- |
| 550 | 550 |
runtime.Gosched() |
| 551 | 551 |
} |
| 552 |
- // Once both checkedMetricChan and uncheckdMetricChan are closed |
|
| 552 |
+ // Once both checkedMetricChan and uncheckedMetricChan are closed |
|
| 553 | 553 |
// and drained, the contraption above will nil out cmc and umc, |
| 554 | 554 |
// and then we can leave the collect loop here. |
| 555 | 555 |
if cmc == nil && umc == nil {
|
| ... | ... |
@@ -933,6 +932,10 @@ func checkMetricConsistency( |
| 933 | 933 |
h.WriteString(lp.GetValue()) |
| 934 | 934 |
h.Write(separatorByteSlice) |
| 935 | 935 |
} |
| 936 |
+ if dtoMetric.TimestampMs != nil {
|
|
| 937 |
+ h.WriteString(strconv.FormatInt(*(dtoMetric.TimestampMs), 10)) |
|
| 938 |
+ h.Write(separatorByteSlice) |
|
| 939 |
+ } |
|
| 936 | 940 |
hSum := h.Sum64() |
| 937 | 941 |
if _, exists := metricHashes[hSum]; exists {
|
| 938 | 942 |
return fmt.Errorf( |
| ... | ... |
@@ -960,7 +963,7 @@ func checkDescConsistency( |
| 960 | 960 |
// Is the desc consistent with the content of the metric? |
| 961 | 961 |
lpsFromDesc := make([]*dto.LabelPair, len(desc.constLabelPairs), len(dtoMetric.Label)) |
| 962 | 962 |
copy(lpsFromDesc, desc.constLabelPairs) |
| 963 |
- for _, l := range desc.variableLabels {
|
|
| 963 |
+ for _, l := range desc.variableLabels.names {
|
|
| 964 | 964 |
lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{
|
| 965 | 965 |
Name: proto.String(l), |
| 966 | 966 |
}) |
| ... | ... |
@@ -22,11 +22,11 @@ import ( |
| 22 | 22 |
"sync/atomic" |
| 23 | 23 |
"time" |
| 24 | 24 |
|
| 25 |
- "github.com/beorn7/perks/quantile" |
|
| 26 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 27 |
- "github.com/golang/protobuf/proto" |
|
| 28 |
- |
|
| 29 | 25 |
dto "github.com/prometheus/client_model/go" |
| 26 |
+ |
|
| 27 |
+ "github.com/beorn7/perks/quantile" |
|
| 28 |
+ "google.golang.org/protobuf/proto" |
|
| 29 |
+ "google.golang.org/protobuf/types/known/timestamppb" |
|
| 30 | 30 |
) |
| 31 | 31 |
|
| 32 | 32 |
// quantileLabel is used for the label that defines the quantile in a |
| ... | ... |
@@ -146,6 +146,21 @@ type SummaryOpts struct {
|
| 146 | 146 |
// is the internal buffer size of the underlying package |
| 147 | 147 |
// "github.com/bmizerany/perks/quantile"). |
| 148 | 148 |
BufCap uint32 |
| 149 |
+ |
|
| 150 |
+ // now is for testing purposes, by default it's time.Now. |
|
| 151 |
+ now func() time.Time |
|
| 152 |
+} |
|
| 153 |
+ |
|
| 154 |
+// SummaryVecOpts bundles the options to create a SummaryVec metric. |
|
| 155 |
+// It is mandatory to set SummaryOpts, see there for mandatory fields. VariableLabels |
|
| 156 |
+// is optional and can safely be left to its default value. |
|
| 157 |
+type SummaryVecOpts struct {
|
|
| 158 |
+ SummaryOpts |
|
| 159 |
+ |
|
| 160 |
+ // VariableLabels are used to partition the metric vector by the given set |
|
| 161 |
+ // of labels. Each label value will be constrained with the optional Constraint |
|
| 162 |
+ // function, if provided. |
|
| 163 |
+ VariableLabels ConstrainableLabels |
|
| 149 | 164 |
} |
| 150 | 165 |
|
| 151 | 166 |
// Problem with the sliding-window decay algorithm... The Merge method of |
| ... | ... |
@@ -177,11 +192,11 @@ func NewSummary(opts SummaryOpts) Summary {
|
| 177 | 177 |
} |
| 178 | 178 |
|
| 179 | 179 |
func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
| 180 |
- if len(desc.variableLabels) != len(labelValues) {
|
|
| 181 |
- panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) |
|
| 180 |
+ if len(desc.variableLabels.names) != len(labelValues) {
|
|
| 181 |
+ panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, labelValues)) |
|
| 182 | 182 |
} |
| 183 | 183 |
|
| 184 |
- for _, n := range desc.variableLabels {
|
|
| 184 |
+ for _, n := range desc.variableLabels.names {
|
|
| 185 | 185 |
if n == quantileLabel {
|
| 186 | 186 |
panic(errQuantileLabelNotAllowed) |
| 187 | 187 |
} |
| ... | ... |
@@ -211,6 +226,9 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
| 211 | 211 |
opts.BufCap = DefBufCap |
| 212 | 212 |
} |
| 213 | 213 |
|
| 214 |
+ if opts.now == nil {
|
|
| 215 |
+ opts.now = time.Now |
|
| 216 |
+ } |
|
| 214 | 217 |
if len(opts.Objectives) == 0 {
|
| 215 | 218 |
// Use the lock-free implementation of a Summary without objectives. |
| 216 | 219 |
s := &noObjectivesSummary{
|
| ... | ... |
@@ -219,6 +237,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
| 219 | 219 |
counts: [2]*summaryCounts{{}, {}},
|
| 220 | 220 |
} |
| 221 | 221 |
s.init(s) // Init self-collection. |
| 222 |
+ s.createdTs = timestamppb.New(opts.now()) |
|
| 222 | 223 |
return s |
| 223 | 224 |
} |
| 224 | 225 |
|
| ... | ... |
@@ -234,7 +253,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
| 234 | 234 |
coldBuf: make([]float64, 0, opts.BufCap), |
| 235 | 235 |
streamDuration: opts.MaxAge / time.Duration(opts.AgeBuckets), |
| 236 | 236 |
} |
| 237 |
- s.headStreamExpTime = time.Now().Add(s.streamDuration) |
|
| 237 |
+ s.headStreamExpTime = opts.now().Add(s.streamDuration) |
|
| 238 | 238 |
s.hotBufExpTime = s.headStreamExpTime |
| 239 | 239 |
|
| 240 | 240 |
for i := uint32(0); i < opts.AgeBuckets; i++ {
|
| ... | ... |
@@ -248,6 +267,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
| 248 | 248 |
sort.Float64s(s.sortedObjectives) |
| 249 | 249 |
|
| 250 | 250 |
s.init(s) // Init self-collection. |
| 251 |
+ s.createdTs = timestamppb.New(opts.now()) |
|
| 251 | 252 |
return s |
| 252 | 253 |
} |
| 253 | 254 |
|
| ... | ... |
@@ -275,6 +295,8 @@ type summary struct {
|
| 275 | 275 |
headStream *quantile.Stream |
| 276 | 276 |
headStreamIdx int |
| 277 | 277 |
headStreamExpTime, hotBufExpTime time.Time |
| 278 |
+ |
|
| 279 |
+ createdTs *timestamppb.Timestamp |
|
| 278 | 280 |
} |
| 279 | 281 |
|
| 280 | 282 |
func (s *summary) Desc() *Desc {
|
| ... | ... |
@@ -296,7 +318,9 @@ func (s *summary) Observe(v float64) {
|
| 296 | 296 |
} |
| 297 | 297 |
|
| 298 | 298 |
func (s *summary) Write(out *dto.Metric) error {
|
| 299 |
- sum := &dto.Summary{}
|
|
| 299 |
+ sum := &dto.Summary{
|
|
| 300 |
+ CreatedTimestamp: s.createdTs, |
|
| 301 |
+ } |
|
| 300 | 302 |
qs := make([]*dto.Quantile, 0, len(s.objectives)) |
| 301 | 303 |
|
| 302 | 304 |
s.bufMtx.Lock() |
| ... | ... |
@@ -429,6 +453,8 @@ type noObjectivesSummary struct {
|
| 429 | 429 |
counts [2]*summaryCounts |
| 430 | 430 |
|
| 431 | 431 |
labelPairs []*dto.LabelPair |
| 432 |
+ |
|
| 433 |
+ createdTs *timestamppb.Timestamp |
|
| 432 | 434 |
} |
| 433 | 435 |
|
| 434 | 436 |
func (s *noObjectivesSummary) Desc() *Desc {
|
| ... | ... |
@@ -479,8 +505,9 @@ func (s *noObjectivesSummary) Write(out *dto.Metric) error {
|
| 479 | 479 |
} |
| 480 | 480 |
|
| 481 | 481 |
sum := &dto.Summary{
|
| 482 |
- SampleCount: proto.Uint64(count), |
|
| 483 |
- SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), |
|
| 482 |
+ SampleCount: proto.Uint64(count), |
|
| 483 |
+ SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), |
|
| 484 |
+ CreatedTimestamp: s.createdTs, |
|
| 484 | 485 |
} |
| 485 | 486 |
|
| 486 | 487 |
out.Summary = sum |
| ... | ... |
@@ -530,20 +557,28 @@ type SummaryVec struct {
|
| 530 | 530 |
// it is handled by the Prometheus server internally, “quantile” is an illegal |
| 531 | 531 |
// label name. NewSummaryVec will panic if this label name is used. |
| 532 | 532 |
func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
| 533 |
- for _, ln := range labelNames {
|
|
| 533 |
+ return V2.NewSummaryVec(SummaryVecOpts{
|
|
| 534 |
+ SummaryOpts: opts, |
|
| 535 |
+ VariableLabels: UnconstrainedLabels(labelNames), |
|
| 536 |
+ }) |
|
| 537 |
+} |
|
| 538 |
+ |
|
| 539 |
+// NewSummaryVec creates a new SummaryVec based on the provided SummaryVecOpts. |
|
| 540 |
+func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec {
|
|
| 541 |
+ for _, ln := range opts.VariableLabels.labelNames() {
|
|
| 534 | 542 |
if ln == quantileLabel {
|
| 535 | 543 |
panic(errQuantileLabelNotAllowed) |
| 536 | 544 |
} |
| 537 | 545 |
} |
| 538 |
- desc := NewDesc( |
|
| 546 |
+ desc := V2.NewDesc( |
|
| 539 | 547 |
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), |
| 540 | 548 |
opts.Help, |
| 541 |
- labelNames, |
|
| 549 |
+ opts.VariableLabels, |
|
| 542 | 550 |
opts.ConstLabels, |
| 543 | 551 |
) |
| 544 | 552 |
return &SummaryVec{
|
| 545 | 553 |
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
| 546 |
- return newSummary(desc, opts, lvs...) |
|
| 554 |
+ return newSummary(desc, opts.SummaryOpts, lvs...) |
|
| 547 | 555 |
}), |
| 548 | 556 |
} |
| 549 | 557 |
} |
| ... | ... |
@@ -662,6 +697,7 @@ type constSummary struct {
|
| 662 | 662 |
sum float64 |
| 663 | 663 |
quantiles map[float64]float64 |
| 664 | 664 |
labelPairs []*dto.LabelPair |
| 665 |
+ createdTs *timestamppb.Timestamp |
|
| 665 | 666 |
} |
| 666 | 667 |
|
| 667 | 668 |
func (s *constSummary) Desc() *Desc {
|
| ... | ... |
@@ -669,7 +705,9 @@ func (s *constSummary) Desc() *Desc {
|
| 669 | 669 |
} |
| 670 | 670 |
|
| 671 | 671 |
func (s *constSummary) Write(out *dto.Metric) error {
|
| 672 |
- sum := &dto.Summary{}
|
|
| 672 |
+ sum := &dto.Summary{
|
|
| 673 |
+ CreatedTimestamp: s.createdTs, |
|
| 674 |
+ } |
|
| 673 | 675 |
qs := make([]*dto.Quantile, 0, len(s.quantiles)) |
| 674 | 676 |
|
| 675 | 677 |
sum.SampleCount = proto.Uint64(s.count) |
| ... | ... |
@@ -718,7 +756,7 @@ func NewConstSummary( |
| 718 | 718 |
if desc.err != nil {
|
| 719 | 719 |
return nil, desc.err |
| 720 | 720 |
} |
| 721 |
- if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
|
| 721 |
+ if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
|
| 722 | 722 |
return nil, err |
| 723 | 723 |
} |
| 724 | 724 |
return &constSummary{
|
| ... | ... |
@@ -23,7 +23,9 @@ type Timer struct {
|
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
// NewTimer creates a new Timer. The provided Observer is used to observe a |
| 26 |
-// duration in seconds. Timer is usually used to time a function call in the |
|
| 26 |
+// duration in seconds. If the Observer implements ExemplarObserver, passing exemplar |
|
| 27 |
+// later on will be also supported. |
|
| 28 |
+// Timer is usually used to time a function call in the |
|
| 27 | 29 |
// following way: |
| 28 | 30 |
// |
| 29 | 31 |
// func TimeMe() {
|
| ... | ... |
@@ -31,6 +33,14 @@ type Timer struct {
|
| 31 | 31 |
// defer timer.ObserveDuration() |
| 32 | 32 |
// // Do actual work. |
| 33 | 33 |
// } |
| 34 |
+// |
|
| 35 |
+// or |
|
| 36 |
+// |
|
| 37 |
+// func TimeMeWithExemplar() {
|
|
| 38 |
+// timer := NewTimer(myHistogram) |
|
| 39 |
+// defer timer.ObserveDurationWithExemplar(exemplar) |
|
| 40 |
+// // Do actual work. |
|
| 41 |
+// } |
|
| 34 | 42 |
func NewTimer(o Observer) *Timer {
|
| 35 | 43 |
return &Timer{
|
| 36 | 44 |
begin: time.Now(), |
| ... | ... |
@@ -53,3 +63,19 @@ func (t *Timer) ObserveDuration() time.Duration {
|
| 53 | 53 |
} |
| 54 | 54 |
return d |
| 55 | 55 |
} |
| 56 |
+ |
|
| 57 |
+// ObserveDurationWithExemplar is like ObserveDuration, but it will also |
|
| 58 |
+// observe exemplar with the duration unless exemplar is nil or provided Observer can't |
|
| 59 |
+// be casted to ExemplarObserver. |
|
| 60 |
+func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration {
|
|
| 61 |
+ d := time.Since(t.begin) |
|
| 62 |
+ eo, ok := t.observer.(ExemplarObserver) |
|
| 63 |
+ if ok && exemplar != nil {
|
|
| 64 |
+ eo.ObserveWithExemplar(d.Seconds(), exemplar) |
|
| 65 |
+ return d |
|
| 66 |
+ } |
|
| 67 |
+ if t.observer != nil {
|
|
| 68 |
+ t.observer.Observe(d.Seconds()) |
|
| 69 |
+ } |
|
| 70 |
+ return d |
|
| 71 |
+} |
| ... | ... |
@@ -14,18 +14,17 @@ |
| 14 | 14 |
package prometheus |
| 15 | 15 |
|
| 16 | 16 |
import ( |
| 17 |
+ "errors" |
|
| 17 | 18 |
"fmt" |
| 18 | 19 |
"sort" |
| 19 | 20 |
"time" |
| 20 | 21 |
"unicode/utf8" |
| 21 | 22 |
|
| 22 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 23 |
- "github.com/golang/protobuf/proto" |
|
| 24 |
- "google.golang.org/protobuf/types/known/timestamppb" |
|
| 25 |
- |
|
| 26 | 23 |
"github.com/prometheus/client_golang/prometheus/internal" |
| 27 | 24 |
|
| 28 | 25 |
dto "github.com/prometheus/client_model/go" |
| 26 |
+ "google.golang.org/protobuf/proto" |
|
| 27 |
+ "google.golang.org/protobuf/types/known/timestamppb" |
|
| 29 | 28 |
) |
| 30 | 29 |
|
| 31 | 30 |
// ValueType is an enumeration of metric types that represent a simple value. |
| ... | ... |
@@ -93,7 +92,7 @@ func (v *valueFunc) Desc() *Desc {
|
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 | 95 |
func (v *valueFunc) Write(out *dto.Metric) error {
|
| 96 |
- return populateMetric(v.valType, v.function(), v.labelPairs, nil, out) |
|
| 96 |
+ return populateMetric(v.valType, v.function(), v.labelPairs, nil, out, nil) |
|
| 97 | 97 |
} |
| 98 | 98 |
|
| 99 | 99 |
// NewConstMetric returns a metric with one fixed value that cannot be |
| ... | ... |
@@ -107,12 +106,12 @@ func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues |
| 107 | 107 |
if desc.err != nil {
|
| 108 | 108 |
return nil, desc.err |
| 109 | 109 |
} |
| 110 |
- if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
|
| 110 |
+ if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
|
| 111 | 111 |
return nil, err |
| 112 | 112 |
} |
| 113 | 113 |
|
| 114 | 114 |
metric := &dto.Metric{}
|
| 115 |
- if err := populateMetric(valueType, value, MakeLabelPairs(desc, labelValues), nil, metric); err != nil {
|
|
| 115 |
+ if err := populateMetric(valueType, value, MakeLabelPairs(desc, labelValues), nil, metric, nil); err != nil {
|
|
| 116 | 116 |
return nil, err |
| 117 | 117 |
} |
| 118 | 118 |
|
| ... | ... |
@@ -132,6 +131,43 @@ func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelVal |
| 132 | 132 |
return m |
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 |
+// NewConstMetricWithCreatedTimestamp does the same thing as NewConstMetric, but generates Counters |
|
| 136 |
+// with created timestamp set and returns an error for other metric types. |
|
| 137 |
+func NewConstMetricWithCreatedTimestamp(desc *Desc, valueType ValueType, value float64, ct time.Time, labelValues ...string) (Metric, error) {
|
|
| 138 |
+ if desc.err != nil {
|
|
| 139 |
+ return nil, desc.err |
|
| 140 |
+ } |
|
| 141 |
+ if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
|
|
| 142 |
+ return nil, err |
|
| 143 |
+ } |
|
| 144 |
+ switch valueType {
|
|
| 145 |
+ case CounterValue: |
|
| 146 |
+ break |
|
| 147 |
+ default: |
|
| 148 |
+ return nil, errors.New("created timestamps are only supported for counters")
|
|
| 149 |
+ } |
|
| 150 |
+ |
|
| 151 |
+ metric := &dto.Metric{}
|
|
| 152 |
+ if err := populateMetric(valueType, value, MakeLabelPairs(desc, labelValues), nil, metric, timestamppb.New(ct)); err != nil {
|
|
| 153 |
+ return nil, err |
|
| 154 |
+ } |
|
| 155 |
+ |
|
| 156 |
+ return &constMetric{
|
|
| 157 |
+ desc: desc, |
|
| 158 |
+ metric: metric, |
|
| 159 |
+ }, nil |
|
| 160 |
+} |
|
| 161 |
+ |
|
| 162 |
+// MustNewConstMetricWithCreatedTimestamp is a version of NewConstMetricWithCreatedTimestamp that panics where |
|
| 163 |
+// NewConstMetricWithCreatedTimestamp would have returned an error. |
|
| 164 |
+func MustNewConstMetricWithCreatedTimestamp(desc *Desc, valueType ValueType, value float64, ct time.Time, labelValues ...string) Metric {
|
|
| 165 |
+ m, err := NewConstMetricWithCreatedTimestamp(desc, valueType, value, ct, labelValues...) |
|
| 166 |
+ if err != nil {
|
|
| 167 |
+ panic(err) |
|
| 168 |
+ } |
|
| 169 |
+ return m |
|
| 170 |
+} |
|
| 171 |
+ |
|
| 135 | 172 |
type constMetric struct {
|
| 136 | 173 |
desc *Desc |
| 137 | 174 |
metric *dto.Metric |
| ... | ... |
@@ -155,11 +191,12 @@ func populateMetric( |
| 155 | 155 |
labelPairs []*dto.LabelPair, |
| 156 | 156 |
e *dto.Exemplar, |
| 157 | 157 |
m *dto.Metric, |
| 158 |
+ ct *timestamppb.Timestamp, |
|
| 158 | 159 |
) error {
|
| 159 | 160 |
m.Label = labelPairs |
| 160 | 161 |
switch t {
|
| 161 | 162 |
case CounterValue: |
| 162 |
- m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e}
|
|
| 163 |
+ m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e, CreatedTimestamp: ct}
|
|
| 163 | 164 |
case GaugeValue: |
| 164 | 165 |
m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
|
| 165 | 166 |
case UntypedValue: |
| ... | ... |
@@ -178,19 +215,19 @@ func populateMetric( |
| 178 | 178 |
// This function is only needed for custom Metric implementations. See MetricVec |
| 179 | 179 |
// example. |
| 180 | 180 |
func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
|
| 181 |
- totalLen := len(desc.variableLabels) + len(desc.constLabelPairs) |
|
| 181 |
+ totalLen := len(desc.variableLabels.names) + len(desc.constLabelPairs) |
|
| 182 | 182 |
if totalLen == 0 {
|
| 183 | 183 |
// Super fast path. |
| 184 | 184 |
return nil |
| 185 | 185 |
} |
| 186 |
- if len(desc.variableLabels) == 0 {
|
|
| 186 |
+ if len(desc.variableLabels.names) == 0 {
|
|
| 187 | 187 |
// Moderately fast path. |
| 188 | 188 |
return desc.constLabelPairs |
| 189 | 189 |
} |
| 190 | 190 |
labelPairs := make([]*dto.LabelPair, 0, totalLen) |
| 191 |
- for i, n := range desc.variableLabels {
|
|
| 191 |
+ for i, l := range desc.variableLabels.names {
|
|
| 192 | 192 |
labelPairs = append(labelPairs, &dto.LabelPair{
|
| 193 |
- Name: proto.String(n), |
|
| 193 |
+ Name: proto.String(l), |
|
| 194 | 194 |
Value: proto.String(labelValues[i]), |
| 195 | 195 |
}) |
| 196 | 196 |
} |
| ... | ... |
@@ -72,6 +72,8 @@ func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
|
| 72 | 72 |
// with a performance overhead (for creating and processing the Labels map). |
| 73 | 73 |
// See also the CounterVec example. |
| 74 | 74 |
func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
|
| 75 |
+ lvs = constrainLabelValues(m.desc, lvs, m.curry) |
|
| 76 |
+ |
|
| 75 | 77 |
h, err := m.hashLabelValues(lvs) |
| 76 | 78 |
if err != nil {
|
| 77 | 79 |
return false |
| ... | ... |
@@ -91,6 +93,9 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
|
| 91 | 91 |
// This method is used for the same purpose as DeleteLabelValues(...string). See |
| 92 | 92 |
// there for pros and cons of the two methods. |
| 93 | 93 |
func (m *MetricVec) Delete(labels Labels) bool {
|
| 94 |
+ labels, closer := constrainLabels(m.desc, labels) |
|
| 95 |
+ defer closer() |
|
| 96 |
+ |
|
| 94 | 97 |
h, err := m.hashLabels(labels) |
| 95 | 98 |
if err != nil {
|
| 96 | 99 |
return false |
| ... | ... |
@@ -106,6 +111,9 @@ func (m *MetricVec) Delete(labels Labels) bool {
|
| 106 | 106 |
// Note that curried labels will never be matched if deleting from the curried vector. |
| 107 | 107 |
// To match curried labels with DeletePartialMatch, it must be called on the base vector. |
| 108 | 108 |
func (m *MetricVec) DeletePartialMatch(labels Labels) int {
|
| 109 |
+ labels, closer := constrainLabels(m.desc, labels) |
|
| 110 |
+ defer closer() |
|
| 111 |
+ |
|
| 109 | 112 |
return m.metricMap.deleteByLabels(labels, m.curry) |
| 110 | 113 |
} |
| 111 | 114 |
|
| ... | ... |
@@ -144,11 +152,11 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
|
| 144 | 144 |
oldCurry = m.curry |
| 145 | 145 |
iCurry int |
| 146 | 146 |
) |
| 147 |
- for i, label := range m.desc.variableLabels {
|
|
| 148 |
- val, ok := labels[label] |
|
| 147 |
+ for i, labelName := range m.desc.variableLabels.names {
|
|
| 148 |
+ val, ok := labels[labelName] |
|
| 149 | 149 |
if iCurry < len(oldCurry) && oldCurry[iCurry].index == i {
|
| 150 | 150 |
if ok {
|
| 151 |
- return nil, fmt.Errorf("label name %q is already curried", label)
|
|
| 151 |
+ return nil, fmt.Errorf("label name %q is already curried", labelName)
|
|
| 152 | 152 |
} |
| 153 | 153 |
newCurry = append(newCurry, oldCurry[iCurry]) |
| 154 | 154 |
iCurry++ |
| ... | ... |
@@ -156,7 +164,10 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
|
| 156 | 156 |
if !ok {
|
| 157 | 157 |
continue // Label stays uncurried. |
| 158 | 158 |
} |
| 159 |
- newCurry = append(newCurry, curriedLabelValue{i, val})
|
|
| 159 |
+ newCurry = append(newCurry, curriedLabelValue{
|
|
| 160 |
+ i, |
|
| 161 |
+ m.desc.variableLabels.constrain(labelName, val), |
|
| 162 |
+ }) |
|
| 160 | 163 |
} |
| 161 | 164 |
} |
| 162 | 165 |
if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 {
|
| ... | ... |
@@ -199,6 +210,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
|
| 199 | 199 |
// a wrapper around MetricVec, implementing a vector for a specific Metric |
| 200 | 200 |
// implementation, for example GaugeVec. |
| 201 | 201 |
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
|
| 202 |
+ lvs = constrainLabelValues(m.desc, lvs, m.curry) |
|
| 202 | 203 |
h, err := m.hashLabelValues(lvs) |
| 203 | 204 |
if err != nil {
|
| 204 | 205 |
return nil, err |
| ... | ... |
@@ -224,6 +236,9 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
|
| 224 | 224 |
// around MetricVec, implementing a vector for a specific Metric implementation, |
| 225 | 225 |
// for example GaugeVec. |
| 226 | 226 |
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
|
| 227 |
+ labels, closer := constrainLabels(m.desc, labels) |
|
| 228 |
+ defer closer() |
|
| 229 |
+ |
|
| 227 | 230 |
h, err := m.hashLabels(labels) |
| 228 | 231 |
if err != nil {
|
| 229 | 232 |
return nil, err |
| ... | ... |
@@ -233,7 +248,7 @@ func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
|
| 236 |
- if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
|
|
| 236 |
+ if err := validateLabelValues(vals, len(m.desc.variableLabels.names)-len(m.curry)); err != nil {
|
|
| 237 | 237 |
return 0, err |
| 238 | 238 |
} |
| 239 | 239 |
|
| ... | ... |
@@ -242,7 +257,7 @@ func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
|
| 242 | 242 |
curry = m.curry |
| 243 | 243 |
iVals, iCurry int |
| 244 | 244 |
) |
| 245 |
- for i := 0; i < len(m.desc.variableLabels); i++ {
|
|
| 245 |
+ for i := 0; i < len(m.desc.variableLabels.names); i++ {
|
|
| 246 | 246 |
if iCurry < len(curry) && curry[iCurry].index == i {
|
| 247 | 247 |
h = m.hashAdd(h, curry[iCurry].value) |
| 248 | 248 |
iCurry++ |
| ... | ... |
@@ -256,7 +271,7 @@ func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
|
| 256 | 256 |
} |
| 257 | 257 |
|
| 258 | 258 |
func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
|
| 259 |
- if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
|
|
| 259 |
+ if err := validateValuesInLabels(labels, len(m.desc.variableLabels.names)-len(m.curry)); err != nil {
|
|
| 260 | 260 |
return 0, err |
| 261 | 261 |
} |
| 262 | 262 |
|
| ... | ... |
@@ -265,17 +280,17 @@ func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
|
| 265 | 265 |
curry = m.curry |
| 266 | 266 |
iCurry int |
| 267 | 267 |
) |
| 268 |
- for i, label := range m.desc.variableLabels {
|
|
| 269 |
- val, ok := labels[label] |
|
| 268 |
+ for i, labelName := range m.desc.variableLabels.names {
|
|
| 269 |
+ val, ok := labels[labelName] |
|
| 270 | 270 |
if iCurry < len(curry) && curry[iCurry].index == i {
|
| 271 | 271 |
if ok {
|
| 272 |
- return 0, fmt.Errorf("label name %q is already curried", label)
|
|
| 272 |
+ return 0, fmt.Errorf("label name %q is already curried", labelName)
|
|
| 273 | 273 |
} |
| 274 | 274 |
h = m.hashAdd(h, curry[iCurry].value) |
| 275 | 275 |
iCurry++ |
| 276 | 276 |
} else {
|
| 277 | 277 |
if !ok {
|
| 278 |
- return 0, fmt.Errorf("label name %q missing in label map", label)
|
|
| 278 |
+ return 0, fmt.Errorf("label name %q missing in label map", labelName)
|
|
| 279 | 279 |
} |
| 280 | 280 |
h = m.hashAdd(h, val) |
| 281 | 281 |
} |
| ... | ... |
@@ -453,7 +468,7 @@ func valueMatchesVariableOrCurriedValue(targetValue string, index int, values [] |
| 453 | 453 |
func matchPartialLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool {
|
| 454 | 454 |
for l, v := range labels {
|
| 455 | 455 |
// Check if the target label exists in our metrics and get the index. |
| 456 |
- varLabelIndex, validLabel := indexOf(l, desc.variableLabels) |
|
| 456 |
+ varLabelIndex, validLabel := indexOf(l, desc.variableLabels.names) |
|
| 457 | 457 |
if validLabel {
|
| 458 | 458 |
// Check the value of that label against the target value. |
| 459 | 459 |
// We don't consider curried values in partial matches. |
| ... | ... |
@@ -597,7 +612,7 @@ func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabe |
| 597 | 597 |
return false |
| 598 | 598 |
} |
| 599 | 599 |
iCurry := 0 |
| 600 |
- for i, k := range desc.variableLabels {
|
|
| 600 |
+ for i, k := range desc.variableLabels.names {
|
|
| 601 | 601 |
if iCurry < len(curry) && curry[iCurry].index == i {
|
| 602 | 602 |
if values[i] != curry[iCurry].value {
|
| 603 | 603 |
return false |
| ... | ... |
@@ -615,7 +630,7 @@ func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabe |
| 615 | 615 |
func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []string {
|
| 616 | 616 |
labelValues := make([]string, len(labels)+len(curry)) |
| 617 | 617 |
iCurry := 0 |
| 618 |
- for i, k := range desc.variableLabels {
|
|
| 618 |
+ for i, k := range desc.variableLabels.names {
|
|
| 619 | 619 |
if iCurry < len(curry) && curry[iCurry].index == i {
|
| 620 | 620 |
labelValues[i] = curry[iCurry].value |
| 621 | 621 |
iCurry++ |
| ... | ... |
@@ -640,3 +655,55 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string {
|
| 640 | 640 |
} |
| 641 | 641 |
return labelValues |
| 642 | 642 |
} |
| 643 |
+ |
|
| 644 |
+var labelsPool = &sync.Pool{
|
|
| 645 |
+ New: func() interface{} {
|
|
| 646 |
+ return make(Labels) |
|
| 647 |
+ }, |
|
| 648 |
+} |
|
| 649 |
+ |
|
| 650 |
+func constrainLabels(desc *Desc, labels Labels) (Labels, func()) {
|
|
| 651 |
+ if len(desc.variableLabels.labelConstraints) == 0 {
|
|
| 652 |
+ // Fast path when there's no constraints |
|
| 653 |
+ return labels, func() {}
|
|
| 654 |
+ } |
|
| 655 |
+ |
|
| 656 |
+ constrainedLabels := labelsPool.Get().(Labels) |
|
| 657 |
+ for l, v := range labels {
|
|
| 658 |
+ constrainedLabels[l] = desc.variableLabels.constrain(l, v) |
|
| 659 |
+ } |
|
| 660 |
+ |
|
| 661 |
+ return constrainedLabels, func() {
|
|
| 662 |
+ for k := range constrainedLabels {
|
|
| 663 |
+ delete(constrainedLabels, k) |
|
| 664 |
+ } |
|
| 665 |
+ labelsPool.Put(constrainedLabels) |
|
| 666 |
+ } |
|
| 667 |
+} |
|
| 668 |
+ |
|
| 669 |
+func constrainLabelValues(desc *Desc, lvs []string, curry []curriedLabelValue) []string {
|
|
| 670 |
+ if len(desc.variableLabels.labelConstraints) == 0 {
|
|
| 671 |
+ // Fast path when there's no constraints |
|
| 672 |
+ return lvs |
|
| 673 |
+ } |
|
| 674 |
+ |
|
| 675 |
+ constrainedValues := make([]string, len(lvs)) |
|
| 676 |
+ var iCurry, iLVs int |
|
| 677 |
+ for i := 0; i < len(lvs)+len(curry); i++ {
|
|
| 678 |
+ if iCurry < len(curry) && curry[iCurry].index == i {
|
|
| 679 |
+ iCurry++ |
|
| 680 |
+ continue |
|
| 681 |
+ } |
|
| 682 |
+ |
|
| 683 |
+ if i < len(desc.variableLabels.names) {
|
|
| 684 |
+ constrainedValues[iLVs] = desc.variableLabels.constrain( |
|
| 685 |
+ desc.variableLabels.names[i], |
|
| 686 |
+ lvs[iLVs], |
|
| 687 |
+ ) |
|
| 688 |
+ } else {
|
|
| 689 |
+ constrainedValues[iLVs] = lvs[iLVs] |
|
| 690 |
+ } |
|
| 691 |
+ iLVs++ |
|
| 692 |
+ } |
|
| 693 |
+ return constrainedValues |
|
| 694 |
+} |
| 643 | 695 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+// Copyright 2022 The Prometheus Authors |
|
| 1 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 2 |
+// you may not use this file except in compliance with the License. |
|
| 3 |
+// You may obtain a copy of the License at |
|
| 4 |
+// |
|
| 5 |
+// http://www.apache.org/licenses/LICENSE-2.0 |
|
| 6 |
+// |
|
| 7 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 8 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 9 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 10 |
+// See the License for the specific language governing permissions and |
|
| 11 |
+// limitations under the License. |
|
| 12 |
+ |
|
| 13 |
+package prometheus |
|
| 14 |
+ |
|
| 15 |
+type v2 struct{}
|
|
| 16 |
+ |
|
| 17 |
+// V2 is a struct that can be referenced to access experimental API that might |
|
| 18 |
+// be present in v2 of client golang someday. It offers extended functionality |
|
| 19 |
+// of v1 with slightly changed API. It is acceptable to use some pieces from v1 |
|
| 20 |
+// and e.g `prometheus.NewGauge` and some from v2 e.g. `prometheus.V2.NewDesc` |
|
| 21 |
+// in the same codebase. |
|
| 22 |
+var V2 = v2{}
|
| ... | ... |
@@ -17,12 +17,10 @@ import ( |
| 17 | 17 |
"fmt" |
| 18 | 18 |
"sort" |
| 19 | 19 |
|
| 20 |
- //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 21 |
- "github.com/golang/protobuf/proto" |
|
| 20 |
+ "github.com/prometheus/client_golang/prometheus/internal" |
|
| 22 | 21 |
|
| 23 | 22 |
dto "github.com/prometheus/client_model/go" |
| 24 |
- |
|
| 25 |
- "github.com/prometheus/client_golang/prometheus/internal" |
|
| 23 |
+ "google.golang.org/protobuf/proto" |
|
| 26 | 24 |
) |
| 27 | 25 |
|
| 28 | 26 |
// WrapRegistererWith returns a Registerer wrapping the provided |
| ... | ... |
@@ -206,7 +204,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc {
|
| 206 | 206 |
constLabels[ln] = lv |
| 207 | 207 |
} |
| 208 | 208 |
// NewDesc will do remaining validations. |
| 209 |
- newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) |
|
| 209 |
+ newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) |
|
| 210 | 210 |
// Propagate errors if there was any. This will override any errer |
| 211 | 211 |
// created by NewDesc above, i.e. earlier errors get precedence. |
| 212 | 212 |
if desc.err != nil {
|
| ... | ... |
@@ -1,25 +1,38 @@ |
| 1 |
+// Copyright 2013 Prometheus Team |
|
| 2 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 3 |
+// you may not use this file except in compliance with the License. |
|
| 4 |
+// You may obtain a copy of the License at |
|
| 5 |
+// |
|
| 6 |
+// http://www.apache.org/licenses/LICENSE-2.0 |
|
| 7 |
+// |
|
| 8 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 9 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 10 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 11 |
+// See the License for the specific language governing permissions and |
|
| 12 |
+// limitations under the License. |
|
| 13 |
+ |
|
| 1 | 14 |
// Code generated by protoc-gen-go. DO NOT EDIT. |
| 15 |
+// versions: |
|
| 16 |
+// protoc-gen-go v1.30.0 |
|
| 17 |
+// protoc v3.20.3 |
|
| 2 | 18 |
// source: io/prometheus/client/metrics.proto |
| 3 | 19 |
|
| 4 | 20 |
package io_prometheus_client |
| 5 | 21 |
|
| 6 | 22 |
import ( |
| 7 |
- fmt "fmt" |
|
| 8 |
- proto "github.com/golang/protobuf/proto" |
|
| 9 |
- timestamp "github.com/golang/protobuf/ptypes/timestamp" |
|
| 10 |
- math "math" |
|
| 23 |
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
|
| 24 |
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
|
| 25 |
+ timestamppb "google.golang.org/protobuf/types/known/timestamppb" |
|
| 26 |
+ reflect "reflect" |
|
| 27 |
+ sync "sync" |
|
| 11 | 28 |
) |
| 12 | 29 |
|
| 13 |
-// Reference imports to suppress errors if they are not otherwise used. |
|
| 14 |
-var _ = proto.Marshal |
|
| 15 |
-var _ = fmt.Errorf |
|
| 16 |
-var _ = math.Inf |
|
| 17 |
- |
|
| 18 |
-// This is a compile-time assertion to ensure that this generated file |
|
| 19 |
-// is compatible with the proto package it is being compiled against. |
|
| 20 |
-// A compilation error at this line likely means your copy of the |
|
| 21 |
-// proto package needs to be updated. |
|
| 22 |
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package |
|
| 30 |
+const ( |
|
| 31 |
+ // Verify that this generated code is sufficiently up-to-date. |
|
| 32 |
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) |
|
| 33 |
+ // Verify that runtime/protoimpl is sufficiently up-to-date. |
|
| 34 |
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) |
|
| 35 |
+) |
|
| 23 | 36 |
|
| 24 | 37 |
type MetricType int32 |
| 25 | 38 |
|
| ... | ... |
@@ -38,23 +51,25 @@ const ( |
| 38 | 38 |
MetricType_GAUGE_HISTOGRAM MetricType = 5 |
| 39 | 39 |
) |
| 40 | 40 |
|
| 41 |
-var MetricType_name = map[int32]string{
|
|
| 42 |
- 0: "COUNTER", |
|
| 43 |
- 1: "GAUGE", |
|
| 44 |
- 2: "SUMMARY", |
|
| 45 |
- 3: "UNTYPED", |
|
| 46 |
- 4: "HISTOGRAM", |
|
| 47 |
- 5: "GAUGE_HISTOGRAM", |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-var MetricType_value = map[string]int32{
|
|
| 51 |
- "COUNTER": 0, |
|
| 52 |
- "GAUGE": 1, |
|
| 53 |
- "SUMMARY": 2, |
|
| 54 |
- "UNTYPED": 3, |
|
| 55 |
- "HISTOGRAM": 4, |
|
| 56 |
- "GAUGE_HISTOGRAM": 5, |
|
| 57 |
-} |
|
| 41 |
+// Enum value maps for MetricType. |
|
| 42 |
+var ( |
|
| 43 |
+ MetricType_name = map[int32]string{
|
|
| 44 |
+ 0: "COUNTER", |
|
| 45 |
+ 1: "GAUGE", |
|
| 46 |
+ 2: "SUMMARY", |
|
| 47 |
+ 3: "UNTYPED", |
|
| 48 |
+ 4: "HISTOGRAM", |
|
| 49 |
+ 5: "GAUGE_HISTOGRAM", |
|
| 50 |
+ } |
|
| 51 |
+ MetricType_value = map[string]int32{
|
|
| 52 |
+ "COUNTER": 0, |
|
| 53 |
+ "GAUGE": 1, |
|
| 54 |
+ "SUMMARY": 2, |
|
| 55 |
+ "UNTYPED": 3, |
|
| 56 |
+ "HISTOGRAM": 4, |
|
| 57 |
+ "GAUGE_HISTOGRAM": 5, |
|
| 58 |
+ } |
|
| 59 |
+) |
|
| 58 | 60 |
|
| 59 | 61 |
func (x MetricType) Enum() *MetricType {
|
| 60 | 62 |
p := new(MetricType) |
| ... | ... |
@@ -63,449 +78,546 @@ func (x MetricType) Enum() *MetricType {
|
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 | 65 |
func (x MetricType) String() string {
|
| 66 |
- return proto.EnumName(MetricType_name, int32(x)) |
|
| 66 |
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) |
|
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 |
-func (x *MetricType) UnmarshalJSON(data []byte) error {
|
|
| 70 |
- value, err := proto.UnmarshalJSONEnum(MetricType_value, data, "MetricType") |
|
| 69 |
+func (MetricType) Descriptor() protoreflect.EnumDescriptor {
|
|
| 70 |
+ return file_io_prometheus_client_metrics_proto_enumTypes[0].Descriptor() |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+func (MetricType) Type() protoreflect.EnumType {
|
|
| 74 |
+ return &file_io_prometheus_client_metrics_proto_enumTypes[0] |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+func (x MetricType) Number() protoreflect.EnumNumber {
|
|
| 78 |
+ return protoreflect.EnumNumber(x) |
|
| 79 |
+} |
|
| 80 |
+ |
|
| 81 |
+// Deprecated: Do not use. |
|
| 82 |
+func (x *MetricType) UnmarshalJSON(b []byte) error {
|
|
| 83 |
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) |
|
| 71 | 84 |
if err != nil {
|
| 72 | 85 |
return err |
| 73 | 86 |
} |
| 74 |
- *x = MetricType(value) |
|
| 87 |
+ *x = MetricType(num) |
|
| 75 | 88 |
return nil |
| 76 | 89 |
} |
| 77 | 90 |
|
| 91 |
+// Deprecated: Use MetricType.Descriptor instead. |
|
| 78 | 92 |
func (MetricType) EnumDescriptor() ([]byte, []int) {
|
| 79 |
- return fileDescriptor_d1e5ddb18987a258, []int{0}
|
|
| 93 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{0}
|
|
| 80 | 94 |
} |
| 81 | 95 |
|
| 82 | 96 |
type LabelPair struct {
|
| 83 |
- Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` |
|
| 84 |
- Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` |
|
| 85 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 86 |
- XXX_unrecognized []byte `json:"-"` |
|
| 87 |
- XXX_sizecache int32 `json:"-"` |
|
| 88 |
-} |
|
| 97 |
+ state protoimpl.MessageState |
|
| 98 |
+ sizeCache protoimpl.SizeCache |
|
| 99 |
+ unknownFields protoimpl.UnknownFields |
|
| 89 | 100 |
|
| 90 |
-func (m *LabelPair) Reset() { *m = LabelPair{} }
|
|
| 91 |
-func (m *LabelPair) String() string { return proto.CompactTextString(m) }
|
|
| 92 |
-func (*LabelPair) ProtoMessage() {}
|
|
| 93 |
-func (*LabelPair) Descriptor() ([]byte, []int) {
|
|
| 94 |
- return fileDescriptor_d1e5ddb18987a258, []int{0}
|
|
| 101 |
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` |
|
| 102 |
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` |
|
| 95 | 103 |
} |
| 96 | 104 |
|
| 97 |
-func (m *LabelPair) XXX_Unmarshal(b []byte) error {
|
|
| 98 |
- return xxx_messageInfo_LabelPair.Unmarshal(m, b) |
|
| 99 |
-} |
|
| 100 |
-func (m *LabelPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 101 |
- return xxx_messageInfo_LabelPair.Marshal(b, m, deterministic) |
|
| 102 |
-} |
|
| 103 |
-func (m *LabelPair) XXX_Merge(src proto.Message) {
|
|
| 104 |
- xxx_messageInfo_LabelPair.Merge(m, src) |
|
| 105 |
+func (x *LabelPair) Reset() {
|
|
| 106 |
+ *x = LabelPair{}
|
|
| 107 |
+ if protoimpl.UnsafeEnabled {
|
|
| 108 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[0] |
|
| 109 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 110 |
+ ms.StoreMessageInfo(mi) |
|
| 111 |
+ } |
|
| 105 | 112 |
} |
| 106 |
-func (m *LabelPair) XXX_Size() int {
|
|
| 107 |
- return xxx_messageInfo_LabelPair.Size(m) |
|
| 113 |
+ |
|
| 114 |
+func (x *LabelPair) String() string {
|
|
| 115 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 108 | 116 |
} |
| 109 |
-func (m *LabelPair) XXX_DiscardUnknown() {
|
|
| 110 |
- xxx_messageInfo_LabelPair.DiscardUnknown(m) |
|
| 117 |
+ |
|
| 118 |
+func (*LabelPair) ProtoMessage() {}
|
|
| 119 |
+ |
|
| 120 |
+func (x *LabelPair) ProtoReflect() protoreflect.Message {
|
|
| 121 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[0] |
|
| 122 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 123 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 124 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 125 |
+ ms.StoreMessageInfo(mi) |
|
| 126 |
+ } |
|
| 127 |
+ return ms |
|
| 128 |
+ } |
|
| 129 |
+ return mi.MessageOf(x) |
|
| 111 | 130 |
} |
| 112 | 131 |
|
| 113 |
-var xxx_messageInfo_LabelPair proto.InternalMessageInfo |
|
| 132 |
+// Deprecated: Use LabelPair.ProtoReflect.Descriptor instead. |
|
| 133 |
+func (*LabelPair) Descriptor() ([]byte, []int) {
|
|
| 134 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{0}
|
|
| 135 |
+} |
|
| 114 | 136 |
|
| 115 |
-func (m *LabelPair) GetName() string {
|
|
| 116 |
- if m != nil && m.Name != nil {
|
|
| 117 |
- return *m.Name |
|
| 137 |
+func (x *LabelPair) GetName() string {
|
|
| 138 |
+ if x != nil && x.Name != nil {
|
|
| 139 |
+ return *x.Name |
|
| 118 | 140 |
} |
| 119 | 141 |
return "" |
| 120 | 142 |
} |
| 121 | 143 |
|
| 122 |
-func (m *LabelPair) GetValue() string {
|
|
| 123 |
- if m != nil && m.Value != nil {
|
|
| 124 |
- return *m.Value |
|
| 144 |
+func (x *LabelPair) GetValue() string {
|
|
| 145 |
+ if x != nil && x.Value != nil {
|
|
| 146 |
+ return *x.Value |
|
| 125 | 147 |
} |
| 126 | 148 |
return "" |
| 127 | 149 |
} |
| 128 | 150 |
|
| 129 | 151 |
type Gauge struct {
|
| 130 |
- Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` |
|
| 131 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 132 |
- XXX_unrecognized []byte `json:"-"` |
|
| 133 |
- XXX_sizecache int32 `json:"-"` |
|
| 134 |
-} |
|
| 152 |
+ state protoimpl.MessageState |
|
| 153 |
+ sizeCache protoimpl.SizeCache |
|
| 154 |
+ unknownFields protoimpl.UnknownFields |
|
| 135 | 155 |
|
| 136 |
-func (m *Gauge) Reset() { *m = Gauge{} }
|
|
| 137 |
-func (m *Gauge) String() string { return proto.CompactTextString(m) }
|
|
| 138 |
-func (*Gauge) ProtoMessage() {}
|
|
| 139 |
-func (*Gauge) Descriptor() ([]byte, []int) {
|
|
| 140 |
- return fileDescriptor_d1e5ddb18987a258, []int{1}
|
|
| 156 |
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` |
|
| 141 | 157 |
} |
| 142 | 158 |
|
| 143 |
-func (m *Gauge) XXX_Unmarshal(b []byte) error {
|
|
| 144 |
- return xxx_messageInfo_Gauge.Unmarshal(m, b) |
|
| 145 |
-} |
|
| 146 |
-func (m *Gauge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 147 |
- return xxx_messageInfo_Gauge.Marshal(b, m, deterministic) |
|
| 148 |
-} |
|
| 149 |
-func (m *Gauge) XXX_Merge(src proto.Message) {
|
|
| 150 |
- xxx_messageInfo_Gauge.Merge(m, src) |
|
| 159 |
+func (x *Gauge) Reset() {
|
|
| 160 |
+ *x = Gauge{}
|
|
| 161 |
+ if protoimpl.UnsafeEnabled {
|
|
| 162 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[1] |
|
| 163 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 164 |
+ ms.StoreMessageInfo(mi) |
|
| 165 |
+ } |
|
| 151 | 166 |
} |
| 152 |
-func (m *Gauge) XXX_Size() int {
|
|
| 153 |
- return xxx_messageInfo_Gauge.Size(m) |
|
| 167 |
+ |
|
| 168 |
+func (x *Gauge) String() string {
|
|
| 169 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 154 | 170 |
} |
| 155 |
-func (m *Gauge) XXX_DiscardUnknown() {
|
|
| 156 |
- xxx_messageInfo_Gauge.DiscardUnknown(m) |
|
| 171 |
+ |
|
| 172 |
+func (*Gauge) ProtoMessage() {}
|
|
| 173 |
+ |
|
| 174 |
+func (x *Gauge) ProtoReflect() protoreflect.Message {
|
|
| 175 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[1] |
|
| 176 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 177 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 178 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 179 |
+ ms.StoreMessageInfo(mi) |
|
| 180 |
+ } |
|
| 181 |
+ return ms |
|
| 182 |
+ } |
|
| 183 |
+ return mi.MessageOf(x) |
|
| 157 | 184 |
} |
| 158 | 185 |
|
| 159 |
-var xxx_messageInfo_Gauge proto.InternalMessageInfo |
|
| 186 |
+// Deprecated: Use Gauge.ProtoReflect.Descriptor instead. |
|
| 187 |
+func (*Gauge) Descriptor() ([]byte, []int) {
|
|
| 188 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{1}
|
|
| 189 |
+} |
|
| 160 | 190 |
|
| 161 |
-func (m *Gauge) GetValue() float64 {
|
|
| 162 |
- if m != nil && m.Value != nil {
|
|
| 163 |
- return *m.Value |
|
| 191 |
+func (x *Gauge) GetValue() float64 {
|
|
| 192 |
+ if x != nil && x.Value != nil {
|
|
| 193 |
+ return *x.Value |
|
| 164 | 194 |
} |
| 165 | 195 |
return 0 |
| 166 | 196 |
} |
| 167 | 197 |
|
| 168 | 198 |
type Counter struct {
|
| 169 |
- Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` |
|
| 170 |
- Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar" json:"exemplar,omitempty"` |
|
| 171 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 172 |
- XXX_unrecognized []byte `json:"-"` |
|
| 173 |
- XXX_sizecache int32 `json:"-"` |
|
| 174 |
-} |
|
| 199 |
+ state protoimpl.MessageState |
|
| 200 |
+ sizeCache protoimpl.SizeCache |
|
| 201 |
+ unknownFields protoimpl.UnknownFields |
|
| 175 | 202 |
|
| 176 |
-func (m *Counter) Reset() { *m = Counter{} }
|
|
| 177 |
-func (m *Counter) String() string { return proto.CompactTextString(m) }
|
|
| 178 |
-func (*Counter) ProtoMessage() {}
|
|
| 179 |
-func (*Counter) Descriptor() ([]byte, []int) {
|
|
| 180 |
- return fileDescriptor_d1e5ddb18987a258, []int{2}
|
|
| 203 |
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` |
|
| 204 |
+ Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar" json:"exemplar,omitempty"` |
|
| 205 |
+ CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"` |
|
| 181 | 206 |
} |
| 182 | 207 |
|
| 183 |
-func (m *Counter) XXX_Unmarshal(b []byte) error {
|
|
| 184 |
- return xxx_messageInfo_Counter.Unmarshal(m, b) |
|
| 185 |
-} |
|
| 186 |
-func (m *Counter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 187 |
- return xxx_messageInfo_Counter.Marshal(b, m, deterministic) |
|
| 188 |
-} |
|
| 189 |
-func (m *Counter) XXX_Merge(src proto.Message) {
|
|
| 190 |
- xxx_messageInfo_Counter.Merge(m, src) |
|
| 208 |
+func (x *Counter) Reset() {
|
|
| 209 |
+ *x = Counter{}
|
|
| 210 |
+ if protoimpl.UnsafeEnabled {
|
|
| 211 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[2] |
|
| 212 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 213 |
+ ms.StoreMessageInfo(mi) |
|
| 214 |
+ } |
|
| 191 | 215 |
} |
| 192 |
-func (m *Counter) XXX_Size() int {
|
|
| 193 |
- return xxx_messageInfo_Counter.Size(m) |
|
| 216 |
+ |
|
| 217 |
+func (x *Counter) String() string {
|
|
| 218 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 194 | 219 |
} |
| 195 |
-func (m *Counter) XXX_DiscardUnknown() {
|
|
| 196 |
- xxx_messageInfo_Counter.DiscardUnknown(m) |
|
| 220 |
+ |
|
| 221 |
+func (*Counter) ProtoMessage() {}
|
|
| 222 |
+ |
|
| 223 |
+func (x *Counter) ProtoReflect() protoreflect.Message {
|
|
| 224 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[2] |
|
| 225 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 226 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 227 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 228 |
+ ms.StoreMessageInfo(mi) |
|
| 229 |
+ } |
|
| 230 |
+ return ms |
|
| 231 |
+ } |
|
| 232 |
+ return mi.MessageOf(x) |
|
| 197 | 233 |
} |
| 198 | 234 |
|
| 199 |
-var xxx_messageInfo_Counter proto.InternalMessageInfo |
|
| 235 |
+// Deprecated: Use Counter.ProtoReflect.Descriptor instead. |
|
| 236 |
+func (*Counter) Descriptor() ([]byte, []int) {
|
|
| 237 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{2}
|
|
| 238 |
+} |
|
| 200 | 239 |
|
| 201 |
-func (m *Counter) GetValue() float64 {
|
|
| 202 |
- if m != nil && m.Value != nil {
|
|
| 203 |
- return *m.Value |
|
| 240 |
+func (x *Counter) GetValue() float64 {
|
|
| 241 |
+ if x != nil && x.Value != nil {
|
|
| 242 |
+ return *x.Value |
|
| 204 | 243 |
} |
| 205 | 244 |
return 0 |
| 206 | 245 |
} |
| 207 | 246 |
|
| 208 |
-func (m *Counter) GetExemplar() *Exemplar {
|
|
| 209 |
- if m != nil {
|
|
| 210 |
- return m.Exemplar |
|
| 247 |
+func (x *Counter) GetExemplar() *Exemplar {
|
|
| 248 |
+ if x != nil {
|
|
| 249 |
+ return x.Exemplar |
|
| 211 | 250 |
} |
| 212 | 251 |
return nil |
| 213 | 252 |
} |
| 214 | 253 |
|
| 215 |
-type Quantile struct {
|
|
| 216 |
- Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` |
|
| 217 |
- Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` |
|
| 218 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 219 |
- XXX_unrecognized []byte `json:"-"` |
|
| 220 |
- XXX_sizecache int32 `json:"-"` |
|
| 254 |
+func (x *Counter) GetCreatedTimestamp() *timestamppb.Timestamp {
|
|
| 255 |
+ if x != nil {
|
|
| 256 |
+ return x.CreatedTimestamp |
|
| 257 |
+ } |
|
| 258 |
+ return nil |
|
| 221 | 259 |
} |
| 222 | 260 |
|
| 223 |
-func (m *Quantile) Reset() { *m = Quantile{} }
|
|
| 224 |
-func (m *Quantile) String() string { return proto.CompactTextString(m) }
|
|
| 225 |
-func (*Quantile) ProtoMessage() {}
|
|
| 226 |
-func (*Quantile) Descriptor() ([]byte, []int) {
|
|
| 227 |
- return fileDescriptor_d1e5ddb18987a258, []int{3}
|
|
| 228 |
-} |
|
| 261 |
+type Quantile struct {
|
|
| 262 |
+ state protoimpl.MessageState |
|
| 263 |
+ sizeCache protoimpl.SizeCache |
|
| 264 |
+ unknownFields protoimpl.UnknownFields |
|
| 229 | 265 |
|
| 230 |
-func (m *Quantile) XXX_Unmarshal(b []byte) error {
|
|
| 231 |
- return xxx_messageInfo_Quantile.Unmarshal(m, b) |
|
| 232 |
-} |
|
| 233 |
-func (m *Quantile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 234 |
- return xxx_messageInfo_Quantile.Marshal(b, m, deterministic) |
|
| 266 |
+ Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` |
|
| 267 |
+ Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` |
|
| 235 | 268 |
} |
| 236 |
-func (m *Quantile) XXX_Merge(src proto.Message) {
|
|
| 237 |
- xxx_messageInfo_Quantile.Merge(m, src) |
|
| 269 |
+ |
|
| 270 |
+func (x *Quantile) Reset() {
|
|
| 271 |
+ *x = Quantile{}
|
|
| 272 |
+ if protoimpl.UnsafeEnabled {
|
|
| 273 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[3] |
|
| 274 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 275 |
+ ms.StoreMessageInfo(mi) |
|
| 276 |
+ } |
|
| 238 | 277 |
} |
| 239 |
-func (m *Quantile) XXX_Size() int {
|
|
| 240 |
- return xxx_messageInfo_Quantile.Size(m) |
|
| 278 |
+ |
|
| 279 |
+func (x *Quantile) String() string {
|
|
| 280 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 241 | 281 |
} |
| 242 |
-func (m *Quantile) XXX_DiscardUnknown() {
|
|
| 243 |
- xxx_messageInfo_Quantile.DiscardUnknown(m) |
|
| 282 |
+ |
|
| 283 |
+func (*Quantile) ProtoMessage() {}
|
|
| 284 |
+ |
|
| 285 |
+func (x *Quantile) ProtoReflect() protoreflect.Message {
|
|
| 286 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[3] |
|
| 287 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 288 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 289 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 290 |
+ ms.StoreMessageInfo(mi) |
|
| 291 |
+ } |
|
| 292 |
+ return ms |
|
| 293 |
+ } |
|
| 294 |
+ return mi.MessageOf(x) |
|
| 244 | 295 |
} |
| 245 | 296 |
|
| 246 |
-var xxx_messageInfo_Quantile proto.InternalMessageInfo |
|
| 297 |
+// Deprecated: Use Quantile.ProtoReflect.Descriptor instead. |
|
| 298 |
+func (*Quantile) Descriptor() ([]byte, []int) {
|
|
| 299 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{3}
|
|
| 300 |
+} |
|
| 247 | 301 |
|
| 248 |
-func (m *Quantile) GetQuantile() float64 {
|
|
| 249 |
- if m != nil && m.Quantile != nil {
|
|
| 250 |
- return *m.Quantile |
|
| 302 |
+func (x *Quantile) GetQuantile() float64 {
|
|
| 303 |
+ if x != nil && x.Quantile != nil {
|
|
| 304 |
+ return *x.Quantile |
|
| 251 | 305 |
} |
| 252 | 306 |
return 0 |
| 253 | 307 |
} |
| 254 | 308 |
|
| 255 |
-func (m *Quantile) GetValue() float64 {
|
|
| 256 |
- if m != nil && m.Value != nil {
|
|
| 257 |
- return *m.Value |
|
| 309 |
+func (x *Quantile) GetValue() float64 {
|
|
| 310 |
+ if x != nil && x.Value != nil {
|
|
| 311 |
+ return *x.Value |
|
| 258 | 312 |
} |
| 259 | 313 |
return 0 |
| 260 | 314 |
} |
| 261 | 315 |
|
| 262 | 316 |
type Summary struct {
|
| 263 |
- SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` |
|
| 264 |
- SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` |
|
| 265 |
- Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` |
|
| 266 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 267 |
- XXX_unrecognized []byte `json:"-"` |
|
| 268 |
- XXX_sizecache int32 `json:"-"` |
|
| 317 |
+ state protoimpl.MessageState |
|
| 318 |
+ sizeCache protoimpl.SizeCache |
|
| 319 |
+ unknownFields protoimpl.UnknownFields |
|
| 320 |
+ |
|
| 321 |
+ SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` |
|
| 322 |
+ SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` |
|
| 323 |
+ Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` |
|
| 324 |
+ CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"` |
|
| 325 |
+} |
|
| 326 |
+ |
|
| 327 |
+func (x *Summary) Reset() {
|
|
| 328 |
+ *x = Summary{}
|
|
| 329 |
+ if protoimpl.UnsafeEnabled {
|
|
| 330 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[4] |
|
| 331 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 332 |
+ ms.StoreMessageInfo(mi) |
|
| 333 |
+ } |
|
| 269 | 334 |
} |
| 270 | 335 |
|
| 271 |
-func (m *Summary) Reset() { *m = Summary{} }
|
|
| 272 |
-func (m *Summary) String() string { return proto.CompactTextString(m) }
|
|
| 273 |
-func (*Summary) ProtoMessage() {}
|
|
| 274 |
-func (*Summary) Descriptor() ([]byte, []int) {
|
|
| 275 |
- return fileDescriptor_d1e5ddb18987a258, []int{4}
|
|
| 336 |
+func (x *Summary) String() string {
|
|
| 337 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 276 | 338 |
} |
| 277 | 339 |
|
| 278 |
-func (m *Summary) XXX_Unmarshal(b []byte) error {
|
|
| 279 |
- return xxx_messageInfo_Summary.Unmarshal(m, b) |
|
| 280 |
-} |
|
| 281 |
-func (m *Summary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 282 |
- return xxx_messageInfo_Summary.Marshal(b, m, deterministic) |
|
| 283 |
-} |
|
| 284 |
-func (m *Summary) XXX_Merge(src proto.Message) {
|
|
| 285 |
- xxx_messageInfo_Summary.Merge(m, src) |
|
| 286 |
-} |
|
| 287 |
-func (m *Summary) XXX_Size() int {
|
|
| 288 |
- return xxx_messageInfo_Summary.Size(m) |
|
| 289 |
-} |
|
| 290 |
-func (m *Summary) XXX_DiscardUnknown() {
|
|
| 291 |
- xxx_messageInfo_Summary.DiscardUnknown(m) |
|
| 340 |
+func (*Summary) ProtoMessage() {}
|
|
| 341 |
+ |
|
| 342 |
+func (x *Summary) ProtoReflect() protoreflect.Message {
|
|
| 343 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[4] |
|
| 344 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 345 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 346 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 347 |
+ ms.StoreMessageInfo(mi) |
|
| 348 |
+ } |
|
| 349 |
+ return ms |
|
| 350 |
+ } |
|
| 351 |
+ return mi.MessageOf(x) |
|
| 292 | 352 |
} |
| 293 | 353 |
|
| 294 |
-var xxx_messageInfo_Summary proto.InternalMessageInfo |
|
| 354 |
+// Deprecated: Use Summary.ProtoReflect.Descriptor instead. |
|
| 355 |
+func (*Summary) Descriptor() ([]byte, []int) {
|
|
| 356 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{4}
|
|
| 357 |
+} |
|
| 295 | 358 |
|
| 296 |
-func (m *Summary) GetSampleCount() uint64 {
|
|
| 297 |
- if m != nil && m.SampleCount != nil {
|
|
| 298 |
- return *m.SampleCount |
|
| 359 |
+func (x *Summary) GetSampleCount() uint64 {
|
|
| 360 |
+ if x != nil && x.SampleCount != nil {
|
|
| 361 |
+ return *x.SampleCount |
|
| 299 | 362 |
} |
| 300 | 363 |
return 0 |
| 301 | 364 |
} |
| 302 | 365 |
|
| 303 |
-func (m *Summary) GetSampleSum() float64 {
|
|
| 304 |
- if m != nil && m.SampleSum != nil {
|
|
| 305 |
- return *m.SampleSum |
|
| 366 |
+func (x *Summary) GetSampleSum() float64 {
|
|
| 367 |
+ if x != nil && x.SampleSum != nil {
|
|
| 368 |
+ return *x.SampleSum |
|
| 306 | 369 |
} |
| 307 | 370 |
return 0 |
| 308 | 371 |
} |
| 309 | 372 |
|
| 310 |
-func (m *Summary) GetQuantile() []*Quantile {
|
|
| 311 |
- if m != nil {
|
|
| 312 |
- return m.Quantile |
|
| 373 |
+func (x *Summary) GetQuantile() []*Quantile {
|
|
| 374 |
+ if x != nil {
|
|
| 375 |
+ return x.Quantile |
|
| 313 | 376 |
} |
| 314 | 377 |
return nil |
| 315 | 378 |
} |
| 316 | 379 |
|
| 317 |
-type Untyped struct {
|
|
| 318 |
- Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` |
|
| 319 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 320 |
- XXX_unrecognized []byte `json:"-"` |
|
| 321 |
- XXX_sizecache int32 `json:"-"` |
|
| 380 |
+func (x *Summary) GetCreatedTimestamp() *timestamppb.Timestamp {
|
|
| 381 |
+ if x != nil {
|
|
| 382 |
+ return x.CreatedTimestamp |
|
| 383 |
+ } |
|
| 384 |
+ return nil |
|
| 322 | 385 |
} |
| 323 | 386 |
|
| 324 |
-func (m *Untyped) Reset() { *m = Untyped{} }
|
|
| 325 |
-func (m *Untyped) String() string { return proto.CompactTextString(m) }
|
|
| 326 |
-func (*Untyped) ProtoMessage() {}
|
|
| 327 |
-func (*Untyped) Descriptor() ([]byte, []int) {
|
|
| 328 |
- return fileDescriptor_d1e5ddb18987a258, []int{5}
|
|
| 329 |
-} |
|
| 387 |
+type Untyped struct {
|
|
| 388 |
+ state protoimpl.MessageState |
|
| 389 |
+ sizeCache protoimpl.SizeCache |
|
| 390 |
+ unknownFields protoimpl.UnknownFields |
|
| 330 | 391 |
|
| 331 |
-func (m *Untyped) XXX_Unmarshal(b []byte) error {
|
|
| 332 |
- return xxx_messageInfo_Untyped.Unmarshal(m, b) |
|
| 333 |
-} |
|
| 334 |
-func (m *Untyped) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 335 |
- return xxx_messageInfo_Untyped.Marshal(b, m, deterministic) |
|
| 392 |
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` |
|
| 336 | 393 |
} |
| 337 |
-func (m *Untyped) XXX_Merge(src proto.Message) {
|
|
| 338 |
- xxx_messageInfo_Untyped.Merge(m, src) |
|
| 394 |
+ |
|
| 395 |
+func (x *Untyped) Reset() {
|
|
| 396 |
+ *x = Untyped{}
|
|
| 397 |
+ if protoimpl.UnsafeEnabled {
|
|
| 398 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[5] |
|
| 399 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 400 |
+ ms.StoreMessageInfo(mi) |
|
| 401 |
+ } |
|
| 339 | 402 |
} |
| 340 |
-func (m *Untyped) XXX_Size() int {
|
|
| 341 |
- return xxx_messageInfo_Untyped.Size(m) |
|
| 403 |
+ |
|
| 404 |
+func (x *Untyped) String() string {
|
|
| 405 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 342 | 406 |
} |
| 343 |
-func (m *Untyped) XXX_DiscardUnknown() {
|
|
| 344 |
- xxx_messageInfo_Untyped.DiscardUnknown(m) |
|
| 407 |
+ |
|
| 408 |
+func (*Untyped) ProtoMessage() {}
|
|
| 409 |
+ |
|
| 410 |
+func (x *Untyped) ProtoReflect() protoreflect.Message {
|
|
| 411 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[5] |
|
| 412 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 413 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 414 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 415 |
+ ms.StoreMessageInfo(mi) |
|
| 416 |
+ } |
|
| 417 |
+ return ms |
|
| 418 |
+ } |
|
| 419 |
+ return mi.MessageOf(x) |
|
| 345 | 420 |
} |
| 346 | 421 |
|
| 347 |
-var xxx_messageInfo_Untyped proto.InternalMessageInfo |
|
| 422 |
+// Deprecated: Use Untyped.ProtoReflect.Descriptor instead. |
|
| 423 |
+func (*Untyped) Descriptor() ([]byte, []int) {
|
|
| 424 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{5}
|
|
| 425 |
+} |
|
| 348 | 426 |
|
| 349 |
-func (m *Untyped) GetValue() float64 {
|
|
| 350 |
- if m != nil && m.Value != nil {
|
|
| 351 |
- return *m.Value |
|
| 427 |
+func (x *Untyped) GetValue() float64 {
|
|
| 428 |
+ if x != nil && x.Value != nil {
|
|
| 429 |
+ return *x.Value |
|
| 352 | 430 |
} |
| 353 | 431 |
return 0 |
| 354 | 432 |
} |
| 355 | 433 |
|
| 356 | 434 |
type Histogram struct {
|
| 435 |
+ state protoimpl.MessageState |
|
| 436 |
+ sizeCache protoimpl.SizeCache |
|
| 437 |
+ unknownFields protoimpl.UnknownFields |
|
| 438 |
+ |
|
| 357 | 439 |
SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` |
| 358 |
- SampleCountFloat *float64 `protobuf:"fixed64,4,opt,name=sample_count_float,json=sampleCountFloat" json:"sample_count_float,omitempty"` |
|
| 440 |
+ SampleCountFloat *float64 `protobuf:"fixed64,4,opt,name=sample_count_float,json=sampleCountFloat" json:"sample_count_float,omitempty"` // Overrides sample_count if > 0. |
|
| 359 | 441 |
SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` |
| 360 | 442 |
// Buckets for the conventional histogram. |
| 361 |
- Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` |
|
| 443 |
+ Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` // Ordered in increasing order of upper_bound, +Inf bucket is optional. |
|
| 444 |
+ CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,15,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"` |
|
| 362 | 445 |
// schema defines the bucket schema. Currently, valid numbers are -4 <= n <= 8. |
| 363 | 446 |
// They are all for base-2 bucket schemas, where 1 is a bucket boundary in each case, and |
| 364 | 447 |
// then each power of two is divided into 2^n logarithmic buckets. |
| 365 | 448 |
// Or in other words, each bucket boundary is the previous boundary times 2^(2^-n). |
| 366 | 449 |
// In the future, more bucket schemas may be added using numbers < -4 or > 8. |
| 367 | 450 |
Schema *int32 `protobuf:"zigzag32,5,opt,name=schema" json:"schema,omitempty"` |
| 368 |
- ZeroThreshold *float64 `protobuf:"fixed64,6,opt,name=zero_threshold,json=zeroThreshold" json:"zero_threshold,omitempty"` |
|
| 369 |
- ZeroCount *uint64 `protobuf:"varint,7,opt,name=zero_count,json=zeroCount" json:"zero_count,omitempty"` |
|
| 370 |
- ZeroCountFloat *float64 `protobuf:"fixed64,8,opt,name=zero_count_float,json=zeroCountFloat" json:"zero_count_float,omitempty"` |
|
| 451 |
+ ZeroThreshold *float64 `protobuf:"fixed64,6,opt,name=zero_threshold,json=zeroThreshold" json:"zero_threshold,omitempty"` // Breadth of the zero bucket. |
|
| 452 |
+ ZeroCount *uint64 `protobuf:"varint,7,opt,name=zero_count,json=zeroCount" json:"zero_count,omitempty"` // Count in zero bucket. |
|
| 453 |
+ ZeroCountFloat *float64 `protobuf:"fixed64,8,opt,name=zero_count_float,json=zeroCountFloat" json:"zero_count_float,omitempty"` // Overrides sb_zero_count if > 0. |
|
| 371 | 454 |
// Negative buckets for the native histogram. |
| 372 | 455 |
NegativeSpan []*BucketSpan `protobuf:"bytes,9,rep,name=negative_span,json=negativeSpan" json:"negative_span,omitempty"` |
| 373 | 456 |
// Use either "negative_delta" or "negative_count", the former for |
| 374 | 457 |
// regular histograms with integer counts, the latter for float |
| 375 | 458 |
// histograms. |
| 376 |
- NegativeDelta []int64 `protobuf:"zigzag64,10,rep,name=negative_delta,json=negativeDelta" json:"negative_delta,omitempty"` |
|
| 377 |
- NegativeCount []float64 `protobuf:"fixed64,11,rep,name=negative_count,json=negativeCount" json:"negative_count,omitempty"` |
|
| 459 |
+ NegativeDelta []int64 `protobuf:"zigzag64,10,rep,name=negative_delta,json=negativeDelta" json:"negative_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). |
|
| 460 |
+ NegativeCount []float64 `protobuf:"fixed64,11,rep,name=negative_count,json=negativeCount" json:"negative_count,omitempty"` // Absolute count of each bucket. |
|
| 378 | 461 |
// Positive buckets for the native histogram. |
| 462 |
+ // Use a no-op span (offset 0, length 0) for a native histogram without any |
|
| 463 |
+ // observations yet and with a zero_threshold of 0. Otherwise, it would be |
|
| 464 |
+ // indistinguishable from a classic histogram. |
|
| 379 | 465 |
PositiveSpan []*BucketSpan `protobuf:"bytes,12,rep,name=positive_span,json=positiveSpan" json:"positive_span,omitempty"` |
| 380 | 466 |
// Use either "positive_delta" or "positive_count", the former for |
| 381 | 467 |
// regular histograms with integer counts, the latter for float |
| 382 | 468 |
// histograms. |
| 383 |
- PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` |
|
| 384 |
- PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` |
|
| 385 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 386 |
- XXX_unrecognized []byte `json:"-"` |
|
| 387 |
- XXX_sizecache int32 `json:"-"` |
|
| 469 |
+ PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). |
|
| 470 |
+ PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` // Absolute count of each bucket. |
|
| 388 | 471 |
} |
| 389 | 472 |
|
| 390 |
-func (m *Histogram) Reset() { *m = Histogram{} }
|
|
| 391 |
-func (m *Histogram) String() string { return proto.CompactTextString(m) }
|
|
| 392 |
-func (*Histogram) ProtoMessage() {}
|
|
| 393 |
-func (*Histogram) Descriptor() ([]byte, []int) {
|
|
| 394 |
- return fileDescriptor_d1e5ddb18987a258, []int{6}
|
|
| 473 |
+func (x *Histogram) Reset() {
|
|
| 474 |
+ *x = Histogram{}
|
|
| 475 |
+ if protoimpl.UnsafeEnabled {
|
|
| 476 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[6] |
|
| 477 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 478 |
+ ms.StoreMessageInfo(mi) |
|
| 479 |
+ } |
|
| 395 | 480 |
} |
| 396 | 481 |
|
| 397 |
-func (m *Histogram) XXX_Unmarshal(b []byte) error {
|
|
| 398 |
- return xxx_messageInfo_Histogram.Unmarshal(m, b) |
|
| 399 |
-} |
|
| 400 |
-func (m *Histogram) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 401 |
- return xxx_messageInfo_Histogram.Marshal(b, m, deterministic) |
|
| 402 |
-} |
|
| 403 |
-func (m *Histogram) XXX_Merge(src proto.Message) {
|
|
| 404 |
- xxx_messageInfo_Histogram.Merge(m, src) |
|
| 482 |
+func (x *Histogram) String() string {
|
|
| 483 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 405 | 484 |
} |
| 406 |
-func (m *Histogram) XXX_Size() int {
|
|
| 407 |
- return xxx_messageInfo_Histogram.Size(m) |
|
| 408 |
-} |
|
| 409 |
-func (m *Histogram) XXX_DiscardUnknown() {
|
|
| 410 |
- xxx_messageInfo_Histogram.DiscardUnknown(m) |
|
| 485 |
+ |
|
| 486 |
+func (*Histogram) ProtoMessage() {}
|
|
| 487 |
+ |
|
| 488 |
+func (x *Histogram) ProtoReflect() protoreflect.Message {
|
|
| 489 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[6] |
|
| 490 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 491 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 492 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 493 |
+ ms.StoreMessageInfo(mi) |
|
| 494 |
+ } |
|
| 495 |
+ return ms |
|
| 496 |
+ } |
|
| 497 |
+ return mi.MessageOf(x) |
|
| 411 | 498 |
} |
| 412 | 499 |
|
| 413 |
-var xxx_messageInfo_Histogram proto.InternalMessageInfo |
|
| 500 |
+// Deprecated: Use Histogram.ProtoReflect.Descriptor instead. |
|
| 501 |
+func (*Histogram) Descriptor() ([]byte, []int) {
|
|
| 502 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{6}
|
|
| 503 |
+} |
|
| 414 | 504 |
|
| 415 |
-func (m *Histogram) GetSampleCount() uint64 {
|
|
| 416 |
- if m != nil && m.SampleCount != nil {
|
|
| 417 |
- return *m.SampleCount |
|
| 505 |
+func (x *Histogram) GetSampleCount() uint64 {
|
|
| 506 |
+ if x != nil && x.SampleCount != nil {
|
|
| 507 |
+ return *x.SampleCount |
|
| 418 | 508 |
} |
| 419 | 509 |
return 0 |
| 420 | 510 |
} |
| 421 | 511 |
|
| 422 |
-func (m *Histogram) GetSampleCountFloat() float64 {
|
|
| 423 |
- if m != nil && m.SampleCountFloat != nil {
|
|
| 424 |
- return *m.SampleCountFloat |
|
| 512 |
+func (x *Histogram) GetSampleCountFloat() float64 {
|
|
| 513 |
+ if x != nil && x.SampleCountFloat != nil {
|
|
| 514 |
+ return *x.SampleCountFloat |
|
| 425 | 515 |
} |
| 426 | 516 |
return 0 |
| 427 | 517 |
} |
| 428 | 518 |
|
| 429 |
-func (m *Histogram) GetSampleSum() float64 {
|
|
| 430 |
- if m != nil && m.SampleSum != nil {
|
|
| 431 |
- return *m.SampleSum |
|
| 519 |
+func (x *Histogram) GetSampleSum() float64 {
|
|
| 520 |
+ if x != nil && x.SampleSum != nil {
|
|
| 521 |
+ return *x.SampleSum |
|
| 432 | 522 |
} |
| 433 | 523 |
return 0 |
| 434 | 524 |
} |
| 435 | 525 |
|
| 436 |
-func (m *Histogram) GetBucket() []*Bucket {
|
|
| 437 |
- if m != nil {
|
|
| 438 |
- return m.Bucket |
|
| 526 |
+func (x *Histogram) GetBucket() []*Bucket {
|
|
| 527 |
+ if x != nil {
|
|
| 528 |
+ return x.Bucket |
|
| 529 |
+ } |
|
| 530 |
+ return nil |
|
| 531 |
+} |
|
| 532 |
+ |
|
| 533 |
+func (x *Histogram) GetCreatedTimestamp() *timestamppb.Timestamp {
|
|
| 534 |
+ if x != nil {
|
|
| 535 |
+ return x.CreatedTimestamp |
|
| 439 | 536 |
} |
| 440 | 537 |
return nil |
| 441 | 538 |
} |
| 442 | 539 |
|
| 443 |
-func (m *Histogram) GetSchema() int32 {
|
|
| 444 |
- if m != nil && m.Schema != nil {
|
|
| 445 |
- return *m.Schema |
|
| 540 |
+func (x *Histogram) GetSchema() int32 {
|
|
| 541 |
+ if x != nil && x.Schema != nil {
|
|
| 542 |
+ return *x.Schema |
|
| 446 | 543 |
} |
| 447 | 544 |
return 0 |
| 448 | 545 |
} |
| 449 | 546 |
|
| 450 |
-func (m *Histogram) GetZeroThreshold() float64 {
|
|
| 451 |
- if m != nil && m.ZeroThreshold != nil {
|
|
| 452 |
- return *m.ZeroThreshold |
|
| 547 |
+func (x *Histogram) GetZeroThreshold() float64 {
|
|
| 548 |
+ if x != nil && x.ZeroThreshold != nil {
|
|
| 549 |
+ return *x.ZeroThreshold |
|
| 453 | 550 |
} |
| 454 | 551 |
return 0 |
| 455 | 552 |
} |
| 456 | 553 |
|
| 457 |
-func (m *Histogram) GetZeroCount() uint64 {
|
|
| 458 |
- if m != nil && m.ZeroCount != nil {
|
|
| 459 |
- return *m.ZeroCount |
|
| 554 |
+func (x *Histogram) GetZeroCount() uint64 {
|
|
| 555 |
+ if x != nil && x.ZeroCount != nil {
|
|
| 556 |
+ return *x.ZeroCount |
|
| 460 | 557 |
} |
| 461 | 558 |
return 0 |
| 462 | 559 |
} |
| 463 | 560 |
|
| 464 |
-func (m *Histogram) GetZeroCountFloat() float64 {
|
|
| 465 |
- if m != nil && m.ZeroCountFloat != nil {
|
|
| 466 |
- return *m.ZeroCountFloat |
|
| 561 |
+func (x *Histogram) GetZeroCountFloat() float64 {
|
|
| 562 |
+ if x != nil && x.ZeroCountFloat != nil {
|
|
| 563 |
+ return *x.ZeroCountFloat |
|
| 467 | 564 |
} |
| 468 | 565 |
return 0 |
| 469 | 566 |
} |
| 470 | 567 |
|
| 471 |
-func (m *Histogram) GetNegativeSpan() []*BucketSpan {
|
|
| 472 |
- if m != nil {
|
|
| 473 |
- return m.NegativeSpan |
|
| 568 |
+func (x *Histogram) GetNegativeSpan() []*BucketSpan {
|
|
| 569 |
+ if x != nil {
|
|
| 570 |
+ return x.NegativeSpan |
|
| 474 | 571 |
} |
| 475 | 572 |
return nil |
| 476 | 573 |
} |
| 477 | 574 |
|
| 478 |
-func (m *Histogram) GetNegativeDelta() []int64 {
|
|
| 479 |
- if m != nil {
|
|
| 480 |
- return m.NegativeDelta |
|
| 575 |
+func (x *Histogram) GetNegativeDelta() []int64 {
|
|
| 576 |
+ if x != nil {
|
|
| 577 |
+ return x.NegativeDelta |
|
| 481 | 578 |
} |
| 482 | 579 |
return nil |
| 483 | 580 |
} |
| 484 | 581 |
|
| 485 |
-func (m *Histogram) GetNegativeCount() []float64 {
|
|
| 486 |
- if m != nil {
|
|
| 487 |
- return m.NegativeCount |
|
| 582 |
+func (x *Histogram) GetNegativeCount() []float64 {
|
|
| 583 |
+ if x != nil {
|
|
| 584 |
+ return x.NegativeCount |
|
| 488 | 585 |
} |
| 489 | 586 |
return nil |
| 490 | 587 |
} |
| 491 | 588 |
|
| 492 |
-func (m *Histogram) GetPositiveSpan() []*BucketSpan {
|
|
| 493 |
- if m != nil {
|
|
| 494 |
- return m.PositiveSpan |
|
| 589 |
+func (x *Histogram) GetPositiveSpan() []*BucketSpan {
|
|
| 590 |
+ if x != nil {
|
|
| 591 |
+ return x.PositiveSpan |
|
| 495 | 592 |
} |
| 496 | 593 |
return nil |
| 497 | 594 |
} |
| 498 | 595 |
|
| 499 |
-func (m *Histogram) GetPositiveDelta() []int64 {
|
|
| 500 |
- if m != nil {
|
|
| 501 |
- return m.PositiveDelta |
|
| 596 |
+func (x *Histogram) GetPositiveDelta() []int64 {
|
|
| 597 |
+ if x != nil {
|
|
| 598 |
+ return x.PositiveDelta |
|
| 502 | 599 |
} |
| 503 | 600 |
return nil |
| 504 | 601 |
} |
| 505 | 602 |
|
| 506 |
-func (m *Histogram) GetPositiveCount() []float64 {
|
|
| 507 |
- if m != nil {
|
|
| 508 |
- return m.PositiveCount |
|
| 603 |
+func (x *Histogram) GetPositiveCount() []float64 {
|
|
| 604 |
+ if x != nil {
|
|
| 605 |
+ return x.PositiveCount |
|
| 509 | 606 |
} |
| 510 | 607 |
return nil |
| 511 | 608 |
} |
| ... | ... |
@@ -513,64 +625,72 @@ func (m *Histogram) GetPositiveCount() []float64 {
|
| 513 | 513 |
// A Bucket of a conventional histogram, each of which is treated as |
| 514 | 514 |
// an individual counter-like time series by Prometheus. |
| 515 | 515 |
type Bucket struct {
|
| 516 |
- CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"` |
|
| 517 |
- CumulativeCountFloat *float64 `protobuf:"fixed64,4,opt,name=cumulative_count_float,json=cumulativeCountFloat" json:"cumulative_count_float,omitempty"` |
|
| 518 |
- UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` |
|
| 516 |
+ state protoimpl.MessageState |
|
| 517 |
+ sizeCache protoimpl.SizeCache |
|
| 518 |
+ unknownFields protoimpl.UnknownFields |
|
| 519 |
+ |
|
| 520 |
+ CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"` // Cumulative in increasing order. |
|
| 521 |
+ CumulativeCountFloat *float64 `protobuf:"fixed64,4,opt,name=cumulative_count_float,json=cumulativeCountFloat" json:"cumulative_count_float,omitempty"` // Overrides cumulative_count if > 0. |
|
| 522 |
+ UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` // Inclusive. |
|
| 519 | 523 |
Exemplar *Exemplar `protobuf:"bytes,3,opt,name=exemplar" json:"exemplar,omitempty"` |
| 520 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 521 |
- XXX_unrecognized []byte `json:"-"` |
|
| 522 |
- XXX_sizecache int32 `json:"-"` |
|
| 523 | 524 |
} |
| 524 | 525 |
|
| 525 |
-func (m *Bucket) Reset() { *m = Bucket{} }
|
|
| 526 |
-func (m *Bucket) String() string { return proto.CompactTextString(m) }
|
|
| 527 |
-func (*Bucket) ProtoMessage() {}
|
|
| 528 |
-func (*Bucket) Descriptor() ([]byte, []int) {
|
|
| 529 |
- return fileDescriptor_d1e5ddb18987a258, []int{7}
|
|
| 526 |
+func (x *Bucket) Reset() {
|
|
| 527 |
+ *x = Bucket{}
|
|
| 528 |
+ if protoimpl.UnsafeEnabled {
|
|
| 529 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[7] |
|
| 530 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 531 |
+ ms.StoreMessageInfo(mi) |
|
| 532 |
+ } |
|
| 530 | 533 |
} |
| 531 | 534 |
|
| 532 |
-func (m *Bucket) XXX_Unmarshal(b []byte) error {
|
|
| 533 |
- return xxx_messageInfo_Bucket.Unmarshal(m, b) |
|
| 534 |
-} |
|
| 535 |
-func (m *Bucket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 536 |
- return xxx_messageInfo_Bucket.Marshal(b, m, deterministic) |
|
| 537 |
-} |
|
| 538 |
-func (m *Bucket) XXX_Merge(src proto.Message) {
|
|
| 539 |
- xxx_messageInfo_Bucket.Merge(m, src) |
|
| 535 |
+func (x *Bucket) String() string {
|
|
| 536 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 540 | 537 |
} |
| 541 |
-func (m *Bucket) XXX_Size() int {
|
|
| 542 |
- return xxx_messageInfo_Bucket.Size(m) |
|
| 543 |
-} |
|
| 544 |
-func (m *Bucket) XXX_DiscardUnknown() {
|
|
| 545 |
- xxx_messageInfo_Bucket.DiscardUnknown(m) |
|
| 538 |
+ |
|
| 539 |
+func (*Bucket) ProtoMessage() {}
|
|
| 540 |
+ |
|
| 541 |
+func (x *Bucket) ProtoReflect() protoreflect.Message {
|
|
| 542 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[7] |
|
| 543 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 544 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 545 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 546 |
+ ms.StoreMessageInfo(mi) |
|
| 547 |
+ } |
|
| 548 |
+ return ms |
|
| 549 |
+ } |
|
| 550 |
+ return mi.MessageOf(x) |
|
| 546 | 551 |
} |
| 547 | 552 |
|
| 548 |
-var xxx_messageInfo_Bucket proto.InternalMessageInfo |
|
| 553 |
+// Deprecated: Use Bucket.ProtoReflect.Descriptor instead. |
|
| 554 |
+func (*Bucket) Descriptor() ([]byte, []int) {
|
|
| 555 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{7}
|
|
| 556 |
+} |
|
| 549 | 557 |
|
| 550 |
-func (m *Bucket) GetCumulativeCount() uint64 {
|
|
| 551 |
- if m != nil && m.CumulativeCount != nil {
|
|
| 552 |
- return *m.CumulativeCount |
|
| 558 |
+func (x *Bucket) GetCumulativeCount() uint64 {
|
|
| 559 |
+ if x != nil && x.CumulativeCount != nil {
|
|
| 560 |
+ return *x.CumulativeCount |
|
| 553 | 561 |
} |
| 554 | 562 |
return 0 |
| 555 | 563 |
} |
| 556 | 564 |
|
| 557 |
-func (m *Bucket) GetCumulativeCountFloat() float64 {
|
|
| 558 |
- if m != nil && m.CumulativeCountFloat != nil {
|
|
| 559 |
- return *m.CumulativeCountFloat |
|
| 565 |
+func (x *Bucket) GetCumulativeCountFloat() float64 {
|
|
| 566 |
+ if x != nil && x.CumulativeCountFloat != nil {
|
|
| 567 |
+ return *x.CumulativeCountFloat |
|
| 560 | 568 |
} |
| 561 | 569 |
return 0 |
| 562 | 570 |
} |
| 563 | 571 |
|
| 564 |
-func (m *Bucket) GetUpperBound() float64 {
|
|
| 565 |
- if m != nil && m.UpperBound != nil {
|
|
| 566 |
- return *m.UpperBound |
|
| 572 |
+func (x *Bucket) GetUpperBound() float64 {
|
|
| 573 |
+ if x != nil && x.UpperBound != nil {
|
|
| 574 |
+ return *x.UpperBound |
|
| 567 | 575 |
} |
| 568 | 576 |
return 0 |
| 569 | 577 |
} |
| 570 | 578 |
|
| 571 |
-func (m *Bucket) GetExemplar() *Exemplar {
|
|
| 572 |
- if m != nil {
|
|
| 573 |
- return m.Exemplar |
|
| 579 |
+func (x *Bucket) GetExemplar() *Exemplar {
|
|
| 580 |
+ if x != nil {
|
|
| 581 |
+ return x.Exemplar |
|
| 574 | 582 |
} |
| 575 | 583 |
return nil |
| 576 | 584 |
} |
| ... | ... |
@@ -582,333 +702,675 @@ func (m *Bucket) GetExemplar() *Exemplar {
|
| 582 | 582 |
// structured here (with all the buckets in a single array separate |
| 583 | 583 |
// from the Spans). |
| 584 | 584 |
type BucketSpan struct {
|
| 585 |
- Offset *int32 `protobuf:"zigzag32,1,opt,name=offset" json:"offset,omitempty"` |
|
| 586 |
- Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` |
|
| 587 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 588 |
- XXX_unrecognized []byte `json:"-"` |
|
| 589 |
- XXX_sizecache int32 `json:"-"` |
|
| 590 |
-} |
|
| 585 |
+ state protoimpl.MessageState |
|
| 586 |
+ sizeCache protoimpl.SizeCache |
|
| 587 |
+ unknownFields protoimpl.UnknownFields |
|
| 591 | 588 |
|
| 592 |
-func (m *BucketSpan) Reset() { *m = BucketSpan{} }
|
|
| 593 |
-func (m *BucketSpan) String() string { return proto.CompactTextString(m) }
|
|
| 594 |
-func (*BucketSpan) ProtoMessage() {}
|
|
| 595 |
-func (*BucketSpan) Descriptor() ([]byte, []int) {
|
|
| 596 |
- return fileDescriptor_d1e5ddb18987a258, []int{8}
|
|
| 589 |
+ Offset *int32 `protobuf:"zigzag32,1,opt,name=offset" json:"offset,omitempty"` // Gap to previous span, or starting point for 1st span (which can be negative). |
|
| 590 |
+ Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` // Length of consecutive buckets. |
|
| 597 | 591 |
} |
| 598 | 592 |
|
| 599 |
-func (m *BucketSpan) XXX_Unmarshal(b []byte) error {
|
|
| 600 |
- return xxx_messageInfo_BucketSpan.Unmarshal(m, b) |
|
| 601 |
-} |
|
| 602 |
-func (m *BucketSpan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 603 |
- return xxx_messageInfo_BucketSpan.Marshal(b, m, deterministic) |
|
| 604 |
-} |
|
| 605 |
-func (m *BucketSpan) XXX_Merge(src proto.Message) {
|
|
| 606 |
- xxx_messageInfo_BucketSpan.Merge(m, src) |
|
| 593 |
+func (x *BucketSpan) Reset() {
|
|
| 594 |
+ *x = BucketSpan{}
|
|
| 595 |
+ if protoimpl.UnsafeEnabled {
|
|
| 596 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[8] |
|
| 597 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 598 |
+ ms.StoreMessageInfo(mi) |
|
| 599 |
+ } |
|
| 607 | 600 |
} |
| 608 |
-func (m *BucketSpan) XXX_Size() int {
|
|
| 609 |
- return xxx_messageInfo_BucketSpan.Size(m) |
|
| 601 |
+ |
|
| 602 |
+func (x *BucketSpan) String() string {
|
|
| 603 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 610 | 604 |
} |
| 611 |
-func (m *BucketSpan) XXX_DiscardUnknown() {
|
|
| 612 |
- xxx_messageInfo_BucketSpan.DiscardUnknown(m) |
|
| 605 |
+ |
|
| 606 |
+func (*BucketSpan) ProtoMessage() {}
|
|
| 607 |
+ |
|
| 608 |
+func (x *BucketSpan) ProtoReflect() protoreflect.Message {
|
|
| 609 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[8] |
|
| 610 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 611 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 612 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 613 |
+ ms.StoreMessageInfo(mi) |
|
| 614 |
+ } |
|
| 615 |
+ return ms |
|
| 616 |
+ } |
|
| 617 |
+ return mi.MessageOf(x) |
|
| 613 | 618 |
} |
| 614 | 619 |
|
| 615 |
-var xxx_messageInfo_BucketSpan proto.InternalMessageInfo |
|
| 620 |
+// Deprecated: Use BucketSpan.ProtoReflect.Descriptor instead. |
|
| 621 |
+func (*BucketSpan) Descriptor() ([]byte, []int) {
|
|
| 622 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{8}
|
|
| 623 |
+} |
|
| 616 | 624 |
|
| 617 |
-func (m *BucketSpan) GetOffset() int32 {
|
|
| 618 |
- if m != nil && m.Offset != nil {
|
|
| 619 |
- return *m.Offset |
|
| 625 |
+func (x *BucketSpan) GetOffset() int32 {
|
|
| 626 |
+ if x != nil && x.Offset != nil {
|
|
| 627 |
+ return *x.Offset |
|
| 620 | 628 |
} |
| 621 | 629 |
return 0 |
| 622 | 630 |
} |
| 623 | 631 |
|
| 624 |
-func (m *BucketSpan) GetLength() uint32 {
|
|
| 625 |
- if m != nil && m.Length != nil {
|
|
| 626 |
- return *m.Length |
|
| 632 |
+func (x *BucketSpan) GetLength() uint32 {
|
|
| 633 |
+ if x != nil && x.Length != nil {
|
|
| 634 |
+ return *x.Length |
|
| 627 | 635 |
} |
| 628 | 636 |
return 0 |
| 629 | 637 |
} |
| 630 | 638 |
|
| 631 | 639 |
type Exemplar struct {
|
| 632 |
- Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` |
|
| 633 |
- Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` |
|
| 634 |
- Timestamp *timestamp.Timestamp `protobuf:"bytes,3,opt,name=timestamp" json:"timestamp,omitempty"` |
|
| 635 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 636 |
- XXX_unrecognized []byte `json:"-"` |
|
| 637 |
- XXX_sizecache int32 `json:"-"` |
|
| 638 |
-} |
|
| 640 |
+ state protoimpl.MessageState |
|
| 641 |
+ sizeCache protoimpl.SizeCache |
|
| 642 |
+ unknownFields protoimpl.UnknownFields |
|
| 639 | 643 |
|
| 640 |
-func (m *Exemplar) Reset() { *m = Exemplar{} }
|
|
| 641 |
-func (m *Exemplar) String() string { return proto.CompactTextString(m) }
|
|
| 642 |
-func (*Exemplar) ProtoMessage() {}
|
|
| 643 |
-func (*Exemplar) Descriptor() ([]byte, []int) {
|
|
| 644 |
- return fileDescriptor_d1e5ddb18987a258, []int{9}
|
|
| 644 |
+ Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` |
|
| 645 |
+ Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` |
|
| 646 |
+ Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp" json:"timestamp,omitempty"` // OpenMetrics-style. |
|
| 645 | 647 |
} |
| 646 | 648 |
|
| 647 |
-func (m *Exemplar) XXX_Unmarshal(b []byte) error {
|
|
| 648 |
- return xxx_messageInfo_Exemplar.Unmarshal(m, b) |
|
| 649 |
-} |
|
| 650 |
-func (m *Exemplar) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 651 |
- return xxx_messageInfo_Exemplar.Marshal(b, m, deterministic) |
|
| 652 |
-} |
|
| 653 |
-func (m *Exemplar) XXX_Merge(src proto.Message) {
|
|
| 654 |
- xxx_messageInfo_Exemplar.Merge(m, src) |
|
| 649 |
+func (x *Exemplar) Reset() {
|
|
| 650 |
+ *x = Exemplar{}
|
|
| 651 |
+ if protoimpl.UnsafeEnabled {
|
|
| 652 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[9] |
|
| 653 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 654 |
+ ms.StoreMessageInfo(mi) |
|
| 655 |
+ } |
|
| 655 | 656 |
} |
| 656 |
-func (m *Exemplar) XXX_Size() int {
|
|
| 657 |
- return xxx_messageInfo_Exemplar.Size(m) |
|
| 657 |
+ |
|
| 658 |
+func (x *Exemplar) String() string {
|
|
| 659 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 658 | 660 |
} |
| 659 |
-func (m *Exemplar) XXX_DiscardUnknown() {
|
|
| 660 |
- xxx_messageInfo_Exemplar.DiscardUnknown(m) |
|
| 661 |
+ |
|
| 662 |
+func (*Exemplar) ProtoMessage() {}
|
|
| 663 |
+ |
|
| 664 |
+func (x *Exemplar) ProtoReflect() protoreflect.Message {
|
|
| 665 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[9] |
|
| 666 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 667 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 668 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 669 |
+ ms.StoreMessageInfo(mi) |
|
| 670 |
+ } |
|
| 671 |
+ return ms |
|
| 672 |
+ } |
|
| 673 |
+ return mi.MessageOf(x) |
|
| 661 | 674 |
} |
| 662 | 675 |
|
| 663 |
-var xxx_messageInfo_Exemplar proto.InternalMessageInfo |
|
| 676 |
+// Deprecated: Use Exemplar.ProtoReflect.Descriptor instead. |
|
| 677 |
+func (*Exemplar) Descriptor() ([]byte, []int) {
|
|
| 678 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{9}
|
|
| 679 |
+} |
|
| 664 | 680 |
|
| 665 |
-func (m *Exemplar) GetLabel() []*LabelPair {
|
|
| 666 |
- if m != nil {
|
|
| 667 |
- return m.Label |
|
| 681 |
+func (x *Exemplar) GetLabel() []*LabelPair {
|
|
| 682 |
+ if x != nil {
|
|
| 683 |
+ return x.Label |
|
| 668 | 684 |
} |
| 669 | 685 |
return nil |
| 670 | 686 |
} |
| 671 | 687 |
|
| 672 |
-func (m *Exemplar) GetValue() float64 {
|
|
| 673 |
- if m != nil && m.Value != nil {
|
|
| 674 |
- return *m.Value |
|
| 688 |
+func (x *Exemplar) GetValue() float64 {
|
|
| 689 |
+ if x != nil && x.Value != nil {
|
|
| 690 |
+ return *x.Value |
|
| 675 | 691 |
} |
| 676 | 692 |
return 0 |
| 677 | 693 |
} |
| 678 | 694 |
|
| 679 |
-func (m *Exemplar) GetTimestamp() *timestamp.Timestamp {
|
|
| 680 |
- if m != nil {
|
|
| 681 |
- return m.Timestamp |
|
| 695 |
+func (x *Exemplar) GetTimestamp() *timestamppb.Timestamp {
|
|
| 696 |
+ if x != nil {
|
|
| 697 |
+ return x.Timestamp |
|
| 682 | 698 |
} |
| 683 | 699 |
return nil |
| 684 | 700 |
} |
| 685 | 701 |
|
| 686 | 702 |
type Metric struct {
|
| 687 |
- Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` |
|
| 688 |
- Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` |
|
| 689 |
- Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` |
|
| 690 |
- Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` |
|
| 691 |
- Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` |
|
| 692 |
- Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` |
|
| 693 |
- TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"` |
|
| 694 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 695 |
- XXX_unrecognized []byte `json:"-"` |
|
| 696 |
- XXX_sizecache int32 `json:"-"` |
|
| 697 |
-} |
|
| 698 |
- |
|
| 699 |
-func (m *Metric) Reset() { *m = Metric{} }
|
|
| 700 |
-func (m *Metric) String() string { return proto.CompactTextString(m) }
|
|
| 701 |
-func (*Metric) ProtoMessage() {}
|
|
| 702 |
-func (*Metric) Descriptor() ([]byte, []int) {
|
|
| 703 |
- return fileDescriptor_d1e5ddb18987a258, []int{10}
|
|
| 703 |
+ state protoimpl.MessageState |
|
| 704 |
+ sizeCache protoimpl.SizeCache |
|
| 705 |
+ unknownFields protoimpl.UnknownFields |
|
| 706 |
+ |
|
| 707 |
+ Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` |
|
| 708 |
+ Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` |
|
| 709 |
+ Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` |
|
| 710 |
+ Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` |
|
| 711 |
+ Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` |
|
| 712 |
+ Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` |
|
| 713 |
+ TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"` |
|
| 714 |
+} |
|
| 715 |
+ |
|
| 716 |
+func (x *Metric) Reset() {
|
|
| 717 |
+ *x = Metric{}
|
|
| 718 |
+ if protoimpl.UnsafeEnabled {
|
|
| 719 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[10] |
|
| 720 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 721 |
+ ms.StoreMessageInfo(mi) |
|
| 722 |
+ } |
|
| 704 | 723 |
} |
| 705 | 724 |
|
| 706 |
-func (m *Metric) XXX_Unmarshal(b []byte) error {
|
|
| 707 |
- return xxx_messageInfo_Metric.Unmarshal(m, b) |
|
| 708 |
-} |
|
| 709 |
-func (m *Metric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 710 |
- return xxx_messageInfo_Metric.Marshal(b, m, deterministic) |
|
| 711 |
-} |
|
| 712 |
-func (m *Metric) XXX_Merge(src proto.Message) {
|
|
| 713 |
- xxx_messageInfo_Metric.Merge(m, src) |
|
| 725 |
+func (x *Metric) String() string {
|
|
| 726 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 714 | 727 |
} |
| 715 |
-func (m *Metric) XXX_Size() int {
|
|
| 716 |
- return xxx_messageInfo_Metric.Size(m) |
|
| 717 |
-} |
|
| 718 |
-func (m *Metric) XXX_DiscardUnknown() {
|
|
| 719 |
- xxx_messageInfo_Metric.DiscardUnknown(m) |
|
| 728 |
+ |
|
| 729 |
+func (*Metric) ProtoMessage() {}
|
|
| 730 |
+ |
|
| 731 |
+func (x *Metric) ProtoReflect() protoreflect.Message {
|
|
| 732 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[10] |
|
| 733 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 734 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 735 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 736 |
+ ms.StoreMessageInfo(mi) |
|
| 737 |
+ } |
|
| 738 |
+ return ms |
|
| 739 |
+ } |
|
| 740 |
+ return mi.MessageOf(x) |
|
| 720 | 741 |
} |
| 721 | 742 |
|
| 722 |
-var xxx_messageInfo_Metric proto.InternalMessageInfo |
|
| 743 |
+// Deprecated: Use Metric.ProtoReflect.Descriptor instead. |
|
| 744 |
+func (*Metric) Descriptor() ([]byte, []int) {
|
|
| 745 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{10}
|
|
| 746 |
+} |
|
| 723 | 747 |
|
| 724 |
-func (m *Metric) GetLabel() []*LabelPair {
|
|
| 725 |
- if m != nil {
|
|
| 726 |
- return m.Label |
|
| 748 |
+func (x *Metric) GetLabel() []*LabelPair {
|
|
| 749 |
+ if x != nil {
|
|
| 750 |
+ return x.Label |
|
| 727 | 751 |
} |
| 728 | 752 |
return nil |
| 729 | 753 |
} |
| 730 | 754 |
|
| 731 |
-func (m *Metric) GetGauge() *Gauge {
|
|
| 732 |
- if m != nil {
|
|
| 733 |
- return m.Gauge |
|
| 755 |
+func (x *Metric) GetGauge() *Gauge {
|
|
| 756 |
+ if x != nil {
|
|
| 757 |
+ return x.Gauge |
|
| 734 | 758 |
} |
| 735 | 759 |
return nil |
| 736 | 760 |
} |
| 737 | 761 |
|
| 738 |
-func (m *Metric) GetCounter() *Counter {
|
|
| 739 |
- if m != nil {
|
|
| 740 |
- return m.Counter |
|
| 762 |
+func (x *Metric) GetCounter() *Counter {
|
|
| 763 |
+ if x != nil {
|
|
| 764 |
+ return x.Counter |
|
| 741 | 765 |
} |
| 742 | 766 |
return nil |
| 743 | 767 |
} |
| 744 | 768 |
|
| 745 |
-func (m *Metric) GetSummary() *Summary {
|
|
| 746 |
- if m != nil {
|
|
| 747 |
- return m.Summary |
|
| 769 |
+func (x *Metric) GetSummary() *Summary {
|
|
| 770 |
+ if x != nil {
|
|
| 771 |
+ return x.Summary |
|
| 748 | 772 |
} |
| 749 | 773 |
return nil |
| 750 | 774 |
} |
| 751 | 775 |
|
| 752 |
-func (m *Metric) GetUntyped() *Untyped {
|
|
| 753 |
- if m != nil {
|
|
| 754 |
- return m.Untyped |
|
| 776 |
+func (x *Metric) GetUntyped() *Untyped {
|
|
| 777 |
+ if x != nil {
|
|
| 778 |
+ return x.Untyped |
|
| 755 | 779 |
} |
| 756 | 780 |
return nil |
| 757 | 781 |
} |
| 758 | 782 |
|
| 759 |
-func (m *Metric) GetHistogram() *Histogram {
|
|
| 760 |
- if m != nil {
|
|
| 761 |
- return m.Histogram |
|
| 783 |
+func (x *Metric) GetHistogram() *Histogram {
|
|
| 784 |
+ if x != nil {
|
|
| 785 |
+ return x.Histogram |
|
| 762 | 786 |
} |
| 763 | 787 |
return nil |
| 764 | 788 |
} |
| 765 | 789 |
|
| 766 |
-func (m *Metric) GetTimestampMs() int64 {
|
|
| 767 |
- if m != nil && m.TimestampMs != nil {
|
|
| 768 |
- return *m.TimestampMs |
|
| 790 |
+func (x *Metric) GetTimestampMs() int64 {
|
|
| 791 |
+ if x != nil && x.TimestampMs != nil {
|
|
| 792 |
+ return *x.TimestampMs |
|
| 769 | 793 |
} |
| 770 | 794 |
return 0 |
| 771 | 795 |
} |
| 772 | 796 |
|
| 773 | 797 |
type MetricFamily struct {
|
| 774 |
- Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` |
|
| 775 |
- Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` |
|
| 776 |
- Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` |
|
| 777 |
- Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` |
|
| 778 |
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
| 779 |
- XXX_unrecognized []byte `json:"-"` |
|
| 780 |
- XXX_sizecache int32 `json:"-"` |
|
| 781 |
-} |
|
| 782 |
- |
|
| 783 |
-func (m *MetricFamily) Reset() { *m = MetricFamily{} }
|
|
| 784 |
-func (m *MetricFamily) String() string { return proto.CompactTextString(m) }
|
|
| 785 |
-func (*MetricFamily) ProtoMessage() {}
|
|
| 786 |
-func (*MetricFamily) Descriptor() ([]byte, []int) {
|
|
| 787 |
- return fileDescriptor_d1e5ddb18987a258, []int{11}
|
|
| 798 |
+ state protoimpl.MessageState |
|
| 799 |
+ sizeCache protoimpl.SizeCache |
|
| 800 |
+ unknownFields protoimpl.UnknownFields |
|
| 801 |
+ |
|
| 802 |
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` |
|
| 803 |
+ Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` |
|
| 804 |
+ Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` |
|
| 805 |
+ Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` |
|
| 806 |
+} |
|
| 807 |
+ |
|
| 808 |
+func (x *MetricFamily) Reset() {
|
|
| 809 |
+ *x = MetricFamily{}
|
|
| 810 |
+ if protoimpl.UnsafeEnabled {
|
|
| 811 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[11] |
|
| 812 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 813 |
+ ms.StoreMessageInfo(mi) |
|
| 814 |
+ } |
|
| 788 | 815 |
} |
| 789 | 816 |
|
| 790 |
-func (m *MetricFamily) XXX_Unmarshal(b []byte) error {
|
|
| 791 |
- return xxx_messageInfo_MetricFamily.Unmarshal(m, b) |
|
| 792 |
-} |
|
| 793 |
-func (m *MetricFamily) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
| 794 |
- return xxx_messageInfo_MetricFamily.Marshal(b, m, deterministic) |
|
| 795 |
-} |
|
| 796 |
-func (m *MetricFamily) XXX_Merge(src proto.Message) {
|
|
| 797 |
- xxx_messageInfo_MetricFamily.Merge(m, src) |
|
| 817 |
+func (x *MetricFamily) String() string {
|
|
| 818 |
+ return protoimpl.X.MessageStringOf(x) |
|
| 798 | 819 |
} |
| 799 |
-func (m *MetricFamily) XXX_Size() int {
|
|
| 800 |
- return xxx_messageInfo_MetricFamily.Size(m) |
|
| 801 |
-} |
|
| 802 |
-func (m *MetricFamily) XXX_DiscardUnknown() {
|
|
| 803 |
- xxx_messageInfo_MetricFamily.DiscardUnknown(m) |
|
| 820 |
+ |
|
| 821 |
+func (*MetricFamily) ProtoMessage() {}
|
|
| 822 |
+ |
|
| 823 |
+func (x *MetricFamily) ProtoReflect() protoreflect.Message {
|
|
| 824 |
+ mi := &file_io_prometheus_client_metrics_proto_msgTypes[11] |
|
| 825 |
+ if protoimpl.UnsafeEnabled && x != nil {
|
|
| 826 |
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|
| 827 |
+ if ms.LoadMessageInfo() == nil {
|
|
| 828 |
+ ms.StoreMessageInfo(mi) |
|
| 829 |
+ } |
|
| 830 |
+ return ms |
|
| 831 |
+ } |
|
| 832 |
+ return mi.MessageOf(x) |
|
| 804 | 833 |
} |
| 805 | 834 |
|
| 806 |
-var xxx_messageInfo_MetricFamily proto.InternalMessageInfo |
|
| 835 |
+// Deprecated: Use MetricFamily.ProtoReflect.Descriptor instead. |
|
| 836 |
+func (*MetricFamily) Descriptor() ([]byte, []int) {
|
|
| 837 |
+ return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{11}
|
|
| 838 |
+} |
|
| 807 | 839 |
|
| 808 |
-func (m *MetricFamily) GetName() string {
|
|
| 809 |
- if m != nil && m.Name != nil {
|
|
| 810 |
- return *m.Name |
|
| 840 |
+func (x *MetricFamily) GetName() string {
|
|
| 841 |
+ if x != nil && x.Name != nil {
|
|
| 842 |
+ return *x.Name |
|
| 811 | 843 |
} |
| 812 | 844 |
return "" |
| 813 | 845 |
} |
| 814 | 846 |
|
| 815 |
-func (m *MetricFamily) GetHelp() string {
|
|
| 816 |
- if m != nil && m.Help != nil {
|
|
| 817 |
- return *m.Help |
|
| 847 |
+func (x *MetricFamily) GetHelp() string {
|
|
| 848 |
+ if x != nil && x.Help != nil {
|
|
| 849 |
+ return *x.Help |
|
| 818 | 850 |
} |
| 819 | 851 |
return "" |
| 820 | 852 |
} |
| 821 | 853 |
|
| 822 |
-func (m *MetricFamily) GetType() MetricType {
|
|
| 823 |
- if m != nil && m.Type != nil {
|
|
| 824 |
- return *m.Type |
|
| 854 |
+func (x *MetricFamily) GetType() MetricType {
|
|
| 855 |
+ if x != nil && x.Type != nil {
|
|
| 856 |
+ return *x.Type |
|
| 825 | 857 |
} |
| 826 | 858 |
return MetricType_COUNTER |
| 827 | 859 |
} |
| 828 | 860 |
|
| 829 |
-func (m *MetricFamily) GetMetric() []*Metric {
|
|
| 830 |
- if m != nil {
|
|
| 831 |
- return m.Metric |
|
| 861 |
+func (x *MetricFamily) GetMetric() []*Metric {
|
|
| 862 |
+ if x != nil {
|
|
| 863 |
+ return x.Metric |
|
| 832 | 864 |
} |
| 833 | 865 |
return nil |
| 834 | 866 |
} |
| 835 | 867 |
|
| 836 |
-func init() {
|
|
| 837 |
- proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value)
|
|
| 838 |
- proto.RegisterType((*LabelPair)(nil), "io.prometheus.client.LabelPair") |
|
| 839 |
- proto.RegisterType((*Gauge)(nil), "io.prometheus.client.Gauge") |
|
| 840 |
- proto.RegisterType((*Counter)(nil), "io.prometheus.client.Counter") |
|
| 841 |
- proto.RegisterType((*Quantile)(nil), "io.prometheus.client.Quantile") |
|
| 842 |
- proto.RegisterType((*Summary)(nil), "io.prometheus.client.Summary") |
|
| 843 |
- proto.RegisterType((*Untyped)(nil), "io.prometheus.client.Untyped") |
|
| 844 |
- proto.RegisterType((*Histogram)(nil), "io.prometheus.client.Histogram") |
|
| 845 |
- proto.RegisterType((*Bucket)(nil), "io.prometheus.client.Bucket") |
|
| 846 |
- proto.RegisterType((*BucketSpan)(nil), "io.prometheus.client.BucketSpan") |
|
| 847 |
- proto.RegisterType((*Exemplar)(nil), "io.prometheus.client.Exemplar") |
|
| 848 |
- proto.RegisterType((*Metric)(nil), "io.prometheus.client.Metric") |
|
| 849 |
- proto.RegisterType((*MetricFamily)(nil), "io.prometheus.client.MetricFamily") |
|
| 850 |
-} |
|
| 851 |
- |
|
| 852 |
-func init() {
|
|
| 853 |
- proto.RegisterFile("io/prometheus/client/metrics.proto", fileDescriptor_d1e5ddb18987a258)
|
|
| 854 |
-} |
|
| 855 |
- |
|
| 856 |
-var fileDescriptor_d1e5ddb18987a258 = []byte{
|
|
| 857 |
- // 896 bytes of a gzipped FileDescriptorProto |
|
| 858 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xdd, 0x8e, 0xdb, 0x44, |
|
| 859 |
- 0x18, 0xc5, 0x9b, 0x5f, 0x7f, 0xd9, 0x6c, 0xd3, 0x61, 0x55, 0x59, 0x0b, 0xcb, 0x06, 0x4b, 0x48, |
|
| 860 |
- 0x0b, 0x42, 0x8e, 0x40, 0x5b, 0x81, 0x0a, 0x5c, 0xec, 0xb6, 0xe9, 0x16, 0x89, 0xb4, 0x65, 0x92, |
|
| 861 |
- 0x5c, 0x14, 0x2e, 0xac, 0x49, 0x32, 0xeb, 0x58, 0x78, 0x3c, 0xc6, 0x1e, 0x57, 0x2c, 0x2f, 0xc0, |
|
| 862 |
- 0x35, 0xaf, 0xc0, 0xc3, 0xf0, 0x22, 0x3c, 0x08, 0x68, 0xfe, 0xec, 0xdd, 0xe2, 0x94, 0xd2, 0x3b, |
|
| 863 |
- 0x7f, 0x67, 0xce, 0xf7, 0xcd, 0x39, 0xe3, 0xc9, 0x71, 0xc0, 0x8f, 0xf9, 0x24, 0xcb, 0x39, 0xa3, |
|
| 864 |
- 0x62, 0x4b, 0xcb, 0x62, 0xb2, 0x4e, 0x62, 0x9a, 0x8a, 0x09, 0xa3, 0x22, 0x8f, 0xd7, 0x45, 0x90, |
|
| 865 |
- 0xe5, 0x5c, 0x70, 0x74, 0x18, 0xf3, 0xa0, 0xe6, 0x04, 0x9a, 0x73, 0x74, 0x12, 0x71, 0x1e, 0x25, |
|
| 866 |
- 0x74, 0xa2, 0x38, 0xab, 0xf2, 0x6a, 0x22, 0x62, 0x46, 0x0b, 0x41, 0x58, 0xa6, 0xdb, 0xfc, 0xfb, |
|
| 867 |
- 0xe0, 0x7e, 0x47, 0x56, 0x34, 0x79, 0x4e, 0xe2, 0x1c, 0x21, 0x68, 0xa7, 0x84, 0x51, 0xcf, 0x19, |
|
| 868 |
- 0x3b, 0xa7, 0x2e, 0x56, 0xcf, 0xe8, 0x10, 0x3a, 0x2f, 0x49, 0x52, 0x52, 0x6f, 0x4f, 0x81, 0xba, |
|
| 869 |
- 0xf0, 0x8f, 0xa1, 0x73, 0x49, 0xca, 0xe8, 0xc6, 0xb2, 0xec, 0x71, 0xec, 0xf2, 0x8f, 0xd0, 0x7b, |
|
| 870 |
- 0xc8, 0xcb, 0x54, 0xd0, 0xbc, 0x99, 0x80, 0x1e, 0x40, 0x9f, 0xfe, 0x42, 0x59, 0x96, 0x90, 0x5c, |
|
| 871 |
- 0x0d, 0x1e, 0x7c, 0xfe, 0x41, 0xd0, 0x64, 0x20, 0x98, 0x1a, 0x16, 0xae, 0xf8, 0xfe, 0xd7, 0xd0, |
|
| 872 |
- 0xff, 0xbe, 0x24, 0xa9, 0x88, 0x13, 0x8a, 0x8e, 0xa0, 0xff, 0xb3, 0x79, 0x36, 0x1b, 0x54, 0xf5, |
|
| 873 |
- 0x6d, 0xe5, 0x95, 0xb4, 0xdf, 0x1c, 0xe8, 0xcd, 0x4b, 0xc6, 0x48, 0x7e, 0x8d, 0x3e, 0x84, 0xfd, |
|
| 874 |
- 0x82, 0xb0, 0x2c, 0xa1, 0xe1, 0x5a, 0xaa, 0x55, 0x13, 0xda, 0x78, 0xa0, 0x31, 0x65, 0x00, 0x1d, |
|
| 875 |
- 0x03, 0x18, 0x4a, 0x51, 0x32, 0x33, 0xc9, 0xd5, 0xc8, 0xbc, 0x64, 0xd2, 0x47, 0xb5, 0x7f, 0x6b, |
|
| 876 |
- 0xdc, 0xda, 0xed, 0xc3, 0x2a, 0xae, 0xf5, 0xf9, 0x27, 0xd0, 0x5b, 0xa6, 0xe2, 0x3a, 0xa3, 0x9b, |
|
| 877 |
- 0x1d, 0xa7, 0xf8, 0x57, 0x1b, 0xdc, 0x27, 0x71, 0x21, 0x78, 0x94, 0x13, 0xf6, 0x26, 0x62, 0x3f, |
|
| 878 |
- 0x05, 0x74, 0x93, 0x12, 0x5e, 0x25, 0x9c, 0x08, 0xaf, 0xad, 0x66, 0x8e, 0x6e, 0x10, 0x1f, 0x4b, |
|
| 879 |
- 0xfc, 0xbf, 0xac, 0x9d, 0x41, 0x77, 0x55, 0xae, 0x7f, 0xa2, 0xc2, 0x18, 0x7b, 0xbf, 0xd9, 0xd8, |
|
| 880 |
- 0x85, 0xe2, 0x60, 0xc3, 0x45, 0xf7, 0xa0, 0x5b, 0xac, 0xb7, 0x94, 0x11, 0xaf, 0x33, 0x76, 0x4e, |
|
| 881 |
- 0xef, 0x62, 0x53, 0xa1, 0x8f, 0xe0, 0xe0, 0x57, 0x9a, 0xf3, 0x50, 0x6c, 0x73, 0x5a, 0x6c, 0x79, |
|
| 882 |
- 0xb2, 0xf1, 0xba, 0x6a, 0xc3, 0xa1, 0x44, 0x17, 0x16, 0x94, 0x9a, 0x14, 0x4d, 0x5b, 0xec, 0x29, |
|
| 883 |
- 0x8b, 0xae, 0x44, 0xb4, 0xc1, 0x53, 0x18, 0xd5, 0xcb, 0xc6, 0x5e, 0x5f, 0xcd, 0x39, 0xa8, 0x48, |
|
| 884 |
- 0xda, 0xdc, 0x14, 0x86, 0x29, 0x8d, 0x88, 0x88, 0x5f, 0xd2, 0xb0, 0xc8, 0x48, 0xea, 0xb9, 0xca, |
|
| 885 |
- 0xc4, 0xf8, 0x75, 0x26, 0xe6, 0x19, 0x49, 0xf1, 0xbe, 0x6d, 0x93, 0x95, 0x94, 0x5d, 0x8d, 0xd9, |
|
| 886 |
- 0xd0, 0x44, 0x10, 0x0f, 0xc6, 0xad, 0x53, 0x84, 0xab, 0xe1, 0x8f, 0x24, 0x78, 0x8b, 0xa6, 0xa5, |
|
| 887 |
- 0x0f, 0xc6, 0x2d, 0xe9, 0xce, 0xa2, 0x5a, 0xfe, 0x14, 0x86, 0x19, 0x2f, 0xe2, 0x5a, 0xd4, 0xfe, |
|
| 888 |
- 0x9b, 0x8a, 0xb2, 0x6d, 0x56, 0x54, 0x35, 0x46, 0x8b, 0x1a, 0x6a, 0x51, 0x16, 0xad, 0x44, 0x55, |
|
| 889 |
- 0x34, 0x2d, 0xea, 0x40, 0x8b, 0xb2, 0xa8, 0x12, 0xe5, 0xff, 0xe9, 0x40, 0x57, 0x6f, 0x85, 0x3e, |
|
| 890 |
- 0x86, 0xd1, 0xba, 0x64, 0x65, 0x72, 0xd3, 0x88, 0xbe, 0x66, 0x77, 0x6a, 0x5c, 0x5b, 0x39, 0x83, |
|
| 891 |
- 0x7b, 0xaf, 0x52, 0x6f, 0x5d, 0xb7, 0xc3, 0x57, 0x1a, 0xf4, 0x5b, 0x39, 0x81, 0x41, 0x99, 0x65, |
|
| 892 |
- 0x34, 0x0f, 0x57, 0xbc, 0x4c, 0x37, 0xe6, 0xce, 0x81, 0x82, 0x2e, 0x24, 0x72, 0x2b, 0x17, 0x5a, |
|
| 893 |
- 0xff, 0x3b, 0x17, 0xa0, 0x3e, 0x32, 0x79, 0x11, 0xf9, 0xd5, 0x55, 0x41, 0xb5, 0x83, 0xbb, 0xd8, |
|
| 894 |
- 0x54, 0x12, 0x4f, 0x68, 0x1a, 0x89, 0xad, 0xda, 0x7d, 0x88, 0x4d, 0xe5, 0xff, 0xee, 0x40, 0xdf, |
|
| 895 |
- 0x0e, 0x45, 0xf7, 0xa1, 0x93, 0xc8, 0x54, 0xf4, 0x1c, 0xf5, 0x82, 0x4e, 0x9a, 0x35, 0x54, 0xc1, |
|
| 896 |
- 0x89, 0x35, 0xbb, 0x39, 0x71, 0xd0, 0x97, 0xe0, 0x56, 0xa9, 0x6b, 0x4c, 0x1d, 0x05, 0x3a, 0x97, |
|
| 897 |
- 0x03, 0x9b, 0xcb, 0xc1, 0xc2, 0x32, 0x70, 0x4d, 0xf6, 0xff, 0xde, 0x83, 0xee, 0x4c, 0xa5, 0xfc, |
|
| 898 |
- 0xdb, 0x2a, 0xfa, 0x0c, 0x3a, 0x91, 0xcc, 0x69, 0x13, 0xb2, 0xef, 0x35, 0xb7, 0xa9, 0x28, 0xc7, |
|
| 899 |
- 0x9a, 0x89, 0xbe, 0x80, 0xde, 0x5a, 0x67, 0xb7, 0x11, 0x7b, 0xdc, 0xdc, 0x64, 0x02, 0x1e, 0x5b, |
|
| 900 |
- 0xb6, 0x6c, 0x2c, 0x74, 0xb0, 0xaa, 0x3b, 0xb0, 0xb3, 0xd1, 0xa4, 0x2f, 0xb6, 0x6c, 0xd9, 0x58, |
|
| 901 |
- 0xea, 0x20, 0x54, 0xa1, 0xb1, 0xb3, 0xd1, 0xa4, 0x25, 0xb6, 0x6c, 0xf4, 0x0d, 0xb8, 0x5b, 0x9b, |
|
| 902 |
- 0x8f, 0x2a, 0x2c, 0x76, 0x1e, 0x4c, 0x15, 0xa3, 0xb8, 0xee, 0x90, 0x89, 0x5a, 0x9d, 0x75, 0xc8, |
|
| 903 |
- 0x0a, 0x95, 0x48, 0x2d, 0x3c, 0xa8, 0xb0, 0x59, 0xe1, 0xff, 0xe1, 0xc0, 0xbe, 0x7e, 0x03, 0x8f, |
|
| 904 |
- 0x09, 0x8b, 0x93, 0xeb, 0xc6, 0x4f, 0x24, 0x82, 0xf6, 0x96, 0x26, 0x99, 0xf9, 0x42, 0xaa, 0x67, |
|
| 905 |
- 0x74, 0x06, 0x6d, 0xa9, 0x51, 0x1d, 0xe1, 0xc1, 0xae, 0x5f, 0xb8, 0x9e, 0xbc, 0xb8, 0xce, 0x28, |
|
| 906 |
- 0x56, 0x6c, 0x99, 0xb9, 0xfa, 0xab, 0xee, 0xb5, 0x5f, 0x97, 0xb9, 0xba, 0x0f, 0x1b, 0xee, 0x27, |
|
| 907 |
- 0x2b, 0x80, 0x7a, 0x12, 0x1a, 0x40, 0xef, 0xe1, 0xb3, 0xe5, 0xd3, 0xc5, 0x14, 0x8f, 0xde, 0x41, |
|
| 908 |
- 0x2e, 0x74, 0x2e, 0xcf, 0x97, 0x97, 0xd3, 0x91, 0x23, 0xf1, 0xf9, 0x72, 0x36, 0x3b, 0xc7, 0x2f, |
|
| 909 |
- 0x46, 0x7b, 0xb2, 0x58, 0x3e, 0x5d, 0xbc, 0x78, 0x3e, 0x7d, 0x34, 0x6a, 0xa1, 0x21, 0xb8, 0x4f, |
|
| 910 |
- 0xbe, 0x9d, 0x2f, 0x9e, 0x5d, 0xe2, 0xf3, 0xd9, 0xa8, 0x8d, 0xde, 0x85, 0x3b, 0xaa, 0x27, 0xac, |
|
| 911 |
- 0xc1, 0xce, 0x05, 0x86, 0xc6, 0x3f, 0x18, 0x3f, 0x3c, 0x88, 0x62, 0xb1, 0x2d, 0x57, 0xc1, 0x9a, |
|
| 912 |
- 0xb3, 0x7f, 0xff, 0x45, 0x09, 0x19, 0xdf, 0xd0, 0x64, 0x12, 0xf1, 0xaf, 0x62, 0x1e, 0xd6, 0xab, |
|
| 913 |
- 0xa1, 0x5e, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0x16, 0x77, 0x81, 0x98, 0xd7, 0x08, 0x00, 0x00, |
|
| 868 |
+var File_io_prometheus_client_metrics_proto protoreflect.FileDescriptor |
|
| 869 |
+ |
|
| 870 |
+var file_io_prometheus_client_metrics_proto_rawDesc = []byte{
|
|
| 871 |
+ 0x0a, 0x22, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, |
|
| 872 |
+ 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, |
|
| 873 |
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, |
|
| 874 |
+ 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, |
|
| 875 |
+ 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, |
|
| 876 |
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x09, 0x4c, |
|
| 877 |
+ 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, |
|
| 878 |
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, |
|
| 879 |
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, |
|
| 880 |
+ 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x47, 0x61, 0x75, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, |
|
| 881 |
+ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, |
|
| 882 |
+ 0x65, 0x22, 0xa4, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, |
|
| 883 |
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, |
|
| 884 |
+ 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x18, |
|
| 885 |
+ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, |
|
| 886 |
+ 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, 0x65, |
|
| 887 |
+ 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, |
|
| 888 |
+ 0x47, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, |
|
| 889 |
+ 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, |
|
| 890 |
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, |
|
| 891 |
+ 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, |
|
| 892 |
+ 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3c, 0x0a, 0x08, 0x51, 0x75, 0x61, 0x6e, |
|
| 893 |
+ 0x74, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, |
|
| 894 |
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, |
|
| 895 |
+ 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, |
|
| 896 |
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x07, 0x53, 0x75, 0x6d, 0x6d, 0x61, |
|
| 897 |
+ 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, |
|
| 898 |
+ 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, |
|
| 899 |
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, |
|
| 900 |
+ 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x70, 0x6c, |
|
| 901 |
+ 0x65, 0x53, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, |
|
| 902 |
+ 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, |
|
| 903 |
+ 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x51, 0x75, |
|
| 904 |
+ 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, |
|
| 905 |
+ 0x12, 0x47, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, |
|
| 906 |
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, |
|
| 907 |
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, |
|
| 908 |
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, |
|
| 909 |
+ 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1f, 0x0a, 0x07, 0x55, 0x6e, 0x74, |
|
| 910 |
+ 0x79, 0x70, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, |
|
| 911 |
+ 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xac, 0x05, 0x0a, 0x09, 0x48, |
|
| 912 |
+ 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, |
|
| 913 |
+ 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, |
|
| 914 |
+ 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, |
|
| 915 |
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, |
|
| 916 |
+ 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, |
|
| 917 |
+ 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, |
|
| 918 |
+ 0x70, 0x6c, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x73, |
|
| 919 |
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x34, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, |
|
| 920 |
+ 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, |
|
| 921 |
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, |
|
| 922 |
+ 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x47, |
|
| 923 |
+ 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, |
|
| 924 |
+ 0x61, 0x6d, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, |
|
| 925 |
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, |
|
| 926 |
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, |
|
| 927 |
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, |
|
| 928 |
+ 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, |
|
| 929 |
+ 0x25, 0x0a, 0x0e, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, |
|
| 930 |
+ 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x7a, 0x65, 0x72, 0x6f, 0x54, 0x68, 0x72, |
|
| 931 |
+ 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x63, |
|
| 932 |
+ 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x7a, 0x65, 0x72, 0x6f, |
|
| 933 |
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x63, 0x6f, |
|
| 934 |
+ 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, |
|
| 935 |
+ 0x0e, 0x7a, 0x65, 0x72, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, |
|
| 936 |
+ 0x45, 0x0a, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x6e, |
|
| 937 |
+ 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, |
|
| 938 |
+ 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x75, |
|
| 939 |
+ 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x0c, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, |
|
| 940 |
+ 0x76, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, |
|
| 941 |
+ 0x76, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x12, 0x52, 0x0d, |
|
| 942 |
+ 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x25, 0x0a, |
|
| 943 |
+ 0x0e, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, |
|
| 944 |
+ 0x0b, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, |
|
| 945 |
+ 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, |
|
| 946 |
+ 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x6f, |
|
| 947 |
+ 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, |
|
| 948 |
+ 0x6e, 0x74, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x0c, 0x70, |
|
| 949 |
+ 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, |
|
| 950 |
+ 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0d, 0x20, |
|
| 951 |
+ 0x03, 0x28, 0x12, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, |
|
| 952 |
+ 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, |
|
| 953 |
+ 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, |
|
| 954 |
+ 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x42, 0x75, |
|
| 955 |
+ 0x63, 0x6b, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, |
|
| 956 |
+ 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, |
|
| 957 |
+ 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, |
|
| 958 |
+ 0x34, 0x0a, 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, |
|
| 959 |
+ 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, |
|
| 960 |
+ 0x14, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, |
|
| 961 |
+ 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x62, |
|
| 962 |
+ 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x70, 0x65, |
|
| 963 |
+ 0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, |
|
| 964 |
+ 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, |
|
| 965 |
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, |
|
| 966 |
+ 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, |
|
| 967 |
+ 0x61, 0x72, 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, |
|
| 968 |
+ 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, |
|
| 969 |
+ 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, |
|
| 970 |
+ 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, |
|
| 971 |
+ 0x22, 0x91, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, 0x35, 0x0a, |
|
| 972 |
+ 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, |
|
| 973 |
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, |
|
| 974 |
+ 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, |
|
| 975 |
+ 0x61, 0x62, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, |
|
| 976 |
+ 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, |
|
| 977 |
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, |
|
| 978 |
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, |
|
| 979 |
+ 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, |
|
| 980 |
+ 0x74, 0x61, 0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, |
|
| 981 |
+ 0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, |
|
| 982 |
+ 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, |
|
| 983 |
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, |
|
| 984 |
+ 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x18, |
|
| 985 |
+ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, |
|
| 986 |
+ 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x61, 0x75, |
|
| 987 |
+ 0x67, 0x65, 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x75, |
|
| 988 |
+ 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, |
|
| 989 |
+ 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, |
|
| 990 |
+ 0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, |
|
| 991 |
+ 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, |
|
| 992 |
+ 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, |
|
| 993 |
+ 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, |
|
| 994 |
+ 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x75, |
|
| 995 |
+ 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, |
|
| 996 |
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, |
|
| 997 |
+ 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, 0x07, 0x75, 0x6e, 0x74, |
|
| 998 |
+ 0x79, 0x70, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, |
|
| 999 |
+ 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, |
|
| 1000 |
+ 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x48, |
|
| 1001 |
+ 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, |
|
| 1002 |
+ 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, |
|
| 1003 |
+ 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, |
|
| 1004 |
+ 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, |
|
| 1005 |
+ 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, |
|
| 1006 |
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, |
|
| 1007 |
+ 0x65, 0x6c, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, |
|
| 1008 |
+ 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, |
|
| 1009 |
+ 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, |
|
| 1010 |
+ 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, |
|
| 1011 |
+ 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, |
|
| 1012 |
+ 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, |
|
| 1013 |
+ 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, |
|
| 1014 |
+ 0x72, 0x69, 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2a, 0x62, 0x0a, 0x0a, 0x4d, |
|
| 1015 |
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x55, |
|
| 1016 |
+ 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47, 0x45, 0x10, |
|
| 1017 |
+ 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x02, 0x12, 0x0b, |
|
| 1018 |
+ 0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x48, |
|
| 1019 |
+ 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, |
|
| 1020 |
+ 0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x05, 0x42, |
|
| 1021 |
+ 0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, |
|
| 1022 |
+ 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, |
|
| 1023 |
+ 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, 0x63, |
|
| 1024 |
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6f, 0x3b, 0x69, |
|
| 1025 |
+ 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x63, 0x6c, 0x69, |
|
| 1026 |
+ 0x65, 0x6e, 0x74, |
|
| 1027 |
+} |
|
| 1028 |
+ |
|
| 1029 |
+var ( |
|
| 1030 |
+ file_io_prometheus_client_metrics_proto_rawDescOnce sync.Once |
|
| 1031 |
+ file_io_prometheus_client_metrics_proto_rawDescData = file_io_prometheus_client_metrics_proto_rawDesc |
|
| 1032 |
+) |
|
| 1033 |
+ |
|
| 1034 |
+func file_io_prometheus_client_metrics_proto_rawDescGZIP() []byte {
|
|
| 1035 |
+ file_io_prometheus_client_metrics_proto_rawDescOnce.Do(func() {
|
|
| 1036 |
+ file_io_prometheus_client_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_io_prometheus_client_metrics_proto_rawDescData) |
|
| 1037 |
+ }) |
|
| 1038 |
+ return file_io_prometheus_client_metrics_proto_rawDescData |
|
| 1039 |
+} |
|
| 1040 |
+ |
|
| 1041 |
+var file_io_prometheus_client_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1) |
|
| 1042 |
+var file_io_prometheus_client_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 12) |
|
| 1043 |
+var file_io_prometheus_client_metrics_proto_goTypes = []interface{}{
|
|
| 1044 |
+ (MetricType)(0), // 0: io.prometheus.client.MetricType |
|
| 1045 |
+ (*LabelPair)(nil), // 1: io.prometheus.client.LabelPair |
|
| 1046 |
+ (*Gauge)(nil), // 2: io.prometheus.client.Gauge |
|
| 1047 |
+ (*Counter)(nil), // 3: io.prometheus.client.Counter |
|
| 1048 |
+ (*Quantile)(nil), // 4: io.prometheus.client.Quantile |
|
| 1049 |
+ (*Summary)(nil), // 5: io.prometheus.client.Summary |
|
| 1050 |
+ (*Untyped)(nil), // 6: io.prometheus.client.Untyped |
|
| 1051 |
+ (*Histogram)(nil), // 7: io.prometheus.client.Histogram |
|
| 1052 |
+ (*Bucket)(nil), // 8: io.prometheus.client.Bucket |
|
| 1053 |
+ (*BucketSpan)(nil), // 9: io.prometheus.client.BucketSpan |
|
| 1054 |
+ (*Exemplar)(nil), // 10: io.prometheus.client.Exemplar |
|
| 1055 |
+ (*Metric)(nil), // 11: io.prometheus.client.Metric |
|
| 1056 |
+ (*MetricFamily)(nil), // 12: io.prometheus.client.MetricFamily |
|
| 1057 |
+ (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp |
|
| 1058 |
+} |
|
| 1059 |
+var file_io_prometheus_client_metrics_proto_depIdxs = []int32{
|
|
| 1060 |
+ 10, // 0: io.prometheus.client.Counter.exemplar:type_name -> io.prometheus.client.Exemplar |
|
| 1061 |
+ 13, // 1: io.prometheus.client.Counter.created_timestamp:type_name -> google.protobuf.Timestamp |
|
| 1062 |
+ 4, // 2: io.prometheus.client.Summary.quantile:type_name -> io.prometheus.client.Quantile |
|
| 1063 |
+ 13, // 3: io.prometheus.client.Summary.created_timestamp:type_name -> google.protobuf.Timestamp |
|
| 1064 |
+ 8, // 4: io.prometheus.client.Histogram.bucket:type_name -> io.prometheus.client.Bucket |
|
| 1065 |
+ 13, // 5: io.prometheus.client.Histogram.created_timestamp:type_name -> google.protobuf.Timestamp |
|
| 1066 |
+ 9, // 6: io.prometheus.client.Histogram.negative_span:type_name -> io.prometheus.client.BucketSpan |
|
| 1067 |
+ 9, // 7: io.prometheus.client.Histogram.positive_span:type_name -> io.prometheus.client.BucketSpan |
|
| 1068 |
+ 10, // 8: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar |
|
| 1069 |
+ 1, // 9: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair |
|
| 1070 |
+ 13, // 10: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp |
|
| 1071 |
+ 1, // 11: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair |
|
| 1072 |
+ 2, // 12: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge |
|
| 1073 |
+ 3, // 13: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter |
|
| 1074 |
+ 5, // 14: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary |
|
| 1075 |
+ 6, // 15: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped |
|
| 1076 |
+ 7, // 16: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram |
|
| 1077 |
+ 0, // 17: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType |
|
| 1078 |
+ 11, // 18: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric |
|
| 1079 |
+ 19, // [19:19] is the sub-list for method output_type |
|
| 1080 |
+ 19, // [19:19] is the sub-list for method input_type |
|
| 1081 |
+ 19, // [19:19] is the sub-list for extension type_name |
|
| 1082 |
+ 19, // [19:19] is the sub-list for extension extendee |
|
| 1083 |
+ 0, // [0:19] is the sub-list for field type_name |
|
| 1084 |
+} |
|
| 1085 |
+ |
|
| 1086 |
+func init() { file_io_prometheus_client_metrics_proto_init() }
|
|
| 1087 |
+func file_io_prometheus_client_metrics_proto_init() {
|
|
| 1088 |
+ if File_io_prometheus_client_metrics_proto != nil {
|
|
| 1089 |
+ return |
|
| 1090 |
+ } |
|
| 1091 |
+ if !protoimpl.UnsafeEnabled {
|
|
| 1092 |
+ file_io_prometheus_client_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1093 |
+ switch v := v.(*LabelPair); i {
|
|
| 1094 |
+ case 0: |
|
| 1095 |
+ return &v.state |
|
| 1096 |
+ case 1: |
|
| 1097 |
+ return &v.sizeCache |
|
| 1098 |
+ case 2: |
|
| 1099 |
+ return &v.unknownFields |
|
| 1100 |
+ default: |
|
| 1101 |
+ return nil |
|
| 1102 |
+ } |
|
| 1103 |
+ } |
|
| 1104 |
+ file_io_prometheus_client_metrics_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1105 |
+ switch v := v.(*Gauge); i {
|
|
| 1106 |
+ case 0: |
|
| 1107 |
+ return &v.state |
|
| 1108 |
+ case 1: |
|
| 1109 |
+ return &v.sizeCache |
|
| 1110 |
+ case 2: |
|
| 1111 |
+ return &v.unknownFields |
|
| 1112 |
+ default: |
|
| 1113 |
+ return nil |
|
| 1114 |
+ } |
|
| 1115 |
+ } |
|
| 1116 |
+ file_io_prometheus_client_metrics_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1117 |
+ switch v := v.(*Counter); i {
|
|
| 1118 |
+ case 0: |
|
| 1119 |
+ return &v.state |
|
| 1120 |
+ case 1: |
|
| 1121 |
+ return &v.sizeCache |
|
| 1122 |
+ case 2: |
|
| 1123 |
+ return &v.unknownFields |
|
| 1124 |
+ default: |
|
| 1125 |
+ return nil |
|
| 1126 |
+ } |
|
| 1127 |
+ } |
|
| 1128 |
+ file_io_prometheus_client_metrics_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1129 |
+ switch v := v.(*Quantile); i {
|
|
| 1130 |
+ case 0: |
|
| 1131 |
+ return &v.state |
|
| 1132 |
+ case 1: |
|
| 1133 |
+ return &v.sizeCache |
|
| 1134 |
+ case 2: |
|
| 1135 |
+ return &v.unknownFields |
|
| 1136 |
+ default: |
|
| 1137 |
+ return nil |
|
| 1138 |
+ } |
|
| 1139 |
+ } |
|
| 1140 |
+ file_io_prometheus_client_metrics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1141 |
+ switch v := v.(*Summary); i {
|
|
| 1142 |
+ case 0: |
|
| 1143 |
+ return &v.state |
|
| 1144 |
+ case 1: |
|
| 1145 |
+ return &v.sizeCache |
|
| 1146 |
+ case 2: |
|
| 1147 |
+ return &v.unknownFields |
|
| 1148 |
+ default: |
|
| 1149 |
+ return nil |
|
| 1150 |
+ } |
|
| 1151 |
+ } |
|
| 1152 |
+ file_io_prometheus_client_metrics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1153 |
+ switch v := v.(*Untyped); i {
|
|
| 1154 |
+ case 0: |
|
| 1155 |
+ return &v.state |
|
| 1156 |
+ case 1: |
|
| 1157 |
+ return &v.sizeCache |
|
| 1158 |
+ case 2: |
|
| 1159 |
+ return &v.unknownFields |
|
| 1160 |
+ default: |
|
| 1161 |
+ return nil |
|
| 1162 |
+ } |
|
| 1163 |
+ } |
|
| 1164 |
+ file_io_prometheus_client_metrics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1165 |
+ switch v := v.(*Histogram); i {
|
|
| 1166 |
+ case 0: |
|
| 1167 |
+ return &v.state |
|
| 1168 |
+ case 1: |
|
| 1169 |
+ return &v.sizeCache |
|
| 1170 |
+ case 2: |
|
| 1171 |
+ return &v.unknownFields |
|
| 1172 |
+ default: |
|
| 1173 |
+ return nil |
|
| 1174 |
+ } |
|
| 1175 |
+ } |
|
| 1176 |
+ file_io_prometheus_client_metrics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1177 |
+ switch v := v.(*Bucket); i {
|
|
| 1178 |
+ case 0: |
|
| 1179 |
+ return &v.state |
|
| 1180 |
+ case 1: |
|
| 1181 |
+ return &v.sizeCache |
|
| 1182 |
+ case 2: |
|
| 1183 |
+ return &v.unknownFields |
|
| 1184 |
+ default: |
|
| 1185 |
+ return nil |
|
| 1186 |
+ } |
|
| 1187 |
+ } |
|
| 1188 |
+ file_io_prometheus_client_metrics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1189 |
+ switch v := v.(*BucketSpan); i {
|
|
| 1190 |
+ case 0: |
|
| 1191 |
+ return &v.state |
|
| 1192 |
+ case 1: |
|
| 1193 |
+ return &v.sizeCache |
|
| 1194 |
+ case 2: |
|
| 1195 |
+ return &v.unknownFields |
|
| 1196 |
+ default: |
|
| 1197 |
+ return nil |
|
| 1198 |
+ } |
|
| 1199 |
+ } |
|
| 1200 |
+ file_io_prometheus_client_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1201 |
+ switch v := v.(*Exemplar); i {
|
|
| 1202 |
+ case 0: |
|
| 1203 |
+ return &v.state |
|
| 1204 |
+ case 1: |
|
| 1205 |
+ return &v.sizeCache |
|
| 1206 |
+ case 2: |
|
| 1207 |
+ return &v.unknownFields |
|
| 1208 |
+ default: |
|
| 1209 |
+ return nil |
|
| 1210 |
+ } |
|
| 1211 |
+ } |
|
| 1212 |
+ file_io_prometheus_client_metrics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1213 |
+ switch v := v.(*Metric); i {
|
|
| 1214 |
+ case 0: |
|
| 1215 |
+ return &v.state |
|
| 1216 |
+ case 1: |
|
| 1217 |
+ return &v.sizeCache |
|
| 1218 |
+ case 2: |
|
| 1219 |
+ return &v.unknownFields |
|
| 1220 |
+ default: |
|
| 1221 |
+ return nil |
|
| 1222 |
+ } |
|
| 1223 |
+ } |
|
| 1224 |
+ file_io_prometheus_client_metrics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
|
|
| 1225 |
+ switch v := v.(*MetricFamily); i {
|
|
| 1226 |
+ case 0: |
|
| 1227 |
+ return &v.state |
|
| 1228 |
+ case 1: |
|
| 1229 |
+ return &v.sizeCache |
|
| 1230 |
+ case 2: |
|
| 1231 |
+ return &v.unknownFields |
|
| 1232 |
+ default: |
|
| 1233 |
+ return nil |
|
| 1234 |
+ } |
|
| 1235 |
+ } |
|
| 1236 |
+ } |
|
| 1237 |
+ type x struct{}
|
|
| 1238 |
+ out := protoimpl.TypeBuilder{
|
|
| 1239 |
+ File: protoimpl.DescBuilder{
|
|
| 1240 |
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
| 1241 |
+ RawDescriptor: file_io_prometheus_client_metrics_proto_rawDesc, |
|
| 1242 |
+ NumEnums: 1, |
|
| 1243 |
+ NumMessages: 12, |
|
| 1244 |
+ NumExtensions: 0, |
|
| 1245 |
+ NumServices: 0, |
|
| 1246 |
+ }, |
|
| 1247 |
+ GoTypes: file_io_prometheus_client_metrics_proto_goTypes, |
|
| 1248 |
+ DependencyIndexes: file_io_prometheus_client_metrics_proto_depIdxs, |
|
| 1249 |
+ EnumInfos: file_io_prometheus_client_metrics_proto_enumTypes, |
|
| 1250 |
+ MessageInfos: file_io_prometheus_client_metrics_proto_msgTypes, |
|
| 1251 |
+ }.Build() |
|
| 1252 |
+ File_io_prometheus_client_metrics_proto = out.File |
|
| 1253 |
+ file_io_prometheus_client_metrics_proto_rawDesc = nil |
|
| 1254 |
+ file_io_prometheus_client_metrics_proto_goTypes = nil |
|
| 1255 |
+ file_io_prometheus_client_metrics_proto_depIdxs = nil |
|
| 914 | 1256 |
} |
| ... | ... |
@@ -132,7 +132,10 @@ func (d *textDecoder) Decode(v *dto.MetricFamily) error {
|
| 132 | 132 |
} |
| 133 | 133 |
// Pick off one MetricFamily per Decode until there's nothing left. |
| 134 | 134 |
for key, fam := range d.fams {
|
| 135 |
- *v = *fam |
|
| 135 |
+ v.Name = fam.Name |
|
| 136 |
+ v.Help = fam.Help |
|
| 137 |
+ v.Type = fam.Type |
|
| 138 |
+ v.Metric = fam.Metric |
|
| 136 | 139 |
delete(d.fams, key) |
| 137 | 140 |
return nil |
| 138 | 141 |
} |
| ... | ... |
@@ -18,9 +18,9 @@ import ( |
| 18 | 18 |
"io" |
| 19 | 19 |
"net/http" |
| 20 | 20 |
|
| 21 |
- "github.com/golang/protobuf/proto" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 22 | 21 |
"github.com/matttproud/golang_protobuf_extensions/pbutil" |
| 23 | 22 |
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" |
| 23 |
+ "google.golang.org/protobuf/encoding/prototext" |
|
| 24 | 24 |
|
| 25 | 25 |
dto "github.com/prometheus/client_model/go" |
| 26 | 26 |
) |
| ... | ... |
@@ -99,8 +99,11 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
| 99 | 99 |
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
|
| 100 | 100 |
return FmtText |
| 101 | 101 |
} |
| 102 |
- if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion || ver == "") {
|
|
| 103 |
- return FmtOpenMetrics |
|
| 102 |
+ if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
|
|
| 103 |
+ if ver == OpenMetricsVersion_1_0_0 {
|
|
| 104 |
+ return FmtOpenMetrics_1_0_0 |
|
| 105 |
+ } |
|
| 106 |
+ return FmtOpenMetrics_0_0_1 |
|
| 104 | 107 |
} |
| 105 | 108 |
} |
| 106 | 109 |
return FmtText |
| ... | ... |
@@ -133,7 +136,7 @@ func NewEncoder(w io.Writer, format Format) Encoder {
|
| 133 | 133 |
case FmtProtoText: |
| 134 | 134 |
return encoderCloser{
|
| 135 | 135 |
encode: func(v *dto.MetricFamily) error {
|
| 136 |
- _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) |
|
| 136 |
+ _, err := fmt.Fprintln(w, prototext.Format(v)) |
|
| 137 | 137 |
return err |
| 138 | 138 |
}, |
| 139 | 139 |
close: func() error { return nil },
|
| ... | ... |
@@ -146,7 +149,7 @@ func NewEncoder(w io.Writer, format Format) Encoder {
|
| 146 | 146 |
}, |
| 147 | 147 |
close: func() error { return nil },
|
| 148 | 148 |
} |
| 149 |
- case FmtOpenMetrics: |
|
| 149 |
+ case FmtOpenMetrics_0_0_1, FmtOpenMetrics_1_0_0: |
|
| 150 | 150 |
return encoderCloser{
|
| 151 | 151 |
encode: func(v *dto.MetricFamily) error {
|
| 152 | 152 |
_, err := MetricFamilyToOpenMetrics(w, v) |
| ... | ... |
@@ -19,20 +19,22 @@ type Format string |
| 19 | 19 |
|
| 20 | 20 |
// Constants to assemble the Content-Type values for the different wire protocols. |
| 21 | 21 |
const ( |
| 22 |
- TextVersion = "0.0.4" |
|
| 23 |
- ProtoType = `application/vnd.google.protobuf` |
|
| 24 |
- ProtoProtocol = `io.prometheus.client.MetricFamily` |
|
| 25 |
- ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" |
|
| 26 |
- OpenMetricsType = `application/openmetrics-text` |
|
| 27 |
- OpenMetricsVersion = "0.0.1" |
|
| 22 |
+ TextVersion = "0.0.4" |
|
| 23 |
+ ProtoType = `application/vnd.google.protobuf` |
|
| 24 |
+ ProtoProtocol = `io.prometheus.client.MetricFamily` |
|
| 25 |
+ ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" |
|
| 26 |
+ OpenMetricsType = `application/openmetrics-text` |
|
| 27 |
+ OpenMetricsVersion_0_0_1 = "0.0.1" |
|
| 28 |
+ OpenMetricsVersion_1_0_0 = "1.0.0" |
|
| 28 | 29 |
|
| 29 | 30 |
// The Content-Type values for the different wire protocols. |
| 30 |
- FmtUnknown Format = `<unknown>` |
|
| 31 |
- FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` |
|
| 32 |
- FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` |
|
| 33 |
- FmtProtoText Format = ProtoFmt + ` encoding=text` |
|
| 34 |
- FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` |
|
| 35 |
- FmtOpenMetrics Format = OpenMetricsType + `; version=` + OpenMetricsVersion + `; charset=utf-8` |
|
| 31 |
+ FmtUnknown Format = `<unknown>` |
|
| 32 |
+ FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` |
|
| 33 |
+ FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` |
|
| 34 |
+ FmtProtoText Format = ProtoFmt + ` encoding=text` |
|
| 35 |
+ FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` |
|
| 36 |
+ FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` |
|
| 37 |
+ FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` |
|
| 36 | 38 |
) |
| 37 | 39 |
|
| 38 | 40 |
const ( |
| ... | ... |
@@ -24,8 +24,8 @@ import ( |
| 24 | 24 |
|
| 25 | 25 |
dto "github.com/prometheus/client_model/go" |
| 26 | 26 |
|
| 27 |
- "github.com/golang/protobuf/proto" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. |
|
| 28 | 27 |
"github.com/prometheus/common/model" |
| 28 |
+ "google.golang.org/protobuf/proto" |
|
| 29 | 29 |
) |
| 30 | 30 |
|
| 31 | 31 |
// A stateFn is a function that represents a state in a state machine. By |
| ... | ... |
@@ -49,19 +49,19 @@ endif |
| 49 | 49 |
GOTEST := $(GO) test |
| 50 | 50 |
GOTEST_DIR := |
| 51 | 51 |
ifneq ($(CIRCLE_JOB),) |
| 52 |
-ifneq ($(shell which gotestsum),) |
|
| 52 |
+ifneq ($(shell command -v gotestsum > /dev/null),) |
|
| 53 | 53 |
GOTEST_DIR := test-results |
| 54 | 54 |
GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- |
| 55 | 55 |
endif |
| 56 | 56 |
endif |
| 57 | 57 |
|
| 58 |
-PROMU_VERSION ?= 0.14.0 |
|
| 58 |
+PROMU_VERSION ?= 0.15.0 |
|
| 59 | 59 |
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz |
| 60 | 60 |
|
| 61 | 61 |
SKIP_GOLANGCI_LINT := |
| 62 | 62 |
GOLANGCI_LINT := |
| 63 | 63 |
GOLANGCI_LINT_OPTS ?= |
| 64 |
-GOLANGCI_LINT_VERSION ?= v1.49.0 |
|
| 64 |
+GOLANGCI_LINT_VERSION ?= v1.53.3 |
|
| 65 | 65 |
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64. |
| 66 | 66 |
# windows isn't included here because of the path separator being different. |
| 67 | 67 |
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) |
| ... | ... |
@@ -91,6 +91,8 @@ BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) |
| 91 | 91 |
PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) |
| 92 | 92 |
TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS)) |
| 93 | 93 |
|
| 94 |
+SANITIZED_DOCKER_IMAGE_TAG := $(subst +,-,$(DOCKER_IMAGE_TAG)) |
|
| 95 |
+ |
|
| 94 | 96 |
ifeq ($(GOHOSTARCH),amd64) |
| 95 | 97 |
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) |
| 96 | 98 |
# Only supported on amd64 |
| ... | ... |
@@ -176,7 +178,7 @@ endif |
| 176 | 176 |
.PHONY: common-yamllint |
| 177 | 177 |
common-yamllint: |
| 178 | 178 |
@echo ">> running yamllint on all YAML files in the repository" |
| 179 |
-ifeq (, $(shell which yamllint)) |
|
| 179 |
+ifeq (, $(shell command -v yamllint > /dev/null)) |
|
| 180 | 180 |
@echo "yamllint not installed so skipping" |
| 181 | 181 |
else |
| 182 | 182 |
yamllint . |
| ... | ... |
@@ -205,7 +207,7 @@ common-tarball: promu |
| 205 | 205 |
.PHONY: common-docker $(BUILD_DOCKER_ARCHS) |
| 206 | 206 |
common-docker: $(BUILD_DOCKER_ARCHS) |
| 207 | 207 |
$(BUILD_DOCKER_ARCHS): common-docker-%: |
| 208 |
- docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \ |
|
| 208 |
+ docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ |
|
| 209 | 209 |
-f $(DOCKERFILE_PATH) \ |
| 210 | 210 |
--build-arg ARCH="$*" \ |
| 211 | 211 |
--build-arg OS="linux" \ |
| ... | ... |
@@ -214,19 +216,19 @@ $(BUILD_DOCKER_ARCHS): common-docker-%: |
| 214 | 214 |
.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) |
| 215 | 215 |
common-docker-publish: $(PUBLISH_DOCKER_ARCHS) |
| 216 | 216 |
$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: |
| 217 |
- docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" |
|
| 217 |
+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" |
|
| 218 | 218 |
|
| 219 | 219 |
DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION))) |
| 220 | 220 |
.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) |
| 221 | 221 |
common-docker-tag-latest: $(TAG_DOCKER_ARCHS) |
| 222 | 222 |
$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: |
| 223 |
- docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" |
|
| 224 |
- docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" |
|
| 223 |
+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" |
|
| 224 |
+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" |
|
| 225 | 225 |
|
| 226 | 226 |
.PHONY: common-docker-manifest |
| 227 | 227 |
common-docker-manifest: |
| 228 |
- DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG)) |
|
| 229 |
- DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" |
|
| 228 |
+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG)) |
|
| 229 |
+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" |
|
| 230 | 230 |
|
| 231 | 231 |
.PHONY: promu |
| 232 | 232 |
promu: $(PROMU) |
| ... | ... |
@@ -51,11 +51,11 @@ ensure the `fixtures` directory is up to date by removing the existing directory |
| 51 | 51 |
extracting the ttar file using `make fixtures/.unpacked` or just `make test`. |
| 52 | 52 |
|
| 53 | 53 |
```bash |
| 54 |
-rm -rf fixtures |
|
| 54 |
+rm -rf testdata/fixtures |
|
| 55 | 55 |
make test |
| 56 | 56 |
``` |
| 57 | 57 |
|
| 58 | 58 |
Next, make the required changes to the extracted files in the `fixtures` directory. When |
| 59 | 59 |
the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file |
| 60 | 60 |
based on the updated `fixtures` directory. And finally, verify the changes using |
| 61 |
-`git diff fixtures.ttar`. |
|
| 61 |
+`git diff testdata/fixtures.ttar`. |
| ... | ... |
@@ -55,7 +55,7 @@ type ARPEntry struct {
|
| 55 | 55 |
func (fs FS) GatherARPEntries() ([]ARPEntry, error) {
|
| 56 | 56 |
data, err := os.ReadFile(fs.proc.Path("net/arp"))
|
| 57 | 57 |
if err != nil {
|
| 58 |
- return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err)
|
|
| 58 |
+ return nil, fmt.Errorf("%s: error reading arp %s: %w", ErrFileRead, fs.proc.Path("net/arp"), err)
|
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
return parseARPEntries(data) |
| ... | ... |
@@ -78,11 +78,11 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) {
|
| 78 | 78 |
} else if width == expectedDataWidth {
|
| 79 | 79 |
entry, err := parseARPEntry(columns) |
| 80 | 80 |
if err != nil {
|
| 81 |
- return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %w", err)
|
|
| 81 |
+ return []ARPEntry{}, fmt.Errorf("%s: Failed to parse ARP entry: %v: %w", ErrFileParse, entry, err)
|
|
| 82 | 82 |
} |
| 83 | 83 |
entries = append(entries, entry) |
| 84 | 84 |
} else {
|
| 85 |
- return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth)
|
|
| 85 |
+ return []ARPEntry{}, fmt.Errorf("%s: %d columns found, but expected %d: %w", ErrFileParse, width, expectedDataWidth, err)
|
|
| 86 | 86 |
} |
| 87 | 87 |
|
| 88 | 88 |
} |
| ... | ... |
@@ -55,7 +55,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
|
| 55 | 55 |
parts := strings.Fields(line) |
| 56 | 56 |
|
| 57 | 57 |
if len(parts) < 4 {
|
| 58 |
- return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
|
|
| 58 |
+ return nil, fmt.Errorf("%w: Invalid number of fields, found: %v", ErrFileParse, parts)
|
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
node := strings.TrimRight(parts[1], ",") |
| ... | ... |
@@ -66,7 +66,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
|
| 66 | 66 |
bucketCount = arraySize |
| 67 | 67 |
} else {
|
| 68 | 68 |
if bucketCount != arraySize {
|
| 69 |
- return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize)
|
|
| 69 |
+ return nil, fmt.Errorf("%w: mismatch in number of buddyinfo buckets, previous count %d, new count %d", ErrFileParse, bucketCount, arraySize)
|
|
| 70 | 70 |
} |
| 71 | 71 |
} |
| 72 | 72 |
|
| ... | ... |
@@ -74,7 +74,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
|
| 74 | 74 |
for i := 0; i < arraySize; i++ {
|
| 75 | 75 |
sizes[i], err = strconv.ParseFloat(parts[i+4], 64) |
| 76 | 76 |
if err != nil {
|
| 77 |
- return nil, fmt.Errorf("invalid value in buddyinfo: %w", err)
|
|
| 77 |
+ return nil, fmt.Errorf("%s: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err)
|
|
| 78 | 78 |
} |
| 79 | 79 |
} |
| 80 | 80 |
|
| ... | ... |
@@ -79,7 +79,7 @@ func parseCPUInfoX86(info []byte) ([]CPUInfo, error) {
|
| 79 | 79 |
// find the first "processor" line |
| 80 | 80 |
firstLine := firstNonEmptyLine(scanner) |
| 81 | 81 |
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
|
| 82 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 82 |
+ return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, firstLine)
|
|
| 83 | 83 |
} |
| 84 | 84 |
field := strings.SplitN(firstLine, ": ", 2) |
| 85 | 85 |
v, err := strconv.ParseUint(field[1], 0, 32) |
| ... | ... |
@@ -192,9 +192,10 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) {
|
| 192 | 192 |
scanner := bufio.NewScanner(bytes.NewReader(info)) |
| 193 | 193 |
|
| 194 | 194 |
firstLine := firstNonEmptyLine(scanner) |
| 195 |
- match, _ := regexp.MatchString("^[Pp]rocessor", firstLine)
|
|
| 195 |
+ match, err := regexp.MatchString("^[Pp]rocessor", firstLine)
|
|
| 196 | 196 |
if !match || !strings.Contains(firstLine, ":") {
|
| 197 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 197 |
+ return nil, fmt.Errorf("%s: Cannot parse line: %q: %w", ErrFileParse, firstLine, err)
|
|
| 198 |
+ |
|
| 198 | 199 |
} |
| 199 | 200 |
field := strings.SplitN(firstLine, ": ", 2) |
| 200 | 201 |
cpuinfo := []CPUInfo{}
|
| ... | ... |
@@ -258,7 +259,7 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) {
|
| 258 | 258 |
|
| 259 | 259 |
firstLine := firstNonEmptyLine(scanner) |
| 260 | 260 |
if !strings.HasPrefix(firstLine, "vendor_id") || !strings.Contains(firstLine, ":") {
|
| 261 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 261 |
+ return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, firstLine)
|
|
| 262 | 262 |
} |
| 263 | 263 |
field := strings.SplitN(firstLine, ": ", 2) |
| 264 | 264 |
cpuinfo := []CPUInfo{}
|
| ... | ... |
@@ -283,7 +284,7 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) {
|
| 283 | 283 |
if strings.HasPrefix(line, "processor") {
|
| 284 | 284 |
match := cpuinfoS390XProcessorRegexp.FindStringSubmatch(line) |
| 285 | 285 |
if len(match) < 2 {
|
| 286 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 286 |
+ return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine)
|
|
| 287 | 287 |
} |
| 288 | 288 |
cpu := commonCPUInfo |
| 289 | 289 |
v, err := strconv.ParseUint(match[1], 0, 32) |
| ... | ... |
@@ -343,7 +344,7 @@ func parseCPUInfoMips(info []byte) ([]CPUInfo, error) {
|
| 343 | 343 |
// find the first "processor" line |
| 344 | 344 |
firstLine := firstNonEmptyLine(scanner) |
| 345 | 345 |
if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") {
|
| 346 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 346 |
+ return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine)
|
|
| 347 | 347 |
} |
| 348 | 348 |
field := strings.SplitN(firstLine, ": ", 2) |
| 349 | 349 |
cpuinfo := []CPUInfo{}
|
| ... | ... |
@@ -421,7 +422,7 @@ func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) {
|
| 421 | 421 |
|
| 422 | 422 |
firstLine := firstNonEmptyLine(scanner) |
| 423 | 423 |
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
|
| 424 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 424 |
+ return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine)
|
|
| 425 | 425 |
} |
| 426 | 426 |
field := strings.SplitN(firstLine, ": ", 2) |
| 427 | 427 |
v, err := strconv.ParseUint(field[1], 0, 32) |
| ... | ... |
@@ -466,7 +467,7 @@ func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) {
|
| 466 | 466 |
|
| 467 | 467 |
firstLine := firstNonEmptyLine(scanner) |
| 468 | 468 |
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
|
| 469 |
- return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine)
|
|
| 469 |
+ return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine)
|
|
| 470 | 470 |
} |
| 471 | 471 |
field := strings.SplitN(firstLine, ": ", 2) |
| 472 | 472 |
v, err := strconv.ParseUint(field[1], 0, 32) |
| ... | ... |
@@ -55,12 +55,13 @@ func (fs FS) Crypto() ([]Crypto, error) {
|
| 55 | 55 |
path := fs.proc.Path("crypto")
|
| 56 | 56 |
b, err := util.ReadFileNoStat(path) |
| 57 | 57 |
if err != nil {
|
| 58 |
- return nil, fmt.Errorf("error reading crypto %q: %w", path, err)
|
|
| 58 |
+ return nil, fmt.Errorf("%s: Cannot read file %v: %w", ErrFileRead, b, err)
|
|
| 59 |
+ |
|
| 59 | 60 |
} |
| 60 | 61 |
|
| 61 | 62 |
crypto, err := parseCrypto(bytes.NewReader(b)) |
| 62 | 63 |
if err != nil {
|
| 63 |
- return nil, fmt.Errorf("error parsing crypto %q: %w", path, err)
|
|
| 64 |
+ return nil, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, crypto, err)
|
|
| 64 | 65 |
} |
| 65 | 66 |
|
| 66 | 67 |
return crypto, nil |
| ... | ... |
@@ -83,7 +84,7 @@ func parseCrypto(r io.Reader) ([]Crypto, error) {
|
| 83 | 83 |
|
| 84 | 84 |
kv := strings.Split(text, ":") |
| 85 | 85 |
if len(kv) != 2 {
|
| 86 |
- return nil, fmt.Errorf("malformed crypto line: %q", text)
|
|
| 86 |
+ return nil, fmt.Errorf("%w: Cannot parae line: %q", ErrFileParse, text)
|
|
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 | 89 |
k := strings.TrimSpace(kv[0]) |
| ... | ... |
@@ -20,7 +20,8 @@ import ( |
| 20 | 20 |
// FS represents the pseudo-filesystem sys, which provides an interface to |
| 21 | 21 |
// kernel data structures. |
| 22 | 22 |
type FS struct {
|
| 23 |
- proc fs.FS |
|
| 23 |
+ proc fs.FS |
|
| 24 |
+ isReal bool |
|
| 24 | 25 |
} |
| 25 | 26 |
|
| 26 | 27 |
// DefaultMountPoint is the common mount point of the proc filesystem. |
| ... | ... |
@@ -39,5 +40,11 @@ func NewFS(mountPoint string) (FS, error) {
|
| 39 | 39 |
if err != nil {
|
| 40 | 40 |
return FS{}, err
|
| 41 | 41 |
} |
| 42 |
- return FS{fs}, nil
|
|
| 42 |
+ |
|
| 43 |
+ isReal, err := isRealProc(mountPoint) |
|
| 44 |
+ if err != nil {
|
|
| 45 |
+ return FS{}, err
|
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ return FS{fs, isReal}, nil
|
|
| 43 | 49 |
} |
| 44 | 50 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+// Copyright 2018 The Prometheus Authors |
|
| 1 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 2 |
+// you may not use this file except in compliance with the License. |
|
| 3 |
+// You may obtain a copy of the License at |
|
| 4 |
+// |
|
| 5 |
+// http://www.apache.org/licenses/LICENSE-2.0 |
|
| 6 |
+// |
|
| 7 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 8 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 9 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 10 |
+// See the License for the specific language governing permissions and |
|
| 11 |
+// limitations under the License. |
|
| 12 |
+ |
|
| 13 |
+//go:build netbsd || openbsd || solaris || windows || nostatfs |
|
| 14 |
+// +build netbsd openbsd solaris windows nostatfs |
|
| 15 |
+ |
|
| 16 |
+package procfs |
|
| 17 |
+ |
|
| 18 |
+// isRealProc returns true on architectures that don't have a Type argument |
|
| 19 |
+// in their Statfs_t struct |
|
| 20 |
+func isRealProc(mountPoint string) (bool, error) {
|
|
| 21 |
+ return true, nil |
|
| 22 |
+} |
| 0 | 23 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,33 @@ |
| 0 |
+// Copyright 2018 The Prometheus Authors |
|
| 1 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 2 |
+// you may not use this file except in compliance with the License. |
|
| 3 |
+// You may obtain a copy of the License at |
|
| 4 |
+// |
|
| 5 |
+// http://www.apache.org/licenses/LICENSE-2.0 |
|
| 6 |
+// |
|
| 7 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 8 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 9 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 10 |
+// See the License for the specific language governing permissions and |
|
| 11 |
+// limitations under the License. |
|
| 12 |
+ |
|
| 13 |
+//go:build !netbsd && !openbsd && !solaris && !windows && !nostatfs |
|
| 14 |
+// +build !netbsd,!openbsd,!solaris,!windows,!nostatfs |
|
| 15 |
+ |
|
| 16 |
+package procfs |
|
| 17 |
+ |
|
| 18 |
+import ( |
|
| 19 |
+ "syscall" |
|
| 20 |
+) |
|
| 21 |
+ |
|
| 22 |
+// isRealProc determines whether supplied mountpoint is really a proc filesystem. |
|
| 23 |
+func isRealProc(mountPoint string) (bool, error) {
|
|
| 24 |
+ stat := syscall.Statfs_t{}
|
|
| 25 |
+ err := syscall.Statfs(mountPoint, &stat) |
|
| 26 |
+ if err != nil {
|
|
| 27 |
+ return false, err |
|
| 28 |
+ } |
|
| 29 |
+ |
|
| 30 |
+ // 0x9fa0 is PROC_SUPER_MAGIC: https://elixir.bootlin.com/linux/v6.1/source/include/uapi/linux/magic.h#L87 |
|
| 31 |
+ return stat.Type == 0x9fa0, nil |
|
| 32 |
+} |
| ... | ... |
@@ -236,7 +236,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) {
|
| 236 | 236 |
|
| 237 | 237 |
m, err := parseFscacheinfo(bytes.NewReader(b)) |
| 238 | 238 |
if err != nil {
|
| 239 |
- return Fscacheinfo{}, fmt.Errorf("failed to parse Fscacheinfo: %w", err)
|
|
| 239 |
+ return Fscacheinfo{}, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, m, err)
|
|
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 | 242 |
return *m, nil |
| ... | ... |
@@ -245,7 +245,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) {
|
| 245 | 245 |
func setFSCacheFields(fields []string, setFields ...*uint64) error {
|
| 246 | 246 |
var err error |
| 247 | 247 |
if len(fields) < len(setFields) {
|
| 248 |
- return fmt.Errorf("Insufficient number of fields, expected %v, got %v", len(setFields), len(fields))
|
|
| 248 |
+ return fmt.Errorf("%s: Expected %d, but got %d: %w", ErrFileParse, len(setFields), len(fields), err)
|
|
| 249 | 249 |
} |
| 250 | 250 |
|
| 251 | 251 |
for i := range setFields {
|
| ... | ... |
@@ -263,7 +263,7 @@ func parseFscacheinfo(r io.Reader) (*Fscacheinfo, error) {
|
| 263 | 263 |
for s.Scan() {
|
| 264 | 264 |
fields := strings.Fields(s.Text()) |
| 265 | 265 |
if len(fields) < 2 {
|
| 266 |
- return nil, fmt.Errorf("malformed Fscacheinfo line: %q", s.Text())
|
|
| 266 |
+ return nil, fmt.Errorf("%w: malformed Fscacheinfo line: %q", ErrFileParse, s.Text())
|
|
| 267 | 267 |
} |
| 268 | 268 |
|
| 269 | 269 |
switch fields[0] {
|
| ... | ... |
@@ -64,6 +64,21 @@ func ParsePInt64s(ss []string) ([]*int64, error) {
|
| 64 | 64 |
return us, nil |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 |
+// Parses a uint64 from given hex in string. |
|
| 68 |
+func ParseHexUint64s(ss []string) ([]*uint64, error) {
|
|
| 69 |
+ us := make([]*uint64, 0, len(ss)) |
|
| 70 |
+ for _, s := range ss {
|
|
| 71 |
+ u, err := strconv.ParseUint(s, 16, 64) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return nil, err |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ us = append(us, &u) |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ return us, nil |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 67 | 82 |
// ReadUintFromFile reads a file and attempts to parse a uint64 from it. |
| 68 | 83 |
func ReadUintFromFile(path string) (uint64, error) {
|
| 69 | 84 |
data, err := os.ReadFile(path) |
| ... | ... |
@@ -221,15 +221,16 @@ func parseIPPort(s string) (net.IP, uint16, error) {
|
| 221 | 221 |
case 46: |
| 222 | 222 |
ip = net.ParseIP(s[1:40]) |
| 223 | 223 |
if ip == nil {
|
| 224 |
- return nil, 0, fmt.Errorf("invalid IPv6 address: %s", s[1:40])
|
|
| 224 |
+ return nil, 0, fmt.Errorf("%s: Invalid IPv6 addr %s: %w", ErrFileParse, s[1:40], err)
|
|
| 225 | 225 |
} |
| 226 | 226 |
default: |
| 227 |
- return nil, 0, fmt.Errorf("unexpected IP:Port: %s", s)
|
|
| 227 |
+ return nil, 0, fmt.Errorf("%s: Unexpected IP:Port %s: %w", ErrFileParse, s, err)
|
|
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 | 230 |
portString := s[len(s)-4:] |
| 231 | 231 |
if len(portString) != 4 {
|
| 232 |
- return nil, 0, fmt.Errorf("unexpected port string format: %s", portString)
|
|
| 232 |
+ return nil, 0, |
|
| 233 |
+ fmt.Errorf("%s: Unexpected port string format %s: %w", ErrFileParse, portString, err)
|
|
| 233 | 234 |
} |
| 234 | 235 |
port, err := strconv.ParseUint(portString, 16, 16) |
| 235 | 236 |
if err != nil {
|
| ... | ... |
@@ -44,14 +44,14 @@ func parseLoad(loadavgBytes []byte) (*LoadAvg, error) {
|
| 44 | 44 |
loads := make([]float64, 3) |
| 45 | 45 |
parts := strings.Fields(string(loadavgBytes)) |
| 46 | 46 |
if len(parts) < 3 {
|
| 47 |
- return nil, fmt.Errorf("malformed loadavg line: too few fields in loadavg string: %q", string(loadavgBytes))
|
|
| 47 |
+ return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, string(loadavgBytes))
|
|
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 | 50 |
var err error |
| 51 | 51 |
for i, load := range parts[0:3] {
|
| 52 | 52 |
loads[i], err = strconv.ParseFloat(load, 64) |
| 53 | 53 |
if err != nil {
|
| 54 |
- return nil, fmt.Errorf("could not parse load %q: %w", load, err)
|
|
| 54 |
+ return nil, fmt.Errorf("%s: Cannot parse load: %f: %w", ErrFileParse, loads[i], err)
|
|
| 55 | 55 |
} |
| 56 | 56 |
} |
| 57 | 57 |
return &LoadAvg{
|
| ... | ... |
@@ -70,7 +70,7 @@ func (fs FS) MDStat() ([]MDStat, error) {
|
| 70 | 70 |
} |
| 71 | 71 |
mdstat, err := parseMDStat(data) |
| 72 | 72 |
if err != nil {
|
| 73 |
- return nil, fmt.Errorf("error parsing mdstat %q: %w", fs.proc.Path("mdstat"), err)
|
|
| 73 |
+ return nil, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, fs.proc.Path("mdstat"), err)
|
|
| 74 | 74 |
} |
| 75 | 75 |
return mdstat, nil |
| 76 | 76 |
} |
| ... | ... |
@@ -90,13 +90,13 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
|
| 90 | 90 |
|
| 91 | 91 |
deviceFields := strings.Fields(line) |
| 92 | 92 |
if len(deviceFields) < 3 {
|
| 93 |
- return nil, fmt.Errorf("not enough fields in mdline (expected at least 3): %s", line)
|
|
| 93 |
+ return nil, fmt.Errorf("%s: Expected 3+ lines, got %q", ErrFileParse, line)
|
|
| 94 | 94 |
} |
| 95 | 95 |
mdName := deviceFields[0] // mdx |
| 96 | 96 |
state := deviceFields[2] // active or inactive |
| 97 | 97 |
|
| 98 | 98 |
if len(lines) <= i+3 {
|
| 99 |
- return nil, fmt.Errorf("error parsing %q: too few lines for md device", mdName)
|
|
| 99 |
+ return nil, fmt.Errorf("%w: Too few lines for md device: %q", ErrFileParse, mdName)
|
|
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 | 102 |
// Failed disks have the suffix (F) & Spare disks have the suffix (S). |
| ... | ... |
@@ -105,7 +105,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
|
| 105 | 105 |
active, total, down, size, err := evalStatusLine(lines[i], lines[i+1]) |
| 106 | 106 |
|
| 107 | 107 |
if err != nil {
|
| 108 |
- return nil, fmt.Errorf("error parsing md device lines: %w", err)
|
|
| 108 |
+ return nil, fmt.Errorf("%s: Cannot parse md device lines: %v: %w", ErrFileParse, active, err)
|
|
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 | 111 |
syncLineIdx := i + 2 |
| ... | ... |
@@ -140,7 +140,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
|
| 140 | 140 |
} else {
|
| 141 | 141 |
syncedBlocks, pct, finish, speed, err = evalRecoveryLine(lines[syncLineIdx]) |
| 142 | 142 |
if err != nil {
|
| 143 |
- return nil, fmt.Errorf("error parsing sync line in md device %q: %w", mdName, err)
|
|
| 143 |
+ return nil, fmt.Errorf("%s: Cannot parse sync line in md device: %q: %w", ErrFileParse, mdName, err)
|
|
| 144 | 144 |
} |
| 145 | 145 |
} |
| 146 | 146 |
} |
| ... | ... |
@@ -168,13 +168,13 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
|
| 168 | 168 |
func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) {
|
| 169 | 169 |
statusFields := strings.Fields(statusLine) |
| 170 | 170 |
if len(statusFields) < 1 {
|
| 171 |
- return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q", statusLine)
|
|
| 171 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err)
|
|
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 | 174 |
sizeStr := statusFields[0] |
| 175 | 175 |
size, err = strconv.ParseInt(sizeStr, 10, 64) |
| 176 | 176 |
if err != nil {
|
| 177 |
- return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err)
|
|
| 177 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err)
|
|
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 | 180 |
if strings.Contains(deviceLine, "raid0") || strings.Contains(deviceLine, "linear") {
|
| ... | ... |
@@ -189,17 +189,17 @@ func evalStatusLine(deviceLine, statusLine string) (active, total, down, size in |
| 189 | 189 |
|
| 190 | 190 |
matches := statusLineRE.FindStringSubmatch(statusLine) |
| 191 | 191 |
if len(matches) != 5 {
|
| 192 |
- return 0, 0, 0, 0, fmt.Errorf("couldn't find all the substring matches: %s", statusLine)
|
|
| 192 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Could not fild all substring matches %s: %w", ErrFileParse, statusLine, err)
|
|
| 193 | 193 |
} |
| 194 | 194 |
|
| 195 | 195 |
total, err = strconv.ParseInt(matches[2], 10, 64) |
| 196 | 196 |
if err != nil {
|
| 197 |
- return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err)
|
|
| 197 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err)
|
|
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 | 200 |
active, err = strconv.ParseInt(matches[3], 10, 64) |
| 201 | 201 |
if err != nil {
|
| 202 |
- return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err)
|
|
| 202 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected active %d: %w", ErrFileParse, active, err)
|
|
| 203 | 203 |
} |
| 204 | 204 |
down = int64(strings.Count(matches[4], "_")) |
| 205 | 205 |
|
| ... | ... |
@@ -209,42 +209,42 @@ func evalStatusLine(deviceLine, statusLine string) (active, total, down, size in |
| 209 | 209 |
func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, pct float64, finish float64, speed float64, err error) {
|
| 210 | 210 |
matches := recoveryLineBlocksRE.FindStringSubmatch(recoveryLine) |
| 211 | 211 |
if len(matches) != 2 {
|
| 212 |
- return 0, 0, 0, 0, fmt.Errorf("unexpected recoveryLine: %s", recoveryLine)
|
|
| 212 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected recoveryLine %s: %w", ErrFileParse, recoveryLine, err)
|
|
| 213 | 213 |
} |
| 214 | 214 |
|
| 215 | 215 |
syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) |
| 216 | 216 |
if err != nil {
|
| 217 |
- return 0, 0, 0, 0, fmt.Errorf("error parsing int from recoveryLine %q: %w", recoveryLine, err)
|
|
| 217 |
+ return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected parsing of recoveryLine %q: %w", ErrFileParse, recoveryLine, err)
|
|
| 218 | 218 |
} |
| 219 | 219 |
|
| 220 | 220 |
// Get percentage complete |
| 221 | 221 |
matches = recoveryLinePctRE.FindStringSubmatch(recoveryLine) |
| 222 | 222 |
if len(matches) != 2 {
|
| 223 |
- return syncedBlocks, 0, 0, 0, fmt.Errorf("unexpected recoveryLine matching percentage: %s", recoveryLine)
|
|
| 223 |
+ return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching percentage %s", ErrFileParse, recoveryLine)
|
|
| 224 | 224 |
} |
| 225 | 225 |
pct, err = strconv.ParseFloat(strings.TrimSpace(matches[1]), 64) |
| 226 | 226 |
if err != nil {
|
| 227 |
- return syncedBlocks, 0, 0, 0, fmt.Errorf("error parsing float from recoveryLine %q: %w", recoveryLine, err)
|
|
| 227 |
+ return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Error parsing float from recoveryLine %q", ErrFileParse, recoveryLine)
|
|
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 | 230 |
// Get time expected left to complete |
| 231 | 231 |
matches = recoveryLineFinishRE.FindStringSubmatch(recoveryLine) |
| 232 | 232 |
if len(matches) != 2 {
|
| 233 |
- return syncedBlocks, pct, 0, 0, fmt.Errorf("unexpected recoveryLine matching est. finish time: %s", recoveryLine)
|
|
| 233 |
+ return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching est. finish time: %s", ErrFileParse, recoveryLine)
|
|
| 234 | 234 |
} |
| 235 | 235 |
finish, err = strconv.ParseFloat(matches[1], 64) |
| 236 | 236 |
if err != nil {
|
| 237 |
- return syncedBlocks, pct, 0, 0, fmt.Errorf("error parsing float from recoveryLine %q: %w", recoveryLine, err)
|
|
| 237 |
+ return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unable to parse float from recoveryLine: %q", ErrFileParse, recoveryLine)
|
|
| 238 | 238 |
} |
| 239 | 239 |
|
| 240 | 240 |
// Get recovery speed |
| 241 | 241 |
matches = recoveryLineSpeedRE.FindStringSubmatch(recoveryLine) |
| 242 | 242 |
if len(matches) != 2 {
|
| 243 |
- return syncedBlocks, pct, finish, 0, fmt.Errorf("unexpected recoveryLine matching speed: %s", recoveryLine)
|
|
| 243 |
+ return syncedBlocks, pct, finish, 0, fmt.Errorf("%w: Unexpected recoveryLine value: %s", ErrFileParse, recoveryLine)
|
|
| 244 | 244 |
} |
| 245 | 245 |
speed, err = strconv.ParseFloat(matches[1], 64) |
| 246 | 246 |
if err != nil {
|
| 247 |
- return syncedBlocks, pct, finish, 0, fmt.Errorf("error parsing float from recoveryLine %q: %w", recoveryLine, err)
|
|
| 247 |
+ return syncedBlocks, pct, finish, 0, fmt.Errorf("%s: Error parsing float from recoveryLine: %q: %w", ErrFileParse, recoveryLine, err)
|
|
| 248 | 248 |
} |
| 249 | 249 |
|
| 250 | 250 |
return syncedBlocks, pct, finish, speed, nil |
| ... | ... |
@@ -152,7 +152,7 @@ func (fs FS) Meminfo() (Meminfo, error) {
|
| 152 | 152 |
|
| 153 | 153 |
m, err := parseMemInfo(bytes.NewReader(b)) |
| 154 | 154 |
if err != nil {
|
| 155 |
- return Meminfo{}, fmt.Errorf("failed to parse meminfo: %w", err)
|
|
| 155 |
+ return Meminfo{}, fmt.Errorf("%s: %w", ErrFileParse, err)
|
|
| 156 | 156 |
} |
| 157 | 157 |
|
| 158 | 158 |
return *m, nil |
| ... | ... |
@@ -165,7 +165,7 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) {
|
| 165 | 165 |
// Each line has at least a name and value; we ignore the unit. |
| 166 | 166 |
fields := strings.Fields(s.Text()) |
| 167 | 167 |
if len(fields) < 2 {
|
| 168 |
- return nil, fmt.Errorf("malformed meminfo line: %q", s.Text())
|
|
| 168 |
+ return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text())
|
|
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 | 171 |
v, err := strconv.ParseUint(fields[1], 0, 64) |
| ... | ... |
@@ -78,11 +78,11 @@ func parseMountInfoString(mountString string) (*MountInfo, error) {
|
| 78 | 78 |
mountInfo := strings.Split(mountString, " ") |
| 79 | 79 |
mountInfoLength := len(mountInfo) |
| 80 | 80 |
if mountInfoLength < 10 {
|
| 81 |
- return nil, fmt.Errorf("couldn't find enough fields in mount string: %s", mountString)
|
|
| 81 |
+ return nil, fmt.Errorf("%w: Too few fields in mount string: %s", ErrFileParse, mountString)
|
|
| 82 | 82 |
} |
| 83 | 83 |
|
| 84 | 84 |
if mountInfo[mountInfoLength-4] != "-" {
|
| 85 |
- return nil, fmt.Errorf("couldn't find separator in expected field: %s", mountInfo[mountInfoLength-4])
|
|
| 85 |
+ return nil, fmt.Errorf("%w: couldn't find separator in expected field: %s", ErrFileParse, mountInfo[mountInfoLength-4])
|
|
| 86 | 86 |
} |
| 87 | 87 |
|
| 88 | 88 |
mount := &MountInfo{
|
| ... | ... |
@@ -98,18 +98,18 @@ func parseMountInfoString(mountString string) (*MountInfo, error) {
|
| 98 | 98 |
|
| 99 | 99 |
mount.MountID, err = strconv.Atoi(mountInfo[0]) |
| 100 | 100 |
if err != nil {
|
| 101 |
- return nil, fmt.Errorf("failed to parse mount ID")
|
|
| 101 |
+ return nil, fmt.Errorf("%w: mount ID: %q", ErrFileParse, mount.MountID)
|
|
| 102 | 102 |
} |
| 103 | 103 |
mount.ParentID, err = strconv.Atoi(mountInfo[1]) |
| 104 | 104 |
if err != nil {
|
| 105 |
- return nil, fmt.Errorf("failed to parse parent ID")
|
|
| 105 |
+ return nil, fmt.Errorf("%w: parent ID: %q", ErrFileParse, mount.ParentID)
|
|
| 106 | 106 |
} |
| 107 | 107 |
// Has optional fields, which is a space separated list of values. |
| 108 | 108 |
// Example: shared:2 master:7 |
| 109 | 109 |
if mountInfo[6] != "" {
|
| 110 | 110 |
mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4]) |
| 111 | 111 |
if err != nil {
|
| 112 |
- return nil, err |
|
| 112 |
+ return nil, fmt.Errorf("%s: %w", ErrFileParse, err)
|
|
| 113 | 113 |
} |
| 114 | 114 |
} |
| 115 | 115 |
return mount, nil |
| ... | ... |
@@ -186,6 +186,8 @@ type NFSOperationStats struct {
|
| 186 | 186 |
CumulativeTotalResponseMilliseconds uint64 |
| 187 | 187 |
// Duration from when a request was enqueued to when it was completely handled. |
| 188 | 188 |
CumulativeTotalRequestMilliseconds uint64 |
| 189 |
+ // The average time from the point the client sends RPC requests until it receives the response. |
|
| 190 |
+ AverageRTTMilliseconds float64 |
|
| 189 | 191 |
// The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions. |
| 190 | 192 |
Errors uint64 |
| 191 | 193 |
} |
| ... | ... |
@@ -264,7 +266,7 @@ func parseMountStats(r io.Reader) ([]*Mount, error) {
|
| 264 | 264 |
if len(ss) > deviceEntryLen {
|
| 265 | 265 |
// Only NFSv3 and v4 are supported for parsing statistics |
| 266 | 266 |
if m.Type != nfs3Type && m.Type != nfs4Type {
|
| 267 |
- return nil, fmt.Errorf("cannot parse MountStats for fstype %q", m.Type)
|
|
| 267 |
+ return nil, fmt.Errorf("%w: Cannot parse MountStats for %q", ErrFileParse, m.Type)
|
|
| 268 | 268 |
} |
| 269 | 269 |
|
| 270 | 270 |
statVersion := strings.TrimPrefix(ss[8], statVersionPrefix) |
| ... | ... |
@@ -288,7 +290,7 @@ func parseMountStats(r io.Reader) ([]*Mount, error) {
|
| 288 | 288 |
// device [device] mounted on [mount] with fstype [type] |
| 289 | 289 |
func parseMount(ss []string) (*Mount, error) {
|
| 290 | 290 |
if len(ss) < deviceEntryLen {
|
| 291 |
- return nil, fmt.Errorf("invalid device entry: %v", ss)
|
|
| 291 |
+ return nil, fmt.Errorf("%w: Invalid device %q", ErrFileParse, ss)
|
|
| 292 | 292 |
} |
| 293 | 293 |
|
| 294 | 294 |
// Check for specific words appearing at specific indices to ensure |
| ... | ... |
@@ -306,7 +308,7 @@ func parseMount(ss []string) (*Mount, error) {
|
| 306 | 306 |
|
| 307 | 307 |
for _, f := range format {
|
| 308 | 308 |
if ss[f.i] != f.s {
|
| 309 |
- return nil, fmt.Errorf("invalid device entry: %v", ss)
|
|
| 309 |
+ return nil, fmt.Errorf("%w: Invalid device %q", ErrFileParse, ss)
|
|
| 310 | 310 |
} |
| 311 | 311 |
} |
| 312 | 312 |
|
| ... | ... |
@@ -343,7 +345,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e |
| 343 | 343 |
switch ss[0] {
|
| 344 | 344 |
case fieldOpts: |
| 345 | 345 |
if len(ss) < 2 {
|
| 346 |
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
|
|
| 346 |
+ return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss)
|
|
| 347 | 347 |
} |
| 348 | 348 |
if stats.Opts == nil {
|
| 349 | 349 |
stats.Opts = map[string]string{}
|
| ... | ... |
@@ -358,7 +360,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e |
| 358 | 358 |
} |
| 359 | 359 |
case fieldAge: |
| 360 | 360 |
if len(ss) < 2 {
|
| 361 |
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
|
|
| 361 |
+ return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss)
|
|
| 362 | 362 |
} |
| 363 | 363 |
// Age integer is in seconds |
| 364 | 364 |
d, err := time.ParseDuration(ss[1] + "s") |
| ... | ... |
@@ -369,7 +371,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e |
| 369 | 369 |
stats.Age = d |
| 370 | 370 |
case fieldBytes: |
| 371 | 371 |
if len(ss) < 2 {
|
| 372 |
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
|
|
| 372 |
+ return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss)
|
|
| 373 | 373 |
} |
| 374 | 374 |
bstats, err := parseNFSBytesStats(ss[1:]) |
| 375 | 375 |
if err != nil {
|
| ... | ... |
@@ -379,7 +381,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e |
| 379 | 379 |
stats.Bytes = *bstats |
| 380 | 380 |
case fieldEvents: |
| 381 | 381 |
if len(ss) < 2 {
|
| 382 |
- return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
|
|
| 382 |
+ return nil, fmt.Errorf("%w: Incomplete information for NFS events: %v", ErrFileParse, ss)
|
|
| 383 | 383 |
} |
| 384 | 384 |
estats, err := parseNFSEventsStats(ss[1:]) |
| 385 | 385 |
if err != nil {
|
| ... | ... |
@@ -389,7 +391,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e |
| 389 | 389 |
stats.Events = *estats |
| 390 | 390 |
case fieldTransport: |
| 391 | 391 |
if len(ss) < 3 {
|
| 392 |
- return nil, fmt.Errorf("not enough information for NFS transport stats: %v", ss)
|
|
| 392 |
+ return nil, fmt.Errorf("%w: Incomplete information for NFS transport stats: %v", ErrFileParse, ss)
|
|
| 393 | 393 |
} |
| 394 | 394 |
|
| 395 | 395 |
tstats, err := parseNFSTransportStats(ss[1:], statVersion) |
| ... | ... |
@@ -428,7 +430,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e |
| 428 | 428 |
// integer fields. |
| 429 | 429 |
func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) {
|
| 430 | 430 |
if len(ss) != fieldBytesLen {
|
| 431 |
- return nil, fmt.Errorf("invalid NFS bytes stats: %v", ss)
|
|
| 431 |
+ return nil, fmt.Errorf("%w: Invalid NFS bytes stats: %v", ErrFileParse, ss)
|
|
| 432 | 432 |
} |
| 433 | 433 |
|
| 434 | 434 |
ns := make([]uint64, 0, fieldBytesLen) |
| ... | ... |
@@ -457,7 +459,7 @@ func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) {
|
| 457 | 457 |
// integer fields. |
| 458 | 458 |
func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) {
|
| 459 | 459 |
if len(ss) != fieldEventsLen {
|
| 460 |
- return nil, fmt.Errorf("invalid NFS events stats: %v", ss)
|
|
| 460 |
+ return nil, fmt.Errorf("%w: invalid NFS events stats: %v", ErrFileParse, ss)
|
|
| 461 | 461 |
} |
| 462 | 462 |
|
| 463 | 463 |
ns := make([]uint64, 0, fieldEventsLen) |
| ... | ... |
@@ -521,7 +523,7 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
|
| 521 | 521 |
} |
| 522 | 522 |
|
| 523 | 523 |
if len(ss) < minFields {
|
| 524 |
- return nil, fmt.Errorf("invalid NFS per-operations stats: %v", ss)
|
|
| 524 |
+ return nil, fmt.Errorf("%w: invalid NFS per-operations stats: %v", ErrFileParse, ss)
|
|
| 525 | 525 |
} |
| 526 | 526 |
|
| 527 | 527 |
// Skip string operation name for integers |
| ... | ... |
@@ -534,7 +536,6 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
|
| 534 | 534 |
|
| 535 | 535 |
ns = append(ns, n) |
| 536 | 536 |
} |
| 537 |
- |
|
| 538 | 537 |
opStats := NFSOperationStats{
|
| 539 | 538 |
Operation: strings.TrimSuffix(ss[0], ":"), |
| 540 | 539 |
Requests: ns[0], |
| ... | ... |
@@ -546,6 +547,9 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
|
| 546 | 546 |
CumulativeTotalResponseMilliseconds: ns[6], |
| 547 | 547 |
CumulativeTotalRequestMilliseconds: ns[7], |
| 548 | 548 |
} |
| 549 |
+ if ns[0] != 0 {
|
|
| 550 |
+ opStats.AverageRTTMilliseconds = float64(ns[6]) / float64(ns[0]) |
|
| 551 |
+ } |
|
| 549 | 552 |
|
| 550 | 553 |
if len(ns) > 8 {
|
| 551 | 554 |
opStats.Errors = ns[8] |
| ... | ... |
@@ -572,10 +576,10 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats |
| 572 | 572 |
} else if protocol == "udp" {
|
| 573 | 573 |
expectedLength = fieldTransport10UDPLen |
| 574 | 574 |
} else {
|
| 575 |
- return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.0 statement: %v", protocol, ss)
|
|
| 575 |
+ return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss)
|
|
| 576 | 576 |
} |
| 577 | 577 |
if len(ss) != expectedLength {
|
| 578 |
- return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss)
|
|
| 578 |
+ return nil, fmt.Errorf("%w: Invalid NFS transport stats 1.0 statement: %v", ErrFileParse, ss)
|
|
| 579 | 579 |
} |
| 580 | 580 |
case statVersion11: |
| 581 | 581 |
var expectedLength int |
| ... | ... |
@@ -584,13 +588,13 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats |
| 584 | 584 |
} else if protocol == "udp" {
|
| 585 | 585 |
expectedLength = fieldTransport11UDPLen |
| 586 | 586 |
} else {
|
| 587 |
- return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.1 statement: %v", protocol, ss)
|
|
| 587 |
+ return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
|
|
| 588 | 588 |
} |
| 589 | 589 |
if len(ss) != expectedLength {
|
| 590 |
- return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss)
|
|
| 590 |
+ return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v", ErrFileParse, ss)
|
|
| 591 | 591 |
} |
| 592 | 592 |
default: |
| 593 |
- return nil, fmt.Errorf("unrecognized NFS transport stats version: %q", statVersion)
|
|
| 593 |
+ return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q", ErrFileParse, statVersion)
|
|
| 594 | 594 |
} |
| 595 | 595 |
|
| 596 | 596 |
// Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay |
| ... | ... |
@@ -18,7 +18,6 @@ import ( |
| 18 | 18 |
"bytes" |
| 19 | 19 |
"fmt" |
| 20 | 20 |
"io" |
| 21 |
- "strconv" |
|
| 22 | 21 |
"strings" |
| 23 | 22 |
|
| 24 | 23 |
"github.com/prometheus/procfs/internal/util" |
| ... | ... |
@@ -28,9 +27,13 @@ import ( |
| 28 | 28 |
// and contains netfilter conntrack statistics at one CPU core. |
| 29 | 29 |
type ConntrackStatEntry struct {
|
| 30 | 30 |
Entries uint64 |
| 31 |
+ Searched uint64 |
|
| 31 | 32 |
Found uint64 |
| 33 |
+ New uint64 |
|
| 32 | 34 |
Invalid uint64 |
| 33 | 35 |
Ignore uint64 |
| 36 |
+ Delete uint64 |
|
| 37 |
+ DeleteList uint64 |
|
| 34 | 38 |
Insert uint64 |
| 35 | 39 |
InsertFailed uint64 |
| 36 | 40 |
Drop uint64 |
| ... | ... |
@@ -55,7 +58,7 @@ func readConntrackStat(path string) ([]ConntrackStatEntry, error) {
|
| 55 | 55 |
|
| 56 | 56 |
stat, err := parseConntrackStat(bytes.NewReader(b)) |
| 57 | 57 |
if err != nil {
|
| 58 |
- return nil, fmt.Errorf("failed to read conntrack stats from %q: %w", path, err)
|
|
| 58 |
+ return nil, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, path, err)
|
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
return stat, nil |
| ... | ... |
@@ -81,73 +84,35 @@ func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) {
|
| 81 | 81 |
|
| 82 | 82 |
// Parses a ConntrackStatEntry from given array of fields. |
| 83 | 83 |
func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) {
|
| 84 |
- if len(fields) != 17 {
|
|
| 85 |
- return nil, fmt.Errorf("invalid conntrackstat entry, missing fields")
|
|
| 86 |
- } |
|
| 87 |
- entry := &ConntrackStatEntry{}
|
|
| 88 |
- |
|
| 89 |
- entries, err := parseConntrackStatField(fields[0]) |
|
| 90 |
- if err != nil {
|
|
| 91 |
- return nil, err |
|
| 92 |
- } |
|
| 93 |
- entry.Entries = entries |
|
| 94 |
- |
|
| 95 |
- found, err := parseConntrackStatField(fields[2]) |
|
| 96 |
- if err != nil {
|
|
| 97 |
- return nil, err |
|
| 98 |
- } |
|
| 99 |
- entry.Found = found |
|
| 100 |
- |
|
| 101 |
- invalid, err := parseConntrackStatField(fields[4]) |
|
| 102 |
- if err != nil {
|
|
| 103 |
- return nil, err |
|
| 104 |
- } |
|
| 105 |
- entry.Invalid = invalid |
|
| 106 |
- |
|
| 107 |
- ignore, err := parseConntrackStatField(fields[5]) |
|
| 108 |
- if err != nil {
|
|
| 109 |
- return nil, err |
|
| 110 |
- } |
|
| 111 |
- entry.Ignore = ignore |
|
| 112 |
- |
|
| 113 |
- insert, err := parseConntrackStatField(fields[8]) |
|
| 84 |
+ entries, err := util.ParseHexUint64s(fields) |
|
| 114 | 85 |
if err != nil {
|
| 115 |
- return nil, err |
|
| 86 |
+ return nil, fmt.Errorf("%s: Cannot parse entry: %d: %w", ErrFileParse, entries, err)
|
|
| 116 | 87 |
} |
| 117 |
- entry.Insert = insert |
|
| 118 |
- |
|
| 119 |
- insertFailed, err := parseConntrackStatField(fields[9]) |
|
| 120 |
- if err != nil {
|
|
| 121 |
- return nil, err |
|
| 88 |
+ numEntries := len(entries) |
|
| 89 |
+ if numEntries < 16 || numEntries > 17 {
|
|
| 90 |
+ return nil, |
|
| 91 |
+ fmt.Errorf("%w: invalid conntrackstat entry, invalid number of fields: %d", ErrFileParse, numEntries)
|
|
| 122 | 92 |
} |
| 123 |
- entry.InsertFailed = insertFailed |
|
| 124 | 93 |
|
| 125 |
- drop, err := parseConntrackStatField(fields[10]) |
|
| 126 |
- if err != nil {
|
|
| 127 |
- return nil, err |
|
| 94 |
+ stats := &ConntrackStatEntry{
|
|
| 95 |
+ Entries: *entries[0], |
|
| 96 |
+ Searched: *entries[1], |
|
| 97 |
+ Found: *entries[2], |
|
| 98 |
+ New: *entries[3], |
|
| 99 |
+ Invalid: *entries[4], |
|
| 100 |
+ Ignore: *entries[5], |
|
| 101 |
+ Delete: *entries[6], |
|
| 102 |
+ DeleteList: *entries[7], |
|
| 103 |
+ Insert: *entries[8], |
|
| 104 |
+ InsertFailed: *entries[9], |
|
| 105 |
+ Drop: *entries[10], |
|
| 106 |
+ EarlyDrop: *entries[11], |
|
| 128 | 107 |
} |
| 129 |
- entry.Drop = drop |
|
| 130 | 108 |
|
| 131 |
- earlyDrop, err := parseConntrackStatField(fields[11]) |
|
| 132 |
- if err != nil {
|
|
| 133 |
- return nil, err |
|
| 109 |
+ // Ignore missing search_restart on Linux < 2.6.35. |
|
| 110 |
+ if numEntries == 17 {
|
|
| 111 |
+ stats.SearchRestart = *entries[16] |
|
| 134 | 112 |
} |
| 135 |
- entry.EarlyDrop = earlyDrop |
|
| 136 | 113 |
|
| 137 |
- searchRestart, err := parseConntrackStatField(fields[16]) |
|
| 138 |
- if err != nil {
|
|
| 139 |
- return nil, err |
|
| 140 |
- } |
|
| 141 |
- entry.SearchRestart = searchRestart |
|
| 142 |
- |
|
| 143 |
- return entry, nil |
|
| 144 |
-} |
|
| 145 |
- |
|
| 146 |
-// Parses a uint64 from given hex in string. |
|
| 147 |
-func parseConntrackStatField(field string) (uint64, error) {
|
|
| 148 |
- val, err := strconv.ParseUint(field, 16, 64) |
|
| 149 |
- if err != nil {
|
|
| 150 |
- return 0, fmt.Errorf("couldn't parse %q field: %w", field, err)
|
|
| 151 |
- } |
|
| 152 |
- return val, err |
|
| 114 |
+ return stats, nil |
|
| 153 | 115 |
} |
| ... | ... |
@@ -130,7 +130,7 @@ func parseIP(hexIP string) (net.IP, error) {
|
| 130 | 130 |
var byteIP []byte |
| 131 | 131 |
byteIP, err := hex.DecodeString(hexIP) |
| 132 | 132 |
if err != nil {
|
| 133 |
- return nil, fmt.Errorf("cannot parse address field in socket line %q", hexIP)
|
|
| 133 |
+ return nil, fmt.Errorf("%s: Cannot parse socket field in %q: %w", ErrFileParse, hexIP, err)
|
|
| 134 | 134 |
} |
| 135 | 135 |
switch len(byteIP) {
|
| 136 | 136 |
case 4: |
| ... | ... |
@@ -144,7 +144,7 @@ func parseIP(hexIP string) (net.IP, error) {
|
| 144 | 144 |
} |
| 145 | 145 |
return i, nil |
| 146 | 146 |
default: |
| 147 |
- return nil, fmt.Errorf("Unable to parse IP %s", hexIP)
|
|
| 147 |
+ return nil, fmt.Errorf("%s: Unable to parse IP %s: %w", ErrFileParse, hexIP, nil)
|
|
| 148 | 148 |
} |
| 149 | 149 |
} |
| 150 | 150 |
|
| ... | ... |
@@ -153,7 +153,8 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
|
| 153 | 153 |
line := &netIPSocketLine{}
|
| 154 | 154 |
if len(fields) < 10 {
|
| 155 | 155 |
return nil, fmt.Errorf( |
| 156 |
- "cannot parse net socket line as it has less then 10 columns %q", |
|
| 156 |
+ "%w: Less than 10 columns found %q", |
|
| 157 |
+ ErrFileParse, |
|
| 157 | 158 |
strings.Join(fields, " "), |
| 158 | 159 |
) |
| 159 | 160 |
} |
| ... | ... |
@@ -162,64 +163,65 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) {
|
| 162 | 162 |
// sl |
| 163 | 163 |
s := strings.Split(fields[0], ":") |
| 164 | 164 |
if len(s) != 2 {
|
| 165 |
- return nil, fmt.Errorf("cannot parse sl field in socket line %q", fields[0])
|
|
| 165 |
+ return nil, fmt.Errorf("%w: Unable to parse sl field in line %q", ErrFileParse, fields[0])
|
|
| 166 | 166 |
} |
| 167 | 167 |
|
| 168 | 168 |
if line.Sl, err = strconv.ParseUint(s[0], 0, 64); err != nil {
|
| 169 |
- return nil, fmt.Errorf("cannot parse sl value in socket line: %w", err)
|
|
| 169 |
+ return nil, fmt.Errorf("%s: Unable to parse sl field in %q: %w", ErrFileParse, line.Sl, err)
|
|
| 170 | 170 |
} |
| 171 | 171 |
// local_address |
| 172 | 172 |
l := strings.Split(fields[1], ":") |
| 173 | 173 |
if len(l) != 2 {
|
| 174 |
- return nil, fmt.Errorf("cannot parse local_address field in socket line %q", fields[1])
|
|
| 174 |
+ return nil, fmt.Errorf("%w: Unable to parse local_address field in %q", ErrFileParse, fields[1])
|
|
| 175 | 175 |
} |
| 176 | 176 |
if line.LocalAddr, err = parseIP(l[0]); err != nil {
|
| 177 | 177 |
return nil, err |
| 178 | 178 |
} |
| 179 | 179 |
if line.LocalPort, err = strconv.ParseUint(l[1], 16, 64); err != nil {
|
| 180 |
- return nil, fmt.Errorf("cannot parse local_address port value in socket line: %w", err)
|
|
| 180 |
+ return nil, fmt.Errorf("%s: Unable to parse local_address port value line %q: %w", ErrFileParse, line.LocalPort, err)
|
|
| 181 | 181 |
} |
| 182 | 182 |
|
| 183 | 183 |
// remote_address |
| 184 | 184 |
r := strings.Split(fields[2], ":") |
| 185 | 185 |
if len(r) != 2 {
|
| 186 |
- return nil, fmt.Errorf("cannot parse rem_address field in socket line %q", fields[1])
|
|
| 186 |
+ return nil, fmt.Errorf("%w: Unable to parse rem_address field in %q", ErrFileParse, fields[1])
|
|
| 187 | 187 |
} |
| 188 | 188 |
if line.RemAddr, err = parseIP(r[0]); err != nil {
|
| 189 | 189 |
return nil, err |
| 190 | 190 |
} |
| 191 | 191 |
if line.RemPort, err = strconv.ParseUint(r[1], 16, 64); err != nil {
|
| 192 |
- return nil, fmt.Errorf("cannot parse rem_address port value in socket line: %w", err)
|
|
| 192 |
+ return nil, fmt.Errorf("%s: Cannot parse rem_address port value in %q: %w", ErrFileParse, line.RemPort, err)
|
|
| 193 | 193 |
} |
| 194 | 194 |
|
| 195 | 195 |
// st |
| 196 | 196 |
if line.St, err = strconv.ParseUint(fields[3], 16, 64); err != nil {
|
| 197 |
- return nil, fmt.Errorf("cannot parse st value in socket line: %w", err)
|
|
| 197 |
+ return nil, fmt.Errorf("%s: Cannot parse st value in %q: %w", ErrFileParse, line.St, err)
|
|
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 | 200 |
// tx_queue and rx_queue |
| 201 | 201 |
q := strings.Split(fields[4], ":") |
| 202 | 202 |
if len(q) != 2 {
|
| 203 | 203 |
return nil, fmt.Errorf( |
| 204 |
- "cannot parse tx/rx queues in socket line as it has a missing colon %q", |
|
| 204 |
+ "%w: Missing colon for tx/rx queues in socket line %q", |
|
| 205 |
+ ErrFileParse, |
|
| 205 | 206 |
fields[4], |
| 206 | 207 |
) |
| 207 | 208 |
} |
| 208 | 209 |
if line.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil {
|
| 209 |
- return nil, fmt.Errorf("cannot parse tx_queue value in socket line: %w", err)
|
|
| 210 |
+ return nil, fmt.Errorf("%s: Cannot parse tx_queue value in %q: %w", ErrFileParse, line.TxQueue, err)
|
|
| 210 | 211 |
} |
| 211 | 212 |
if line.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil {
|
| 212 |
- return nil, fmt.Errorf("cannot parse rx_queue value in socket line: %w", err)
|
|
| 213 |
+ return nil, fmt.Errorf("%s: Cannot parse trx_queue value in %q: %w", ErrFileParse, line.RxQueue, err)
|
|
| 213 | 214 |
} |
| 214 | 215 |
|
| 215 | 216 |
// uid |
| 216 | 217 |
if line.UID, err = strconv.ParseUint(fields[7], 0, 64); err != nil {
|
| 217 |
- return nil, fmt.Errorf("cannot parse uid value in socket line: %w", err)
|
|
| 218 |
+ return nil, fmt.Errorf("%s: Cannot parse UID value in %q: %w", ErrFileParse, line.UID, err)
|
|
| 218 | 219 |
} |
| 219 | 220 |
|
| 220 | 221 |
// inode |
| 221 | 222 |
if line.Inode, err = strconv.ParseUint(fields[9], 0, 64); err != nil {
|
| 222 |
- return nil, fmt.Errorf("cannot parse inode value in socket line: %w", err)
|
|
| 223 |
+ return nil, fmt.Errorf("%s: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err)
|
|
| 223 | 224 |
} |
| 224 | 225 |
|
| 225 | 226 |
return line, nil |
| ... | ... |
@@ -131,7 +131,7 @@ func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, erro |
| 131 | 131 |
} else if fields[6] == disabled {
|
| 132 | 132 |
line.Slab = false |
| 133 | 133 |
} else {
|
| 134 |
- return nil, fmt.Errorf("unable to parse capability for protocol: %s", line.Name)
|
|
| 134 |
+ return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name)
|
|
| 135 | 135 |
} |
| 136 | 136 |
line.ModuleName = fields[7] |
| 137 | 137 |
|
| ... | ... |
@@ -173,7 +173,7 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro |
| 173 | 173 |
} else if capabilities[i] == "n" {
|
| 174 | 174 |
*capabilityFields[i] = false |
| 175 | 175 |
} else {
|
| 176 |
- return fmt.Errorf("unable to parse capability block for protocol: position %d", i)
|
|
| 176 |
+ return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i)
|
|
| 177 | 177 |
} |
| 178 | 178 |
} |
| 179 | 179 |
return nil |
| 180 | 180 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,143 @@ |
| 0 |
+// Copyright 2023 The Prometheus Authors |
|
| 1 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 2 |
+// you may not use this file except in compliance with the License. |
|
| 3 |
+// You may obtain a copy of the License at |
|
| 4 |
+// |
|
| 5 |
+// http://www.apache.org/licenses/LICENSE-2.0 |
|
| 6 |
+// |
|
| 7 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 8 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 9 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 10 |
+// See the License for the specific language governing permissions and |
|
| 11 |
+// limitations under the License. |
|
| 12 |
+ |
|
| 13 |
+package procfs |
|
| 14 |
+ |
|
| 15 |
+import ( |
|
| 16 |
+ "bufio" |
|
| 17 |
+ "bytes" |
|
| 18 |
+ "fmt" |
|
| 19 |
+ "io" |
|
| 20 |
+ "strconv" |
|
| 21 |
+ "strings" |
|
| 22 |
+ |
|
| 23 |
+ "github.com/prometheus/procfs/internal/util" |
|
| 24 |
+) |
|
| 25 |
+ |
|
| 26 |
+const ( |
|
| 27 |
+ blackholeRepresentation string = "*" |
|
| 28 |
+ blackholeIfaceName string = "blackhole" |
|
| 29 |
+ routeLineColumns int = 11 |
|
| 30 |
+) |
|
| 31 |
+ |
|
| 32 |
+// A NetRouteLine represents one line from net/route. |
|
| 33 |
+type NetRouteLine struct {
|
|
| 34 |
+ Iface string |
|
| 35 |
+ Destination uint32 |
|
| 36 |
+ Gateway uint32 |
|
| 37 |
+ Flags uint32 |
|
| 38 |
+ RefCnt uint32 |
|
| 39 |
+ Use uint32 |
|
| 40 |
+ Metric uint32 |
|
| 41 |
+ Mask uint32 |
|
| 42 |
+ MTU uint32 |
|
| 43 |
+ Window uint32 |
|
| 44 |
+ IRTT uint32 |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func (fs FS) NetRoute() ([]NetRouteLine, error) {
|
|
| 48 |
+ return readNetRoute(fs.proc.Path("net", "route"))
|
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+func readNetRoute(path string) ([]NetRouteLine, error) {
|
|
| 52 |
+ b, err := util.ReadFileNoStat(path) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return nil, err |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ routelines, err := parseNetRoute(bytes.NewReader(b)) |
|
| 58 |
+ if err != nil {
|
|
| 59 |
+ return nil, fmt.Errorf("failed to read net route from %s: %w", path, err)
|
|
| 60 |
+ } |
|
| 61 |
+ return routelines, nil |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func parseNetRoute(r io.Reader) ([]NetRouteLine, error) {
|
|
| 65 |
+ var routelines []NetRouteLine |
|
| 66 |
+ |
|
| 67 |
+ scanner := bufio.NewScanner(r) |
|
| 68 |
+ scanner.Scan() |
|
| 69 |
+ for scanner.Scan() {
|
|
| 70 |
+ fields := strings.Fields(scanner.Text()) |
|
| 71 |
+ routeline, err := parseNetRouteLine(fields) |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return nil, err |
|
| 74 |
+ } |
|
| 75 |
+ routelines = append(routelines, *routeline) |
|
| 76 |
+ } |
|
| 77 |
+ return routelines, nil |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+func parseNetRouteLine(fields []string) (*NetRouteLine, error) {
|
|
| 81 |
+ if len(fields) != routeLineColumns {
|
|
| 82 |
+ return nil, fmt.Errorf("invalid routeline, num of digits: %d", len(fields))
|
|
| 83 |
+ } |
|
| 84 |
+ iface := fields[0] |
|
| 85 |
+ if iface == blackholeRepresentation {
|
|
| 86 |
+ iface = blackholeIfaceName |
|
| 87 |
+ } |
|
| 88 |
+ destination, err := strconv.ParseUint(fields[1], 16, 32) |
|
| 89 |
+ if err != nil {
|
|
| 90 |
+ return nil, err |
|
| 91 |
+ } |
|
| 92 |
+ gateway, err := strconv.ParseUint(fields[2], 16, 32) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ return nil, err |
|
| 95 |
+ } |
|
| 96 |
+ flags, err := strconv.ParseUint(fields[3], 10, 32) |
|
| 97 |
+ if err != nil {
|
|
| 98 |
+ return nil, err |
|
| 99 |
+ } |
|
| 100 |
+ refcnt, err := strconv.ParseUint(fields[4], 10, 32) |
|
| 101 |
+ if err != nil {
|
|
| 102 |
+ return nil, err |
|
| 103 |
+ } |
|
| 104 |
+ use, err := strconv.ParseUint(fields[5], 10, 32) |
|
| 105 |
+ if err != nil {
|
|
| 106 |
+ return nil, err |
|
| 107 |
+ } |
|
| 108 |
+ metric, err := strconv.ParseUint(fields[6], 10, 32) |
|
| 109 |
+ if err != nil {
|
|
| 110 |
+ return nil, err |
|
| 111 |
+ } |
|
| 112 |
+ mask, err := strconv.ParseUint(fields[7], 16, 32) |
|
| 113 |
+ if err != nil {
|
|
| 114 |
+ return nil, err |
|
| 115 |
+ } |
|
| 116 |
+ mtu, err := strconv.ParseUint(fields[8], 10, 32) |
|
| 117 |
+ if err != nil {
|
|
| 118 |
+ return nil, err |
|
| 119 |
+ } |
|
| 120 |
+ window, err := strconv.ParseUint(fields[9], 10, 32) |
|
| 121 |
+ if err != nil {
|
|
| 122 |
+ return nil, err |
|
| 123 |
+ } |
|
| 124 |
+ irtt, err := strconv.ParseUint(fields[10], 10, 32) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ return nil, err |
|
| 127 |
+ } |
|
| 128 |
+ routeline := &NetRouteLine{
|
|
| 129 |
+ Iface: iface, |
|
| 130 |
+ Destination: uint32(destination), |
|
| 131 |
+ Gateway: uint32(gateway), |
|
| 132 |
+ Flags: uint32(flags), |
|
| 133 |
+ RefCnt: uint32(refcnt), |
|
| 134 |
+ Use: uint32(use), |
|
| 135 |
+ Metric: uint32(metric), |
|
| 136 |
+ Mask: uint32(mask), |
|
| 137 |
+ MTU: uint32(mtu), |
|
| 138 |
+ Window: uint32(window), |
|
| 139 |
+ IRTT: uint32(irtt), |
|
| 140 |
+ } |
|
| 141 |
+ return routeline, nil |
|
| 142 |
+} |
| ... | ... |
@@ -16,7 +16,6 @@ package procfs |
| 16 | 16 |
import ( |
| 17 | 17 |
"bufio" |
| 18 | 18 |
"bytes" |
| 19 |
- "errors" |
|
| 20 | 19 |
"fmt" |
| 21 | 20 |
"io" |
| 22 | 21 |
"strings" |
| ... | ... |
@@ -70,7 +69,7 @@ func readSockstat(name string) (*NetSockstat, error) {
|
| 70 | 70 |
|
| 71 | 71 |
stat, err := parseSockstat(bytes.NewReader(b)) |
| 72 | 72 |
if err != nil {
|
| 73 |
- return nil, fmt.Errorf("failed to read sockstats from %q: %w", name, err)
|
|
| 73 |
+ return nil, fmt.Errorf("%s: sockstats from %q: %w", ErrFileRead, name, err)
|
|
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 | 76 |
return stat, nil |
| ... | ... |
@@ -84,13 +83,13 @@ func parseSockstat(r io.Reader) (*NetSockstat, error) {
|
| 84 | 84 |
// Expect a minimum of a protocol and one key/value pair. |
| 85 | 85 |
fields := strings.Split(s.Text(), " ") |
| 86 | 86 |
if len(fields) < 3 {
|
| 87 |
- return nil, fmt.Errorf("malformed sockstat line: %q", s.Text())
|
|
| 87 |
+ return nil, fmt.Errorf("%w: Malformed sockstat line: %q", ErrFileParse, s.Text())
|
|
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 | 90 |
// The remaining fields are key/value pairs. |
| 91 | 91 |
kvs, err := parseSockstatKVs(fields[1:]) |
| 92 | 92 |
if err != nil {
|
| 93 |
- return nil, fmt.Errorf("error parsing sockstat key/value pairs from %q: %w", s.Text(), err)
|
|
| 93 |
+ return nil, fmt.Errorf("%s: sockstat key/value pairs from %q: %w", ErrFileParse, s.Text(), err)
|
|
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 | 96 |
// The first field is the protocol. We must trim its colon suffix. |
| ... | ... |
@@ -119,7 +118,7 @@ func parseSockstat(r io.Reader) (*NetSockstat, error) {
|
| 119 | 119 |
// parseSockstatKVs parses a string slice into a map of key/value pairs. |
| 120 | 120 |
func parseSockstatKVs(kvs []string) (map[string]int, error) {
|
| 121 | 121 |
if len(kvs)%2 != 0 {
|
| 122 |
- return nil, errors.New("odd number of fields in key/value pairs")
|
|
| 122 |
+ return nil, fmt.Errorf("%w:: Odd number of fields in key/value pairs %q", ErrFileParse, kvs)
|
|
| 123 | 123 |
} |
| 124 | 124 |
|
| 125 | 125 |
// Iterate two values at a time to gather key/value pairs. |
| ... | ... |
@@ -64,7 +64,7 @@ func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) {
|
| 64 | 64 |
|
| 65 | 65 |
entries, err := parseSoftnet(bytes.NewReader(b)) |
| 66 | 66 |
if err != nil {
|
| 67 |
- return nil, fmt.Errorf("failed to parse /proc/net/softnet_stat: %w", err)
|
|
| 67 |
+ return nil, fmt.Errorf("%s: /proc/net/softnet_stat: %w", ErrFileParse, err)
|
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
return entries, nil |
| ... | ... |
@@ -76,13 +76,14 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) {
|
| 76 | 76 |
s := bufio.NewScanner(r) |
| 77 | 77 |
|
| 78 | 78 |
var stats []SoftnetStat |
| 79 |
+ cpuIndex := 0 |
|
| 79 | 80 |
for s.Scan() {
|
| 80 | 81 |
columns := strings.Fields(s.Text()) |
| 81 | 82 |
width := len(columns) |
| 82 | 83 |
softnetStat := SoftnetStat{}
|
| 83 | 84 |
|
| 84 | 85 |
if width < minColumns {
|
| 85 |
- return nil, fmt.Errorf("%d columns were detected, but at least %d were expected", width, minColumns)
|
|
| 86 |
+ return nil, fmt.Errorf("%w: detected %d columns, but expected at least %d", ErrFileParse, width, minColumns)
|
|
| 86 | 87 |
} |
| 87 | 88 |
|
| 88 | 89 |
// Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2347 |
| ... | ... |
@@ -127,9 +128,13 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) {
|
| 127 | 127 |
|
| 128 | 128 |
softnetStat.SoftnetBacklogLen = us[0] |
| 129 | 129 |
softnetStat.Index = us[1] |
| 130 |
+ } else {
|
|
| 131 |
+ // For older kernels, create the Index based on the scan line number. |
|
| 132 |
+ softnetStat.Index = uint32(cpuIndex) |
|
| 130 | 133 |
} |
| 131 | 134 |
softnetStat.Width = width |
| 132 | 135 |
stats = append(stats, softnetStat) |
| 136 |
+ cpuIndex++ |
|
| 133 | 137 |
} |
| 134 | 138 |
|
| 135 | 139 |
return stats, nil |
| ... | ... |
@@ -108,14 +108,14 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
|
| 108 | 108 |
line := s.Text() |
| 109 | 109 |
item, err := nu.parseLine(line, hasInode, minFields) |
| 110 | 110 |
if err != nil {
|
| 111 |
- return nil, fmt.Errorf("failed to parse /proc/net/unix data %q: %w", line, err)
|
|
| 111 |
+ return nil, fmt.Errorf("%s: /proc/net/unix encountered data %q: %w", ErrFileParse, line, err)
|
|
| 112 | 112 |
} |
| 113 | 113 |
|
| 114 | 114 |
nu.Rows = append(nu.Rows, item) |
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 | 117 |
if err := s.Err(); err != nil {
|
| 118 |
- return nil, fmt.Errorf("failed to scan /proc/net/unix data: %w", err)
|
|
| 118 |
+ return nil, fmt.Errorf("%s: /proc/net/unix encountered data: %w", ErrFileParse, err)
|
|
| 119 | 119 |
} |
| 120 | 120 |
|
| 121 | 121 |
return &nu, nil |
| ... | ... |
@@ -126,7 +126,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, |
| 126 | 126 |
|
| 127 | 127 |
l := len(fields) |
| 128 | 128 |
if l < min {
|
| 129 |
- return nil, fmt.Errorf("expected at least %d fields but got %d", min, l)
|
|
| 129 |
+ return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l)
|
|
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
// Field offsets are as follows: |
| ... | ... |
@@ -136,29 +136,29 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, |
| 136 | 136 |
|
| 137 | 137 |
users, err := u.parseUsers(fields[1]) |
| 138 | 138 |
if err != nil {
|
| 139 |
- return nil, fmt.Errorf("failed to parse ref count %q: %w", fields[1], err)
|
|
| 139 |
+ return nil, fmt.Errorf("%s: ref count %q: %w", ErrFileParse, fields[1], err)
|
|
| 140 | 140 |
} |
| 141 | 141 |
|
| 142 | 142 |
flags, err := u.parseFlags(fields[3]) |
| 143 | 143 |
if err != nil {
|
| 144 |
- return nil, fmt.Errorf("failed to parse flags %q: %w", fields[3], err)
|
|
| 144 |
+ return nil, fmt.Errorf("%s: Unable to parse flags %q: %w", ErrFileParse, fields[3], err)
|
|
| 145 | 145 |
} |
| 146 | 146 |
|
| 147 | 147 |
typ, err := u.parseType(fields[4]) |
| 148 | 148 |
if err != nil {
|
| 149 |
- return nil, fmt.Errorf("failed to parse type %q: %w", fields[4], err)
|
|
| 149 |
+ return nil, fmt.Errorf("%s: Failed to parse type %q: %w", ErrFileParse, fields[4], err)
|
|
| 150 | 150 |
} |
| 151 | 151 |
|
| 152 | 152 |
state, err := u.parseState(fields[5]) |
| 153 | 153 |
if err != nil {
|
| 154 |
- return nil, fmt.Errorf("failed to parse state %q: %w", fields[5], err)
|
|
| 154 |
+ return nil, fmt.Errorf("%s: Failed to parse state %q: %w", ErrFileParse, fields[5], err)
|
|
| 155 | 155 |
} |
| 156 | 156 |
|
| 157 | 157 |
var inode uint64 |
| 158 | 158 |
if hasInode {
|
| 159 | 159 |
inode, err = u.parseInode(fields[6]) |
| 160 | 160 |
if err != nil {
|
| 161 |
- return nil, fmt.Errorf("failed to parse inode %q: %w", fields[6], err)
|
|
| 161 |
+ return nil, fmt.Errorf("%s failed to parse inode %q: %w", ErrFileParse, fields[6], err)
|
|
| 162 | 162 |
} |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 | 165 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,182 @@ |
| 0 |
+// Copyright 2023 The Prometheus Authors |
|
| 1 |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 2 |
+// you may not use this file except in compliance with the License. |
|
| 3 |
+// You may obtain a copy of the License at |
|
| 4 |
+// |
|
| 5 |
+// http://www.apache.org/licenses/LICENSE-2.0 |
|
| 6 |
+// |
|
| 7 |
+// Unless required by applicable law or agreed to in writing, software |
|
| 8 |
+// distributed under the License is distributed on an "AS IS" BASIS, |
|
| 9 |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 10 |
+// See the License for the specific language governing permissions and |
|
| 11 |
+// limitations under the License. |
|
| 12 |
+ |
|
| 13 |
+package procfs |
|
| 14 |
+ |
|
| 15 |
+import ( |
|
| 16 |
+ "bufio" |
|
| 17 |
+ "bytes" |
|
| 18 |
+ "fmt" |
|
| 19 |
+ "io" |
|
| 20 |
+ "strconv" |
|
| 21 |
+ "strings" |
|
| 22 |
+ |
|
| 23 |
+ "github.com/prometheus/procfs/internal/util" |
|
| 24 |
+) |
|
| 25 |
+ |
|
| 26 |
+// Wireless models the content of /proc/net/wireless. |
|
| 27 |
+type Wireless struct {
|
|
| 28 |
+ Name string |
|
| 29 |
+ |
|
| 30 |
+ // Status is the current 4-digit hex value status of the interface. |
|
| 31 |
+ Status uint64 |
|
| 32 |
+ |
|
| 33 |
+ // QualityLink is the link quality. |
|
| 34 |
+ QualityLink int |
|
| 35 |
+ |
|
| 36 |
+ // QualityLevel is the signal gain (dBm). |
|
| 37 |
+ QualityLevel int |
|
| 38 |
+ |
|
| 39 |
+ // QualityNoise is the signal noise baseline (dBm). |
|
| 40 |
+ QualityNoise int |
|
| 41 |
+ |
|
| 42 |
+ // DiscardedNwid is the number of discarded packets with wrong nwid/essid. |
|
| 43 |
+ DiscardedNwid int |
|
| 44 |
+ |
|
| 45 |
+ // DiscardedCrypt is the number of discarded packets with wrong code/decode (WEP). |
|
| 46 |
+ DiscardedCrypt int |
|
| 47 |
+ |
|
| 48 |
+ // DiscardedFrag is the number of discarded packets that can't perform MAC reassembly. |
|
| 49 |
+ DiscardedFrag int |
|
| 50 |
+ |
|
| 51 |
+ // DiscardedRetry is the number of discarded packets that reached max MAC retries. |
|
| 52 |
+ DiscardedRetry int |
|
| 53 |
+ |
|
| 54 |
+ // DiscardedMisc is the number of discarded packets for other reasons. |
|
| 55 |
+ DiscardedMisc int |
|
| 56 |
+ |
|
| 57 |
+ // MissedBeacon is the number of missed beacons/superframe. |
|
| 58 |
+ MissedBeacon int |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// Wireless returns kernel wireless statistics. |
|
| 62 |
+func (fs FS) Wireless() ([]*Wireless, error) {
|
|
| 63 |
+ b, err := util.ReadFileNoStat(fs.proc.Path("net/wireless"))
|
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return nil, err |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ m, err := parseWireless(bytes.NewReader(b)) |
|
| 69 |
+ if err != nil {
|
|
| 70 |
+ return nil, fmt.Errorf("%s: wireless: %w", ErrFileParse, err)
|
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ return m, nil |
|
| 74 |
+} |
|
| 75 |
+ |
|
| 76 |
+// parseWireless parses the contents of /proc/net/wireless. |
|
| 77 |
+/* |
|
| 78 |
+Inter-| sta-| Quality | Discarded packets | Missed | WE |
|
| 79 |
+face | tus | link level noise | nwid crypt frag retry misc | beacon | 22 |
|
| 80 |
+ eth1: 0000 5. -256. -10. 0 1 0 3 0 0 |
|
| 81 |
+ eth2: 0000 5. -256. -20. 0 2 0 4 0 0 |
|
| 82 |
+*/ |
|
| 83 |
+func parseWireless(r io.Reader) ([]*Wireless, error) {
|
|
| 84 |
+ var ( |
|
| 85 |
+ interfaces []*Wireless |
|
| 86 |
+ scanner = bufio.NewScanner(r) |
|
| 87 |
+ ) |
|
| 88 |
+ |
|
| 89 |
+ for n := 0; scanner.Scan(); n++ {
|
|
| 90 |
+ // Skip the 2 header lines. |
|
| 91 |
+ if n < 2 {
|
|
| 92 |
+ continue |
|
| 93 |
+ } |
|
| 94 |
+ |
|
| 95 |
+ line := scanner.Text() |
|
| 96 |
+ |
|
| 97 |
+ parts := strings.Split(line, ":") |
|
| 98 |
+ if len(parts) != 2 {
|
|
| 99 |
+ return nil, fmt.Errorf("%w: expected 2 parts after splitting line by ':', got %d for line %q", ErrFileParse, len(parts), line)
|
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ name := strings.TrimSpace(parts[0]) |
|
| 103 |
+ stats := strings.Fields(parts[1]) |
|
| 104 |
+ |
|
| 105 |
+ if len(stats) < 10 {
|
|
| 106 |
+ return nil, fmt.Errorf("%w: invalid number of fields in line %d, expected 10+, got %d: %q", ErrFileParse, n, len(stats), line)
|
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ status, err := strconv.ParseUint(stats[0], 16, 16) |
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ return nil, fmt.Errorf("%w: invalid status in line %d: %q", ErrFileParse, n, line)
|
|
| 112 |
+ } |
|
| 113 |
+ |
|
| 114 |
+ qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], ".")) |
|
| 115 |
+ if err != nil {
|
|
| 116 |
+ return nil, fmt.Errorf("%s: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err)
|
|
| 117 |
+ } |
|
| 118 |
+ |
|
| 119 |
+ qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], ".")) |
|
| 120 |
+ if err != nil {
|
|
| 121 |
+ return nil, fmt.Errorf("%s: Quality:level as integer %q: %w", ErrFileParse, qlevel, err)
|
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+ qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], ".")) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ return nil, fmt.Errorf("%s: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err)
|
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ dnwid, err := strconv.Atoi(stats[4]) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ return nil, fmt.Errorf("%s: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err)
|
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ dcrypt, err := strconv.Atoi(stats[5]) |
|
| 135 |
+ if err != nil {
|
|
| 136 |
+ return nil, fmt.Errorf("%s: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err)
|
|
| 137 |
+ } |
|
| 138 |
+ |
|
| 139 |
+ dfrag, err := strconv.Atoi(stats[6]) |
|
| 140 |
+ if err != nil {
|
|
| 141 |
+ return nil, fmt.Errorf("%s: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err)
|
|
| 142 |
+ } |
|
| 143 |
+ |
|
| 144 |
+ dretry, err := strconv.Atoi(stats[7]) |
|
| 145 |
+ if err != nil {
|
|
| 146 |
+ return nil, fmt.Errorf("%s: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err)
|
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ dmisc, err := strconv.Atoi(stats[8]) |
|
| 150 |
+ if err != nil {
|
|
| 151 |
+ return nil, fmt.Errorf("%s: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err)
|
|
| 152 |
+ } |
|
| 153 |
+ |
|
| 154 |
+ mbeacon, err := strconv.Atoi(stats[9]) |
|
| 155 |
+ if err != nil {
|
|
| 156 |
+ return nil, fmt.Errorf("%s: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err)
|
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ w := &Wireless{
|
|
| 160 |
+ Name: name, |
|
| 161 |
+ Status: status, |
|
| 162 |
+ QualityLink: qlink, |
|
| 163 |
+ QualityLevel: qlevel, |
|
| 164 |
+ QualityNoise: qnoise, |
|
| 165 |
+ DiscardedNwid: dnwid, |
|
| 166 |
+ DiscardedCrypt: dcrypt, |
|
| 167 |
+ DiscardedFrag: dfrag, |
|
| 168 |
+ DiscardedRetry: dretry, |
|
| 169 |
+ DiscardedMisc: dmisc, |
|
| 170 |
+ MissedBeacon: mbeacon, |
|
| 171 |
+ } |
|
| 172 |
+ |
|
| 173 |
+ interfaces = append(interfaces, w) |
|
| 174 |
+ } |
|
| 175 |
+ |
|
| 176 |
+ if err := scanner.Err(); err != nil {
|
|
| 177 |
+ return nil, fmt.Errorf("%s: Failed to scan /proc/net/wireless: %w", ErrFileRead, err)
|
|
| 178 |
+ } |
|
| 179 |
+ |
|
| 180 |
+ return interfaces, nil |
|
| 181 |
+} |
| ... | ... |
@@ -115,7 +115,7 @@ func (fs FS) NewXfrmStat() (XfrmStat, error) {
|
| 115 | 115 |
fields := strings.Fields(s.Text()) |
| 116 | 116 |
|
| 117 | 117 |
if len(fields) != 2 {
|
| 118 |
- return XfrmStat{}, fmt.Errorf("couldn't parse %q line %q", file.Name(), s.Text())
|
|
| 118 |
+ return XfrmStat{}, fmt.Errorf("%w: %q line %q", ErrFileParse, file.Name(), s.Text())
|
|
| 119 | 119 |
} |
| 120 | 120 |
|
| 121 | 121 |
name := fields[0] |
| ... | ... |
@@ -15,7 +15,6 @@ package procfs |
| 15 | 15 |
|
| 16 | 16 |
import ( |
| 17 | 17 |
"bufio" |
| 18 |
- "io" |
|
| 19 | 18 |
"os" |
| 20 | 19 |
"path/filepath" |
| 21 | 20 |
"strconv" |
| ... | ... |
@@ -38,12 +37,7 @@ func (fs FS) NetStat() ([]NetStat, error) {
|
| 38 | 38 |
var netStatsTotal []NetStat |
| 39 | 39 |
|
| 40 | 40 |
for _, filePath := range statFiles {
|
| 41 |
- file, err := os.Open(filePath) |
|
| 42 |
- if err != nil {
|
|
| 43 |
- return nil, err |
|
| 44 |
- } |
|
| 45 |
- |
|
| 46 |
- procNetstat, err := parseNetstat(file) |
|
| 41 |
+ procNetstat, err := parseNetstat(filePath) |
|
| 47 | 42 |
if err != nil {
|
| 48 | 43 |
return nil, err |
| 49 | 44 |
} |
| ... | ... |
@@ -56,14 +50,17 @@ func (fs FS) NetStat() ([]NetStat, error) {
|
| 56 | 56 |
|
| 57 | 57 |
// parseNetstat parses the metrics from `/proc/net/stat/` file |
| 58 | 58 |
// and returns a NetStat structure. |
| 59 |
-func parseNetstat(r io.Reader) (NetStat, error) {
|
|
| 60 |
- var ( |
|
| 61 |
- scanner = bufio.NewScanner(r) |
|
| 62 |
- netStat = NetStat{
|
|
| 63 |
- Stats: make(map[string][]uint64), |
|
| 64 |
- } |
|
| 65 |
- ) |
|
| 59 |
+func parseNetstat(filePath string) (NetStat, error) {
|
|
| 60 |
+ netStat := NetStat{
|
|
| 61 |
+ Stats: make(map[string][]uint64), |
|
| 62 |
+ } |
|
| 63 |
+ file, err := os.Open(filePath) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return netStat, err |
|
| 66 |
+ } |
|
| 67 |
+ defer file.Close() |
|
| 66 | 68 |
|
| 69 |
+ scanner := bufio.NewScanner(file) |
|
| 67 | 70 |
scanner.Scan() |
| 68 | 71 |
|
| 69 | 72 |
// First string is always a header for stats |
| ... | ... |
@@ -15,13 +15,13 @@ package procfs |
| 15 | 15 |
|
| 16 | 16 |
import ( |
| 17 | 17 |
"bytes" |
| 18 |
+ "errors" |
|
| 18 | 19 |
"fmt" |
| 19 | 20 |
"io" |
| 20 | 21 |
"os" |
| 21 | 22 |
"strconv" |
| 22 | 23 |
"strings" |
| 23 | 24 |
|
| 24 |
- "github.com/prometheus/procfs/internal/fs" |
|
| 25 | 25 |
"github.com/prometheus/procfs/internal/util" |
| 26 | 26 |
) |
| 27 | 27 |
|
| ... | ... |
@@ -30,12 +30,18 @@ type Proc struct {
|
| 30 | 30 |
// The process ID. |
| 31 | 31 |
PID int |
| 32 | 32 |
|
| 33 |
- fs fs.FS |
|
| 33 |
+ fs FS |
|
| 34 | 34 |
} |
| 35 | 35 |
|
| 36 | 36 |
// Procs represents a list of Proc structs. |
| 37 | 37 |
type Procs []Proc |
| 38 | 38 |
|
| 39 |
+var ( |
|
| 40 |
+ ErrFileParse = errors.New("Error Parsing File")
|
|
| 41 |
+ ErrFileRead = errors.New("Error Reading File")
|
|
| 42 |
+ ErrMountPoint = errors.New("Error Accessing Mount point")
|
|
| 43 |
+) |
|
| 44 |
+ |
|
| 39 | 45 |
func (p Procs) Len() int { return len(p) }
|
| 40 | 46 |
func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
| 41 | 47 |
func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID }
|
| ... | ... |
@@ -43,7 +49,7 @@ func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID }
|
| 43 | 43 |
// Self returns a process for the current process read via /proc/self. |
| 44 | 44 |
func Self() (Proc, error) {
|
| 45 | 45 |
fs, err := NewFS(DefaultMountPoint) |
| 46 |
- if err != nil {
|
|
| 46 |
+ if err != nil || errors.Unwrap(err) == ErrMountPoint {
|
|
| 47 | 47 |
return Proc{}, err
|
| 48 | 48 |
} |
| 49 | 49 |
return fs.Self() |
| ... | ... |
@@ -92,7 +98,7 @@ func (fs FS) Proc(pid int) (Proc, error) {
|
| 92 | 92 |
if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil {
|
| 93 | 93 |
return Proc{}, err
|
| 94 | 94 |
} |
| 95 |
- return Proc{PID: pid, fs: fs.proc}, nil
|
|
| 95 |
+ return Proc{PID: pid, fs: fs}, nil
|
|
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 | 98 |
// AllProcs returns a list of all currently available processes. |
| ... | ... |
@@ -105,7 +111,7 @@ func (fs FS) AllProcs() (Procs, error) {
|
| 105 | 105 |
|
| 106 | 106 |
names, err := d.Readdirnames(-1) |
| 107 | 107 |
if err != nil {
|
| 108 |
- return Procs{}, fmt.Errorf("could not read %q: %w", d.Name(), err)
|
|
| 108 |
+ return Procs{}, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, names, err)
|
|
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 | 111 |
p := Procs{}
|
| ... | ... |
@@ -114,7 +120,7 @@ func (fs FS) AllProcs() (Procs, error) {
|
| 114 | 114 |
if err != nil {
|
| 115 | 115 |
continue |
| 116 | 116 |
} |
| 117 |
- p = append(p, Proc{PID: int(pid), fs: fs.proc})
|
|
| 117 |
+ p = append(p, Proc{PID: int(pid), fs: fs})
|
|
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 | 120 |
return p, nil |
| ... | ... |
@@ -206,7 +212,7 @@ func (p Proc) FileDescriptors() ([]uintptr, error) {
|
| 206 | 206 |
for i, n := range names {
|
| 207 | 207 |
fd, err := strconv.ParseInt(n, 10, 32) |
| 208 | 208 |
if err != nil {
|
| 209 |
- return nil, fmt.Errorf("could not parse fd %q: %w", n, err)
|
|
| 209 |
+ return nil, fmt.Errorf("%s: Cannot parse line: %v: %w", ErrFileParse, i, err)
|
|
| 210 | 210 |
} |
| 211 | 211 |
fds[i] = uintptr(fd) |
| 212 | 212 |
} |
| ... | ... |
@@ -237,6 +243,19 @@ func (p Proc) FileDescriptorTargets() ([]string, error) {
|
| 237 | 237 |
// FileDescriptorsLen returns the number of currently open file descriptors of |
| 238 | 238 |
// a process. |
| 239 | 239 |
func (p Proc) FileDescriptorsLen() (int, error) {
|
| 240 |
+ // Use fast path if available (Linux v6.2): https://github.com/torvalds/linux/commit/f1f1f2569901 |
|
| 241 |
+ if p.fs.isReal {
|
|
| 242 |
+ stat, err := os.Stat(p.path("fd"))
|
|
| 243 |
+ if err != nil {
|
|
| 244 |
+ return 0, err |
|
| 245 |
+ } |
|
| 246 |
+ |
|
| 247 |
+ size := stat.Size() |
|
| 248 |
+ if size > 0 {
|
|
| 249 |
+ return int(size), nil |
|
| 250 |
+ } |
|
| 251 |
+ } |
|
| 252 |
+ |
|
| 240 | 253 |
fds, err := p.fileDescriptors() |
| 241 | 254 |
if err != nil {
|
| 242 | 255 |
return 0, err |
| ... | ... |
@@ -278,14 +297,14 @@ func (p Proc) fileDescriptors() ([]string, error) {
|
| 278 | 278 |
|
| 279 | 279 |
names, err := d.Readdirnames(-1) |
| 280 | 280 |
if err != nil {
|
| 281 |
- return nil, fmt.Errorf("could not read %q: %w", d.Name(), err)
|
|
| 281 |
+ return nil, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, names, err)
|
|
| 282 | 282 |
} |
| 283 | 283 |
|
| 284 | 284 |
return names, nil |
| 285 | 285 |
} |
| 286 | 286 |
|
| 287 | 287 |
func (p Proc) path(pa ...string) string {
|
| 288 |
- return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
|
|
| 288 |
+ return p.fs.proc.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
|
|
| 289 | 289 |
} |
| 290 | 290 |
|
| 291 | 291 |
// FileDescriptorsInfo retrieves information about all file descriptors of |
| ... | ... |
@@ -51,7 +51,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) {
|
| 51 | 51 |
|
| 52 | 52 |
fields := strings.SplitN(cgroupStr, ":", 3) |
| 53 | 53 |
if len(fields) < 3 {
|
| 54 |
- return nil, fmt.Errorf("at least 3 fields required, found %d fields in cgroup string: %s", len(fields), cgroupStr)
|
|
| 54 |
+ return nil, fmt.Errorf("%w: 3+ fields required, found %d fields in cgroup string: %s", ErrFileParse, len(fields), cgroupStr)
|
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
cgroup := &Cgroup{
|
| ... | ... |
@@ -60,7 +60,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) {
|
| 60 | 60 |
} |
| 61 | 61 |
cgroup.HierarchyID, err = strconv.Atoi(fields[0]) |
| 62 | 62 |
if err != nil {
|
| 63 |
- return nil, fmt.Errorf("failed to parse hierarchy ID")
|
|
| 63 |
+ return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, cgroup.HierarchyID)
|
|
| 64 | 64 |
} |
| 65 | 65 |
if fields[1] != "" {
|
| 66 | 66 |
ssNames := strings.Split(fields[1], ",") |
| ... | ... |
@@ -46,7 +46,7 @@ func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) {
|
| 46 | 46 |
fields := strings.Fields(CgroupSummaryStr) |
| 47 | 47 |
// require at least 4 fields |
| 48 | 48 |
if len(fields) < 4 {
|
| 49 |
- return nil, fmt.Errorf("at least 4 fields required, found %d fields in cgroup info string: %s", len(fields), CgroupSummaryStr)
|
|
| 49 |
+ return nil, fmt.Errorf("%w: 4+ fields required, found %d fields in cgroup info string: %s", ErrFileParse, len(fields), CgroupSummaryStr)
|
|
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 | 52 |
CgroupSummary := &CgroupSummary{
|
| ... | ... |
@@ -54,15 +54,15 @@ func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) {
|
| 54 | 54 |
} |
| 55 | 55 |
CgroupSummary.Hierarchy, err = strconv.Atoi(fields[1]) |
| 56 | 56 |
if err != nil {
|
| 57 |
- return nil, fmt.Errorf("failed to parse hierarchy ID")
|
|
| 57 |
+ return nil, fmt.Errorf("%w: Unable to parse hierarchy ID from %q", ErrFileParse, fields[1])
|
|
| 58 | 58 |
} |
| 59 | 59 |
CgroupSummary.Cgroups, err = strconv.Atoi(fields[2]) |
| 60 | 60 |
if err != nil {
|
| 61 |
- return nil, fmt.Errorf("failed to parse Cgroup Num")
|
|
| 61 |
+ return nil, fmt.Errorf("%w: Unable to parse Cgroup Num from %q", ErrFileParse, fields[2])
|
|
| 62 | 62 |
} |
| 63 | 63 |
CgroupSummary.Enabled, err = strconv.Atoi(fields[3]) |
| 64 | 64 |
if err != nil {
|
| 65 |
- return nil, fmt.Errorf("failed to parse Enabled")
|
|
| 65 |
+ return nil, fmt.Errorf("%w: Unable to parse Enabled from %q", ErrFileParse, fields[3])
|
|
| 66 | 66 |
} |
| 67 | 67 |
return CgroupSummary, nil |
| 68 | 68 |
} |
| ... | ... |
@@ -111,7 +111,7 @@ func parseInotifyInfo(line string) (*InotifyInfo, error) {
|
| 111 | 111 |
} |
| 112 | 112 |
return i, nil |
| 113 | 113 |
} |
| 114 |
- return nil, fmt.Errorf("invalid inode entry: %q", line)
|
|
| 114 |
+ return nil, fmt.Errorf("%w: invalid inode entry: %q", ErrFileParse, line)
|
|
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 | 117 |
// ProcFDInfos represents a list of ProcFDInfo structs. |
| ... | ... |
@@ -66,7 +66,7 @@ func parseInterrupts(r io.Reader) (Interrupts, error) {
|
| 66 | 66 |
continue |
| 67 | 67 |
} |
| 68 | 68 |
if len(parts) < 2 {
|
| 69 |
- return nil, fmt.Errorf("not enough fields in interrupts (expected at least 2 fields but got %d): %s", len(parts), parts)
|
|
| 69 |
+ return nil, fmt.Errorf("%w: Not enough fields in interrupts (expected 2+ fields but got %d): %s", ErrFileParse, len(parts), parts)
|
|
| 70 | 70 |
} |
| 71 | 71 |
intName := parts[0][:len(parts[0])-1] // remove trailing : |
| 72 | 72 |
|
| ... | ... |
@@ -103,7 +103,7 @@ func (p Proc) Limits() (ProcLimits, error) {
|
| 103 | 103 |
//fields := limitsMatch.Split(s.Text(), limitsFields) |
| 104 | 104 |
fields := limitsMatch.FindStringSubmatch(s.Text()) |
| 105 | 105 |
if len(fields) != limitsFields {
|
| 106 |
- return ProcLimits{}, fmt.Errorf("couldn't parse %q line %q", f.Name(), s.Text())
|
|
| 106 |
+ return ProcLimits{}, fmt.Errorf("%w: couldn't parse %q line %q", ErrFileParse, f.Name(), s.Text())
|
|
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
switch fields[1] {
|
| ... | ... |
@@ -154,7 +154,7 @@ func parseUint(s string) (uint64, error) {
|
| 154 | 154 |
} |
| 155 | 155 |
i, err := strconv.ParseUint(s, 10, 64) |
| 156 | 156 |
if err != nil {
|
| 157 |
- return 0, fmt.Errorf("couldn't parse value %q: %w", s, err)
|
|
| 157 |
+ return 0, fmt.Errorf("%s: couldn't parse value %q: %w", ErrFileParse, s, err)
|
|
| 158 | 158 |
} |
| 159 | 159 |
return i, nil |
| 160 | 160 |
} |
| ... | ... |
@@ -65,7 +65,7 @@ type ProcMap struct {
|
| 65 | 65 |
func parseDevice(s string) (uint64, error) {
|
| 66 | 66 |
toks := strings.Split(s, ":") |
| 67 | 67 |
if len(toks) < 2 {
|
| 68 |
- return 0, fmt.Errorf("unexpected number of fields")
|
|
| 68 |
+ return 0, fmt.Errorf("%w: unexpected number of fields, expected: 2, got: %q", ErrFileParse, len(toks))
|
|
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 | 71 |
major, err := strconv.ParseUint(toks[0], 16, 0) |
| ... | ... |
@@ -95,7 +95,7 @@ func parseAddress(s string) (uintptr, error) {
|
| 95 | 95 |
func parseAddresses(s string) (uintptr, uintptr, error) {
|
| 96 | 96 |
toks := strings.Split(s, "-") |
| 97 | 97 |
if len(toks) < 2 {
|
| 98 |
- return 0, 0, fmt.Errorf("invalid address")
|
|
| 98 |
+ return 0, 0, fmt.Errorf("%w: invalid address", ErrFileParse)
|
|
| 99 | 99 |
} |
| 100 | 100 |
|
| 101 | 101 |
saddr, err := parseAddress(toks[0]) |
| ... | ... |
@@ -114,7 +114,7 @@ func parseAddresses(s string) (uintptr, uintptr, error) {
|
| 114 | 114 |
// parsePermissions parses a token and returns any that are set. |
| 115 | 115 |
func parsePermissions(s string) (*ProcMapPermissions, error) {
|
| 116 | 116 |
if len(s) < 4 {
|
| 117 |
- return nil, fmt.Errorf("invalid permissions token")
|
|
| 117 |
+ return nil, fmt.Errorf("%w: invalid permissions token", ErrFileParse)
|
|
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 | 120 |
perms := ProcMapPermissions{}
|
| ... | ... |
@@ -141,7 +141,7 @@ func parsePermissions(s string) (*ProcMapPermissions, error) {
|
| 141 | 141 |
func parseProcMap(text string) (*ProcMap, error) {
|
| 142 | 142 |
fields := strings.Fields(text) |
| 143 | 143 |
if len(fields) < 5 {
|
| 144 |
- return nil, fmt.Errorf("truncated procmap entry")
|
|
| 144 |
+ return nil, fmt.Errorf("%w: truncated procmap entry", ErrFileParse)
|
|
| 145 | 145 |
} |
| 146 | 146 |
|
| 147 | 147 |
saddr, eaddr, err := parseAddresses(fields[0]) |
| ... | ... |
@@ -195,8 +195,8 @@ func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
|
| 195 | 195 |
// Remove trailing :. |
| 196 | 196 |
protocol := strings.TrimSuffix(nameParts[0], ":") |
| 197 | 197 |
if len(nameParts) != len(valueParts) {
|
| 198 |
- return procNetstat, fmt.Errorf("mismatch field count mismatch in %s: %s",
|
|
| 199 |
- fileName, protocol) |
|
| 198 |
+ return procNetstat, fmt.Errorf("%w: mismatch field count mismatch in %s: %s",
|
|
| 199 |
+ ErrFileParse, fileName, protocol) |
|
| 200 | 200 |
} |
| 201 | 201 |
for i := 1; i < len(nameParts); i++ {
|
| 202 | 202 |
value, err := strconv.ParseFloat(valueParts[i], 64) |
| ... | ... |
@@ -40,7 +40,7 @@ func (p Proc) Namespaces() (Namespaces, error) {
|
| 40 | 40 |
|
| 41 | 41 |
names, err := d.Readdirnames(-1) |
| 42 | 42 |
if err != nil {
|
| 43 |
- return nil, fmt.Errorf("failed to read contents of ns dir: %w", err)
|
|
| 43 |
+ return nil, fmt.Errorf("%s: failed to read contents of ns dir: %w", ErrFileRead, err)
|
|
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 | 46 |
ns := make(Namespaces, len(names)) |
| ... | ... |
@@ -52,13 +52,13 @@ func (p Proc) Namespaces() (Namespaces, error) {
|
| 52 | 52 |
|
| 53 | 53 |
fields := strings.SplitN(target, ":", 2) |
| 54 | 54 |
if len(fields) != 2 {
|
| 55 |
- return nil, fmt.Errorf("failed to parse namespace type and inode from %q", target)
|
|
| 55 |
+ return nil, fmt.Errorf("%w: namespace type and inode from %q", ErrFileParse, target)
|
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 | 58 |
typ := fields[0] |
| 59 | 59 |
inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) |
| 60 | 60 |
if err != nil {
|
| 61 |
- return nil, fmt.Errorf("failed to parse inode from %q: %w", fields[1], err)
|
|
| 61 |
+ return nil, fmt.Errorf("%s: inode from %q: %w", ErrFileParse, fields[1], err)
|
|
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 | 64 |
ns[name] = Namespace{typ, uint32(inode)}
|
| ... | ... |
@@ -61,14 +61,14 @@ type PSIStats struct {
|
| 61 | 61 |
func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) {
|
| 62 | 62 |
data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource)))
|
| 63 | 63 |
if err != nil {
|
| 64 |
- return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %q: %w", resource, err)
|
|
| 64 |
+ return PSIStats{}, fmt.Errorf("%s: psi_stats: unavailable for %q: %w", ErrFileRead, resource, err)
|
|
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 |
- return parsePSIStats(resource, bytes.NewReader(data)) |
|
| 67 |
+ return parsePSIStats(bytes.NewReader(data)) |
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
// parsePSIStats parses the specified file for pressure stall information. |
| 71 |
-func parsePSIStats(resource string, r io.Reader) (PSIStats, error) {
|
|
| 71 |
+func parsePSIStats(r io.Reader) (PSIStats, error) {
|
|
| 72 | 72 |
psiStats := PSIStats{}
|
| 73 | 73 |
|
| 74 | 74 |
scanner := bufio.NewScanner(r) |
| ... | ... |
@@ -135,12 +135,12 @@ func (s *ProcSMapsRollup) parseLine(line string) error {
|
| 135 | 135 |
} |
| 136 | 136 |
vBytes := vKBytes * 1024 |
| 137 | 137 |
|
| 138 |
- s.addValue(k, v, vKBytes, vBytes) |
|
| 138 |
+ s.addValue(k, vBytes) |
|
| 139 | 139 |
|
| 140 | 140 |
return nil |
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 |
-func (s *ProcSMapsRollup) addValue(k string, vString string, vUint uint64, vUintBytes uint64) {
|
|
| 143 |
+func (s *ProcSMapsRollup) addValue(k string, vUintBytes uint64) {
|
|
| 144 | 144 |
switch k {
|
| 145 | 145 |
case "Rss": |
| 146 | 146 |
s.Rss += vUintBytes |
| ... | ... |
@@ -159,8 +159,8 @@ func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) {
|
| 159 | 159 |
// Remove trailing :. |
| 160 | 160 |
protocol := strings.TrimSuffix(nameParts[0], ":") |
| 161 | 161 |
if len(nameParts) != len(valueParts) {
|
| 162 |
- return procSnmp, fmt.Errorf("mismatch field count mismatch in %s: %s",
|
|
| 163 |
- fileName, protocol) |
|
| 162 |
+ return procSnmp, fmt.Errorf("%w: mismatch field count mismatch in %s: %s",
|
|
| 163 |
+ ErrFileParse, fileName, protocol) |
|
| 164 | 164 |
} |
| 165 | 165 |
for i := 1; i < len(nameParts); i++ {
|
| 166 | 166 |
value, err := strconv.ParseFloat(valueParts[i], 64) |
| ... | ... |
@@ -18,7 +18,6 @@ import ( |
| 18 | 18 |
"fmt" |
| 19 | 19 |
"os" |
| 20 | 20 |
|
| 21 |
- "github.com/prometheus/procfs/internal/fs" |
|
| 22 | 21 |
"github.com/prometheus/procfs/internal/util" |
| 23 | 22 |
) |
| 24 | 23 |
|
| ... | ... |
@@ -112,7 +111,7 @@ type ProcStat struct {
|
| 112 | 112 |
// Aggregated block I/O delays, measured in clock ticks (centiseconds). |
| 113 | 113 |
DelayAcctBlkIOTicks uint64 |
| 114 | 114 |
|
| 115 |
- proc fs.FS |
|
| 115 |
+ proc FS |
|
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 | 118 |
// NewStat returns the current status information of the process. |
| ... | ... |
@@ -139,7 +138,7 @@ func (p Proc) Stat() (ProcStat, error) {
|
| 139 | 139 |
) |
| 140 | 140 |
|
| 141 | 141 |
if l < 0 || r < 0 {
|
| 142 |
- return ProcStat{}, fmt.Errorf("unexpected format, couldn't extract comm %q", data)
|
|
| 142 |
+ return ProcStat{}, fmt.Errorf("%w: unexpected format, couldn't extract comm %q", ErrFileParse, data)
|
|
| 143 | 143 |
} |
| 144 | 144 |
|
| 145 | 145 |
s.Comm = string(data[l+1 : r]) |
| ... | ... |
@@ -210,8 +209,7 @@ func (s ProcStat) ResidentMemory() int {
|
| 210 | 210 |
|
| 211 | 211 |
// StartTime returns the unix timestamp of the process in seconds. |
| 212 | 212 |
func (s ProcStat) StartTime() (float64, error) {
|
| 213 |
- fs := FS{proc: s.proc}
|
|
| 214 |
- stat, err := fs.Stat() |
|
| 213 |
+ stat, err := s.proc.Stat() |
|
| 215 | 214 |
if err != nil {
|
| 216 | 215 |
return 0, err |
| 217 | 216 |
} |
| ... | ... |
@@ -15,6 +15,7 @@ package procfs |
| 15 | 15 |
|
| 16 | 16 |
import ( |
| 17 | 17 |
"bytes" |
| 18 |
+ "sort" |
|
| 18 | 19 |
"strconv" |
| 19 | 20 |
"strings" |
| 20 | 21 |
|
| ... | ... |
@@ -76,6 +77,9 @@ type ProcStatus struct {
|
| 76 | 76 |
UIDs [4]string |
| 77 | 77 |
// GIDs of the process (Real, effective, saved set, and filesystem GIDs) |
| 78 | 78 |
GIDs [4]string |
| 79 |
+ |
|
| 80 |
+ // CpusAllowedList: List of cpu cores processes are allowed to run on. |
|
| 81 |
+ CpusAllowedList []uint64 |
|
| 79 | 82 |
} |
| 80 | 83 |
|
| 81 | 84 |
// NewStatus returns the current status information of the process. |
| ... | ... |
@@ -161,10 +165,38 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt |
| 161 | 161 |
s.VoluntaryCtxtSwitches = vUint |
| 162 | 162 |
case "nonvoluntary_ctxt_switches": |
| 163 | 163 |
s.NonVoluntaryCtxtSwitches = vUint |
| 164 |
+ case "Cpus_allowed_list": |
|
| 165 |
+ s.CpusAllowedList = calcCpusAllowedList(vString) |
|
| 164 | 166 |
} |
| 167 |
+ |
|
| 165 | 168 |
} |
| 166 | 169 |
|
| 167 | 170 |
// TotalCtxtSwitches returns the total context switch. |
| 168 | 171 |
func (s ProcStatus) TotalCtxtSwitches() uint64 {
|
| 169 | 172 |
return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches |
| 170 | 173 |
} |
| 174 |
+ |
|
| 175 |
+func calcCpusAllowedList(cpuString string) []uint64 {
|
|
| 176 |
+ s := strings.Split(cpuString, ",") |
|
| 177 |
+ |
|
| 178 |
+ var g []uint64 |
|
| 179 |
+ |
|
| 180 |
+ for _, cpu := range s {
|
|
| 181 |
+ // parse cpu ranges, example: 1-3=[1,2,3] |
|
| 182 |
+ if l := strings.Split(strings.TrimSpace(cpu), "-"); len(l) > 1 {
|
|
| 183 |
+ startCPU, _ := strconv.ParseUint(l[0], 10, 64) |
|
| 184 |
+ endCPU, _ := strconv.ParseUint(l[1], 10, 64) |
|
| 185 |
+ |
|
| 186 |
+ for i := startCPU; i <= endCPU; i++ {
|
|
| 187 |
+ g = append(g, i) |
|
| 188 |
+ } |
|
| 189 |
+ } else if len(l) == 1 {
|
|
| 190 |
+ cpu, _ := strconv.ParseUint(l[0], 10, 64) |
|
| 191 |
+ g = append(g, cpu) |
|
| 192 |
+ } |
|
| 193 |
+ |
|
| 194 |
+ } |
|
| 195 |
+ |
|
| 196 |
+ sort.Slice(g, func(i, j int) bool { return g[i] < g[j] })
|
|
| 197 |
+ return g |
|
| 198 |
+} |
| ... | ... |
@@ -44,7 +44,7 @@ func (fs FS) SysctlInts(sysctl string) ([]int, error) {
|
| 44 | 44 |
vp := util.NewValueParser(f) |
| 45 | 45 |
values[i] = vp.Int() |
| 46 | 46 |
if err := vp.Err(); err != nil {
|
| 47 |
- return nil, fmt.Errorf("field %d in sysctl %s is not a valid int: %w", i, sysctl, err)
|
|
| 47 |
+ return nil, fmt.Errorf("%s: field %d in sysctl %s is not a valid int: %w", ErrFileParse, i, sysctl, err)
|
|
| 48 | 48 |
} |
| 49 | 49 |
} |
| 50 | 50 |
return values, nil |
| ... | ... |
@@ -68,7 +68,7 @@ func parseV21SlabEntry(line string) (*Slab, error) {
|
| 68 | 68 |
l := slabSpace.ReplaceAllString(line, " ") |
| 69 | 69 |
s := strings.Split(l, " ") |
| 70 | 70 |
if len(s) != 16 {
|
| 71 |
- return nil, fmt.Errorf("unable to parse: %q", line)
|
|
| 71 |
+ return nil, fmt.Errorf("%w: unable to parse: %q", ErrFileParse, line)
|
|
| 72 | 72 |
} |
| 73 | 73 |
var err error |
| 74 | 74 |
i := &Slab{Name: s[0]}
|
| ... | ... |
@@ -57,7 +57,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 57 | 57 |
) |
| 58 | 58 |
|
| 59 | 59 |
if !scanner.Scan() {
|
| 60 |
- return Softirqs{}, fmt.Errorf("softirqs empty")
|
|
| 60 |
+ return Softirqs{}, fmt.Errorf("%w: softirqs empty", ErrFileRead)
|
|
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 | 63 |
for scanner.Scan() {
|
| ... | ... |
@@ -74,7 +74,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 74 | 74 |
softirqs.Hi = make([]uint64, len(perCPU)) |
| 75 | 75 |
for i, count := range perCPU {
|
| 76 | 76 |
if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 77 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (HI%d): %w", count, i, err)
|
|
| 77 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err)
|
|
| 78 | 78 |
} |
| 79 | 79 |
} |
| 80 | 80 |
case parts[0] == "TIMER:": |
| ... | ... |
@@ -82,7 +82,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 82 | 82 |
softirqs.Timer = make([]uint64, len(perCPU)) |
| 83 | 83 |
for i, count := range perCPU {
|
| 84 | 84 |
if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 85 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (TIMER%d): %w", count, i, err)
|
|
| 85 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err)
|
|
| 86 | 86 |
} |
| 87 | 87 |
} |
| 88 | 88 |
case parts[0] == "NET_TX:": |
| ... | ... |
@@ -90,7 +90,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 90 | 90 |
softirqs.NetTx = make([]uint64, len(perCPU)) |
| 91 | 91 |
for i, count := range perCPU {
|
| 92 | 92 |
if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 93 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (NET_TX%d): %w", count, i, err)
|
|
| 93 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err)
|
|
| 94 | 94 |
} |
| 95 | 95 |
} |
| 96 | 96 |
case parts[0] == "NET_RX:": |
| ... | ... |
@@ -98,7 +98,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 98 | 98 |
softirqs.NetRx = make([]uint64, len(perCPU)) |
| 99 | 99 |
for i, count := range perCPU {
|
| 100 | 100 |
if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 101 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (NET_RX%d): %w", count, i, err)
|
|
| 101 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err)
|
|
| 102 | 102 |
} |
| 103 | 103 |
} |
| 104 | 104 |
case parts[0] == "BLOCK:": |
| ... | ... |
@@ -106,7 +106,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 106 | 106 |
softirqs.Block = make([]uint64, len(perCPU)) |
| 107 | 107 |
for i, count := range perCPU {
|
| 108 | 108 |
if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 109 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (BLOCK%d): %w", count, i, err)
|
|
| 109 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err)
|
|
| 110 | 110 |
} |
| 111 | 111 |
} |
| 112 | 112 |
case parts[0] == "IRQ_POLL:": |
| ... | ... |
@@ -114,7 +114,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 114 | 114 |
softirqs.IRQPoll = make([]uint64, len(perCPU)) |
| 115 | 115 |
for i, count := range perCPU {
|
| 116 | 116 |
if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 117 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (IRQ_POLL%d): %w", count, i, err)
|
|
| 117 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err)
|
|
| 118 | 118 |
} |
| 119 | 119 |
} |
| 120 | 120 |
case parts[0] == "TASKLET:": |
| ... | ... |
@@ -122,7 +122,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 122 | 122 |
softirqs.Tasklet = make([]uint64, len(perCPU)) |
| 123 | 123 |
for i, count := range perCPU {
|
| 124 | 124 |
if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 125 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (TASKLET%d): %w", count, i, err)
|
|
| 125 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err)
|
|
| 126 | 126 |
} |
| 127 | 127 |
} |
| 128 | 128 |
case parts[0] == "SCHED:": |
| ... | ... |
@@ -130,7 +130,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 130 | 130 |
softirqs.Sched = make([]uint64, len(perCPU)) |
| 131 | 131 |
for i, count := range perCPU {
|
| 132 | 132 |
if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 133 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (SCHED%d): %w", count, i, err)
|
|
| 133 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err)
|
|
| 134 | 134 |
} |
| 135 | 135 |
} |
| 136 | 136 |
case parts[0] == "HRTIMER:": |
| ... | ... |
@@ -138,7 +138,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 138 | 138 |
softirqs.HRTimer = make([]uint64, len(perCPU)) |
| 139 | 139 |
for i, count := range perCPU {
|
| 140 | 140 |
if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 141 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (HRTIMER%d): %w", count, i, err)
|
|
| 141 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err)
|
|
| 142 | 142 |
} |
| 143 | 143 |
} |
| 144 | 144 |
case parts[0] == "RCU:": |
| ... | ... |
@@ -146,14 +146,14 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) {
|
| 146 | 146 |
softirqs.RCU = make([]uint64, len(perCPU)) |
| 147 | 147 |
for i, count := range perCPU {
|
| 148 | 148 |
if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 149 |
- return Softirqs{}, fmt.Errorf("couldn't parse %q (RCU%d): %w", count, i, err)
|
|
| 149 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err)
|
|
| 150 | 150 |
} |
| 151 | 151 |
} |
| 152 | 152 |
} |
| 153 | 153 |
} |
| 154 | 154 |
|
| 155 | 155 |
if err := scanner.Err(); err != nil {
|
| 156 |
- return Softirqs{}, fmt.Errorf("couldn't parse softirqs: %w", err)
|
|
| 156 |
+ return Softirqs{}, fmt.Errorf("%s: couldn't parse softirqs: %w", ErrFileParse, err)
|
|
| 157 | 157 |
} |
| 158 | 158 |
|
| 159 | 159 |
return softirqs, scanner.Err() |
| ... | ... |
@@ -93,10 +93,10 @@ func parseCPUStat(line string) (CPUStat, int64, error) {
|
| 93 | 93 |
&cpuStat.Guest, &cpuStat.GuestNice) |
| 94 | 94 |
|
| 95 | 95 |
if err != nil && err != io.EOF {
|
| 96 |
- return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu): %w", line, err)
|
|
| 96 |
+ return CPUStat{}, -1, fmt.Errorf("%s: couldn't parse %q (cpu): %w", ErrFileParse, line, err)
|
|
| 97 | 97 |
} |
| 98 | 98 |
if count == 0 {
|
| 99 |
- return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu): 0 elements parsed", line)
|
|
| 99 |
+ return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): 0 elements parsed", ErrFileParse, line)
|
|
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 | 102 |
cpuStat.User /= userHZ |
| ... | ... |
@@ -116,7 +116,7 @@ func parseCPUStat(line string) (CPUStat, int64, error) {
|
| 116 | 116 |
|
| 117 | 117 |
cpuID, err := strconv.ParseInt(cpu[3:], 10, 64) |
| 118 | 118 |
if err != nil {
|
| 119 |
- return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu/cpuid): %w", line, err)
|
|
| 119 |
+ return CPUStat{}, -1, fmt.Errorf("%s: couldn't parse %q (cpu/cpuid): %w", ErrFileParse, line, err)
|
|
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
return cpuStat, cpuID, nil |
| ... | ... |
@@ -136,7 +136,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) {
|
| 136 | 136 |
&softIRQStat.Hrtimer, &softIRQStat.Rcu) |
| 137 | 137 |
|
| 138 | 138 |
if err != nil {
|
| 139 |
- return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %q (softirq): %w", line, err)
|
|
| 139 |
+ return SoftIRQStat{}, 0, fmt.Errorf("%s: couldn't parse %q (softirq): %w", ErrFileParse, line, err)
|
|
| 140 | 140 |
} |
| 141 | 141 |
|
| 142 | 142 |
return softIRQStat, total, nil |
| ... | ... |
@@ -187,6 +187,10 @@ func parseStat(r io.Reader, fileName string) (Stat, error) {
|
| 187 | 187 |
err error |
| 188 | 188 |
) |
| 189 | 189 |
|
| 190 |
+ // Increase default scanner buffer to handle very long `intr` lines. |
|
| 191 |
+ buf := make([]byte, 0, 8*1024) |
|
| 192 |
+ scanner.Buffer(buf, 1024*1024) |
|
| 193 |
+ |
|
| 190 | 194 |
for scanner.Scan() {
|
| 191 | 195 |
line := scanner.Text() |
| 192 | 196 |
parts := strings.Fields(scanner.Text()) |
| ... | ... |
@@ -197,34 +201,34 @@ func parseStat(r io.Reader, fileName string) (Stat, error) {
|
| 197 | 197 |
switch {
|
| 198 | 198 |
case parts[0] == "btime": |
| 199 | 199 |
if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
|
| 200 |
- return Stat{}, fmt.Errorf("couldn't parse %q (btime): %w", parts[1], err)
|
|
| 200 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (btime): %w", ErrFileParse, parts[1], err)
|
|
| 201 | 201 |
} |
| 202 | 202 |
case parts[0] == "intr": |
| 203 | 203 |
if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
|
| 204 |
- return Stat{}, fmt.Errorf("couldn't parse %q (intr): %w", parts[1], err)
|
|
| 204 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (intr): %w", ErrFileParse, parts[1], err)
|
|
| 205 | 205 |
} |
| 206 | 206 |
numberedIRQs := parts[2:] |
| 207 | 207 |
stat.IRQ = make([]uint64, len(numberedIRQs)) |
| 208 | 208 |
for i, count := range numberedIRQs {
|
| 209 | 209 |
if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil {
|
| 210 |
- return Stat{}, fmt.Errorf("couldn't parse %q (intr%d): %w", count, i, err)
|
|
| 210 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (intr%d): %w", ErrFileParse, count, i, err)
|
|
| 211 | 211 |
} |
| 212 | 212 |
} |
| 213 | 213 |
case parts[0] == "ctxt": |
| 214 | 214 |
if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
|
| 215 |
- return Stat{}, fmt.Errorf("couldn't parse %q (ctxt): %w", parts[1], err)
|
|
| 215 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (ctxt): %w", ErrFileParse, parts[1], err)
|
|
| 216 | 216 |
} |
| 217 | 217 |
case parts[0] == "processes": |
| 218 | 218 |
if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
|
| 219 |
- return Stat{}, fmt.Errorf("couldn't parse %q (processes): %w", parts[1], err)
|
|
| 219 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (processes): %w", ErrFileParse, parts[1], err)
|
|
| 220 | 220 |
} |
| 221 | 221 |
case parts[0] == "procs_running": |
| 222 | 222 |
if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
|
| 223 |
- return Stat{}, fmt.Errorf("couldn't parse %q (procs_running): %w", parts[1], err)
|
|
| 223 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (procs_running): %w", ErrFileParse, parts[1], err)
|
|
| 224 | 224 |
} |
| 225 | 225 |
case parts[0] == "procs_blocked": |
| 226 | 226 |
if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
|
| 227 |
- return Stat{}, fmt.Errorf("couldn't parse %q (procs_blocked): %w", parts[1], err)
|
|
| 227 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q (procs_blocked): %w", ErrFileParse, parts[1], err)
|
|
| 228 | 228 |
} |
| 229 | 229 |
case parts[0] == "softirq": |
| 230 | 230 |
softIRQStats, total, err := parseSoftIRQStat(line) |
| ... | ... |
@@ -247,7 +251,7 @@ func parseStat(r io.Reader, fileName string) (Stat, error) {
|
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 | 249 |
if err := scanner.Err(); err != nil {
|
| 250 |
- return Stat{}, fmt.Errorf("couldn't parse %q: %w", fileName, err)
|
|
| 250 |
+ return Stat{}, fmt.Errorf("%s: couldn't parse %q: %w", ErrFileParse, fileName, err)
|
|
| 251 | 251 |
} |
| 252 | 252 |
|
| 253 | 253 |
return stat, nil |
| ... | ... |
@@ -64,7 +64,7 @@ func parseSwapString(swapString string) (*Swap, error) {
|
| 64 | 64 |
swapFields := strings.Fields(swapString) |
| 65 | 65 |
swapLength := len(swapFields) |
| 66 | 66 |
if swapLength < 5 {
|
| 67 |
- return nil, fmt.Errorf("too few fields in swap string: %s", swapString)
|
|
| 67 |
+ return nil, fmt.Errorf("%w: too few fields in swap string: %s", ErrFileParse, swapString)
|
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
swap := &Swap{
|
| ... | ... |
@@ -74,15 +74,15 @@ func parseSwapString(swapString string) (*Swap, error) {
|
| 74 | 74 |
|
| 75 | 75 |
swap.Size, err = strconv.Atoi(swapFields[2]) |
| 76 | 76 |
if err != nil {
|
| 77 |
- return nil, fmt.Errorf("invalid swap size: %s", swapFields[2])
|
|
| 77 |
+ return nil, fmt.Errorf("%s: invalid swap size: %s: %w", ErrFileParse, swapFields[2], err)
|
|
| 78 | 78 |
} |
| 79 | 79 |
swap.Used, err = strconv.Atoi(swapFields[3]) |
| 80 | 80 |
if err != nil {
|
| 81 |
- return nil, fmt.Errorf("invalid swap used: %s", swapFields[3])
|
|
| 81 |
+ return nil, fmt.Errorf("%s: invalid swap used: %s: %w", ErrFileParse, swapFields[3], err)
|
|
| 82 | 82 |
} |
| 83 | 83 |
swap.Priority, err = strconv.Atoi(swapFields[4]) |
| 84 | 84 |
if err != nil {
|
| 85 |
- return nil, fmt.Errorf("invalid swap priority: %s", swapFields[4])
|
|
| 85 |
+ return nil, fmt.Errorf("%s: invalid swap priority: %s: %w", ErrFileParse, swapFields[4], err)
|
|
| 86 | 86 |
} |
| 87 | 87 |
|
| 88 | 88 |
return swap, nil |
| ... | ... |
@@ -45,7 +45,7 @@ func (fs FS) AllThreads(pid int) (Procs, error) {
|
| 45 | 45 |
|
| 46 | 46 |
names, err := d.Readdirnames(-1) |
| 47 | 47 |
if err != nil {
|
| 48 |
- return Procs{}, fmt.Errorf("could not read %q: %w", d.Name(), err)
|
|
| 48 |
+ return Procs{}, fmt.Errorf("%s: could not read %q: %w", ErrFileRead, d.Name(), err)
|
|
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 | 51 |
t := Procs{}
|
| ... | ... |
@@ -54,7 +54,8 @@ func (fs FS) AllThreads(pid int) (Procs, error) {
|
| 54 | 54 |
if err != nil {
|
| 55 | 55 |
continue |
| 56 | 56 |
} |
| 57 |
- t = append(t, Proc{PID: int(tid), fs: fsi.FS(taskPath)})
|
|
| 57 |
+ |
|
| 58 |
+ t = append(t, Proc{PID: int(tid), fs: FS{fsi.FS(taskPath), fs.isReal}})
|
|
| 58 | 59 |
} |
| 59 | 60 |
|
| 60 | 61 |
return t, nil |
| ... | ... |
@@ -66,13 +67,13 @@ func (fs FS) Thread(pid, tid int) (Proc, error) {
|
| 66 | 66 |
if _, err := os.Stat(taskPath); err != nil {
|
| 67 | 67 |
return Proc{}, err
|
| 68 | 68 |
} |
| 69 |
- return Proc{PID: tid, fs: fsi.FS(taskPath)}, nil
|
|
| 69 |
+ return Proc{PID: tid, fs: FS{fsi.FS(taskPath), fs.isReal}}, nil
|
|
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 | 72 |
// Thread returns a process for a given TID of Proc. |
| 73 | 73 |
func (proc Proc) Thread(tid int) (Proc, error) {
|
| 74 |
- tfs := fsi.FS(proc.path("task"))
|
|
| 75 |
- if _, err := os.Stat(tfs.Path(strconv.Itoa(tid))); err != nil {
|
|
| 74 |
+ tfs := FS{fsi.FS(proc.path("task")), proc.fs.isReal}
|
|
| 75 |
+ if _, err := os.Stat(tfs.proc.Path(strconv.Itoa(tid))); err != nil {
|
|
| 76 | 76 |
return Proc{}, err
|
| 77 | 77 |
} |
| 78 | 78 |
return Proc{PID: tid, fs: tfs}, nil
|
| ... | ... |
@@ -86,7 +86,7 @@ func (fs FS) VM() (*VM, error) {
|
| 86 | 86 |
return nil, err |
| 87 | 87 |
} |
| 88 | 88 |
if !file.Mode().IsDir() {
|
| 89 |
- return nil, fmt.Errorf("%s is not a directory", path)
|
|
| 89 |
+ return nil, fmt.Errorf("%w: %s is not a directory", ErrFileRead, path)
|
|
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 | 92 |
files, err := os.ReadDir(path) |
| ... | ... |
@@ -75,11 +75,11 @@ var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`) |
| 75 | 75 |
func (fs FS) Zoneinfo() ([]Zoneinfo, error) {
|
| 76 | 76 |
data, err := os.ReadFile(fs.proc.Path("zoneinfo"))
|
| 77 | 77 |
if err != nil {
|
| 78 |
- return nil, fmt.Errorf("error reading zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err)
|
|
| 78 |
+ return nil, fmt.Errorf("%s: error reading zoneinfo %q: %w", ErrFileRead, fs.proc.Path("zoneinfo"), err)
|
|
| 79 | 79 |
} |
| 80 | 80 |
zoneinfo, err := parseZoneinfo(data) |
| 81 | 81 |
if err != nil {
|
| 82 |
- return nil, fmt.Errorf("error parsing zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err)
|
|
| 82 |
+ return nil, fmt.Errorf("%s: error parsing zoneinfo %q: %w", ErrFileParse, fs.proc.Path("zoneinfo"), err)
|
|
| 83 | 83 |
} |
| 84 | 84 |
return zoneinfo, nil |
| 85 | 85 |
} |
| ... | ... |
@@ -984,21 +984,21 @@ github.com/philhofer/fwd |
| 984 | 984 |
# github.com/pkg/errors v0.9.1 |
| 985 | 985 |
## explicit |
| 986 | 986 |
github.com/pkg/errors |
| 987 |
-# github.com/prometheus/client_golang v1.14.0 |
|
| 988 |
-## explicit; go 1.17 |
|
| 987 |
+# github.com/prometheus/client_golang v1.17.0 |
|
| 988 |
+## explicit; go 1.19 |
|
| 989 | 989 |
github.com/prometheus/client_golang/prometheus |
| 990 | 990 |
github.com/prometheus/client_golang/prometheus/internal |
| 991 | 991 |
github.com/prometheus/client_golang/prometheus/promhttp |
| 992 |
-# github.com/prometheus/client_model v0.3.0 |
|
| 993 |
-## explicit; go 1.9 |
|
| 992 |
+# github.com/prometheus/client_model v0.5.0 |
|
| 993 |
+## explicit; go 1.19 |
|
| 994 | 994 |
github.com/prometheus/client_model/go |
| 995 |
-# github.com/prometheus/common v0.42.0 |
|
| 995 |
+# github.com/prometheus/common v0.44.0 |
|
| 996 | 996 |
## explicit; go 1.18 |
| 997 | 997 |
github.com/prometheus/common/expfmt |
| 998 | 998 |
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg |
| 999 | 999 |
github.com/prometheus/common/model |
| 1000 |
-# github.com/prometheus/procfs v0.9.0 |
|
| 1001 |
-## explicit; go 1.18 |
|
| 1000 |
+# github.com/prometheus/procfs v0.11.1 |
|
| 1001 |
+## explicit; go 1.19 |
|
| 1002 | 1002 |
github.com/prometheus/procfs |
| 1003 | 1003 |
github.com/prometheus/procfs/internal/fs |
| 1004 | 1004 |
github.com/prometheus/procfs/internal/util |