Configuring Logback in SpringBoot using application.properties

I have a Java Spring Boot application that we are switching to use Sentry (from Errbit).

We are using the Logback appender, since that is what we were using for our previous solution.

We would like all of our configuration to be in a single application.properties file.

Right now, the only way we can figure out how to do that is:

public static void main(String [] args) {
    System.setProperty("sentry.properties.file", "application.properties");

    SpringApplication.run(Application.class, args);
}

However, that requires us to use dsn = ..., environment = ..., etc. instead of sentry.dsn = ..., etc. That makes it difficult to ensure that the Sentry variables don’t conflict with other application-specific config that may already be there.

We tried several other options, including adding this:

@Autowired
private Environment env;

@PostConstruct
public void postConstruct() {
	String[] sentryProps = {
		"sentry.dsn",
		"sentry.environment",
        // etc. ...
	};

	for (String prop : sentryProps) {
		System.setProperty(prop, env.getProperty(prop));
	}
}

The problem is that @PostConstruct runs too late in the startup process to catch things like database connection errors.

Also, this is a really bad hack.

Is there a better way to get the Sentry properties from the application.properties file?

You can create sentry.properties under src/main/resources and put all sentry configuration there.
Then simply init sentry before spring boot application startup.

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

It’ll lookup for senty properties under src/main/resources and your sentry connection will be initialized before application startup.
This is the way I’ve configured, not sure is it an ideal way to do so.

That still does not solve my issue, namely that I want to be able to use a single configuration file (that being my application.properties) to have all configuration. I want this file to be able to be modified for each deployment, which your suggestion does not solve.

I ended up doing it like this (note that since this thread was started I have converted this application to Kotlin):

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent
import org.springframework.boot.runApplication
import org.springframework.context.ApplicationListener
import io.sentry.Sentry

@SpringBootApplication
class Application

fun main(args: Array<String>) {
    runApplication<Application>(*args) {
		this.addListeners(ApplicationListener<ApplicationEnvironmentPreparedEvent> {
			val env = it.environment

			// Copy over all `sentry` properties into the system properties so Sentry can find them
			for (propName in arrayOf("dsn", "environment", "stacktrace.app.packages")) {
				System.setProperty("sentry.$propName", env.getProperty("sentry.$propName"))
			}

			Sentry.init()
		})
	}
}

It’s not the best or cleanest way, but it accomplishes my requirements.

Then maybe you can pass all sentry parameters like environment and stacktrace.app.packages in sentry.dsn which is initialized in application.properties

for eg. add this property in your application.properties.

sentry.dsn=https://public:private@host:port/1?environment=dev&release=${version}&stacktrace.app.packages=com.example.demo&servername=dev-server&async.queuesize=100

Then you’ll only need to call sentry.init() in main(). Using this you can skip setting up system properties.