---
title: Supercharge your Rails logs with tags
teaser: A hidden Rails feature that can level up your debugging game.
tags: rails
author: Justin Toniazzo
published_on: 2024-08-05
---

Logs are a great way to keep an eye on what’s happening in a system. They can provide insight into decisions made, logic paths taken, and results of operations.

As your Rails app grows in size and complexity, however, it can be hard to find what you need amidst the sea of logs. You might even be tempted to remove log statements to reduce noise. But that can come at the expense of reducing visibility into other parts of the app, and make your or your coworker’s lives harder in the future.

## Rails tagged logs

Rails has [a solution](https://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html) for this issue. It allows you to prefix log messages with a tag, making it easier to filter logs to only those you care about right now. Here’s how it works:

```ruby
Rails.logger.tagged("tag") do
  Rails.logger.info("message")
end
```

That will write a log like `[tag] message`.  This is useful in your production logs, but [very helpful locally](https://thoughtbot.com/blog/tail-your-test-logs) as well. If you combine that with `grep` you can easily filter your development log down to just log statements you care about.

```bash
tail -f log/development.log | grep tag
```

This will only print lines that include `tag`.

Here are examples of a few situations where I’ve found adding tags to logs helpful.

## Understanding new code by adding tagged logs

If you’re just getting started learning about a complex new app or system, you can wrap the entrypoint in `Rails.logger.tagged` to get a better idea of type types of operations that task performs. For example if you have a complex job, you can wrap its `perform` method with a tagged log to filter down to just logs written by that job.

```ruby
class MyJob < ApplicationJob
  def perform
    Rails.logger.tagged("MyJob") do
      # ...
    end
  end
end
```

## Using tagged logs to add context

You can add extra information to logs you’re already writing to help you get a better understanding of the environment. Perhaps you have an endpoint that can be accessed by both regular users and admins, but you notice different behavior for each type. By adding that context to your log statements, you can more easily compare and contrast requests in those two situations.

```ruby
class UsersController < ApplicationController
  def update
    Rails.logger.tagged(current_user.admin? ? "Admin" : "User") do
      # ...
    end
  end
end
```

## Tagging logs conditionally

If you pass something that’s `.blank?` (like `nil`, `false`, or `""`) to `Rails.logger.tagged` it won’t add the tag. You can use this to add tags in certain conditions. For example if you have some way of detecting a suspicious request (e.g. a bot or something), tagging requests made by those users could help keep an eye on them.

```ruby
# config/initializers/suspicious_request.rb

class SuspiciousRequest
  def initialize(app)
    @app = app
  end

  def call(env)
    Rails.logger.tagged(tag) do
      @app.call(env)
    end
  end

  private

  def tag = suspicious? ? "Suspicious" : nil

  def suspicious? = true # some real implementation, hopefully 😅
end

# also in config/initializers/suspicious_request.rb
Rails.application.config.middleware.use(SuspiciousRequest)
```

## Using multiple levels of tagged logs

Calls to `Rails.logger.tagged` can be nested. This appends additional tags after the existing ones. So add as many levels of context as you like!

```ruby
Rails.logger.tagged("first") do
  Rails.logger.tagged("second") do
    Rails.logger.info("wow!")
  end
end

# => [first] [second] wow!
```

## Filter through the noise with tagged logs

Adding tags to logs can be a great way of filtering through noisy logs. The extra context can also make it easier to understand the full picture, or call attention to certain messages. Tags are useful not only as a temporary addition to your development code to help you understand a system or investigate a bug, but also useful as long-term additions to your production logs.

Rails has all sorts of built in little goodies like this. I’m constantly discovering new things. With other languages or frameworks you’d have to add a library to do something like this, or build it yourself. But with Rails it’s all built in and there’s a canonical way of doing things. That’s one of the main reasons I like the framework so much, and what keeps me coming back to it year after year.

Want to chat more about maintaining your Rails app? Let's talk about how we can work together at [thoughtbot.com/hire-us](https://thoughtbot.com/hire-us)
