Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • 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
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Working with Django
      • Background Jobs in Python
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Single Sign-on (SSO)
  • 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 March 08, 2023

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

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
  • Podcasts
  • Support Channels
  • Status

Language Reference

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

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences