Managing Heroku from the Command Line

In this article by Mike Coutermarsh, author of Heroku Cookbook, we will cover the following topics:

  • Viewing application logs
  • Searching logs
  • Installing add-ons
  • Managing environment variables
  • Enabling the maintenance page
  • Managing releases and rolling back
  • Running one-off tasks and dynos
  • Managing SSH keys
  • Sharing and collaboration
  • Monitoring load average and memory usage

(For more resources related to this topic, see here.)

Heroku was built to be managed from its command-line interface. The better we learn it, the faster and more effective we will be in administering our application. The goal of this article is to get comfortable with using the CLI. We'll see that each Heroku command follows a common pattern. Once we learn a few of these commands, the rest will be relatively simple to master.

In this article, we won't cover every command available in the CLI, but we will focus on the ones that we'll be using the most. As we learn each command, we will also learn a little more about what is happening behind the scenes so that we get a better understanding of how Heroku works. The more we understand, the more we'll be able to take advantage of the platform.

Before we start, let's note that if we ever need to get a list of the available commands, we can run the following command:

$ heroku help

We can also quickly display the documentation for a single command:

$ heroku help command_name

Viewing application logs

Logging gets a little more complex for any application that is running multiple servers and several different types of processes. Having visibility into everything that is happening within our application is critical to maintaining it. Heroku handles this by combining and sending all of our logs to one place, the Logplex.

The Logplex provides us with a single location to view a stream of our logs across our entire application. In this recipe, we'll learn how to view logs via the CLI. We'll learn how to quickly get visibility into what's happening within our application.

How to do it…

To start, let's open up a terminal, navigate to an existing Heroku application, and perform the following steps:

  1. First, to view our applications logs, we can use the logs command:

    $ heroku logs
    2014-03-31T23:35:51.195150+00:00 app[web.1]:   Rendered pages/about.html.slim within layouts/application (25.0ms)

    2014-03-31T23:35:51.215591+00:00 app[web.1]:   Rendered layouts/_navigation_links.html.erb (2.6ms)
    2014-03-31T23:35:51.230010+00:00 app[web.1]:   Rendered layouts/_messages.html.slim (13.0ms)
    2014-03-31T23:35:51.215967+00:00 app[web.1]:   Rendered layouts/_navigation.html.slim (10.3ms)
    2014-03-31T23:35:51.231104+00:00 app[web.1]: Completed 200 OK in 109ms (Views: 65.4ms | ActiveRecord: 0.0ms)
    2014-03-31T23:35:51.242960+00:00 heroku[router]: at=info method=GET path=

    Heroku logs anything that our application sends to STDOUT or STDERR. If we're not seeing logs, it's very likely our application is not configured correctly.

  2.  We can also watch our logs in real time. This is known as tailing:

    $ heroku logs --tail

    Instead of --tail, we can also use -t.

    We'll need to press Ctrl + C to end the command and stop tailing the logs.

  3. If we want to see the 100 most recent lines, we can use -n:

    $ heroku logs -n 100

    The Logplex stores a maximum of 1500 lines. To view more lines, we'll have to set up a log storage.

  4. We can filter the logs to only show a specific process type. Here, we will only see logs from our web dynos:

    $ heroku logs -p web
  5. If we want, we can be as granular as showing the logs from an individual dyno. This will show only the logs from the second web dyno:

    $ heroku logs -p web.2
  6. We can use this for any process type; we can try it for our workers if we'd like:

    $ heroku logs -p worker
  7. The Logplex contains more than just logs from our application. We can also view logs generated by Heroku or the API. Let's try changing the source to Heroku to only see the logs generated by Heroku. This will only show us logs related to the router and resource usage:

    $ heroku logs --source heroku
  8. To view logs for only our application, we can set the source to app:

    $ heroku logs --source app
  9. We can also view logs from the API. These logs will show any administrative actions we've taken, such as scaling dynos or changing configuration variables. This can be useful when multiple developers are working on an application:

    $ heroku logs --source api
  10. We can even combine the different flags. Let's try tailing the logs for only our web dynos:

    $ heroku logs -p web --tail
  11. That's it! Remember that if we ever need more information on how to view logs via the CLI, we can always use the help command:

    $ heroku help logs

