Spree API and New Relic monitoring - ruby-on-rails

I've got problem with monitoring my app with New Relic.
I have latest Spree engine mounted in my routes and own controller to serve as root.
For some reason, New Relic gathers only data from this root route, any call to Spree JSON API is ignored and don't show up in Dashboard, so I can see only one transaction and it's pretty useless.
Is there any way to enable monitoring on whole mounted app? Am I missing something?

As long as you're running on Rails 4.0 or later, adding the following to app/controllers/spree/api/base_controller_decorator.rb or some equivalent location should get instrumentation wired up:
class Spree::Api::BaseController
include ActionController::Instrumentation
end
This works because on Rails 4.0 and later New Relic's controller instrumentation is based off ActiveSupport::Notifications, and include ActionController::Instrumentation gets those events flowing.

My guess is that this is happening because Spree's API is inheriting from ActionController::Metal, where NewRelic doesn't hook into.
Check here: https://github.com/spree/spree/blob/6ac62c32f91e6626b338564aab7a7ad570cbd4c3/api/app/controllers/spree/api/base_controller.rb#L5
This is probably a good argument for switching away from this within Spree, so please submit an issue for that.

I've found a way to bypass the problem in this article.
Create app/controllers/spree/api/base_controller_decorator.rb with following code:
require 'new_relic/agent/instrumentation/action_controller_subscriber'
require 'new_relic/agent/instrumentation/rails4/action_controller'
Spree::Api::BaseController.class_eval do
before_filter :check_for_user
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
include NewRelic::Agent::Instrumentation::Rails4::ActionController
NewRelic::Agent::Instrumentation::ActionControllerSubscriber \
.subscribe(/^process_action.action_controller$/)
end

Related

Automatic Reloading of Sinatra App mounted inside Rails App

I've run into what I hope is an easy-ish fix for someone more experienced than me when adding a Sinatra app to an existing Rails app.
I currently have a large rails monolith that I am planning to break apart into an SPA backed by a JSON API. Since I will still need to support the monolith until the API is completed I would like to mount the API (written in Sinatra) inside the existing Rails app as I port functionality over with a goal of removing the Rails app itself in a few months. The reason I've mounted the Sinatra app inside Rails instead of setting it up as a separate service was that I wanted easy code sharing between the two as I intend to continue using ActiveRecord as my ORM in Sinatra once the migration is complete.
I've mounted the Sinatra mockup inside the Rails app without any issues using the Rails routes.rb file as:
Rails.application.routes.draw do
mount API::Core, at: '/api'
...
end
I'm not doing any work with config.ru as mounting the API inside the routes.rb file seemed to suit my needs. If I need to put in some more legwork to get this running properly that is not an issue.
The entrypoint for the sinatra app is also fairly simple with just a couple controllers loaded in to segment the routing:
require 'sinatra/base'
require 'sinatra/json'
require_relative 'controllers/first_controller'
require_relative 'controllers/second_controller'
module API
class Core < Sinatra::Base
register Sinatra::FirstControllerApi
register Sinatra::SecondControllerApi
end
end
The problem I'm running into is one I expected with Sinatra but haven't been able to flex my google-fu enough to find a solution. Rails automatically reloads code on each change/request as expected but Sinatra does not. Every time I change controller code in the Sinatra API I need to restart the entire Rails server to serve the new content. Since my dev environment runs in docker containers this can take a while to start up each time and is becoming cumbersome.
Is there a 'canonical' solution to the problem of automagically reloading the Sinatra app mounted inside the Rails app or am I just over-complicating the problem? I know there are some gems for Sinatra that apply to this space but I haven't seen any info in how to get them working in this 'odd' edge case.
Please let me know if you need any more info, hopefully I've provided enough for someone to comprehend my issues.
Just like with a Sinatra app on it's own, a Sinatra app mounted inside o rails will not automatically reload as you make changes. Typically in Sinatra people would use external tools to help solve this problem, so they might set up something like Shotgun to watch the directory and restart the server any time a change has happened.
But, like most things in Rails, there is a way hook into it's functionatly for your own programming benefit.
ActiveSupport::FileUpdateChecker
Rails has a handy ActiveSupport::FileUpdateChecker that can watch a file, or a list of files. When they change it will call back to a block. You can use this to reload the Sinatra app -- or anything else for that matter.
In your case you might want to add the following to config/environments/development.rb in the config block for the application:
Rails.application.configure do
# ...
sinatra_reloader = ActiveSupport::FileUpdateChecker.new(Dir["path/to/sinatra/app/**"]) do
Rails.application.reload_routes!
end
config.to_prepare do
sinatra_reloader.execute_if_updated
end
end
Robert Mosolgo has a good write up on his blog: Watching Files During Rails Development. His approach is a little more thorough, but more complicated.

Rails engine creates circular dependency fault

I have an app with a rails engine i use. I've stripped them down pretty much to the bone, but i get a fault when I start the engine up with multi-threading enabled. I faults out with missing constant the model name i'm calling from the controller. I've reduced it down to just calling the Model.all.pluck(:id). And still get the fault. The models are being invoked via an Ajax call to the controller.
The app runs correctly if i refresh the page and continue, never faulting out again, that I can see.
I think it's actually a multi-treading issue, I'm using Rails 4.1, Ruby 2.12 and Puma 2.8.2 and postgress.
This is happening on my development system a macbook. I will don't see it in the heroku logs when I deploy, but ??
Now somewhat curious. I've made the issue go away, by forcing the app to load each model in the engine, one at a time. Things seem to run smoothly after that.
Any suggestions on how to dubug this
This is directly linked to config.eager_load settings of your app. In production it is set to true so you do not have the circular dependency problem, in development it is generally set to false and that's where rails auto loading systems may trigger this kind of error.
I do believe (though I'm not certain) that you can solve this by not declaring nested classes and modules in one single line
Instead of
class MyModule::MyClass
...
end
Use
module MyModule
class MyClass
...
end
end

Rails 3.0.9 + open_id_authentication

I'm using open_id_authentication gem to authenticate to google. In my sessions controller I call
authenticate_with_open_id(complete_identity_url, OPENID_OPTS) do |openid_result, identity_url, registration|
and it returns 401 status code Unauthenticated. But it should show google page in which I must confirm access.
I made example app: https://github.com/mbashirov/rails3-test, it only has code in sessions controller and routes set.
That code works perfectly on rails 2.3 app. There is error?
Thanks.
Solution.
In sessions controller add
class SessionsController < ApplicationController
include OpenIdAuthentication
In config/application.rb add
config.app_middleware.use OpenIdAuthentication
After this two steps all works fine.
If it works in 2.3 and then doesn't work in 3, it sounds like an error not of your own making.
Next steps:
1) Upgrade to latest 3.1 (or better 3.1.1) Rails
2) Contact the authors of the gem to see what their 3.1 support plans are. They may already be working on a solution that you can help test.
3) If you have the skills, it would be awesome for you to contribute back by solving the problem.
I suggest that you start with an Ether peek tool such as Fiddler or a Mac tool to see if your machine is sending out the same requests/getting the same responses when running 3.1.1 vs 2.3.
Then debug....

Ruby and/or Rails caching require()'ed scripts?

I'm testing out a basic Rails app and I seem to be getting some undesirable caching behavior on a library script that's being require()'ed into my controller script.
Suppose FooController.rb contains the following:
require 'utils' # a library script
class FooController
def some_action
#some_member = do_something() # global method defined in utils.rb
end
end
It appears that changes to utils.rb do not take effect until I restart the Rails server. I don't believe this is due to a misconfiguration of Rails' class caching, since a) I am running in a "development" environment, and b) I can make changes directly to the controller code (e.g., to the some_action method above) that are reflected upon the next execution of the script. I've been testing this with some calls to puts that spam messages into the console.
Is there some behavior in either Ruby or Rails that would cause require()-ed scripts to remain cached? If so, is there a way to configure that behavior?
Rails class reloader is relatively naive. I believe it's only intended to reload things like controllers and models, leaving anything you might be require'ing into your project alone. So, if you have some custom code in the lib directory or elsewhere that you have changed it is expected behavior for you to have to restart the Rails server.
If you want to require each time the code is encountered, you really want load.
http://www.ruby-doc.org/core/Kernel.html#method-i-load

Renaming controllers in Rails and cleaning out generated content

I was following along with the railscast regarding the restful_authentication plugin.
He recommended running the command:
script/generate authenticated user session
Which I did, and everything generated "fine", but then sessions wouldn't work. Checking the site again, he mentions a naming standard and listed updated code which stated:
script/generate authenticated user sessions
With sessions being pluralized.
So now I have session_controller.rb with a SessionController in it, but I guess by naming standards, it is looking for SessionsController, causing the code to fail out with the error "NameError in SessionsController#create "
I see the problem, which is pretty obvious, but what I don't know is, how do I fix this without regenerating the content? Is there a way to reverse the generation process to clear out all changes made by the generation?
I tried just renaming the files to sessions_controller with e SessionsController class, but that failed.
While writing this, I solved my own problem. I had to rename session to sessions in the routes file as a map.resource and rename the view directory from session to sessions, and update session_path in the html.erb file to sessions_path.
So I solved my problem, but my answer regarding removing generated content still remains. Is it possible to ungenerate content?
Actually, script/destroy works for any generator - generators work by reading a script of sorts on what files to create; script/destroy just reads that script in reverse and removes all the files created, as long as you give it the same arguments you passed to script/generate.
To sum up: script/destroy authenticated user session would have removed all the generated files for you, after which you could have run script/generate user sessions without a problem.
I've never tried script/destroy, but if you're reverting changes that you just made, the generate command should give you a list of files added and changes made. If you're using a version control system of some sort, running status/diff might help as well.
You can just roll back to the previous revision in subversion, and start again, right? right? :-)
rails has script/destroy for 'ungenerating' stuff, but I suspect that will only work for the stuff rails ships with, not the restful authentication plugin.
I'd say your best bet is find-in-files (or grep -R if you're not using an IDE) - find everything that refers to your old SessionController and change it

Resources