No episodio anterior nós vimos como configurar o agente OTEL no NGINX.
O que acontece se misturarmos agentes java do AppDynamics com agentes java OTEL? E se adicionar na mistura o agente do NGINX do no post anterior? Confusão... medo... pânico!
Calma, nesse post vamos ver que essa mistura fica boa e visualizada no AppDynamics fica bem bacana. Pense no seguinte cenário, na sua empresa existe uma aplicação crítica que atualmente é monitorada por agentes do AppDynamics. A partir de agora essa aplicação vai consumir serviços de uma API que acabou de entrar em produção já instrumentada utilizando OpenTelemetry.
Basicamente teremos esse cenário.

E agora? Como vemos o impacto que os novos serviços e APIs têm em nossa aplicação? Simples, da mesma forma que o agente do NGINX envia as informações para o AppDynamics também podemos fazer para os agentes java.

Bora ver como fazer isso?
Para começar
Antes de começar você vai precisar de:
- docker
- docker-compose
- Controller AppDynamics SaaS
- Um editor de textos
Configurando
O primeiro passo é clonar o repo:
git clone https://github.com/lof000/appd-sample-apps-otel.git
Se você não fez o build do NGNIX com o agente no post anterior, aproveita para fazer isso agora.
Nesse post não vamos fazer nenhum build. O objetivo é entendermos como tudo funciona e termos um exemplo executável para brincar.
No post anterior veja em “Configurando a comunicação do coletor com o AppDynamics” para entender como configurar o OpenTelmetry Collector. Depois crie um arquivo .env na pasta nginxotel-backends com o seguinte conteúdo, ajustando com os dados da sua controller.
APPDYNAMICS_CONTROLLER_HOST_NAME=<controller host>
APPDYNAMICS_CONTROLLER_PORT=443
APPDYNAMICS_CONTROLLER_SSL_ENABLED=true
APPDYNAMICS_AGENT_ACCOUNT_NAME=<account>
APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY=<access key>
APPDYNAMICS_JAVA_AGENT_REUSE_NODE_NAME=true
APPDYNAMICS_JAVA_AGENT_REUSE_NODE_NAME_PREFIX=true
APPDYNAMICS_AGENT_APPLICATION_NAME=<application name>
OTEL_EXPORTER_ENDPOINT=http://otel-collector:4317
Agora vamos analisar partes do arquivo docker-compose.yaml para entender o que vamos rodar.
Nessa sessão estamos montando 2 volumes, um com o agente do AppDynamics e outro com o agente java OTEL.
# AGENTE JAVA - APPDYNAMICS
# APM - AGENT VOLUME (SIDECAR)
appd-agent-saas:
image: docker.io/appdynamics/java-agent:latest
container_name: appd-agent
volumes:
- agent-volume:/opt/appdynamics
# AGENTE JAVA - OTEL
# APM - AGENT VOLUME (SIDECAR)
otel-agent-saas:
image: leandrovo/otel-agent-java:1.20.0
container_name: otel-java-agent
volumes:
- otel-agent-volume:/opt/agent
Aqui montamos o NGINX já com o agente OTEL de forma similar ao que fizemos no passado.
nginx:
image: nginx_otel:latest
container_name: nginx
volumes:
- type: bind
source: ./opentelemetry_module-frontend.conf
target: /opt/opentelemetry_module.conf
- type: bind
source: ./default-front.conf
target: /etc/nginx/conf.d/default.conf
- type: bind
source: ./nginx.conf
target: /etc/nginx/nginx.conf
ports:
- "80:80"
depends_on:
- bank
Nessa parte estamos montando e configurando o agente do AppDynamics na aplicação bank. É interessante notar estamos informando os parâmetros para configuração da comunicação com a controller do AppDynamics e com o OTEL Collector. O agente do AppDynamics envia informações para os dois ao mesmo tempo.
# =====================================================================
# Digital Bank Service Configuration
# =====================================================================
bank:
image: leandrovo/digitalbank-new:1.0
container_name: bank
hostname: bank
environment:
.....
#APM AGENT VARIABLES
JAVA_OPTS: '-javaagent:/opt/appdynamics/javaagent.jar -Dappdynamics.opentelemetry.enabled=true -Dotel.traces.exporter=otlp'
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_ENDPOINT}
OTEL_RESOURCE_ATTRIBUTES: service.name=bank,service.namespace=${APPDYNAMICS_AGENT_APPLICATION_NAME}
APPDYNAMICS_CONTROLLER_HOST_NAME: ${APPDYNAMICS_CONTROLLER_HOST_NAME}
APPDYNAMICS_CONTROLLER_PORT: ${APPDYNAMICS_CONTROLLER_PORT}
APPDYNAMICS_CONTROLLER_SSL_ENABLED: ${APPDYNAMICS_CONTROLLER_SSL_ENABLED}
APPDYNAMICS_AGENT_ACCOUNT_NAME: ${APPDYNAMICS_AGENT_ACCOUNT_NAME}
APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY: ${APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY}
APPDYNAMICS_JAVA_AGENT_REUSE_NODE_NAME: ${APPDYNAMICS_JAVA_AGENT_REUSE_NODE_NAME}
APPDYNAMICS_JAVA_AGENT_REUSE_NODE_NAME_PREFIX: ${APPDYNAMICS_JAVA_AGENT_REUSE_NODE_NAME_PREFIX}
APPDYNAMICS_AGENT_APPLICATION_NAME: ${APPDYNAMICS_AGENT_APPLICATION_NAME}
APPDYNAMICS_AGENT_TIER_NAME: 'bank'
APPDYNAMICS_AGENT_NODE_NAME: 'bank-node'
....
#APM - ADD AGENT VOLUME
volumes:
- agent-volume:/opt/appdynamics
restart: unless-stopped
Por último estamos montando e configurando o agente OTEL no backend que implementa uma das APIs. Perceba que aqui não existem os parâmetros de configuração do AppDynamics, somente os de configuração OTEL.
visa:
image: leandrovo/digitalbank-backend-java:1.0
container_name: backends-visa-java
ports:
- "10082:8081"
environment:
#APM AGENT VARIABLES
JAVA_TOOL_OPTIONS: '-javaagent:/opt/agent/opentelemetry-javaagent.jar'
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_ENDPOINT}
OTEL_RESOURCE_ATTRIBUTES: service.name=visa,service.namespace=${APPDYNAMICS_AGENT_APPLICATION_NAME}
#APM - ADD AGENT VOLUME
volumes:
- otel-agent-volume:/opt/agent
restart: unless-stopped
Testando
Vamos executar e ver o que acontece.
docker-compose up -d
Minutos depois...

Coisas interessantes para observarmos nesse desenho. Independente do agente utilizado estamos vendo as informações no mesmo contexto, fica simples de entender quem impacta a aplicação. As camadas nginx_otel, visa_otel e atm-search_otel estão instrumentadas com agentes OTEL e as camadas bank e credit estão instrumentadas com agentes do AppDynamics.
Viram como o resultado da mistura fica bom? Utilizando o AppDynamics como um backend para os traces e métricas enviados pelos agentes (OTEL ou não) temos uma visão unificada da nossa aplicação e fica fácil identificar qualquer impacto na experiência dos nossos clientes.
No próximo episódio veremos como fica isso tudo no AppDynamicsCloud!