-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add otlp with spring boot sample (#327)
* Add initial setup files for new example * Add functioning spring boot application * add additional mappings to enhance sample * Add spring boot application properties * Update spring application to generate traces * Run application in GKE * Fix bug in credential refresh * Add client application to test credential refresh * Add readme for sample * Add missing EOF lines * Readme style update
- Loading branch information
Showing
9 changed files
with
541 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# OTLP Trace with Spring Boot and Google Auth | ||
|
||
A sample Spring Boot service that exports OTLP traces, protected by Google authentication. The sample uses auto-refreshing credentials. | ||
|
||
### Prerequisites | ||
|
||
##### Get Google Cloud Credentials on your machine | ||
|
||
```shell | ||
gcloud auth application-default login | ||
``` | ||
|
||
##### Export the Google Cloud Project ID to `GOOGLE_CLOUD_PROJECT` environment variable: | ||
|
||
```shell | ||
export GOOGLE_CLOUD_PROJECT="my-awesome-gcp-project-id" | ||
``` | ||
|
||
##### Update build.gradle to set required arguments | ||
|
||
Update [`build.gradle`](build.grade) to set the following: | ||
|
||
``` | ||
'-Dotel.resource.attributes=gcp.project_id=<YOUR_PROJECT_ID>, | ||
'-Dotel.exporter.otlp.headers=X-Goog-User-Project=<YOUR_QUOTA_PROJECT>', | ||
# Optional - if you want to export using gRPC protocol | ||
'-Dotel.exporter.otlp.protocol=grpc', | ||
``` | ||
|
||
## Running Locally on your machine | ||
|
||
Setup your endpoint with the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable: | ||
|
||
```shell | ||
export OTEL_EXPORTER_OTLP_ENDPOINT="http://your-endpoint:port" | ||
``` | ||
|
||
To run the spring boot application from project root: | ||
|
||
```shell | ||
./gradlew :examples-otlp-spring:run | ||
``` | ||
|
||
This will start the web application on localhost:8080. The application provides 2 routes: | ||
- http://localhost:8080/ : The index root; does not generate a trace. | ||
- http://localhost:8080/work : This route generates a trace. | ||
|
||
Visit these routes to interact with the application. | ||
|
||
## Running on Google Kubernetes Engine | ||
|
||
> [!NOTE] | ||
> You need to have a GKE cluster already setup in your GCP project before continuing with these steps. | ||
Create artifact registry repository to host your containerized image of the application: | ||
```shell | ||
gcloud artifacts repositories create otlp-samples --repository-format=docker --location=us-central1 | ||
|
||
gcloud auth configure-docker us-central1-docker.pkg.dev | ||
``` | ||
|
||
Build and push your image to the Artifact Registry. | ||
```shell | ||
./gradlew :examples:otlp-spring:jib --image="us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/otlp-samples/spring-otlp-trace-example:v1" | ||
``` | ||
|
||
Deploy the image on your Kubernetes cluster and setup port forwarding to interact with your cluster: | ||
```shell | ||
sed s/%GOOGLE_CLOUD_PROJECT%/$GOOGLE_CLOUD_PROJECT/g \ | ||
examples/otlp-spring/k8s/deployment.yaml | kubectl apply -f - | ||
|
||
# This connects port 8080 on your machine to port 60000 on the spring-otlp-service | ||
kubectl port-forward service/spring-otlp-service 8080:60000 | ||
``` | ||
|
||
After successfully setting up port-forwarding, you can send requests to your cluster via `curl` or some similar tool: | ||
```shell | ||
curl http://localhost:8080/work?desc=test | ||
``` | ||
|
||
### Sending continuous requests | ||
|
||
The sample comes with a [client program](src/test/java/com/google/cloud/opentelemetry/examples/otlpspring/MainClient.java) which sends requests to deployed application on your cluster at a fixed rate. | ||
Once you have port forwarding setup for your cluster, run this client program to send continuous requests to the Spring service to generate multiple traces. | ||
|
||
```shell | ||
./gradlew :examples-otlp-spring:runClient | ||
``` | ||
|
||
### GKE Cleanup | ||
|
||
After running the sample, delete the deployment and the service if you are done with it: | ||
```shell | ||
kubectl delete services spring-otlp-service | ||
kubectl delete deployment spring-otlp-trace-example | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright 2024 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
plugins { | ||
id 'java' | ||
id 'application' | ||
id 'com.google.cloud.tools.jib' | ||
} | ||
|
||
description = 'Example showcasing OTLP trace ingest on GCP and Google Auth in a Spring Boot App' | ||
|
||
group 'com.google.cloud.opentelemetry.examples' | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
implementation(libraries.opentelemetry_api) | ||
implementation(libraries.opentelemetry_sdk) | ||
implementation(libraries.opentelemetry_otlp_exporter) | ||
implementation(libraries.opentelemetry_sdk_autoconf) | ||
implementation(libraries.google_auth) | ||
|
||
implementation(libraries.spring_boot_starter_web) | ||
} | ||
|
||
// Provide headers from env variable | ||
// export OTEL_EXPORTER_OTLP_ENDPOINT="http://path/to/yourendpoint:port" | ||
def autoconf_config = [ | ||
'-Dotel.resource.attributes=gcp.project_id=<YOUR_PROJECT>', | ||
'-Dotel.exporter.otlp.headers=X-Goog-User-Project=<YOUR_QUOTA_PROJECT>', | ||
'-Dotel.traces.exporter=otlp', | ||
'-Dotel.metrics.exporter=none', | ||
'-Dotel.exporter.otlp.protocol=http/protobuf', | ||
'-Dotel.java.global-autoconfigure.enabled=true', | ||
'-Dotel.service.name=spring-otlp-trace-example-service', | ||
] | ||
|
||
application { | ||
mainClass = "com.google.cloud.opentelemetry.examples.otlpspring.Main" | ||
applicationDefaultJvmArgs = autoconf_config | ||
} | ||
|
||
jib { | ||
from.image = "gcr.io/distroless/java-debian10:11" | ||
containerizingMode = "packaged" | ||
container.jvmFlags = autoconf_config as List | ||
container.ports = ["8080"] | ||
container.environment = [ | ||
"OTEL_EXPORTER_OTLP_ENDPOINT":"http://path/to/yourendpoint:port", | ||
] | ||
} | ||
|
||
tasks.register('runClient', JavaExec) { | ||
classpath = sourceSets.test.runtimeClasspath | ||
mainClass = 'com.google.cloud.opentelemetry.examples.otlpspring.MainClient' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: spring-otlp-trace-example | ||
namespace: default | ||
labels: | ||
app: spring-otlp-trace-example | ||
tier: backend | ||
spec: | ||
selector: | ||
matchLabels: | ||
app: spring-otlp-trace-example | ||
tier: backend | ||
template: | ||
metadata: | ||
labels: | ||
app: spring-otlp-trace-example | ||
tier: backend | ||
spec: | ||
containers: | ||
- name: spring-otlp-trace-example | ||
image: us-central1-docker.pkg.dev/%GOOGLE_CLOUD_PROJECT%/otlp-samples/spring-otlp-trace-example:v1 | ||
imagePullPolicy: Always | ||
# required for resource detection in GKE environment | ||
env: | ||
- name: NAMESPACE | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.namespace | ||
- name: CONTAINER_NAME | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.name | ||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: spring-otlp-service | ||
spec: | ||
selector: | ||
app: spring-otlp-trace-example | ||
tier: backend | ||
ports: | ||
- protocol: TCP | ||
port: 60000 | ||
targetPort: 8080 |
74 changes: 74 additions & 0 deletions
74
...c/main/java/com/google/cloud/opentelemetry/examples/otlpspring/ApplicationController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright 2024 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.google.cloud.opentelemetry.examples.otlpspring; | ||
|
||
import io.opentelemetry.api.trace.Span; | ||
import io.opentelemetry.context.Scope; | ||
import io.opentelemetry.sdk.OpenTelemetrySdk; | ||
import java.util.Optional; | ||
import java.util.Random; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class ApplicationController { | ||
private static final String INSTRUMENTATION_SCOPE_NAME = ApplicationController.class.getName(); | ||
private static final Random random = new Random(); | ||
|
||
private static final String INDEX_GREETING = | ||
"Welcome to OTLP Trace sample with Google Auth on Spring"; | ||
private static final String WORK_RESPONSE_FMT = "Work finished in %d ms"; | ||
|
||
private final Logger logger = LoggerFactory.getLogger(ApplicationController.class); | ||
private final OpenTelemetrySdk openTelemetrySdk; | ||
|
||
@Autowired | ||
public ApplicationController(OpenTelemetrySdk openTelemetrySdk) { | ||
this.openTelemetrySdk = openTelemetrySdk; | ||
} | ||
|
||
@GetMapping("/") | ||
public String index() { | ||
return INDEX_GREETING; | ||
} | ||
|
||
@GetMapping("/work") | ||
public String simulateWork(@RequestParam(name = "desc") Optional<String> description) { | ||
String desc = description.orElse("generic"); | ||
// Generate a span | ||
Span span = | ||
openTelemetrySdk.getTracer(INSTRUMENTATION_SCOPE_NAME).spanBuilder(desc).startSpan(); | ||
long workDurationMillis; | ||
try (Scope scope = span.makeCurrent()) { | ||
span.addEvent("Event A"); | ||
// Do some work for the use case | ||
// Simulate work: this could be simulating a network request or an expensive disk operation | ||
workDurationMillis = 100 + random.nextInt(5) * 100; | ||
Thread.sleep(workDurationMillis); | ||
span.addEvent("Event B"); | ||
} catch (InterruptedException e) { | ||
logger.debug("Error while sleeping: {}", e.getMessage()); | ||
throw new RuntimeException(e); | ||
} finally { | ||
span.end(); | ||
} | ||
return String.format(WORK_RESPONSE_FMT, workDurationMillis); | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
...es/otlp-spring/src/main/java/com/google/cloud/opentelemetry/examples/otlpspring/Main.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright 2024 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.google.cloud.opentelemetry.examples.otlpspring; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
@SpringBootApplication | ||
public class Main { | ||
private static final Logger logger = LoggerFactory.getLogger(Main.class); | ||
|
||
public static void main(String[] args) { | ||
logger.info("Starting OTLP with Spring Boot and Google Auth"); | ||
SpringApplication.run(Main.class, args); | ||
} | ||
} |
Oops, something went wrong.