* This change abstracts the DatadogStatsClient into a ForemStatsClient. The purpose of this abstraction is to set the foundation for a subsequent PR that will allow one to use New Relic for recording Forem stats, instead of Datadog, if there is a New Relic configuration found. This specific change creates an abstraction layer that can be built upon, without changing any actual default behavior. All specs still pass. * Use delegate instead of explicit methods. * Delegate instead of explicit methods. * Fix the error. * Refactor according to the suggestions in the comments. * Ooops. Stats work better when all of the code is committed. * Removing the alias of count to increment since that was done in error.
65 lines
2.1 KiB
Ruby
65 lines
2.1 KiB
Ruby
module Search
|
|
# Search client (uses Elasticsearch as a backend)
|
|
class Client
|
|
class << self
|
|
# adapted from https://api.rubyonrails.org/classes/Module.html#method-i-delegate_missing_to
|
|
def method_missing(method, *args, &block)
|
|
return super unless target.respond_to?(method, false)
|
|
|
|
# define for re-use
|
|
self.class.define_method(method) do |*new_args, &new_block|
|
|
request do
|
|
target.public_send(method, *new_args, &new_block)
|
|
end
|
|
end
|
|
|
|
# call the original method, this will only be called the first time
|
|
# as in subsequent calls, the newly defined method will prevail
|
|
request do
|
|
target.public_send(method, *args, &block)
|
|
end
|
|
end
|
|
|
|
# adapted from https://api.rubyonrails.org/classes/Module.html#method-i-delegate_missing_to
|
|
def respond_to_missing?(method, _include_all = false)
|
|
target.respond_to?(method, false) || super
|
|
end
|
|
|
|
private
|
|
|
|
TRANSPORT_EXCEPTIONS = [
|
|
Elasticsearch::Transport::Transport::Errors::BadRequest,
|
|
Elasticsearch::Transport::Transport::Errors::NotFound,
|
|
].freeze
|
|
|
|
def request
|
|
yield
|
|
rescue *TRANSPORT_EXCEPTIONS => e
|
|
class_name = e.class.name.demodulize
|
|
record_error(e.message, class_name)
|
|
|
|
# raise specific error if known, generic one if unknown
|
|
error_class = "::Search::Errors::Transport::#{class_name}".safe_constantize
|
|
raise error_class, e.message if error_class
|
|
|
|
raise ::Search::Errors::TransportError, e.message
|
|
end
|
|
|
|
def record_error(error_message, class_name)
|
|
Honeycomb.add_field("elasticsearch.result", "error")
|
|
Honeycomb.add_field("elasticsearch.error", class_name)
|
|
ForemStatsClient.increment("elasticsearch.errors", tags: ["error:#{class_name}", "message:#{error_message}"])
|
|
end
|
|
|
|
def target
|
|
@target ||= Elasticsearch::Client.new(
|
|
url: ApplicationConfig["ELASTICSEARCH_URL"],
|
|
retry_on_failure: 5,
|
|
request_timeout: 30,
|
|
adapter: :patron,
|
|
log: Rails.env.development?,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|