Skip to content

Commit

Permalink
preserve old flags but mark them as deprecated
Browse files Browse the repository at this point in the history
Signed-off-by: Tommy Li <[email protected]>
  • Loading branch information
tommyzli committed Sep 4, 2024
1 parent 9abb63b commit ac0a08e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 19 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ If you are still using the legacy [Access scopes][access-scopes], the `https://w

| Flag | Required | Default | Description |
| ----------------------------------- | -------- |---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `google.project-id` | No | GCloud SDK auto-discovery | Repeatable flag of Google Project IDs |
| `google.project-ids` | No | GCloud SDK auto-discovery | Repeatable flag of Google Project IDs |
| `google.projects.filter` | No | | GCloud projects filter expression. See more [here](https://cloud.google.com/sdk/gcloud/reference/projects/list). |
| `monitoring.metrics-ingest-delay` | No | | Offsets metric collection by a delay appropriate for each metric type, e.g. because bigquery metrics are slow to appear |
| `monitoring.drop-delegated-projects` | No | No | Drop metrics from attached projects and fetch `project_id` only. |
Expand Down Expand Up @@ -143,7 +143,7 @@ If we want to get all `CPU` (`compute.googleapis.com/instance/cpu`) and `Disk` (

```
stackdriver_exporter \
--google.project-id=my-test-project \
--google.project-ids=my-test-project \
--monitoring.metrics-prefixes "compute.googleapis.com/instance/cpu"
--monitoring.metrics-prefixes "compute.googleapis.com/instance/disk"
```
Expand All @@ -170,7 +170,7 @@ The final query sent to the metrics API already includes filters for project and
Full example
```
stackdriver_exporter \
--google.project-id=my-test-project \
--google.project-ids=my-test-project \
--monitoring.metrics-prefixes='pubsub.googleapis.com/subscription' \
--monitoring.metrics-prefixes='compute.googleapis.com/instance/cpu' \
--monitoring.filters='pubsub.googleapis.com/subscription:resource.labels.subscription_id=monitoring.regex.full_match("us-west4.*my-team-subs.*")' \
Expand Down
64 changes: 48 additions & 16 deletions stackdriver_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ var (
"web.stackdriver-telemetry-path", "Path under which to expose Stackdriver metrics.",
).Default("/metrics").String()

projectID = kingpin.Flag(
"google.project-id", "DEPRECATED - Comma seperated list of Google Project IDs. Use 'google.project-ids' instead.",
).String()

projectIDs = kingpin.Flag(
"google.project-id", "Google Project IDs. Repeat this flag for multiple projects.",
"google.project-ids", "Repeatable flag of Google Project IDs",
).Strings()

projectsFilter = kingpin.Flag(
Expand Down Expand Up @@ -86,10 +90,13 @@ var (
).Default("503").Ints()

// Monitoring collector flags
monitoringMetricsTypePrefixes = kingpin.Flag(
"monitoring.metrics-type-prefixes", "DEPRECATED - Comma separated Google Stackdriver Monitoring Metric Type prefixes. Use 'monitoring.metrics-prefixes' instead.",
).String()

monitoringMetricsPrefixes = kingpin.Flag(
"monitoring.metrics-prefixes", "Google Stackdriver Monitoring Metric Type prefixes. Repeat this flag to scrape multiple prefixes.",
).Required().Strings()
).Strings()

