internal/vulndbreqs: simplify counting logic

We were counting a day at a time anyway, so specialize some functions
for a single date instead of a range.

Change-Id: Ibff78fcbf21de9ae4393d39c6def70ef7c4e9f99
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/500237
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/cmd/vulndbreqs/main.go b/cmd/vulndbreqs/main.go
index 79d1153..59eb383 100644
--- a/cmd/vulndbreqs/main.go
+++ b/cmd/vulndbreqs/main.go
@@ -25,7 +25,6 @@
 var (
 	limit    = flag.Int("limit", 0, "max log entries to compute")
 	fromDate = flag.String("from", "", "start date for compute")
-	toDate   = flag.String("to", "", "end date for compute")
 )
 
 func main() {
@@ -101,12 +100,7 @@
 		return err
 	}
 	from = from.AddDays(-1)
-	to, err := civil.ParseDate(*toDate)
-	if err != nil {
-		return err
-	}
-	to = to.AddDays(1)
-	rcs, err := vulndbreqs.Compute(ctx, projectID, from, to, *limit, hmacKey)
+	rcs, err := vulndbreqs.Compute(ctx, projectID, from, *limit, hmacKey)
 	if err != nil {
 		return err
 	}
diff --git a/internal/vulndbreqs/compute.go b/internal/vulndbreqs/compute.go
index 4d01bb9..4497c2f 100644
--- a/internal/vulndbreqs/compute.go
+++ b/internal/vulndbreqs/compute.go
@@ -20,8 +20,6 @@
 	"cloud.google.com/go/civil"
 	"cloud.google.com/go/logging/logadmin"
 	"cloud.google.com/go/storage"
-	"golang.org/x/exp/maps"
-	"golang.org/x/exp/slices"
 	"golang.org/x/pkgsite-metrics/internal/bigquery"
 	"golang.org/x/pkgsite-metrics/internal/derrors"
 	"golang.org/x/pkgsite-metrics/internal/log"
