stackify-ruby-apm 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37b3e9d03e3a48f658ac93e0c7fb2bde7ff1bbe4b477d8db6307288182da1218
4
- data.tar.gz: d85d9a3ebefa5f9fa86b232887087634c7fa3a464b8a430da6f43ec1e2a76973
3
+ metadata.gz: 5644c5079318a7c3529770465f45372106c02a8334b4648880cee789495c9a17
4
+ data.tar.gz: 6309a247094d7795b7abf970bf7ca46c3ea6a499de6aa03cb8b92c22080ee191
5
5
  SHA512:
6
- metadata.gz: 6d7ad0838dc3db4eedb0f1dd9dfdc7ad7987952fcbdb8a5b1e852ecd2451b4193cf6f7e3df70046db7b9766834a23313e059bb5ea9752b965bba79c5332330d0
7
- data.tar.gz: e5bddb17c802ee238fb73ad50b4208ff91b5072b6057726977478d61189cab9812eaef7df8153688722118fb7fbd5e69869c963d35c17a4084a33e1f16e7420b
6
+ metadata.gz: b3ebbe0dc60d749aa5cffde012ac3f5fa815fd3b1a52c110fc9ff213ab7252a69a1d43dc951f3578c725cfdc32e29b3b1a1f59666293357c3f86deabefd6b5f5
7
+ data.tar.gz: 97a7f413c89124d246d4c499c8fada9e6c2373a21adc3e096fcce9c8dadd1cb0e32e55b300cbe1c4c3a633711444ef3822796596047cf2b25629f7fc00d1b0fa
data/README.md CHANGED
@@ -25,6 +25,14 @@
25
25
  ```
26
26
  5. Build/Deploy your application
27
27
 
28
+ ### Custom Instrumentation in Rails
29
+
30
+ In the config/initializer folder of your Rails app create a file `config/initializer/stackify.rb` and then add this configuration
31
+
32
+ Rails.configuration.to_prepare do
33
+ StackifyRubyAPM.run_custom_instrument
34
+ end
35
+
28
36
  ### Non-Rails Guide
29
37
 
30
38
  1. Install **Stackify Linux Agent**.
@@ -47,9 +55,21 @@
47
55
 
48
56
  5. In the `config.ru` add the following lines:
49
57
 
50
- ``` use StackifyRubyAPM::Middleware
58
+ ```
59
+ use StackifyRubyAPM::Middleware
51
60
  StackifyRubyAPM.start
52
61
  at_exit { StackifyRubyAPM.stop }
53
62
  ```
54
63
 
55
64
  6. Build/Deploy your application
65
+
66
+ ### Custom Instrumentation in Non-Rails
67
+
68
+ In `config.ru` file add this line: StackifyRubyAPM.run_custom_instrument
69
+
70
+ Example:
71
+
72
+ use StackifyRubyAPM::Middleware
73
+ StackifyRubyAPM.start
74
+ StackifyRubyAPM.run_custom_instrument
75
+ at_exit { StackifyRubyAPM.stop }
@@ -175,6 +175,7 @@ module StackifyRubyAPM
175
175
  curb
176
176
  curb/easy
177
177
  curb/multi
178
+ httparty
178
179
  stackify_logger
179
180
  ]
180
181
  end
@@ -312,21 +313,21 @@ module StackifyRubyAPM
312
313
  @device_id = nil
313
314
  @client_run_domain = nil
314
315
  begin
315
- info 'Reading the Stackify props in Environment variables'
316
+ info '[Config] Reading the Stackify props in Environment variables'
316
317
  @client_run_domain = ENV['STACKIFY_RUM_DOMAIN'] || nil
317
318
  if ENV['STACKIFY_ENV']
318
319
  props = ENV['STACKIFY_ENV'].split('|')
319
320
  @client_id = props[0].to_s if props[0]
320
321
  @device_id = props[1].to_s if props[1]
321
- info "stackify.properties: clientId=#{@client_id}, deviceId=#{@device_id}, client_rum_domain=#{@client_run_domain}"
322
+ info "[Config] stackify.properties: clientId=#{@client_id}, deviceId=#{@device_id}, client_rum_domain=#{@client_run_domain}"
322
323
  end