How it works

Under the covers, the Heroku CLI is simply passes our request to Heroku's API and then uses Ruby to parse and display our logs. If you're interested in exactly how it works, the code is open source on GitHub at https://github.com/heroku/heroku/blob/master/lib/heroku/command/logs.rb.

Viewing logs via the CLI is most useful in situations where we need to see exactly what our application is doing right now. We'll find that we use it a lot around deploys and when debugging issues. Since the Logplex has a limit of 1500 lines, it's not meant to view any historical data. For this, we'll need to set up log drains and enable a logging add-on.

Searching logs

Heroku does not have the built-in capability to search our logs from the command line. We can get around this limitation easily by making use of some other command-line tools.

In this recipe, we will learn how to combine Heroku's logs with Grep, a command-line tool to search text. This will allow us to search our recent logs for keywords, helping us track down errors more quickly.

Getting ready

For this recipe, we'll need to have Grep installed. For OS X and Linux machines, it should already be installed. We can install Grep using the following steps:

  1. To check if we have Grep installed, let's open up a terminal and type the following:

    $ grep
    usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
           [-e pattern] [-f file] [--binary-files=value] [--color=when]
           [--context[=num]] [--directories=action] [--label] [--line-buffered]
           [--null] [pattern] [file ...]
  2. If we do not see usage instructions, we can visit http://www.gnu.org/software/grep/ for the download and installation instructions.

How to do it…

Let's start searching our logs by opening a terminal and navigating to one of our Heroku applications using the following steps:

  1. To search for a keyword in our logs, we need to pipe our logs into Grep. This simply means that we will be passing our logs into Grep and having Grep search them for us. Let's try this now. The following command will search the output of heroku logs for the word error:

    $ heroku logs | grep error
  2. Sometimes, we might want to search for a longer string that includes special characters. We can do this by surrounding it with quotes:

    $ heroku logs | grep "path=/pages/about host"
  3. It can be useful to also see the lines surrounding the line that matched our search. We can do this as well. The next command will show us the line that contains an error as well as the three lines above and below it:

    $ heroku logs | grep error -C 3
  4. We can even search with regular expressions. The next command will show us every line that matches a number that ends with MB. So, for example, lines with 100 MB, 25 MB, or 3 MB will all appear:

    $ heroku logs | grep '\d*MB'

    To learn more about regular expressions, visit http://regex.learncodethehardway.org/.

How it works…

Like most Unix-based tools, Grep was built to accomplish a single task and to do it well. Global regular expression print (Grep) is built to search a set of files for a pattern and then print all of the matches.

Grep can also search anything it receives through standard input; this is exactly how we used it in this recipe. By piping the output of our Heroku logs into Grep, we are passing our logs to Grep as standard input.

See also

Installing add-ons

Our application needs some additional functionality provided by an outside service. What should we do? In the past, this would have involved creating accounts, managing credentials, and, maybe, even bringing up servers and installing software. This whole process has been simplified by the Heroku add-on marketplace.

For any additional functionality that our application needs, our first stop should always be Heroku add-ons. Heroku has made attaching additional resources to our application a plug-and-play process. If we need an additional database, caching, or error logging, they can be set up with a single command.

In this recipe, we will learn the ins and outs of using the Heroku CLI to install and manage our application's add-ons.

How to do it...

