igorkasyanchuk / rails_performance

Monitor performance of you Rails applications (self-hosted and free)
https://www.railsjazz.com/
MIT License
976 stars 53 forks source link

When using Docker, the config always initiated before version created resulting cannot read envar config #39

Closed IrvanFza closed 5 months ago

IrvanFza commented 2 years ago

When using Docker, this gem always runs invoke rake command in lib/rails_performance/gems/rake_ext.rb:30 before the version is created. This makes it cannot read the Redis configuration specified in the envar config, so it always return the default host and port.

Redis::CannotConnectError: Error connecting to Redis on 127.0.0.1:6379 (Errno::ECONNREFUSED)
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:379:in `establish_connection'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:117:in `block in connect'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:344:in `with_reconnect'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:116:in `connect'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:417:in `ensure_connected'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:269:in `block in process'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:356:in `logging'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:268:in `process'
/usr/local/bundle/gems/redis-4.5.1/lib/redis/client.rb:162:in `call'
/usr/local/bundle/gems/redis-4.5.1/lib/redis.rb:861:in `block in set'
/usr/local/bundle/gems/redis-4.5.1/lib/redis.rb:72:in `block in synchronize'
/usr/local/bundle/gems/redis-4.5.1/lib/redis.rb:72:in `synchronize'
/usr/local/bundle/gems/redis-4.5.1/lib/redis.rb:857:in `set'
/usr/local/bundle/gems/redis-namespace-1.8.1/lib/redis/namespace.rb:476:in `call_with_namespace'
/usr/local/bundle/gems/redis-namespace-1.8.1/lib/redis/namespace.rb:352:in `block (2 levels) in <class:Namespace>'
/usr/local/bundle/gems/rails_performance-1.0.1/lib/rails_performance/utils.rb:33:in `save_to_redis'
/usr/local/bundle/gems/rails_performance-1.0.1/lib/rails_performance/models/rake_record.rb:44:in `save'
/usr/local/bundle/gems/rails_performance-1.0.1/lib/rails_performance/gems/rake_ext.rb:22:in `invoke_with_rails_performance'
/usr/local/bundle/gems/rails_performance-1.0.1/lib/rails_performance/gems/rake_ext.rb:30:in `invoke'

I suspect the code in https://github.com/igorkasyanchuk/rails_performance/blob/master/lib/rails_performance/engine.rb#L60-L62 that caused this.

    config.after_initialize do
      next unless RailsPerformance.enabled

      ActionView::LogSubscriber.send :prepend, RailsPerformance::Extensions::View
      ActiveRecord::LogSubscriber.send :prepend, RailsPerformance::Extensions::Db

      if defined?(::Rake::Task)
        require_relative './gems/rake_ext.rb'
        RailsPerformance::Gems::RakeExt.init
      end
    end

My workaround is to read an envar config to enable this gem before any other config like so:

RailsPerformance.setup do |config|
  config.enabled = ENV['RAILS_PERFORMANCE_ENABLED'] == 'true'
 # Other config
end

And inject the ENV['RAILS_PERFORMANCE_ENABLED'] after the Docker finish creating the version and start the rails server like so.

RAILS_PERFORMANCE_ENABLED=true bundle exec rails server -b 0.0.0.0 -p 80 -e production

If this issue is not a priority right now or cannot be fixed at the moment, it would be great if my solution can be included in the docs to help anyone that faces the same issue.

ekampp commented 1 year ago

I also run my application inside docker. I'm using this in the configuration to set a Redis URL inside the docker environment:

RailsPerformance.setup do |config|
  redis = Redis.new URL: "redis://redis" # <-- Your internal docker address for Redis goes here
  config.redis = Redis::Namespace.new("#{Rails.env}-rails-performance", redis: redis)
  # ...
end
igorkasyanchuk commented 1 year ago

@ekampp can't suggest anything, I don't have docker installed on my machine. It would be great if you can prepare a fix and send a PR with it

ekampp commented 1 year ago

The above configuration works for me in docker. If configured, it should already work, and no fix is required.

0llirocks commented 5 months ago

@igorkasyanchuk The issue described here is not about the url for redis but about the creation of the image. If you create an image for an rails app you sometimes call some kind of rake command. The problem here is that this invokes the rails_performance gem which wants to start and searches for a redis. The problem is not that no redis is found (which is expected during image creation) but that the gem starts on the rake command rather than on the rails server command. In the end the gem should only start when the application is started and not when any rake command is executed.

The workaround is to enable the gem via env variable and only set it when starting the image/container.

igorkasyanchuk commented 5 months ago

yes, because gem tracks rake command execution.

a possible long-term solution can be to make it configurable.

short-term for you if you override "https://github.com/igorkasyanchuk/rails_performance/blob/master/lib/rails_performance/gems/rake_ext.rb"

and make methods empty, so nothing will happen

0llirocks commented 5 months ago

I ended up implementing a similar workaround as Irvan, just wanted to clarify that this is still an issue when creating an image. Adding a config would be great.

igorkasyanchuk commented 5 months ago

added a new config include_rake_tasks (by default false) so I think if you just upgrade gem this issue won't happen

0llirocks commented 5 months ago

@igorkasyanchuk The config fixes the issue, thank you!