tag:blogger.com,1999:blog-13475452476086910542024-03-13T09:51:55.981-07:00My cat wants to learn Ruby on RailsScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-1347545247608691054.post-32754372598826310112015-07-16T18:06:00.001-07:002015-07-16T18:09:26.485-07:00How to discover what is generating an SQL statement in your Rails logJust spreading a really cool tip I came across. Ryan Bigg has <a href="http://ryanbigg.com/2013/06/finding-sql-queries-in-rails/">this blog post</a> showing how you can find out what is creating an SQL statement in your log. I was having a devil of a time figuring out where a particular callback was coming from and discovered his great post.
Essentially you hook into ActiveSupport::Notifications and then put in logic in the regex piece to describe the query you are looking for. In this case I did this in development.rb:
<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> ActiveSupport::Notifications.subscribe('sql.active_record') do |_, _, _, _, details|
if details[:sql] =~ /UPDATE "answers" SET position =/
puts '*' * 50
puts caller.join("\n")
puts '*' * 50
end
end
</code></pre>
And then looked at the call stack to see where it was coming from. I could have output to the logger too. And I would not recommend doing this on Production.
ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-71918178366402646602015-07-12T21:07:00.003-07:002015-07-12T21:08:14.358-07:00A new gem to help monitor Postgres performance in standalone instancesI just released <a href="https://rubygems.org/gems/postgres_monitor">my own gem</a> for querying Postgres Databases for performance issues. I had used <a href="https://github.com/heroku/heroku-pg-extras">Heroku PG Extras</a> and the <a href="https://github.com/GoBoundless/newrelic_postgres_plugin">Go Boundless New Relic Postgres plugin</a> previously. Each are excellent tools with a lot of overlap. The holes for each-- hosting on Heroku needed for PG Extras and the lack of visibility into the queries themselves on New Relic-- pushed me to write this gem.
My aim is to build an engine on it that will display the stats in screens that can be plugged into an application. We'll see how that goes.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-88052338182178117152015-02-19T15:18:00.000-08:002015-02-19T15:18:21.081-08:00Using Puma on Heroku instead of UnicornA few years back I wrote about using <a href="http://mycatwantstolearnrails.blogspot.com/2013/02/heroku-with-unicorn-backlog-settings.html">Unicorn</a> on Heroku along with <a href="http://mycatwantstolearnrails.blogspot.com/2013/04/heroku-unicorn-request-backlog.html">Unicorn Worker Killer</a>. Oyr need was to increase the number of web requests an app could handle on Heroku.
Puma tested faster at the time but did not offer worker processes. You have to use threads and for an app that was never intended to be threaded running on Ruby MRI it was too much work to adjust. Puma has since added the concept of Worker Processes and, given the <a href="https://www.engineyard.com/articles/rails-server">performance advantages found with Puma</a> it made sense to install it.
Still, I was used to some variability with Unicorn and wanted to replicate some of the same things. <a href="https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server">This article</a> from Heroku offered most of the help I needed though I did reduce the default thread count from 5 to 1.
Additionally the section on the use of the <a href="https://github.com/heroku/rack-timeout">Rack Timeout gem</a> was helpful though I wound up doing this so that I could adjust the timeout via environment variable:
<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> Rack::Timeout.timeout = 20 # seconds
</code></pre>
What I did not find was helpful instructions on queue length. Puma defaults to 1024 and the previously mentioned article from Heroku cautions strongly against altering that queue length. Still, from previous performance testing on Heroku sometimes a shorter queue length is warranted (<b>DO YOUR OWN TESTING!</b>). This <a href="https://mikecoutermarsh.com/adjusting-pumas-backlog-for-heroku/">blog post</a> originally suggested altering the queue length but again he cautions against it on Heroku. If you find that a shorter queue length helps then it is a setting in the config/puma.rb file:
<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> backlog = Integer(ENV['PUMA_BACKLOG'] || 20)
bind "tcp://0.0.0.0:#{port}?backlog=#{backlog}"
</code></pre>
Good luck and Heroku onScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-24198932973153634652014-11-26T16:28:00.000-08:002014-11-26T16:31:15.081-08:00Getting PhantomJS to work with Stripe following the POODLE issueRecently with the POODLE issue we ran into a case where our PhantomJS tests would not run on Codeship. After some swearing and digging we found that PhantomJS defaulted to using 'SSLv3' and Stripe no longer supported that. Therefore when our feature tests went to access Stripe they failed.
To get around this we had to change the default for PhantomJS in our spec_helper.rb file. This is done by the phantom_options array in the options hash:
<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> Capybara.register_driver :poltergeist do |app|
options = {
phantomjs_logger: WarningSuppressor.new,
phantomjs_options: ['--ssl-protocol=tlsv1']
}
Capybara::Poltergeist::Driver.new(app, options)
end
</code></pre>
So if you need to use that, or any of the other PhantomJS command line options listed <a href="http://phantomjs.org/api/command-line.html">here</a>, you can do that in the phantomjs_options array.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-41986185094881243712014-11-14T16:36:00.001-08:002014-11-14T16:39:57.703-08:00Installing Cassandra on Digital OceanRecently I had a chance to install cassandra on a three node cluster out on Digital Ocean. Here are <a href="https://gist.github.com/scottshea/06b92ada950e1e90710e#file-cassandrainstall-md">my steps</a> in a handy markdown gist.
YMMV
ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-56829923095674642732014-05-07T11:02:00.001-07:002014-05-07T11:06:07.315-07:00Testing a Rails/Ember app with Teaspoon & QUnit and watching the tests runRecently I have had to start working with an Ember application. It is certainly a challenge. For Unit testing we decided to look at <a href="http://qunitjs.com/">QUnit</a> for our front end pieces. Being used to:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>save_and_open_page
</code></pre>
and looking at tests running visually I was a bit stymied until I realized you could use the `-d` flag to override the phantom.js we set up in the config. So:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>teaspoon -d selenium
</code></pre>
will run the tests with Firefox & Selenium (normal version issues apply)
ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-7930840248973726792014-02-26T22:16:00.003-08:002014-02-26T22:16:49.888-08:00Using table_for with HTML elements in Active AdminAh yes another foray into ActiveAdmin. Recently I needed to use the table_for feature on a show page and add some html options to it. This required looking into the code itself as the documentation was not exactly clear in either ActiveAdmin or Arbre.
Essentially you need to do something like this:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code> table_for agent.quotes, {:id => 'agent_quotes'} do
column 'Quote Number' do |quote|
quote.slug
end
column 'Business' do |quote|
quote.business.name
end
column 'Status' do |quote|
quote.state
end
column '' do |quote|
link_to 'View Quote', admin_quote_path(quote.id)
end
end
</code></pre>
It was as simple as adding a hash with the needed items after the collection for the table_for:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>table_for collection, {:id => 'html_id', :class => 'html_class'}
</code></pre>ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-51149752850073236082013-07-09T16:21:00.001-07:002013-07-09T16:22:29.879-07:00Uploading CSV files to a Rails Application using ActiveAdminRecently I had try and upload CSV files to a rails application via Active Admin. I had the inkling that maybe I was not the first to have done this. A short google search later and I was lead to <a href="http://stackoverflow.com/a/9859037/839849">this answer</a> on Stack Overflow<br />
<br />
I loved it except for the processing class listed under csv_db. It seemed too limiting in that it requires EVERY column to be there whether data is present or not. I recalled a <a href="http://railscasts.com/episodes/396-importing-csv-and-excel?view=asciicast" target="_blank">Railscast</a> that offered up a much more flexible solution and created this:<br />
<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>require 'csv'
class CsvDb
class << self
def convert_save(model_name, csv_data)
begin
target_model = model_name.classify.constantize
CSV.foreach(csv_data.path, :headers => true) do |row|
target_model.create(row.to_hash)
end
rescue Exception => e
Rails.logger.error e.message
Rails.logger.error e.backtrace.join("\n")
end
end
end
end
</code></pre>
<br />
<br />
If you replace the code from the Stackoverflow post in csv_db with this you should be able to load any number of columns you wish. As soon as I figure out the updating of existing records I will post a follow-up.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-47920751240930294002013-04-28T19:49:00.001-07:002013-04-28T19:50:55.441-07:00Flay, a gem to help improve the maintainability of your code Recently I read <a href="http://www.codebeerstartups.com/2013/04/must-have-gems-for-development-machine-in-ruby-on-rails/?goback=%2Egde_62218_member_235756060">a post</a> where the author listed the must have gems for rails development. Being an avid watcher of Railscasts I knew many of them however one, <a href="https://github.com/seattlerb/flay">flay</a>, caught my attention. It comes out of the Seattle Ruby group which also brought us <a href="https://github.com/seattlerb/flog">flog</a>.
</br></br>
Flay is along the same lines as Flog; it analyzes your code looking for issues. Rather than looking for tortured code though it is looking for similar or duplicate code blocks. You install with `gem install flay` and then run it against your files, e.g.:
</br></br>
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>flay ./app/models/*.rb
</code></pre>
</br>
A report is generated of the suspect areas like this:
</br></br>
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>macscott:test-project scottshea$ flay ./app/models/*.rb
Total score (lower is better) = 1666
1) Similar code found in :call (mass = 170)
./app/models/level.rb:8
./app/models/level.rb:9
./app/models/level.rb:10
./app/models/level.rb:11
./app/models/level.rb:15
./app/models/level.rb:17
./app/models/level.rb:19
./app/models/level.rb:20
./app/models/level.rb:22
./app/models/level.rb:23
2) Similar code found in :defs (mass = 154)
./app/models/item_step.rb:260
./app/models/response.rb:195
3) Similar code found in :defs (mass = 138)
./app/models/feedback.rb:62
./app/models/hint.rb:54
./app/models/subtitle.rb:51
4) Similar code found in :call (mass = 136)
./app/models/level.rb:12
./app/models/level.rb:13
./app/models/level.rb:14
./app/models/level.rb:16
./app/models/level.rb:18
./app/models/level.rb:21
./app/models/level.rb:24
./app/models/level.rb:25
5) IDENTICAL code found in :defn (mass*2 = 128)
./app/models/report_generator.rb:7
./app/models/summary_report_generator.rb:7
6) IDENTICAL code found in :defn (mass*2 = 120)
./app/models/image.rb:17
./app/models/sharded_image.rb:23
[truncated]
</code></pre>
</br>
The total app score of 1666 can be viewed in its individual components showing areas that provide the most bang for the buck. For experienced developers operating on their own or in a small team Flay may be unnecessary. However, on larger projects (as the one I ran it on) or those with beginner or intermediate programmers it can help increase the maintainability of your codebase.
</br></br>
I am not sure where the 1666 would rank on the overall chart (is that really bad? representative?) but the 'lower is better' advice holds true. This <a href="http://stackoverflow.com/questions/5357064/good-flay-score">Stackoverflow question</a> offers some interpretation of the score but really the best advice is "don't let it get higher!"ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com2tag:blogger.com,1999:blog-1347545247608691054.post-70571540727787556342013-04-22T20:24:00.002-07:002013-04-22T20:25:35.391-07:00A rake task to automate deployment and database migration to HerokuOne of my major annoyances with Heroku is that the deploy does not automatically run any database migrations.
Seriously?!
So I ran into this tonight when I am trying to explain to a seasoned SA that while Heroku automatically will recompile your assets for you it will not do the migrations. A Google turned up this <a href="http://stackoverflow.com/questions/5966290/rails-3-and-heroku-automatically-rake-dbmigrate-on-push">Stackoverflow</a> question which in turn led to <a href="https://gist.github.com/njvitto/362873">this gist</a>.
And I am excited to be trying it out.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-45865565441081847492013-04-20T23:29:00.001-07:002013-04-20T23:30:11.436-07:00Using Sidekiq with Faye to notify client web pages and applications of updatesRecently I was given a small coding challenge of how I would update sites & client applicaitons with notifications of content being released. My mind immediately flew to the <a href="http://faye.jcoglan.com/">faye gem</a>. However, this would be a serious block if my app had to halt everything to send out the notification to a bunch of browsers.
So, I added in <a href="http://mperham.github.io/sidekiq/">Sidekiq</a>. In the Content Model I put this to call out to Sidekiq:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code> def self.release_next
ContentWorker.perform_async
end
</code></pre>
The ContentWorker then looks like this:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>class ContentWorker
include Sidekiq::Worker
sidekiq_options queue: "content"
def perform
next_release = Content.next_release(Content.last_release)
# puts the data into JSON format; for actual content it could encode a url that is then loaded
vars = ["title" => next_release.title,
"site" => next_release.site,
"released_at" => next_release.released_at.strftime("%l:%M:%S %p %m-%d-%Y")].to_json
message = {:channel => "/releases", :data => vars, :ext => {:auth_token => FAYE_TOKEN}}
uri = URI.parse(FAYE_SUBSCRIPTION_PATH)
Net::HTTP.post_form(uri, :message => message.to_json)
next_release.update_attribute(:released_at, DateTime.now)
end
end
</code></pre>
I created a designated queue in Sidekiq for the messages and then made the Faye channel creation configurable via an environment variable from an initializer file (<app_root>/config/initializers/faye_configuration.rb):
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>FAYE_SUBSCRIPTION_PATH = "http://localhost:9292/faye"
</code></pre>
The client then just listens in on the Faye channel and acts upon a message coming through. Here is the Javascript I wrote for listening to the Channel and adding the new release to the top of the view table just below the headers:
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>$(function() {
var faye = new Faye.Client("http://192.168.0.12:9292/faye");
faye.subscribe("/releases", function(data) {
add_to_table(data);
});
});
function add_to_table(data){
var json_obj = jQuery.parseJSON(data);
var $content_table = $('#content_table');
if ($content_table.find('tr').length >= 10 ) {
$content_table.find("tr:last").remove();
}
$("#header").after("<tr><td>" + json_obj[0].title+ "</td><td>" + json_obj[0].site + "</td><td>" + json_obj[0].released_at + "</td></tr>");
}
</code></pre>
All in all a nice little challenge. I have not had a chance to try it out beyond my home network yet so I am not sure how performant the solution would be.
</br></br>
Railscasts used for this:
</br>
<a href="http://railscasts.com/episodes/260-messaging-with-faye"><i>Faye</i></a></br>
<a href="http://railscasts.com/episodes/366-sidekiq"><i>Sidekiq</i></a>ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com2tag:blogger.com,1999:blog-1347545247608691054.post-16644134466903109232013-04-03T11:18:00.001-07:002013-04-03T11:20:22.930-07:00Using Unicorn Worker Killer to help reduce queue backlog on Heroku with UnicornIn light of the update <a href="https://blog.heroku.com/archives/2013/4/2/routing_and_web_performance_on_heroku_a_faq" target="_blank">from Heroku CTO Adam Wiggins</a> and having been part of the efforts to test the larger Dynos with Unicorn on Heroku I felt it necessary to share <a href="https://github.com/kzk/unicorn-worker-killer" target="_blank">Unicorn Worker Killer</a>; a tool we have found indispensable.<br />
<br />
Based on configurable thresholds for memory and number of requests received it will kill off a Unicorn Worker. For those of you on Heroku this is valuable in that it then returns all the requests back to the Heroku random routing. While not an exact correlation between too many requests and memory size it does help keep individual workers from becoming too overloaded.<br />
<br />
Add this to your Gemfile:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>gem 'unicorn-worker-killer'
</code></pre>
<br />
The gem suggests that you configure your `config.ru` file for the thresholds. This can be cumbersome on Heroku if you need to test out different settings.<br />
<br />
Thankfully you can also control the thresholds via environment variables. In config.ru do:
<br />
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"><code>max_request_min = ENV['MAX_REQUEST_MIN'].to_i || 3072
max_request_max = ENV['MAX_REQUEST_MAX'].to_i || 4096
# Max requests per worker
use Unicorn::WorkerKiller::MaxRequests, max_request_min, max_request_max
oom_min = ((ENV['OOM_MIN'].to_i || 192) * (1024**2))
oom_max = ((ENV['OOM_MAX'].to_i || 256) * (1024**2))
# Max memory size (RSS) per worker
use Unicorn::WorkerKiller::Oom, oom_min, oom_max
</code></pre>
<br />
The run this on the heroku command line:
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>heroku config:add OOM_MAX=256 memory_limit_min =192 MAX_REQUEST_MIN=3072 MAX_REQUEST_MAX=4096 -a unicon-ttm-sandbox
</code></pre>
That will add in the variables needed to control the thresholds. The example shows the defaults though we found dropping the OOM_MAX to 216 worked bestScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com8tag:blogger.com,1999:blog-1347545247608691054.post-39644079428755082052013-03-14T11:36:00.000-07:002013-03-14T11:36:02.391-07:00Heroku plugin providing insight into the Postgres database for your applicationHeroku provides a lovely plugin called <a href="https://github.com/heroku/heroku-pg-extras" target="_blank">heroku-pg-extras</a> which can provide some insight into the inner workings of the postgres databases connected to your application. By default it will hit the database listed in the DATABASE_URL variable for Heroku. However you can specify the database using the database color url; e.g. HEROKU_POSTGRES_PURPLE_URL.<br />
<br />
The plugin does the following:<br />
<ul>
<li>cache_hit - <i>calculates your cache hit rate (effective databases are at 99% and up)</i></li>
<li>index_usage - <i>calculates your index hit rate (effective databases are at 99% and up)</i></li>
<li>ps - <i>view active queries with execution time</i></li>
<li>locks - <i>display queries with active locks</i></li>
<li>blocking - <i>display queries holding locks other queries are waiting to be released</i></li>
<li>kill - <i>-f,--force; terminates the connection in addition to cancelling the query</i></li>
<li>total_index_size - <i>show the total size of the indexes in MB</i></li>
<li>index_size -<i> show the size of the indexes in MB descending by size</i></li>
<li>seq_scans - <i>show the count of seq_scans by table descending by order</i></li>
<li>long_running_queries - <i>show queries taking longer than 5 minutes </i></li>
<li>bloat - <i>show table and index bloat in your database ordered by most wasteful</i></li>
<li>mandlebrot - <i>show the mandelbrot set</i></li>
</ul>
<div>
These are based on the stats collections process used by postgres which has its own body of literature in collection and analysis starting with their main <a href="http://www.postgresql.org/docs/9.2/static/monitoring-stats.html" target="_blank">documentation</a>. It may be worth opening a ticket with Heroku to clear the stats first as they accumulate over time. Changes to the application will not be readily apparent if you still have the stats from the previous app state. Therefore you may want to open a ticket with Heroku to clean the stats (you need to be a superuser to do this yourself and Heroku does not give you superuser access).</div>
<div>
<br /></div>
<div>
Disclaimer: I am a contributer to the project</div>
ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-23865653081812032202013-03-14T10:32:00.002-07:002013-03-14T10:32:28.058-07:00Errors building Nokogiri on Lion/Mountain LionI kept getting an odd error with Nokogiri on my new Macbook:<br />
<br />
<span class="label" style="color: #3f639e; font-family: 'Courier New', monospace, monospace; font-size: 13px; line-height: 20.15625px; margin: 0px; padding: 0px; white-space: pre-wrap;">WARNING:</span><span style="background-color: #f5f2f0; color: #3f639e; font-family: monospace, monospace; font-size: 13px; line-height: 20.15625px; white-space: pre-wrap;"> Nokogiri was built against LibXML version </span><span class="number" style="color: #3f639e; font-family: 'Courier New', monospace, monospace; font-size: 13px; line-height: 20.15625px; margin: 0px; padding: 0px; white-space: pre-wrap;">2.9</span><span class="number" style="color: #3f639e; font-family: 'Courier New', monospace, monospace; font-size: 13px; line-height: 20.15625px; margin: 0px; padding: 0px; white-space: pre-wrap;">.0</span><span style="background-color: #f5f2f0; color: #3f639e; font-family: monospace, monospace; font-size: 13px; line-height: 20.15625px; white-space: pre-wrap;">, but has dynamically loaded </span><span class="number" style="color: #3f639e; font-family: 'Courier New', monospace, monospace; font-size: 13px; line-height: 20.15625px; margin: 0px; padding: 0px; white-space: pre-wrap;">2.7</span><span class="number" style="color: #3f639e; font-family: 'Courier New', monospace, monospace; font-size: 13px; line-height: 20.15625px; margin: 0px; padding: 0px; white-space: pre-wrap;">.8</span><br />
<br />
With help from <a href="https://coderwall.com/p/o5ewia" target="_blank">this post</a> I was able to resolve the issue. It seems that "This happens because the Lion system default libxml2 (loaded at bootstrap) is used, regardless of which libxml2 Nokogiri was built against". No real original work on my part here other than a Google search. However I wanted to spread the effort of Michele Gerarduzzi a litte further and give credit where credit is due.<br />
<br />
The relevant post: <a href="https://coderwall.com/p/o5ewia" target="_blank">Get rid of Nokogiri LibXML warning on OSX Lion</a>ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-80822734080674315642013-02-14T08:29:00.000-08:002013-02-14T11:40:18.055-08:00Heroku with Unicorn backlog settings and performanceIn light of this <a href="http://rapgenius.com/James-somers-herokus-ugly-secret-lyrics" target="_blank">post from Rap Genius</a> and subsequent <a href="http://news.ycombinator.com/item?id=5215884" target="_blank">blow up on Hacker News</a> I decided to share what we did to play with the request queue on Unicorn & Heroku.<br />
<br />
In the app/config/unicorn.rb we changed the backlog line to this:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>:backlog => Integer(ENV['UNICORN_BACKLOG'] || 200)
</code></pre>
<br />
And then we can alter the backlog as necessary via:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>heroku config:set UNICORN_BACKLOG=25 -a <app_name>
</code></pre>
<br />
We found 25 to be a sweet spot for two Unicorn Workers but it may be different with four (which we are experimenting with now). Again this is also relative to the app so your results may (and probably will) be different.<br />
<br />
Update:<br />
<br />
I neglected to mention that you have to move the port declaration from config.ru and put it in the unicorn.rb too. The full line should be something like this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>listen ENV['PORT'], :backlog => Integer(ENV['UNICORN_BACKLOG'] || 200)
</code></pre>
ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com2tag:blogger.com,1999:blog-1347545247608691054.post-90046328452082591632013-02-09T10:11:00.003-08:002013-02-09T10:11:57.537-08:00Formatting Source for a blog postI found this <a href="http://formatmysourcecode.blogspot.com/" target="_blank">handy blog post</a> for formatting my source code to place here in my last blog post. I encourage you to check it out!ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-16723017738574663762013-02-09T10:08:00.003-08:002013-02-09T10:12:46.688-08:00Heroku: Scaling Dynos at night and in the morningI needed a rake task to auto scale Dynos on Heroku; wind them down at night and wind them up in the morning. I found this <a href="http://stackoverflow.com/questions/9186655/heroku-cedar-how-to-scale-web-dynos-based-on-time-of-day" target="_blank">helpful post</a> on Stackoverflow. I made a few modifications and would up with this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>namespace :scale_dynos do
require 'heroku-api'
desc "scales up dynos"
task :up do
dyno_max = [6,0].include?(Time.now.wday) ? ENV['WEEKEND_DYNO_MAX'] : ENV['DYNO_MAX']
heroku = Heroku::API.new(:api_key => ENV['HEROKU_API_KEY'])
heroku.post_ps_scale(ENV['APP_NAME'], 'web', dyno_max.to_i)
end
desc "scales down dynos"
task :down do
dyno_min = ENV['DYNO_MIN']
heroku = Heroku::API.new(:api_key => ENV['HEROKU_API_KEY'])
heroku.post_ps_scale(ENV['APP_NAME'], 'web', dyno_min.to_i)
end
end
</code></pre>
<br />
<br />
It adjusts for the weekend to scale to a different level if you set the ENV varaible. Additionally here is how I set the Heroku config vars. The add command does them all at once but the remove goes through one by one, removes the VAR and restarts the app.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>heroku config:add DYNO_MIN=1 DYNO_MAX=25 WEEKEND_DYNO_MAX=1 APP_NAME=<your app name> HEROKU_API_KEY=<your api key> -a <your app name>
heroku config:remove DYNO_MIN DYNO_MAX WEEKEND_DYNO_MAX APP_NAME HEROKU_API_KEY -a <your app name>
</code></pre>
<br />
You will need the <a href="https://rubygems.org/gems/heroku-api" target="_blank">heroku-api</a> gem. I also set the Gemfile entry to this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>gem 'heroku-api', :require => false
</code></pre>
<br />
Since the rake task is called twice a day there was no need to load the gem into memory for the rest of the time.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com2tag:blogger.com,1999:blog-1347545247608691054.post-44798985633412333382012-06-19T08:47:00.000-07:002012-06-19T08:47:11.581-07:00Current Rails ProjectCurrently I am working with a company that is upgrading their Rails 1.2.3 app to Rails 3.0.13. We decided not to tackle the asset pipeline in this go around.<br />
<br />
In production their app resides on a Windows server hosted inside the clients walls and operates off of MS-SQL. I have it up and running on my Windows box at home while I work on an Ubuntu laptop. I am trying to make it as agnostic as possible so that should a client want the Rails app on a Linux server there is little to change. Who knows how successful this will be.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0tag:blogger.com,1999:blog-1347545247608691054.post-64262752964742548462012-06-19T08:41:00.003-07:002012-06-19T08:42:39.051-07:00Customary Introduction PostThe title of my blog comes from the fact that I have a cat who will sit on my lap staring at the screen while I try to write code. I am taking the stance that he wants to learn what I am doing rather than he is really saying "Srsly? You should read a best practices book."<br />
<br />
I am a mid-range Ruby/Rails developer at this stage. Proficient in some areas, woefully lacking in others. Also, because I have only had one 'longish' term assignment I have had to hop around from Windows to Linux to Mac and from Rails 1.2.3 to 2.3.n to 3.n.<br />
<br />
I find myself learning a lot of things... sometimes repeatedly... so I decided to start blogging about it as a way to take notes and possibly help someone else-- hopefully more than just providing a "don't do this!" example.ScottJSheahttp://www.blogger.com/profile/00203580998442914103noreply@blogger.com0