Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added application insights starter for spring boot #518

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions azure-application-insights-spring-boot-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@

**Application Insights Spring Boot Starter**

This Starter provides you the minimal and required configuration to use Application Insights in your Spring Boot application.

**Requirements**
Spring Boot 1.5+ or 2.0+

**Quick Start**

*1. Add dependency*
Gradle:
```groovy
compile "com.microsoft.azure:azure-application-insights-spring-boot-starter:${version}"
```

Maven:
```xml
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-application-insights-spring-boot-starter</artifactId>
<version>${version}</version>
</dependency>
```

*2. Provide Instrumentation Key*

Add property
```
azure.application-insights.instrumentation-key=<key from the Azure Portal>
```
into your `application.properties`

*3. Run your application*

Start your spring boot application as usual and in few minutes you'll start getting events.

**Additional Configuration**

#### Sending custom telemetry
```java
@RestController
public class TelemetryController {

@Autowired
private TelemetryClient telemetryClient;

@RequestMapping("/telemetry")
public void telemetry() {
telemetryClient.trackEvent("my event");
}
}
```


#### Sending logs to the application insight

Follow the instructions from [Spring Boot logging documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html) to configure custom logback or log4j2 appender.

`logback-spring.xml`:
```xml
<appender name="aiAppender"
class="com.microsoft.applicationinsights.logback.ApplicationInsightsAppender">
</appender>
<root level="trace">
<appender-ref ref="aiAppender" />
</root>
```

`log4j2.xml`:
```xml
<Configuration packages="com.microsoft.applicationinsights.log4j.v2">
<Appenders>
<ApplicationInsightsAppender name="aiAppender" />
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="aiAppender"/>
</Root>
</Loggers>
</Configuration>
```

#### Register own telemetry module, processor or initializer by defining it as a bean in the configuration
```java
@SpringBootApplication
public class MyApplication {

public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}

@Bean
public TelemetryModule myTelemetryModule() {
return new MyTelemetryModule();
}

@Bean
public TelemetryInitializer myTelemetryInitializer() {
return new MyTelemetryInitializer();
}

@Bean
public TelemetryProcessor myTelemetryProcessor() {
return new MyTelemetryProcessor();
}

@Bean
public ContextInitializer myContextInitializer() {
return new MyContextInitializer();
}
}
```


#### Configure more parameters using `application.properties`
```properties
# Instrumentation key from the Azure Portal. Required.
azure.application-insights.instrumentation-key=00000000-0000-0000-0000-000000000000

# Enable/Disable tracking. Default value: true.
azure.application-insights.enabled=true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as below for defaults.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default it's true and should not be specified to run application. Only single required property is azure.application-insights.instrumentation-key

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.


# Enable/Disable web modules. Default value: true.
azure.application-insights.web.enabled=true

# Logging type [console, file]. Default value: console.
azure.application-insights.logger.type=console
# Logging level [all, trace, info, warn, error, off]. Default value: error.
azure.application-insights.logger.level=error

# Enable/Disable developer mode, all telemetry will be sent immediately without batching. Significantly affects performance and should be used only in developer environment. Default value: false.
azure.application-insights.channel.in-process.developer-mode=false
# Endpoint address, Default value: https://dc.services.visualstudio.com/v2/track.
azure.application-insights.channel.in-process.endpoint-address=https://dc.services.visualstudio.com/v2/track
# Maximum count of telemetries that will be batched before sending. Must be between 1 and 1000. Default value: 500.
azure.application-insights.channel.in-process.max-telemetry-buffer-capacity=500
# Interval to send telemetry. Must be between 1 and 300. Default value: 5 seconds.
azure.application-insights.channel.in-process.flush-interval-in-seconds=5
# Size of disk that we can use. Must be between 1 and 1000. Default value: 10 megabytes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does't the default and maximum value both seem to be too low. What do you think? Should we bump up this capacity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't really know what is this property about at all :) probably it's a question to @littleaj that have bumped maximum value from 100 to 1000 recently.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gavlyukovskiy this property is used for disk persistence. When the network fails the telemetry gets stored in the disk and when it is restored we transmit that telemetry to the cloud.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhaval24 nice to know, added your explanation to the documentation :)

azure.application-insights.channel.in-process.max-transmission-storage-files-capacity-in-mb=10
# Enable/Disable throttling on sending telemetry data. Default value: true.
azure.application-insights.channel.in-process.throttling=true

# Percent of telemetry events that will be sent to Application Insights. Must be between 0.0 and 100.0. Default value: 100 (all telemetry events).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add this comment here :
"All sampling percentage must be in a ratio of 100/N where N is a whole number (2, 3, 4, …). E.g. 50 for 1/2 or 33.33 for 1/3.
* Failure to follow this pattern can result in unexpected / incorrect computation of values in the portal."

This is important. We can only set specific sampling percentages for UI to be consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't understand, can it be 2/3?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so 100/N = Sampling ratio.
Eg 100/2 = 50
100/3 = 33
100/4 = 25
100/5 = 20
100/10 = 10 etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably we can create property for N instead? It would be less error prone if we say that N must be between 1 (100%) and 100 (1%).

what about 0%, is it valid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just read the documentation for .NET, it can be 1000 (0.1%) as well. Looks really odd to me, I mean that 1/3 is not really 33 or 33.3 or 33.33, it's 33.(3) which you can properly specify in properties and for this reason per documentation I have to chose closest percentage to 100/N.

azure.application-insights.telemetry-processor.sampling.percentage=100
# If set only telemetry of specified types will be included. Default value: all telemetries are included;
azure.application-insights.telemetry-processor.sampling.include=
# If set telemetry of specified type will be excluded. Default value: none telemetries are excluded.
azure.application-insights.telemetry-processor.sampling.exclude=

# Enable/Disable default telemetry modules. Default value: true.
azure.application-insights.default-modules.ProcessPerformanceCountersModule.enabled=true
azure.application-insights.default-modules.WebRequestTrackingTelemetryModule.enabled=true
azure.application-insights.default-modules.WebSessionTrackingTelemetryModule.enabled=true
azure.application-insights.default-modules.WebUserTrackingTelemetryModule.enabled=true
azure.application-insights.default-modules.WebPerformanceCounterModule.enabled=true
azure.application-insights.default-modules.WebOperationIdTelemetryInitializer.enabled=true
azure.application-insights.default-modules.WebOperationNameTelemetryInitializer.enabled=true
azure.application-insights.default-modules.WebSessionTelemetryInitializer.enabled=true
azure.application-insights.default-modules.WebUserTelemetryInitializer.enabled=true
azure.application-insights.default-modules.WebUserAgentTelemetryInitializer.enabled=true
```
51 changes: 51 additions & 0 deletions azure-application-insights-spring-boot-starter/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the ""Software""), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

