go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/aggrmetrics/driver.go (about) 1 // Copyright 2021 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aggrmetrics 16 17 import ( 18 "context" 19 "sync" 20 21 "go.chromium.org/luci/common/errors" 22 "go.chromium.org/luci/common/tsmon" 23 "go.chromium.org/luci/common/tsmon/types" 24 25 "go.chromium.org/luci/cv/internal/common" 26 ) 27 28 // New creates a new Driver for metrics aggregation. 29 func New(env *common.Env) *Driver { 30 d := &Driver{ 31 aggregators: []aggregator{ 32 &runsAggregator{}, 33 &pmReporter{}, 34 &builderPresenceAggregator{env: env}, 35 }, 36 } 37 return d 38 } 39 40 // Driver takes care of invoking aggregators and correctly working with 41 // aggregated metrics. 42 type Driver struct { 43 aggregators []aggregator 44 } 45 46 type aggregator interface { 47 // metrics must return of metrics set by the aggregator, which should be reset 48 // after the tsmon flush. 49 metrics() []types.Metric 50 51 // report should aggregate CV's state and report the tsmon metrics for the 52 // provided projects. 53 report(ctx context.Context, projects []string) error 54 } 55 56 // Cron reports all the aggregated metrics for all active projects. 57 // 58 // Resets all known reporting metrics at the beginning. It is expected to be 59 // called once per minute, e.g., by GAE cron. 60 func (d *Driver) Cron(ctx context.Context) error { 61 d.resetMetrics(ctx) 62 active, err := activeProjects(ctx) 63 if err != nil { 64 return err 65 } 66 67 errs := errors.NewLazyMultiError(len(d.aggregators)) 68 var wg sync.WaitGroup 69 wg.Add(len(d.aggregators)) 70 for i, a := range d.aggregators { 71 i, a := i, a 72 go func() { 73 defer wg.Done() 74 if err := a.report(ctx, active); err != nil { 75 errs.Assign(i, err) 76 } 77 }() 78 } 79 wg.Wait() 80 81 return common.MostSevereError(errs.Get()) 82 } 83 84 func (d *Driver) resetMetrics(ctx context.Context) { 85 store := tsmon.GetState(ctx).Store() 86 for _, a := range d.aggregators { 87 for _, m := range a.metrics() { 88 store.Reset(ctx, m) 89 } 90 } 91 }