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:
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.
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?
Automatic level normalization - Handles different level formats (:warn vs 'warning', symbols vs strings)
Consistent exception formatting -
log_exception_to_railsprovides standardized exception logging with special handling forBackendServiceExceptionNull safety - Gracefully handles nil exceptions and empty messages
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:
# 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.loggerfor most loggingUse
Vets::SharedLoggingwhen you need standardized formatting - Especially for exception loggingInclude structured context - Use hashes instead of string interpolation
Log at appropriate levels - Don't log everything as
:errorInclude 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
Help and feedback
Get help from the Platform Support Team in Slack.
Submit a feature idea to the Platform.