Skip to content

Commit

Permalink
change elasticsearch patcher from alias to prepend method.
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahchen6 committed Aug 7, 2023
1 parent 8bc9600 commit 6066c4c
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 108 deletions.
5 changes: 2 additions & 3 deletions gemfiles/ruby_3.1.2_contrib.gemfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

199 changes: 94 additions & 105 deletions lib/datadog/tracing/contrib/elasticsearch/patcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,126 +19,115 @@ def target_version
Integration.version
end

# `Elasticsearch` namespace renamed to `Elastic` in version 8.0.0 of the transport gem:
# @see https://github.com/elastic/elastic-transport-ruby/commit/ef804cbbd284f2a82d825221f87124f8b5ff823c
def transport_module
if Integration.version >= Gem::Version.new('8.0.0')
::Elastic::Transport
else
::Elasticsearch::Transport
end
end

def patch
require 'uri'
require 'json'
require_relative 'quantize'

patch_elasticsearch_transport_client
transport_module::Client.prepend(Client)
end

SELF_DEPRECATION_ONLY_ONCE = Core::Utils::OnlyOnce.new

# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def patch_elasticsearch_transport_client
# rubocop:disable Metrics/BlockLength
transport_module::Client.class_eval do
alias_method :perform_request_without_datadog, :perform_request
remove_method :perform_request

def perform_request(*args)
# DEV-2.0: Remove this access, as `Client#self` in this context is not exposed to the user
# since `elasticsearch` v8.0.0. In contrast, `Client#transport` is always available across
# all `elasticsearch` gem versions and should be used instead.
service = Datadog.configuration_for(self, :service_name)

if service
SELF_DEPRECATION_ONLY_ONCE.run do
Datadog.logger.warn(
'Providing configuration though the Elasticsearch client object is deprecated.' \
'Configure the `client#transport` object instead: ' \
'Datadog.configure_onto(client.transport, service_name: service_name, ...)'
)
end
# Patches Elasticsearch::Transport::Client module
module Client
def perform_request(method, path, params = {}, body = nil)
# DEV-2.0: Remove this access, as `Client#self` in this context is not exposed to the user
# since `elasticsearch` v8.0.0. In contrast, `Client#transport` is always available across
# all `elasticsearch` gem versions and should be used instead.
service = Datadog.configuration_for(self, :service_name)

if service
SELF_DEPRECATION_ONLY_ONCE.run do
Datadog.logger.warn(
'Providing configuration though the Elasticsearch client object is deprecated.' \
'Configure the `client#transport` object instead: ' \
'Datadog.configure_onto(client.transport, service_name: service_name, ...)'
)
end
end

# `Client#transport` is most convenient object both this integration and the library
# user have shared access to across all `elasticsearch` versions.
#
# `Client#self` in this context is an internal object that the library user
# does not have access to since `elasticsearch` v8.0.0.
service ||= Datadog.configuration_for(transport, :service_name) || datadog_configuration[:service_name]

full_url = URI.parse(path)
url = full_url.path
response = nil

Tracing.trace(Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_QUERY, service: service) do |span|
begin
connection = transport.connections.first
host = connection.host[:host] if connection
port = connection.host[:port] if connection

span.span_type = Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_TYPE_QUERY

span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_QUERY)
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)

span.set_tag(Contrib::Ext::DB::TAG_SYSTEM, Ext::TAG_SYSTEM)

# 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)

# Tag as an external peer service
if Contrib::SpanAttributeSchema.default_span_attribute_schema?
span.set_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE, span.service)
end

span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, host) if host

# Set analytics sample rate
if Contrib::Analytics.enabled?(datadog_configuration[:analytics_enabled])
Contrib::Analytics.set_sample_rate(span, datadog_configuration[:analytics_sample_rate])
end

# `Client#transport` is most convenient object both this integration and the library
# user have shared access to across all `elasticsearch` versions.
#
# `Client#self` in this context is an internal object that the library user
# does not have access to since `elasticsearch` v8.0.0.
service ||= Datadog.configuration_for(transport, :service_name) || datadog_configuration[:service_name]

method = args[0]
path = args[1]
params = args[2]
body = args[3]
full_url = URI.parse(path)

url = full_url.path
response = nil

Tracing.trace(Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_QUERY, service: service) do |span|
begin
connection = transport.connections.first
host = connection.host[:host] if connection
port = connection.host[:port] if connection

span.span_type = Datadog::Tracing::Contrib::Elasticsearch::Ext::SPAN_TYPE_QUERY

span.set_tag(Tracing::Metadata::Ext::TAG_COMPONENT, Ext::TAG_COMPONENT)
span.set_tag(Tracing::Metadata::Ext::TAG_OPERATION, Ext::TAG_OPERATION_QUERY)
span.set_tag(Tracing::Metadata::Ext::TAG_KIND, Tracing::Metadata::Ext::SpanKind::TAG_CLIENT)

span.set_tag(Contrib::Ext::DB::TAG_SYSTEM, Ext::TAG_SYSTEM)

# 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)

# Tag as an external peer service
if Contrib::SpanAttributeSchema.default_span_attribute_schema?
span.set_tag(Tracing::Metadata::Ext::TAG_PEER_SERVICE, span.service)
end

span.set_tag(Tracing::Metadata::Ext::TAG_PEER_HOSTNAME, host) if host

# Set analytics sample rate
if Contrib::Analytics.enabled?(datadog_configuration[:analytics_enabled])
Contrib::Analytics.set_sample_rate(span, datadog_configuration[:analytics_sample_rate])
end

span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_METHOD, method)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_URL, url)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_PARAMS, params) if params
if body
quantize_options = datadog_configuration[:quantize]
quantized_body = Datadog::Tracing::Contrib::Elasticsearch::Quantize.format_body(
body,
quantize_options
)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_BODY, quantized_body)
end
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, host) if host
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, port) if port

quantized_url = Datadog::Tracing::Contrib::Elasticsearch::Quantize.format_url(url)
span.resource = "#{method} #{quantized_url}"
rescue StandardError => e
Datadog.logger.error(e.message)
ensure
# the call is still executed
response = perform_request_without_datadog(*args)
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.status)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_METHOD, method)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_URL, url)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_PARAMS, params) if params
if body
quantize_options = datadog_configuration[:quantize]
quantized_body = Datadog::Tracing::Contrib::Elasticsearch::Quantize.format_body(
body,
quantize_options
)
span.set_tag(Datadog::Tracing::Contrib::Elasticsearch::Ext::TAG_BODY, quantized_body)
end
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_HOST, host) if host
span.set_tag(Tracing::Metadata::Ext::NET::TAG_TARGET_PORT, port) if port

quantized_url = Datadog::Tracing::Contrib::Elasticsearch::Quantize.format_url(url)
span.resource = "#{method} #{quantized_url}"
rescue StandardError => e
Datadog.logger.error(e.message)
ensure
# the call is still executed
response = perform_request_without_datadog(*args)
span.set_tag(Tracing::Metadata::Ext::HTTP::TAG_STATUS_CODE, response.status)
end
response
end
response
end

def datadog_configuration
Datadog.configuration.tracing[:elasticsearch]
end
def datadog_configuration
Datadog.configuration.tracing[:elasticsearch]
end
# rubocop:enable Metrics/BlockLength
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity


# `Elasticsearch` namespace renamed to `Elastic` in version 8.0.0 of the transport gem:
# @see https://github.com/elastic/elastic-transport-ruby/commit/ef804cbbd284f2a82d825221f87124f8b5ff823c
def transport_module
Expand Down

0 comments on commit 6066c4c

Please sign in to comment.