How to limit one transactions in Sentry for Ruby App - ruby-on-rails

In my Sentry, one transaction occurs too often (rails request: ApiController#start). I want to limit this, or turn off. Only for this one.
How to do that?
config/initializers/sentry.rb:
Sentry.init do |config|
config.dsn = 'https://.......'
config.breadcrumbs_logger = [:active_support_logger, :http_logger]
# To activate performance monitoring, set one of these options.
# We recommend adjusting the value in production:
config.traces_sample_rate = 1.0
# or
config.traces_sampler = lambda do |context|
true
end
config.environment = 'production'
end

Related

Rails 6.1 development environment not printing query trigger code line with verbose active

I have both lines:
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
ActiveRecord::Base.verbose_query_logs = true
in my config/environments/development/rb
But in my development log the sql queries are logged like:
2022-08-10 08:35:18.536410 D [74:puma srv tp 004] (0.006ms) ActiveRecord -- Model Load -- { :sql => "SELECT ....", :binds => { .... }, :allocations => 1, :cached => true }
I have an N+1 queries issue to fix, but the information about which line in the code triggered the query is missing, so this is not helping me much.
I tried also using active-record-query-trace gem, with configuration:
if Rails.env.development?
ActiveRecordQueryTrace.enabled = true
ActiveRecordQueryTrace.level = :full
ActiveRecordQueryTrace.colorize = true # No colorization (default)
ActiveRecordQueryTrace.colorize = :light_purple
# Optional: other gem config options go here
end
but I see no changes at all in how queries are logged.
How can I enable the logging of the line triggering the query?
Thanks
If you want to know the reference point that made a DB query I used to use a gem called Marginalia. I use it in Rails 6 and it does exactaly what you are looking for.
From what I am reading Rails 7 includes this feature as a native feature (which is quite awesome I might add).
I found a link that talks about this:
Rails 7 includes Marginalia
Their example says:
# config/application.rb
module Saeloun
class Application < Rails::Application
config.active_record.query_log_tags_enabled = true
end
end

Rails app GET routes not working in production mode

I've inherited a Rails application that isn't completely functional when running in production mode. GET requests to the server are resulting in a no route match found error; however, when the server is run in development mode all routes will work, giving an expected 200 status.
Reviewing the code reveals that the application expects a prefixed subdomain in addition to the domain used in a successful URL request.
class ApplicationContext
def initialize(subdomain, host_with_port)
if subdomain.present?
case subdomain
when Rails.application.config.workninja.admin_subdomain
#environment = :admin
when Rails.application.config.workninja.mobile_subdomain
#environment = :mobile
else
#environment = :customer
end
else
raise 'Could not initialize ApplicationContext without subdomain'
end
#url_options = {subdomain: subdomain, host: host_with_port}
setup_method = "setup_#{#environment.to_s}_environment".to_sym
if respond_to?(setup_method, true)
send(setup_method, subdomain, host_with_port)
else
raise 'Unknown context environment'
end
end
attr_reader :environment
attr_reader :url_options
attr_reader :agency
def self.current
Thread.current['workninja:tenant_context']
end
def admin?
#environment == :admin
end
def mobile?
#environment == :mobile
end
def customer?
#environment == :customer
end
def ui_url_for(path, subdomain = url_options[:subdomain])
base = "#{Rails.application.config.workninja.https ? 'https' :
'http'}://#{subdomain}.#{Rails.application.config.workninja.domain}"
if Rails.application.config.workninja.html5mode
puts URI.join(base, path).to_s
else
puts URI.join(base, "/#/#{path}".gsub(/\/+/, '/')).to_s
end
end
The original front end supplied with the application constructs the request's URLs depending on the environment the sever was launched in.
{
"environment": "development",
"url": "http://admin.workninja.local:3000"
}
{
"environment": "production",
"url": "/api"
}
To me the production URL doesn't make sense as all it does is append "/api" to the root domain that the front end is hosted on. I can only assume that it's just a placeholder that needs to be replaced with the domain name that the rails server is hosted on once it's running in a live environment. The "/api" path isn't used throughout the functional development version of the app which makes me further assume it's a placeholder.
Using the above as a guide I replaced "/api" with "http://admin.workninja.com.au". After hosting the application on a live domain I confirmed it was working by running:
curl http://admin.workninja.com.com.au/auth -X POST
This gave me an expected error about credentials not being supplied but it shows that the server is actually receiving something. If you haven't realised the rails server when launched in production mode will respond to a POST request but still not a GET.
This is where my understanding of the problem breaks down. If
http://admin.workninja.local:3000/roles
works ("/roles being one of the applications routes") in a development environment why doesn't
http://admin.workninja.com.au/roles
work in a production environment as well? Can you assume from this fact that something isn't broken in the ruby codebase?
Below are some of the files relating to the configuration of the rails application in a production environment.
/config/deploy/production.rb
set :branch, 'master'
server 'ec2-54-66-230-174.ap-southeast-2.compute.amazonaws.com', user: 'ubuntu', roles: %w{app web db worker}
/config/environments/production.rb
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
# This needs to be set to true in order for rails to launch in a production environment
config.eager_load = false
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like
# NGINX, varnish or squid.
# config.action_dispatch.rack_cache = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :warn
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# Application hostname
config.surgeforce.domain = 'surgeforce.com.au'
config.surgeforce.https = false
config.surgeforce.html5mode = true
end
/config/puma.rb
threads 1, 6
workers Integer(ENV['PUMA_WORKERS'] || 3)
on_worker_boot do
require "active_record"
cwd = File.dirname(__FILE__)+"/.."
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"] || YAML.load_file("#{cwd}/config/database.yml")[ENV["RAILS_ENV"]])
end
If you believe any other piece of the applications code to be critical in the investigation let me know and I'll include it.
The problem is that Rails' subdomain method is very simple and doesn't know anything about the structure of com.au domains. For "admin.workninja.com.au" which you use on production, the subdomain method would return "admin.workninja". From the docs:
Returns all the \subdomains as a string, so "dev.www" would be
returned for "dev.www.rubyonrails.org". You can specify a different tld_length, such as 2 to catch "www" instead of "www.rubyonrails" in "www.rubyonrails.co.uk".
And – without knowing your configuration– "admin.workninja" will very likely not match your config.workninja.admin_subdomain configuration anymore.
The solution is to configure a tld length of 2 on production. Just add the following to the configuration block in your config/environments/production.rb:
config.action_dispatch.tld_length = 2 # Defaults to 1

