Skip to main content
Skip table of contents

Logging in Vets-API

Last Updated:

This guide explains how to implement logging in Vets-API using Rails logger and the Vets::SharedLogging module.

Overview

Vets-API logs to DataDog via the Rails logger. All application logging should use Rails logger methods.

Note on Sentry: We are migrating away from Sentry. Do not add new Sentry logging. Existing Sentry logging calls will be removed over time. If you have existing log_*_to_sentry calls in your code, work on replacing them and please do not add new ones.

Choosing Your Logging Approach

Option 1: Rails.logger (Recommended for most cases)

This is the default choice for new code. Use the built-in Rails logger for general application logging:

RUBY
Rails.logger.debug("Debug information here")
Rails.logger.info("Informational message", { user_id: 123 })
Rails.logger.warn("Warning message", { service: "external_api" })
Rails.logger.error("Error occurred", { error_details: details })
Rails.logger.fatal("Critical failure", { context: "database" })

When to use:

  • General application flow logging

  • Debug information

  • Business logic events

  • Performance tracking

  • Error logging

Option 2: Vets::SharedLogging (For standardized logging with additional features)

Provides Rails message logging with context formatting and BackendServiceException handling.

RUBY
log_message_to_rails("User login failed", :error, { user_id: 123 })
log_exception_to_rails(exception, :error)

The source code lives at: lib/vets/shared_logging.rb Why use Vets::SharedLogging instead of Rails.logger directly?

  1. Automatic level normalization - Handles different level formats (:warn vs 'warning', symbols vs strings)

  2. Consistent exception formatting - log_exception_to_rails provides standardized exception logging with special handling for BackendServiceException

  3. Null safety - Gracefully handles nil exceptions and empty messages

RUBY
    def show
      claim = lighthouse_service.get_claim(params[:id])

      render json: ClaimSerializer.new(claim), status: :ok
    rescue Common::Exceptions::BackendServiceException => e
      # Log with special structured handling - extracts error details and backtrace
      log_exception_to_rails(e, :error)

      # Handle the error, don't re-raise
      render json: { errors: [{ title: 'Service unavailable', detail: e.message }] },
             status: :service_unavailable
    end

log_exception_to_rails extracts structured data with BackendServiceException:

RUBY
# BackendServiceException has errors with attributes:
  exception.errors.first.attributes
  # => { status: 502, detail: "Bad Gateway", code: "LH_502", source: "Lighthouse API" }

  # SharedLogging extracts these and merges with backtrace:
  Rails.logger.error(
    "Lighthouse service unavailable",  # ← exception.message
    {                                   # ← structured hash for DataDog
      status: 502,
      detail: "Bad Gateway",
      code: "LH_502",
      source: "Lighthouse API",
      backtrace: ["lib/lighthouse/benefits_claims/service.rb:45:in `get_claim'", ...]
    }
  )

Logging Best Practices

✅ Do

  • Use Rails.logger for most logging

  • Use Vets::SharedLogging when you need standardized formatting - Especially for exception logging

  • Include structured context - Use hashes instead of string interpolation

  • Log at appropriate levels - Don't log everything as :error

  • Include relevant IDs as long as they’re not PII

❌ Don't

  • Don't add new Sentry logging - We're migrating away from Sentry

  • Don't log PII. See list of PII here

  • Don't log secrets - API keys, tokens, passwords

  • Don't log excessive data in production - Large payloads, full request/response bodies


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.