323
324
  rescue StandardError => e
324
- info 'Error occured while reading the Stackify props in Environment variables.'
325
+ info '[Config] Error occured while reading the Stackify props in Environment variables.'
325
326
  info e.inspect
326
327
  end
327
- info 'No clientId found in environment variables.' if @client_id.nil?
328
- info 'No deviceId found in environment variables.' if @device_id.nil?
329
- info 'No client RUM domain found in environment variables.' if @client_run_domain.nil?
328
+ info '[Config] No clientId found in environment variables.' if @client_id.nil?
329
+ info '[Config] No deviceId found in environment variables.' if @device_id.nil?
330
+ info '[Config] No client RUM domain found in environment variables.' if @client_run_domain.nil?
330
331
  end
331
332
  # rubocop:enable Metrics/CyclomaticComplexity
332
333
  # rubocop:enable Metrics/PerceivedComplexity
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This class will custom instrument a class and method
4
+
5
+ module StackifyRubyAPM
6
+ # @api private
7
+ class InstrumenterHelper
8
+ # rubocop:disable Metrics/CyclomaticComplexity
9
+ # rubocop:disable Metrics/PerceivedComplexity
10
+ # rubocop:disable Lint/UselessAssignment
11
+ # rubocop:disable Security/Eval
12
+ attr_accessor :custom_instrumented, :custom_class_info
13
+ @custom_instrumented = {}
14
+ @custom_class_info = {}
15
+
16
+ def self.custom_instrumented_reset
17
+ @custom_instrumented.each do |custom_instrument, values|
18
+ current_class = custom_instrument
19
+ module_consget = Module.const_get(current_class)
20
+ values.each_key do |current_method|
21
+ is_method_exists = StackifyRubyAPM::Spies.ismethod_exists(current_class, current_method)
22
+ if is_method_exists
23
+ @custom_instrumented[current_class.to_s][current_method.to_s] = false
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.m_class(tracked_func, current_class, class_path, current_method, tracked_function_name)
30
+ module_consget = Module.const_get(current_class)
31
+ classspyitem = "#{current_class}Spy"
32
+ module_consget_spy = Module.const_get(current_class)
33
+ current_method_without = "_without_apm_#{current_method}"
34
+
35
+ unless @custom_instrumented[current_class.to_s]
36
+ @custom_instrumented[current_class.to_s] = {}
37
+ end
38
+
39
+ unless @custom_instrumented[current_class.to_s][current_method.to_s]
40
+ @custom_instrumented[current_class.to_s][current_method.to_s] = false
41
+ end
42
+
43
+ unless @custom_class_info[current_class.to_s]
44
+ @custom_class_info[current_class.to_s] = {}
45
+ end
46
+
47
+ unless @custom_class_info[current_class.to_s]['controller']
48
+ @custom_class_info[current_class.to_s]['controller'] = false
49
+ end
50
+
51
+ unless @custom_class_info[current_class.to_s]['model']
52
+ @custom_class_info[current_class.to_s]['model'] = false
53
+ end
54
+
55
+ return unless @custom_instrumented[current_class.to_s][current_method.to_s] == false
56
+
57
+ eval <<-RUBY
58
+ class #{classspyitem}
59
+ def install
60
+ #{current_class}.class_eval do
61
+ alias_method "#{current_method_without}", "#{current_method}"
62
+
63
+ def #{current_method}(*args, &block)
64
+ return #{current_method_without}(*args, &block) unless StackifyRubyAPM.current_transaction
65
+
66
+ name = "Custom Instrument"
67
+ type = "#{current_class}##{current_method}"
68
+ ctx = if "#{tracked_func}" == 'true'
69
+ Span::Context.new(
70
+ CATEGORY: 'Ruby',
71
+ TRACKED_FUNC: "#{tracked_function_name}"
72
+ )
73
+ else
74
+ Span::Context.new(
75
+ CATEGORY: 'Ruby'
76
+ )
77
+ end
78
+
79
+ req = #{current_method_without}(*args, &block)
80
+ StackifyRubyAPM.span name, type, context: ctx do
81
+ req
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ StackifyRubyAPM::Spies.register current_class.to_s, class_path.to_s, #{classspyitem}.new, true, "#{current_method}", "#{tracked_func}", "#{tracked_function_name}"
88
+ RUBY
89
+
90
+ @custom_instrumented[current_class.to_s][current_method.to_s] = true
91
+ @custom_class_info[current_class.to_s]['controller'] = true if class_path && class_path.include?('controllers')
92
+ @custom_class_info[current_class.to_s]['model'] = true if class_path && class_path.include?('models')
93
+ end
94
+
95
+ def self.m_singleton(tracked_func, current_class, class_path, current_method, tracked_function_name)
96
+ module_consget = Module.const_get(current_class)
97
+ classspyitem = "#{current_class}Spy"
98
+
99
+ unless @custom_instrumented[current_class.to_s]
100
+ @custom_instrumented[current_class.to_s] = {}
101
+ end
102
+
103
+ unless @custom_instrumented[current_class.to_s][current_method.to_s]
104
+ @custom_instrumented[current_class.to_s][current_method.to_s] = false
105
+ end
106
+
107
+ unless @custom_class_info[current_class.to_s]
108
+ @custom_class_info[current_class.to_s] = {}
109
+ end
110
+
111
+ unless @custom_class_info[current_class.to_s]['controller']
112
+ @custom_class_info[current_class.to_s]['controller'] = false
113
+ end
114
+
115
+ unless @custom_class_info[current_class.to_s]['model']
116
+ @custom_class_info[current_class.to_s]['model'] = false
117
+ end
118
+
119
+ return unless @custom_instrumented[current_class.to_s][current_method.to_s] == false
120
+
121
+ eval <<-RUBY
122
+ class #{classspyitem}
123
+ def install
124
+ #{current_class}.class_eval do
125
+ singleton_class.send(:alias_method, :"_self_without_apm_#{current_method}", :"#{current_method}")
126
+
127
+ def self.#{current_method}(*args, &block)
128
+ return _self_without_apm_#{current_method}(*args, &block) unless StackifyRubyAPM.current_transaction
129
+
130
+ name = "Custom Instrument"
131
+ type = "#{current_class}##{current_method}"
132
+ ctx = if "#{tracked_func}" == 'true'
133
+ Span::Context.new(
134
+ CATEGORY: 'Ruby',
135
+ TRACKED_FUNC: "#{tracked_function_name}"
136
+ )
137
+ else
138
+ Span::Context.new(
139
+ CATEGORY: 'Ruby'
140
+ )
141
+ end
142
+ req = _self_without_apm_#{current_method}(*args, &block)
143
+ StackifyRubyAPM.span name, type, context: ctx do
144
+ req
145
+ end
146
+ end
147
+
148
+ def self.get_class_name
149
+ return self.class.name
150
+ end
151
+ end
152
+ end
153
+ end
154
+ StackifyRubyAPM::Spies.register current_class.to_s, class_path.to_s, #{classspyitem}.new, true, "#{current_method}", "#{tracked_func}", "#{tracked_function_name}"
155
+ RUBY
156
+ @custom_instrumented[current_class.to_s][current_method.to_s] = true
157
+ @custom_class_info[current_class.to_s]['controller'] = true if class_path && class_path.include?('controllers')
158
+ @custom_class_info[current_class.to_s]['model'] = true if class_path && class_path.include?('models')
159
+ end
160
+ # rubocop:enable Metrics/CyclomaticComplexity
161
+ # rubocop:enable Metrics/PerceivedComplexity
162
+ # rubocop:enable Lint/UselessAssignment
163
+ # rubocop:enable Security/Eval
164
+ end
165
+ end
@@ -5,6 +5,7 @@
5
5
  #
