|
| 1 | +--- |
| 2 | +title: Integrate Application Performance Monitoring into Container Images |
| 3 | +description: Describes how to integrate application performance monitoring into container images. |
| 4 | +author: KarlErickson |
| 5 | +ms.author: dixue |
| 6 | +ms.service: azure-spring-apps |
| 7 | +ms.topic: upgrade-and-migration-article |
| 8 | +ms.date: 01/29/2025 |
| 9 | +ms.custom: devx-track-java, devx-track-extended-java |
| 10 | +--- |
| 11 | + |
| 12 | +# Integrate application performance monitoring into container images |
| 13 | + |
| 14 | +[!INCLUDE [deprecation-note](../includes/deprecation-note.md)] |
| 15 | + |
| 16 | +**This article applies to:** ✅ Basic/Standard ✅ Enterprise |
| 17 | + |
| 18 | +This article explains how to integrate the Application Insights Java agent into your container image. In a similar way, you can also integrate other application performance monitoring (APM) agents into your container image, including AppDynamics, New Relic, and Dynatrace. |
| 19 | + |
| 20 | +Azure Spring Apps integrates smoothly with APM agents. When migrating applications to Azure Container Apps or Azure Kubernetes Service (AKS), you need to integrate with APM while building the image. The process is similar to the approach used by Azure Spring Apps. You can also add an APM agent in a separate init-container and inject it into a container app during its initialization. |
| 21 | + |
| 22 | +## Prerequisites |
| 23 | + |
| 24 | +- [Docker](https://docs.docker.com/get-docker/) |
| 25 | +- [Pack CLI](https://buildpacks.io/docs/for-platform-operators/how-to/integrate-ci/pack/) |
| 26 | + |
| 27 | +## Choose the Application Insights Java agent |
| 28 | + |
| 29 | +Azure Spring Apps currently uses Application Insights Java agent 3.5.2. You can choose another version depending on your needs. You can find all versions on the [Application Insights Java releases page](https://github.com/microsoft/ApplicationInsights-Java/releases). |
| 30 | + |
| 31 | +You can find the Application Insights connection string in the Azure portal on the **Overview** pane of your Application Insights instance. This string is required for the instructions in this article. |
| 32 | + |
| 33 | +There are some configuration options for Application Insights Java agent, such as sampling percentage and cloud role name. For more information, see [Configuration options of Application Insights for Java](/azure/azure-monitor/app/java-standalone-config). |
| 34 | + |
| 35 | +If you're using a Dockerfile to build a container image, see the [Use Dockerfile](#use-dockerfile) section. If you're using Paketo Buildpacks to build a container image, see the [Use Paketo Buildpacks](#use-paketo-buildpacks) section. |
| 36 | + |
| 37 | +## Use Dockerfile |
| 38 | + |
| 39 | +Use the following steps to modify your Dockerfile: |
| 40 | + |
| 41 | +1. Download the Application Insights Java agent and create a configuration file for it, called **applicationinsights.json**. |
| 42 | +1. Add the `-javaagent` option to the entry point of the container image. |
| 43 | + |
| 44 | +To learn more about building JAR file or WAR file with a Dockerfile, see [Build a container image from a JAR or WAR](./migrate-to-azure-container-apps-build-artifacts.md). |
| 45 | + |
| 46 | +### Build a JAR file |
| 47 | + |
| 48 | +The following example Dockerfile builds a JAR file with the previous changes: |
| 49 | + |
| 50 | +```dockerfile |
| 51 | +FROM mcr.microsoft.com/openjdk/jdk:17-mariner |
| 52 | + |
| 53 | +ARG APP_INSIGHTS_VERSION |
| 54 | +ARG APP_INSIGHTS_CONNECTION_STRING |
| 55 | +ARG JAR_FILENAME |
| 56 | + |
| 57 | +# Set up Application Insights agent |
| 58 | +ADD https://github.com/microsoft/ApplicationInsights-Java/releases/download/${APP_INSIGHTS_VERSION}/applicationinsights-agent-${APP_INSIGHTS_VERSION}.jar \ |
| 59 | + /java-agent/applicationinsights-agent.jar |
| 60 | +RUN echo "{\"connectionString\": \"${APP_INSIGHTS_CONNECTION_STRING}\"}" > applicationinsights.json \ |
| 61 | + && mv applicationinsights.json /java-agent/applicationinsights.json |
| 62 | + |
| 63 | +COPY $JAR_FILENAME /opt/app/app.jar |
| 64 | + |
| 65 | +# Add -javaagent option |
| 66 | +ENTRYPOINT ["java", "-javaagent:/java-agent/applicationinsights-agent.jar", "-jar", "/opt/app/app.jar"] |
| 67 | +``` |
| 68 | + |
| 69 | +When you build a container image with this Dockerfile, you need to add build arguments using `--build-arg`, as shown in the following example: |
| 70 | + |
| 71 | +```bash |
| 72 | +docker build -t <image-name>:<image-tag> \ |
| 73 | + -f JAR.dockerfile \ |
| 74 | + --build-arg APP_INSIGHTS_VERSION=3.5.2 \ |
| 75 | + --build-arg APP_INSIGHTS_CONNECTION_STRING="<connection-string>" \ |
| 76 | + --build-arg JAR_FILENAME=<path-to-jar> \ |
| 77 | + . |
| 78 | +``` |
| 79 | + |
| 80 | +### Build a WAR file |
| 81 | + |
| 82 | +The following example Dockerfile builds a WAR file with the previous changes: |
| 83 | + |
| 84 | +```dockerfile |
| 85 | +FROM mcr.microsoft.com/openjdk/jdk:17-mariner |
| 86 | + |
| 87 | +ARG TOMCAT_VERSION |
| 88 | +ARG TOMCAT_MAJOR_VERSION |
| 89 | +ARG APP_INSIGHTS_VERSION |
| 90 | +ARG APP_INSIGHTS_CONNECTION_STRING |
| 91 | +ARG WAR_FILENAME |
| 92 | +ARG TOMCAT_HOME=/opt/tomcat |
| 93 | + |
| 94 | +# Set up Application Insights agent |
| 95 | +ADD https://github.com/microsoft/ApplicationInsights-Java/releases/download/${APP_INSIGHTS_VERSION}/applicationinsights-agent-${APP_INSIGHTS_VERSION}.jar \ |
| 96 | + /java-agent/applicationinsights-agent.jar |
| 97 | +RUN echo "{\"connectionString\": \"${APP_INSIGHTS_CONNECTION_STRING}\"}" > applicationinsights.json \ |
| 98 | + && mv applicationinsights.json /java-agent/applicationinsights.json |
| 99 | + |
| 100 | +# Set up Tomcat |
| 101 | +ADD https://archive.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR_VERSION/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz \ |
| 102 | + $TOMCAT_HOME/apache-tomcat-$TOMCAT_VERSION.tar.gz |
| 103 | +RUN tdnf update -y \ |
| 104 | + && tdnf install -y tar \ |
| 105 | + && tar -zxf $TOMCAT_HOME/apache-tomcat-$TOMCAT_VERSION.tar.gz -C $TOMCAT_HOME --strip-components 1 \ |
| 106 | + && rm $TOMCAT_HOME/apache-tomcat-$TOMCAT_VERSION.tar.gz \ |
| 107 | + && rm -r $TOMCAT_HOME/webapps/* |
| 108 | + |
| 109 | +COPY $WAR_FILENAME $TOMCAT_HOME/webapps/app.war |
| 110 | + |
| 111 | +# Add the -javaagent option |
| 112 | +ENTRYPOINT ["/bin/sh", "-c" , "export CATALINA_OPTS=-javaagent:/java-agent/applicationinsights-agent.jar && /opt/tomcat/bin/catalina.sh run"] |
| 113 | +``` |
| 114 | + |
| 115 | +When you build a container image with this Dockerfile, you need to add build arguments using `--build-arg`, as shown in the following example: |
| 116 | + |
| 117 | +```bash |
| 118 | +docker build -t <image-name>:<image-tag> \ |
| 119 | + -f WAR.dockerfile \ |
| 120 | + --build-arg APP_INSIGHTS_VERSION=3.5.2 \ |
| 121 | + --build-arg APP_INSIGHTS_CONNECTION_STRING="<connection-string>" \ |
| 122 | + --build-arg WAR_FILENAME=<path-to-war> \ |
| 123 | + --build-arg TOMCAT_VERSION=<version> \ |
| 124 | + --build-arg TOMCAT_MAJOR_VERSION=<major-version> \ |
| 125 | + . |
| 126 | +``` |
| 127 | + |
| 128 | +### Integrate other application performance monitoring agents using Dockerfile |
| 129 | + |
| 130 | +You can integrate other application performance monitoring (APM) agents in a similar way. The following list shows a few other APM agents, along with a brief description on how to integrate them. For download instructions, see the APM official documentation. |
| 131 | + |
| 132 | +- Dynatrace |
| 133 | + - Download the Dynatrace agent in the Dockerfile. |
| 134 | + - Set the following environment variables at runtime: |
| 135 | + - `LD_PRELOAD=<path-to-agent>` |
| 136 | + - `DT_TENANT=<tenant>` |
| 137 | + - `DT_TENANTTOKEN=<token>` |
| 138 | + - `DT_CONNECTION_POINT=<connection-point>` |
| 139 | + - `DT_LOGLEVELCON=info` |
| 140 | + For more information, see [Set up OneAgent on containers for application-only monitoring](https://docs.dynatrace.com/docs/ingest-from/setup-on-container-platforms/docker/set-up-oneagent-on-containers-for-application-only-monitoring). |
| 141 | +- AppDynamics |
| 142 | + - Download the AppDynamics agent in the Dockerfile. |
| 143 | + - Add `-javaagent:<path-to-agent>` to the JVM options. |
| 144 | + - Set the required environment variables, including `APPDYNAMICS_AGENT_ACCOUNT_NAME`, `APPDYNAMICS_AGENT_ACCOUNT_ACCESS_KEY`, and so on, at runtime. For a complete list of configuration properties, see [AppDynamics Java Agent Configuration Properties](https://docs.appdynamics.com/appd/23.x/latest/en/application-monitoring/install-app-server-agents/java-agent/administer-the-java-agent/java-agent-configuration-properties). |
| 145 | +- New Relic |
| 146 | + - Download the New Relic agent in the Dockerfile. If you have a New Relic Java agent config file, copy it from local machine to your container. For more information about config files, see [Java agent configuration: Config file](https://docs.newrelic.com/docs/apm/agents/java-agent/configuration/java-agent-configuration-config-file/). |
| 147 | + - Add `-javaagent:<path-to-agent>` to the JVM options. |
| 148 | + - Set the environment variables `NEW_RELIC_LICENSE_KEY=<license-key>` and `NEW_RELIC_APP_NAME=<app-name>` at runtime, if you haven't set them in a config file or you want to override the values in a config file. |
| 149 | + |
| 150 | +There's another approach to integrate an APM agent, which is to prebuild a container image for the APM agent and run it as an init container. For more information about this approach, see [Tutorial: Configure the Application Performance Management (APM) Java agent with init containers in Azure Container Apps](../../container-apps/java-application-performance-management-config.md). |
| 151 | + |
| 152 | +## Use Paketo Buildpacks |
| 153 | + |
| 154 | +To integrate the Application Insights agent in your container image, you need a binding. For more information about bindings, see [Bindings](https://paketo.io/docs/howto/configuration/#bindings) in the Paketo documentation. |
| 155 | + |
| 156 | +First, use the following commands to create a binding named **application-insights** in the **bindings** directory on your local machine. The binding consists of only one file, named **type**. The content of the **type** file is the text `ApplicationInsights`, indicating an Application Insights binding. |
| 157 | + |
| 158 | +```bash |
| 159 | +mkdir -p bindings/application-insights |
| 160 | +echo "ApplicationInsights" > bindings/application-insights/type |
| 161 | +``` |
| 162 | + |
| 163 | +The following diagram shows the directory structure: |
| 164 | + |
| 165 | +``` |
| 166 | +bindings |
| 167 | +└── application-insights |
| 168 | + └── type |
| 169 | +``` |
| 170 | + |
| 171 | +Then, use the following command to build the image. Provide the binding to your build by using the `--volume` option. The pack CLI mounts the binding directory into the build container. Then, the Application Insights buildpack detects it and participates in the build process. |
| 172 | + |
| 173 | +```bash |
| 174 | +pack build <image-name>:<image-tag> \ |
| 175 | + --volume $(pwd)/bindings/application-insights:/platform/bindings/application-insights" \ |
| 176 | + --path <path-to-source-root> \ |
| 177 | + --builder <builder-name> |
| 178 | +``` |
| 179 | +
|
| 180 | +To deploy the container image in an Azure Container Apps environment, you can use the Azure CLI. For more information, see [Deploy Azure Container Apps with the az containerapp up command](../../container-apps/containerapp-up.md). There are two approaches to pass the Application Insights connection string to the Application Insights agent at runtime. One approach is to pass the connection string as an environment variable. For more information, see the [Configure with environment variables](#configure-with-environment-variables) section. The other approach is to pass the connection string via bindings. For more information, see the [Configure with Bindings](#configure-with-bindings) section. |
| 181 | +
|
| 182 | +### Configure with environment variables |
| 183 | +
|
| 184 | +To pass a connection string to Application Insights, specify `APPLICATIONINSIGHTS_CONNECTION_STRING` in the `--env-vars` option, as shown in the following example. You can specify other environment variables if you want to pass more configuration options to the agent. |
| 185 | +
|
| 186 | +```azurecli |
| 187 | +az containerapp up \ |
| 188 | + --name <container-app-name> \ |
| 189 | + --image <image-name>:<image-tag> \ |
| 190 | + --resource-group <resource-group> \ |
| 191 | + --environment <environment-name> \ |
| 192 | + --location <location> \ |
| 193 | + --env-vars "APPLICATIONINSIGHTS_CONNECTION_STRING=<connection-string>" |
| 194 | +``` |
| 195 | +
|
| 196 | +### Configure with bindings |
| 197 | +
|
| 198 | +To configure the Application Insights agent with bindings, you can store the Application Insights connection string, binding type, and any other configurations as secrets in your container app. Mount the secrets in a volume so that the Application Insights buildpack can read them at runtime. |
| 199 | +
|
| 200 | +With the following command, you declare two secrets at the application level: `type` and `connection-string`. They're mounted to **/bindings/application-insights** in the container. The buildpack searches for bindings in the **/bindings** directory because the `SERVICE_BINDING_ROOT` environment variable is set. |
| 201 | +
|
| 202 | +```azurecli |
| 203 | +az containerapp create \ |
| 204 | + --name <container-app-name> \ |
| 205 | + --image <image-name>:<image-tag> \ |
| 206 | + --resource-group <resource-group> \ |
| 207 | + --environment <environment-name> \ |
| 208 | + --secrets "type=ApplicationInsights" "connection-string=<connection-string>" \ |
| 209 | + --secret-volume-mount "/bindings/application-insights" \ |
| 210 | + --env-vars "SERVICE_BINDING_ROOT=/bindings" |
| 211 | +``` |
| 212 | +
|
| 213 | +Alternatively, you can store the connection string in Azure Key Vault and reference it in secrets. For more information, see [Manage secrets in Azure Container Apps](../../container-apps/manage-secrets.md). |
| 214 | +
|
| 215 | +To deploy the container image to Azure Kubernetes Service, see [How to use buildpacks in Kubernetes for Java](https://github.com/paketo-buildpacks/azure-application-insights/blob/main/docs/how-to-use-buildpacks-in-kubernetes-for-java.md#runtime-phase). |
| 216 | +
|
| 217 | +### Integrate other application performance monitoring agents using Paketo Buildpacks |
| 218 | +
|
| 219 | +There are buildpacks for various APM agents, including the following agents. For more information about binding setup and configurations, see the documentation for each agent. |
| 220 | +
|
| 221 | +- [Dynatrace](https://github.com/paketo-buildpacks/dynatrace) |
| 222 | +- [AppDynamics](https://github.com/paketo-buildpacks/appdynamics) |
| 223 | +- [New Relic](https://github.com/paketo-buildpacks/new-relic) |
0 commit comments