1*a24ffb47SSadaf Ebrahimi# OpenCensus Stackdriver Stats Exporter 2*a24ffb47SSadaf Ebrahimi 3*a24ffb47SSadaf EbrahimiThe *OpenCensus Stackdriver Stats Exporter* is a stats exporter that exports data to 4*a24ffb47SSadaf EbrahimiStackdriver Monitoring. [Stackdriver Monitoring][stackdriver-monitoring] provides visibility into 5*a24ffb47SSadaf Ebrahimithe performance, uptime, and overall health of cloud-powered applications. Stackdriver ingests that 6*a24ffb47SSadaf Ebrahimidata and generates insights via dashboards, charts, and alerts. 7*a24ffb47SSadaf Ebrahimi 8*a24ffb47SSadaf Ebrahimi## Quickstart 9*a24ffb47SSadaf Ebrahimi 10*a24ffb47SSadaf Ebrahimi### Prerequisites 11*a24ffb47SSadaf Ebrahimi 12*a24ffb47SSadaf EbrahimiTo use this exporter, you must have an application that you'd like to monitor. The app can be on 13*a24ffb47SSadaf EbrahimiGoogle Cloud Platform, on-premise, or another cloud platform. 14*a24ffb47SSadaf Ebrahimi 15*a24ffb47SSadaf EbrahimiIn order to be able to push your stats to [Stackdriver Monitoring][stackdriver-monitoring], you must: 16*a24ffb47SSadaf Ebrahimi 17*a24ffb47SSadaf Ebrahimi1. [Create a Cloud project](https://support.google.com/cloud/answer/6251787?hl=en). 18*a24ffb47SSadaf Ebrahimi2. [Enable billing](https://support.google.com/cloud/answer/6288653#new-billing). 19*a24ffb47SSadaf Ebrahimi3. [Enable the Stackdriver Monitoring API](https://console.cloud.google.com/apis/dashboard). 20*a24ffb47SSadaf Ebrahimi 21*a24ffb47SSadaf EbrahimiThese steps enable the API but don't require that your app is hosted on Google Cloud Platform. 22*a24ffb47SSadaf Ebrahimi 23*a24ffb47SSadaf Ebrahimi### Hello "Stackdriver Stats" 24*a24ffb47SSadaf Ebrahimi 25*a24ffb47SSadaf Ebrahimi#### Add the dependencies to your project 26*a24ffb47SSadaf Ebrahimi 27*a24ffb47SSadaf EbrahimiFor Maven add to your `pom.xml`: 28*a24ffb47SSadaf Ebrahimi```xml 29*a24ffb47SSadaf Ebrahimi<dependencies> 30*a24ffb47SSadaf Ebrahimi <dependency> 31*a24ffb47SSadaf Ebrahimi <groupId>io.opencensus</groupId> 32*a24ffb47SSadaf Ebrahimi <artifactId>opencensus-api</artifactId> 33*a24ffb47SSadaf Ebrahimi <version>0.28.3</version> 34*a24ffb47SSadaf Ebrahimi </dependency> 35*a24ffb47SSadaf Ebrahimi <dependency> 36*a24ffb47SSadaf Ebrahimi <groupId>io.opencensus</groupId> 37*a24ffb47SSadaf Ebrahimi <artifactId>opencensus-exporter-stats-stackdriver</artifactId> 38*a24ffb47SSadaf Ebrahimi <version>0.28.3</version> 39*a24ffb47SSadaf Ebrahimi </dependency> 40*a24ffb47SSadaf Ebrahimi <dependency> 41*a24ffb47SSadaf Ebrahimi <groupId>io.opencensus</groupId> 42*a24ffb47SSadaf Ebrahimi <artifactId>opencensus-impl</artifactId> 43*a24ffb47SSadaf Ebrahimi <version>0.28.3</version> 44*a24ffb47SSadaf Ebrahimi <scope>runtime</scope> 45*a24ffb47SSadaf Ebrahimi </dependency> 46*a24ffb47SSadaf Ebrahimi</dependencies> 47*a24ffb47SSadaf Ebrahimi``` 48*a24ffb47SSadaf Ebrahimi 49*a24ffb47SSadaf EbrahimiFor Gradle add to your dependencies: 50*a24ffb47SSadaf Ebrahimi```groovy 51*a24ffb47SSadaf Ebrahimicompile 'io.opencensus:opencensus-api:0.28.3' 52*a24ffb47SSadaf Ebrahimicompile 'io.opencensus:opencensus-exporter-stats-stackdriver:0.28.3' 53*a24ffb47SSadaf Ebrahimiruntime 'io.opencensus:opencensus-impl:0.28.3' 54*a24ffb47SSadaf Ebrahimi``` 55*a24ffb47SSadaf Ebrahimi 56*a24ffb47SSadaf Ebrahimi#### Register the exporter 57*a24ffb47SSadaf Ebrahimi 58*a24ffb47SSadaf EbrahimiThis uses the default configuration for authentication and a given project ID. 59*a24ffb47SSadaf Ebrahimi 60*a24ffb47SSadaf Ebrahimi```java 61*a24ffb47SSadaf Ebrahimipublic class MyMainClass { 62*a24ffb47SSadaf Ebrahimi public static void main(String[] args) { 63*a24ffb47SSadaf Ebrahimi StackdriverStatsExporter.createAndRegister( 64*a24ffb47SSadaf Ebrahimi StackdriverStatsConfiguration.builder().build()); 65*a24ffb47SSadaf Ebrahimi } 66*a24ffb47SSadaf Ebrahimi} 67*a24ffb47SSadaf Ebrahimi``` 68*a24ffb47SSadaf Ebrahimi 69*a24ffb47SSadaf Ebrahimi#### Set Monitored Resource for exporter 70*a24ffb47SSadaf Ebrahimi 71*a24ffb47SSadaf EbrahimiBy default, Stackdriver Stats Exporter will try to automatically detect the environment if your 72*a24ffb47SSadaf Ebrahimiapplication is running on GCE, GKE or AWS EC2, and generate a corresponding Stackdriver GCE/GKE/EC2 73*a24ffb47SSadaf Ebrahimimonitored resource. For GKE particularly, you may want to set up some environment variables so that 74*a24ffb47SSadaf EbrahimiExporter can correctly identify your pod, cluster and container. Follow the Kubernetes instruction 75*a24ffb47SSadaf Ebrahimi[here](https://cloud.google.com/kubernetes-engine/docs/tutorials/custom-metrics-autoscaling#exporting_metrics_from_the_application) 76*a24ffb47SSadaf Ebrahimiand [here](https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/). 77*a24ffb47SSadaf Ebrahimi 78*a24ffb47SSadaf EbrahimiOtherwise, Exporter will use [a global Stackdriver monitored resource with a project_id label](https://cloud.google.com/monitoring/api/resources#tag_global), 79*a24ffb47SSadaf Ebrahimiand it works fine when you have only one exporter running. 80*a24ffb47SSadaf Ebrahimi 81*a24ffb47SSadaf EbrahimiIf you want to have multiple processes exporting stats for the same metric concurrently, and your 82*a24ffb47SSadaf Ebrahimiapplication is running on some different environment than GCE, GKE or AWS EC2 (for example DataFlow), 83*a24ffb47SSadaf Ebrahimiplease associate a unique monitored resource with each exporter if possible. 84*a24ffb47SSadaf EbrahimiPlease note that there is also an "opencensus_task" metric label that uniquely identifies the 85*a24ffb47SSadaf Ebrahimiuploaded stats. 86*a24ffb47SSadaf Ebrahimi 87*a24ffb47SSadaf EbrahimiTo set a custom MonitoredResource: 88*a24ffb47SSadaf Ebrahimi 89*a24ffb47SSadaf Ebrahimi```java 90*a24ffb47SSadaf Ebrahimipublic class MyMainClass { 91*a24ffb47SSadaf Ebrahimi public static void main(String[] args) { 92*a24ffb47SSadaf Ebrahimi // A sample DataFlow monitored resource. 93*a24ffb47SSadaf Ebrahimi MonitoredResource myResource = MonitoredResource.newBuilder() 94*a24ffb47SSadaf Ebrahimi .setType("dataflow_job") 95*a24ffb47SSadaf Ebrahimi .putLabels("project_id", "my_project") 96*a24ffb47SSadaf Ebrahimi .putLabels("job_name", "my_job") 97*a24ffb47SSadaf Ebrahimi .putLabels("region", "us-east1") 98*a24ffb47SSadaf Ebrahimi .build(); 99*a24ffb47SSadaf Ebrahimi 100*a24ffb47SSadaf Ebrahimi // Set a custom MonitoredResource. Please make sure each Stackdriver Stats Exporter has a 101*a24ffb47SSadaf Ebrahimi // unique MonitoredResource. 102*a24ffb47SSadaf Ebrahimi StackdriverStatsExporter.createAndRegister( 103*a24ffb47SSadaf Ebrahimi StackdriverStatsConfiguration.builder().setMonitoredResource(myResource).build()); 104*a24ffb47SSadaf Ebrahimi } 105*a24ffb47SSadaf Ebrahimi} 106*a24ffb47SSadaf Ebrahimi``` 107*a24ffb47SSadaf Ebrahimi 108*a24ffb47SSadaf EbrahimiFor a complete list of valid Stackdriver monitored resources, please refer to [Stackdriver 109*a24ffb47SSadaf EbrahimiDocumentation](https://cloud.google.com/monitoring/custom-metrics/creating-metrics#which-resource). 110*a24ffb47SSadaf EbrahimiPlease also note that although there are a lot of monitored resources available on [Stackdriver](https://cloud.google.com/monitoring/api/resources), 111*a24ffb47SSadaf Ebrahimionly [a small subset of them](https://cloud.google.com/monitoring/custom-metrics/creating-metrics#which-resource) 112*a24ffb47SSadaf Ebrahimiare compatible with the Opencensus Stackdriver Stats Exporter. 113*a24ffb47SSadaf Ebrahimi 114*a24ffb47SSadaf Ebrahimi#### Authentication 115*a24ffb47SSadaf Ebrahimi 116*a24ffb47SSadaf EbrahimiThis exporter uses [google-cloud-java](https://github.com/GoogleCloudPlatform/google-cloud-java), 117*a24ffb47SSadaf Ebrahimifor details about how to configure the authentication see [here](https://github.com/GoogleCloudPlatform/google-cloud-java#authentication). 118*a24ffb47SSadaf Ebrahimi 119*a24ffb47SSadaf EbrahimiIf you prefer to manually set the credentials use: 120*a24ffb47SSadaf Ebrahimi``` 121*a24ffb47SSadaf EbrahimiStackdriverStatsExporter.createAndRegister( 122*a24ffb47SSadaf Ebrahimi StackdriverStatsConfiguration.builder() 123*a24ffb47SSadaf Ebrahimi .setCredentials(new GoogleCredentials(new AccessToken(accessToken, expirationTime))) 124*a24ffb47SSadaf Ebrahimi .setProjectId("MyStackdriverProjectId") 125*a24ffb47SSadaf Ebrahimi .setExportInterval(Duration.create(60, 0)) 126*a24ffb47SSadaf Ebrahimi .build()); 127*a24ffb47SSadaf Ebrahimi``` 128*a24ffb47SSadaf Ebrahimi 129*a24ffb47SSadaf Ebrahimi#### Specifying a Project ID 130*a24ffb47SSadaf Ebrahimi 131*a24ffb47SSadaf EbrahimiThis exporter uses [google-cloud-java](https://github.com/GoogleCloudPlatform/google-cloud-java), 132*a24ffb47SSadaf Ebrahimifor details about how to configure the project ID see [here](https://github.com/GoogleCloudPlatform/google-cloud-java#specifying-a-project-id). 133*a24ffb47SSadaf Ebrahimi 134*a24ffb47SSadaf EbrahimiIf you prefer to manually set the project ID use: 135*a24ffb47SSadaf Ebrahimi``` 136*a24ffb47SSadaf EbrahimiStackdriverStatsExporter.createAndRegister( 137*a24ffb47SSadaf Ebrahimi StackdriverStatsConfiguration.builder().setProjectId("MyStackdriverProjectId").build()); 138*a24ffb47SSadaf Ebrahimi``` 139*a24ffb47SSadaf Ebrahimi 140*a24ffb47SSadaf Ebrahimi#### Java Versions 141*a24ffb47SSadaf Ebrahimi 142*a24ffb47SSadaf EbrahimiJava 7 or above is required for using this exporter. 143*a24ffb47SSadaf Ebrahimi 144*a24ffb47SSadaf Ebrahimi## FAQ 145*a24ffb47SSadaf Ebrahimi### Why did I get a PERMISSION_DENIED error from Stackdriver when using this exporter? 146*a24ffb47SSadaf EbrahimiTo use our Stackdriver Stats exporter, you need to set up billing for your cloud project, since 147*a24ffb47SSadaf Ebrahimicreating and uploading custom metrics to Stackdriver Monitoring is 148*a24ffb47SSadaf Ebrahimi[not free](https://cloud.google.com/stackdriver/pricing_v2#monitoring-costs). 149*a24ffb47SSadaf Ebrahimi 150*a24ffb47SSadaf EbrahimiTo enable billing, follow the instructions [here](https://support.google.com/cloud/answer/6288653#new-billing). 151*a24ffb47SSadaf Ebrahimi 152*a24ffb47SSadaf Ebrahimi### What is "opencensus_task" metric label ? 153*a24ffb47SSadaf EbrahimiStackdriver requires that each Timeseries to be updated only by one task at a time. A 154*a24ffb47SSadaf Ebrahimi`Timeseries` is uniquely identified by the `MonitoredResource` and the `Metric`'s labels. 155*a24ffb47SSadaf EbrahimiStackdriver exporter adds a new `Metric` label for each custom `Metric` to ensure the uniqueness 156*a24ffb47SSadaf Ebrahimiof the `Timeseries`. The format of the label is: `{LANGUAGE}-{PID}@{HOSTNAME}`, if `{PID}` is not 157*a24ffb47SSadaf Ebrahimiavailable a random number will be used. 158*a24ffb47SSadaf Ebrahimi 159*a24ffb47SSadaf EbrahimiYou have the option to override the "opencensus_task" metric label with custom constant labels using 160*a24ffb47SSadaf Ebrahimi`StackdriverStatsConfiguration.Builder.setConstantLabels()`. If you do so, make sure that the 161*a24ffb47SSadaf Ebrahimimonitored resource together with these labels is unique to the current process. This is to ensure 162*a24ffb47SSadaf Ebrahimithat there is only a single writer to each time series in Stackdriver. 163*a24ffb47SSadaf Ebrahimi 164*a24ffb47SSadaf EbrahimiYou can also set `StackdriverStatsConfiguration.Builder.setConstantLabels()` to an empty map to 165*a24ffb47SSadaf Ebrahimiavoid getting the default "opencensus_task" label. You should only do this if you know that the 166*a24ffb47SSadaf Ebrahimimonitored resource uniquely identifies this process. 167*a24ffb47SSadaf Ebrahimi 168*a24ffb47SSadaf Ebrahimi### Why did I get an error "java.lang.NoSuchMethodError: com.google.common...", like "java.lang.NoSuchMethodError:com.google.common.base.Throwables.throwIfInstanceOf"? 169*a24ffb47SSadaf EbrahimiThis is probably because there is a version conflict on Guava in the dependency tree. 170*a24ffb47SSadaf Ebrahimi 171*a24ffb47SSadaf EbrahimiFor example, `com.google.common.base.Throwables.throwIfInstanceOf` is introduced to Guava 20.0. 172*a24ffb47SSadaf EbrahimiIf your application has a dependency that bundles a Guava with version 19.0 or below 173*a24ffb47SSadaf Ebrahimi(for example, gRPC 1.10.0), it might cause a `NoSuchMethodError` since 174*a24ffb47SSadaf Ebrahimi`com.google.common.base.Throwables.throwIfInstanceOf` doesn't exist before Guava 20.0. 175*a24ffb47SSadaf Ebrahimi 176*a24ffb47SSadaf EbrahimiIn this case, please either add an explicit dependency on a newer version of Guava that has the 177*a24ffb47SSadaf Ebrahiminew method (20.0 in the previous example), or if possible, upgrade the dependency that depends on 178*a24ffb47SSadaf EbrahimiGuava to a newer version that depends on the newer Guava (for example, upgrade to gRPC 1.12.0). 179*a24ffb47SSadaf Ebrahimi 180*a24ffb47SSadaf Ebrahimi[stackdriver-monitoring]: https://cloud.google.com/monitoring/ 181