I'm running a local copy of the railscasts website to get familiar with rails 3. I was examining the development log after I was clicking around, and here's what I see:
Started GET "/" for 127.0.0.1 at 2010-12-16 14:17:07 -0500
Processing by EpisodesController#index as HTML
Episode Load (0.5ms) SELECT "episodes".* FROM "episodes" WHERE (published_at <= '2010-12-16 19:17:07.872204') ORDER BY position DESC LIMIT 10 OFFSET 0
Rendered shared/_navigation.html.erb (1.4ms)
Sponsor Load (0.2ms) SELECT "sponsors".* FROM "sponsors" WHERE (active = 't')
Tag Load (0.1ms) SELECT "tags".* FROM "tags" ORDER BY name
Rendered shared/_side.html.erb (4.2ms)
Rendered episodes/index.html.erb within layouts/application (9.8ms)
Completed 200 OK in 117ms (Views: 12.7ms | ActiveRecord: 0.8ms | Sphinx: 0.0ms)
Where is the rest of the response time coming from? It says 117ms for the full request and it looks like it's logging all database queries. Is the remaining time really just controller logic?
The problem was simple. This is a development log snippet, so all of that extra time was gobbled up by rails reloading the classes.
The rest of the time would go to:
Controller, view, model logic
Sending/receiving the HTTP data
Rails internals
Logging, printing the console
Related
I created a gem to work with Box API V2 (https://github.com/youpdidou/omniauth-box/). I tested it in development. The authentication is created as needed and recorded in DB, but there is an error in the redirect to my page at the end of the process (cf. log below).
My app works fine with other providers (I have Twitter and Yammer, using the omniauth-twitter, and omniauth-yammer gem), so it seems the error could come something I am missing in my Gem (something related to the refresh token?), or maybe it is related to the fact The Box authentication process has 2 steps (1 for credentials, 1 to authorize access to files - cf. http://developers.box.com/oauth/)...
What am I missing here? How to debug this, and what should I look at?
(box) Callback phase initiated.
Started GET "/auth/box/callback?state=7d550f7c0d367d4af73ca3a1d82985c78730126887e3e813&code=fV19In0Elnq1GNX61t32N1h8anezbTiH" for 127.0.0.1 at 2013-01-30 00:28:18 -0800
Processing by AuthenticationsController#create as HTML
Parameters: {"state"=>"7d550f7c0d367d4af73ca3a1d82985c78730126887e3e813", "code"=>"fV19In0Elnq1GNX61t32N1h8anezbTiH", "provider"=>"box"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
Authentication Load (0.5ms) SELECT `authentications`.* FROM `authentications` WHERE `authentications`.`user_id` = 1 AND `authentications`.`provider` = 'box' AND `authentications`.`uid` = '288560' LIMIT 1
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO `authentications` (`created_at`, `oauth_secret`, `oauth_token`, `provider`, `uid`, `updated_at`, `user_id`) VALUES ('2013-01-30 08:28:19', NULL, NULL, 'box', '288560', '2013-01-30 08:28:19', 1)
(1.5ms) COMMIT
(0.1ms) BEGIN
(0.4ms) UPDATE `authentications` SET `oauth_token` = 'cZga3uA89eslNAURbJlZaySukIs9IxTF', `updated_at` = '2013-01-30 08:28:19' WHERE `authentications`.`id` = 26
(0.5ms) COMMIT
Redirected to http://localhost:3000/services
Completed 302 Found in 14ms (ActiveRecord: 3.7ms)
[2013-01-30 00:28:19] ERROR Errno::ECONNRESET: Connection reset by peer
/Users/alex/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/webrick/httpserver.rb:80:in `eof?'
/Users/alex/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/webrick/httpserver.rb:80:in `run'
/Users/alex/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
This isn't related to box I think but rails itself, you might want to look at:
ERROR Errno::ECONNRESET: Connection reset by peer
as this person seems to have near enough the exact same error as you.
EDITED to include answer:
quoted from #Matt Smith
My quick guess is this looks like you have a problem with your sessions and protect_from_forgery is kicking in.
I had a similar problem and smashed my head against the wall for a few days, it turned out to be I was assigning an entire object to a session object instead of just the id. A quick note, non-GET requests are the ones that trigger the protect_from_forgery.
I had a similar problem in a non-rails app. In my case I was doing some ajax requests on client and redirected to the box authentication page afterwards, without waiting for the server to complete the requests.
Using a promise and redirecting after the request is done fixed the issue. Something like:
$.ajax(my_url, {dataType: "json"}).then(function(data){window.location.replace(auth_url)};
Hope you find some inspiration here.
Stumped here, on our website we have an FAQ, on the admin side we have the ability to add/edit/delete FAQ categories and individual FAQ's inside those categories.
In my faq_controller I have these 2 methods:
def destroy
faq = load_faq_for_faq_category
faq.destroy if faq
redirect_to "/faq_categories/#{params[:faq_category_id]}"
end
private
def load_faq_for_faq_category
faq = Faq.where(:id => params[:id]).first!
if faq.faq_category_id != params[:faq_category_id].to_i
raise ActiveRecord::RecordNotFound, "FAQ doesn't belong to specified FAQ Category"
end
faq
end
This line:
redirect_to "/faq_categories/#{params[:faq_category_id]}"
Used to be:
redirect_to :back
but that wasn't working to I switched to the more explicit path but no matter what I do it won't destroy the faq.
My server log says this:
Started DELETE "/faq_categories/4/faq/50" at 2012-12-19 15:44:32 +0000
Processing by FaqController#destroy as HTML
Parameters: {"faq_category_id"=>"4", "id"=>"50"}
Redirected to http://my_staging_server/faq_categories/4/faq/50
Filter chain halted as :redirect_to_https rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
The weirdest thing about this though is that it works on my local machine. My local log looks like this:
Started DELETE "/faq_categories/1/faq/5" for 127.0.0.1 at 2012-12-19 09:03:05 -0700
Processing by FaqController#destroy as HTML
Parameters: {"faq_category_id"=>"1", "id"=>"5"}
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
Role Exists (0.1ms) SELECT 1 AS one FROM `roles` INNER JOIN `roles_users` ON `roles`.`id` = `roles_users`.`role_id` WHERE `roles_users`.`user_id` = 1 AND `roles`.`lookup_code` = 'root' LIMIT 1
Faq Load (0.1ms) SELECT `faqs`.* FROM `faqs` WHERE `faqs`.`id` = 5 LIMIT 1
(0.2ms) BEGIN
CACHE (0.0ms) SELECT `faqs`.* FROM `faqs` WHERE `faqs`.`id` = 5 LIMIT 1
SQL (0.2ms) DELETE FROM `faqs` WHERE `faqs`.`id` = 5
SQL (0.3ms) UPDATE `faqs` SET position = (position - 1) WHERE (`faq_category_id` = 1 AND position > 1)
(45.1ms) COMMIT
Redirected to http://localhost:3000/faq_categories/1
Completed 302 Found in 54ms (ActiveRecord: 46.3ms)
Which is correct so...
TL:DR Why is this redirect_to not working on my staging server, and what exactly does the filter chain halted as :redirect_to_https line mean?
May be you set HTTPS in your production config file but not development config file.
Say your controller is called faq_categories, and the method is called show
You can do it by:
class faq_categories_Controller
skip_filter :redirect_to_https
end
which will prevent the HTTPS checking
Or you can do it by:
redirect_to {:protocol => 'https://', :controller => 'faq_categories', :action => 'show'}
The site was already using https, so I still don't know why the filter chain was breaking but #code4j started me in the right direction.
Adding this to my faq_controller fixed the problem:
skip_filter :redirect_to_https
I recollect getting log files that were nicely ordered, so that you could follow one request, then the next, and so on.
Now, the log files are, as my 4 year old says "all scroggled up", meaning that they are no longer separate, distinct chunks of text. Loggings from two requests get intertwined/mixed up.
For instance:
Started GET /foobar
...
Completed 200 OK in 2ms (Views: 0.4ms | ActiveRecord: 0.8ms)
Patient Load (wait, that's from another request that has nothing to do with foobar!)
[ blank space ]
Something else
This is maddening, because I can't tell what's happening within one single request.
This is running on Passenger.
I tried to search for the same answer but couldn't find any good info. I'm not sure if you should fix server or rails code.
If you want more info about the issue here is the commit that removed old way of logging https://github.com/rails/rails/commit/04ef93dae6d9cec616973c1110a33894ad4ba6ed
If you value production log readability over everything else you can use the
PassengerMaxInstancesPerApp 1
configuration. It might cause some scaling issues. Alternatively you could stuff something like this in application.rb:
process_log_filename = Rails.root + "log/#{Rails.env}-#{Process.pid}.log"
log_file = File.open(process_log_filename, 'a')
Rails.logger = ActiveSupport::BufferedLogger.new(log_file)
Yep!, they have made some changes in the ActiveSupport::BufferedLogger so it is not any more waiting until the request has ended to flush the logs:
http://news.ycombinator.com/item?id=4483390
https://github.com/rails/rails/commit/04ef93dae6d9cec616973c1110a33894ad4ba6ed
But they have added the ActiveSupport::TaggedLogging which is very funny and you can stamp every log with any kind of mark you want.
In your case could be good to stamp the logs with the request UUID like this:
# config/application.rb
config.log_tags = [:uuid]
Then even if the logs are messed up you still can follow which of them correspond to the request you are following up.
You can make more funny things with this feature to help you in your logs study:
How to log user_name in Rails?
http://zogovic.com/post/21138929607/running-time-in-rails-logs
Well, for me the TaggedLogging solution is a no go, I can live with some logs getting lost if the server crashes badly, but I want my logs to be perfectly ordered. So, following advice from the issue comments I'm applying this to my app:
# lib/sequential_logs.rb
module ActiveSupport
class BufferedLogger
def flush
#log_dest.flush
end
def respond_to?(method, include_private = false)
super
end
end
end
# config/initializers/sequential_logs.rb
require 'sequential_logs.rb'
Rails.logger.instance_variable_get(:#logger).instance_variable_get(:#log_dest).sync = false
As far as I can say this hasn't affected my app, it is still running and now my logs make sense again.
They should add some quasi-random reqid and write it in every line regarding one single request. This way you won't get confused.
I haven't used it, but I believe Lumberjack's unit_of_work method may be what you're looking for. You call:
Lumberjack.unit_of_work do
yield
end
And all logging done either in that block or in the yielded block are tagged with a unique ID.
My app is based on Rails 3.2.2. Faced some strange problem: all actions in development/production are called twice. Any suggestions?
Started GET "/faqs" for 127.0.0.1 at 2012-07-07 17:08:06 +0200
Processing by FaqsController#index as HTML
Faq Load (0.5ms) SELECT `faqs`.* FROM `faqs` WHERE `faqs`.`active` = 1 ORDER BY position asc
Rendered faqs/index.html.haml within layouts/application (3.1ms)
Rendered shared/_navigation_bar.html.haml (5.3ms)
Rendered devise/registrations/_register.html.erb (5.5ms)
Completed 200 OK in 137ms (Views: 43.3ms | ActiveRecord: 0.5ms | Solr: 0.0ms)
Started GET "/faqs" for 127.0.0.1 at 2012-07-07 17:08:06 +0200
Processing by FaqsController#index as */*
Faq Load (0.2ms) SELECT `faqs`.* FROM `faqs` WHERE `faqs`.`active` = 1 ORDER BY position asc
Rendered faqs/index.html.haml within layouts/application (0.2ms)
Rendered shared/_navigation_bar.html.haml (3.9ms)
Rendered devise/registrations/_register.html.erb (12.1ms)
Completed 200 OK in 33ms (Views: 30.2ms | ActiveRecord: 0.2ms | Solr: 0.0ms)
Updated #1
Simple controller:
class FaqsController < ApplicationController
respond_to :html
def index
#faqs = Faq.all
respond_with(#faqs)
end
end
View is quite simple too:
%h2 Faqs
- #faqs.each_with_index do |faq, index|
.span9
%h3
= "%d." % (index + 1)
= faq.title
%p= faq.body
This is probably due to Chrome. You can test in Safari/Firefox/IE etc
The reason I believe it causes two loads is because Chrome "forks" the request and essentially makes two requests. It renders the first one that returns in its window.
IIRC I researched this many years ago and this was a feature implemented to render pages faster.
This issue probably does not have anything to do with Rails 3.2.2.
This exact behavior would be seen if you had javascript on your pages that was making an ajax request when the page was loaded. I would walk through all of your script assets and look for one that is meant to call back to your app after the page is loaded. You'll probably find the culprit there.
I'm using Rails 3.0.12, and in my development environment, ActiveRecord queries are very slow when I have config.cache_classes=false in my development environment. A controller action that executes 3 queries takes over 200ms locally.
[INFO: 06/01 12:34:16 #10831] Started GET "/api/v1/subscription.json" for 127.0.0.1 at 2012-06-01 12:34:16 -0400
[INFO: 06/01 12:34:16 #10831] Processing by Api::V1::SubscriptionsController#show as JSON
[DEBUG: 06/01 12:34:16 #10831] User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."apikey" = 'xyz' LIMIT 1
[DEBUG: 06/01 12:34:16 #10831] Site Load (0.6ms) SELECT "sites".* FROM "sites" WHERE "sites"."id" = 1 LIMIT 1
[DEBUG: 06/01 12:34:16 #10831] Subscription Load (1.9ms) SELECT "subscriptions".* FROM "subscriptions" WHERE ("subscriptions".site_id = 1) LIMIT 1
[INFO: 06/01 12:34:16 #10831] Completed 200 OK in 236ms (Views: 1.5ms | ActiveRecord: 3.3ms)
Notice the actual AR queries are very fast but the total time is 236ms. Another controller action that does not do any AR queries takes 1ms.
When I set config.cache_classes=false in my development environment, the action that runs AR queries executes in 4ms as I would expect.
Are the AR classes really being reloaded with every request? I thought cache_classes only dealt with stuff in the app directory. Any thoughts on how I can improve this? I would obviously like to run with cache_classes=false so I don't have to restart rails with every change, but my API runs too slow to do any meaningful testing currently.