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,45 @@
1
+ module OneApm
2
+ module Agent
3
+ class Agent
4
+ module Helpers
5
+
6
+ def obfuscator
7
+ @obfuscator ||= lambda {|sql| OneApm::Agent::Database.default_sql_obfuscator(sql) }
8
+ end
9
+ # Sets a thread local variable as to whether we should or
10
+ # should not record sql in the current thread. Returns the
11
+ # previous value, if there is one
12
+ def set_record_sql(should_record) #THREAD_LOCAL_ACCESS
13
+ state = TransactionState.tl_get
14
+ prev = state.record_sql
15
+ state.record_sql = should_record
16
+ prev.nil? || prev
17
+ end
18
+
19
+ # Sets a thread local variable as to whether we should or
20
+ # should not record transaction traces in the current
21
+ # thread. Returns the previous value, if there is one
22
+ def set_record_tt(should_record) #THREAD_LOCAL_ACCESS
23
+ state = TransactionState.tl_get
24
+ prev = state.record_tt
25
+ state.record_tt = should_record
26
+ prev.nil? || prev
27
+ end
28
+
29
+ # Push flag indicating whether we should be tracing in this
30
+ # thread. This uses a stack which allows us to disable tracing
31
+ # children of a transaction without affecting the tracing of
32
+ # the whole transaction
33
+ def push_trace_execution_flag(should_trace=false) #THREAD_LOCAL_ACCESS
34
+ TransactionState.tl_get.push_traced(should_trace)
35
+ end
36
+
37
+ # Pop the current trace execution status. Restore trace execution status
38
+ # to what it was before we pushed the current flag.
39
+ def pop_trace_execution_flag #THREAD_LOCAL_ACCESS
40
+ TransactionState.tl_get.pop_traced
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,226 @@
1
+ module OneApm
2
+ module Agent
3
+ class Agent
4
+ # Herein lies the corpse of the former 'start' method. May
5
+ # its unmatched flog score rest in pieces.
6
+ module Start
7
+
8
+ # Sanity-check the agent configuration and start the agent,
9
+ # setting up the worker thread and the exit handler to shut
10
+ # down the agent
11
+ def check_config_and_start_agent
12
+ return unless monitoring? && has_correct_license_key?
13
+ return if using_forking_dispatcher?
14
+ setup_and_start_agent
15
+ end
16
+
17
+ # This is the shared method between the main agent startup and the
18
+ # after_fork call restarting the thread in deferred dispatchers.
19
+ #
20
+ # Treatment of @started and env report is important to get right.
21
+ def setup_and_start_agent(options={})
22
+ @started = true
23
+ @harvester.mark_started
24
+
25
+ unless in_resque_child_process?
26
+ generate_environment_report
27
+ install_exit_handler
28
+ @harvest_samplers.load_samplers unless Agent.config[:disable_samplers]
29
+ end
30
+
31
+ connect_in_foreground if Agent.config[:sync_startup]
32
+ start_worker_thread(options)
33
+ end
34
+
35
+ # True if we have initialized and completed 'start'
36
+ def started?
37
+ @started
38
+ end
39
+
40
+ # Check whether we have already started, which is an error condition
41
+ def already_started?
42
+ if started?
43
+ ::OneApm::Agent.logger.error("Agent Started Already!")
44
+ true
45
+ end
46
+ end
47
+
48
+ # Installs our exit handler, which exploits the weird
49
+ # behavior of at_exit blocks to make sure it runs last, by
50
+ # doing an at_exit within an at_exit block.
51
+ def install_exit_handler
52
+ if Agent.config[:send_data_on_exit] && !weird_ruby?
53
+ at_exit do
54
+ # Workaround for MRI 1.9 bug that loses exit codes in at_exit blocks.
55
+ # This is necessary to get correct exit codes for the agent's
56
+ # test suites.
57
+ # http://bugs.ruby-lang.org/issues/5218
58
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
59
+ exit_status = $!.status if $!.is_a?(SystemExit)
60
+ shutdown
61
+ exit exit_status if exit_status
62
+ else
63
+ shutdown
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # The agent is disabled when it is not force enabled by the
70
+ # 'agent_enabled' option (e.g. in a manual start), or
71
+ # enabled normally through the configuration file
72
+ def disabled?
73
+ !Agent.config[:agent_enabled]
74
+ end
75
+
76
+ # Logs the configured application names
77
+ def app_name_configured?
78
+ names = Agent.config.app_names
79
+ return names.respond_to?(:any?) && names.any?
80
+ end
81
+
82
+ # Connecting in the foreground blocks further startup of the
83
+ # agent until we have a connection - useful in cases where
84
+ # you're trying to log a very-short-running process and want
85
+ # to get statistics from before a server connection
86
+ # (typically 20 seconds) exists
87
+ def connect_in_foreground
88
+ OneApm::Agent.disable_all_tracing { connect(:keep_retrying => false) }
89
+ end
90
+
91
+ # If we're using sinatra, old versions run in an at_exit
92
+ # block so we should probably know that
93
+ def using_sinatra?
94
+ defined?(Sinatra::Application)
95
+ end
96
+
97
+ # we should not set an at_exit block if people are using
98
+ # these as they don't do standard at_exit behavior per MRI/YARV
99
+ def weird_ruby?
100
+ OneApm::LanguageSupport.using_engine?('rbx') ||
101
+ OneApm::LanguageSupport.using_engine?('jruby') ||
102
+ using_sinatra?
103
+ end
104
+
105
+ # Warn the user if they have configured their agent not to
106
+ # send data, that way we can see this clearly in the log file
107
+ def monitoring?
108
+ if Agent.config[:monitor_mode]
109
+ true
110
+ else
111
+ ::OneApm::Agent.logger.warn('Agent configured not to send data in this environment.')
112
+ false
113
+ end
114
+ end
115
+
116
+ # Tell the user when the license key is missing so they can
117
+ # fix it by adding it to the file
118
+ def has_license_key?
119
+ if Agent.config[:license_key] && Agent.config[:license_key].length > 0
120
+ true
121
+ else
122
+ ::OneApm::Agent.logger.warn("No license key found. " +
123
+ "This often means your oneapm.yml file was not found, or it lacks a section for the running environment, '#{OneApm::Probe.instance.env}'. You may also want to try linting your oneapm.yml to ensure it is valid YML.")
124
+ false
125
+ end
126
+ end
127
+
128
+ # A correct license key exists and is of the proper length
129
+ def has_correct_license_key?
130
+ has_license_key?
131
+ end
132
+
133
+ # If we're using a dispatcher that forks before serving
134
+ # requests, we need to wait until the children are forked
135
+ # before connecting, otherwise the parent process sends useless data
136
+ def using_forking_dispatcher?
137
+ if [:puma, :passenger, :rainbows, :unicorn].include? Agent.config[:dispatcher]
138
+ ::OneApm::Agent.logger.info "Deferring startup of agent reporting thread because #{Agent.config[:dispatcher]} may fork."
139
+ true
140
+ else
141
+ false
142
+ end
143
+ end
144
+
145
+ def defer_for_background_jobs?
146
+ if defer_for_delayed_job?
147
+ ::OneApm::Agent.logger.debug "Deferring startup for DelayedJob"
148
+ return true
149
+ end
150
+
151
+ if defer_for_resque?
152
+ ::OneApm::Agent.logger.debug "Deferring startup for Resque in case it daemonizes"
153
+ return true
154
+ end
155
+
156
+ false
157
+ end
158
+
159
+ require 'one_apm/inst/background_job/delayed_job_injection'
160
+
161
+ def defer_for_delayed_job?
162
+ OneApm::Agent.config[:dispatcher] == :delayed_job &&
163
+ !OneApm::DelayedJobInjection.worker_name
164
+ end
165
+
166
+ # Return true if we're using resque and it hasn't had a chance to (potentially)
167
+ # daemonize itself. This avoids hanging when there's a Thread started
168
+ # before Resque calls Process.daemon (Jira RUBY-857)
169
+ def defer_for_resque?
170
+ OneApm::Agent.config[:dispatcher] == :resque &&
171
+ OneApm::LanguageSupport.can_fork? &&
172
+ !OneApm::Agent::PipeChannelManager.listener.started?
173
+ end
174
+
175
+ def in_resque_child_process?
176
+ @service.is_a?(OneApm::Agent::PipeService)
177
+ end
178
+
179
+ # Log startup information that we almost always want to know
180
+ def log_startup
181
+ log_environment
182
+ log_dispatcher
183
+ log_app_name
184
+ end
185
+
186
+ # Classy logging of the agent version and the current pid,
187
+ # so we can disambiguate processes in the log file and make
188
+ # sure they're running a reasonable version
189
+ def log_version_and_pid
190
+ ::OneApm::Agent.logger.debug "OneApm Ruby Agent #{OneApm::VERSION::STRING} Initialized: pid = #{$$}"
191
+ end
192
+
193
+ # Log the environment the app thinks it's running in.
194
+ # Useful in debugging, as this is the key for config YAML lookups.
195
+ def log_environment
196
+ ::OneApm::Agent.logger.info "Environment: #{OneApm::Probe.instance.env}"
197
+ end
198
+
199
+ # Logs the dispatcher to the log file to assist with
200
+ # debugging. When no debugger is present, logs this fact to
201
+ # assist with proper dispatcher detection
202
+ def log_dispatcher
203
+ dispatcher_name = Agent.config[:dispatcher].to_s
204
+
205
+ if dispatcher_name.empty?
206
+ ::OneApm::Agent.logger.info 'No known dispatcher detected.'
207
+ else
208
+ ::OneApm::Agent.logger.info "Dispatcher: #{dispatcher_name}"
209
+ end
210
+ end
211
+
212
+ def log_app_name
213
+ ::OneApm::Agent.logger.info "Application: #{Agent.config.app_names.join(", ")}"
214
+ end
215
+
216
+ def log_ignore_url_regexes
217
+ regexes = OneApm::Agent.config[:'rules.ignore_url_regexes']
218
+
219
+ unless regexes.empty?
220
+ ::OneApm::Agent.logger.info "Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}."
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,148 @@
1
+ module OneApm
2
+ module Agent
3
+ class Agent
4
+ # All of this module used to be contained in the
5
+ # start_worker_thread method - this is an artifact of
6
+ # refactoring and can be moved, renamed, etc at will
7
+ module StartWorkerThread
8
+
9
+ # Never allow any data type to be reported more frequently than once
10
+ # per second.
11
+ MIN_ALLOWED_REPORT_PERIOD = 1.0
12
+ UTILIZATION_REPORT_PERIOD = 30 * 60 # every half hour
13
+ LOG_ONCE_KEYS_RESET_PERIOD = 60.0
14
+
15
+ # Try to launch the worker thread and connect to the server.
16
+ #
17
+ # See #connect for a description of connection_options.
18
+ def start_worker_thread(connection_options = {})
19
+ if disable = OneApm::Agent.config[:disable_harvest_thread]
20
+ OneApm::Agent.logger.info "Not starting Ruby Agent worker thread because :disable_harvest_thread is #{disable}"
21
+ return
22
+ end
23
+
24
+ ::OneApm::Agent.logger.info "Creating Ruby Agent worker thread."
25
+ @worker_thread = OneApm::Agent::Threading::AgentThread.create('Worker Loop') do
26
+ deferred_work!(connection_options)
27
+ end
28
+ end
29
+
30
+ # This is the method that is run in a new thread in order to
31
+ # background the harvesting and sending of data during the
32
+ # normal operation of the agent.
33
+ #
34
+ # Takes connection options that determine how we should
35
+ # connect to the server, and loops endlessly - typically we
36
+ # never return from this method unless we're shutting down
37
+ # the agent
38
+ def deferred_work!(connection_options)
39
+ catch_errors do
40
+ OneApm::Agent.disable_all_tracing do
41
+ connect(connection_options)
42
+ if connected?
43
+ create_and_run_event_loop
44
+ # never reaches here unless there is a problem or
45
+ # the agent is exiting
46
+ else
47
+ ::OneApm::Agent.logger.debug "No connection. Worker thread ending."
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def create_and_run_event_loop
54
+ @event_loop = create_event_loop
55
+
56
+ @event_loop.on(:report_data) { transmit_data }
57
+ @event_loop.on(:report_event_data) { transmit_event_data }
58
+ @event_loop.on(:reset_log_once_keys) { OneApm::Agent.logger.clear_already_logged }
59
+
60
+ @event_loop.fire_every(Agent.config[:data_report_period], :report_data)
61
+ @event_loop.fire_every(report_period_for(:analytic_event_data), :report_event_data)
62
+ @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
63
+
64
+ if Agent.config[:collect_utilization] && !in_resque_child_process?
65
+ @event_loop.on(:report_utilization_data) { transmit_utilization_data }
66
+
67
+ @event_loop.fire(:report_utilization_data)
68
+ @event_loop.fire_every(UTILIZATION_REPORT_PERIOD, :report_utilization_data)
69
+ end
70
+
71
+ @event_loop.run
72
+ end
73
+
74
+ def create_event_loop
75
+ EventLoop.new
76
+ end
77
+
78
+ def report_period_for(method)
79
+ config_key = "data_report_periods.#{method}".to_sym
80
+ period = Agent.config[config_key]
81
+ if !period
82
+ period = Agent.config[:data_report_period]
83
+ ::OneApm::Agent.logger.warn("Could not find configured period for #{method}, falling back to data_report_period (#{period} s)")
84
+ end
85
+ if period < MIN_ALLOWED_REPORT_PERIOD
86
+ ::OneApm::Agent.logger.warn("Configured #{config_key} was #{period}, but minimum allowed is #{MIN_ALLOWED_REPORT_PERIOD}, using #{MIN_ALLOWED_REPORT_PERIOD}.")
87
+ period = MIN_ALLOWED_REPORT_PERIOD
88
+ end
89
+ period
90
+ end
91
+
92
+ def stop_event_loop
93
+ if @event_loop
94
+ @event_loop.run_once(true) if Agent.config[:force_send]
95
+ @event_loop.stop
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ # a wrapper method to handle all the errors that can happen
102
+ # in the connection and worker thread system. This
103
+ # guarantees a no-throw from the background thread.
104
+ def catch_errors
105
+ yield
106
+ rescue OneApm::ForceRestartException => e
107
+ handle_force_restart(e)
108
+ retry
109
+ rescue OneApm::ForceDisconnectException => e
110
+ handle_force_disconnect(e)
111
+ rescue => e
112
+ handle_other_error(e)
113
+ end
114
+
115
+ # Handles the case where the server tells us to restart -
116
+ # this clears the data, clears connection attempts, and
117
+ # waits a while to reconnect.
118
+ def handle_force_restart(error)
119
+ ::OneApm::Agent.logger.debug error.message
120
+ drop_buffered_data
121
+ @service.reset_metric_id_cache if @service
122
+ @connect_state = :pending
123
+ sleep 30
124
+ end
125
+
126
+ # when a disconnect is requested, stop the current thread, which
127
+ # is the worker thread that gathers data and talks to the
128
+ # server.
129
+ def handle_force_disconnect(error)
130
+ ::OneApm::Agent.logger.warn "OneApm forced this agent to disconnect (#{error.message})"
131
+ disconnect
132
+ end
133
+
134
+ # Handles an unknown error in the worker thread by logging
135
+ # it and disconnecting the agent, since we are now in an
136
+ # unknown state.
137
+ def handle_other_error(error)
138
+ ::OneApm::Agent.logger.error "Unhandled error in worker thread, disconnecting this agent process:"
139
+ # These errors are fatal (that is, they will prevent the agent from
140
+ # reporting entirely), so we really want backtraces when they happen
141
+ ::OneApm::Agent.logger.log_exception(:error, error)
142
+ disconnect
143
+ end
144
+
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/transaction/transaction_state'
4
+
5
+ module OneApm
6
+ module Agent
7
+ # This module supports calculation of actual time spent processing requests over the course of
8
+ # one harvest period. It's similar to what you would get if you just added up all the
9
+ # execution times of controller calls, however that will be inaccurate when requests
10
+ # span the minute boundaries. This module manages accounting of requests not yet
11
+ # completed.
12
+ #
13
+ # Calls are re-entrant. All start calls must be paired with finish
14
+ # calls, or a reset call.
15
+ module BusyCalculator
16
+
17
+ extend self
18
+
19
+ # For testability, add accessors:
20
+ attr_reader :harvest_start, :accumulator
21
+
22
+ # sets up busy calculations based on the start and end of
23
+ # transactions - used for a rough estimate of what percentage of
24
+ # wall clock time is spent processing requests
25
+ def dispatcher_start(time) #THREAD_LOCAL_ACCESS
26
+ state = TransactionState.tl_get
27
+ state.busy_entries ||= 0
28
+ callers = state.busy_entries += 1
29
+ return if callers > 1
30
+ @lock.synchronize do
31
+ @entrypoint_stack.push time
32
+ end
33
+ end
34
+
35
+ # called when a transaction finishes, to add time to the
36
+ # instance variable accumulator. this is harvested when we send
37
+ # data to the server
38
+ def dispatcher_finish(end_time = nil) #THREAD_LOCAL_ACCESS
39
+ state = TransactionState.tl_get
40
+ # If #dispatcher_start hasn't been called at least once, abort early
41
+ return unless state.busy_entries
42
+
43
+ end_time ||= time_now
44
+ callers = state.busy_entries -= 1
45
+
46
+ # Ignore nested calls
47
+ return if callers > 0
48
+
49
+ @lock.synchronize do
50
+ if @entrypoint_stack.empty?
51
+ ::OneApm::Agent.logger.warn("Stack underflow tracking dispatcher entry and exit!\n #{caller.join(" \n")}")
52
+ else
53
+ @accumulator += (end_time - @entrypoint_stack.pop).to_f
54
+ end
55
+ end
56
+ end
57
+
58
+ # this returns the size of the entry point stack, which
59
+ # determines how many transactions are running
60
+ def busy_count
61
+ @entrypoint_stack.size
62
+ end
63
+
64
+ # Reset the state of the information accumulated by all threads,
65
+ # but only reset the recursion counter for this thread.
66
+ def reset #THREAD_LOCAL_ACCESS
67
+ @entrypoint_stack = []
68
+ TransactionState.tl_get.busy_entries = 0
69
+ @lock ||= Mutex.new
70
+ @accumulator = 0
71
+ @harvest_start = time_now
72
+ end
73
+
74
+
75
+ # Called before uploading to to the server to collect current busy stats.
76
+ def harvest_busy
77
+ busy = 0
78
+ t0 = time_now
79
+ @lock.synchronize do
80
+ busy = accumulator
81
+ @accumulator = 0
82
+
83
+ # Walk through the stack and capture all times up to
84
+ # now for entrypoints
85
+ @entrypoint_stack.size.times do |frame|
86
+ busy += (t0 - @entrypoint_stack[frame]).to_f
87
+ @entrypoint_stack[frame] = t0
88
+ end
89
+
90
+ end
91
+
92
+ busy = 0.0 if busy < 0.0 # don't go below 0%
93
+
94
+ time_window = (t0 - harvest_start).to_f
95
+ time_window = 1.0 if time_window == 0.0 # protect against divide by zero
96
+
97
+ busy = busy / time_window
98
+
99
+ if Agent.config[:report_instance_busy]
100
+ OneApm::Agent.record_metric('Instance/Busy', busy)
101
+ end
102
+ @harvest_start = t0
103
+ end
104
+
105
+ private
106
+
107
+ # so we can stub Time.now only for the BusyCalculator in tests
108
+ def time_now
109
+ Time.now
110
+ end
111
+
112
+ self.reset
113
+ end
114
+ end
115
+ end