How do I get Rails to load my test envionrment variables when I run tests?

I'm using Rails 5. I have this file, config/environment_variables.yml
development:
COINBASE_KEY: devkey
COINBASE_SECRET: devsecret
test:
COINBASE_KEY: testkey
COINBASE_SECRET: testsecret
production:
COINBASE_KEY: prodkey
COINBASE_SECRET: prodsecret
I load it with the file, config/initializers/environment_variables.rb
module EnvironmentVariables
class Application < Rails::Application
config.before_configuration do
env_file = Rails.root.join("config", 'environment_variables.yml').to_s
if File.exists?(env_file)
YAML.load_file(env_file)[Rails.env].each do |key, value|
ENV[key.to_s] = value
end # end YAML.load_file
end # end if File.exists?
end # end config.before_configuration
end # end class
end # end module
but when I run my test using
rails test test/services/crypto_currency_service_test.rb
The test variables aren't loading -- rather those from the dev environment are loading. Below is my test file
require 'coinbase/wallet'
require 'minitest/mock'
class CryptoCurrencyServiceTest < ActiveSupport::TestCase
test 'sell' do
last_transaction = MyTransaction.new({
:transaction_type => "buy",
:amount_in_usd => "100",
:btc_price_in_usd => "3000"
})
puts "env: #{ENV['COINBASE_KEY']}"
#client = Coinbase::Wallet::Client.new(api_key: ENV['COINBASE_KEY'], api_secret: ENV['COINBASE_SECRET'])
How do I get the test variables to load by default when I run tests?
Edit: Here's the config/environments/test.rb file, which I haven't (consciously) changed ...
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=3600'
}
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end
I would not recommend to write custom code for this. There are existing solutions for setting up environment variables. See dotenv-rails for example. It allows you to put common variables into .env file. Just add gem 'dotenv-rails' to your Gemfile and put common variables into .env file:
# .env
COINBASE_KEY: devkey
COINBASE_SECRET: devsecret
If you need environment-specific variables it allows you to have separate files for this: .env.development, .env.test and .env.production:
#.env.test
COINBASE_KEY: testkey
COINBASE_SECRET: testsecret
#.env.production
COINBASE_KEY: prodkey
COINBASE_SECRET: prodsecret
From the comments in your original post, I suggest checking if config.before_configuration block is not at fault. Might be the case that the rails environment is loaded after that block has run and so you get Rails.env == 'test' when you print that out inside a test, but in the configuration it takes keys from default (development) environment.
Might I suggest moving this part
env_file = Rails.root.join("config", 'environment_variables.yml').to_s
if File.exists?(env_file)
YAML.load_file(env_file)[Rails.env].each do |key, value|
ENV[key.to_s] = value
end # end YAML.load_file
end # end if File.exists?
out in an intializer and then check the environment variables. Might fix the problem. (because initializers surely should respect the environment)
UPDATE: From the documentation it seems that before_configuration block is the VERY first block config part to run, so Rails.env is probably not yet set at that point.

