aboutsummaryrefslogtreecommitdiffstats
path: root/dashboard
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-08-30 10:28:50 +0200
committerTaras Madan <tarasmadan@google.com>2024-08-30 11:51:11 +0000
commitf885a8ff9168f5e83a85ec9b1b02764e02c0f4e8 (patch)
tree98a8ba6bc4c9029ba934e6d8e1a034e4ad1debc5 /dashboard
parent3cb12728f957eec0a79ed1d53e0719fb1a772a6b (diff)
dashboard/app: total coverage is about months or quarters
Total coverage page defaults to quarters (?period=quarter). Monthly data is available with ?period=month.
Diffstat (limited to 'dashboard')
-rw-r--r--dashboard/app/entities_spanner.go31
-rw-r--r--dashboard/app/graphs.go23
2 files changed, 42 insertions, 12 deletions
diff --git a/dashboard/app/entities_spanner.go b/dashboard/app/entities_spanner.go
index abe7556d3..ff154986e 100644
--- a/dashboard/app/entities_spanner.go
+++ b/dashboard/app/entities_spanner.go
@@ -19,10 +19,11 @@ import (
type CoverageHistory struct {
instrumented map[string]int64
covered map[string]int64
+ periods map[coveragedb.TimePeriod]struct{}
}
// MergedCoverage uses dates, not time.
-func MergedCoverage(ctx context.Context, ns string, fromDate, toDate civil.Date) (*CoverageHistory, error) {
+func MergedCoverage(ctx context.Context, ns, periodType string) (*CoverageHistory, error) {
projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
client, err := coveragedb.NewClient(ctx, projectID)
if err != nil {
@@ -30,20 +31,29 @@ func MergedCoverage(ctx context.Context, ns string, fromDate, toDate civil.Date)
}
defer client.Close()
+ minDays, maxDays, err := coveragedb.MinMaxDays(periodType)
+ if err != nil {
+ return nil, fmt.Errorf("coveragedb.MinMaxDays: %w", err)
+ }
+ pOps, err := coveragedb.PeriodOps(periodType)
+ if err != nil {
+ return nil, fmt.Errorf("coveragedb.PeriodOps: %w", err)
+ }
stmt := spanner.Statement{
SQL: `
select
dateto as targetdate,
+ duration as days,
cast(sum(instrumented) as INTEGER) as instrumented,
cast(sum(covered) as INTEGER) as covered
from merge_history join files
on merge_history.session = files.session
-where namespace=$1 and dateto>=$2 and dateto<=$3
-group by dateto`,
+where namespace=$1 and duration>=$2 and duration<=$3
+group by dateto, duration`,
Params: map[string]interface{}{
"p1": ns,
- "p2": fromDate,
- "p3": toDate,
+ "p2": minDays,
+ "p3": maxDays,
},
}
@@ -52,6 +62,7 @@ group by dateto`,
res := &CoverageHistory{
instrumented: map[string]int64{},
covered: map[string]int64{},
+ periods: map[coveragedb.TimePeriod]struct{}{},
}
for {
row, err := iter.Next()
@@ -63,14 +74,24 @@ group by dateto`,
}
var r struct {
Targetdate civil.Date
+ Days int64
Instrumented int64
Covered int64
}
if err = row.ToStruct(&r); err != nil {
return nil, fmt.Errorf("failed to row.ToStruct() spanner DB: %w", err)
}
+ period := coveragedb.TimePeriod{DateTo: r.Targetdate, Days: int(r.Days)}
+ if !pOps.IsValidPeriod(period) {
+ continue
+ }
res.instrumented[r.Targetdate.String()] = r.Instrumented
res.covered[r.Targetdate.String()] = r.Covered
+ if _, found := res.periods[period]; found {
+ return nil, fmt.Errorf("db error: only one period expected for date %s, days %d",
+ period.DateTo.String(), period.Days)
+ }
+ res.periods[period] = struct{}{}
}
return res, nil
}
diff --git a/dashboard/app/graphs.go b/dashboard/app/graphs.go
index 7e9a45c84..e4ded73d6 100644
--- a/dashboard/app/graphs.go
+++ b/dashboard/app/graphs.go
@@ -16,6 +16,7 @@ import (
"cloud.google.com/go/civil"
"github.com/google/syzkaller/pkg/cover"
+ "github.com/google/syzkaller/pkg/coveragedb"
db "google.golang.org/appengine/v2/datastore"
)
@@ -232,18 +233,26 @@ func handleCoverageGraph(c context.Context, w http.ResponseWriter, r *http.Reque
if err != nil {
return err
}
- yesterday := civil.DateOf(time.Now().Add(-1 * 24 * time.Hour))
- monthAgo := yesterday.AddDays(-31)
- hist, err := MergedCoverage(c, hdr.Namespace, monthAgo, yesterday)
+ periodType := r.FormValue("period")
+ if periodType == "" {
+ periodType = coveragedb.QuarterPeriod
+ }
+ if periodType != coveragedb.QuarterPeriod && periodType != coveragedb.MonthPeriod {
+ return fmt.Errorf("only quarter and month are allowed, but received %s instead", periodType)
+ }
+ hist, err := MergedCoverage(c, hdr.Namespace, periodType)
if err != nil {
return err
}
- dates := []string{}
- for i := 31; i >= 0; i-- {
- dates = append(dates, yesterday.AddDays(-i).String())
+ pOps, err := coveragedb.PeriodOps(periodType)
+ if err != nil {
+ return err
}
+ periodEndDates := coveragedb.GenNPeriodEndDatesTill(12, civil.DateOf(time.Now()), pOps)
+
cols := []uiGraphColumn{}
- for _, date := range dates {
+ for _, periodEndDate := range periodEndDates {
+ date := periodEndDate.String()
if _, ok := hist.covered[date]; !ok || hist.instrumented[date] == 0 {
cols = append(cols, uiGraphColumn{Hint: date, Vals: []uiGraphValue{{IsNull: true}}})
} else {