blob: 6c94b29f2e073a8035c9f673a3f891115d1b729a [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"time"
cloudmonitoring "google.golang.org/api/monitoring/v3"
"v.io/jiri/tool"
"v.io/v23/context"
"v.io/x/devtools/internal/monitoring"
"v.io/x/devtools/internal/test"
"v.io/x/lib/gcm"
)
const (
buildTimeStatSuffix = "__debug/stats/system/metadata/build.Time"
)
type metadataData struct {
location *monitoring.ServiceLocation
buildTime time.Time
}
// checkServiceMetadata checks all service metadata and adds the results to GCM.
func checkServiceMetadata(v23ctx *context.T, ctx *tool.Context, s *cloudmonitoring.Service) error {
serviceNames := []string{
monitoring.SNMounttable,
monitoring.SNIdentity,
monitoring.SNRole,
monitoring.SNProxy,
monitoring.SNBenchmark,
monitoring.SNAllocator,
}
hasError := false
mdMetadata, err := gcm.GetMetric("service-metadata", projectFlag)
if err != nil {
return err
}
now := time.Now()
strNow := now.UTC().Format(time.RFC3339)
for _, serviceName := range serviceNames {
ms, err := checkSingleServiceMetadata(v23ctx, ctx, serviceName)
if err != nil {
test.Fail(ctx, "%s\n", serviceName)
fmt.Fprintf(ctx.Stderr(), "%v\n", err)
hasError = true
continue
}
aggBuildTime := newAggregator()
aggBuildAge := newAggregator()
for _, m := range ms {
buildTimeUnix := m.buildTime.Unix()
buildAgeInHours := now.Sub(m.buildTime).Hours()
instance := m.location.Instance
zone := m.location.Zone
aggBuildTime.add(float64(buildTimeUnix))
aggBuildAge.add(buildAgeInHours)
// Send data to GCM
if err := sendDataToGCM(s, mdMetadata, float64(buildTimeUnix), strNow, instance, zone, serviceName, "build time"); err != nil {
return err
}
if err := sendDataToGCM(s, mdMetadata, buildAgeInHours, strNow, instance, zone, serviceName, "build age"); err != nil {
return err
}
label := fmt.Sprintf("%s (%s, %s)", serviceName, instance, zone)
test.Pass(ctx, "%s: build time: %d, build age: %v\n", label, buildTimeUnix, buildAgeInHours)
}
// Send aggregated data to GCM.
mdMetadataAgg, err := gcm.GetMetric("service-metadata-agg", projectFlag)
if err != nil {
return err
}
if err := sendAggregatedDataToGCM(ctx, s, mdMetadataAgg, aggBuildTime, strNow, serviceName, "build time"); err != nil {
return err
}
if err := sendAggregatedDataToGCM(ctx, s, mdMetadataAgg, aggBuildAge, strNow, serviceName, "build age"); err != nil {
return err
}
}
if hasError {
return fmt.Errorf("failed to check metadata for some services.")
}
return nil
}
func checkSingleServiceMetadata(v23ctx *context.T, ctx *tool.Context, serviceName string) ([]metadataData, error) {
mountedName, err := monitoring.GetServiceMountedName(namespaceRootFlag, serviceName)
if err != nil {
return nil, err
}
// Resolve name and group results by routing ids.
groups, err := monitoring.ResolveAndProcessServiceName(v23ctx, ctx, serviceName, mountedName)
if err != nil {
return nil, err
}
// Get metadata for each group.
metadata := []metadataData{}
errors := []error{}
for _, group := range groups {
// Query build time.
timeResult, err := monitoring.GetStat(v23ctx, ctx, group, buildTimeStatSuffix)
if err != nil {
errors = append(errors, err)
continue
}
strTime := timeResult[0].GetStringValue()
buildTime, err := time.Parse("2006-01-02T15:04:05Z", strTime)
if err != nil {
errors = append(errors, fmt.Errorf("Parse(%v) failed: %v", strTime, err))
continue
}
location, err := monitoring.GetServiceLocation(v23ctx, ctx, group)
if err != nil {
errors = append(errors, err)
continue
}
metadata = append(metadata, metadataData{
location: location,
buildTime: buildTime,
})
}
if len(errors) == len(groups) {
return nil, fmt.Errorf("%v", errors)
}
return metadata, nil
}