Heroku Logs – The Complete Guide

Platforms like Heroku give you the freedom to focus on building great applications rather than getting lost setting up and maintaining infrastructure. Heroku provides many great features to achieve this, and the one we will focus on today is logging. This tutorial, will uncover best practices for making the most of Heroku logs and integrating them with Coralogix logging. To better understand how logs are generated, we’ll begin by revisiting the fundamentals of Heroku’s architecture. Feel free to skip to the logging section if you are already familiar with those.

Heroku Logs – Basic concepts 

Cheat Sheet

CommandDescription
heroku logs -t
heroku logs -tp router
(-tail)  real-time log stream
(-tp) router log entries only
heroku logs -n 200specify the number of log entries to display.
heroku logs –d router(–dyno) filter to specify dyno, in this example, router
heroku logs –source app(–source) filter to specify source, in this example, app logs.
heroku drains –jsonobtain the drain tokens for your app’s log drains
heroku releases heroku releases:info v19
heroku rollback
View release history View info on a version (here v19)
Rollback a release
heroku addons:create coralogix:testAdd a log analytics add-on

Heroku Basic Architecture

Applications deployed on Heroku live in lightweight Linux containers called Dynos. Dynos can range from holding simple web apps to complex enterprise systems. The scalability of these containers, vertically and horizontally, is one of the flexible aspects of Heroku that developers leverage. They include the following types:

  • Web Dynos are web processes that receive HTTP traffic from routers.
  • Worker Dynos may be any non-web-type process type used for background processes, queueing, and cron jobs.
  • One-off dynos are ad-hoc or temporary dynos that can run as attached or detached from local machines. One-off Dynos are typically used for DB migrations, console sessions, background jobs, and other administrative tasks, such as processes started by the Heroku Scheduler.

Heroku Logging

Heroku provides a tool called Logplex, that collates and routes log streams from all running processes into a single channel. Logs from that channel can then be sent through a Drain to a third-party logging add-on that specializes in log monitoring, such as Coralogix.

Heroku Runtime Logs

The Heroku platform maintains four categories of logs for deployed apps. For example, log entries generated by a dependency-related error thrown when running an app are separated from messages about deploying new code. The four categories are as follows:

  • App logs – Entries generated when an app runs and throws an exception, for example, for a missing dependency such as an inaccessible library. The CLI log filter is:  –source app.
  • API logs – Developer administrative actions (such as deploying new code) trigger entries to the API log. Scaling processes and toggling maintenance modes are other examples in this category. These logs can set progressive delays in retrying an API call when one fails. API logs can also be used to catch authentication failures and issues with push requests. The CLI filter is:  –source app –dyno api
  • System logs – Contain information about hardware systems and system processes, or in other words, infrastructure. A system log entry will be generated when the Heroku platform restarts an app because of an infrastructure issue (e.g., failed HTTP request). The CLI filter to query system log entries is:  –source heroku
  • Add-on logs – Add-on logs are generated by add-ons to the Heroku platform, like Redis Cloud, MongoDB, SendGrid, or Coralogix.

Heroku Build Logs

Heroku build logs are generated by successful and failed builds in your continuous integration and deployment pipelines.
These logs can be accessed in your app’s activity feed on the Heroku dashboard. They can also be configured with a tool like Coralogix to benchmark errors for each build version. 

Log Severity

Log data can be quantified by level of urgency. Here is the standard set of levels used in Heroku logs with examples of events for which Heroku Logplex generates a log entry:

SeverityDescriptionExample
emergencysystem is unusable“Child cannot open lock file. Exiting”
alertImmediate action required“getpwuid: couldn’t determine user name from uid”
criticalThreats to app functionality“socket: Failed to get a socket, exiting child”
errorClient not receiving adequate service“Premature end of script headers”
warningissues which don’t threaten app functioning but may need observation“child process 01 did not exit, sending another SIGHUP”
noticeNormal events which may need monitoring“httpd: caught SIGBUS, attempting to dump core in …”
infoInformational“Server is busy…”
debugLogs normal events for debugging“opening config file …”
trace 1-8For finding functions in code, locating code chunks“proxy: FTP: … ”

