Micrometer Stackdriver Monitoring

Stackdriver Monitoring is a dimensional time-series SaaS with built-in dashboarding.

1. Installing micrometer-registry-stackdriver

It is recommended to use the BOM provided by Micrometer (or your framework if any), you can see how to configure it here. The examples below assume you are using a BOM.

1.1. Gradle

After the BOM is configured, add the following dependency:

implementation 'io.micrometer:micrometer-registry-stackdriver'
The version is not needed for this dependency since it is defined by the BOM.

1.2. Maven

After the BOM is configured, add the following dependency:

<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-registry-stackdriver</artifactId>
</dependency>
The version is not needed for this dependency since it is defined by the BOM.

2. Configuring

The following example configures Stackdriver:

StackdriverConfig stackdriverConfig = new StackdriverConfig() {
    @Override
    public String projectId() {
        return MY_PROJECT_ID;
    }

    @Override
    public String get(String key) {
        return null;
    }
}

MeterRegistry registry = StackdriverMeterRegistry.builder(stackdriverConfig).build();

StackdriverConfig is an interface with a set of default methods. If, in the implementation of get(String k), rather than returning null, you instead bind it to a property source, you can override the default configuration. For example, Micrometer’s Spring Boot support binds properties that are prefixed with management.metrics.export.stackdriver directly to the StackdriverConfig:

management.metrics.export.stackdriver:
    project-id: MY_PROJECT_ID
    resource-type: global

    # You will probably want to disable Stackdriver Monitoring publishing in a local development profile.
    enabled: true

    # The interval at which metrics are sent to Stackdriver Monitoring. The default is 1 minute.
    step: 1m

For most environments, you need to create and configure credentials to push metrics to Stackdriver Monitoring. In most cases, you should create a service account with Stackdriver Monitoring permissions and configure a GOOGLE_APPLICATION_CREDENTIALS environmental variable to the path of the service account key file. The following example shows how to do so:

export PROJECT_ID=MY_PROJECT_ID
export APP_NAME=MY_APP

# Create a service account
gcloud iam service-accounts create $APP_NAME

# Grant the service account Stackdriver Monitoring writer permission
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$APP_NAME@$PROJECT_ID.iam.gserviceaccount.com \
  --role roles/monitoring.metricWriter

# Create a key JSON file
gcloud iam service-accounts keys create $HOME/$APP_NAME-key.json \
  --iam-account $APP_NAME@$PROJECT_ID.iam.gserviceaccount.com

# Configure GOOGLE_APPLICATION_CREDENTIALS env var
export GOOGLE_APPLICATION_CREDENTIALS=$HOME/$APP_NAME-key.json

When running in managed environments (such as Google App Engine, Google Cloud Run, and Google Cloud Function), you need not configure this environmental variable. In those environments, a service account is automatically associated with the application instance. The underlying Stackdriver Monitoring client library can automatically detect and use those credentials.

3. Stackdriver Labels

Micrometer metrics tags are mapped to Stackdriver metrics labels. With tags and labels, you can further filter or group by the tag or label. See Micrometer Concepts for more information on tags. The following example filters by tags:

MeterRegistry registry = StackdriverMeterRegistry.builder(stackdriverConfig).build();
registry.config().commonTags("application", "my-application");

You can also configure resource labels with the StackdriverConfig method, resourceLabels. Depending on the configured resourceType, there will be required resource labels. See the documentation on choosing a monitored resource type.

When using Micrometer across multiple applications or instances, it is necessary that Stackdriver labels are unique per application or instance. Otherwise, you will see errors such as One or more TimeSeries could not be written: One or more points were written more frequently than the maximum sampling period configured. If using a resource type other than global, the resource labels may already make metrics unique per application instance. If not, a common tag with the hostname or platform-provided instance ID may be a good candidate for achieving this.

4. Spring Boot

Spring Boot provides auto-configuration for Micrometer’s StackdriverMeterRegistry. For more information, see the Spring Boot documentation.

You can manually configure or register the StackdriverMeterRegistry. In addition to using Spring Boot Actuator, make sure you create the StackdriverMeterRegistry bean:

@Bean
StackdriverConfig stackdriverConfig() {
    return new StackdriverConfig() {
        @Override
        public String projectId() {
            return MY_PROJECT_ID;
        }

        @Override
        public String get(String key) {
            return null;
        }
    }
}

@Bean
StackdriverMeterRegistry meterRegistry(StackdriverConfig stackdriverConfig) {
    return StackdriverMeterRegistry.builder(stackdriverConfig).build();
}

You can also use Spring Boot Actuator Common Tags configuration to configure common tags:

spring.application.name=my-application
management.metrics.tags.application=${spring.application.name}

5. GraalVM native image compilation

To compile an application by using micrometer-registry-stackdriver to a native image using GraalVM, add the native-image-support-java library as a dependency. Doing so ensures that the correct native image configuration is available and avoids errors like Classes that should be initialized at run time got initialized during image building.