diff --git a/lib/ddtrace.rb b/lib/ddtrace.rb index 13353ff810b..83f712fa82c 100644 --- a/lib/ddtrace.rb +++ b/lib/ddtrace.rb @@ -50,7 +50,7 @@ def configure(target = configuration, opts = {}) require 'ddtrace/contrib/concurrent_ruby/integration' require 'ddtrace/contrib/dalli/patcher' require 'ddtrace/contrib/delayed_job/integration' -require 'ddtrace/contrib/elasticsearch/patcher' +require 'ddtrace/contrib/elasticsearch/integration' require 'ddtrace/contrib/excon/patcher' require 'ddtrace/contrib/faraday/patcher' require 'ddtrace/contrib/grape/patcher' diff --git a/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb b/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb new file mode 100644 index 00000000000..5fd362d095e --- /dev/null +++ b/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb @@ -0,0 +1,16 @@ +require 'ddtrace/contrib/configuration/settings' +require 'ddtrace/contrib/elasticsearch/ext' + +module Datadog + module Contrib + module Elasticsearch + module Configuration + # Custom settings for the Elasticsearch integration + class Settings < Contrib::Configuration::Settings + option :quantize, default: {} + option :service_name, default: Ext::SERVICE_NAME + end + end + end + end +end diff --git a/lib/ddtrace/contrib/elasticsearch/ext.rb b/lib/ddtrace/contrib/elasticsearch/ext.rb new file mode 100644 index 00000000000..ae34391d6ac --- /dev/null +++ b/lib/ddtrace/contrib/elasticsearch/ext.rb @@ -0,0 +1,18 @@ +module Datadog + module Contrib + module Elasticsearch + # Elasticsearch integration constants + module Ext + APP = 'elasticsearch'.freeze + SERVICE_NAME = 'elasticsearch'.freeze + + SPAN_QUERY = 'elasticsearch.query'.freeze + + TAG_BODY = 'elasticsearch.body'.freeze + TAG_METHOD = 'elasticsearch.method'.freeze + TAG_PARAMS = 'elasticsearch.params'.freeze + TAG_URL = 'elasticsearch.url'.freeze + end + end + end +end diff --git a/lib/ddtrace/contrib/elasticsearch/integration.rb b/lib/ddtrace/contrib/elasticsearch/integration.rb new file mode 100644 index 00000000000..c0996dbe941 --- /dev/null +++ b/lib/ddtrace/contrib/elasticsearch/integration.rb @@ -0,0 +1,37 @@ +require 'ddtrace/contrib/integration' +require 'ddtrace/contrib/elasticsearch/configuration/settings' +require 'ddtrace/contrib/elasticsearch/patcher' + +module Datadog + module Contrib + module Elasticsearch + # Description of Elasticsearch integration + class Integration + include Contrib::Integration + + register_as :elasticsearch, auto_patch: true + + def self.version + Gem.loaded_specs['elasticsearch-transport'] \ + && Gem.loaded_specs['elasticsearch-transport'].version + end + + def self.present? + super && defined?(::Elasticsearch::Transport) + end + + def self.compatible? + super && version >= Gem::Version.new('1.0.0') + end + + def default_configuration + Configuration::Settings.new + end + + def patcher + Patcher + end + end + end + end +end diff --git a/lib/ddtrace/contrib/elasticsearch/patcher.rb b/lib/ddtrace/contrib/elasticsearch/patcher.rb index 28ce02c98bf..1befbad9997 100644 --- a/lib/ddtrace/contrib/elasticsearch/patcher.rb +++ b/lib/ddtrace/contrib/elasticsearch/patcher.rb @@ -1,45 +1,34 @@ -# requirements should be kept minimal as Patcher is a shared requirement. +require 'ddtrace/contrib/patcher' +require 'ddtrace/ext/app_types' +require 'ddtrace/ext/net' +require 'ddtrace/contrib/elasticsearch/ext' module Datadog module Contrib module Elasticsearch - URL = 'elasticsearch.url'.freeze - METHOD = 'elasticsearch.method'.freeze - PARAMS = 'elasticsearch.params'.freeze - BODY = 'elasticsearch.body'.freeze - - SERVICE = 'elasticsearch'.freeze - - # Patcher enables patching of 'elasticsearch/transport' module. + # Patcher enables patching of 'elasticsearch' module. module Patcher - include Base - register_as :elasticsearch, auto_patch: true - option :service_name, default: SERVICE - option :quantize, default: {} - - @patched = false + include Contrib::Patcher module_function - # patch applies our patch if needed + def patched? + done?(:elasticsearch) + end + def patch - if !@patched && (defined?(::Elasticsearch::Transport::VERSION) && \ - Gem::Version.new(::Elasticsearch::Transport::VERSION) >= Gem::Version.new('1.0.0')) + do_once(:elasticsearch) do begin require 'uri' require 'json' require 'ddtrace/pin' - require 'ddtrace/ext/app_types' require 'ddtrace/contrib/elasticsearch/quantize' - patch_elasticsearch_transport_client() - - @patched = true + patch_elasticsearch_transport_client rescue StandardError => e - Datadog::Tracer.log.error("Unable to apply Elastic Search integration: #{e}") + Datadog::Tracer.log.error("Unable to apply Elasticsearch integration: #{e}") end end - @patched end # rubocop:disable Metrics/MethodLength @@ -54,7 +43,11 @@ def patch_elasticsearch_transport_client def initialize(*args, &block) service = Datadog.configuration[:elasticsearch][:service_name] - pin = Datadog::Pin.new(service, app: 'elasticsearch', app_type: Datadog::Ext::AppTypes::DB) + pin = Datadog::Pin.new( + service, + app: Datadog::Contrib::Elasticsearch::Ext::APP, + app_type: Datadog::Ext::AppTypes::DB + ) pin.onto(self) initialize_without_datadog(*args, &block) end @@ -74,29 +67,29 @@ def perform_request(*args) url = full_url.path response = nil - pin.tracer.trace('elasticsearch.query') do |span| + pin.tracer.trace(Datadog::Contrib::Elasticsearch::Ext::SPAN_QUERY) do |span| begin connection = transport.connections.first host = connection.host[:host] if connection port = connection.host[:port] if connection span.service = pin.service - span.span_type = Ext::AppTypes::DB + span.span_type = Datadog::Ext::AppTypes::DB # load JSON for the following fields unless they're already strings params = JSON.generate(params) if params && !params.is_a?(String) body = JSON.generate(body) if body && !body.is_a?(String) - span.set_tag(METHOD, method) - span.set_tag(URL, url) - span.set_tag(PARAMS, params) if params + span.set_tag(Datadog::Contrib::Elasticsearch::Ext::TAG_METHOD, method) + span.set_tag(Datadog::Contrib::Elasticsearch::Ext::TAG_URL, url) + span.set_tag(Datadog::Contrib::Elasticsearch::Ext::TAG_PARAMS, params) if params if body quantize_options = Datadog.configuration[:elasticsearch][:quantize] quantized_body = Datadog::Contrib::Elasticsearch::Quantize.format_body(body, quantize_options) - span.set_tag(BODY, quantized_body) + span.set_tag(Datadog::Contrib::Elasticsearch::Ext::TAG_BODY, quantized_body) end - span.set_tag('out.host', host) if host - span.set_tag('out.port', port) if port + span.set_tag(Datadog::Ext::NET::TARGET_HOST, host) if host + span.set_tag(Datadog::Ext::NET::TARGET_PORT, port) if port quantized_url = Datadog::Contrib::Elasticsearch::Quantize.format_url(url) span.resource = "#{method} #{quantized_url}" @@ -105,18 +98,13 @@ def perform_request(*args) ensure # the call is still executed response = perform_request_without_datadog(*args) - span.set_tag('http.status_code', response.status) + span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.status) end end response end end end - - # patched? tells wether patch has been successfully applied - def patched? - @patched - end end end end