Log response time at Heroku - ruby-on-rails

Heroku adds a HTTP header called X-Request-Start. Its a unix timestamp.
I have a Rails 3.2 application at Heroku and want to log response time for HTTP requests.
Whats the latest point of possible integration in Rails to do:
start = Time.at(env['HTTP_X_REQUEST_START'].to_f / 1000.0).utc
response_time = Time.now.utc - start
I'm thinking of implementing a Rack middleware to calculate the response time.

Are you aware that Heroku already logs your response time? In your terminal do heroku logs -t --app your-app-name and you'll see service=xxxms which is the number of miliseconds each request takes.

Related

rails server not response after idle a while(1 or 2 hours)

I started rails server with puma webserver.(Centos 7)
simple command rails s -b 0.0.0.0 .
It is working great in working hours these day. But next day can't call rails server.(but can call rails server 1 times and like cache . And then no more access.)
It seen like request to server and don't get response and waiting server response.
After check rails log, only have one update log for today. (when I get response 1st time.)

How can you see your rails server running on heroku, so you can see full output while sending REST requests?

Typically if you use your localhost, you can just run
rails s
from terminal and then when you hit your webserver, you can see the output.
However, when I run
heroku run rails s
and then I hit my webserver up on heroku, I don't get any output like I do when I "rails s" with localhost.
Is there anyway to achieve this?
If you want to see the live server logs, use this command
heroku logs -t
There are many more options available, look at this answer heroku - how to see all the logs
You can use heroku logs command in terminal to see the log just like you see using rails s command.

Heroku - how to flush Rails logs after each request

I'm running a Rails 3 app on Heroku.
This is the output of heroku logs --tail --source app:
https://gist.github.com/4000998
The Started GET "/" lines appear in real time as HTTP requests are made. However, the Processing by Controller lines get buffered and then dumped to the log all at once.
This makes it very hard to debug issues in the app as it is difficult to match up the controller logs with the rest of the app's logs. How do I get the buffered logs to flush after each request?
Add the following line to your config.ru:
$stdout.sync = true

Restart my heroku application automatically

