Skip to main content Link Menu Expand (external link) Document Search Copy Copied

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.

Step by step guidance

  1. 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
    
  2. 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
    
  3. 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
    
  4. 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
    
  5. Assign the user identity to the container apps environment

    az containerapp env identity assign -g $RESOURCE_GROUP -n $ACA_ENVIRONMENT --user-assigned $USER_ID
    
  6. 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
    
  7. 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
    
  8. 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
    
  9. Create the below Dockerfile in the staging-acr directory. This Dockerfile copies the application jar file and ai.jar file into the container. It also adds the ai.jar file as a javaagent to your app, so it can start logging. You should replace the value 3.2.5 with the VERSION you get from source project. The resulting Dockerfile 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"]
    
  10. You will now use Azure Container Apps’ ability to deploy from source code with the --source switch. If you execute this statement in the staging-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 the api-gateway service. Notice how you are also setting the APPLICATIONINSIGHTS_CONNECTION_STRING and APPLICATIONINSIGHTS_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
    
  11. 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.