Skip to content

Commit

Permalink
Add a Spring native image example (#137)
Browse files Browse the repository at this point in the history
Co-authored-by: jason plumb <75337021+breedx-splk@users.noreply.github.com>
Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
  • Loading branch information
3 people committed Jun 13, 2023
1 parent 4d038d7 commit 73dc750
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ of them assume you have docker running on your local machine.
- This module demonstrates using the OpenTelemetry Java Agent with a simple
spring boot application. Traces, metrics, and logs are exported to a
collector via OTLP.
- [Spring native image telemetry with OpenTelemetry Spring Starter](spring-native)
- This module demonstrates using the OpenTelemetry Spring Boot starter with a
Graal VM native image. Traces and metrics are exported to a collector via OTLP.
- [Configuring Log Appenders](log-appender)
- This module demonstrates how to configure the Log4j and Logback appenders to
bridge logs into the OpenTelemetry Log SDK.
Expand Down
3 changes: 2 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ include ":opentelemetry-examples-autoconfigure",
":opentelemetry-examples-prometheus",
":opentelemetry-examples-sdk-usage",
":opentelemetry-examples-telemetry-testing",
":opentelemetry-examples-zipkin"
":opentelemetry-examples-zipkin",
":opentelemetry-examples-spring-native"

rootProject.children.each {
it.projectDir = "$rootDir/" + it.name
Expand Down
103 changes: 103 additions & 0 deletions spring-native/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# OpenTelemetry Java Agent Example

This example demonstrates usage of the [OpenTelemetry Spring starter](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/spring/starters/spring-boot-starter) with a Spring Boot application and a GraalVM native image.

It consists of a Spring Boot application with:

- A simple web API available at `GET http://localhost:8080/ping`. When called,
the OpenTelemetry Spring starter records spans and metrics.
- A docker compose setup configured to run the application and export to
the [collector](https://opentelemetry.io/docs/collector/) via OTLP.
- The collector is configured with
the [OTLP receiver](https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver)
and export it to standard out with
the [logging exporter](https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter/loggingexporter)

## Prerequisites

* GraalVM for Java 17
* Docker compose

# How to run

Build the GraalVM native image
```shell
cd spring-native
../gradlew bootBuildImage --imageName=otel-native-graalvm
```

Run the application and the collector with docker compose
```shell
docker-compose up
```

In a separate shell, exercise the application by calling its endpoint
```shell
curl http://localhost:8080/ping
```

Watch for spans, metrics, and logs in the collector log output.

Example of the beginning of the collector log after the ping:
```
graal-native-collector-1 | Span #0
graal-native-collector-1 | Trace ID : 668c936f4f0580bac9db40162e8159fa
graal-native-collector-1 | Parent ID :
graal-native-collector-1 | ID : 858b9b11341b1bb9
graal-native-collector-1 | Name : GET /ping
graal-native-collector-1 | Kind : Server
graal-native-collector-1 | Start time : 2023-06-09 13:49:43.270616 +0000 UTC
graal-native-collector-1 | End time : 2023-06-09 13:49:43.271635862 +0000 UTC
graal-native-collector-1 | Status code : Unset
graal-native-collector-1 | Status message :
graal-native-collector-1 | Attributes:
graal-native-collector-1 | -> http.target: Str(/ping)
graal-native-collector-1 | -> net.sock.peer.addr: Str(172.20.0.1)
graal-native-collector-1 | -> user_agent.original: Str(curl/8.0.1)
graal-native-collector-1 | -> net.host.name: Str(localhost)
graal-native-collector-1 | -> net.sock.host.addr: Str(172.20.0.3)
graal-native-collector-1 | -> http.route: Str(/ping)
graal-native-collector-1 | -> net.sock.peer.port: Int(42646)
graal-native-collector-1 | -> http.method: Str(GET)
graal-native-collector-1 | -> http.scheme: Str(http)
graal-native-collector-1 | -> http.status_code: Int(200)
graal-native-collector-1 | -> net.protocol.version: Str(1.1)
graal-native-collector-1 | -> net.host.port: Int(8080)
graal-native-collector-1 | -> net.protocol.name: Str(http)
graal-native-collector-1 | -> http.response_content_length: Int(4)
graal-native-collector-1 | {"kind": "exporter", "data_type": "traces", "name": "logging"}
graal-native-collector-1 | 2023-06-09T13:50:07.529Z info MetricsExporter {"kind": "exporter", "data_type": "metrics", "name": "logging", "resource metrics": 1, "metrics": 3, "data points": 3}
graal-native-collector-1 | 2023-06-09T13:50:07.529Z info ResourceMetrics #0
graal-native-collector-1 | Resource SchemaURL:
graal-native-collector-1 | Resource attributes:
graal-native-collector-1 | -> service.name: Str(unknown_service:java)
graal-native-collector-1 | -> telemetry.sdk.language: Str(java)
graal-native-collector-1 | -> telemetry.sdk.name: Str(opentelemetry)
graal-native-collector-1 | -> telemetry.sdk.version: Str(1.26.0)
graal-native-collector-1 | ScopeMetrics #0
graal-native-collector-1 | ScopeMetrics SchemaURL:
graal-native-collector-1 | InstrumentationScope io.opentelemetry.spring-webmvc-6.0
graal-native-collector-1 | Metric #0
graal-native-collector-1 | Descriptor:
graal-native-collector-1 | -> Name: http.server.duration
graal-native-collector-1 | -> Description: The duration of the inbound HTTP request
graal-native-collector-1 | -> Unit: ms
graal-native-collector-1 | -> DataType: Histogram
graal-native-collector-1 | -> AggregationTemporality: Cumulative
graal-native-collector-1 | HistogramDataPoints #0
graal-native-collector-1 | Data point attributes:
graal-native-collector-1 | -> http.method: Str(GET)
graal-native-collector-1 | -> http.route: Str(/ping)
graal-native-collector-1 | -> http.scheme: Str(http)
graal-native-collector-1 | -> http.status_code: Int(200)
graal-native-collector-1 | -> net.host.name: Str(localhost)
graal-native-collector-1 | -> net.host.port: Int(8080)
graal-native-collector-1 | -> net.protocol.name: Str(http)
graal-native-collector-1 | -> net.protocol.version: Str(1.1)
graal-native-collector-1 | StartTimestamp: 2023-06-09 13:49:07.528013 +0000 UTC
graal-native-collector-1 | Timestamp: 2023-06-09 13:50:07.528308 +0000 UTC
graal-native-collector-1 | Count: 1
graal-native-collector-1 | Sum: 0.991699
graal-native-collector-1 | Min: 0.991699
graal-native-collector-1 | Max: 0.991699
```
25 changes: 25 additions & 0 deletions spring-native/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'org.graalvm.buildtools.native' version '0.9.20'
}

compileJava {
sourceCompatibility = "17"
targetCompatibility = "17"
}
description = 'OpenTelemetry Example for Spring native images'
ext.moduleName = "io.opentelemetry.examples.native"

dependencyManagement {
imports {
mavenBom 'io.opentelemetry:opentelemetry-bom:1.26.0'
mavenBom 'io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.26.0-alpha'
}
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter")
}
18 changes: 18 additions & 0 deletions spring-native/collector-spring-native-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
receivers:
otlp:
protocols:
grpc:
exporters:
logging:
verbosity: detailed
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [logging]
traces:
receivers: [otlp]
exporters: [logging]
logs:
receivers: [otlp]
exporters: [logging]
22 changes: 22 additions & 0 deletions spring-native/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '3'
services:
app:
image: otel-native-graalvm
environment:
OTEL_SERVICE_NAME: "graal-native-example-app"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://collector:4317"
# Logs are disabled by default
OTEL_LOGS_EXPORTER: "otlp"
ports:
- "8080:8080"
depends_on:
- collector
collector:
image: otel/opentelemetry-collector-contrib:0.77.0
volumes:
- ./collector-spring-native-config.yaml:/collector-spring-native-config.yaml
command: ["--config=/collector-spring-native-config.yaml"]
expose:
- "4317"
ports:
- "4317:4317"
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.opentelemetry.example.graal;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.opentelemetry.example.graal;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {

@GetMapping("/ping")
public String ping() {
return "pong";
}
}

0 comments on commit 73dc750

Please sign in to comment.