Skip to content

Add config.logtail.enabled to turn the integration off per environment - #60

Merged
PetrHeinz merged 6 commits into
mainfrom
claude/logtail-enabled-switch
Oct 2, 2026
Merged

PetrHeinz merged 6 commits into
mainfrom
claude/logtail-enabled-switch

Conversation

@PetrHeinz

@PetrHeinz PetrHeinz commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

There is no way to turn the Rails integration off in one environment. Installing the gem is enough to change local logging: the gem silences DebugExceptions' own logging, so development logs lose exception backtraces; log/development.log stops being written once config/application.rb sets config.logger = Logtail::Logger.create_default_logger(...) as the docs show; and when the logger is only configured for production, the default Rails logger prints raw Ruby hashes. The red-team reproduced all three on Rails 8.1, e.g. with the docs setup in development a failing request logged only ArgumentError (issue10 boom), without a backtrace, and no log/development.log was written. Reported in #10

This adds config.logtail.enabled, true by default:

  • Logtail::Config#enabled= and #enabled? in lib/logtail-rails/config.rb, reachable as config.logtail.enabled in config/application.rb and config/environments/*.rb.
  • A new :logtail_enabled initializer runs after the environment files are loaded and before Rails' :initialize_logger. When the switch is off, it calls Logtail::Integrations::Rails.enabled = false before the :logtail initializer builds its middleware list, so no Logtail middleware is installed, DebugExceptions, Rails::Rack::Logger and the log subscribers stay unpatched, and the Rails.event subscriber stays disabled.
  • If config.logger holds a Logtail::Logger at that point, typically the one create_default_logger built in config/application.rb, it's replaced by a Logtail::Logger that writes to log/<env>.log. Calls like Rails.logger.info("message", key: value) keep working, nothing goes to Better Stack, and rails server still mirrors the log to the console.
  • One README line.

Behaviour and compatibility:

  • Nothing changes unless an app sets the switch to false.
  • It has to be set in config/application.rb or an environment file. config/initializers/* run after Rails has set up its logger, which is too late.
  • Any Logtail::Logger in config.logger is replaced, not only one built by create_default_logger, since a disabled environment shouldn't send logs.
  • In a Sidekiq server process, Sidekiq.logger keeps the logger that create_default_logger gave it. This PR doesn't change that.

The tests boot a small app in a subprocess per case, because booting patches Rails classes for the whole process: switched off in development (where create_default_logger builds the HTTP logger) and in test (where it returns the STDOUT logger), plus a control boot with the default.

Targets the 0.2.15 patch release. No dependencies.

The commit "Expect real response durations in the request specs" is the same change as in #59: logtail-rack 0.2.8 times responses with the monotonic clock, which Timecop doesn't freeze, so three existing specs now fail on every branch based on main. It's identical in both PRs, so it merges cleanly whichever lands first.

The first commit only adds the tests and is expected to fail on CI. The implementation follows in the next commit.

Follow-up (f2e1f30 test, 0cb8ae6 fix): with the switch off, the log file used to start with Ruby Logger's # Logfile created on … by logger.rb line. That happened because the path was passed to Logger, which then created the file. Rails opens log/<env>.log itself, so stock Rails has no such line. The file is now opened the same way. I ran the same app side by side, once without the gem and once with config.logtail.enabled = false: log/development.log, log/test.log and the console output were identical apart from timings.

🤖 Generated with Claude Code

PetrHeinz and others added 4 commits October 1, 2026 18:43
Each case boots a small app in a subprocess, since booting patches
Rails classes for the whole process. With `config.logtail.enabled =
false` in an environment file, no Logtail middleware may be installed,
DebugExceptions must keep its own logging, the Rails.event subscriber
stays off, and Rails.logger has to write log/<env>.log, also when
config/application.rb created the logger with create_default_logger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new initializer runs once the environment files are loaded and before
Rails' :initialize_logger. When the switch is off, it disables all
integrations before the :logtail initializer picks the middlewares, and
replaces a Logtail::Logger in config.logger, typically the one
create_default_logger built in config/application.rb, with one writing
to log/<env>.log, so structured logger calls keep working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mattr_accessor ignores its default: option before Rails 5.2, so
EventLogSubscriber.enabled starts as nil there. It only matters on Rails
8.1 and newer anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
logtail-rack 0.2.8 times responses with the monotonic clock, which Timecop
doesn't freeze, so "Completed 200 OK in 0.0ms" no longer holds. The last CI
run on main still resolved logtail-rack 0.2.7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PetrHeinz and others added 2 commits October 2, 2026 11:05
With config.logtail.enabled = false the log file starts with Ruby Logger's
"# Logfile created on … by logger.rb" line, which Rails' own log file
doesn't have. This test fails until the file is opened the way Rails does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… as Rails

Passing the path to Logger made it create the file and write its
"# Logfile created on …" header. Rails opens log/<env>.log itself in append
mode, so its log has no such line. Doing the same makes the log output with
config.logtail.enabled = false identical to an app without the gem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PetrHeinz
PetrHeinz marked this pull request as ready for review October 2, 2026 09:21
@PetrHeinz
PetrHeinz merged commit ea71250 into main Oct 2, 2026
68 checks passed
@PetrHeinz
PetrHeinz deleted the claude/logtail-enabled-switch branch October 2, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant