metrics: record the number of times lint rules are triggered during a build

This metric records the number of times it sees a lint warning in the
progress stream and categorizes the number of times each rule has been
triggered. This will only record whether a lint warning was triggered
and not whether the linter was even used or which rules were present.
That information isn't presently part of the stream.

With this change, we might be reaching some of the limitations that
spying on the progress stream gives us for metrics and may want to
consider another way for the build to communicate metrics back to the
client.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
Jonathan A. Sternberg 2024-05-29 14:01:52 -05:00
parent 55c86543ca
commit 1a93bbd3a5
No known key found for this signature in database
GPG Key ID: 6603D4B96394F6B1
1 changed files with 41 additions and 0 deletions

View File

@ -29,6 +29,7 @@ func newMetrics(mp metric.MeterProvider, attrs attribute.Set) *metricWriter {
newExecMetricRecorder(meter, attrs), newExecMetricRecorder(meter, attrs),
newExportImageMetricRecorder(meter, attrs), newExportImageMetricRecorder(meter, attrs),
newIdleMetricRecorder(meter, attrs), newIdleMetricRecorder(meter, attrs),
newLintMetricRecorder(meter, attrs),
}, },
attrs: attrs, attrs: attrs,
} }
@ -426,3 +427,43 @@ func calculateIdleTime(started, completed []time.Time) time.Duration {
} }
return elapsed return elapsed
} }
type lintMetricRecorder struct {
// Attributes holds the set of attributes for all metrics produced.
Attributes attribute.Set
// Count holds the metric for the number of times a lint rule has been triggered
// within the current build.
Count metric.Int64Counter
}
func newLintMetricRecorder(meter metric.Meter, attrs attribute.Set) *lintMetricRecorder {
mr := &lintMetricRecorder{
Attributes: attrs,
}
mr.Count, _ = meter.Int64Counter("lint.trigger.count",
metric.WithDescription("Measures the number of times a lint rule has been triggered."))
return mr
}
func (mr *lintMetricRecorder) Record(ss *client.SolveStatus) {
for _, warning := range ss.Warnings {
m := reLintMessage.FindSubmatch(warning.Short)
if m == nil {
continue
}
ruleName := string(m[1])
mr.Count.Add(context.Background(), 1,
metric.WithAttributeSet(mr.Attributes),
metric.WithAttributes(
lintRuleNameProperty.String(ruleName),
),
)
}
}
var (
reLintMessage = regexp.MustCompile(`^Lint Rule '(\w+)':`)
lintRuleNameProperty = attribute.Key("lint.rule.name")
)