Class: Hypertrace::Instrumentation::RackCompatible

Inherits:
Object
  • Object
show all
Defined in:
lib/hypertrace/instrumentation/rack_compatible.rb

Constant Summary collapse

CONTENT_TYPE_SUBSTRINGS =
%w[json x-www-form-urlencoded]

Class Method Summary collapse

Class Method Details

.action_dispatch_defined?Boolean

memoize so we don’t check action dispatch

Returns:

  • (Boolean)


75
76
77
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 75

def self.action_dispatch_defined?
  @_action_dispatch_defined ||= defined?(ActionDispatch) && defined?(ActionDispatch::Response) && defined?(ActionDispatch::Response::RackBody)
end

.extract_headers_from_env(env) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 79

def self.extract_headers_from_env env
  result = env.select{|x|x.start_with?("HTTP_")}
  result.transform_keys!{|k|k[5..-1]}
  if env.has_key?("CONTENT_TYPE")
    result['content-type'] = env['CONTENT_TYPE']
  end
  if env.has_key?("CONTENT_LENGTH")
    result['content-length'] = env["CONTENT_LENGTH"]
  end
  result
end

.extract_req_headers_as_attributes(env, attr_prefix) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 9

def self.extract_req_headers_as_attributes env, attr_prefix
  return unless Hypertrace::RubyAgent.instance.config.data_capture.http_headers.request

  headers = extract_headers_from_env(env)
  attr_hash = headers.map do |key, value|
    # https://github.com/rails/rails/blob/a6bf6d55804850b390d840b87a679b784c0a3db4/actionpack/lib/action_dispatch/http/headers.rb#L5-L23
    # in rack underscore and dashes resolve to the same header(using - instead of _)
    key = key.gsub('_', '-')
    ["#{attr_prefix}.#{key}".downcase, value]
  end.to_h

  attr_hash
end

.extract_response_body(rack_response) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 35

def self.extract_response_body rack_response
  if rack_response.is_a?(Rack::Response)
    body = rack_response.respond_to?(:body) ? rack_response.body : nil
    return Hypertrace::Instrumentation::DataCapture.capturable_body(body)
  end

  if rack_response.is_a?(Rack::BodyProxy)
    count = 0
    while count < 15
      rack_response = rack_response.instance_variable_get(:'@body')
      if rack_response.is_a?(Array)
        body = rack_response.respond_to?(:join) ? rack_response.join('') : nil
        return Hypertrace::Instrumentation::DataCapture.capturable_body(body)
      end
      if action_dispatch_defined? && rack_response.is_a?(ActionDispatch::Response::RackBody)
        return Hypertrace::Instrumentation::DataCapture.capturable_body(rack_response.body) if rack_response.respond_to?(:body)
      end
      unless rack_response.is_a?(Rack::BodyProxy)
        return
      end
      count += 1
    end
  elsif rack_response.is_a?(Array) && rack_response.length == 3
    body = rack_response[2]
    if body.is_a?(Array)
      return Hypertrace::Instrumentation::DataCapture.capturable_body(body.join(''))
    end
  end
end

.extract_response_headers_as_attributes(rack_response, attr_prefix) ⇒ Object



65
66
67
68
69
70
71
72
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 65

def self.extract_response_headers_as_attributes rack_response, attr_prefix
  return unless Hypertrace::RubyAgent.instance.config.data_capture.http_headers.response
  return if rack_response.is_a?(Rack::BodyProxy)

  rack_response[1].map do |header, value|
    ["#{attr_prefix}.#{header}".downcase, value]
  end.to_h
end

.should_record_env?(env) ⇒ Boolean

Returns:

  • (Boolean)


23
24
25
26
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 23

def self.should_record_env?(env)
  return false unless env.has_key?("CONTENT_TYPE")
  Hypertrace::Instrumentation::DataCapture.can_capture?(env['CONTENT_TYPE'], Hypertrace::Instrumentation::DataCapture::TYPE_REQUEST)
end

.should_record_rack_array?(response) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
# File 'lib/hypertrace/instrumentation/rack_compatible.rb', line 28

def self.should_record_rack_array?(response)
  content_type_arr = response[1].find{|x|x && x[0].downcase == "content-type"}
  return false unless content_type_arr
  content_type = content_type_arr[1]
  Hypertrace::Instrumentation::DataCapture.can_capture?(content_type, Hypertrace::Instrumentation::DataCapture::TYPE_RESPONSE)
end