Logging Practice for Elastic Beanstalk Java Apps

If your Java applications are deployed to AWS Elastic Beanstalk, you may want to configure the logging to make error diagnostics much easier. We can use Beanstalk console to request and download log files, but you need to configure the app first to make your log files available for download.

Configure app logging

You should first configure the logging framework to log entries to files. You can put the log files to /var/log directory.

For example, you can set an environment variable that only set for Beanstalk and use different logging appenders. Logback supports using if in the configuration file.

Add your own logging files

To make your log files available to Beanstalk, you need to add custom configurations. Create a new directory .ebextensions in the src/main/resources directory and add following file tail-logs.config.

1
2
3
4
5
6
7
8
9
10
11
12
13
files:
"/opt/elasticbeanstalk/tasks/taillogs.d/my-app.conf" :
mode: "000644"
owner: webapp
group: webapp
content: |
/var/log/myapp.log
"/opt/elasticbeanstalk/tasks/bundlelogs.d/my-app.conf" :
mode: "000644"
owner: webapp
group: webapp
content: |
/var/log/myapp.log

After deploying a new version, you should be able to find your app’s log files in the downloaded archive.

Spring MVC swallows exceptions

Sometimes you may find out that exceptions are swallowed by Spring MVC and didn’t appear in log files. You can add your own exception handler to avoid that.

Below is an exception handler class that makes sure exceptions are logged.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;

import java.util.Date;

@ControllerAdvice
@RestController
public class DefaultExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionHandler.class);

@ExceptionHandler(Exception.class)
public final ResponseEntity<ErrorDetails> handleAllExceptions(Exception ex, WebRequest request) {
LOGGER.warn("Internal error", ex);
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(),
request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}

public class ErrorDetails {
private Date timestamp;
private String message;
private String details;

public ErrorDetails(Date timestamp, String message, String details) {
this.timestamp = timestamp;
this.message = message;
this.details = details;
}

public Date getTimestamp() {
return timestamp;
}

public String getMessage() {
return message;
}

public String getDetails() {
return details;
}

}
}
Comments