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,352 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/agent'
4
+ require 'one_apm/probe'
5
+ require 'one_apm/transaction/transaction_sample_builder'
6
+ require 'one_apm/transaction/sample_buffer/force_persist_sample_buffer'
7
+ require 'one_apm/transaction/sample_buffer/slowest_sample_buffer'
8
+ require 'one_apm/transaction/sample_buffer/synthetics_sample_buffer'
9
+ require 'one_apm/transaction/sample_buffer/xray_sample_buffer'
10
+
11
+ module OneApm
12
+ module Collector
13
+
14
+ # This class contains the logic for recording and storing transaction
15
+ # traces (sometimes referred to as 'transaction samples').
16
+ #
17
+ # A transaction trace is a detailed timeline of the events that happened
18
+ # during the processing of a single transaction, including database calls,
19
+ # template rendering calls, and other instrumented method calls.
20
+ #
21
+ # @api public
22
+ class TransactionSampler
23
+
24
+ # Module defining methods stubbed out when the agent is disabled
25
+ module Shim
26
+ def on_start_transaction(*args); end
27
+ def notice_push_frame(*args); end
28
+ def notice_pop_frame(*args); end
29
+ def on_finishing_transaction(*args); end
30
+ end
31
+
32
+ attr_reader :last_sample, :xray_sample_buffer
33
+
34
+ def initialize
35
+ @xray_sample_buffer = OneApm::Transaction::XraySampleBuffer.new
36
+
37
+ @sample_buffers = []
38
+ @sample_buffers << @xray_sample_buffer
39
+ @sample_buffers << OneApm::Transaction::SlowestSampleBuffer.new
40
+ @sample_buffers << OneApm::Transaction::SyntheticsSampleBuffer.new
41
+ @sample_buffers << OneApm::Transaction::ForcePersistSampleBuffer.new
42
+
43
+ # This lock is used to synchronize access to the @last_sample
44
+ # and related variables. It can become necessary on JRuby or
45
+ # any 'honest-to-god'-multithreaded system
46
+ @samples_lock = Mutex.new
47
+
48
+ Agent.config.register_callback(:'transaction_tracer.enabled') do |enabled|
49
+ if enabled
50
+ threshold = Agent.config[:'transaction_tracer.transaction_threshold']
51
+ ::OneApm::Agent.logger.debug "Transaction tracing threshold is #{threshold} seconds."
52
+ else
53
+ ::OneApm::Agent.logger.debug "Transaction traces will not be sent to the OneApm service."
54
+ end
55
+ end
56
+
57
+ Agent.config.register_callback(:'transaction_tracer.record_sql') do |config|
58
+ if config == 'raw'
59
+ ::OneApm::Agent.logger.warn("Agent is configured to send raw SQL to the service")
60
+ end
61
+ end
62
+ end
63
+
64
+ def enabled?
65
+ Agent.config[:'transaction_tracer.enabled']
66
+ end
67
+
68
+ def on_start_transaction(state, start_time, uri=nil)
69
+ if enabled?
70
+ start_builder(state, start_time.to_f)
71
+ builder = state.transaction_sample_builder
72
+ builder.set_transaction_uri(uri) if builder
73
+ end
74
+ end
75
+
76
+ # This delegates to the builder to create a new open transaction segment
77
+ # for the frame, beginning at the optionally specified time.
78
+ #
79
+ # Note that in developer mode, this captures a stacktrace for
80
+ # the beginning of each segment, which can be fairly slow
81
+ def notice_push_frame(state, time=Time.now)
82
+ builder = state.transaction_sample_builder
83
+ return unless builder
84
+
85
+ segment = builder.trace_entry(time.to_f)
86
+ segment
87
+ end
88
+
89
+ # Informs the transaction sample builder about the end of a traced frame
90
+ def notice_pop_frame(state, frame, time = Time.now)
91
+ builder = state.transaction_sample_builder
92
+ return unless builder
93
+ raise "finished already???" if builder.sample.finished
94
+ builder.trace_exit(frame, time.to_f)
95
+ end
96
+
97
+ def custom_parameters_from_transaction(txn)
98
+ if Agent.config[:'transaction_tracer.capture_attributes']
99
+ txn.custom_parameters
100
+ else
101
+ {}
102
+ end
103
+ end
104
+
105
+ # This is called when we are done with the transaction. We've
106
+ # unwound the stack to the top level. It also clears the
107
+ # transaction sample builder so that it won't continue to have
108
+ # frames appended to it.
109
+ #
110
+ # It sets various instance variables to the finished sample,
111
+ # depending on which settings are active. See `store_sample`
112
+ def on_finishing_transaction(state, txn, time=Time.now, gc_time=nil)
113
+ last_builder = state.transaction_sample_builder
114
+ return unless last_builder && enabled?
115
+
116
+ state.transaction_sample_builder = nil
117
+ return if last_builder.ignored?
118
+
119
+ last_builder.set_request_params(txn.filtered_params)
120
+ last_builder.set_transaction_name(txn.best_name)
121
+ last_builder.finish_trace(time.to_f, custom_parameters_from_transaction(txn))
122
+
123
+ last_sample = last_builder.sample
124
+ last_sample.guid = txn.guid
125
+ last_sample.set_custom_param(:gc_time, gc_time) if gc_time
126
+
127
+ if state.is_cross_app?
128
+ last_sample.set_custom_param(:'bw.trip_id', txn.cat_trip_id(state))
129
+ last_sample.set_custom_param(:'bw.path_hash', txn.cat_path_hash(state))
130
+ end
131
+
132
+ if txn.is_synthetics_request?
133
+ last_sample.set_custom_param(:'bw.synthetics_resource_id', txn.synthetics_resource_id)
134
+ last_sample.set_custom_param(:'bw.synthetics_job_id', txn.synthetics_job_id)
135
+ last_sample.set_custom_param(:'bw.synthetics_monitor_id', txn.synthetics_monitor_id)
136
+
137
+ last_sample.synthetics_resource_id = txn.synthetics_resource_id
138
+ end
139
+
140
+ @samples_lock.synchronize do
141
+ @last_sample = last_sample
142
+ store_sample(@last_sample)
143
+ @last_sample
144
+ end
145
+ end
146
+
147
+ def store_sample(sample)
148
+ @sample_buffers.each do |sample_buffer|
149
+ sample_buffer.store(sample)
150
+ end
151
+ end
152
+
153
+ # Tells the builder to ignore a transaction, if we are currently
154
+ # creating one. Only causes the sample to be ignored upon end of
155
+ # the transaction, and does not change the metrics gathered
156
+ # outside of the sampler
157
+ def ignore_transaction(state)
158
+ builder = state.transaction_sample_builder
159
+ builder.ignore_transaction if builder
160
+ end
161
+
162
+ # Sets the CPU time used by a transaction, delegates to the builder
163
+ def notice_transaction_cpu_time(state, cpu_time)
164
+ builder = state.transaction_sample_builder
165
+ builder.set_transaction_cpu_time(cpu_time) if builder
166
+ end
167
+
168
+ MAX_DATA_LENGTH = 16384
169
+ # This method is used to record metadata into the currently
170
+ # active segment like a sql query, memcache key, or Net::HTTP uri
171
+ #
172
+ # duration is seconds, float value.
173
+ def notice_extra_data(builder, message, duration, key)
174
+ return unless builder
175
+ segment = builder.current_segment
176
+ if segment
177
+ if key != :sql
178
+ segment[key] = self.class.truncate_message(message)
179
+ else
180
+ # message is expected to have been pre-truncated by notice_sql
181
+ segment[key] = message
182
+ end
183
+ append_backtrace(segment, duration)
184
+ end
185
+ end
186
+
187
+ private :notice_extra_data
188
+
189
+ # Truncates the message to `MAX_DATA_LENGTH` if needed, and
190
+ # appends an ellipsis because it makes the trucation clearer in
191
+ # the UI
192
+ def self.truncate_message(message)
193
+ if message.length > (MAX_DATA_LENGTH - 4)
194
+ message[0..MAX_DATA_LENGTH - 4] + '...'
195
+ else
196
+ message
197
+ end
198
+ end
199
+
200
+ # Appends a backtrace to a segment if that segment took longer
201
+ # than the specified duration
202
+ def append_backtrace(segment, duration)
203
+ if duration >= Agent.config[:'transaction_tracer.stack_trace_threshold']
204
+ segment[:backtrace] = caller.join("\n")
205
+ end
206
+ end
207
+
208
+ # Attaches an SQL query on the current transaction trace segment.
209
+ #
210
+ # This method should be used only by gem authors wishing to extend
211
+ # the Ruby agent to instrument new database interfaces - it should
212
+ # generally not be called directly from application code.
213
+ #
214
+ # @param sql [String] the SQL query being recorded
215
+ # @param config [Object] the driver configuration for the connection
216
+ # @param duration [Float] number of seconds the query took to execute
217
+ # @param explainer [Proc] for internal use only - 3rd-party clients must
218
+ # not pass this parameter.
219
+ #
220
+ # @api public
221
+ #
222
+ def notice_sql(sql, config, duration, state=nil, &explainer) #THREAD_LOCAL_ACCESS sometimes
223
+ # some statements (particularly INSERTS with large BLOBS
224
+ # may be very large; we should trim them to a maximum usable length
225
+ state ||= OneApm::TransactionState.tl_get
226
+ builder = state.transaction_sample_builder
227
+ if state.is_sql_recorded?
228
+ statement = build_database_statement(sql, config, explainer)
229
+ notice_extra_data(builder, statement, duration, :sql)
230
+ end
231
+ end
232
+
233
+ def build_database_statement(sql, config, explainer)
234
+ statement = OneApm::Agent::Database::Statement.new(OneApm::Agent::Database.capture_query(sql))
235
+ if config
236
+ statement.adapter = config[:adapter]
237
+ statement.config = config
238
+ end
239
+ statement.explainer = explainer
240
+
241
+ statement
242
+ end
243
+
244
+ # Attaches an additional non-SQL query parameter to the current
245
+ # transaction trace segment.
246
+ #
247
+ # This may be used for recording a query against a key-value store like
248
+ # memcached or redis.
249
+ #
250
+ # This method should be used only by gem authors wishing to extend
251
+ # the Ruby agent to instrument uninstrumented key-value stores - it should
252
+ # generally not be called directly from application code.
253
+ #
254
+ # @param key [String] the name of the key that was queried
255
+ # @param duration [Float] number of seconds the query took to execute
256
+ #
257
+ # @api public
258
+ #
259
+ def notice_nosql(key, duration) #THREAD_LOCAL_ACCESS
260
+ builder = tl_builder
261
+ notice_extra_data(builder, key, duration, :key)
262
+ end
263
+
264
+ def notice_nosql_statement(statement, duration) #THREAD_LOCAL_ACCESS
265
+ builder = tl_builder
266
+ notice_extra_data(builder, statement, duration, :statement)
267
+ end
268
+
269
+ # Set parameters on the current segment.
270
+ def add_segment_parameters(params) #THREAD_LOCAL_ACCESS
271
+ builder = tl_builder
272
+ return unless builder
273
+ params.each { |k,v| builder.current_segment[k] = v }
274
+ end
275
+
276
+ # Gather transaction traces that we'd like to transmit to the server.
277
+ def harvest!
278
+ return [] unless enabled?
279
+
280
+ samples = @samples_lock.synchronize do
281
+ @last_sample = nil
282
+ harvest_from_sample_buffers
283
+ end
284
+ prepare_samples(samples)
285
+ end
286
+
287
+ def prepare_samples(samples)
288
+ samples.select do |sample|
289
+ begin
290
+ sample.prepare_to_send!
291
+ rescue => e
292
+ OneApm::Agent.logger.error("Failed to prepare transaction trace. Error: ", e)
293
+ false
294
+ else
295
+ true
296
+ end
297
+ end
298
+ end
299
+
300
+ def merge!(previous)
301
+ @samples_lock.synchronize do
302
+ @sample_buffers.each do |buffer|
303
+ buffer.store_previous(previous)
304
+ end
305
+ end
306
+ end
307
+
308
+ def count
309
+ @samples_lock.synchronize do
310
+ samples = @sample_buffers.inject([]) { |all, b| all.concat(b.samples) }
311
+ samples.uniq.size
312
+ end
313
+ end
314
+
315
+ def harvest_from_sample_buffers
316
+ # map + flatten hit mocking issues calling to_ary on 1.9.2. We only
317
+ # want a single level flatten anyway, but, as you probably already
318
+ # know, Ruby 1.8.6 :/
319
+ result = []
320
+ @sample_buffers.each { |buffer| result.concat(buffer.harvest_samples) }
321
+ result.uniq
322
+ end
323
+
324
+ # reset samples without rebooting the web server (used by dev mode)
325
+ def reset!
326
+ @samples_lock.synchronize do
327
+ @last_sample = nil
328
+ @sample_buffers.each { |sample_buffer| sample_buffer.reset! }
329
+ end
330
+ end
331
+
332
+ # Checks to see if the transaction sampler is disabled, if
333
+ # transaction trace recording is disabled by a thread local, or
334
+ # if execution is untraced - if so it clears the transaction
335
+ # sample builder from the thread local, otherwise it generates a
336
+ # new transaction sample builder with the stated time as a
337
+ # starting point and saves it in the thread local variable
338
+ def start_builder(state, time=nil)
339
+ if !enabled? || !state.is_transaction_traced? || !state.is_execution_traced?
340
+ state.transaction_sample_builder = nil
341
+ else
342
+ state.transaction_sample_builder ||= OneApm::TransactionSampleBuilder.new(time)
343
+ end
344
+ end
345
+
346
+ # The current thread-local transaction sample builder
347
+ def tl_builder
348
+ OneApm::TransactionState.tl_get.transaction_sample_builder
349
+ end
350
+ end
351
+ end
352
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Collector
5
+ class UtilizationData
6
+
7
+ REMOTE_DATA_VALID_CHARS = /^[0-9a-zA-Z_ .\/-]$/.freeze
8
+
9
+ def harvest!
10
+ [hostname, container_id, cpu_count, instance_type]
11
+ end
12
+
13
+ # No persistent data, so no need for merging or resetting
14
+ def merge!(*_); end
15
+ def reset!(*_); end
16
+
17
+ def hostname
18
+ OneApm::Agent::Hostname.get
19
+ end
20
+
21
+ def container_id
22
+ ::OneApm::Agent::SystemInfo.docker_container_id
23
+ end
24
+
25
+ def cpu_count
26
+ ::OneApm::Agent::SystemInfo.clear_processor_info
27
+ ::OneApm::Agent::SystemInfo.num_logical_processors
28
+ end
29
+
30
+ def instance_type
31
+ nil
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ module Collector
5
+ class StatsEngine
6
+ module GCProfiler
7
+ GCSnapshot = Struct.new(:gc_time_s, :gc_call_count)
8
+
9
+ def self.init
10
+ return @profiler if @initialized
11
+ @profiler = if RailsBenchProfiler.enabled?
12
+ RailsBenchProfiler.new
13
+ elsif CoreGCProfiler.enabled?
14
+ CoreGCProfiler.new
15
+ end
16
+ @initialized = true
17
+ @profiler
18
+ end
19
+
20
+ def self.reset
21
+ @profiler = nil
22
+ @initialized = nil
23
+ end
24
+
25
+ def self.take_snapshot
26
+ init
27
+ if @profiler
28
+ GCSnapshot.new(@profiler.call_time_s, @profiler.call_count)
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def self.record_delta(start_snapshot, end_snapshot)
35
+ if @profiler && start_snapshot && end_snapshot
36
+ elapsed_gc_time_s = end_snapshot.gc_time_s - start_snapshot.gc_time_s
37
+ num_calls = end_snapshot.gc_call_count - start_snapshot.gc_call_count
38
+ record_gc_metric(num_calls, elapsed_gc_time_s)
39
+
40
+ @profiler.reset
41
+ elapsed_gc_time_s
42
+ end
43
+ end
44
+
45
+ def self.record_gc_metric(call_count, elapsed) #THREAD_LOCAL_ACCESS
46
+ OneApm::Agent.instance.stats_engine.tl_record_scoped_and_unscoped_metrics(gc_metric_name, GC_ROLLUP) do |stats|
47
+ stats.call_count += call_count
48
+ stats.total_call_time += elapsed
49
+ stats.total_exclusive_time += elapsed
50
+ end
51
+ end
52
+
53
+ GC_ROLLUP = 'GC/Transaction/all'.freeze
54
+ GC_OTHER = 'GC/Transaction/allOther'.freeze
55
+ GC_WEB = 'GC/Transaction/allWeb'.freeze
56
+
57
+ def self.gc_metric_name
58
+ if OneApm::Transaction.recording_web_transaction?
59
+ GC_WEB
60
+ else
61
+ GC_OTHER
62
+ end
63
+ end
64
+
65
+ class RailsBenchProfiler
66
+ def self.enabled?
67
+ ::GC.respond_to?(:time) && ::GC.respond_to?(:collections)
68
+ end
69
+
70
+ def call_time_s
71
+ ::GC.time.to_f / 1_000_000 # this value is reported in us, so convert to s
72
+ end
73
+
74
+ def call_count
75
+ ::GC.collections
76
+ end
77
+
78
+ def reset
79
+ ::GC.clear_stats
80
+ end
81
+ end
82
+
83
+ class CoreGCProfiler
84
+ def self.enabled?
85
+ OneApm::LanguageSupport.gc_profiler_enabled?
86
+ end
87
+
88
+ def call_time_s
89
+ OneApm::Agent.instance.monotonic_gc_profiler.total_time_s
90
+ end
91
+
92
+ def call_count
93
+ ::GC.count
94
+ end
95
+
96
+ # When using GC::Profiler, it's important to periodically call
97
+ # GC::Profiler.clear in order to avoid unbounded growth in the number
98
+ # of GC recordds that are stored. However, we actually do this
99
+ # internally within MonotonicGCProfiler on calls to #total_time_s,
100
+ # so the reset here is a no-op.
101
+ def reset; end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end