View Heroku Logs

Logs can be accessed and viewed from the Heroku platform. After Heroku is installed locally, developers can also use the CLI to view, define, filter, target, and query logs.

The most commonly used CLI command to retrieve logs is:

$ heroku logs

Let’s look at the anatomy of a Heroku log. First, enter the following CLI command to display 200 logs:

$ heroku logs -n 200

Heroku would show 100 lines by default without the -n parameter above. Using the -n, or –num parameter, we can display up to 1500 lines from the log. Here is an example of a typical log entry:

2023-01-02T15:13:02.723498+00:01 heroku[router]: at=info method=GET path="/posts" host=myapp.herokuapp.com" fwd="178.68.87.34" dyno=web.1 connect=1ms service=18ms status=200 bytes=975 2023-09-16T15:13:47.893472+00:00 app[worker.3]: 2 jobs processed at 16.6761 j/s, 0 failed ...

In the above entry, we can see the following information:

  • Timestamp – The precise time when the Dyno generated the log entry, according to the standard RFC5424 format. The default timezone is UTC (see below for how to change the default timezone).
  • Source – web dynos, background workers, and crons generate log entries shown as app. HTTP routers and dyno managers are shown as Heroku.
  • Dyno – In this example, worker #3 is the Dyno, and the Heroku HTTP router is shown as router.
  • Message – contains the content, in this case, the status, which is equal to 200, and the byte length. In practice, the message contents typically require smart analytics apps to assist with interpretation.

The filter is another important CLI parameter. For example, by using the following filter, we can choose to display only the log entries originating from a specific Dyno:

$ heroku logs --dyno

But also logs originating from a specific source, such as our app:

$ heroku logs --source app

Or system logs:

$ heroku logs --source heroku

As mentioned, Heroku uses the UTC time zone for its dynos by default. You can change it, although the recommended approach is to convert to the client’s local timezone when displaying the data.

To check the current timezone:

$ heroku config:get TZ

To change the timezone for Heroku logs:

$ heroku config:add TZ="America/New_York"

Here’s a complete list of supported timezone formats.

Best Practices for Heroku Logging

Although some logging practices will depend on your app’s specificities and the programming languages you use, here are five universal best practices for logging with Heroku: 

  1. Log useful events

Ideally, a Heroku log should contain an entry for every useful event in the behavior of an application. Examples of useful events are:

  • Authentication, Authorization, and Access – These events include successful and failed authentication and authorizations, system access, data access, and application access.
  • Changes – These events include changes to systems or applications, changes to data (creation and destruction), application installation, and changes.
  • Availability –  Availability events include the startup and shutdown of systems and applications, builds and releases, faults and errors that affect application availability, and backup successes and failures.
  • Resources –  Resource issues to log include exhausted resources, exceeded capacities, and connectivity issues.
  • Threats – Some common threats to logs include invalid inputs and security issues known to affect the application.
  1. Be intentional about the data you include

Don’t log sensitive data like passwords, API keys, or other confidential information. If you need to log something for debugging purposes, obfuscate or redact the sensitive parts.

Do include contextual information like requests and session IDs in your logs. This can help you trace a specific request’s lifecycle and troubleshoot issues.

  1. Structure your logs 

Use structured log formats like JSON or key-value pairs to make log entries more machine-readable, as this can simplify log analysis and parsing. You can also use logging libraries or frameworks designed for your programming language, such as Winston for Node.js, Log4j for Java, or Django logging for Python. These libraries provide structured logging and allow you to configure log levels easily.

  1. Use correct log levels

Use different log levels (e.g., DEBUG, INFO, WARN, ERROR) to categorize log messages based on severity. This helps you filter and analyze logs effectively.

  1. Define log retention policies

Define log retention policies to manage log data storage efficiently. Store logs for a reasonable period based on your compliance and debugging needs. Heroku’s retention period is one week, so you should consider adding a logging add-on for production-ready persistence of logs.

Set up a Logging Add-on: Coralogix