monitoringMetricsInterval = kingpin.Flag(
"monitoring.metrics-interval", "Interval to request the Google Stackdriver Monitoring Metrics for. Only the most recent data point is used.",
Expand Down Expand Up @@ -137,15 +144,15 @@ func init() {
prometheus.MustRegister(versioncollector.NewCollector("stackdriver_exporter"))
}

func getDefaultGCPProject(ctx context.Context) (*[]string, error) {
func getDefaultGCPProject(ctx context.Context) (*string, error) {
credentials, err := google.FindDefaultCredentials(ctx, compute.ComputeScope)
if err != nil {
return nil, err
}
if credentials.ProjectID == "" {
return nil, fmt.Errorf("unable to identify the gcloud project. Got empty string")
}
return &[]string{credentials.ProjectID}, nil
return &credentials.ProjectID, nil
}

func createMonitoringService(ctx context.Context) (*monitoring.Service, error) {
Expand Down Expand Up @@ -269,16 +276,29 @@ func main() {
kingpin.Parse()

logger := promlog.New(promlogConfig)
if *projectID != "" {
level.Warn(logger).Log("msg", "The google.project-id flag is deprecated and will be replaced by google.project-ids.")
}
if *monitoringMetricsTypePrefixes != "" {
level.Warn(logger).Log("msg", "The monitoring.metrics-type-prefixes flag is deprecated and will be replaced by monitoring.metrics-prefix.")
}
if *monitoringMetricsTypePrefixes == "" && len(*monitoringMetricsPrefixes) == 0 {
level.Error(logger).Log("msg", "At least one GCP monitoring prefix is required.")
os.Exit(1)
}

ctx := context.Background()
if len(*projectIDs) == 0 && *projectsFilter == "" {
level.Info(logger).Log("msg", "Neither projectID nor projectsFilter was provided. Trying to discover it")
var discoveredProjectIDs []string

if len(*projectIDs) == 0 && *projectID == "" && *projectsFilter == "" {
level.Info(logger).Log("msg", "Neither projectIDs nor projectsFilter was provided. Trying to discover it")
var err error
projectIDs, err = getDefaultGCPProject(ctx)
defaultProject, err := getDefaultGCPProject(ctx)
if err != nil {
level.Error(logger).Log("msg", "no explicit projectID and error trying to discover default GCloud project", "err", err)
level.Error(logger).Log("msg", "no explicit projectIDs and error trying to discover default GCloud project", "err", err)
os.Exit(1)
}
discoveredProjectIDs = append(discoveredProjectIDs, *defaultProject)
}

monitoringService, err := createMonitoringService(ctx)
Expand All @@ -287,42 +307,54 @@ func main() {
os.Exit(1)
}

var discoveredProjectIDs []string

if *projectsFilter != "" {
discoveredProjectIDs, err = utils.GetProjectIDsFromFilter(ctx, *projectsFilter)
projectIDsFromFilter, err := utils.GetProjectIDsFromFilter(ctx, *projectsFilter)
if err != nil {
level.Error(logger).Log("msg", "failed to get project IDs from filter", "err", err)
os.Exit(1)
}
discoveredProjectIDs = append(discoveredProjectIDs, projectIDsFromFilter...)
}

if len(*projectIDs) > 0 {
discoveredProjectIDs = append(discoveredProjectIDs, *projectIDs...)
}
if *projectID != "" {
discoveredProjectIDs = append(discoveredProjectIDs, strings.Split(*projectID, ",")...)
}

var metricsPrefixes []string
if len(*monitoringMetricsPrefixes) > 0 {
metricsPrefixes = append(metricsPrefixes, *monitoringMetricsPrefixes...)
}
if *monitoringMetricsTypePrefixes != "" {
metricsPrefixes = append(metricsPrefixes, strings.Split(*monitoringMetricsTypePrefixes, ",")...)
}

level.Info(logger).Log(
"msg", "Starting stackdriver_exporter",
"version", version.Info(),
"build_context", version.BuildContext(),
"projects", *projectIDs,
"metric_prefixes", *monitoringMetricsPrefixes,
"metric_prefixes", fmt.Sprintf("%v", metricsPrefixes),
"extra_filters", strings.Join(*monitoringMetricsExtraFilter, ","),
"projectIDs", fmt.Sprintf("%v", discoveredProjectIDs),
"projectsFilter", *projectsFilter,
)

parsedMetricsPrefixes := parseMetricTypePrefixes(*monitoringMetricsPrefixes)
parsedMetricsPrefixes := parseMetricTypePrefixes(metricsPrefixes)
metricExtraFilters := parseMetricExtraFilters()
// drop duplicate projects
slices.Sort(discoveredProjectIDs)
uniqueProjectIds := slices.Compact(discoveredProjectIDs)

if *metricsPath == *stackdriverMetricsPath {
handler := newHandler(
discoveredProjectIDs, parsedMetricsPrefixes, metricExtraFilters, monitoringService, logger, prometheus.DefaultGatherer)
uniqueProjectIds, parsedMetricsPrefixes, metricExtraFilters, monitoringService, logger, prometheus.DefaultGatherer)
http.Handle(*metricsPath, promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, handler))
} else {
level.Info(logger).Log("msg", "Serving Stackdriver metrics at separate path", "path", *stackdriverMetricsPath)
handler := newHandler(
discoveredProjectIDs, parsedMetricsPrefixes, metricExtraFilters, monitoringService, logger, nil)
uniqueProjectIds, parsedMetricsPrefixes, metricExtraFilters, monitoringService, logger, nil)
http.Handle(*stackdriverMetricsPath, promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, handler))
http.Handle(*metricsPath, promhttp.Handler())
}
Expand Down

0 comments on commit ac0a08e

Please sign in to comment.