Unable to link Spring boot application with Azure Application insight using application.properties, when logback.xml is used - spring-boot

I have created a spring-boot starter project and linked Azure Application insight to it. The properties like instrumentation- key is defined in "application.properties". On launching the application it is correctly linked to App Insight as can be verified by Live Metrics Stream.
However same application fails to connect to Azure App Insight if logback.xml is included in project (in resources), in this case to connect to App insight I have to include ApplicationInsights.xml as well.
But I do not want to use "ApplicationInsights.xml" in my application for 2 reasons. 1. I do not want multiple configuration files. 2. I am not able to inject key , i.e. not able to externalize key which might come as vm arguments or environment variable.
Defining InstrumentationKey and other configuration in application.properties works only when logback.xml is not present.
sample project (asset-register.zip) can be found at https://github.com/Microsoft/ApplicationInsights-Java/issues/710

Related

Multiple web applications in one tomcat instance start with a properties file from another applications

We have multiple web applications in one tomcat instance on 1 server, all running a spring-boot application inside.
Whenever we start tomcat and it starts to boot up all the spring-boot applications we mostly see that each application might use property files/settings from another application.
What especially happens is that we see it sometimes use the database information from other applications being used, resulting in a database which holds tables from other applications. This is scary since we might start a database migration or something.
We also see that the logs are written to the wrong project log file.
We define these settings using a application.properties like (or sometimes application-test.properties or application-secret.properties):
spring.datasource.username
spring.datasource.password
logging.file.name
Anyone have an idea why this is happening?
We found 2 possible causes for this behavior:
if Tomcat is started in a directory where application property files are present, or where application property files are placed in a /config subdirectory, like a WEB-INF/classes directory, these application property files are used by every Spring Boot application deployed in the tomcat instance. To fix this, make sure the Tomcat start script changes the working directory to a directory not containing application property files.
if the 'startStopThreads' attribute of the Tomcat Engine element in server.xml is set to values higher than 1, Spring Boot applications seem to occasionally and randomly use application property files of other Spring Boot applications deployed in the Tomcat instance. When 'startStopThreads' is set to 1, we don't see this behavior.

Azure ApplicationInsights using logback in Spring Boot - application name not propagated

Currently Im trying to integrate our Spring Boot Java services with Azure Application Insights.
First of all I shall write that below issue from 2018 seems to be still active/alive as I encountered this behavior when using 2.6.0 version.
https://github.com/Microsoft/ApplicationInsights-Java/issues/710
https://github.com/microsoft/ApplicationInsights-Java/issues/1014
It seems the application.yml (not properties in my case) are not used and I was able to get it working only with ApplicationInsgights.xml file.
Anyway there are some workarounds for setting the instrumentation key so OK.
However my question is following:
Why the Logback logs dont have application name in "traces" table/data set in Azure portal?
Under which column should the application name be populated? It was populated in column "cloud_RoleName", but now it is not populated despite no changes were made. Column "appId" is some UUID and column "appName" has name of the application insights resource, not the value from spring.application.name.
This doc does not seem up to date:
https://learn.microsoft.com/en-us/azure/azure-monitor/reference/tables/traces
Also the app. Im connecting to AI is run outside Azure, which can possibly play some role.
Thanks.

Using Spring Boot profiles on external tomcat

I am looking for a solution to the problem, which is that having an external Tomcat server with several different applications (war),
I would like to use application Spring Profile (dev, prod) to choose application.properties for a given profile.
To avoid keeping the database configuration in the git repository, I didn't store in the application
application.properties, but I kept them in the $catalina.base directory, where in common.loader
I indicated the path to this directory. This worked until I started deploying several different applications. Then each of them began to use
from the same datasource. One solution is to keep the application.properties in Jenkins and directly in Jobie indicating which one to use,
but I am not sure if this is a good solution.
Option 1: Create a separate instance of tomcat (using same tomcat binary) and place application.properties in instance's classpath. As classpath is separate for every instance, applications don't refer to same application.properties file. Refer to this article to see how to create multiple instances on same tomcat server.
Option 2: Create JNDI datasource on tomcat server and use it in your application to access database. This way, should you choose to, same datasource can be shared across different related applications and/or modules. For more information on how to create JNDI datasource in Tomcat, refer to this link

Spring Cloud Config dual bootstrap files behavior