To begin, let's open a terminal and navigate to one of our Heroku applications using the following steps:

  1. Let's start by taking a look at all of the available Heroku add-ons. We can do this with the addons:list command:

    $ heroku addons:list

    There are so many add-ons that viewing them through the CLI is pretty difficult. For easier navigation and search, we should take a look at https://addons.heroku.com/.

  2. If we want to see the currently installed add-ons for our application, we can simply type the following:

    $ heroku addons
    === load-tester-rails Configured Add-ons
    heroku-postgresql:dev       HEROKU_POSTGRESQL_MAROON
    heroku-postgresql:hobby-dev HEROKU_POSTGRESQL_ONYX
    librato:development
    newrelic:stark

    Remember that for any command, we can always add --app app_name to specify the application.

  3. Alternatively, our application's add-ons are also listed through the Heroku Dashboard available at https://dashboard.heroku.com.

    Heroku Cookbook

  4. The installation of a new add-on is done with addons:add. Here, we are going to install the error logging service, Rollbar:

    $ heroku addons:add rollbar
    heroku addons:add rollbar
    Adding rollbar on load-tester-rails... done, v22 (free)
    Use `heroku addons:docs rollbar` to view documentation.
  5. We can quickly open up the documentation for an add-on with addons:docs:

    $ heroku addons:docs rollbar
  6. Removing an add-on is just as simple. We'll need to type our application name to confirm. For this example, our application is called load-tester-rails:

    $ heroku addons:remove rollbar
    !   WARNING: Destructive Action
    !   This command will affect the app: load-tester-rails
    !   To proceed, type "load-tester-rails" or re-run this command with --confirm load-tester-rails

    > load-tester-rails
    Removing rollbar on load-tester-rails... done, v23 (free)
  7. Each add-on comes with different tiers of service. Let's try upgrading our rollbar add-on to the starter tier:

    $ heroku addons:upgrade rollbar:starter
    Upgrading to rollbar:starter on load-tester-rails... done, v26 ($12/mo)
    Plan changed to starter
    Use `heroku addons:docs rollbar` to view documentation.
  8. Now, if we want, we can downgrade back to its original level with addons:downgrade:

    $ heroku addons:downgrade rollbar
    Downgrading to rollbar on load-tester-rails... done, v27 (free)
    Plan changed to free
    Use `heroku addons:docs rollbar` to view documentation.
  9. If we ever forget any of the commands, we can always use help to quickly see the documentation:

    $ heroku help addons

    Some add-ons might charge you money. Before continuing, let's double check that we only have the correct ones enabled, using the $ heroku addons command.

How it works…

Heroku has created a standardized process for all add-on providers to follow. This ensures a consistent experience when provisioning any add-on for our application.

It starts when we request the creation of an add-on. Heroku sends an HTTP request to the provider, asking them to provision an instance of their service. The provider must then respond to Heroku with the connection details for their service in the form of environment variables. For example, if we were to provision Redis To Go, we will get back our connection details in a REDISTOGO_URL variable:

REDISTOGO_URL: redis://user:pass@server.redistogo.com:9652

Heroku adds these variables to our application and restarts it. On restart, the variables are available for our application, and we can connect to the service using them. The specifics on how to connect using the variables will be in the add-ons documentation. Installation will depend on the specific language or framework we're using.

See also

Managing environment variables

Our applications will often need access to various credentials in the form of API tokens, usernames, and passwords for integrations with third-party services. We can store this information in our Git repository, but then, anyone with access to our code will also have a copy of our production credentials. We should instead use environment variables to store any configuration information for our application. Configuration information should be separate from our application's code and instead be tied to the specific deployment of the application.

Changing our application to use environment variables is simple. Let's look at an example in Ruby; let's assume that we currently have secret_api_token defined in our application's code:

secret_api_token = '123abc'

We can remove the token and replace it with an environment variable:

secret_api_token = ENV['SECRET_TOKEN']

In addition to protecting our credentials, using environment variables makes our application more configurable. We'll be able to quickly make configuration changes without having to change code and redeploy.

The terms "configuration variable" and "environment variable" are interchangeable. Heroku usually uses "configuration" due to how tightly the variables are coupled with the state of the application.

How to do it...

