docbrown/app/services/search/client.rb
Kirk Haines ed74f2f245
Abstract DatadogStatsClient to ForemStatsClient (#12304)
* 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.
2021-01-27 11:25:44 -05:00

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