stackify-ruby-apm 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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