Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Model Context Protocol
    • Vector Database
    • Heroku Inference
      • Inference Essentials
      • AI Models
      • Inference API
      • Quick Start Guides
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Patterns & Best Practices
  • Writing Best Practices For Application Logs

Writing Best Practices For Application Logs

English — 日本語に切り替える

Last updated September 09, 2024

Table of Contents

  • Define which events to log
  • Include pertinent details
  • Exclude sensitive information
  • Use structured logging
  • Log at the correct level
  • Additional Information

Logging is an important data source for troubleshooting issues, business intelligence, and meeting compliance. Logs give records of precisely what your application is doing when.

You can log from anywhere in your app’s code with an output statement. Heroku also aggregates logs from other components of the platform. For more info about logs aggregated from other sources and how logging works, see Logging. This article focuses on best practices for writing logs that your application code generates.

Heroku Enterprise customers with Premier or Signature Success Plans can request in-depth guidance on this topic from the Customer Solutions Architecture (CSA) team. Learn more about Expert Coaching Sessions here or contact your Salesforce account executive.

Define which events to log

Log events that tell the story of how your app is behaving. Always log:

  • Application errors
  • Input and output validation failures
  • Authentication successes and failures
  • Authorization failures
  • Session management failures
  • Privilege elevation successes and failures
  • Other higher-risk events, like data import and export
  • Logging initialization
  • Opt-ins, like terms of service

Consider logging other events that address these use cases:

  • Troubleshooting
  • Monitoring and performance improvement
  • Testing
  • Understanding user behavior
  • Security and auditing

For example, for auditing purposes, log an event whenever a user updates their profile in your app.

Include pertinent details

Heroku’s logging infrastructure records when and where something occurred. It automatically adds to your log output a timestamp and the dyno that a log message came from:

timestamp source[dyno]: message

Add context to the message content, such as:

  • What action was performed
  • Who performed the action
  • Why a failure occurred
  • Remediation information when possible for WARN and ERROR messages
  • HTTP request ID - see HTTP Request IDs for more info.

The Open Web Application Security Project (OWASP) has a larger list of suggested event attributes. Choose attributes that provide just enough meaningful context.

Here is an example of not enough context:

2019-06-20T17:21:00.002899+00:00 app[web.1]: INFO: Address removed.

This message shows the event time and location (web.1 dyno), but only a general description of what happened.

Just enough context:

2019-06-20T17:21:00.002899+00:00 app[web.1]: INFO: Address removed by customer. {"addressid":18344857, "customerid":50333}

This message includes which customer removed which record.

Some logging add-on providers limit individual message size. Check your logging add-on provider’s documentation for size limitations.

Exclude sensitive information

In the Common Runtime, we expand the values of the config vars referenced in your code commands before sending the output to your logs for audit purposes. Avoid using direct references to sensitive environment variables where your app code writes to standard out (stdout) or standard error (stderr).

Keep security and compliance requirements in mind:

  • Don’t emit sensitive Personal Identifiable Information (PII).
  • Don’t emit encryption keys or secrets to your logs.
  • Ensure that your company’s privacy policy covers your log data.
  • Ensure that your logging add-on provider meets your compliance needs.
  • Ensure that you meet data residency requirements.

Unless you are using Private Space Logging with a Shield Private Space, all log data passes through Heroku’s logging infrastructure located in the U.S. region. For more info, see Private Space Logging and Logplex.

Use structured logging

Human readable logs are helpful, but structured logs add value, especially as an application’s logs become more complex or as request throughput increases. Structured logging provides a well-defined format for your log entries so you can more easily parse, query, and process them for analytics.

The structure of log entries from the Heroku platform is called logfmt, where each line consists of a single level of densely packed key/value pairs. This format is human readable and fairly easy to parse, if needed.

JSON is the de facto standard for structured logging, but consider using key=value pairs, XML, or another format for your application logs. Review the supported formats that your add-on provider can automatically parse.

Consider these unstructured log entries:

2019-06-20T17:21:00.002899+00:00 app[email-wrkr.1]: DEBUG: Fetching mailing list 14777
2019-06-20T17:22:00.000098+00:00 app[email-wrkr.1]: DEBUG: User 3654 opted out

Changing these entries to use structured JSON results in:

2019-06-20T17:21:00.002899+00:00 app[email-wrkr.1]: DEBUG: Fetching mailing list {"listid":14777}
2019-06-20T17:22:00.000098+00:00 app[email-wrkr.1]: DEBUG: User opted out {"userid":3654}

The consistent format of these log messages makes it straightforward for your chosen log drain to parse them, extract the JSON metadata, and make it available for searching and filtering.

Log at the correct level

Record events at the correct level.

Log levels:

  • INFO - Informational messages that do not indicate any fault or error.
  • WARN - Indicates that there is a potential problem, but with no user experience impact.
  • ERROR - Indicates a serious problem, with some user experience impact.
  • FATAL - Indicates fatal errors, user experience is majorly impacted.
  • DEBUG - Used for debugging. The messaging targets specifically the app’s developers.

For example, logging an ERROR as INFO will interfere with troubleshooting. Also, if an exception is expected behavior and does not indicate degraded behavior, consider logging that exception as INFO instead of ERROR. For more details about log levels, see the Art of Logging.

To ensure you are logging at the correct level: - Review your logging framework settings, especially if you didn’t set the log level. - Document and review exceptions to determine whether to log as INFO or ERROR. - Check other log messages to ensure they are recording at the level that you expect. - Consider setting separate log levels on your development and production environments.

Additional Information

The Open Web Application Security Project (OWASP) provides an excellent logging cheat sheet containing guidance on all aspects of logging.

Heroku’s logging infrastructure has limited retention of your logs. See the Logging article for more info and provision a logging add-on or a custom log drain to persist your logs.

Keep reading

  • Patterns & Best Practices

Feedback

Log in to submit feedback.

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices