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

Azure Application Insights SpringBoot Starter #646

Merged
merged 55 commits into from
May 16, 2018
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9bc3711
Added application insights starter for spring boot
gavlyukovskiy Jan 9, 2018
dd97415
Added a way to disable default modules, added documentation and readme
gavlyukovskiy Feb 16, 2018
cce54ae
Polish readme
gavlyukovskiy Feb 17, 2018
946f04a
Added properties to disable quick pulse integration, all web modules;
gavlyukovskiy Feb 20, 2018
91f112b
Fixed bean ordering issue
gavlyukovskiy Feb 21, 2018
abeff08
Added properties for channel and new sampler, created TelemetryType e…
gavlyukovskiy Feb 25, 2018
e8f688f
Added documentation to added properties, added default values, update…
gavlyukovskiy Feb 25, 2018
ed16e55
Changed sampling configuration, added more tests for autoconfiguration
gavlyukovskiy Feb 27, 2018
83e1554
Changed constants with default values to public in order to use them …
gavlyukovskiy Feb 27, 2018
b55c467
Added explicit dependency on TelemetryConfiguration for QuickPulse bean
gavlyukovskiy Mar 1, 2018
afe1d0c
Polish
gavlyukovskiy Mar 1, 2018
dcadfc1
Merge branch 'master' into spring-boot-starter
gavlyukovskiy Mar 13, 2018
62086f3
Updated documentation regarding configuration values window
gavlyukovskiy Mar 13, 2018
a4fda92
Updated documentation of properties
gavlyukovskiy Mar 14, 2018
77d88a6
Merge pull request #518 from gavlyukovskiy/spring-boot-starter
dhaval24 Mar 15, 2018
2385ab0
Merge branch 'master' into spring-boot-starter
dhaval24 Mar 15, 2018
4bd0b4b
update build script to fix pom generation, enforced InternalLoggerBea…
dhaval24 Mar 15, 2018
bc19586
improving the way to locate agent and registering web app
dhaval24 Mar 16, 2018
b2fbcd9
adding way to get empty telemetry configuration object
dhaval24 Mar 17, 2018
be1e235
adding max_instant_rety configuration for boot
dhaval24 Mar 20, 2018
ce361b4
Merge branch 'master' into spring-boot-starter
dhaval24 Mar 22, 2018
94cdc2d
refactoring spelling error
dhaval24 Mar 26, 2018
9aa1fc0
Merge branch 'spring-boot-starter' of https://github.com/Microsoft/Ap…
dhaval24 Mar 26, 2018
abc91c3
Merge branch 'master' into spring-boot-starter
dhaval24 Apr 3, 2018
b7ef489
fix a test
dhaval24 Apr 3, 2018
943ad11
fixing broken initialization
dhaval24 Apr 4, 2018
79b5f0c
changing SpringBootContextInitializer to TelemetryInitializer, contex…
dhaval24 Apr 4, 2018
1580e79
updating enabling web modules and enabling AI, adding autoconfigurati…
dhaval24 Apr 9, 2018
3d194e5
migrate tests to junit4
dhaval24 Apr 9, 2018
905304b
Merge branch 'master' into spring-boot-starter
dhaval24 Apr 9, 2018
b90254f
adding more tests
dhaval24 Apr 10, 2018
bd934f1
Merge branch 'HeartBeat' into spring-boot-starter
dhaval24 Apr 10, 2018
9338c7a
Heartbeat updates to accomodate autoconfig in SpringBoot
dhaval24 Apr 10, 2018
7b60bc2
Adding auto cofiguration for SpringBoot
dhaval24 Apr 11, 2018
fd1f2eb
removing SpringBootInitializer to push meta deta, instead moving to h…
dhaval24 Apr 11, 2018
aad2b50
autoconfigure cloud_RoleName, removed field injection to constructor …
dhaval24 Apr 12, 2018
99fb891
fixing dependency version
dhaval24 Apr 12, 2018
2896f6d
specifying the version number
dhaval24 Apr 12, 2018
8454f87
resolving merge issues
dhaval24 Apr 20, 2018
85a2072
resolving merge conflict, removed unused Operating system conditional…
dhaval24 Apr 20, 2018
16a5a87
remove unused imports
dhaval24 Apr 20, 2018
94ca1e1
modifying version number
dhaval24 Apr 24, 2018
7cf8f72
Merge branch 'master' into spring-boot-starter
dhaval24 Apr 24, 2018
5e56ee3
updating the archive base name for consistency, adding javadocs
dhaval24 Apr 24, 2018
642cbe7
adding null check, some fixes and reducing styling
dhaval24 Apr 26, 2018
62c50fe
fix test and intermediate commit
dhaval24 Apr 26, 2018
613e59d
removing TelemetryType enum for better maintanability, refactoring st…
dhaval24 May 4, 2018
1a24b0a
Revert "improving the way to locate agent and registering web app"
dhaval24 May 4, 2018
aa4c93c
resolving merge conflict
dhaval24 May 4, 2018
b9936e6
modularizing way to specify version number of starter, adding starter…
dhaval24 May 13, 2018
58b9028
reverting a file and fixing dual initialization
dhaval24 May 14, 2018
4a843ba
adding the configuration parity tests
dhaval24 May 15, 2018
abba801
updating readme with migration steps
dhaval24 May 16, 2018
ba6d722
Merge branch 'master' into spring-boot-starter
dhaval24 May 16, 2018
0f67356
Smoke Tests for SpringBoot Application using SpringBoot AI Starter (#…
dhaval24 May 16, 2018
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
182 changes: 182 additions & 0 deletions azure-application-insights-spring-boot-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@

**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

# 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 space that Application Insights can use to store telemetry in case of network outage. Must be between 1 and 1000. Default value: 10 megabytes.
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. Percentage must be close to 100/N where N is an integer.
# E.g. 50 (=100/2), 33.33 (=100/3), 25 (=100/4), 20, 1 (=100/100), 0.1 (=100/1000). Default value: 100 (all telemetry events).
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.JvmPerformanceCountersModule.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

#Enable/Disable heartbeat module. Default value : true
azure.application-insights.heart-beat.enabled=true
#Default heartbeat interval is 15 minutes. Minimum heartbeat interval can be 30 seconds.
azure.application-insights.heart-beat.heart-beat-interval=900
#If set of properties are specified they would be excluded from Heartbeat payload
azure.application-insights.heart-beat.excluded-heart-beat-properties-list=
#If set of HeartBeat providers are specified they would be excluded
azure.application-insights.heart-beat.excluded-heart-beat-provider-list
```

###Completely disable Application Insights using `application.properties`
```properties
azure.application-insights.enabled=false
azure.application-insights.web.enabled=false
```
Note: Do not configure `azure.application-insights.instrumentation-key` property for optimal performance
and avoiding any Application Insights beans creation by Spring.
49 changes: 49 additions & 0 deletions azure-application-insights-spring-boot-starter/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 = 'applicationinsights-spring-boot-starter'
version = '1.0.0-BETA'

dependencies {
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('junit:junit:4.12')
testCompile('org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE')
testCompile('org.assertj:assertj-core:2.6.0')
}

compileJava.dependsOn(processResources)
// region Publishing properties

projectPomName = project.msftAppInsightsJavaSdk + " Spring Boot starter"
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 }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* 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.ApplicationInsightsProperties.HeartBeat;
import com.microsoft.applicationinsights.boot.HeartBeatProvider.SpringBootHeartBeatProvider;
import com.microsoft.applicationinsights.boot.initializer.SpringBootTelemetryInitializer;
import com.microsoft.applicationinsights.extensibility.initializer.DeviceInfoContextInitializer;
import com.microsoft.applicationinsights.extensibility.initializer.SdkVersionContextInitializer;
import com.microsoft.applicationinsights.internal.heartbeat.HeartBeatModule;
import com.microsoft.applicationinsights.internal.heartbeat.HeartbeatDefaultPayload;
import com.microsoft.applicationinsights.internal.perfcounter.JvmPerformanceCountersModule;
import com.microsoft.applicationinsights.internal.perfcounter.ProcessPerformanceCountersModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;

/**
* <h1>Core Application Insights Configuration</h1>
* <p>
* This class provides the Core Configuration for ApplicationInsights. This configuration is
* irrespective of WebApplications. {@link Configuration} for non-web applications.
* </p>
*
* @author Arthur Gavlyukovskiy, Dhaval Doshi
*/
@Configuration
@EnableConfigurationProperties(ApplicationInsightsProperties.class)
@ConditionalOnProperty(value = "azure.application-insights.enabled", havingValue = "true", matchIfMissing = true)
public class ApplicationInsightsModuleConfiguration {

/**
* Instance for the container of ApplicationInsights Properties
*/
private ApplicationInsightsProperties applicationInsightsProperties;

@Autowired
public ApplicationInsightsModuleConfiguration(ApplicationInsightsProperties properties) {
this.applicationInsightsProperties = properties;
}

/**
* Bean for SdkVersionContextInitializer
* @return instance of {@link SdkVersionContextInitializer}
*/
@Bean
public SdkVersionContextInitializer sdkVersionContextInitializer() {
return new SdkVersionContextInitializer();
}

/**
* Bean for DeviceInfoContextInitializer
* @return instance of {@link DeviceInfoContextInitializer}
*/
@Bean
public DeviceInfoContextInitializer deviceInfoContextInitializer() {
return new DeviceInfoContextInitializer();
}

/**
* Bean for SpringBootTelemetryInitializer
* @return instance of {@link SpringBootTelemetryInitializer}
*/
@Bean
public SpringBootTelemetryInitializer springBootTelemetryInitializer() {
return new SpringBootTelemetryInitializer();
}

/**
* Bean for ProcessPerformanceCounterModule
* @return instance of {@link ProcessPerformanceCountersModule}
*/
//FIXME: This should be conditional on operating System. However, current architecture of ProcessBuiltInPerformanceCountersFactory
//FIXME: does not separate this concerns therefore cannot condition as of now.
@Bean
@DependsOn("performanceCounterContainer")
@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);
}
}

/**
* Bean for JvmPerformanceCounterModule
* @return instance of {@link JvmPerformanceCountersModule}
*/
@Bean
@DependsOn("performanceCounterContainer")
@ConditionalOnProperty(value = "azure.application-insights.default.modules.JvmPerformanceCountersModule.enabled", havingValue = "true", matchIfMissing = true)
public JvmPerformanceCountersModule jvmPerformanceCountersModule() {
try {
return new JvmPerformanceCountersModule();
}
catch (Exception e) {
throw new IllegalStateException("Could not initialize Jvm Performance Counters module "
+ "please set the property 'azure.application-insights.default.modules.JvmPerformanceCountersModule.enabled=false' to "
+ "avoid this error message", e);
}
}

/**
* Bean for HeartBeatModule. This also sets the properties for HeartBeatModule
* @param environment
* @return initialized instance with user specified properties of {@link HeartBeatModule}
*/
@Bean
@ConditionalOnProperty(value = "azure.application-insights.default.modules.HeartBeat.enabled", havingValue = "true", matchIfMissing = true)
public HeartBeatModule heartBeatModule(Environment environment) {
try {
HeartBeatModule heartBeatModule = new HeartBeatModule();
HeartbeatDefaultPayload.addDefaultPayLoadProvider(new SpringBootHeartBeatProvider(environment));
Copy link
Contributor

Choose a reason for hiding this comment

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

If it's expected from users to be able to provide own HeartBeatProvider implementation it's worth to create bean:

@Bean
@ConditionalOnMissingBean
public HeartBeatPayloadProviderInterface heartBeatPayloadProviderInterface(Environment environment) {
    return new SpringBootHeartBeatProvider(environment);
}

and inject HeartBeatPayloadProviderInterface into HeartBeatModule. It's important to have interface declaration instead of implementation - SpringBootHeartBeatProvider because only this way users are able to override the bean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In all cases we would like to have the properties of the current provider for better assessment. However it makes sense to do this more elegantly using bean. I would refactor this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gavlyukovskiy this is now addressed.

HeartBeat heartBeat = applicationInsightsProperties.getHeartBeat();
heartBeatModule.setHeartBeatInterval(heartBeat.getHeartBeatInterval());
if (heartBeat.getExcludedHeartBeatPropertiesList().size() > 0) {
heartBeatModule.setExcludedHeartBeatProperties(heartBeat.getExcludedHeartBeatPropertiesList());
}
if (heartBeat.getExcludedHeartBeatProviderList().size() > 0) {
heartBeatModule.setExcludedHeartBeatPropertiesProvider(heartBeat.getExcludedHeartBeatProviderList());
}
return heartBeatModule;
}
catch (Exception e) {
throw new IllegalStateException("could not configure Heartbeat, please set 'azure.application-insights.default.modules.HearBeat.enabled'"
+ " to false ", e);
}
}
}
Loading