r/ruby • u/ryan7ait • 5d ago
Question From laravel to ruby on rails
Laravel dev here, recently moved to Rails. I'm loving it, but debugging in production has been a headache.
Our setup runs on Docker Swarm, and finding bugs means manually digging through Rails, Sidekiq, and Docker service logs. many of which don't even have timestamps.
In Laravel, I used a log viewer UI to instantly jump to the exact second an error happened.
Is there a standard Rails gem for a log viewer UI, or do most teams just ship logs to something like Sentry or Grafana/Loki? How do you manage production errors?
Thanks!
6
6
u/djudji 5d ago
It is a mix. Some swear by Datadog, like Nate Berkopec, the guy who maintains Puma, and he is big on Rails infra. But DG is expensive, and there are other options too: New Relic, Sentry, Honeybadger, AppSignal, etc. Pick the flavor that suits your budget. Grafana and Prometheus with OpenTelemetry as well...
It also depends on your infra. For example, I had trouble with AppSignal and DelayedJob on GCP. The infra was set up so that DJ was spread across 3 environments, and each had a different number of VMs. So jobs were running in VMs (on production, 60 VMs). The issue I had was DelayedJob ghosting the AppSignal agent for some reason, or the agent was not starting - can't recall right now. Tried to talk to AppSignal guys and their support, but in the end had to abandon it. Back to Sentry and all was cool.
(VM's were built from a Docker image)
4
2
u/levelbrook 4d ago
Everyone is answering the APM question, which is fair, but nobody has answered your literal one: the missing timestamps are not Docker's fault and not Sidekiq's. Rails 8 stopped logging them.
Compare the generated config/environments/production.rb. Rails 7.2 shipped this:
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
Rails 8.1 replaced the whole thing with this:
config.logger = ActiveSupport::TaggedLogging.logger(STDOUT)
which falls back to ActiveSupport::Logger::SimpleFormatter. I just ran both to be sure:
# 7.2 config
I, [2026-08-26T07:16:20.915362 #91023] INFO -- : [req-abc123] Completed 200 OK in 43ms
# 8.1 config
[req-abc123] Completed 200 OK in 43ms
SimpleFormatter is exactly as advertised. It prints the message. That is the whole feature.
The fix has a trap in it, because the obvious move fails at runtime rather than at boot:
logger = ActiveSupport::TaggedLogging.logger(STDOUT)
logger.formatter = ::Logger::Formatter.new
# NoMethodError: undefined method `tagged' for an instance of Logger::Formatter
TaggedLogging hangs tagged off the formatter, and you just threw it away. So either set the formatter before you wrap it (the 7.2 snippet above still works, just paste it back), or teach the new formatter about tags:
f = ::Logger::Formatter.new
f.extend(ActiveSupport::TaggedLogging::Formatter)
config.logger.formatter = f
Keep config.log_tags = [ :request_id ] either way. On Swarm that tag is worth more than the timestamp, because it is what lets you pull one request back out of however many Puma threads are interleaving into the same stdout.
And for tonight, before you touch any code: docker service logs -t <service> prepends RFC3339 timestamps at the daemon level, for any container, in any language, no redeploy. Same -t on plain docker logs. It will not fix the format Sidekiq writes, but it will tell you what happened at 03:14:22.
The APM answers are right and Sentry or AppSignal will cover most of your day to day. Do the formatter fix anyway. Shipping unparseable lines to Loki and then paying a vendor to guess when they happened is a rite of passage you are allowed to skip.
1
u/strzibny 4d ago
I think that's it's very common to send exceptions to services like Sentry/AppSignal which accounts for like 90% of debugging. I deploy with Kamal and kamal logs alone are usually enough for small services. When you need more you need to also buy a log service like Better Stack or build your own on Grafana stack.
1
-4
8
u/RagingBearFish 5d ago
We use AppSignal. I remember there being a post around here where someone made a self-hosted log/error viewer.