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,81 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Agent
5
+ class PipeService
6
+ attr_reader :channel_id, :buffer, :pipe
7
+ attr_accessor :request_timeout, :agent_id, :collector
8
+
9
+ def initialize(channel_id)
10
+ @channel_id = channel_id
11
+ @collector = OneApm::Support::Server.new(:name => 'parent', :port => 0)
12
+ @pipe = OneApm::Agent::PipeChannelManager.channels[@channel_id]
13
+ if @pipe && @pipe.parent_pid != $$
14
+ @pipe.after_fork_in_child
15
+ else
16
+ OneApm::Agent.logger.error("No communication channel to parent process, please see https://oneapm.com/docs/ruby/resque-instrumentation for more information.")
17
+ end
18
+ end
19
+
20
+ def connect(config)
21
+ nil
22
+ end
23
+
24
+ def get_agent_commands
25
+ []
26
+ end
27
+
28
+ def analytic_event_data(events)
29
+ write_to_pipe(:analytic_event_data, events) if events
30
+ end
31
+
32
+ def custom_event_data(events)
33
+ write_to_pipe(:custom_event_data, events) if events
34
+ end
35
+
36
+ def metric_data(unsent_timeslice_data)
37
+ write_to_pipe(:metric_data, unsent_timeslice_data)
38
+ {}
39
+ end
40
+
41
+ def transaction_sample_data(transactions)
42
+ write_to_pipe(:transaction_sample_data, transactions) if transactions
43
+ end
44
+
45
+ def error_data(errors)
46
+ write_to_pipe(:error_data, errors) if errors
47
+ end
48
+
49
+ def sql_trace_data(sql)
50
+ write_to_pipe(:sql_trace_data, sql) if sql
51
+ end
52
+
53
+ def shutdown(time)
54
+ @pipe.close if @pipe
55
+ end
56
+
57
+ # Invokes the block it is passed. This is used to implement HTTP
58
+ # keep-alive in the CollectorService, and is a required interface for any
59
+ # Service class.
60
+ def session
61
+ yield
62
+ end
63
+
64
+ def reset_metric_id_cache
65
+ # we don't cache metric IDs, so nothing to do
66
+ end
67
+
68
+ private
69
+
70
+ def marshal_payload(data)
71
+ OneApm::LanguageSupport.with_cautious_gc do
72
+ Marshal.dump(data)
73
+ end
74
+ end
75
+
76
+ def write_to_pipe(endpoint, data)
77
+ @pipe.write(marshal_payload([endpoint, data])) if @pipe
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Agent
5
+ class Sampler
6
+
7
+ attr_reader :id
8
+
9
+ @sampler_classes = []
10
+
11
+ class << self
12
+
13
+ def named(new_name)
14
+ @name = new_name
15
+ end
16
+
17
+ def name
18
+ @name
19
+ end
20
+
21
+ def inherited(subclass)
22
+ @sampler_classes << subclass
23
+ end
24
+
25
+ def supported_on_this_platform?
26
+ true
27
+ end
28
+
29
+ def enabled?
30
+ if @name
31
+ config_key = "disable_#{@name}_sampler"
32
+ !(Agent.config[config_key])
33
+ else
34
+ true
35
+ end
36
+ end
37
+
38
+ def sampler_classes
39
+ @sampler_classes
40
+ end
41
+
42
+ end
43
+
44
+ def initialize(id = nil)
45
+ @id = id || self.class.name
46
+ end
47
+
48
+ def poll
49
+ raise "Implement in the subclass"
50
+ end
51
+
52
+ class Unsupported < StandardError; end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Agent
5
+ class SamplerCollection
6
+ include Enumerable
7
+
8
+ def initialize(event_listener)
9
+ @samplers = []
10
+ @event_listener = event_listener
11
+ @event_listener.subscribe(:before_harvest) { poll_samplers }
12
+ end
13
+
14
+ def each(&blk)
15
+ @samplers.each(&blk)
16
+ end
17
+
18
+ def clear()
19
+ @samplers.clear
20
+ end
21
+
22
+ def sampler_class_registered?(sampler_class)
23
+ self.any? { |s| s.class == sampler_class }
24
+ end
25
+
26
+ # adds samplers to the sampler collection so that they run every
27
+ # minute. This is dynamically recognized by any class that
28
+ # subclasses OneApm::Agent::Sampler
29
+ def load_samplers
30
+ Sampler.sampler_classes.each do |subclass|
31
+ add_sampler(subclass)
32
+ end
33
+ end
34
+
35
+ def poll_samplers
36
+ @samplers.delete_if do |sampler|
37
+ begin
38
+ sampler.poll
39
+ false
40
+ rescue => e
41
+ ::OneApm::Agent.logger.warn("Removing #{sampler} from list", e)
42
+ true # remove the bad sampler
43
+ end
44
+ end
45
+ end
46
+
47
+ def add_sampler(sampler_class)
48
+ supported = sampler_class.supported_on_this_platform?
49
+ enabled = sampler_class.enabled?
50
+ if supported && enabled && !sampler_class_registered?(sampler_class)
51
+ sampler = sampler_class.new
52
+ sampler.setup_events(@event_listener) if sampler.respond_to?(:setup_events)
53
+ @samplers << sampler
54
+ ::OneApm::Agent.logger.debug("Registered #{sampler_class.name} for harvest time sampling.")
55
+ else
56
+ ::OneApm::Agent.logger.debug("#{sampler_class.name} not supported on this platform.")
57
+ end
58
+ rescue OneApm::Agent::Sampler::Unsupported => e
59
+ ::OneApm::Agent.logger.info("#{sampler_class.name} not available: #{e}")
60
+ rescue => e
61
+ ::OneApm::Agent.logger.error("Error registering sampler:", e)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/agent/sampler'
4
+
5
+ module OneApm
6
+ module Agent
7
+ module Samplers
8
+ class CpuSampler < OneApm::Agent::Sampler
9
+ attr_reader :last_time
10
+
11
+ named :cpu
12
+
13
+ def initialize
14
+ @processor_count = OneApm::Agent::SystemInfo.num_logical_processors
15
+ poll
16
+ end
17
+
18
+ def self.supported_on_this_platform?
19
+ # Process.times on JRuby < 1.7.0 reports wall clock elapsed time, not actual cpu time used
20
+ defined?(JRuby) ? (JRUBY_VERSION >= '1.7.0') : true
21
+ end
22
+
23
+ def poll
24
+ now = Time.now
25
+ t = Process.times
26
+ if @last_time
27
+ elapsed = now - @last_time
28
+ return if elapsed < 1 # Causing some kind of math underflow
29
+
30
+ usertime = t.utime - @last_utime
31
+ systemtime = t.stime - @last_stime
32
+
33
+ if systemtime >= 0
34
+ OneApm::Agent.record_metric("CPU/System Time", systemtime)
35
+ OneApm::Agent.record_metric("CPU/System/Utilization", systemtime / (elapsed * @processor_count))
36
+ end
37
+ if usertime >= 0
38
+ OneApm::Agent.record_metric("CPU/User Time", usertime)
39
+ OneApm::Agent.record_metric("CPU/User/Utilization", usertime / (elapsed * @processor_count))
40
+ end
41
+ end
42
+ @last_utime = t.utime
43
+ @last_stime = t.stime
44
+ @last_time = now
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/agent/sampler'
4
+ require 'one_apm/inst/background_job/delayed_job_injection'
5
+
6
+ module OneApm
7
+ module Agent
8
+ module Samplers
9
+ # This sampler records the status of your delayed job table once a minute.
10
+ # It assumes jobs are cleared after being run, and failed jobs are not (otherwise
11
+ # the failed job metric is useless).
12
+ #
13
+ # In earlier versions it will break out the queue length by priority. In later
14
+ # versions of DJ where distinct queues are supported, it breaks it out by queue name.
15
+ #
16
+ class DelayedJobSampler < OneApm::Agent::Sampler
17
+ named :delayed_job
18
+
19
+ # DelayedJob supports multiple backends, only some of which we can
20
+ # handle. Check whether we think we've got what we need here.
21
+ def self.supported_backend?
22
+ ::Delayed::Worker.backend.to_s == "Delayed::Backend::ActiveRecord::Job"
23
+ end
24
+
25
+ def initialize
26
+ raise Unsupported, "DJ queue sampler disabled" if Agent.config[:disable_dj]
27
+ raise Unsupported, "DJ queue sampling unsupported with backend '#{::Delayed::Worker.backend}'" unless self.class.supported_backend?
28
+ raise Unsupported, "No DJ worker present. Skipping DJ queue sampler" unless OneApm::DelayedJobInjection.worker_name
29
+ end
30
+
31
+ def record_failed_jobs(value)
32
+ OneApm::Agent.record_metric("Workers/DelayedJob/failed_jobs", value)
33
+ end
34
+
35
+ def record_locked_jobs(value)
36
+ OneApm::Agent.record_metric("Workers/DelayedJob/locked_jobs", value)
37
+ end
38
+
39
+ FAILED_QUERY = 'failed_at is not NULL'.freeze
40
+ LOCKED_QUERY = 'locked_by is not NULL'.freeze
41
+
42
+ def failed_jobs
43
+ count(FAILED_QUERY)
44
+ end
45
+
46
+ def locked_jobs
47
+ count(LOCKED_QUERY)
48
+ end
49
+
50
+ def count(query)
51
+ if ::ActiveRecord::VERSION::MAJOR.to_i < 4
52
+ ::Delayed::Job.count(query)
53
+ else
54
+ ::Delayed::Job.where(query).count
55
+ end
56
+ end
57
+
58
+ def self.supported_on_this_platform?
59
+ defined?(::Delayed::Job)
60
+ end
61
+
62
+ def poll
63
+ record_failed_jobs(failed_jobs)
64
+ record_locked_jobs(locked_jobs)
65
+ record_queue_length_metrics
66
+ end
67
+
68
+ private
69
+
70
+ def record_queue_length_metrics
71
+ counts = []
72
+ counts << record_counts_by("queue", "name") if ::Delayed::Job.instance_methods.include?(:queue)
73
+ counts << record_counts_by("priority")
74
+
75
+ all_metric = "Workers/DelayedJob/queue_length/all"
76
+ OneApm::Agent.record_metric(all_metric, counts.max)
77
+ end
78
+
79
+ QUEUE_QUERY_CONDITION = 'run_at <= ? and failed_at is NULL'.freeze
80
+
81
+ def record_counts_by(column_name, metric_segment = column_name)
82
+ all_count = 0
83
+ queue_counts(column_name).each do |column_val, count|
84
+ all_count += count
85
+ column_val = "default" if column_val.nil? || column_val == ""
86
+ metric = "Workers/DelayedJob/queue_length/#{metric_segment}/#{column_val}"
87
+ OneApm::Agent.record_metric(metric, count)
88
+ end
89
+ all_count
90
+ end
91
+
92
+ def queue_counts(column_name)
93
+ now = ::Delayed::Job.db_time_now
94
+ # There is not an ActiveRecord syntax for what we're trying to do
95
+ # here that's valid on 2.x through 4.1, so split it up.
96
+ result = if ::ActiveRecord::VERSION::MAJOR.to_i < 4
97
+ ::Delayed::Job.count(:group => column_name,
98
+ :conditions => [QUEUE_QUERY_CONDITION, now])
99
+ else
100
+ ::Delayed::Job.where(QUEUE_QUERY_CONDITION, now).
101
+ group(column_name).
102
+ count
103
+ end
104
+ result.to_a
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,144 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/agent/sampler'
4
+
5
+ module OneApm
6
+ module Agent
7
+ module Samplers
8
+
9
+ class MemorySampler < OneApm::Agent::Sampler
10
+ named :memory
11
+
12
+ attr_accessor :sampler
13
+
14
+ def initialize
15
+ # macos, linux, solaris
16
+ if defined? JRuby
17
+ @sampler = JavaHeapSampler.new
18
+ elsif platform =~ /linux/
19
+ @sampler = ProcStatus.new
20
+ if !@sampler.can_run?
21
+ ::OneApm::Agent.logger.debug "Error attempting to use /proc/#{$$}/status file for reading memory. Using ps command instead."
22
+ @sampler = ShellPS.new("ps -o rsz")
23
+ else
24
+ ::OneApm::Agent.logger.debug "Using /proc/#{$$}/status for reading process memory."
25
+ end
26
+ elsif platform =~ /darwin9/ # 10.5
27
+ @sampler = ShellPS.new("ps -o rsz")
28
+ elsif platform =~ /darwin1\d+/ # >= 10.6
29
+ @sampler = ShellPS.new("ps -o rss")
30
+ elsif platform =~ /freebsd/
31
+ @sampler = ShellPS.new("ps -o rss")
32
+ elsif platform =~ /solaris/
33
+ @sampler = ShellPS.new("/usr/bin/ps -o rss -p")
34
+ end
35
+
36
+ raise Unsupported, "Unsupported platform for getting memory: #{platform}" if @sampler.nil?
37
+ raise Unsupported, "Unable to run #{@sampler}" unless @sampler.can_run?
38
+ end
39
+
40
+ def self.supported_on_this_platform?
41
+ defined?(JRuby) or platform =~ /linux|darwin|freebsd|solaris/
42
+ end
43
+
44
+ def self.platform
45
+ if RUBY_PLATFORM =~ /java/
46
+ %x[uname -s].downcase
47
+ else
48
+ RUBY_PLATFORM.downcase
49
+ end
50
+ end
51
+ def platform
52
+ OneApm::Agent::Samplers::MemorySampler.platform
53
+ end
54
+
55
+ def poll
56
+ sample = @sampler.get_sample
57
+ if sample
58
+ OneApm::Agent.record_metric("Memory/Used", sample)
59
+ end
60
+ end
61
+
62
+ class Base
63
+ def can_run?
64
+ return false if @broken
65
+ m = get_memory rescue nil
66
+ m && m > 0
67
+ end
68
+
69
+ def get_sample
70
+ return nil if @broken
71
+ begin
72
+ m = get_memory
73
+ if m.nil?
74
+ ::OneApm::Agent.logger.warn "Unable to get the resident memory for process #{$$}. Disabling memory sampler."
75
+ @broken = true
76
+ end
77
+ return m
78
+ rescue => e
79
+ ::OneApm::Agent.logger.warn "Unable to get the resident memory for process #{$$}. Disabling memory sampler.", e
80
+ @broken = true
81
+ return nil
82
+ end
83
+ end
84
+ end
85
+
86
+ class JavaHeapSampler < Base
87
+
88
+ def get_memory
89
+ raise "Can't sample Java heap unless running in JRuby" unless defined? JRuby
90
+ java.lang.Runtime.getRuntime.totalMemory / (1024 * 1024).to_f rescue nil
91
+ end
92
+ def to_s
93
+ "JRuby Java heap sampler"
94
+ end
95
+ end
96
+
97
+ class ShellPS < Base
98
+ def initialize(command)
99
+ super()
100
+ @command = command
101
+ end
102
+ # Returns the amount of resident memory this process is using in MB
103
+ #
104
+ def get_memory
105
+ process = $$
106
+ memory = `#{@command} #{process}`.split("\n")[1].to_f / 1024.0 rescue nil
107
+ # if for some reason the ps command doesn't work on the resident os,
108
+ # then don't execute it any more.
109
+ raise "Faulty command: `#{@command} #{process}`" if memory.nil? || memory <= 0
110
+ memory
111
+ end
112
+ def to_s
113
+ "shell command sampler: #{@command}"
114
+ end
115
+ end
116
+
117
+ # ProcStatus
118
+ #
119
+ # A class that samples memory by reading the file /proc/$$/status, which is specific to linux
120
+ #
121
+ class ProcStatus < Base
122
+
123
+ # Returns the amount of resident memory this process is using in MB
124
+ #
125
+ def get_memory
126
+ proc_status = File.open(proc_status_file, "r") {|f| f.read_nonblock(4096).strip }
127
+ if proc_status =~ /RSS:\s*(\d+) kB/i
128
+ return $1.to_f / 1024.0
129
+ end
130
+ raise "Unable to find RSS in #{proc_status_file}"
131
+ end
132
+
133
+ def proc_status_file
134
+ "/proc/#{$$}/status"
135
+ end
136
+
137
+ def to_s
138
+ "proc status file sampler: #{proc_status_file}"
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end