I have a setup where I am using the following:
Spring Boot 1.5.13 with Spring Cloud Version Edgware.S3
I have Spring Cloud Config Server and my Spring Boot apps are its clients
Each app carries a bootstrap.yml with the config server uri and some other properties.
Running containers on a Docker Swarm
I am currently passing Swarm secrets to the clients via a custom script which reads the files put into /run/secrets/ and creating a /config/bootstrap.properties file. It ends up looking like this:
spring.cloud.config.username=user
spring.cloud.config.password=password
My Docker image's default command is then this:
java -Djava.security.egd=file:/dev/./urandom -jar /${appName}.jar --spring.cloud.bootstrap.location=file:/config/bootstrap.properties"
Great. This is working without a problem. The app, seemingly, reads:
The external bootstrap.properties to read in the config server's credentials
The classpath bootstrap.yml to read in the rest of the config client props
Fetches and reads in the config server's application-appName.yml
Then reads the bundled application.yml from the classpath
Now. I'm moving the apps to Spring Boot 2.0.3 with Finchley.RELEASE and well, this breaks.
What is happening now is:
The external bootstrap.properties is read in to get the config server's credentials
The classpath bootstrap.yml is SKIPPED entirely (UNEXPECTED!)
Fetches and reads in the config server's application-appName.yml
Then reads the bundled application.yml from the classpath
The problem is that the properties that were set in the internal bootstrap.yml are now missing for the app so it blows up on start. I've been able to reproduce it outside the container environment by doing the same thing; point the app to an external bootstrap.properties. If I copy over the bootstrap.yml properties into the bootstrap.properties, then it works just fine. Also, if I don't provide an external properties file, then the internal bootstrap.yml kicks in without a problem. So it's either one or the other!
I'v also tried modifying the bootstrap location to include the default locations but no luck:
-- spring.cloud.bootstrap.location=file:/config/bootstrap.properties,classpath:,classpath:/config,file:,file:config/
Any ideas where to look next? Maybe there is a new spring.cloud.config property I'm missing? Or can anyone confirm which behavior is the correct behavior? Assuming they fixed a potential loophole in Finchley then I can just put this to rest and look for another solution. If it's 'broken' in Finchley, I guess an issue report is in order?
Well, some more digging showed that it looks like this is the new behavior:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide
The behavior of the spring.config.location configuration has been fixed; it previously added a location to the list of default ones, now it replaces the default locations. If you were relying on the way it was handled previously, you should now use spring.config.additional-location instead.
It didn't look to be Spring Cloud specific but I had nothing to lose.
Changing my java command to use this new property did the trick:
--spring.config.additional-location=file:/config/bootstrap.properties
Thanks.

Including profiles via a Spring Boot starter

I'm having issues with a custom Spring Boot starter. How can a starter cause a profile to be included and pull related configuration from a config server?
Perhaps my use case is unique, because I haven't found any helpful information online. I'm working in an enterprise environment and this starter is for use by my team, so we're able to control some things (like profile names) that perhaps wouldn't make sense in the open source world.
Here is the scenario: We have a Spring Cloud Config Server running to provide configuration. Across our Spring Boot projects, we have standardized on certain profile names such as "prod" and "nonprod" to control configuration in our different environments. I am trying to create a starter to provide reusable functionality. For example purposes, let's say I'm creating a starter that provides an interface to an appliance that performs cryptographic work for us. This starter will need the IP address of the appliance and various other configuration which differs between production and non-production.
Within the config repo, I will have files such as application.yml, application-nonprod.yml, application-nonprodEncryption.yml, etc.
My goal is to have the custom encryption starter automatically include the nonprodEncryption profile when that starter is included in an application. By doing this, apps which don't need encryption do not load the encryption related properties.
Here are my experimental findings so far:
Within an application's bootstrap.yml, I can put a block such as
spring.profiles: nonprod
spring:
profiles:
include:
- nonprodEncryption
and that produces the desired result (i.e. the application-nonprodEncryption.yml file is loaded from the config server and used), but this is an undesirable solution as every app that uses my custom starter would need to include this boilerplate configuration.
When I move the above configuration to the starter's bootstrap.yml, it seems to have no effect.
When I move the above configuration to the starter's application.yml, it seems to be applied (i.e. it shows up in the The following profiles are active: list), but it is too late in the lifecycle to cause the appropriate configuration to be pulled from the config server.
Other things I've considered:
Why not just put all of the configuration into the main profile config file (e.g. application-nonprod.yml)? From a separation of concerns and maintenance standpoint, I'd like to keep configuration for individual starters isolated from each other. Also, some configuration data is more sensitive than other config data, so I don't like the idea of exposing all of the configuration to all apps, since many apps won't need some of the more sensitive configuration. Yes, they could get to it, but why load it into their memory if they don't need it?
Why not just specify the extra profiles when we launch the app? These apps will be running on a cloud platform. The platform will specify either "prod" or "nonprod" as the profile based on which tier the app is running in. I want to manage that at the platform level rather than the app level, so I want the list of profiles provided at app launch to be uniform across all apps (add adding, for example, nonprodEncryption to the list just gets me into the same situation as above - all apps would have all of the configuration, so I might as well just put it all in a single file).
We are currently using Spring Boot 1.5.10.
Any thoughts on how to achieve what I'm trying to do?
I finally found a solution (in case anyone else finds themselves in the same spot).
Step 1: Add a configuration class like this to your starter:
package com.company.bootstrap;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Profile;
#Configuration
#Profile("nonprod")
public class BootstrapNonprod {
public BootstrapNonprod(ConfigurableApplicationContext ctx) {
ctx.getEnvironment().addActiveProfile("nonprodEncryption");
}
}
This will conditionally add a profile. In this example, whenever the "nonprod" profile is active, this class will add the "nonprodEncryption" profile.
Step 2: In your starter's spring.factories file, add a line such as this:
org.springframework.cloud.bootstrap.BootstrapConfiguration=com.company.bootstrap.BootstrapNonprod
It seems like it is just that simple.

Resources