Heroku makes it easy to set our application's environment variables through the config command. Let's launch a terminal and navigate to an existing Heroku project to try it out, using the following steps:

  1. We can use the config command to see a list of all our existing environment variables:

    $ heroku config
  2. To view only the value of a specific variable, we can use get:

    $ heroku config:get DATABASE_URL
  3. To set a new variable, we can use set:

    $ heroku config:set VAR_NAME=var_value
    Setting config vars and restarting load-tester-rails... done, v28
    VAR_NAME: var_value
  4. Each time we set a config variable, Heroku will restart our application. We can set multiple values at once to avoid multiple restarts:

    $ heroku config:set SECRET=value SECRET2=value
    Setting config vars and restarting load-tester-rails... done, v29
    SECRET: value
    SECRET2: value
  5. To delete a variable, we use unset:

    $ heroku config:unset SECRET
    Unsetting SECRET and restarting load-tester-rails... done, v30
  6. If we want, we can delete multiple variables with a single command:

    $ heroku config:unset VAR_NAME SECRET2
    Unsetting VAR_NAME and restarting load-tester-rails... done, v31
    Unsetting SECRET2 and restarting load-tester-rails... done, v32

    Heroku tracks each configuration change as a release. This makes it easy for us to roll back changes if we make a mistake.

How it works…

Environment variables are used on Unix-based operating systems to manage and share configuration information between applications. As they are so common, changing our application to use them does not lock us into deploying only to Heroku.

Heroku stores all of our configuration variables in one central location. Each change to these variables is tracked, and we can view the history by looking through our past releases. When Heroku spins up a new dyno, part of the process is taking all of our configuration settings and setting them as environment variables on the dyno. This is why whenever we make a configuration change, Heroku restarts our dynos.

As configuration variables are such a key part of our Heroku application, any change to them will also be included in our Heroku logs.

See also

Enabling the maintenance page

Occasionally, we will need to make changes to our application that requires downtime. The proper way to do this is to put up a maintenance page that displays a friendly message and respond to all the incoming HTTP requests with a 503 Service Unavailable status.

Doing this will keep our users informed and also avoid any negative SEO effects. Search engines understand that when they receive a 503 response, they should come back later to recrawl the site. If we didn't use a maintenance page and our application returned a 404 or 500 errors instead, it's possible that a search engine crawler might remove the page from their index.

How to do it...

Let's open up a terminal and navigate to one of our Heroku projects to begin with, using the following steps:

  1. We can view if our application's maintenance page is currently enabled with the maintenance command:

    $ heroku maintenance
    off
  2. Let's try turning it on. This will stop traffic from being routed to our dynos and show the maintenance page as follows:

    $ heroku maintenance:on
    Enabling maintenance mode for load-tester-rails... done
  3. Now, if we visit our application, we'll see the default Heroku maintenance page:

    Heroku Cookbook

  4. To disable the maintenance page and resume sending users to our application, we can use the maintenance:off command:

    $ heroku maintenance:off
    Disabling maintenance mode for load-tester-rails... done

Managing releases and rolling back

What do we do if disaster strikes and our newly released code breaks our application? Luckily for us, Heroku keeps a copy of every deploy and configuration change to our application. This enables us to roll back to a previous version while we work to correct the errors in our latest release.

Heads up! Rolling back only affects application code and configuration variables. Add-ons and our database will not be affected by a rollback.

In this recipe, we will learn how to manage our releases and roll back code from the CLI.

How to do it...