6
6
  # @param file
7
7
  # @removed the header of the generated log
8
+ require 'logger'
8
9
  module StackifyRubyAPM
9
10
  # @api private
10
11
  class StackifyLogger < Logger
@@ -5,6 +5,7 @@
5
5
  #
6
6
  # @param file
7
7
  # @removed the header of the generated log
8
+ require 'logger'
8
9
  module StackifyRubyAPM
9
10
  # @api private
10
11
  class StackifyLogger < Logger
@@ -47,7 +47,12 @@ module StackifyRubyAPM
47
47
  end
48
48
 
49
49
  def build_span(span)
50
- span_type = span.type
50
+ span_type = if span.name == 'Custom Instrument'
51
+ "custom.#{span.type}"
52
+ else
53
+ span.type
54
+ end
55
+
51
56
  span_context = span.context && span.context.to_h
52
57
 
53
58
  {
@@ -28,6 +28,11 @@ module StackifyRubyAPM
28
28
  :THREAD_ID,
29
29
  :ID,
30
30
  :TRACKED_FUNC
31
+ # rubocop:disable Style/VariableName
32
+ def update_status(status)
33
+ @STATUS = status
34
+ end
35
+ # rubocop:enable Style/VariableName
31
36
  end
32
37
  end
33
38
  end
@@ -13,14 +13,19 @@ module StackifyRubyAPM
13
13
  # @api private
14
14
  class Registration
15
15
  extend Forwardable
16
-
17
- def initialize(const_name, require_paths, spy)
16
+ # rubocop:disable Metrics/ParameterLists
17
+ def initialize(const_name, require_paths, spy, custom_instrumented = false, custom_method = '', tracked_func = false, tracked_function_name = '')
18
18
  @const_name = const_name
19
19
  @require_paths = Array(require_paths)
20
20
  @spy = spy
21
+ @custom_instrumented = custom_instrumented
22
+ @custom_method = custom_method
23
+ @tracked_func = tracked_func
24
+ @tracked_function_name = tracked_function_name
21
25
  end
26
+ # rubocop:enable Metrics/ParameterLists
22
27
 
23
- attr_reader :const_name, :require_paths
28
+ attr_reader :const_name, :require_paths, :custom_instrumented, :custom_method, :tracked_func, :tracked_function_name
24
29
 
25
30
  def_delegator :@spy, :install
26
31
  end
@@ -71,7 +76,6 @@ module StackifyRubyAPM
71
76
  if ENV['STACKIFY_RUBY_ENV'] == 'rspec'
72
77
  file = 'spec/integration/stackify_spec.json'
73
78
  end
74
-
75
79
  return unless File.exist?(file)
76
80
 
77
81
  File.open(file) do |f|
@@ -86,6 +90,35 @@ module StackifyRubyAPM
86
90
  rescue NameError
87
91
  return false
88
92
  end
93
+
94
+ # rubocop:disable Metrics/CyclomaticComplexity
95
+ # rubocop:disable Metrics/PerceivedComplexity
96
+ def self.ismethod_exists(class_name, current_method)
97
+ module_consget = Module.const_get(class_name)
98
+ current_method_without_apm = "_without_apm_#{current_method}"
99
+ self_current_method_without_apm = "_self_without_apm_#{current_method}"
100
+
101
+ with_flag = module_consget.instance_methods(false).include?(:"#{current_method_without_apm}")
102
+ self_with_flag = module_consget.instance_methods(false).include?(:"#{self_current_method_without_apm}")
103
+
104
+ current_method_exists = module_consget.instance_methods(false).include?(:"#{current_method}")
105
+ self_current_method_exists = module_consget.instance_methods(false).include?(:"self.#{current_method}")
106
+
107
+ exists = false
108
+ if (self_with_flag == false && with_flag == false) &&
109
+ (current_method_exists == true || self_current_method_exists == true)
110
+ exists = true
111
+ end
112
+
113
+ if (module_consget.methods.include?(:"#{current_method_without_apm}") == false &&
114
+ module_consget.methods.include?(:"#{self_current_method_without_apm}") == false) &&
115
+ (module_consget.methods.include?(:"#{current_method}") || module_consget.methods.include?(:"self.#{current_method}"))
116
+ exists = true
117
+ end
118
+ exists
119
+ end
120
+ # rubocop:enable Metrics/CyclomaticComplexity
121
+ # rubocop:enable Metrics/PerceivedComplexity
89
122
  end
90
123
  end
91
124
 
@@ -3,89 +3,31 @@
3
3
  # Monkey patch for the custom instrumentation any values from config/stackify.json will be loop and will
4
4
  # register as a spy.
5
5
  #
6
+ require 'stackify_apm/instrumenter_helper.rb'
6
7
  require 'stackify_apm/config'
7
8
  require 'json'
8
-
9
+ # rubocop:disable Metrics/CyclomaticComplexity
10
+ # rubocop:disable Metrics/PerceivedComplexity
9
11
  module StackifyRubyAPM
10
12
  # @api private
11
13
  module Spies
12
- def self.m_class(tracked_func, current_class, current_method, tracked_function_name)
13
- Module.const_get(current_class.to_s).class_eval <<-RUBY
14
- alias :"__without_apm_#{current_method}" :"#{current_method}"
15
-
16
- def #{current_method}(*args, &block)
17
- return __without_apm_#{current_method}(*args, &block) unless StackifyRubyAPM.current_transaction
18
- name = "Custom Instrument"
19
- type = "#{current_class}##{current_method}"
20
- ctx = if "#{tracked_func}" == 'true'
21
- Span::Context.new(
22
- CATEGORY: 'Ruby',
23
- TRACKED_FUNC: "#{tracked_function_name}"
24
- )
25
- else
26
- Span::Context.new(
27
- CATEGORY: 'Ruby'
28
- )
29
- end
30
- req = __without_apm_#{current_method}(*args, &block)
31
- StackifyRubyAPM.span name, type, context: ctx do
32
- req
33
- end
34
- end
35
-
36
- def get_class_name
37
- return self.class.name
38
- end
39
- RUBY
40
- end
41
-
42
- def self.m_singleton(tracked_func, current_class, current_method, tracked_function_name)
43
- Module.const_get(current_class.to_s).class_eval <<-RUBY
44
- singleton_class.send(:alias_method, :"__self_without_apm_#{current_method}", :"#{current_method}")
45
-
46
- def self.#{current_method}(*args, &block)
47
- return __self_without_apm_#{current_method}(*args, &block) unless StackifyRubyAPM.current_transaction
14
+ def self.run_custom_instrumentation
15
+ config = Config.new
16
+ to_instrument = parse_json_config(config.json_config_file)
17
+ if config.logger.nil?
18
+ config.debug_logger
19
+ config.logger.send(:info, '[StackifyRubyAPM] Error: config/stackify.json does not exist which is required for custom instrumentation!') if to_instrument.nil?
20
+ end
48
21
 
49
- name = "Custom Instrument"
50
- type = "#{current_class}##{current_method}"
51
- ctx = if "#{tracked_func}" == 'true'
52
- Span::Context.new(
53
- CATEGORY: 'Ruby',
54
- TRACKED_FUNC: "#{tracked_function_name}"
55
- )
56
- else
57
- Span::Context.new(
58
- CATEGORY: 'Ruby'
59
- )
60
- end
61
- req = __self_without_apm_#{current_method}(*args, &block)
62
- StackifyRubyAPM.span name, type, context: ctx do
63
- req
64
- end
65
- end
22
+ return unless !to_instrument.nil? && !to_instrument.empty? && defined?(to_instrument['instrumentation']) && (to_instrument['instrumentation'].count > 0)
66
23
 
67
- def self.get_class_name
68
- return self.class.name
69
- end
70
- RUBY
71
- end
72
-
73
- config = Config.new
74
- to_instrument = parse_json_config(config.json_config_file)
75
- if defined?(to_instrument['instrumentation']) && (to_instrument['instrumentation'].count > 0)
76
24
  to_instrument['instrumentation'].each do |custom_spy|
77
25
  current_class = custom_spy['class']
78
26
  current_method = custom_spy['method']
79
27
  tracked_func = custom_spy['trackedFunction']
80
- tracked_func_name = if defined?(custom_spy['trackedFunctionName'])
81
- custom_spy['trackedFunctionName']
82
- end
28
+ tracked_func_name = defined?(custom_spy['trackedFunctionName']) ? custom_spy['trackedFunctionName'] : ''
83
29
 
84
- tracked_function_tpl = if tracked_func_name.nil?
85
- '{{ClassName}}.{{MethodName}}'
86
- else
87
- tracked_func_name
88
- end
30
+ tracked_function_tpl = tracked_func_name.nil? ? '{{ClassName}}.{{MethodName}}' : tracked_func_name
89
31
 
90
32
  tracked_function_name = tracked_function_tpl.sub '{{ClassName}}', current_class
91
33
  tracked_function_name = tracked_function_name.sub '{{MethodName}}', current_method
@@ -95,10 +37,17 @@ module StackifyRubyAPM
95
37
  mod_constant = Module.const_get(current_class.to_s)
96
38
  klass_method_flag = mod_constant.method_defined?(current_method.to_s)
97
39
  singleton_method_flag = mod_constant.respond_to?(current_method.to_s)
40
+
41
+ class_location = mod_constant.instance_methods(false).map do |m|
42
+ mod_constant.instance_method(m).source_location.first
43
+ end.uniq
44
+
45
+ class_path = class_location.last
46
+
98
47
  if klass_method_flag
99
- StackifyRubyAPM::Spies.m_class(tracked_func, current_class, current_method, tracked_function_name)
48
+ StackifyRubyAPM::InstrumenterHelper.m_class(tracked_func, current_class, class_path, current_method, tracked_function_name)
100
49
  elsif singleton_method_flag
101
- StackifyRubyAPM::Spies.m_singleton(tracked_func, current_class, current_method, tracked_function_name)
50
+ StackifyRubyAPM::InstrumenterHelper.m_singleton(tracked_func, current_class, class_path, current_method, tracked_function_name)
102
51
  end
103
52
  end
104
53
  # rubocop:enable Style/Next
@@ -106,3 +55,5 @@ module StackifyRubyAPM
106
55
  end
107
56
  end
108
57
  end
58
+ # rubocop:enable Metrics/CyclomaticComplexity
59
+ # rubocop:enable Metrics/PerceivedComplexity
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Monkey patch for the CurbSpy class for sending & receiving Curb responses.
4
+ #
5
+ require 'stackify_apm/config'
6
+
7
+ module StackifyRubyAPM
8
+ # @api private
9
+ module Spies
10
+ # @api private
11
+ class HTTPartySpy
12
+ def install
13
+ # puts HTTParty::ClassMethods.instance_methods(false).inspect
14
+ HTTParty::ClassMethods.module_eval do
15
+ alias_method 'perform_request_without_apm', 'perform_request'
16
+
17
+ # singleton_class.send(:alias_method, :perform_request_without_apm, :perform_request)
18
+
19
+ private :perform_request
20
+
21
+ def perform_request(http_method, path, options, &block)
22
+ req = nil
23
+ return perform_request_without_apm(http_method, path, options, &block) unless StackifyRubyAPM.current_transaction
24
+ # Data configuration
25
+ #
26
+ method = http_method.to_s.gsub('Net::HTTP::', '').upcase
27
+ uri = path.strip
28
+ name = "#{method} #{uri}"
29
+ type = "ext.HTTParty.#{method}"
30
+ # Submits HTTP request
31
+ #
32
+ # req = perform_request_without_apm(http_method, path, options, &block)
33
+ # Builds span context
34
+ #
35
+ # status_code = req.code
36
+
37
+ ctx = Span::Context.new(
38
+ CATEGORY: 'Web External',
39
+ SUBCATEGORY: 'Execute',
40
+ URL: uri,
41
+ STATUS: '',
42
+ METHOD: method
43
+ )
44
+ # Creates new span from HTTP result
45
+ #
46
+ # class_info = { 'classname' => 'httparty', 'hostname' => URI.parse(uri).host }
47
+ StackifyRubyAPM.span name, type, context: ctx do
48
+ req = perform_request_without_apm(http_method, path, options, &block)
49
+ status_code = req.code
50
+ ctx.update_status(status_code)
51
+ req
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ # Registers CurbSpy spy, go to: /stackify/spies.rb
58
+ #
59
+ register 'HTTParty::ClassMethods', 'httparty', HTTPartySpy.new
60
+ end
61
+ end
@@ -11,9 +11,8 @@ module StackifyRubyAPM
11
11
 
12
12
  def request(req, body = nil, &block)
13
13
  result = nil
14
- unless StackifyRubyAPM.current_transaction
15
- request_without_apm(req, body, &block)
16
- end
14
+ return request_without_apm(req, body, &block) unless StackifyRubyAPM.current_transaction
15
+ return request_without_apm(req, body, &block) if started? && req['span']
17
16
 
18
17
  # Data configuration
19
18
  #
@@ -25,23 +24,25 @@ module StackifyRubyAPM
25
24
  name = "#{method} #{host}"
26
25
  type = "ext.net_http.#{method}"
27
26
 
28
- # Submits HTTP request
29
- #
30
- result = request_without_apm(req, body, &block)
31
-
32
27
  # Builds span context
33
28
  #
34
29
  ctx = Span::Context.new(
35
30
  CATEGORY: 'Web External',
36
31
  SUBCATEGORY: 'Execute',
37
32
  URL: req.uri.nil? ? host : req.uri,
38
- STATUS: result.code.to_i,
33
+ STATUS: '',
39
34
  METHOD: method
40
35
  )
41
36
 
42
37
  # Creates new span from HTTP result
43
38
  #
44
39
  StackifyRubyAPM.span name, type, context: ctx do
40
+ # Submits HTTP request
41
+ #
42
+ req['span'] = true
43
+ result = request_without_apm(req, body, &block)
44
+ status_code = result.code.to_i
45
+ ctx.update_status(status_code)
45
46
  return result
46
47
  end
47
48
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Sets the version of the APM
4
4
  module StackifyRubyAPM
5
- VERSION = '1.4.0'.freeze
5
+ VERSION = '1.5.0'.freeze
6
6
  end
@@ -16,9 +16,9 @@
16
16
  require 'stackify_apm/log'
17
17
  require 'stackify_apm/version'
18
18
  require 'stackify_apm/util/dig'
19
- require 'stackify_apm/agent'
20
19
  # Checks ruby version
21
20
  require RUBY_VERSION.to_f >= 2.4 ? 'stackify_apm/logger/logger_high_version' : 'stackify_apm/logger/logger_lower_version'
21
+ require 'stackify_apm/agent'
22
22
  require 'stackify_apm/helper/database_helper'
23
23
  require 'stackify_apm/util'
24
24
  require 'stackify_apm/config'
@@ -27,6 +27,7 @@ require 'stackify_apm/instrumenter'
27
27
  require 'stackify_apm/internal_error'
28
28
  # require 'stackify_apm/util'
29
29
  require 'stackify_apm/middleware'
30
+ require 'stackify_apm/instrumenter_helper'
30
31
 
31
32
  # Checks if the framework using is Rails
32
33
  require 'stackify_apm/railtie' if defined?(::Rails::Railtie)
@@ -65,6 +66,13 @@ module StackifyRubyAPM
65
66
  data-a=\"#{config.application_name}\" data-e=\"#{config.environment_name}\" data-enableInternalLogging=\"#{config.debug_logging}\" type=\"text/javascript\" async></script>"
66
67
  end
67
68
 
69
+ # Run the custom instrument
70
+ def self.run_custom_instrument
71
+ return unless running?
72
+ StackifyRubyAPM::InstrumenterHelper.custom_instrumented_reset
73
+ StackifyRubyAPM::Spies.run_custom_instrumentation
74
+ end
75
+
68
76
  # Stops the StackifyRubyAPM Agent
69
77
  def self.stop
70
78
  Agent.stop
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stackify-ruby-apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stackify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-18 00:00:00.000000000 Z
11
+ date: 2019-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,6 +127,7 @@ files:
127
127
  - lib/stackify_apm/error_builder.rb
128
128
  - lib/stackify_apm/helper/database_helper.rb
129
129
  - lib/stackify_apm/instrumenter.rb
130
+ - lib/stackify_apm/instrumenter_helper.rb
130
131
  - lib/stackify_apm/internal_error.rb
131
132
  - lib/stackify_apm/log.rb
132
133
  - lib/stackify_apm/logger/log_device.rb
@@ -153,6 +154,7 @@ files:
153
154
  - lib/stackify_apm/spies/curb/easy.rb
154
155
  - lib/stackify_apm/spies/curb/multi.rb
155
156
  - lib/stackify_apm/spies/custom_instrumenter.rb
157
+ - lib/stackify_apm/spies/httparty.rb
156
158
  - lib/stackify_apm/spies/httpclient.rb
157
159
  - lib/stackify_apm/spies/httprb.rb
158
160
  - lib/stackify_apm/spies/mongo.rb