oneapm_rpm 1.1.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.
Files changed (234) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +30 -0
  3. data/.rubocop.yml +725 -0
  4. data/Gemfile +3 -0
  5. data/Guardfile +7 -0
  6. data/LICENSE +1 -0
  7. data/README.md +3 -0
  8. data/config/cert/cacert.pem +1177 -0
  9. data/config/database.yml +5 -0
  10. data/lib/initializers/goliath.rb +11 -0
  11. data/lib/initializers/other.rb +1 -0
  12. data/lib/initializers/rails.rb +15 -0
  13. data/lib/one_apm/agent.rb +253 -0
  14. data/lib/one_apm/agent/agent.rb +283 -0
  15. data/lib/one_apm/agent/agent/connect.rb +175 -0
  16. data/lib/one_apm/agent/agent/container_data_manager.rb +218 -0
  17. data/lib/one_apm/agent/agent/forkable_dispatcher_functions.rb +96 -0
  18. data/lib/one_apm/agent/agent/helpers.rb +45 -0
  19. data/lib/one_apm/agent/agent/start.rb +226 -0
  20. data/lib/one_apm/agent/agent/start_worker_thread.rb +148 -0
  21. data/lib/one_apm/agent/busy_calculator.rb +115 -0
  22. data/lib/one_apm/agent/cross_app/cross_app_monitor.rb +181 -0
  23. data/lib/one_apm/agent/cross_app/cross_app_tracing.rb +336 -0
  24. data/lib/one_apm/agent/database.rb +308 -0
  25. data/lib/one_apm/agent/database/active_record_helper.rb +80 -0
  26. data/lib/one_apm/agent/database/obfuscation_helpers.rb +76 -0
  27. data/lib/one_apm/agent/database/obfuscator.rb +78 -0
  28. data/lib/one_apm/agent/database/postgres_explain_obfuscator.rb +45 -0
  29. data/lib/one_apm/agent/datastores.rb +175 -0
  30. data/lib/one_apm/agent/datastores/metric_helper.rb +83 -0
  31. data/lib/one_apm/agent/datastores/mongo.rb +27 -0
  32. data/lib/one_apm/agent/datastores/mongo/metric_translator.rb +189 -0
  33. data/lib/one_apm/agent/datastores/mongo/obfuscator.rb +37 -0
  34. data/lib/one_apm/agent/datastores/mongo/statement_formatter.rb +51 -0
  35. data/lib/one_apm/agent/event/event_listener.rb +40 -0
  36. data/lib/one_apm/agent/event/event_loop.rb +191 -0
  37. data/lib/one_apm/agent/event/worker_loop.rb +97 -0
  38. data/lib/one_apm/agent/harvester.rb +48 -0
  39. data/lib/one_apm/agent/inbound_request_monitor.rb +30 -0
  40. data/lib/one_apm/agent/javascript_instrumentor.rb +186 -0
  41. data/lib/one_apm/agent/pipe/pipe_channel_manager.rb +275 -0
  42. data/lib/one_apm/agent/pipe/pipe_service.rb +81 -0
  43. data/lib/one_apm/agent/sampler.rb +55 -0
  44. data/lib/one_apm/agent/sampler_collection.rb +65 -0
  45. data/lib/one_apm/agent/samplers/cpu_sampler.rb +49 -0
  46. data/lib/one_apm/agent/samplers/delayed_job_sampler.rb +109 -0
  47. data/lib/one_apm/agent/samplers/memory_sampler.rb +144 -0
  48. data/lib/one_apm/agent/samplers/object_sampler.rb +22 -0
  49. data/lib/one_apm/agent/samplers/vm_sampler.rb +124 -0
  50. data/lib/one_apm/agent/synthetics_monitor.rb +48 -0
  51. data/lib/one_apm/agent/threading/agent_thread.rb +74 -0
  52. data/lib/one_apm/agent/threading/backtrace_node.rb +133 -0
  53. data/lib/one_apm/agent/threading/backtrace_service.rb +259 -0
  54. data/lib/one_apm/agent/threading/thread_profile.rb +155 -0
  55. data/lib/one_apm/collector/collector/helper.rb +139 -0
  56. data/lib/one_apm/collector/collector/http_connection.rb +254 -0
  57. data/lib/one_apm/collector/collector/server_methods.rb +71 -0
  58. data/lib/one_apm/collector/collector_service.rb +123 -0
  59. data/lib/one_apm/collector/commands/agent_command.rb +17 -0
  60. data/lib/one_apm/collector/commands/thread_profiler_session.rb +108 -0
  61. data/lib/one_apm/collector/commands/xray_session.rb +53 -0
  62. data/lib/one_apm/collector/commands/xray_session_collection.rb +156 -0
  63. data/lib/one_apm/collector/containers/agent_command_router.rb +153 -0
  64. data/lib/one_apm/collector/containers/custom_event_aggregator.rb +94 -0
  65. data/lib/one_apm/collector/containers/error_collector.rb +349 -0
  66. data/lib/one_apm/collector/containers/sql_sampler.rb +331 -0
  67. data/lib/one_apm/collector/containers/stats_engine.rb +34 -0
  68. data/lib/one_apm/collector/containers/transaction_event_aggregator.rb +249 -0
  69. data/lib/one_apm/collector/containers/transaction_sampler.rb +352 -0
  70. data/lib/one_apm/collector/containers/utilization_data.rb +36 -0
  71. data/lib/one_apm/collector/stats_engine/gc_profiler.rb +106 -0
  72. data/lib/one_apm/collector/stats_engine/metric_stats.rb +243 -0
  73. data/lib/one_apm/collector/stats_engine/stats_hash.rb +105 -0
  74. data/lib/one_apm/configuration.rb +429 -0
  75. data/lib/one_apm/configuration/autostart.rb +41 -0
  76. data/lib/one_apm/configuration/default_source.rb +1026 -0
  77. data/lib/one_apm/configuration/environment_source.rb +113 -0
  78. data/lib/one_apm/configuration/high_security_source.rb +56 -0
  79. data/lib/one_apm/configuration/manual_source.rb +13 -0
  80. data/lib/one_apm/configuration/server_source.rb +60 -0
  81. data/lib/one_apm/configuration/yaml_source.rb +134 -0
  82. data/lib/one_apm/errors/agent_errors.rb +26 -0
  83. data/lib/one_apm/errors/internal_agent_error.rb +16 -0
  84. data/lib/one_apm/errors/noticed_error.rb +79 -0
  85. data/lib/one_apm/frameworks/external.rb +15 -0
  86. data/lib/one_apm/frameworks/rails.rb +103 -0
  87. data/lib/one_apm/frameworks/rails3.rb +37 -0
  88. data/lib/one_apm/frameworks/rails4.rb +21 -0
  89. data/lib/one_apm/frameworks/ruby.rb +21 -0
  90. data/lib/one_apm/frameworks/sinatra.rb +12 -0
  91. data/lib/one_apm/inst/3rd/active_merchant.rb +35 -0
  92. data/lib/one_apm/inst/3rd/acts_as_solr.rb +70 -0
  93. data/lib/one_apm/inst/3rd/authlogic.rb +23 -0
  94. data/lib/one_apm/inst/3rd/sunspot.rb +31 -0
  95. data/lib/one_apm/inst/background_job/active_job.rb +88 -0
  96. data/lib/one_apm/inst/background_job/delayed_job.rb +52 -0
  97. data/lib/one_apm/inst/background_job/delayed_job_injection.rb +8 -0
  98. data/lib/one_apm/inst/background_job/resque.rb +107 -0
  99. data/lib/one_apm/inst/background_job/sidekiq.rb +64 -0
  100. data/lib/one_apm/inst/dispatcher/passenger.rb +25 -0
  101. data/lib/one_apm/inst/dispatcher/rainbows.rb +23 -0
  102. data/lib/one_apm/inst/framework/grape.rb +94 -0
  103. data/lib/one_apm/inst/framework/padrino.rb +30 -0
  104. data/lib/one_apm/inst/framework/sinatra.rb +185 -0
  105. data/lib/one_apm/inst/framework/sinatra/ignorer.rb +50 -0
  106. data/lib/one_apm/inst/framework/sinatra/transaction_namer.rb +54 -0
  107. data/lib/one_apm/inst/http_clients/curb.rb +189 -0
  108. data/lib/one_apm/inst/http_clients/excon.rb +70 -0
  109. data/lib/one_apm/inst/http_clients/excon/connection.rb +31 -0
  110. data/lib/one_apm/inst/http_clients/excon/middleware.rb +55 -0
  111. data/lib/one_apm/inst/http_clients/httpclient.rb +44 -0
  112. data/lib/one_apm/inst/http_clients/net.rb +34 -0
  113. data/lib/one_apm/inst/http_clients/typhoeus.rb +76 -0
  114. data/lib/one_apm/inst/nosql/memcache.rb +134 -0
  115. data/lib/one_apm/inst/nosql/mongo.rb +126 -0
  116. data/lib/one_apm/inst/nosql/mongo_moped.rb +85 -0
  117. data/lib/one_apm/inst/nosql/redis.rb +83 -0
  118. data/lib/one_apm/inst/orm/active_record.rb +99 -0
  119. data/lib/one_apm/inst/orm/active_record_4.rb +28 -0
  120. data/lib/one_apm/inst/orm/data_mapper.rb +180 -0
  121. data/lib/one_apm/inst/orm/sequel.rb +47 -0
  122. data/lib/one_apm/inst/rack.rb +38 -0
  123. data/lib/one_apm/inst/rack/rack.rb +44 -0
  124. data/lib/one_apm/inst/rack/rack_builder.rb +51 -0
  125. data/lib/one_apm/inst/rails/action_controller.rb +118 -0
  126. data/lib/one_apm/inst/rails/action_web_service.rb +44 -0
  127. data/lib/one_apm/inst/rails/errors.rb +43 -0
  128. data/lib/one_apm/inst/rails3/action_controller.rb +172 -0
  129. data/lib/one_apm/inst/rails3/errors.rb +43 -0
  130. data/lib/one_apm/inst/rails4/action_controller.rb +27 -0
  131. data/lib/one_apm/inst/rails4/action_controller_subscriber.rb +121 -0
  132. data/lib/one_apm/inst/rails4/action_view.rb +23 -0
  133. data/lib/one_apm/inst/rails4/action_view_subscriber.rb +93 -0
  134. data/lib/one_apm/inst/rails4/active_record_subscriber.rb +96 -0
  135. data/lib/one_apm/inst/rails4/errors.rb +42 -0
  136. data/lib/one_apm/inst/rails_middleware.rb +40 -0
  137. data/lib/one_apm/inst/support/evented_subscriber.rb +98 -0
  138. data/lib/one_apm/inst/support/ignore_actions.rb +39 -0
  139. data/lib/one_apm/inst/support/queue_time.rb +76 -0
  140. data/lib/one_apm/inst/transaction_base.rb +405 -0
  141. data/lib/one_apm/logger/agent_logger.rb +206 -0
  142. data/lib/one_apm/logger/audit_logger.rb +78 -0
  143. data/lib/one_apm/logger/memory_logger.rb +50 -0
  144. data/lib/one_apm/logger/null_logger.rb +19 -0
  145. data/lib/one_apm/metrics/metric_data.rb +72 -0
  146. data/lib/one_apm/metrics/metric_spec.rb +82 -0
  147. data/lib/one_apm/metrics/stats.rb +173 -0
  148. data/lib/one_apm/probe.rb +16 -0
  149. data/lib/one_apm/probe/framework_loader.rb +53 -0
  150. data/lib/one_apm/probe/instance_methods.rb +105 -0
  151. data/lib/one_apm/probe/instrumentation.rb +60 -0
  152. data/lib/one_apm/rack/browser_monitoring.rb +144 -0
  153. data/lib/one_apm/rack/middleware_base.rb +27 -0
  154. data/lib/one_apm/rack/middleware_hooks.rb +17 -0
  155. data/lib/one_apm/rack/middleware_tracing.rb +81 -0
  156. data/lib/one_apm/rack/middleware_wrapper.rb +86 -0
  157. data/lib/one_apm/support/chained_call.rb +15 -0
  158. data/lib/one_apm/support/coerce.rb +81 -0
  159. data/lib/one_apm/support/collection_helper.rb +79 -0
  160. data/lib/one_apm/support/dotted_hash.rb +45 -0
  161. data/lib/one_apm/support/encoders.rb +34 -0
  162. data/lib/one_apm/support/environment_report.rb +127 -0
  163. data/lib/one_apm/support/event_buffer.rb +82 -0
  164. data/lib/one_apm/support/event_buffer/sampled_buffer.rb +45 -0
  165. data/lib/one_apm/support/event_buffer/sized_buffer.rb +21 -0
  166. data/lib/one_apm/support/event_buffer/synthetics_event_buffer.rb +40 -0
  167. data/lib/one_apm/support/helper.rb +49 -0
  168. data/lib/one_apm/support/hostname.rb +13 -0
  169. data/lib/one_apm/support/http_clients/curb_wrappers.rb +65 -0
  170. data/lib/one_apm/support/http_clients/excon_wrappers.rb +63 -0
  171. data/lib/one_apm/support/http_clients/httpclient_wrappers.rb +61 -0
  172. data/lib/one_apm/support/http_clients/net_http_wrappers.rb +48 -0
  173. data/lib/one_apm/support/http_clients/typhoeus_wrappers.rb +73 -0
  174. data/lib/one_apm/support/http_clients/uri_util.rb +39 -0
  175. data/lib/one_apm/support/json_marshaller.rb +68 -0
  176. data/lib/one_apm/support/json_wrapper.rb +130 -0
  177. data/lib/one_apm/support/language_support.rb +142 -0
  178. data/lib/one_apm/support/library_detection.rb +119 -0
  179. data/lib/one_apm/support/local_environment.rb +196 -0
  180. data/lib/one_apm/support/marshaller.rb +62 -0
  181. data/lib/one_apm/support/method_tracer.rb +334 -0
  182. data/lib/one_apm/support/method_tracer/helpers.rb +92 -0
  183. data/lib/one_apm/support/method_tracer/traced_method_stack.rb +103 -0
  184. data/lib/one_apm/support/obfuscator.rb +47 -0
  185. data/lib/one_apm/support/okjson.rb +601 -0
  186. data/lib/one_apm/support/parameter_filtering.rb +35 -0
  187. data/lib/one_apm/support/rules_engine.rb +56 -0
  188. data/lib/one_apm/support/rules_engine/replacement_rule.rb +80 -0
  189. data/lib/one_apm/support/rules_engine/segment_terms_rule.rb +46 -0
  190. data/lib/one_apm/support/server.rb +11 -0
  191. data/lib/one_apm/support/supported_versions.rb +257 -0
  192. data/lib/one_apm/support/system_info.rb +211 -0
  193. data/lib/one_apm/support/timer_lib.rb +29 -0
  194. data/lib/one_apm/support/version_number.rb +51 -0
  195. data/lib/one_apm/support/vm.rb +30 -0
  196. data/lib/one_apm/support/vm/jruby_vm.rb +38 -0
  197. data/lib/one_apm/support/vm/monotonic_gc_profiler.rb +43 -0
  198. data/lib/one_apm/support/vm/mri_vm.rb +85 -0
  199. data/lib/one_apm/support/vm/rubinius_vm.rb +129 -0
  200. data/lib/one_apm/support/vm/snapshot.rb +18 -0
  201. data/lib/one_apm/transaction.rb +336 -0
  202. data/lib/one_apm/transaction/class_methods.rb +132 -0
  203. data/lib/one_apm/transaction/instance_helpers.rb +82 -0
  204. data/lib/one_apm/transaction/metric_constants.rb +42 -0
  205. data/lib/one_apm/transaction/sample_buffer/force_persist_sample_buffer.rb +21 -0
  206. data/lib/one_apm/transaction/sample_buffer/slowest_sample_buffer.rb +21 -0
  207. data/lib/one_apm/transaction/sample_buffer/synthetics_sample_buffer.rb +21 -0
  208. data/lib/one_apm/transaction/sample_buffer/transaction_sample_buffer.rb +101 -0
  209. data/lib/one_apm/transaction/sample_buffer/xray_sample_buffer.rb +60 -0
  210. data/lib/one_apm/transaction/segment.rb +193 -0
  211. data/lib/one_apm/transaction/segment_summary.rb +51 -0
  212. data/lib/one_apm/transaction/thread_local_access.rb +73 -0
  213. data/lib/one_apm/transaction/transaction_analysis.rb +78 -0
  214. data/lib/one_apm/transaction/transaction_apdex.rb +20 -0
  215. data/lib/one_apm/transaction/transaction_cpu.rb +22 -0
  216. data/lib/one_apm/transaction/transaction_finish_append.rb +67 -0
  217. data/lib/one_apm/transaction/transaction_ignore.rb +33 -0
  218. data/lib/one_apm/transaction/transaction_jruby_functions.rb +40 -0
  219. data/lib/one_apm/transaction/transaction_metrics.rb +53 -0
  220. data/lib/one_apm/transaction/transaction_name.rb +90 -0
  221. data/lib/one_apm/transaction/transaction_namer.rb +49 -0
  222. data/lib/one_apm/transaction/transaction_sample.rb +204 -0
  223. data/lib/one_apm/transaction/transaction_sample_builder.rb +168 -0
  224. data/lib/one_apm/transaction/transaction_state.rb +149 -0
  225. data/lib/one_apm/transaction/transaction_summary.rb +28 -0
  226. data/lib/one_apm/transaction/transaction_synthetics.rb +40 -0
  227. data/lib/one_apm/transaction/transaction_timings.rb +54 -0
  228. data/lib/one_apm/version.rb +13 -0
  229. data/lib/oneapm_rpm.rb +16 -0
  230. data/lib/sequel/extensions/oneapm_instrumentation.rb +84 -0
  231. data/lib/sequel/plugins/oneapm_instrumentation.rb +66 -0
  232. data/oneapm.yml +135 -0
  233. data/oneapm_rpm.gemspec +58 -0
  234. metadata +474 -0
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Agent
5
+ module Instrumentation
6
+ module Sinatra
7
+ module Ignorer
8
+
9
+ def self.should_ignore?(app, type)
10
+ return false if !app.settings.respond_to?(:oneapm_ignores)
11
+
12
+ app.settings.oneapm_ignores[type].any? do |pattern|
13
+ pattern.match(app.request.path_info)
14
+ end
15
+ end
16
+
17
+ def oneapm_ignore(*routes)
18
+ set_oneapm_ignore(:routes, *routes)
19
+ end
20
+
21
+ def oneapm_ignore_apdex(*routes)
22
+ set_oneapm_ignore(:apdex, *routes)
23
+ end
24
+
25
+ def oneapm_ignore_enduser(*routes)
26
+ set_oneapm_ignore(:enduser, *routes)
27
+ end
28
+
29
+ private
30
+
31
+ def set_oneapm_ignore(type, *routes)
32
+ # Important to default this in the context of the actual app
33
+ # If it's done at register time, ignores end up shared between apps.
34
+ set :oneapm_ignores, Hash.new([]) if !respond_to?(:oneapm_ignores)
35
+
36
+ # If we call an ignore without a route, it applies to the whole app
37
+ routes = ["*"] if routes.empty?
38
+
39
+ settings.oneapm_ignores[type] += routes.map do |r|
40
+ # Ugly sending to private Base#compile, but we want to mimic
41
+ # exactly Sinatra's mapping of route text to regex
42
+ send(:compile, r).first
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Agent
5
+ module Instrumentation
6
+ module Sinatra
7
+ module TransactionNamer
8
+ extend self
9
+
10
+ def transaction_name_for_route(env, request)
11
+ name = route_for_sinatra(env)
12
+ name = route_name_for_padrino(request) if name.nil?
13
+
14
+ transaction_name(name, request) unless name.nil?
15
+ end
16
+
17
+ def initial_transaction_name(request)
18
+ transaction_name(OneApm::Transaction::UNKNOWN_METRIC, request)
19
+ end
20
+
21
+ def transaction_name(route_text, request)
22
+ verb = http_verb(request)
23
+
24
+ route_text = route_text.source if route_text.is_a?(Regexp)
25
+ name = route_text.gsub(%r{^[/^\\A]*(.*?)[/\$\?\\z]*$}, '\1')
26
+ name = "#{verb} #{name}" unless verb.nil?
27
+ name
28
+ rescue => e
29
+ ::OneApm::Agent.logger.debug("#{e.class} : #{e.message} - Error encountered trying to identify Sinatra transaction name")
30
+ OneApm::Transaction::UNKNOWN_METRIC
31
+ end
32
+
33
+ def http_verb(request)
34
+ request.request_method if request.respond_to?(:request_method)
35
+ end
36
+
37
+ # For bare Sinatra, our override on process_route captures the last
38
+ # route into the environment for us to use later on
39
+ def route_for_sinatra(env)
40
+ env["oneapm.last_route"]
41
+ end
42
+
43
+ # For Padrino, the request object has a copy of the matched route
44
+ # on it when we go to evaluating, so we can just retrieve that
45
+ def route_name_for_padrino(request)
46
+ request.route_obj.original_path
47
+ rescue
48
+ nil
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,189 @@
1
+ # encoding: utf-8
2
+
3
+ LibraryDetection.defer do
4
+ named :curb
5
+
6
+ CURB_MINIMUM_VERSION = ::OneApm::VersionNumber.new("0.8.1")
7
+
8
+ depends_on do
9
+ defined?(::Curl) && defined?(::Curl::CURB_VERSION) &&
10
+ ::OneApm::VersionNumber.new(::Curl::CURB_VERSION) >= CURB_MINIMUM_VERSION
11
+ end
12
+
13
+ executes do
14
+ ::OneApm::Agent.logger.info 'Installing Curb instrumentation'
15
+ require 'one_apm/agent/cross_app/cross_app_tracing'
16
+ require 'one_apm/support/http_clients/curb_wrappers'
17
+ end
18
+
19
+ executes do
20
+ class Curl::Easy
21
+
22
+ attr_accessor :_oa_instrumented,
23
+ :_oa_http_verb,
24
+ :_oa_header_str,
25
+ :_oa_original_on_header,
26
+ :_oa_original_on_complete,
27
+ :_oa_serial
28
+
29
+ # We have to hook these three methods separately, as they don't use
30
+ # Curl::Easy#http
31
+ def http_head_with_oneapm(*args, &blk)
32
+ self._oa_http_verb = :HEAD
33
+ http_head_without_oneapm(*args, &blk)
34
+ end
35
+ alias_method :http_head_without_oneapm, :http_head
36
+ alias_method :http_head, :http_head_with_oneapm
37
+
38
+ def http_post_with_oneapm(*args, &blk)
39
+ self._oa_http_verb = :POST
40
+ http_post_without_oneapm(*args, &blk)
41
+ end
42
+ alias_method :http_post_without_oneapm, :http_post
43
+ alias_method :http_post, :http_post_with_oneapm
44
+
45
+ def http_put_with_oneapm(*args, &blk)
46
+ self._oa_http_verb = :PUT
47
+ http_put_without_oneapm(*args, &blk)
48
+ end
49
+ alias_method :http_put_without_oneapm, :http_put
50
+ alias_method :http_put, :http_put_with_oneapm
51
+
52
+
53
+ # Hook the #http method to set the verb.
54
+ def http_with_oneapm( verb )
55
+ self._oa_http_verb = verb.to_s.upcase
56
+ http_without_oneapm( verb )
57
+ end
58
+
59
+ alias_method :http_without_oneapm, :http
60
+ alias_method :http, :http_with_oneapm
61
+
62
+
63
+ # Hook the #perform method to mark the request as non-parallel.
64
+ def perform_with_oneapm
65
+ self._oa_serial = true
66
+ perform_without_oneapm
67
+ end
68
+
69
+ alias_method :perform_without_oneapm, :perform
70
+ alias_method :perform, :perform_with_oneapm
71
+
72
+ # We override this method in order to ensure access to header_str even
73
+ # though we use an on_header callback
74
+ def header_str_with_oneapm
75
+ if self._oa_serial
76
+ self._oa_header_str
77
+ else
78
+ # Since we didn't install a header callback for a non-serial request,
79
+ # just fall back to the original implementation.
80
+ header_str_without_oneapm
81
+ end
82
+ end
83
+
84
+ alias_method :header_str_without_oneapm, :header_str
85
+ alias_method :header_str, :header_str_with_oneapm
86
+ end # class Curl::Easy
87
+
88
+
89
+ class Curl::Multi
90
+ include OneApm::Support::MethodTracer
91
+
92
+ # Add CAT with callbacks if the request is serial
93
+ def add_with_oneapm(curl) #THREAD_LOCAL_ACCESS
94
+ if curl.respond_to?(:_oa_serial) && curl._oa_serial
95
+ hook_pending_request(curl) if OneApm::Agent.tl_is_execution_traced?
96
+ end
97
+
98
+ return add_without_oneapm( curl )
99
+ end
100
+
101
+ alias_method :add_without_oneapm, :add
102
+ alias_method :add, :add_with_oneapm
103
+
104
+
105
+ # Trace as an External/Multiple call if the first request isn't serial.
106
+ def perform_with_oneapm(&blk)
107
+ return perform_without_oneapm if
108
+ self.requests.first &&
109
+ self.requests.first.respond_to?(:_oa_serial) &&
110
+ self.requests.first._oa_serial
111
+
112
+ trace_execution_scoped("External/Multiple/Curb::Multi/perform") do
113
+ perform_without_oneapm(&blk)
114
+ end
115
+ end
116
+
117
+ alias_method :perform_without_oneapm, :perform
118
+ alias_method :perform, :perform_with_oneapm
119
+
120
+
121
+ # Instrument the specified +request+ (a Curl::Easy object) and set up cross-application
122
+ # tracing if it's enabled.
123
+ def hook_pending_request(request) #THREAD_LOCAL_ACCESS
124
+ wrapped_request, wrapped_response = wrap_request(request)
125
+ state = OneApm::TransactionState.tl_get
126
+ t0 = Time.now
127
+ segment = OneApm::Agent::CrossAppTracing.start_trace(state, t0, wrapped_request)
128
+
129
+ unless request._oa_instrumented
130
+ install_header_callback(request, wrapped_response)
131
+ install_completion_callback(request, t0, segment, wrapped_request, wrapped_response)
132
+ request._oa_instrumented = true
133
+ end
134
+ rescue => err
135
+ OneApm::Agent.logger.error("Untrapped exception", err)
136
+ end
137
+
138
+
139
+ # Create request and response adapter objects for the specified +request+
140
+ def wrap_request(request)
141
+ return OneApm::Support::HTTPClients::CurbRequest.new(request),
142
+ OneApm::Support::HTTPClients::CurbResponse.new(request)
143
+ end
144
+
145
+
146
+ # Install a callback that will record the response headers to enable
147
+ # CAT linking
148
+ def install_header_callback( request, wrapped_response )
149
+ original_callback = request.on_header
150
+ request._oa_original_on_header = original_callback
151
+ request._oa_header_str = ''
152
+ request.on_header do |header_data|
153
+ wrapped_response.append_header_data( header_data )
154
+
155
+ if original_callback
156
+ original_callback.call( header_data )
157
+ else
158
+ header_data.length
159
+ end
160
+ end
161
+ end
162
+
163
+ # Install a callback that will finish the trace.
164
+ def install_completion_callback(request, t0, segment, wrapped_request, wrapped_response) #THREAD_LOCAL_ACCESS
165
+ original_callback = request.on_complete
166
+ request._oa_original_on_complete = original_callback
167
+ request.on_complete do |finished_request|
168
+ begin
169
+ state = OneApm::TransactionState.tl_get
170
+ OneApm::Agent::CrossAppTracing.finish_trace(state, t0, segment, wrapped_request, wrapped_response)
171
+ ensure
172
+ # Make sure the existing completion callback is run, and restore the
173
+ # on_complete callback to how it was before.
174
+ original_callback.call(finished_request) if original_callback
175
+ remove_instrumentation_callbacks(request)
176
+ end
177
+ end
178
+ end
179
+
180
+ def remove_instrumentation_callbacks(request)
181
+ request.on_complete(&request._oa_original_on_complete)
182
+ request.on_header(&request._oa_original_on_header)
183
+ request._oa_instrumented = false
184
+ end
185
+
186
+ end # class Curl::Multi
187
+
188
+ end
189
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ LibraryDetection.defer do
4
+ named :excon
5
+
6
+ # We have two ways of instrumenting Excon:
7
+ # - For newer versions, use the middleware mechanism Excon exposes
8
+ # - For older versions, monkey-patch Excon::Connection#request
9
+ #
10
+ # EXCON_MINIMUM_VERSION is the minimum version we attempt to instrument at all.
11
+ # EXCON_MIDDLEWARE_MINIMUM_VERSION is the min version we use the newer
12
+ # instrumentation for.
13
+ #
14
+ # Note that middlewares were added to Excon prior to 0.19, but we don't
15
+ # use middleware-based instrumentation prior to that version because it didn't
16
+ # expose a way for middlewares to know about request failures.
17
+ #
18
+ # Why don't we use Excon.defaults[:instrumentor]?
19
+ # While this might seem a perfect fit, it unfortunately isn't suitable in
20
+ # current form. Someone might reasonably set the default instrumentor to
21
+ # something else after we install our instrumentation. Ideally, excon would
22
+ # itself conform to the #subscribe interface of ActiveSupport::Notifications,
23
+ # so we could safely subscribe and not be clobbered by future subscribers,
24
+ # but alas, it does not yet.
25
+
26
+ EXCON_MINIMUM_VERSION = ::OneApm::VersionNumber.new("0.10.1")
27
+ EXCON_MIDDLEWARE_MINIMUM_VERSION = ::OneApm::VersionNumber.new("0.19.0")
28
+
29
+ depends_on do
30
+ defined?(::Excon) && defined?(::Excon::VERSION)
31
+ end
32
+
33
+ executes do
34
+ excon_version = OneApm::VersionNumber.new(::Excon::VERSION)
35
+ if excon_version >= EXCON_MINIMUM_VERSION
36
+ install_excon_instrumentation(excon_version)
37
+ else
38
+ ::OneApm::Agent.logger.warn("Excon instrumentation requires at least version #{EXCON_MINIMUM_VERSION}")
39
+ end
40
+ end
41
+
42
+ def install_excon_instrumentation(excon_version)
43
+ require 'one_apm/agent/cross_app/cross_app_tracing'
44
+ require 'one_apm/support/http_clients/excon_wrappers'
45
+
46
+ if excon_version >= EXCON_MIDDLEWARE_MINIMUM_VERSION
47
+ install_middleware_excon_instrumentation
48
+ else
49
+ install_legacy_excon_instrumentation
50
+ end
51
+ end
52
+
53
+ def install_middleware_excon_instrumentation
54
+ ::OneApm::Agent.logger.info 'Installing middleware-based Excon instrumentation'
55
+ require 'one_apm/inst/http_clients/excon/middleware'
56
+ defaults = Excon.defaults
57
+
58
+ if defaults[:middlewares]
59
+ defaults[:middlewares] << ::Excon::Middleware::OneApmCrossAppTracing
60
+ else
61
+ ::OneApm::Agent.logger.warn("Did not find :middlewares key in Excon.defaults, skipping Excon instrumentation")
62
+ end
63
+ end
64
+
65
+ def install_legacy_excon_instrumentation
66
+ ::OneApm::Agent.logger.info 'Installing legacy Excon instrumentation'
67
+ require 'one_apm/inst/http_clients/excon/connection'
68
+ ::Excon::Connection.install_oneapm_instrumentation
69
+ end
70
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module ::Excon
4
+ class Connection
5
+ def oneapm_connection_params
6
+ (@connection || @data)
7
+ end
8
+
9
+ def oneapm_resolved_request_params(request_params)
10
+ resolved = oneapm_connection_params.merge(request_params)
11
+ resolved[:headers] = resolved[:headers].merge(request_params[:headers] || {})
12
+ resolved
13
+ end
14
+
15
+ def request_with_oneapm_trace(params, &block)
16
+ orig_response = nil
17
+ resolved_params = oneapm_resolved_request_params(params)
18
+ wrapped_request = ::OneApm::Support::HTTPClients::ExconHTTPRequest.new(resolved_params)
19
+ ::OneApm::Agent::CrossAppTracing.tl_trace_http_request(wrapped_request) do
20
+ orig_response = request_without_oneapm_trace(resolved_params, &block)
21
+ ::OneApm::Support::HTTPClients::ExconHTTPResponse.new(orig_response)
22
+ end
23
+ orig_response
24
+ end
25
+
26
+ def self.install_oneapm_instrumentation
27
+ alias request_without_oneapm_trace request
28
+ alias request request_with_oneapm_trace
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ module ::Excon
4
+ module Middleware
5
+ class OneApmCrossAppTracing
6
+ TRACE_DATA_IVAR = :@oneapm_trace_data
7
+
8
+ def initialize(stack)
9
+ @stack = stack
10
+ end
11
+
12
+ def request_call(datum) #THREAD_LOCAL_ACCESS
13
+ begin
14
+ # Only instrument this request if we haven't already done so, because
15
+ # we can get request_call multiple times for requests marked as
16
+ # :idempotent in the options, but there will be only a single
17
+ # accompanying response_call/error_call.
18
+ if datum[:connection] && !datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
19
+ wrapped_request = ::OneApm::Support::HTTPClients::ExconHTTPRequest.new(datum)
20
+ state = ::OneApm::TransactionState.tl_get
21
+ t0 = Time.now
22
+ segment = ::OneApm::Agent::CrossAppTracing.start_trace(state, t0, wrapped_request)
23
+ datum[:connection].instance_variable_set(TRACE_DATA_IVAR, [t0, segment, wrapped_request])
24
+ end
25
+ rescue => e
26
+ OneApm::Agent.logger.debug(e)
27
+ end
28
+ @stack.request_call(datum)
29
+ end
30
+
31
+ def response_call(datum)
32
+ finish_trace(datum)
33
+ @stack.response_call(datum)
34
+ end
35
+
36
+ def error_call(datum)
37
+ finish_trace(datum)
38
+ @stack.error_call(datum)
39
+ end
40
+
41
+ def finish_trace(datum) #THREAD_LOCAL_ACCESS
42
+ trace_data = datum[:connection] && datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
43
+ if trace_data
44
+ datum[:connection].instance_variable_set(TRACE_DATA_IVAR, nil)
45
+ t0, segment, wrapped_request = trace_data
46
+ if datum[:response]
47
+ wrapped_response = ::OneApm::Support::HTTPClients::ExconHTTPResponse.new(datum[:response])
48
+ end
49
+ state = ::OneApm::TransactionState.tl_get
50
+ ::OneApm::Agent::CrossAppTracing.finish_trace(state, t0, segment, wrapped_request, wrapped_response)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end