Structuring Monitoring Data in Monolithic Applications With Namespaces
Tags: devops, monitoring, architecture
Published: 2020-12-15 15:39:11

## What Are Namespaces?

Everything that happens in an AppSignal-monitored application is logged under a namespace. Namespaces work like folders, grouping events, issues, and monitoring data into manageable chunks.

By default, every application starts with three default namespaces: `web`, `background`, and `frontend`.

-   The web namespace holds all your HTTP requests. In MVC-oriented frameworks such as Rails or Sinatra, this includes controller actions.
-   The background namespace holds activity from background jobs, libraries, and tasks.
-   The frontend namespace logs the events sent by the [AppSignal for JavaScript](https://docs.appsignal.com/front-end/) integration.

AppSignal maps incoming events using built-in per-application and per-integration rules. However, you can change these mappings at any time and even create new namespaces to model your application structure.

## Trying Out Namespaces in Ruby

Let’s try out namespaces on a Ruby on Rails (ROR) application. After creating a fresh Rails project with `rails new` and setting up the [rails integration](https://docs.appsignal.com/ruby/integrations/rails.html), you’ll find the `web` namespace in your dashboard.

![Dashboard showing web namespace](https://blog.appsignal.com/images/blog/2020-11/img/web1.png)

AppSignal shows the namespace as soon as it receives transactions from any of the controllers.

![Most recent actions. Shows controller events.](https://blog.appsignal.com/images/blog/2020-11/img/web1-controllers.png)

The rest of the default namespaces won’t appear until there is some activity in them. Let’s add something in the background namespace to make things more interesting. This is how the dashboard looks after adding [Sidekiq](https://sidekiq.org/) to the project (check the code in [examples repository](https://github.com/appsignal/appsignal-examples/tree/rails-5+sidekiq)).

![Dashboard showing the background namespace](https://blog.appsignal.com/images/blog/2020-11/img/bg1a.png)

AppSignal assigns the action to the background namespace because it recognizes Sidekiq as a job processor. AppSignal integrates with most of the popular background processors out there, but if yours is omitted, you can always [add instrumentation](https://docs.appsignal.com/ruby/instrumentation/background-jobs.html) to your jobs manually.

![Last events in the background namespace](https://blog.appsignal.com/images/blog/2020-11/img/bg1b.png)

## Creating Custom Namespaces

On large monolithic applications, the default namespaces can feel too generic. A big website typically serves static content, dynamic pages, API endpoints, among other web services. Most of this would all end up on the `web` namespace.

Also, every part of the application has a different priority. A login page problem is a lot more urgent than one in the internal administration panel. Yet AppSignal treats all issues within a namespace as equal. When there is a lot of activity, it can be hard to identify the most critical issues.

So, we should organize namespaces by priority and areas of responsibility. Then we can attach separate notification policies and alert only the interested parties. Following this reasoning, we could create custom namespaces for the `login_page`, `api_endpoints`, and `admin_panel`.

![Custom namespaces let us create fine-grained zones for the application](https://blog.appsignal.com/images/blog/2020-11/img/namespace-comparison.png)

To create a [new namespace in Ruby](https://docs.appsignal.com/guides/namespaces.html), we’ll use `Appsignal.set_namespace`. Take a look at the following code, which creates a job in a namespace called `urgent_background`:

``` ruby
class FetchPricesWorker
    include Sidekiq::Worker

    def perform
        Appsignal.set_namespace("urgent_background")

        # worker code ...

    end
end
```

Once we made this change and restarted the app, these new jobs will appear in the newly-created namespace:

![Dashboard showing the urgent\_background namespace](https://blog.appsignal.com/images/blog/2020-11/img/ubg1a.png)

We can confirm that the actual job has been logged by checking the action name in the dashboard:

![Last events in the urgent\_background namespace](https://blog.appsignal.com/images/blog/2020-11/img/ubg1b.png)

Custom namespaces also work in [all integrations](https://docs.appsignal.com/guides/namespaces.html).

## Ignoring Namespaces

Another benefit of custom namespaces is that they let us disregard events from parts of the application we don’t care about. For instance, we may choose to ignore events from the `admin_panel` completely.

Ignoring a namespace takes three steps:

1.  Assign the parts we don’t want to monitor to a custom namespace.
2.  Configure the integration to ignore the namespace.
3.  Restart your app.

For Ruby, add the [ignore\_namespaces](https://docs.appsignal.com/ruby/instrumentation/namespaces.html#ignore-by-namespace) option in the AppSignal config file:

``` ruby
production:
  ignore_namespaces:
    - "admin_panel"
```

Ignoring a namespace skips all the transaction and span data at the source. Custom metric data is still reported.

The Elixir and JavaScript integrations have similar options. For more details check the [ignoring namespaces guide](https://docs.appsignal.com/guides/filter-data/ignore-namespaces.html).

## Namespaces for Monolithic Applications

Now that we know how namespaces work, let’s examine a few ways we can use them to partition a monolithic application.

While there are no set rules, partitioning boils down to two strategies. You may choose one of them or a mix of both as a starting point:

- **By role**: we assign namespaces to functional or logical units within the project. Thus, we may find it sensible to define namespaces such as `billing`, `sign_in` or `sign_up`, `admin_panel`, and `homepage`. One glance at the AppSigal dashboard and you will understand what’s going on in each part of the application. This approach works well when the code can be nicely broken up by clear boundaries.
- **By severity**: here we use namespaces as a prioritizing device. It’s up to you to establish which parts of the code are `critical`, `important`, `medium`, or `low`. This approach lets you immediately sort out what problems you want to address first.


Suppose that we have a controllers that handle user sign in and registration. When choosing to partition by role, we could map them to the `user_login` namespace.

```ruby
# in Rails we use before_action callback to change
# the namespace before the request starts
class LoginController < ApplicationController
    before_action :set_appsignal_namespace

    def set_appsignal_namespace
        # Sets the namespace
        Appsignal.set_namespace("user_login")
    end

    # controller actions ...
end
```

But if you prefer using priority namespaces, a controller in charge of billing would probably go in the `critical` namespace.

```ruby
class BillingPageController < ApplicationController
    before_action :set_appsignal_namespace

    def set_appsignal_namespace
        Appsignal.set_namespace("critical")
    end
end
```

Controllers that inherit from these share the same namespace as their parents:

```ruby
# any controllers that inherit from LoginController
# are also part of the "user_login" namespace
class RegistrationController < LoginController

    # there’s no need for before_action here
    # this controller already reports to the parent’s namespace

end
```

As we’ve seen, jobs and tasks are automatically assigned to the `background` namespace. Whenever possible, we should assign them into more specific ones. For instance, a database cleanup job could go into the `database` namespace, like this:

```ruby
class ActiveJobDatabaseCleanupJob < ActiveJob::Base
  queue_as :default

  def perform(argument = nil, options = {})
    Appsignal.set_namespace("database")
```

Priorities also work for jobs. We could assign unimportant tasks to `low` for instance, as in this Rake task:

```ruby
task :unimportant_job do

  # Run this rake job in the low namespace
  Appsignal.set_namespace("low")

  # job code ...

end
```

In some cases, you will want to log actions using a manual transaction. You can define the namespace while creating it, like in the following example, which codes a custom mailer job:

```ruby
class Job
    def perform

        # Create a transaction for this job and set the namespace
        transaction = Appsignal::Transaction.create(
            SecureRandom.uuid,
            "mailer",
            Appsignal::Transaction::GenericRequest.new(ENV.to_hash)
        )

        # job code ...

    end
end
```

## Namespaces and Notifications

Not everyone in the team needs to be notified about every problem. Frontend specialists don’t care about background jobs as much as backend developers. Still, they may want to know when there’s a problem in the backend. Backend developers will surely like to be notified of performance issues on the `web` namespace. Namespaces let us route notifications to the right people.

### Setting Up Per-Namespace Notifiers

We can create notification groups that are only active for specific namespaces. For instance, we could send emails for errors in the `web` namespace, or send a message into the \#frontend Slack channel for issues in the `frontend` namespace.

To create per-namespace notification groups, go to App Settings &gt; Notifications &gt; Notifiers and click on **Add Integration**.

![Adding an integration](https://blog.appsignal.com/images/blog/2020-11/img/add-integration.png)

Select one of the integrations and type its name. Choose which type of messages to send and for which namespace. For example, let’s create a Slack notification for the `#frontend` channel.

![slack integration](https://blog.appsignal.com/images/blog/2020-11/img/frontend-slack.png)

While we’re still here, create a second notification for the backend developers:

![New notification group for web](https://blog.appsignal.com/images/blog/2020-11/img/notification-web.png)

You can configure as many notifiers as you need to keep the team up to date with everything that’s happening.

![Notifiers for different parts of the application](https://blog.appsignal.com/images/blog/2020-11/img/notifiers.png)

### Changing Per-Namespace Notifications

When an incident is created, AppSignal will apply a notification policy. This policy is based on the namespace the error comes from. We can define separate policies for each namespace.

To see the [namespace defaults](https://docs.appsignal.com/application/notification-settings.html#organization-and-app-namespace-defaults) for your application, go to [App Settings &gt; Notifications &gt; **Namespace defaults**](https://appsignal.com/redirect-to/app?to=notifications).

![Namespace defaults for web, background and urgent\_background](https://blog.appsignal.com/images/blog/2020-11/img/namespace-defaults.png)

Here, you’ll find options to customize error and performance notifications for every namespace:

-   **Every occurrence**: sends notifications every time an incident is triggered, with a 5-minute cooldown.
-   **First on deploy**: notifies you of the first error after deploying the application.
-   **First after close**: sends a notification the first time a closed issue is reopened.
-   **Never notify**: disables notifications altogether.

### Creating Per-Namespace Triggers

Triggers tell AppSignal to create an incident and send notifications when a metric goes over or below a predefined value. Since different parts of an application may have different thresholds, we should create separate triggers for each namespace. The classic example is a trigger that alerts us when throughput is too low in the `web` namespace.

To create a trigger, go to [Anomaly Detection &gt; Triggers](https://appsignal.com/redirect-to/app?to=triggers), and click on **Add your first trigger**.

Select an Actions trigger type on the left menu and choose the relevant namespace. Then, set the thresholds that trigger the alert.

![Creating a new trigger for the web namespace](https://blog.appsignal.com/images/blog/2020-11/img/create-trigger-web.png)

Here you can also define which groups should be notified. To finalize, click on **Save Trigger**.

![This alert will send a notification to backend developers](https://blog.appsignal.com/images/blog/2020-11/img/create-trigger-web-notify.png)

## Conclusion

Namespaces let make sense of your application’s monitoring data. They are also indispensable for firing notifications and incidents on a fine-grained level, limiting noise, and avoiding false positives.

After checking how custom namespaces work on [Ruby](https://docs.appsignal.com/ruby/instrumentation/namespaces.html), [Node.js](https://docs.appsignal.com/nodejs/tracing/namespaces.html), and [Elixir](https://docs.appsignal.com/elixir/instrumentation/namespaces.html), read these next to continue learning how to use namespaces:

- [Namespaces in AppSignal](https://docs.appsignal.com/application/namespaces.html)
- [Grouping with namespaces](https://docs.appsignal.com/guides/namespaces.html)
- [What's The Difference Between Monitoring Webhooks and Background Jobs](https://blog.appsignal.com/2020/03/25/whats-the-difference-between-monitoring-webhooks-and-background-jobs.html)
- [Gem 2.2 - Custom namespaces!](https://blog.appsignal.com/2017/05/03/gem-2-2.html)

*Our guest author Tomas spent 10 years working at IBM, where he did a bit of everything: development, service delivery, database administration, and cloud engineering. He's now an independent consultant and a technical writer.*