In this recipe, we'll view and manage our releases from the Heroku CLI, using the releases command. Let's open up a terminal now and navigate to one of our Heroku projects by performing the following steps:

  1. Heroku tracks every deploy and configuration change as a release. We can view all of our releases from both the CLI and the web dashboard with the releases command:

    $ heroku releases
    === load-tester-rails Releases
    v33 Add WEB_CON config vars coutermarsh.mike@gmail.com 2014/03/30 11:18:49 (~ 5h ago)
    v32 Remove SEC config vars       coutermarsh.mike@gmail.com 2014/03/29 19:38:06 (~ 21h ago)
    v31 Remove VAR config vars     coutermarsh.mike@gmail.com 2014/03/29 19:38:05 (~ 21h ago)
    v30 Remove config vars       coutermarsh.mike@gmail.com 2014/03/29 19:27:05 (~ 21h ago)
    v29 Deploy 9218c1c vars coutermarsh.mike@gmail.com 2014/03/29 19:24:29 (~ 21h ago)
  2. Alternatively, we can view our releases through the Heroku dashboard. Visit https://dashboard.heroku.com, select one of our applications, and click on Activity:

    Heroku Cookbook

  3. We can view detailed information about each release using the info command. This shows us everything about the change and state of the application during this release:

    $ heroku releases:info v33
    === Release v33
    Addons: librato:development
           newrelic:stark
           rollbar:free
           sendgrid:starter
    By:     coutermarsh.mike@gmail.com
    Change: Add WEB_CONCURRENCY config vars
    When:   2014/03/30 11:18:49 (~ 6h ago)
    === v33 Config Vars
    WEB_CONCURRENCY: 3
  4. We can revert to the previous version of our application with the rollback command:

    $ heroku rollback
    Rolling back load-tester-rails... done, v32
    !   Warning: rollback affects code and config vars; it doesn't add or remove addons. To undo, run: heroku rollback v33

    Rolling back creates a new version of our application in the release history.

  5. We can also specify a specific version to roll back to:

    $ heroku rollback v30
    Rolling back load-tester-rails... done, v30

    The version we roll back to does not have to be an older version. Although it sounds contradictory, we can also roll back to newer versions of our application.

How it works…

Behind the scenes, each Heroku release is tied to a specific slug and set of configuration variables. As Heroku keeps a copy of each slug that we deploy, we're able to quickly roll back to previous versions of our code without having to rebuild our application.

For each deploy release created, it will include a reference to the Git SHA that was pushed to master. The Git SHA is a reference to the last commit made to our repository before it was deployed. This is useful if we want to know exactly what code was pushed out in that release.

On our local machine, we can run the $ git checkout git-sha-here command to view our application's code in the exact state it was when deployed.

Running one-off tasks and dynos

In more traditional hosting environments, developers will often log in to servers to perform basic administrative tasks or debug an issue. With Heroku, we can do this by launching one-off dynos. These are dynos that contain our application code but do not serve web requests.

For a Ruby on Rails application, one-off dynos are often used to run database migrations or launch a Rails console.

How to do it...

In this recipe, we will learn how to execute commands on our Heroku applications with the heroku run command. Let's launch a terminal now to get started with the following steps:

  1. To have Heroku start a one-off dyno and execute any single command, we will use heroku run. Here, we can try it out by running a simple command to print some text to the screen:

    $ heroku run echo "hello heroku"
    Running `echo "hello heroku"` attached to terminal... up, run.7702
    "hello heroku"

    One-off dynos are automatically shut down after the command has finished running.

  2. We can see that Heroku is running this command on a dyno with our application's code. Let's run ls to see a listing of the files on the dyno. They should look familiar:

    $ heroku run ls
    Running `ls` attached to terminal... up, run.5518
    app bin config config.ru db Gemfile Gemfile.lock lib log Procfile     public Rakefile README README.md tmp
  3. If we want to run multiple commands, we can start up a bash session. Type exit to close the session:

    $ heroku run bash
    Running `bash` attached to terminal... up, run.2331
    ~ $ ls
    app bin config config.ru db Gemfile Gemfile.lock      lib log Procfile public Rakefile README README.md tmp
    ~ $ echo "hello"
    hello
    ~ $ exit
    exit
  4. We can run tasks in the background using the detached mode. The output of the command goes to our logs rather than the screen:

    $ heroku run:detached echo "hello heroku"
    Running `echo hello heroku` detached... up, run.4534
    Use `heroku logs -p run.4534` to view the output.
  5. If we need more power, we can adjust the size of the one-off dynos. This command will launch a bash session in a 2X dyno:

    $ heroku run --size=2X bash
  6. If we are running one-off dynos in the detached mode, we can view their status and stop them in the same way we would stop any other dyno:

    $ heroku ps
    === run: one-off processes
    run.5927 (1X): starting 2014/03/29 16:18:59 (~ 6s ago)
    $ heroku ps:stop run.5927

