I'm working on a Rails site that I did not create, and some of my log messages are hard to find in the sea of "Expire fragment" messages in log/production.log. It does not seem to indicate any sort of problem, so I'd like to suppress those messages and make it easy to find the messages my code is generating. Is there any way to suppress them?
You can try overriding the logger in an initializer, like here.
# Create logger that ignores messages containing “CACHE”
class CacheFreeLogger < ::Logger
def debug(message, *args, &block)
super unless message.include? 'Expire fragment'
end
end
# Overwrite ActiveRecord’s logger
ActiveRecord::Base.logger = ActiveSupport::TaggedLogging.new(
CacheFreeLogger.new(STDOUT)) unless Rails.env.test?
Related
I ran into a problem, when PG fails out of sync (well known problem)(example).
PG fails out of sync, sequence of id stops incrementing and raises ActiveRecord::RecordNotUnique error.
But all solutions proposed here (all I found) propose some manual solutions - either do some operations in console, either run custom rake task.
However, I find this unsatisfying for production: each times it happens, users get 500, while someone administrating server should operatively save the day. (And according to test data for some reason it possible will occur frequently in my case).
So I would like rather to patch ActiveRecord Base class to catch this specific error and rescue it.
I use this logic sometimes in controller:
class ApplicationController < ActionController::Base
rescue_from ActionController::ParameterMissing, ActiveRecord::RecordNotFound do |e|
# some logic here
end
end
However, here I don't need retry. Also, I would like to not to go deep in monkey patching, for example, without overriding Base create method.
So I was thinking of something like this:
module ActiveRecord
class Base
rescue ActiveRecord::RecordNotUnique => e
if e.message.include? '_pkey'
table =e.message.match(//) #regex to define table
ActiveRecord::Base.connection.reset_pk_sequence!(table)
retry
else
raise
end
end
end
But it most likely doesn't work, as I'm not sure if Rails/Ruby will understand what exactly it asked to retry.
Is there any solution?
P.S. Not related solution for overall problem of sequence which will work without manual command line commands and having unserved users are also appreciated.
To answer the question you're asking, no. rescue can only be used from within a begin..end block or method body.
begin
bad_method
rescue SomeException
retry
end
def some_method
bad_method
rescue SomeException
retry
end
rescue_from is just a framework helper method created because of how indirect the execution is in a controller.
To answer the question you're really asking, sure. You can override create_or_update with a rescue/retry.
module NonUniquePkeyRecovery
def create_or_update(*)
super
rescue ActiveRecord::RecordNotUnique => e
raise unless e.message.include? '_pkey'
self.class.connection.reset_pk_sequence!(self.class.table_name)
retry
end
end
ActiveSupport.on_load(:active_record) do
include NonUniquePkeyRecovery
end
I'm running a sidekiq application on heroku with papertrails addon and I use exceptions to fail jobs. For each exception full stacktrace is stored in papertrail logs which is definitely not what I want.
I didn't find a way how to turn off that feature. Could you give me a hint what I could do with that?
Maybe I should handle job failing in a different way?
Thanks!
Here's a modification of the standard error logger that limits the backtrace logging to the lines unique to the application:
class ExceptionHandlerLogger
def call(ex, ctxHash)
Sidekiq.logger.warn(Sidekiq.dump_json(ctxHash)) if !ctxHash.empty?
Sidekiq.logger.warn "#{ex.class.name}: #{ex.message}"
unless ex.backtrace.nil?
Sidekiq.logger.warn filter_backtrace(ex.backtrace).join("\n")
end
end
def filter_backtrace(backtrace)
index = backtrace.index { |item| item.include?('/lib/sidekiq/processor.rb') }
backtrace.first(index.to_i)
end
end
if !Sidekiq.error_handlers.delete_if { |h| h.class == Sidekiq::ExceptionHandler::Logger }
fail "default sidekiq logger class changed!"
end
Sidekiq.error_handlers << ExceptionHandlerLogger.new
i'm on the way of redesigning my activity feed, i already implemented the logic with redis and rails (wich works great by the way) but i'm still unsure how to create/trigger the events.
In my first approach i used observer, which had the downside of not having current_user available. and, using observer is a bad idea anyways :)
My preferred method would be to create/trigger the events in the controller, which should look sth like:
class UserController < LocationController
def invite
...
if user.save
trigger! UserInvitedEvent, {creator: current_user, ...}, :create
....
end
end
end
The trigger method should
create the UserInvitedEvent with some params. (:create can be default option)
could be deactivate (e.g. deactivate for testing)
could be executed with e.g. resque
i looked in some gems (fnordmetrics, ...) but i could not find a slick implementation for that.
I'd build something like the following:
# config/initializers/event_tracking.rb
modlue EventTracking
attr_accessor :enabled
def enable
#enabled = true
end
def disable
#enabled = false
end
module_function
def Track(event, options)
if EventTracking.enabled
event.classify.constantize.new(options)
end
end
end
include EventTracking
EventTracking.enable unless Rails.env.test?
The module_function hack let's us have the Track() function globally, and exports it to the global namespace, you (key thing is that the method is copied to the global scope, so it's effectively global, read more here: http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-module_function)
Then we enable tracking for all modes except production, we call event.classify.constantize in Rails that should turn something like :user_invited_event into UserInvitedEvent, and offers the possibility of namespacing, for example Track(:'users/invited'). The semantics of this are defined by ActiveSupport's inflection module.
I think that should be a decent start to your tracking code I've been using that in a project with a lot of success until now!
With the (new) rails intrumentation and ActiveSupport::Notifications system you can completely decouple the notification and the actual feed construction.
See http://railscasts.com/episodes/249-notifications-in-rails-3?view=asciicast
I want to write a logging model and controller, to log everything that user does. I was thinking about creating a db table with from ip address, controller that user called, view that was displayed and params.inspect.
Is there a way to get to a variable which controller is currently being used? What is the best way to deploy this? Is out there a gem that do all this?
Thank you
If you set the log level in production to :debug then every request is logged with the information you need. Perhaps, it might be easier to write a parser for the debug production log.
If you prefer, you can also add a filter to your ApplicationController:
class ApplicationController
before_filter :log_activity
def log_activity
if Rails.env == 'production'
#logger ||= Logger.new("#{Rails.root}/log/activity.log")
values = [
request.remote_ip,
controller_name,
action_name,
params.inspect
]
#logger.info "#{values.join ' | '}"
end
end
...
end
this might not be complete as you want the output to be more verbose, but this is the idea.
I am upgrading a Rails 2 to Rails 3 application (code not written by me).
The (well tested code) uses shoulda and Test::Unit, and extensively uses the macros should_create and should_change.
I understand from this discussion that the shoulda maintainers want to get rid of both methods but that people using Test::Unit don't find it necessary (not sure I am grasping the whole discussion though).
Anaway, is there a way to selectively turn of the deprecation warnings for specified macros? I already know from this posting that you can turn off the deprecation warnings in the Rake test output entirely by setting:
ActiveSupport::Deprecation.silenced = true
in your the test environment file and I also know that you can put specific pieces of code in a block to get them silenced:
ActiveSupport::Deprecation.silence do
# no warnings for any use of deprecated methods here
end
The latter is an option but would require me to go over all the tests and enclose the should_create macros in such a block. So I was wondering there was a way to eliminate warnings for specific macros entirely with one configuration setting?
Old question - but if you have new depreciations you'd like to selectively ignore:
ActiveSupport::Deprecation.behavior = lambda do |msg, stack|
unless /LIBRARY_NAME/ =~ msg
ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:stderr].call(msg,stack) # whichever handlers you want - this is the default
end
end
This is for ActiveSupport 3.
In fact I stil had lots of other deprecation warnings from code that was in plugins or gems I had installed. In order to avoid most of that, I overwrote the Deprecation::warn method in test_helper.rb. So instead of the previous code, use:
module ActiveSupport
module Deprecation
class << self
def warn(message = nil, callstack = caller)
# modif pvh the following lines make sure no deprecation warnings are sent
# for code that is
# not by my but in some gem or plugin...
return if silenced || callstack.grep(/myrailsappname/).blank?
# return if silenced
deprecation_message(callstack, message).tap do |m|
behavior.each { |b| b.call(m, callstack) }
end
end
end
end
end
BTW you need to replace myrailsappname with your app's name (the name of the folder it resides in). There is probably a more generic way to get that name, but I couldn't find it right now.
Can I recommend an alternative?
module ActiveSupport
class Deprecation
module Reporting
# Mute specific deprecation messages
def warn(message = nil, callstack = nil)
return if message.match(/Automatic updating of counter caches/)
super
end
end
end
end
I think I have found a solution: in test/test_helper.rb I reopened the module and overwrote macro definition with an identical definition but the deprecation warning commented out. There are probably much more elegant ways to do this though...
# modif pvh DEPREC
# reopen the module and silence the deprecation statement to avoid
# having my results overflown by these deprecation warnings...
module Shoulda # :nodoc:
module Macros
def should_create(class_name)
##::ActiveSupport::Deprecation.warn
should_change_record_count_of(class_name, 1, 'create')
end
end
end
Create a file called selective_deprecation_silencer.rb in your config/initializers folder with the following content:
#place in the following array the messages you want to silence
silenced = [/Using a dynamic :action segment in a route is deprecated/,
/Using a dynamic :controller segment in a route is deprecated/]
silenced_expr = Regexp.new(silenced.join('|'))
ActiveSupport::Deprecation.behavior = lambda do |msg, stack, deprecation_horizon, gem_name|
unless msg =~ silenced_expr
ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:stderr].call(msg, stack, deprecation_horizon, gem_name)
end
end