Rails 4 Active Admin Problems

I am having two big problems with Active Admin
When I go to edit a user the encrypted password does not show so essentially i'm having to hack my own site and copy and paste another encrypted password in to the field to update the user - this is the same with create user.
The second issue is I cannot create a new user. When I go to create a user nothing happens. I don't get an error. The page just refreshes and the user does not save.
User.rb
ActiveAdmin.register User do
controller do
def permitted_params
params.permit!
end
end
end
I tried destroying my install of active admin and then I reinstalled it and generated the models again but same result. I'm using Rails 4.2.1 and Ruby 2.0.0.
gem 'activeadmin', github: 'activeadmin'
In development.rb
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end
I tried changing config.cache_classes = false to true but that does not work either.
I'm not sure what to do here. Any suggestions? I take it this is a bug. Hope it can be fixed. Thanks.
It appears you're permitted_params method in your app/admin/user.rb file is unconventional and could be causing you problems. You need to add them like this and also put in :encrypted_password if you want to be able to change/edit it ...
ActiveAdmin.register User do
permit_params :email, :password, :password_confirmation, :encrypted_password
...
end

rails custom_configuration gem produces empty orderedoptions

Ruby 2.1.5
Rails 4.0.13
Using the custom_configuration gem, I get unexpected results.
config/environments/development.rb
JumboSIP::Application.configure do
# Settings specified here will take precedence over those in config/application.rb.
module Devise
module LdapAdapter
def self.valid_credentials?(login, password)
return true
end
end
end
config.cache_store = :memory_store
config.log_level = :debug
config.assets.compile = true
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
[..etc]
# ------------------------------------
# Application-specific configuration
# ------------------------------------
# use active directory auythentication (only for production)
config.x.use_ad_auth = false
# Enable to create cockpit cache files
config.x.cockpit_cache_enabled = false
config/initializers/scheduler.rb
if Rails.configuration.x.cockpit_cache_enabled
Rails.logger.info 'Initializing Cockpit Cache Scheduler'
puts 'Initializing Cockpit Cache Scheduler'
The code in the if is reached while it should not.
Debug inspection shows that
Rails.configuration.x.cockpit_cache_enabled evaluates to Empty ActiveSupport:OrderedOptions.
Rails.configuration.x is of type CustomConfiguration::Configuration
I checked I am actually in development environment.
Any clue as to why this happens? Any conflicts with other gems?
If I uses orderedoptions outside this gem, behaviour is as expected
It's two months delayed, but I ran into the same issue. The custom_configuration gem expects the options to be namespaced under another hash. Instead of:
config.x.cockpit_cache_enabled = false
try:
config.x.cockpit.cache_enabled = false
Now you should be able to access the value with:
Rails.configuration.x.cockpit.cache_enabled

Resources