How it works…

When we issue the heroku run command, Heroku spins up a new dyno with our latest slug and runs the command. Heroku does not start our application; the only command that runs is the command that we explicitly pass to it.

One-off dynos act a little differently than standard dynos. If we create one dyno in the detached mode, it will run until we stop it manually, or it will shut down automatically after 24 hours. It will not restart like a normal dyno will.

If we run bash from a one-off dyno, it will run until we close the connection or reach an hour of inactivity.

Managing SSH keys

Heroku manages access to our application's Git repository with SSH keys. When we first set up the Heroku Toolbelt, we had to upload either a new or existing public key to Heroku's servers. This key allows us to access our Heroku Git repositories without entering our password each time.

If we ever want to deploy our Heroku applications from another computer, we'll either need to have the same key on that computer or provide Heroku with an additional one. It's easy enough to do this via the CLI, which we'll learn in this recipe.

How to do it…

To get started, let's fire up a terminal. We'll be using the keys command in this recipe by performing the following steps:

  1. First, let's view all of the existing keys in our Heroku account:

    $ heroku keys
    === coutermarsh.mike@gmail.com Keys
    ssh-rsa AAAAB3NzaC...46hEzt1Q== coutermarsh.mike@gmail.com
    ssh-rsa AAAAB3NzaC...6EU7Qr3S/v coutermarsh.mike@gmail.com
    ssh-rsa AAAAB3NzaC...bqCJkM4w== coutermarsh.mike@gmail.com
  2. To remove an existing key, we can use keys:remove. To the command, we need to pass a string that matches one of the keys:

    $ heroku keys:remove "7Qr3S/v coutermarsh.mike@gmail.com"
    Removing 7Qr3S/v coutermarsh.mike@gmail.com SSH key... done
  3. To add our current user's public key, we can use keys:add. This will look on our machine for a public key (~/.ssh/id_rsa.pub) and upload it:

    $ heroku keys:add
    Found existing public key: /Users/mike/.ssh/id_rsa.pub
    Uploading SSH public key /Users/mike/.ssh/id_rsa.pub… done

    To create a new SSH key, we can run $ ssh-keygen -t rsa.

  4. If we'd like, we can also specify where the key is located if it is not in the default /.ssh/ directory:

    $ heroku keys:add /path/to/key.pub

How it works…

SSH keys are the standard method for password-less authentication. There are two parts to each SSH key. There is a private key, which stays on our machine and should never be shared, and there is a public key, which we can freely upload and share.

Each key has its purpose. The public key is used to encrypt messages. The private key is used to decrypt messages.

When we try to connect to our Git repositories, Heroku's server uses our public key to create an encrypted message that can only be decrypted by our private key. The server then sends the message to our machine; our machine's SSH client decrypts it and sends the response to the server. Sending the correct response successfully authenticates us.

SSH keys are not used for authentication to the Heroku CLI. The CLI uses an authentication token that is stored in our ~/.netrc file.

Sharing and collaboration

We can invite collaborators through both the web dashboard and the CLI. In this recipe, we'll learn how to quickly invite collaborators through the CLI.

How to do it…

To start, let's open a terminal and navigate to the Heroku application that we would like to share, using the following steps:

  1. To see the current users who have access to our application, we can use the sharing command:

    $ heroku sharing
    === load-tester-rails Access List
    coutermarsh.mike@gmail.com owner
    mike@form26.com             collaborator
  2. To invite a collaborator, we can use sharing:add:

    $ heroku sharing:add coutermarshmike@gmail.com
    Adding coutermarshmike@gmail.com to load-tester-rails as collaborator... done

    Heroku will send an e-mail to the user we're inviting, even if they do not already have a Heroku account.

  3. If we'd like to revoke access to our application, we can do so with sharing:remove:
    $ heroku sharing:remove coutermarshmike@gmail.com
    Removing coutermarshmike@gmail.com from load-tester-rails collaborators... done