To bypass Heroku’s relatively short retention period (1 week) and 1500 log entries history limit, you must either set up an add-on or a custom drain. A logging add-on provides capabilities for managing and analyzing logs, which will help troubleshoot issues, monitor application performance, and derive insights from your log data. It streamlines the log management process, making it an essential tool for maintaining a healthy and reliable application on the Heroku platform.

Setting up an add-on with Heroku is pretty straightforward. Let’s take Coralogix as an example:

You can head to https://elements.heroku.com/addons/coralogix and click ‘Install Coralogix Observability.’ You can also do this straight from your Heroku dashboard by clicking on the ‘Configure add-ons’ option.

Next, you can choose a plan and your Heroku destination app. 

Submit your order, and wait a few seconds for the add-on to be provisioned. From this point, any logs your application generates will feed into Coralogix! To make it better still, you can install the Extension Package for Heroku that includes out-of-the-box Heroku parsing rules, 20+ alerts, and a predefined Kibana dashboard. All you need to do is go to Coralogix Extension Packages and deploy the Heroku Extension Package.

Quick Tips for Heroku Logging with Coralogix

TL;DR: Coralogix released a new addon for Heroku: https://elements.heroku.com/addons/coralogix. In this post we cover best Logging practices, how different cloud providers enable them, what makes Heroku logging special, and how Coralogix utilizes Heroku’s approach to provide it’s 3rd generation logging experience. 

Lost in the Clouds

Widespread cloud hosting opened a world of possibilities for developers, reducing the need to maintain, monitor and scale their own infrastructure, and instead focus on building their applications. When cloud services are working the way you expect, then the ability to not have to worry about what is happening behind the scenes is a liberating one, but alongside this also gives your lack of control and when you experience a problem (and you will), tracing its source can be a challenge. A typical source of information is your log files, but as infrastructure, locations and services constantly shift around the World, where do you look, how do you access them and what should you log that’s relevant to such a setup? In this post, I will mainly focus on Heroku, and compare it’s very different way of handling logging to most other cloud providers.

Logging Best Practices

Even with fully cloud-based applications, most normal rules of logging apply, and following them will make tracing issues in your application easier to identify. Read “The Most Important Things to Log in Your Application Software” and “JAVA logging – how to do it right” for more details, but in summary, these rules are:

  • Enable logging: This sounds like an obvious rule in an article about logging, but double check you have enabled logging before deploying your application and don’t solely rely on your infrastructure logging.
  • Categorize your logs: Especially in a distributed system, the ability to filter logs to particular categories, or error levels such as authorization, access, or critical can help you drill down into a barrage of information.
  • Logs are not only for you: Your logs are useful sources of information for a variety of stakeholders including support and QA engineers, and new programmers on your team. Keep them readable, understandable and clear as to their purpose.
  • Use 3rd party systems: There are dozens and dozens of 3rd party logging tools to help you consolidate and understand your logs better. From open source to SaaS options, you will find a solution that suits your needs.
  • Use standard logging libraries: whether you are writing to file or using a log aggregator, always prefer a standard logging library over doing your own log printing, we ofter see mistakes like using console.log which causes break-lines to be read as separate lines, etc. There are many great logging libraries out there for most languages, prefer them over implementing your own logging. 

Amazon Web Services

In true Amazon fashion, AWS has its own custom solution for logging that integrates well with all aspects of its service but requires learning new tools and processes. CloudWatch Logs aggregates real-time and streamed logs from various AWS services into one convenient location, and adds alerting to CloudTrail based on defined conditions and events. CloudWatch has integrations with about a dozen 3rd party partner services including Splunk and DataDog, but if your provider of choice isn’t on that list then you have to rely on CloudWatch or parse the logs yourself from an S3 bucket.

Microsoft Azure

Azure’s logging offering is comprehensive, offering logging at most levels of the technology stack, in a self-contained monitoring UI. Azure then allows you to take this a step further with log analytics and for larger teams, the Operations Management Suite expands log analytics into an entire operations suite.

Google Compute Engine

