Ruby on Rails Log Levels: Examples and Best Practices

Logging is important in any software development project because it helps to understand how the application is behaving and identify issues when they occur. The errors of an application cannot all be treated in the same way, as they have different levels of importance. Depending on where the error occurs in your application, it can be fatal to a process or just a warning.

To categorize these errors, we use log levels that help to search and filter error messages. Furthermore, log levels can be valuable if you wish to create logs in the development or staging environment without overwhelming your production log with irrelevant data. Depending on the importance of the message you want to log, there are five available log levels in Rails: debug, info, warn, error, fatal, and unknown. Let’s dive deeper into each of them:

DEBUG

At the lowest level of logging, this information is regarding anything a developer cares about and is often used during development or staging to identify and fix issues before an application goes live.

1
2
3
4
5
6
def calculate_price(item)
  Rails.logger.debug "Calculating price for item #{item.id} with discount #{item.discount}"
  price = item.price - item.discount
  Rails.logger.debug "Final price calculated: #{price}"
  return price
end

In this example, this information is useful for developers when debugging the calculate_price method. The logs show the item ID and discount being used in the calculation, as well as the final calculated price.

INFO

Info-level logging is used to track information about an application’s behavior that may be important to end users. This level of logging can be useful to monitor user interactions making it easier to identify potential issues that may affect the user experience.

1
2
3
4
def send_confirmation_email(user)
  # Send confirmation email code
  Rails.logger.info "Confirmation email sent to #{user.email}"
end

This example is indicating that a confirmation email has been sent to the user’s email address.

WARN

This can be valuable for those issues that need to be addressed but do not require immediate action because the application is still functioning correctly.

1
2
3
4
5
6
def process_order(order)
  if order.items.empty?
    Rails.logger.warn "Order #{order.id} has no items"
  end
  # Process order code
end

The level is a warning when an order has no items. While this situation might not be critical, it could indicate an issue with the order processing logic.

ERROR

The error log level is typically used to alert about issues that need to be addressed immediately. These messages indicate that an error has occurred that is preventing the application from functioning normally. For example, you might use the error log level to output a message when a required parameter is missing or when a database query fails.

1
2
3
4
5
6
7
8
9
def divide(a, b)
  begin
    result = a / b
  rescue ZeroDivisionError => e
    Rails.logger.error "Error dividing #{a} by #{b}: #{e.message}"
    result = nil
  end
  return result
end

In this example, the error level is used to log an error message when attempting to divide by zero. This is a critical error that could cause the application to fail if not handled properly.

FATAL

This log level indicates that a catastrophic error has occurred and it has to be addressed immediately. For example, you might use the fatal log level to output a message when a critical system file is missing or when a required library cannot be loaded. These messages indicate that the application has encountered a problem that is so severe that it cannot continue to function.

1
2
3
4
5
6
7
8
def destroy_user(user)
  if user.admin?
    Rails.logger.fatal "Attempted to destroy admin user #{user.id}"
    raise "Cannot destroy admin user"
  else
    # Destroy user code
  end
end

It also raises an exception when attempting to destroy an admin user. This is a serious error that could potentially cause data loss if not handled properly.

UNKNOWN

It may be useful for debugging or troubleshooting when the error does not fit into any specific category. These messages may not provide any immediate value, but they can be useful for identifying patterns or trends over time.

1
2
3
4
5
6
7
def some_method(param)
  if param.nil?
    Rails.logger.unknown "Param is nil, using default value"
    param = "default"
  end
  # Method code
end

This example is used to log a message when a parameter is nil. While this message might not fit neatly into any of the standard log levels, it’s still useful to log the information so developers can understand what’s happening in the code.