How it works…

When we add another collaborator to our Heroku application, they are granted the same abilities as us, except that they cannot manage paid add-ons or delete the application. Otherwise, they have full control to administrate the application. If they have an existing Heroku account, their SSH key will be immediately added to the application's Git repository.

See also

Monitoring load average and memory usage

We can monitor the resource usage of our dynos from the command line using the log-runtime-metrics plugin. This will give us visibility into the CPU and memory usage of our dynos. With this data, we'll be able to determine if our dynos are correctly sized, detect problems earlier, and determine whether we need to scale our application.

How to do it…

Let's open up a terminal; we'll be completing this recipe with the CLI by performing the following steps:

  1. First, we'll need to install the log-runtime-metrics plugin via the CLI. We can do this easily through heroku labs:

    $ heroku labs:enable log-runtime-metrics
  2. Now that the runtime metrics plugin is installed, we'll need to restart our dynos for it to take effect:

    $ heroku restart
  3. Now that the plugin is installed and running, our dynos' resource usage will be printed to our logs. Let's view them now:

    $ heroku logs
    heroku[web.1]: source=web.1 dyno=heroku.21 sample#load_avg_1m=0.00 sample#load_avg_5m=0.00
    heroku[web.1]: source=web.1 dyno=heroku.21
    sample#memory_total=105.28MB sample#memory_rss=105.28MB
    sample#memory_cache=0.00MB
    sample#memory_swap=0.00MB
    sample#memory_pgpgin=31927pages
    sample#memory_pgpgout=4975pages
  4. From the logs, we can see that for this application, our load average is 0, and this dyno is using a total of 105 MB of RAM.

How it works…

Now that we have some insight into how our dynos are using resources, we need to learn how to interpret these numbers. Understanding the utilization of our dynos will be key for us if we ever need to diagnose a performance-related issue.

In our logs, we will now see load_avg_1m and load_avg_5m. This is our dynos' load average over a 1-minute and 5-minute period. The timeframes are helpful in determining whether we're experiencing a brief spike in activity or it is more sustained. Load average is the amount of total computational work that the CPU has to complete. The 1X and 2X dynos have access to four virtual cores. A load average of four means that the dynos' CPU is fully utilized. Any value above four is a warning sign that the dyno might be overloaded, and response times could begin to suffer. Web applications are typically not CPU-intensive applications, seeing low load averages for web dynos should be expected. If we start seeing high load averages, we should consider either adding more dynos or using larger dynos to handle the load.

Our memory usage is also shown in the logs. The key value that we want to keep track of is memory_rrs, which is the total amount of RAM being utilized by our application. It's best to keep this value no higher than 50 to 70 percent of the total RAM available on the dyno. For a 1X dyno with 512 MB of memory, this would mean keeping our memory usage no greater than 250 to 350 MB. This allows our application's room to grow under load and helps us avoid any memory swapping. Seeing values above 70 percent is an indication that we need to either adjust our application's memory usage or scale up.

Memory swap occurs when our dyno runs out of RAM. To compensate, our dyno will begin using its hard drive to store data that will normally be stored in RAM. For any web application, any swap should be considered evil. This value should always be zero. If our dyno starts swapping, we can expect that it will significantly slow down our application's response times. Seeing any swap is an immediate indication that we must either reduce our application's memory consumption or start scaling.

See also

    • Load average and memory usage are particularly useful when performing application load tests.

Summary

In this article, we learned various commands on how to view application logs, installing add-ons, viewing application logs, enabling the maintenance page, managing SSH keys, sharing and collaboration, and so on.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Heroku Cookbook

Explore Title