Skip to content

Commit 956d746

Browse files
committed
cue/stats: start reporting which CUE evaluator version was used
Currently, when we select an evaluator version via CUE_EXPERIMENT or via the Go API, it can be hard to really tell whether that version is actually being used as part of evaluation. It may not be due to bugs, for example, or because the way we are trying to select the version doesn't actually work as intended, such as CUE_EXPERIMENT not affecting the Go API until https://cuelang.org/cl/1202685. As agreed with Marcel, a nice way for the evaluator to report the version it used is the same way it already knows how to report other information back to the user about the evaluation: CUE_STATS_FILE. Note that it's currently not possible to collect these stats via the exposed Go API, and that is a separate problem that we need to tackle. Signed-off-by: Daniel Martí <[email protected]> Change-Id: I6c868b44dde88ca491570c526d1e2f2f0503f1d1 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1202746 Reviewed-by: Marcel van Lohuizen <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 52c4418 commit 956d746

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

cmd/cue/cmd/testdata/script/stats.txtar

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ env CUE_STATS_FILE=-
2222
exec cue eval x.cue
2323
cmp stderr out/stderr
2424

25+
# Check that EvalVersion reports the correct value.
26+
env CUE_STATS_FILE=-
27+
env CUE_EXPERIMENT=evalv3=0
28+
exec cue eval x.cue
29+
stderr -count=1 '"EvalVersion": 2,'
30+
env CUE_EXPERIMENT=evalv3=1
31+
exec cue eval x.cue
32+
stderr -count=1 '"EvalVersion": 3,'
33+
2534
-- x.cue --
2635
a: 1
2736
b: 2
@@ -36,6 +45,7 @@ contents overwritten
3645
-- out/stats.json --
3746
{
3847
"CUE": {
48+
"EvalVersion": 2,
3949
"Unifications": 4,
4050
"Disjuncts": 6,
4151
"Conjuncts": 8,
@@ -51,6 +61,7 @@ contents overwritten
5161
}
5262
-- out/stats.cue --
5363
CUE: {
64+
EvalVersion: 2
5465
Unifications: 4
5566
Disjuncts: 6
5667
Conjuncts: 8
@@ -65,6 +76,7 @@ Go: {
6576
}
6677
-- out/stats.yaml --
6778
CUE:
79+
EvalVersion: 2
6880
Unifications: 4
6981
Disjuncts: 6
7082
Conjuncts: 8
@@ -78,6 +90,7 @@ Go:
7890
-- out/stderr --
7991
{
8092
"CUE": {
93+
"EvalVersion": 2,
8194
"Unifications": 4,
8295
"Disjuncts": 6,
8396
"Conjuncts": 8,

cue/stats/stats.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,23 @@ import (
2020
"strings"
2121
"sync"
2222
"text/template"
23+
24+
"cuelang.org/go/internal"
2325
)
2426

2527
// Counts holds counters for key events during a CUE evaluation.
2628
//
2729
// This is an experimental type and the contents may change without notice.
2830
type Counts struct {
31+
// Note that we can't use the public [cuecontext.EvalVersion] type
32+
// as that would lead to an import cycle. We could use "int" but that's a bit odd.
33+
// There's no harm in referencing an internal type in practice, given that
34+
// the public type is a type alias for the internal type already.
35+
36+
// EvalVersion is the evaluator version which was used for the CUE evaluation,
37+
// corresponding to one of the values under [cuelang.org/go/cue/cuecontext.EvalVersion].
38+
EvalVersion internal.EvaluatorVersion
39+
2940
// Operation counters
3041
//
3142
// These counters account for several key operations.
@@ -69,6 +80,22 @@ type Counts struct {
6980
// add checks on each of the operations.
7081

7182
func (c *Counts) Add(other Counts) {
83+
switch v, vo := c.EvalVersion, other.EvalVersion; {
84+
case v == internal.EvalVersionUnset:
85+
// The first time we add evaluator counts, we record the evaluator version being used.
86+
if vo == internal.EvalVersionUnset {
87+
panic("the first call to Counts.Add must provide an evaluator version")
88+
}
89+
c.EvalVersion = vo
90+
case v != vo:
91+
// Any further evaluator counts being added must match the same evaluator version.
92+
//
93+
// TODO(mvdan): this is currently not possible to enforce, as we collect stats globally
94+
// via [adt.AddStats] which includes stats from contexts created with different versions.
95+
// We likely need to refactor the collection of stats so that it is not global first.
96+
97+
// panic(fmt.Sprintf("cannot mix evaluator versions in Counts.Add: %v vs %v", v, vo))
98+
}
7299
c.Unifications += other.Unifications
73100
c.Conjuncts += other.Conjuncts
74101
c.Disjuncts += other.Disjuncts

internal/core/adt/context.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ func New(v *Vertex, cfg *Config) *OpContext {
186186
Format: cfg.Format,
187187
vertex: v,
188188
Version: version,
189+
stats: stats.Counts{EvalVersion: version},
189190
Config: flags,
190191
taskContext: schedConfig,
191192
}

0 commit comments

Comments
 (0)