This project was built in order to easily spin up a handful of services that encapsulate a basic OpenTelemetry pipeline. There are two app services that are spun up, and they are already instrumented.
otel-java-basicis instrumented with the OpenTelemetry Java Instrumentation JARappd-java-basicis instrumented with AppDynamics Java Instrumentation JAR.
Both app services send OpenTelemetry Spans to the OpenTelemetry Dev Collector.
The OpenTelemetry Collector sends Spans to
- Jaeger All-In-One backend
- AppDynamics backend
The full stack of services consists of:
- Jaeger
- OpenTelemetry Collector (no agent)
- Spring PetClinic with OpenTelemetry Java Instrumentation JAR
- Spring PetClinic with AppDynamics Java Instrumentation JAR
More information about the Compose Services can be found below.
Note: This project was built/tested only on Docker for Mac, and uses Docker-Compose
It's not necessary to build anything in this project. All images can be pulled from Docker Hub when you run with Docker Compose.
In order to run this project, you'll need:
-
Docker for Mac
-
Docker Compose
Note: The Docker versions must support Docker Compose File version 3.2+
- Clone this repository to your local machine.
-
Copy the
.env_publicfile to a file named.envin the root project directory, and configure it for your AppDynamics backend. Detailed notes on specific requirements is down below.IMPORTANT: The
.envfile MUST be configured for this project to work with the AppDynamics backend!
- Edit the
OTEL_RESOURCE_ATTRIBUTESenvironment variables in thedocker-comopose.ymlfile for both app services below by appending your initials using the same value as in Step 2
otel-java-basicappd-java-basic
Before
OTEL_RESOURCE_ATTRIBUTES: "service.name=otel-java-basic,service.namespace=otel-java-basic-<YOUR_INITIALS_HERE>"After
OTEL_RESOURCE_ATTRIBUTES: "service.name=otel-java-basic,service.namespace=otel-java-basic-kjt"IMPORTANT: The
service.namespacevalue should now match theAPPDYNAMICS_AGENT_APPLICATION_NAMEin the.envfile
- Configure the
otel-collector-config.yamlfile in the root project directory by configuring theprocessors.resource.attributessection toward your AppDynamics backend. More detailed notes on specific requirements is down below.
- Use Docker Compose to start
$ docker-compose up -d- Open the OTel-Instrumented Spring PetClinic app on
http://$DOCKER_HOSTNAME:8080($DOCKER_HOSTNAMEis generallylocalhost), and click around for a bit.
- Open the AppD-Instrumented Spring PetClinic app on
http://$DOCKER_HOSTNAME:8081($DOCKER_HOSTNAMEis generallylocalhost), and click around for a bit.
- Then, open Jaeger on
http://$DOCKER_HOSTNAME:16686, chooseotel-java-basicorappd-java-basicfrom the services drop-down menu, click the "Find Traces" button, and then choose a trace!
- Tear down the Compose Services
$ docker-compose downJaeger tracing backend.
Jaeger "all-in-one" Image, pulled from jaegertracing/all-in-one:latest.
By default, accessible on http://$DOCKER_HOSTNAME:16686.
OpenTelemetry Collector.
OpenTelemetry development Image, pulled from otel/opentelemetry-collector-dev:latest.
There is no UI, merely a pipeline that is configured via appd-otel-collector-config.yaml.
Spring PetClinic app.
Spring PetClinic Image, pulled from kjtully/otel-java-basic:latest Image built from the otel-trainig fork of the Spring PetClinic Repo.
By default, accessible on http://$DOCKER_HOSTNAME:8080.
Spring PetClinic app.
Spring PetClinic Image, pulled from kjtully/appd-java-basic:latest Image built from the otel-trainig fork of the Spring PetClinic Repo.
By default, accessible on http://$DOCKER_HOSTNAME:8081.
This file is located in the project root and manages building and running the Docker containers. It uses the .env file to populate environment variables for the project to work properly.
This file contains all of the environment variables that need to be populated in order for the project to run, and for the performance tools to operate. Items that must be tailored to your environment are:
This configuration is used by the AppD Hybrid Java Agent to connect to the AppD Controller of your choice. Replace all values in <angle_brackets> with the actual values per your AppDynamics backend.
IMPORTANT: The
<YOUR_INITIALS_HERE>in the env varAPPDYNAMICS_AGENT_APPLICATION_NAMEis free-form, but ends up as part of the Application name in AppDynamics, so it should be meaningful. Also, make note of the value that you use for<YOUR_INITIALS_HERE>- you'll use it again in the next step during the configuration of thedocker-compose.ymlfile.
# AppD Agent
APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY=<access_key>
APPDYNAMICS_AGENT_ACCOUNT_NAME=<appd_account>
APPDYNAMICS_CONTROLLER_HOST_NAME=<appd_controller_url>
APPDYNAMICS_CONTROLLER_PORT=<app_controller_port>
APPDYNAMICS_CONTROLLER_SSL_ENABLED=<false_or_true>
APPDYNAMICS_AGENT_APPLICATION_NAME=otel-java-basic-<YOUR_INITIALS_HERE>
# Tier and Node names are set in docker-compose.yml individuallyAPI Key for the AppDynamics OpenTelemetry Ingestion Service. Replace the value <my_x_api_key> with the OpenTelemetry API Key for the AppDynamics backend.
# AppD OTel Ingest API Key
X_API_KEY=<my_x_api_key>The value: sections of the below should be configured by replacing all values in <angle_brackets> with the actual values per your AppDynamics backend - you'd reuse values that you've already configured in the .env file.
.env file value |
otel-collector.yaml file value |
|---|---|
APPDYNAMICS_AGENT_ACCOUNT_NAME |
appdynamics.controller.account |
APPDYNAMICS_CONTROLLER_HOST_NAME |
appdynamics.controller.host |
APPDYNAMICS_CONTROLLER_PORT |
appdynamics.controller.port |
processors:
resource:
attributes:
- key: appdynamics.controller.account
action: upsert
value: "<appd_account>"
# example: "customer1"
- key: appdynamics.controller.host
action: upsert
value: "<appd_controller_url>"
# example: "my-appd-controller.saas.appdynamics.com"
- key: appdynamics.controller.port
action: upsert
value: <appd_controller_port>
# example: 443
batch:The endpoint section of the below should be configured by replacing <your_appd_otel_endpoint> with the proper AppDynamics API endpoint defined in the docs - example for US endpoint below.
Note, the x-api-key header is already defined in the .env file, so there is no need to define it here.
exporters:
...
otlphttp:
endpoint: <your_appd_otel_endpoint>
# example: https://pdx-sls-agent-api.saas.appdynamics.com
headers: {"x-api-key": "${X_API_KEY}"}The pipelines section within the services section does not need to be changed, although it should be understood that both the above processors and exporters have been defined in order to complete the pipeline.
pipelines:
traces:
receivers: [otlp]
processors: [resource, batch]
exporters: [logging, jaeger, otlphttp]