Logging in Spring Boot

Introduction

In this chapter, we will explore how to implement logging in a Spring Boot application using an Employee Management Project as an example. Logging is crucial for tracking the behavior of an application, debugging issues, and monitoring performance. Spring Boot provides robust support for various logging frameworks and makes it easy to configure and use them.

Table of Contents

  1. Introduction
  2. Benefits of Logging
  3. Setting Up Logging in Spring Boot
  4. Configuring Log Levels
  5. Logging in the Application Code
  6. Using Different Logging Frameworks
  7. Example: Logging in Employee Management Project
  8. Conclusion

Benefits of Logging

  1. Debugging: Helps identify and fix issues in the code.
  2. Monitoring: Provides insights into the application’s behavior and performance.
  3. Auditing: Keeps a record of important events and transactions.
  4. Maintenance: Assists in maintaining and improving the application over time.

Setting Up Logging in Spring Boot

Spring Boot uses Logback as the default logging framework. However, it also supports other logging frameworks like Log4j2 and SLF4J. By default, Spring Boot logs information to the console, but you can configure it to log to files, databases, or other destinations.

Default Logging Setup

Out of the box, Spring Boot uses Logback with the following default configuration:

  • INFO level logging for the root logger.
  • DEBUG level logging for the Spring framework.

You can change these defaults in the application.properties or application.yml file.

Configuring Log Levels

Log levels control the verbosity of the log output. The common log levels are:

  1. TRACE: Most detailed information.
  2. DEBUG: Detailed information used for debugging.
  3. INFO: General information about the application’s running state.
  4. WARN: Potentially harmful situations.
  5. ERROR: Error events that might still allow the application to continue running.
  6. FATAL: Very severe error events that will presumably lead the application to abort.

Example Configuration in application.properties

logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.com.example=TRACE

Example Configuration in application.yml

logging:
  level:
    root: WARN
    org.springframework.web: DEBUG
    com.example: TRACE

Logging in the Application Code

You can use the SLF4J API to add logging to your application code. SLF4J (Simple Logging Facade for Java) is a facade for various logging frameworks, allowing you to plug in the desired logging framework at deployment time.

Example of Logging in a Spring Boot Application

package com.example.employeemanagement.controller;

import com.example.employeemanagement.model.Employee;
import com.example.employeemanagement.service.EmployeeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

    private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);

    @Autowired
    private EmployeeService employeeService;

    @PostMapping
    public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) {
        logger.debug("Request to save employee: {}", employee);
        Employee savedEmployee = employeeService.saveEmployee(employee);
        return new ResponseEntity<>(savedEmployee, HttpStatus.CREATED);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Employee> getEmployeeById(@PathVariable Long id) {
        logger.debug("Request to get employee by id: {}", id);
        Employee employee = employeeService.getEmployeeById(id);
        return new ResponseEntity<>(employee, HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity<List<Employee>> getAllEmployees() {
        logger.debug("Request to get all employees");
        List<Employee> employees = employeeService.getAllEmployees();
        return new ResponseEntity<>(employees, HttpStatus.OK);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employeeDetails) {
        logger.debug("Request to update employee with id: {}", id);
        Employee updatedEmployee = employeeService.updateEmployee(id, employeeDetails);
        return new ResponseEntity<>(updatedEmployee, HttpStatus.OK);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteEmployee(@PathVariable Long id) {
        logger.debug("Request to delete employee with id: {}", id);
        employeeService.deleteEmployee(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

Explanation

  • Logger Initialization: A logger is created using LoggerFactory.getLogger().
  • Logging Statements: Various log levels (DEBUG, INFO, WARN, ERROR) are used to log messages at different points in the code.

Using Different Logging Frameworks

Log4j2

To use Log4j2 instead of Logback, add the following dependencies to your pom.xml file:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

Example Configuration for Log4j2

Create a log4j2.xml file in the src/main/resources directory:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <File name="File" fileName="logs/app.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="File" />
        </Root>
        <Logger name="com.example" level="debug" additivity="false">
            <AppenderRef ref="Console" />
            <AppenderRef ref="File" />
        </Logger>
    </Loggers>
</Configuration>

Example: Logging in Employee Management Project

Project Structure

com.example.employeemanagement
├── config
├── controller
│   └── EmployeeController.java
├── dto
├── exception
├── model
│   └── Employee.java
├── repository
│   └── EmployeeRepository.java
├── service
│   ├── EmployeeService.java
│   ├── impl
│   │   └── EmployeeServiceImpl.java
├── util
├── EmployeeManagementApplication.java
src/main/resources
├── application.properties
├── log4j2.xml

application.properties

logging.level.root=WARN
logging.level.com.example=DEBUG

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <File name="File" fileName="logs/app.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="File" />
        </Root>
        <Logger name="com.example" level="debug" additivity="false">
            <AppenderRef ref="Console" />
            <AppenderRef ref="File" />
        </Logger>
    </Loggers>
</Configuration>

EmployeeController.java

package com.example.employeemanagement.controller;

import com.example.employeemanagement.model.Employee;
import com.example.employeemanagement.service.EmployeeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

    private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);

    @Autowired
    private EmployeeService employeeService;

    @PostMapping
    public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) {
        logger.debug("Request to save employee: {}", employee);
        Employee savedEmployee = employeeService.saveEmployee(employee);
        return new ResponseEntity<>(savedEmployee, HttpStatus.CREATED);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Employee> getEmployeeById(@PathVariable Long id) {
        logger.debug("Request to get employee by id: {}", id);
        Employee employee = employeeService.getEmployeeById(id);
        return new ResponseEntity<>(employee, HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity<List<Employee>> getAllEmployees() {
        logger.debug

("Request to get all employees");
        List<Employee> employees = employeeService.getAllEmployees();
        return new ResponseEntity<>(employees, HttpStatus.OK);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employeeDetails) {
        logger.debug("Request to update employee with id: {}", id);
        Employee updatedEmployee = employeeService.updateEmployee(id, employeeDetails);
        return new ResponseEntity<>(updatedEmployee, HttpStatus.OK);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteEmployee(@PathVariable Long id) {
        logger.debug("Request to delete employee with id: {}", id);
        employeeService.deleteEmployee(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

Conclusion

In this chapter, we explored how to implement logging in a Spring Boot application using the Employee Management Project as an example. We discussed the benefits of logging, how to set up logging in Spring Boot, configure log levels, and use different logging frameworks. Proper logging is essential for debugging, monitoring, auditing, and maintaining your application, making it a critical aspect of any robust Spring Boot application.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top