Configure Application Insights to receive monitoring information from your applications
You now know how to set up monitoring for your overall Azure Container Apps environment. However, you would also like to get monitoring info on how your applications run in the cluster. To track Application specific monitoring data, you can use Application Insights.
In this next module you will create an Application Insights resource and enable application monitoring for each of your microservices. For enabling this, you will not have to change anything in your microservices themselves, you can make use of the Java auto-instrumentation feature of Azure Monitor, which uses an agent-based approach to collect the monitoring data.
Currently, to add the Application Insights monitoring agent to your apps, you need to include the Application Insights jar file to your microservices. The only way to do that is to take hold of the containerization process. You will use a Dockerfile to redeploy the container apps for this lab to add application insights. The following steps are needed:
- Create a dockerfile for containerizing your microservices.
- Add the Application Insights jar file to your docker file.
- Add an environment variable to your microservices with the connection string info for your Application Insights instance.
- To get a proper application map in Application Insights, you will also have to define a different role for each of the microservices in the cluster, so Application Insights knows what microservice the monitoring data comes from.
You can follow the below guidance to do so.
- Azure Monitor OpenTelemetry-based auto-instrumentation for Java applications
- Spring Boot via Docker entry point
- Workspace-based Application Insights resources
Step by step guidance
-
As a first step, you will need to create an Application Insights resource. Execute the below statement in your bash shell.
WORKSPACEID=$(az monitor log-analytics workspace show -n $WORKSPACE -g $RESOURCE_GROUP --query id -o tsv) AINAME=ai-$APPNAME-$UNIQUEID az extension add -n application-insights az monitor app-insights component create \ --app $AINAME \ --location $LOCATION \ --kind web \ -g $RESOURCE_GROUP \ --workspace $WORKSPACEID
-
Make note of the Application Insights connection string, you will need this later in this module.
AI_CONNECTIONSTRING=$(az monitor app-insights component show --app $AINAME -g $RESOURCE_GROUP --query connectionString --output tsv) echo $AI_CONNECTIONSTRING
-
Since you will now be containerizing the different microservices, you will also need to create a new Azure Container Registry (ACR) instance for holding your container images.
MYACR=acr$APPNAME$UNIQUEID az acr create \ -n $MYACR \ -g $RESOURCE_GROUP \ --sku Basic \ --admin-enabled true
-
You will also need to create an identity which can be used by your container apps to connect to the Container Registry.
ACA_IDENTITY=uid-petclinic-$UNIQUEID az identity create --resource-group $RESOURCE_GROUP --name $ACA_IDENTITY --output json USER_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $ACA_IDENTITY --query id --output tsv) SP_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $ACA_IDENTITY --query principalId --output tsv) echo $USER_ID echo $SP_ID
-
Assign the user identity to the container apps environment
az containerapp env identity assign -g $RESOURCE_GROUP -n $ACA_ENVIRONMENT --user-assigned $USER_ID
-
Assign access for the container app identity to pull images from your container registry.
ACR_ID=$(az acr show -n $MYACR -g $RESOURCE_GROUP --query id -o tsv) az role assignment create --assignee $SP_ID --scope $ACR_ID --role acrpull
-
As a next step create the docker file which you will use to deploy the different microservices to include the application insights jar file. As a first step, create a staging-acr folder and navigate to it.
mkdir staging-acr cd ./staging-acr
-
In this new folder download the latest application insights agent jar file. Also rename the jar file to ai.jar so you have an easier name in the next steps.
AI_VERSION=3.5.4 wget https://github.com/microsoft/ApplicationInsights-Java/releases/download/$AI_VERSION/applicationinsights-agent-$AI_VERSION.jar mv applicationinsights-agent-$AI_VERSION.jar ai.jar
-
Create the below
Dockerfile
in thestaging-acr
directory. ThisDockerfile
copies the application jar file andai.jar
file into the container. It also adds theai.jar
file as a javaagent to your app, so it can start logging. You should replace the value3.2.5
with the VERSION you get from source project. The resultingDockerfile
should look like this.# Build stage FROM mcr.microsoft.com/openjdk/jdk:17-mariner COPY spring-petclinic-my-service-3.2.5.jar app.jar COPY ai.jar ai.jar EXPOSE 8080 # Run the jar file ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-javaagent:/ai.jar","-jar","/app.jar"]
-
You will now use Azure Container Apps’ ability to deploy from source code with the
--source
switch. If you execute this statement in thestaging-acr
directory, it will pick up the files in the directory as well as the Dockerfile and it will containerize the application for you. Do this first for theapi-gateway
service. Notice how you are also setting theAPPLICATIONINSIGHTS_CONNECTION_STRING
andAPPLICATIONINSIGHTS_CONFIGURATION_CONTENT
environment variables.export APP_NAME="api-gateway" cp ../spring-petclinic-$APP_NAME/target/spring-petclinic-$APP_NAME-$VERSION.jar spring-petclinic-$APP_NAME-$VERSION.jar sed -i "s|my-service|$APP_NAME|g" Dockerfile az containerapp delete --name $APP_NAME --resource-group $RESOURCE_GROUP --yes az containerapp create \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --source . \ --env-vars APPLICATIONINSIGHTS_CONNECTION_STRING=$AI_CONNECTIONSTRING APPLICATIONINSIGHTS_CONFIGURATION_CONTENT='{"role": {"name": "api-gateway"}}' InstrumentationKey=$AI_CONNECTIONSTRING \ --registry-server $MYACR.azurecr.io \ --registry-identity $USER_ID \ --environment $ACA_ENVIRONMENT \ --user-assigned $USER_ID \ --ingress external \ --target-port 8080 \ --min-replicas 1 \ --bind $JAVA_CONFIG_COMP_NAME $JAVA_EUREKA_COMP_NAME \ --runtime java sed -i "s|$APP_NAME|my-service|g" Dockerfile rm spring-petclinic-$APP_NAME-$VERSION.jar
-
Once the
api-gateway
deployment has succeeded, execute the same statements for the other microservices.export APP_NAME="customers-service" cp ../spring-petclinic-$APP_NAME/target/spring-petclinic-$APP_NAME-$VERSION.jar spring-petclinic-$APP_NAME-$VERSION.jar sed -i "s|my-service|$APP_NAME|g" Dockerfile az containerapp delete --name $APP_NAME --resource-group $RESOURCE_GROUP --yes az containerapp create \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --source . \ --env-vars APPLICATIONINSIGHTS_CONNECTION_STRING=$AI_CONNECTIONSTRING APPLICATIONINSIGHTS_CONFIGURATION_CONTENT='{"role": {"name": "customers-service"}}' InstrumentationKey=$AI_CONNECTIONSTRING \ --registry-server $MYACR.azurecr.io \ --registry-identity $USER_ID \ --environment $ACA_ENVIRONMENT \ --user-assigned $USER_ID \ --ingress internal \ --target-port 8080 \ --min-replicas 1 \ --bind $JAVA_CONFIG_COMP_NAME $JAVA_EUREKA_COMP_NAME \ --runtime java sed -i "s|$APP_NAME|my-service|g" Dockerfile rm spring-petclinic-$APP_NAME-$VERSION.jar export APP_NAME="vets-service" cp ../spring-petclinic-$APP_NAME/target/spring-petclinic-$APP_NAME-$VERSION.jar spring-petclinic-$APP_NAME-$VERSION.jar sed -i "s|my-service|$APP_NAME|g" Dockerfile az containerapp delete --name $APP_NAME --resource-group $RESOURCE_GROUP --yes az containerapp create \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --source . \ --env-vars APPLICATIONINSIGHTS_CONNECTION_STRING=$AI_CONNECTIONSTRING APPLICATIONINSIGHTS_CONFIGURATION_CONTENT='{"role": {"name": "vets-service"}}' InstrumentationKey=$AI_CONNECTIONSTRING \ --registry-server $MYACR.azurecr.io \ --registry-identity $USER_ID \ --environment $ACA_ENVIRONMENT \ --user-assigned $USER_ID \ --ingress internal \ --target-port 8080 \ --min-replicas 1 \ --bind $JAVA_CONFIG_COMP_NAME $JAVA_EUREKA_COMP_NAME \ --runtime java sed -i "s|$APP_NAME|my-service|g" Dockerfile rm spring-petclinic-$APP_NAME-$VERSION.jar export APP_NAME="visits-service" cp ../spring-petclinic-$APP_NAME/target/spring-petclinic-$APP_NAME-$VERSION.jar spring-petclinic-$APP_NAME-$VERSION.jar sed -i "s|my-service|$APP_NAME|g" Dockerfile az containerapp delete --name $APP_NAME --resource-group $RESOURCE_GROUP --yes az containerapp create \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --source . \ --env-vars APPLICATIONINSIGHTS_CONNECTION_STRING=$AI_CONNECTIONSTRING APPLICATIONINSIGHTS_CONFIGURATION_CONTENT='{"role": {"name": "visits-service"}}' InstrumentationKey=$AI_CONNECTIONSTRING \ --registry-server $MYACR.azurecr.io \ --registry-identity $USER_ID \ --environment $ACA_ENVIRONMENT \ --user-assigned $USER_ID \ --ingress internal \ --target-port 8080 \ --min-replicas 1 \ --bind $JAVA_CONFIG_COMP_NAME $JAVA_EUREKA_COMP_NAME \ --runtime java sed -i "s|$APP_NAME|my-service|g" Dockerfile rm spring-petclinic-$APP_NAME-$VERSION.jar export APP_NAME="admin-server" cp ../spring-petclinic-$APP_NAME/target/spring-petclinic-$APP_NAME-$VERSION.jar spring-petclinic-$APP_NAME-$VERSION.jar sed -i "s|my-service|$APP_NAME|g" Dockerfile az containerapp delete --name $APP_NAME --resource-group $RESOURCE_GROUP --yes az containerapp create \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --source . \ --env-vars APPLICATIONINSIGHTS_CONNECTION_STRING=$AI_CONNECTIONSTRING APPLICATIONINSIGHTS_CONFIGURATION_CONTENT='{"role": {"name": "admin-server"}}' InstrumentationKey=$AI_CONNECTIONSTRING \ --registry-server $MYACR.azurecr.io \ --registry-identity $USER_ID \ --environment $ACA_ENVIRONMENT \ --user-assigned $USER_ID \ --ingress external \ --target-port 8080 \ --min-replicas 1 \ --bind $JAVA_CONFIG_COMP_NAME $JAVA_EUREKA_COMP_NAME \ --runtime java sed -i "s|$APP_NAME|my-service|g" Dockerfile rm spring-petclinic-$APP_NAME-$VERSION.jar
Notice that for each of the microservices, we indicate a different role-name. This role-name will be used in the Application Insights Application Map to properly show the communication between your microservices.
To make sure everything is back up and running as expected, you may want to double check if all your services are back up and running. Check console log if you are seeing any service in failed state.