This terminal command restarts my heroku application:
heroku restart
Is there a way to run a script that will run this command and restart my application every hour?
I actually just had to solve this problem for my apps and wrote a post on it with more details. Basically, you need the heroku-api gem now since the heroku gem is replaced by the CLI. Then you need a rake task, a couple of config variables and the heroku scheduler plugin (free except for minimal dyno time).
The rake task looks like this:
namespace :heroku do
desc 'restarts all the heroku dynos so we can control when they restart'
task :restart do
Heroku::API.
new(username: ENV['HEROKU_USERNAME'], password: ENV['HEROKU_PASSWORD']).
post_ps_restart(ENV['HEROKU_APP_NAME'])
end
end
You can also set it up to use your API token instead of putting your username and password into the config. This only matters if you don't want your co-contributors/coworkers knowing your password or the password to your main account on Heroku.
heroku config:set HEROKU_USERNAME=[username] HEROKU_PASSWORD=[password] HEROKU_APP_NAME=[app_name] -a [app_name]
Now, go ahead and deploy and test:
git push [heroku_remote_name] [feature_branch]:master
heroku run rake heroku:restart -a [app_name]
Lastly, we’ll need to set up the task to run this on schedule. I’ve chosen to go with the free Heroku cron add-on:
heroku addons:add scheduler:standard -a [app_name]
heroku addons:open scheduler -a [app_name]
This will open up the scheduler UI in your browser and you can create a scheduled worker to run the rake task whenever you’d like. We only need it once per day and we’re choosing to run it before our first scheduled job of the day.
My original post with frigged up CSS (see update2 below):
https://web.archive.org/web/20150612091315/http://engineering.korrelate.com/2013/08/21/restart-heroku-dynos-on-your-terms/
UPDATE
I changed the name of the task from "implode" to "restart" to be way more clear as to what is happening. Implode is a fun name but pretty much useless otherwise.
UPDATE2
Apparently my company removed the blog post. I'm adding more of the code here and I've updated the link, but the CSS looks like a dog threw it up. My apologies.
You could create a heroku cron job that uses the Heroku api on your application to restart itself...
One question though - why?
We solved this by using a buildpack to get the heroku command available to the dyno itself, then using Heroku Scheduler.
We added the https://github.com/gregburek/heroku-buildpack-toolbelt buildpack per its instructions:
heroku buildpacks:add https://github.com/gregburek/heroku-buildpack-toolbelt.git
heroku config:add HEROKU_TOOLBELT_API_EMAIL=`heroku whoami`
heroku config:add HEROKU_TOOLBELT_API_PASSWORD=`heroku auth:token`
Then made sure the app slug was rebuilt per the instructions:
git push heroku master
In Heroku Scheduler, we added this as a hourly job:
vendor/heroku-toolbelt/bin/heroku ps:restart -a $HEROKU_APP_NAME
You can determine if it's working by looking for Scheduler output in the Heroku logs, and of course by the memory graph of the app in the Heroku dashboard (if you're restarting to work around a memory leak).
A script isn't necessary, just "crash" your application and Heroku will restart it.
Just don't do this more frequently than once every ten minutes or Heroku will subject you to a 10 minute timeout.
In node.js you do this with process.exit(0).
From Chris at Heroku Support:
A crashed dyno will be restarted immediately. If the dyno moves from a
crashed state into an "up" state (meaning that the dyno bound to
$PORT) then it's subject to being a normal running dyno. If it crashes
again during the boot or "starting" sequence then it won't be
restarted again until after the TIMEOUT period. The TIMEOUT period is
currently 10 minutes but that is subject to change. This prevents
dynos that are continually crashing from putting extraneous load on
the platform.
However, as good as that sounds, it doesn't work in practice. You will hit the timeout every time you exit because the dyno manager expects your app to be up:
For your worker process management you're exiting the process cleanly
but the platform is expecting the dyno to be up. It sounds like you're
essentially crashing the dyno as a result.
So again, if you need to restart periodically -- and that period can be set to > 10 minutes -- this is a easy and simple way to manage memory clearing. If you need to reboot dynamically (for example, when idle is detected) or frequently you will need to explore other options.
You can access the name of the dyno (ex. "worker.3", "web.1") through the environment variable "PS" and issue a heroku API restart command programmatically.
Inspired by https://www.stormconsultancy.co.uk/blog/development/ruby-on-rails/automatically-restart-struggling-heroku-dynos-using-logentries/
# Setup
heroku plugins:install https://github.com/heroku/heroku-oauth
heroku authorizations:create -s write
heroku config:add RESTART_API_KEY=<API KEY>
heroku config:add APP_NAME=<App Name>
heroku addons:add scheduler:standard -a <App Name>
heroku addons:open scheduler -a <App Name>
add `rake restart`
# Gemfile
gem 'platform-api', require: false
# Rakefile
task :restart do
require 'platform-api'
app_name = ENV.fetch('APP_NAME')
key = ENV.fetch('RESTART_API_KEY')
connection = PlatformAPI.connect_oauth(key)
connection.dyno.list(app_name).map do |info|
if info['type'] == 'web' && info['state'] == 'up'
puts "Restarting #{info.inspect}"
connection.dyno.restart(app_name, info['name'])
else
puts "Skipping #{info.inspect}"
end
end
end
I solved this with a very simple curl command script within the repo that is triggered using the free Heroku scheduler.
#!/bin/sh
curl -X DELETE "https://api.heroku.com/apps/${HEROKU_APP_NAME}/dynos" \
--user "${HEROKU_CLI_USER}:${HEROKU_CLI_TOKEN}" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.heroku+json; version=3"
See https://gist.github.com/mattheworiordan/f052b7693aacd025f025537418fa5708.
We've given our app a long-running token to use to authenticate with the Heroku API, and simply included a curl request in our code to restart the app.
Create a long-running API token:
$ heroku authorizations:create --description="Long-lived token for app restarts"
Creating OAuth Authorization... done
Client: <none>
ID: abcdabcd-abcd-4bcd-abcd-abcdabcdabcd
Description: Long-lived token for app restarts
Scope: global
Token: 12341234-1234-4234-1234-123412341234
Updated at: Tue May 11 2021 09:16:38 GMT-0400 (Eastern Daylight Time) (less than a minute ago)
Note the Token. We've stored it in the ENV via heroku config, along with the app name:
$ heroku config:set HEROKU_API_TOKEN=12341234-1234-4234-1234-123412341234 HEROKU_APP_NAME=not-really-an-app
In our code we have the following method to restart the app via Heroku's API, using this API call:
def restart!
# Using puts to log output, replace with your logging system if needed
puts `curl -v -s -n -X DELETE https://api.heroku.com/apps/#{ENV["HEROKU_APP_NAME"]}/dynos -H "Content-Type: application/json" -H "Accept: application/vnd.heroku+json; version=3" -H "Authorization: Bearer #{ENV["HEROKU_API_TOKEN"]}"`
end
Finally, as you're interested in automatic restarts every hour, the restart! method above can be scheduled using Heroku's Scheduler, rufus-scheduler, as a Sidekiq job, or otherwise.
Note: Heroku has some limits/timing logic around app restarts, mostly centered around dyno crashes. Reading the docs may help inform your app restart strategy.
As far as I can tell, simply running heroku ps:restart --app APPNAME in the Heroku Scheduler add-on works fine. It's unclear to me why the additional steps in other answers are necessary.

Cramp and heroku

I have been playing around with Cramp to do some real time pushing of information in an app. Its all working great locally but when I push off to heroku I seem to be having issues with the ports.
I have a socket set up in cramp which inherits from websocket
class LiveSocket < Cramp::Websocket
and I also have a cramp action called home which basically just renders some erb for the home page
class HomeAction < Cramp::Action
in my route file I set up the following and also a static file server
Rack::Builder.new do
puts "public file at #{File.join(File.dirname(__FILE__), '../public')}"
file_server = Rack::File.new(File.join(File.dirname(__FILE__), 'public'))
routes = HttpRouter.new do
add('/').to(HomeAction)
get('/LiveSocket').to(LiveSocket)
end
run Rack::Cascade.new([file_server, routes])
end
Then on the client end the javascript connects to
var ws = new WebSocket("ws://<%= request.host_with_port %>/LiveSocket");
As I say locally it all works. We connect and start receiving notifications from the server. On heroku we run thin on the Cedar stack and have a profile which looks like
web: bundle exec thin --timeout 0 start -p $PORT
When I load up the site the page itself loads fine but on trying to connect the websocket I get an error which says
servername.herokuapp.com Unexpected response code: 200
I am guessing this has something to do with how heroku routes its requests but I do know that you can run a node.js websocket server on heroku so figure there must be a way to get this working too.
Thanks in advance for any help.
cheers
stuart
I don't think Heroku supports websockets :( http://devcenter.heroku.com/articles/http-routing#the_herokuappcom_http_stack

Resources