Google Compute Engine offers Stackdriver that’s based on the open source fluentd logging layer. If you’re a GCE user, then it’s your best option, with direct connections to Google’s storage and analysis products. Intriguingly it also works with AWS (but not Azure), making it an ideal candidate, if your application runs across multiple clouds (and it should). Stackdriver receives log entries from multiple sources across the GCE stack, including VMs and applications. You can analyze your logs via a semi-searchable GUI, an API, or CLI tool.

Heroku

Heroku takes a different approach to cloud-based application development, shifting the focus from infrastructure to applications. Combined with Heroku’s tools for Docker, Git and CLI workflows, it makes developing applications for testing and production a breeze. However, the ephemeral nature of Heroku makes knowing what’s going on behind the scenes of your application something of a mystery at times.

By default logging consists of using the subcommand heroku logs to view output, and with a variety of parameters to filter the source or dyno (Heroku parlance for an instance), but once you add multiple dynos (which you invariably will as you scale) getting to grips with what’s going on in your logs can be difficult. Filtering the log output is a start, but you need to know where to look before you start looking, and generally, you resort to logs because you’re unsure what the problem is.

To aid the process Heroku offers the ‘Log Drains’ feature to forward raw log output to 3rd party providers, or providers of your own creation. This makes initial log usage harder, but by removing an official logging solution, offer far more flexibility over your specific needs in the longer term.

Coralogix and Heroku

Coralogix has recently released a logging add-on that forwards all Heroku output to a Coralogix account you specify.

provision coralogix on heroku

Or use the CLI with:

heroku addons:create coralogix:test
Then within a few seconds, any logs that your application generates will feed right into Coralogix, ready for use the high scale, high-speed search and analytics that Coralogix offers. Here’s a simple example, that shows that even with a small application generating simple log records, as soon it starts scaling, logs become hard to traverse and understand.

Sample Application

The sample application consists of a Python and Ruby application that randomly generates a cat from the Cat API every 2 seconds and logs the value.

I started with one instance of each, then scaled to three instances, here are the logs using heroku logs one one instance.

one worker sending logs to coralogix

And another example of mixed logs with messages from Heroku, debug messages and errors, already getting confusing.

two workers sending logs to Coralogix

Throw in two more workers and tracking down the source of messages is getting even more confusing. And the sample application has two applications running three workers each.

multiple workers on Coralogix

Let’s use Coralogix instead. You can open the dashboard page, or again use the CLI and see the initial display right after you start sending logs:

CLI: heroku addons:open coralogix

coralogix dashboard

view heroku logs in coralogix

After 24 hours, Coralogix’ Loggregation feature will kick in to automatically cluster log entries and make finding what you need faster and easier. In the screenshot below you can see that Loggregation has identified that despite being ‘random’, the CatAPI repeats itself a lot, outputting the same value over 1,000 times. In this case, it’s not important, but in a mission critical application, this helps you identify patterns clearly.

loggregation on heroku logs

Errors and broken flows are often introduced by new versions and builds of an application. Coralogix’s integration with Heroku includes an integration to Heroku Pipelines and offers an automatic status for new Heroku builds (or tags). Coralogix presents the suspicious and common errors introduced since that build as well as the alerts and anomalies which might be related to the new version release, thus allowing you to pinpoint issues to particular versions and points in time.

Heroku builds status coralogix

new logs created since heroku build

After 5 days of learning, Coralogix will start to send a daily report highlighting new anomalies (errors and critical messages), further helping you identify new errors, and not constantly bombard you with logging noise.

In addition to the machine learning aspect, Coralogix offers the entire set of Logging capabilities, including Log Query, a centralized live tail, user defined alerts to email or slack, and a fully hosted Kibana for data slicing and dashboards creation.

Making Logging Personal

I started this post by highlighting best practices for logging, and many of them focus on making logs work for you and your team. By compelling you to use their own internal solutions, many of the cloud providers can make your logging experience impersonal and unfocused. Whilst logging with Heroku can take extra steps, to begin with, when you get the setup honed, it can result in a logging system that truly works the way you want and helps you see the issues that matter.

Provision the Coralogix addon and start enjoying 3rd generation Log analytics