apply from: "$buildScriptsDir/common-java.gradle"
apply from: "$buildScriptsDir/publishing.gradle"

archivesBaseName = 'azure-application-insights-spring-boot-starter'

dependencies {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bunch of new dependencies. We need to be bit careful what is absolutely needed and also register them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have everything needed here to use with spring boot, only new dependency is assertj and junit of newer version and both testCompile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gavlyukovskiy Isn't junit 5.x still in beta?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, it was released in September and actually yesterday they did second GA release - 5.1.0 :)

compile (project(':core'))
compile (project(':web'))
provided('org.springframework.boot:spring-boot:1.5.9.RELEASE')
provided('org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE')
provided('org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE')
provided('org.springframework.boot:spring-boot-configuration-processor:1.5.9.RELEASE')

testCompile('org.junit.jupiter:junit-jupiter-api:5.0.2')
testCompile('org.junit.jupiter:junit-jupiter-params:5.0.2')
testCompile('org.junit.jupiter:junit-jupiter-engine:5.0.2')
testCompile('org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE')
testCompile('org.assertj:assertj-core:3.9.0')
}

// region Publishing properties

projectPomName = project.msftAppInsightsJavaSdk + " Spring Boot starter"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this POM project name consistent with other AI pom generation scripts? For example look at the build.gradle in core module. It is slightly different. How does this difference affect here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took web module to copy this I intentionally did not include shadowJar because I have no need in it.

ProjectPomName actually is equal to Microsoft Application Insights Java SDK Spring Boot starter, I don't know why other modules use msftAppInsights and then add ' Java SDK', for example project.msftAppInsights + " Java SDK Core" == project.msftAppInsightsJavaSdk + ' Core'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, shadow jar is not needed in this case. Shadowing is usually done only for dependencies that we need to encapsulate like Apache HTTP Client. In this case the SpringBoot Starter jar will be shipped as a jar and it will pull all the transitive dependencies once loaded into the SpringBoot Project, so we do not need that.

projectPomDescription = "This is the Spring Boot starter of " + project.msftAppInsightsJavaSdk

whenPomConfigured = { p ->
def agentArtifactId = project(":agent").jar.baseName
p.dependencies = p.dependencies.findAll { dep -> dep.artifactId != agentArtifactId }
writePomToArtifactsDirectory(p, project.name)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the ""Software""), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

package com.microsoft.applicationinsights.boot;

import com.microsoft.applicationinsights.boot.conditional.ConditionalOnOperatingSystem;
import com.microsoft.applicationinsights.boot.conditional.OperatingSystem;
import com.microsoft.applicationinsights.boot.initializer.SpringBootContextInitializer;
import com.microsoft.applicationinsights.extensibility.initializer.DeviceInfoContextInitializer;
import com.microsoft.applicationinsights.extensibility.initializer.SdkVersionContextInitializer;
import com.microsoft.applicationinsights.internal.perfcounter.ProcessPerformanceCountersModule;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/**
* {@link Configuration} for non-web applications.
*
* @author Arthur Gavlyukovskiy
*/
@Configuration
public class ApplicationInsightsModuleConfiguration {

@Bean
public SpringBootContextInitializer springBootContextInitializer(Environment environment) {
return new SpringBootContextInitializer(environment);
}

@Bean
public SdkVersionContextInitializer sdkVersionContextInitializer() {
return new SdkVersionContextInitializer();
}

@Bean
public DeviceInfoContextInitializer deviceInfoContextInitializer() {
return new DeviceInfoContextInitializer();
}

@Bean
@ConditionalOnOperatingSystem(OperatingSystem.WINDOWS)
@ConditionalOnProperty(value = "azure.application-insights.default-modules.ProcessPerformanceCountersModule.enabled", havingValue = "true", matchIfMissing = true)
public ProcessPerformanceCountersModule processPerformanceCountersModule() {
try {
return new ProcessPerformanceCountersModule();
}
catch (Exception e) {
throw new IllegalStateException("Could not initialize Windows performance counters module, " +
"please set property 'azure.application-insights.default-modules.ProcessPerformanceCountersModule.enabled=false' to avoid this error message.", e);
}
}
}
Loading