@@ -58,19 +56,19 @@
 // ComputeAndStoreDate computes the request counts for the given date and writes them to BigQuery.
 // It does so even if there is already stored information for that date.
 func ComputeAndStoreDate(ctx context.Context, vulndbBucketProjectID string, client *bigquery.Client, hmacKey []byte, date civil.Date) error {
-	ircs, err := Compute(ctx, vulndbBucketProjectID, date, date, 0, hmacKey)
+	ircs, err := Compute(ctx, vulndbBucketProjectID, date, 0, hmacKey)
 	if err != nil {
 		return err
 	}
 	if len(ircs) == 0 {
 		ircs = []*IPRequestCount{{Date: date, IP: "NONE", Count: 0}}
 	}
-	rcs := sumRequestCounts(ircs)
-	if len(rcs) != 1 {
-		return fmt.Errorf("got %d dates, want 1", len(rcs))
+	count := 0
+	for _, rc := range ircs {
+		count += rc.Count
 	}
-	log.Infof(ctx, "writing request count %d for %s; %d distinct IPs", rcs[0].Count, rcs[0].Date, len(ircs))
-	return writeToBigQuery(ctx, client, rcs, ircs)
+	log.Infof(ctx, "writing request count %d for %s; %d distinct IPs", count, date, len(ircs))
+	return writeToBigQuery(ctx, client, []*RequestCount{{Date: date, Count: count}}, ircs)
 }
 
 func sumRequestCounts(ircs []*IPRequestCount) []*RequestCount {
@@ -86,25 +84,21 @@
 }
 
 // Compute queries the vulndb load balancer logs for all
-// vuln DB requests between the given dates, inclusive.
-// It returns request counts for each date, sorted from newest to oldest.
+// vuln DB requests on the given date.
+// It returns request counts for the date.
 // If limit is positive, it reads no more than limit entries from the log (for testing only).
-func Compute(ctx context.Context, vulndbBucketProjectID string, fromDate, toDate civil.Date, limit int, hmacKey []byte) ([]*IPRequestCount, error) {
+func Compute(ctx context.Context, vulndbBucketProjectID string, date civil.Date, limit int, hmacKey []byte) ([]*IPRequestCount, error) {
 	if len(hmacKey) < 16 {
 		return nil, errors.New("HMAC secret must be at least 16 bytes")
 	}
-	log.Infof(ctx, "computing request counts from %s to %s", fromDate, toDate)
+	log.Infof(ctx, "computing request counts for %s", date)
 	client, err := logadmin.NewClient(ctx, vulndbBucketProjectID)
 	if err != nil {
 		return nil, err
 	}
 	defer client.Close()
 
-	type key struct {
-		date civil.Date
-		ip   string
-	}
-	counts := map[key]int{}
+	counts := map[string]int{} // key is obfuscated IP address
 
 	it := newEntryIterator(ctx, client,
 		// This filter has three sections, marked with blank lines. It is more
@@ -137,8 +131,8 @@
 		-httpRequest.requestUrl="https://vuln.go.dev/index.json"
 		-httpRequest.requestUrl:"https://vuln.go.dev/ID/"
 
-		timestamp>=`+fromDate.String()+`
-		timestamp<`+toDate.AddDays(1).String())
+		timestamp>=`+date.String()+`
+		timestamp<`+date.AddDays(1).String())
 	// Count each log entry we see, bucketing by date.
 	// The timestamps are in order from oldest to newest
 	// (https://cloud.google.com/logging/docs/reference/v2/rpc/google.logging.v2#google.logging.v2.ListLogEntriesRequest).
@@ -156,33 +150,21 @@
 		if r := entry.HTTPRequest; r != nil {
 			ip = obfuscate(r.RemoteIP, hmacKey)
 		}
-		counts[key{civil.DateOf(entry.Timestamp), ip}]++
+		counts[ip]++
 		n++
 		if limit > 0 && n > limit {
 			break
 		}
 	}
+	if logErr != nil {
+		log.Errorf(ctx, logErr, "when reading load balancer logs, no progress")
+		return nil, logErr
+	}
 
 	// Convert the counts map to a slice of IPRequestCounts.
-	keys := maps.Keys(counts)
-	// Sort from newest to oldest.
-	slices.SortFunc(keys, func(k1, k2 key) bool { return k1.date.After(k2.date) })
-	// If we encountered an error, try to make partial progress by returning
-	// at least one day's worth of data.
-	if logErr != nil {
-		if len(keys) > 1 {
-			// The last date may have partial data, so drop it.
-			keys = keys[:len(keys)-1]
-			log.Warnf(ctx, "error when reading load balancer logs, partial progress: %v",
-				logErr)
-		} else {
-			log.Errorf(ctx, logErr, "when reading load balancer logs, no progress")
-			return nil, logErr
-		}
-	}
 	var ircs []*IPRequestCount
-	for _, k := range keys {
-		ircs = append(ircs, &IPRequestCount{Date: k.date, IP: k.ip, Count: counts[k]})
+	for ip, count := range counts {
+		ircs = append(ircs, &IPRequestCount{Date: date, IP: ip, Count: count})
 	}
 	return ircs, nil
 }
diff --git a/internal/vulndbreqs/compute_test.go b/internal/vulndbreqs/compute_test.go
index 34f19bd..37c0bcd 100644
--- a/internal/vulndbreqs/compute_test.go
+++ b/internal/vulndbreqs/compute_test.go
@@ -30,7 +30,7 @@
 	// Assume there are more than 10 requests a day.
 	yesterday := civil.DateOf(time.Now()).AddDays(-1)
 	const n = 10
-	igot, err := Compute(context.Background(), projID, yesterday, yesterday, n, []byte("this-is-a-fake-hmac-key"))
+	igot, err := Compute(context.Background(), projID, yesterday, n, []byte("this-is-a-fake-hmac-key"))
 	if err != nil {
 		t.Fatal(err)
 	}