AppInsight Java Agent dependency done right with Azure Artefacts and Gradle

Przemek Sempruch
4 min readNov 12, 2019

--

If you ever happen to ship your application with Azure App Service and SpringBoot (Java) you probably want to integrate it with Azure AppInsights to monitor your application behaviour and logs.

Sadly, Microsoft does not publish agent jar anywhere nice such as Maven Central Repository, but only publishes it on Github. This breaks the natural flow of importing a dependency using any dependency manager such as Maven or Gradle.

The simplest solution to this would be to start publishing the agent jar as it happens with other AppInsights artefacts. As much as I can shout and cheer for that, I cannot make it happen.

Other solution is to download the agent jar and check it into your Java project repository. I have seen it happening on many projects but I am not an advocate of that approach due to quite popular principle:

“Never commit binaries to a git repo”.

It always starts with an innocent statement: “this is just a single file”, but then new versions arrive, new binaries get pushed, the repo bloats, others start repeating the pattern and all bad stuff spreads like a vermin :-) If you had to manage more than one Java project, would you also add the agent jar to each of repositories, bloat each of them and update each of them when necessary ?

Recently, I have come up with somewhat twisted but effective approach to this problem using Gradle and Azure Artefacts repository. The idea can be illustrated as below:

Dependency management

I managed to create a simple Publisher Java project of which a single responsibility was to download the agent jar with a specific version from source git repo (or any other location) and publish it to Artefact Repository e.g. Azure Artefacts. Below there is a simple Gradle script to do that:

ext {
applicationInsightsVersion = '2.5.0'
}
task downloadInsights(type: Download) {
src "https://github.com/microsoft/ApplicationInsights-Java/releases/download/${applicationInsightsVersion}/applicationinsights-agent-${applicationInsightsVersion}.jar"
dest buildDir
}
publishing {
publications {
maven(MavenPublication) {
groupId = 'some group id'
artifactId = 'applicationinsights-agent'
version = applicationInsightsVersion
artifact "${buildDir}/applicationinsights-agent-${applicationInsightsVersion}.jar"
}
}
repositories {
maven {
url 'https://pkgs.dev.azure.com/{YOUR_ORGANISATION}/_packaging/{YOUR_REPOSITORY}/maven/v1'
credentials {
username "AZURE_ARTIFACTS"
password System.getenv("AZURE_ARTIFACTS_ENV_ACCESS_TOKEN")
}
}
}
}

This project can be built with Azure DevOps Pipeline or any CI tool like Jenkins. Upon execution of

gradle bootJar

I end up with agent jar file landed in my Azure Artefacts repository.

Agent Jar post upload

Now that the artefact is published, it is time for a Consumer project to pull in the agent as a dependency.

What I would like to achieve is to pull newly created dependency and place it in the location that is convenient for release artefact packaging and deployment e.g. next to the output uber jar.

All I need to do is to add following entries to the consumer project build.gradle

(1)
configurations {
agentlib {
transitive = false
}
}
(2)
repositories {
mavenLocal()
maven {
url 'https://pkgs.dev.azure.com/{YOUR_ORGANISATION}/_packaging/{YOUR_REPOSITORY}/maven/v1'
credentials {
username "AZURE_ARTIFACTS"
password System.getenv("AZURE_ARTIFACTS_ENV_ACCESS_TOKEN")
}
}
3)
dependencies {
agentlib '{GROUP_ID}:applicationinsights-agent:2.5.0'
}
4)
task copyAgentLib(type: Copy) {
from configurations.agentlib
into "$buildDir/libs"
}
5)
bootJar.finalizedBy(copyAgentLib)

Let’s go step by step through what it does:

  1. As I want the agent jar output location to be configurable I create a separate Gradle configuration called agentlib to delineate the type and purpose of the agent as a dependendcy.
  2. I want to pull the JAR dependency from my Azure Artefacts repository so I add repository entry to the known repositories.
  3. I add agent JAR dependency to my agentlib configuration.
  4. I create a task copyAgentLib that copies dependencies from agentlib configuration to the uber jar output folder.
  5. I ensure the copying task executes after uber jar is built.

With this I am ready for my consumer Java project to be built with the CI of my choice.

Summing up

Although it all seems an overhead since Microsoft could just put the agent jar into Maven Central and Publisher project would become redundant, we learnt how to:

  1. Create a custom JAR artefact for your Java project that can be consumed in a unified and safe way — you could pull everything raw and dirty, but what if that file disappeared from a source location? Storing the imported artefact in the custom repository gives you safety and reduces the risk of losing it.
  2. Create custom configuration in Gradle so that separate rules can be applied to their dependencies.

Personally, I would love this article to inspire Microsoft to see the value in publishing the agent jar and simplify the process ❤️

--

--