-
Notifications
You must be signed in to change notification settings - Fork 205
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
Changes from 3 commits
9bc3711
dd97415
cce54ae
946f04a
91f112b
abeff08
e8f688f
ed16e55
83e1554
b55c467
afe1d0c
579eb5c
dcadfc1
62086f3
a4fda92
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
|
||
**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 | ||
# Enable/Disable tracking | ||
azure.application-insights.enabled=true | ||
|
||
# Instrumentation key from the Azure Portal | ||
azure.application-insights.instrumentation-key=00000000-0000-0000-0000-000000000000 | ||
|
||
# Logging type [console, file] | ||
azure.application-insights.logger.type=console | ||
# Logging level [all, trace, info, warn, error, off] | ||
azure.application-insights.logger.level=info | ||
|
||
# Enable/Disable default telemetry modules | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if user doesn't care to specify all these? By default are they turned on? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By default they are all turned on, added these properties just in case user wants to disable those. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, it makes sense to specify all the available properties to tweak in the readme, however please make a note there that all these properties are turned on by default so that user can have an understanding. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about calling them default already makes them turned on by default ;) I will add note that all those enabled by default |
||
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 | ||
``` |
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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gavlyukovskiy Isn't junit 5.x still in beta? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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,72 @@ | ||
/* | ||
* 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.TelemetryConfiguration; | ||
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.ConditionalOnBean; | ||
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 | ||
@ConditionalOnBean(TelemetryConfiguration.class) | ||
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", e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The throw from here means it would crash the user application? In that event it is much advised to rather log the message using logger rather than throwing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will change this to logging error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I remember why I did it, actually you can't just log error here because bean instance must be returned. I'm not quite sure how to fix this properly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although I don't see any reason why it would throw an exception. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like very unlikely situation. Can't you return null in such case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's possible, in best case we can either create conditional where we try to create instance and return true only if it was successfully created, or have message with clear action to do, something like 'We are failed to create performance metric, please set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gavlyukovskiy from technical point of view it's possible, such bean declaration is 100% valid and it works: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, it's valid. But then I should check that module is not null when initializing them in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gavlyukovskiy I am fine with failing and asking to set the message please set azure.application-insights.default-modules.ProcessPerformanceCountersModule.enabled=false to avoid this error message'. Please add this conditional. |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* 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.extensibility.TelemetryModule; | ||
import com.microsoft.applicationinsights.internal.logger.InternalLogger.LoggerOutputType; | ||
import com.microsoft.applicationinsights.internal.logger.InternalLogger.LoggingLevel; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* {@link ConfigurationProperties} for configuring application insights. | ||
* | ||
* @author Arthur Gavlyukovskiy | ||
*/ | ||
@ConfigurationProperties("azure.application-insights") | ||
public class ApplicationInsightsProperties { | ||
|
||
/** | ||
* Enables application insights auto-configuration. | ||
*/ | ||
private boolean enabled = true; | ||
/** | ||
* Instrumentation key from Azure Portal. | ||
*/ | ||
private String instrumentationKey; | ||
/** | ||
* Logger properties. | ||
*/ | ||
private Logger logger = new Logger(); | ||
|
||
public boolean isEnabled() { | ||
return enabled; | ||
} | ||
|
||
public void setEnabled(boolean enabled) { | ||
this.enabled = enabled; | ||
} | ||
|
||
public String getInstrumentationKey() { | ||
return instrumentationKey; | ||
} | ||
|
||
public void setInstrumentationKey(String instrumentationKey) { | ||
this.instrumentationKey = instrumentationKey; | ||
} | ||
|
||
public Logger getLogger() { | ||
return logger; | ||
} | ||
|
||
public void setLogger(Logger logger) { | ||
this.logger = logger; | ||
} | ||
|
||
public static class Logger { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this class mean default logging values? If yes, then level should be error. Info logging will flood the user's production environment and reduce throughput. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, there are defaults. Will change to ERROR |
||
/** | ||
* Type of application insights logger. | ||
*/ | ||
private LoggerOutputType type = LoggerOutputType.CONSOLE; | ||
/** | ||
* Minimal level of application insights logger. | ||
*/ | ||
private LoggingLevel level = LoggingLevel.INFO; | ||
|
||
public LoggerOutputType getType() { | ||
return type; | ||
} | ||
|
||
public void setType(LoggerOutputType type) { | ||
this.type = type; | ||
} | ||
|
||
public LoggingLevel getLevel() { | ||
return level; | ||
} | ||
|
||
public void setLevel(LoggingLevel level) { | ||
this.level = level; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.