blob: 26729d61cf2049cecc67687c4fab9ccd7cb3f498 [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 metrics provides common metrics code for Lucifer.
//
// Monitoring configuration is global to the program. This package sets
// up Stackdriver Trace, BigQuery, and tsmon.
//
// The GOOGLE_APPLICATION_CREDENTIALS environment variable specifies the GCP
// service account credentials for metrics.
//
// A top level trace is set up with the program name, taken from the
// first command argument.
package metrics
import (
"context"
"log"
"os"
"path/filepath"
"lucifer/logdog"
"cloud.google.com/go/bigquery"
"go.chromium.org/luci/common/tsmon"
"go.chromium.org/luci/common/tsmon/target"
)
var programName = filepath.Base(os.Args[0])
// logLabel is used for LabeledLog messages.
const logLabel = "metrics"
// Config describes configuration for Setup.
type Config struct {
GCPProject string
}
// Client represents all of the monitoring component clients. The
// client should be closed after use.
type Client struct {
ctx context.Context
logger logdog.Logger
bqClient *bigquery.Client
}
// Close closes the monitoring client components.
func (c *Client) Close() error {
s := c.logger.Step("Flush metrics")
defer s.Close()
// Cleanup should be performed in reverse order of Setup.
if c.bqClient != nil {
if err := c.bqClient.Close(); err != nil {
log.Printf("Error closing BigQuery client: %s", err)
}
}
tsmon.Shutdown(c.ctx)
return nil
}
// Setup configures monitoring based on the given Config. Make sure
// to close the client after use. Errors in setting up monitoring
// components will be logged and ignored so the caller does not need
// to worry about stopping the entire program (better to have no
// metrics and think there is an outage than to actually have an
// outage).
func Setup(ctx context.Context, logger logdog.Logger, c Config) (context.Context, *Client) {
cl := &Client{
ctx: ctx,
logger: logger,
}
s := logger.Step("Set up metrics")
defer s.Close()
fl := tsmonFlags()
if err := tsmon.InitializeFromFlags(ctx, &fl); err != nil {
log.Printf("Skipping tsmon setup: %s", err)
}
b, err := bigquery.NewClient(ctx, c.GCPProject)
if err != nil {
log.Printf("Skipping BigQuery setup: %s", err)
} else {
cl.bqClient = b
}
return ctx, cl
}
func tsmonFlags() tsmon.Flags {
fl := tsmon.NewFlags()
fl.Flush = tsmon.FlushManual
fl.Target.SetDefaultsFromHostname()
fl.Target.TargetType = target.TaskType
fl.Target.TaskServiceName = programName
fl.Target.TaskJobName = programName
return fl
}