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,173 @@
1
+ # encoding: utf-8
2
+ module OneApm
3
+ module Metrics
4
+ class Stats
5
+
6
+ attr_accessor :call_count
7
+ attr_accessor :min_call_time
8
+ attr_accessor :max_call_time
9
+ attr_accessor :total_call_time
10
+ attr_accessor :total_exclusive_time
11
+ attr_accessor :sum_of_squares
12
+
13
+ def self.create_from_hash hash_value
14
+ stats = Stats.new
15
+ stats.call_count = hash_value[:count] if hash_value[:count]
16
+ stats.total_call_time = hash_value[:total] if hash_value[:total]
17
+ stats.total_exclusive_time = hash_value[:total] if hash_value[:total]
18
+ stats.min_call_time = hash_value[:min] if hash_value[:min]
19
+ stats.max_call_time = hash_value[:max] if hash_value[:max]
20
+ stats.sum_of_squares = hash_value[:sum_of_squares] if hash_value[:sum_of_squares]
21
+ stats
22
+ end
23
+
24
+ def initialize
25
+ reset
26
+ end
27
+
28
+ def reset
29
+ @call_count = 0
30
+ @total_call_time = 0.0
31
+ @total_exclusive_time = 0.0
32
+ @min_call_time = 0.0
33
+ @max_call_time = 0.0
34
+ @sum_of_squares = 0.0
35
+ end
36
+
37
+ def is_reset?
38
+ call_count == 0 && total_call_time == 0.0 && total_exclusive_time == 0.0
39
+ end
40
+
41
+ def merge(other_stats)
42
+ stats = self.clone
43
+ stats.merge!(other_stats)
44
+ end
45
+
46
+ def merge!(other)
47
+ @min_call_time = other.min_call_time if min_time_less?(other)
48
+ @max_call_time = other.max_call_time if other.max_call_time > max_call_time
49
+ @total_call_time += other.total_call_time
50
+ @total_exclusive_time += other.total_exclusive_time
51
+ @sum_of_squares += other.sum_of_squares
52
+ @call_count += other.call_count
53
+ self
54
+ end
55
+
56
+ def to_s
57
+ "[#{'%2i' % call_count.to_i} calls #{'%.4f' % total_call_time.to_f}s / #{'%.4f' % total_exclusive_time.to_f}s ex]"
58
+ end
59
+
60
+ def to_json(*_)
61
+ {
62
+ 'call_count' => call_count.to_i,
63
+ 'min_call_time' => min_call_time.to_f,
64
+ 'max_call_time' => max_call_time.to_f,
65
+ 'total_call_time' => total_call_time.to_f,
66
+ 'total_exclusive_time' => total_exclusive_time.to_f,
67
+ 'sum_of_squares' => sum_of_squares.to_f
68
+ }.to_json(*_)
69
+ end
70
+
71
+ def record(value=nil, aux=nil, &blk)
72
+ if blk
73
+ yield self
74
+ else
75
+ case value
76
+ when Numeric
77
+ aux ||= value
78
+ self.record_data_point(value, aux)
79
+ when :apdex_s, :apdex_t, :apdex_f
80
+ self.record_apdex(value, aux)
81
+ when OneApm::Metrics::Stats
82
+ self.merge!(value)
83
+ end
84
+ end
85
+ end
86
+
87
+ # record a single data point into the statistical gatherer. The gatherer
88
+ # will aggregate all data points collected over a specified period and upload
89
+ # its data to the OneApm server
90
+ def record_data_point(value, exclusive_time = value)
91
+ @call_count += 1
92
+ @min_call_time = value if value < @min_call_time || @call_count == 1
93
+ @max_call_time = value if value > @max_call_time
94
+ @total_call_time += value
95
+ @total_exclusive_time += exclusive_time
96
+
97
+ @sum_of_squares += (value * value)
98
+ self
99
+ end
100
+
101
+ alias trace_call record_data_point
102
+
103
+ # increments the call_count by one
104
+ def increment_count(value = 1)
105
+ @call_count += value
106
+ end
107
+
108
+ def inspect
109
+ "#<OneApm::Metrics::Stats #{to_s} >"
110
+ end
111
+
112
+ # Concerned about implicit usage of inspect relying on stats format, so
113
+ # putting back a version to get full inspection as separate method
114
+ def inspect_full
115
+ variables = instance_variables.map do |ivar|
116
+ "#{ivar.to_s}=#{instance_variable_get(ivar).inspect}"
117
+ end.join(" ")
118
+ "#<OneApm::Metrics::Stats #{variables}>"
119
+ end
120
+
121
+ def ==(other)
122
+ other.class == self.class &&
123
+ (
124
+ @min_call_time == other.min_call_time &&
125
+ @max_call_time == other.max_call_time &&
126
+ @total_call_time == other.total_call_time &&
127
+ @total_exclusive_time == other.total_exclusive_time &&
128
+ @sum_of_squares == other.sum_of_squares &&
129
+ @call_count == other.call_count
130
+ )
131
+ end
132
+
133
+ # Apdex-related accessors
134
+ alias_method :apdex_s, :call_count
135
+ alias_method :apdex_t, :total_call_time
136
+ alias_method :apdex_f, :total_exclusive_time
137
+
138
+ def record_apdex(bucket, apdex_t)
139
+ case bucket
140
+ when :apdex_s then @call_count += 1
141
+ when :apdex_t then @total_call_time += 1
142
+ when :apdex_f then @total_exclusive_time += 1
143
+ end
144
+ if apdex_t
145
+ @min_call_time = apdex_t
146
+ @max_call_time = apdex_t
147
+ else
148
+ ::OneApm::Agent.logger.warn("Attempted to set apdex_t to #{apdex_t.inspect}, backtrace = #{caller.join("\n")}")
149
+ end
150
+ end
151
+
152
+ protected
153
+
154
+ def min_time_less?(other)
155
+ (other.min_call_time < min_call_time && other.call_count > 0) || call_count == 0
156
+ end
157
+ end
158
+
159
+ class ChainedStats
160
+ attr_accessor :scoped_stats, :unscoped_stats
161
+
162
+ def initialize(scoped_stats, unscoped_stats)
163
+ @scoped_stats = scoped_stats
164
+ @unscoped_stats = unscoped_stats
165
+ end
166
+
167
+ def method_missing(method, *args)
168
+ unscoped_stats.send(method, *args)
169
+ scoped_stats.send(method, *args)
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/support/local_environment'
4
+ require 'one_apm/support/language_support'
5
+ require 'one_apm/support/helper'
6
+ require 'one_apm/support/version_number'
7
+
8
+ require 'one_apm/probe/framework_loader'
9
+ require 'one_apm/probe/instrumentation'
10
+ require 'one_apm/probe/instance_methods'
11
+
12
+ require 'one_apm/agent'
13
+
14
+ module OneApm
15
+ class Probe; end
16
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ module OneApm
4
+ class Probe
5
+ module FrameworkLoader
6
+
7
+ def init(options = {})
8
+ instance.init_plugin options
9
+ end
10
+
11
+ def instance
12
+ @instance ||= new_instance
13
+ end
14
+
15
+ def new_instance
16
+ if Agent.config[:framework] == :test
17
+ load_test_framework
18
+ else
19
+ load_framework_class(Agent.config[:framework]).new(local_env)
20
+ end
21
+ end
22
+
23
+ def reset
24
+ @instance = nil
25
+ @local_env = nil
26
+ end
27
+
28
+ def local_env
29
+ @local_env ||= OneApm::LocalEnvironment.new
30
+ end
31
+
32
+ def load_test_framework
33
+ config = File.expand_path(File.join('..', '..', '..', '..', 'test', 'config', 'oneapm.yml'), __FILE__)
34
+ require 'config/test_control'
35
+ OneApm::Probe::Frameworks::Test.new(local_env, config)
36
+ end
37
+
38
+ def load_framework_class(framework)
39
+ begin
40
+ require "one_apm/frameworks/#{framework}"
41
+ rescue LoadError
42
+ end
43
+ OneApm::Probe::Frameworks.const_get(framework.to_s.capitalize)
44
+ end
45
+
46
+ def oneapm_root
47
+ File.expand_path(File.join('..', '..', '..', '..'), __FILE__)
48
+ end
49
+ end
50
+
51
+ extend FrameworkLoader
52
+ end
53
+ end
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/logger/null_logger'
4
+ require 'one_apm/logger/memory_logger'
5
+ require 'one_apm/logger/agent_logger'
6
+
7
+ module OneApm
8
+ class Probe
9
+ module InstanceMethods
10
+
11
+ attr_writer :env
12
+ attr_reader :local_env
13
+
14
+ def init_plugin(options = {})
15
+ env = options[:env] || self.env
16
+
17
+ Agent.logger.info("Starting the OneApm agent in #{env.inspect} environment.")
18
+
19
+ configure_agent(env, options)
20
+
21
+ # Be sure to only create once! RUBY-1020
22
+ if ::OneApm::Agent.logger.is_startup_logger?
23
+ ::OneApm::Agent.logger = OneApm::Agent::AgentLogger.new(root, options.delete(:log))
24
+ end
25
+
26
+ # Merge the stringified options into the config as overrides:
27
+ environment_name = options.delete(:env) and self.env = environment_name
28
+
29
+ OneApm::Agent::PipeChannelManager.listener.start if options.delete(:start_channel_listener)
30
+
31
+ # An artifact of earlier implementation, we put both #add_method_tracer and #trace_execution
32
+ # methods in the module methods.
33
+ Module.send :include, OneApm::Support::MethodTracer::ClassMethods
34
+ Module.send :include, OneApm::Support::MethodTracer
35
+
36
+ init_config(options)
37
+
38
+ # initialize agent
39
+ OneApm::Agent.instance = OneApm::Agent::Agent.instance
40
+ OneApm::Agent.instance.start_service_if_needed
41
+
42
+ if Agent.config[:agent_enabled] && !OneApm::Agent.instance.started?
43
+ start_agent
44
+ install_instrumentation
45
+ elsif !Agent.config[:agent_enabled]
46
+ install_shim
47
+ else
48
+ detect_dependencies
49
+ end
50
+ end
51
+
52
+ def configure_agent(env, options)
53
+ manual = OneApm::Configuration::ManualSource.new(options)
54
+ Agent.config.replace_or_add_config(manual)
55
+
56
+ config_file_path = @config_file_override || Agent.config[:config_path]
57
+ Agent.config.replace_or_add_config(OneApm::Configuration::YamlSource.new(config_file_path, env))
58
+
59
+ if Agent.config[:high_security]
60
+ Agent.logger.info("Installing high security configuration based on local configuration")
61
+ Agent.config.replace_or_add_config(OneApm::Configuration::HighSecuritySource.new(Agent.config))
62
+ end
63
+ end
64
+
65
+ # Install the real agent into the Agent module, and issue the start command.
66
+ def start_agent
67
+ OneApm::Agent.instance.start
68
+ end
69
+
70
+ def app
71
+ Agent.config[:framework]
72
+ end
73
+
74
+ def framework
75
+ Agent.config[:framework]
76
+ end
77
+
78
+ def settings
79
+ OneApm::Agent.config.to_collector_hash
80
+ end
81
+
82
+ def dispatcher
83
+ OneApm::Agent.config[:dispatcher]
84
+ end
85
+
86
+ def oneapm_root
87
+ OneApm::Probe.oneapm_root
88
+ end
89
+
90
+ protected
91
+
92
+ def initialize(local_env, config_file_override = nil)
93
+ @local_env = local_env
94
+ @instrumentation_files = []
95
+ @config_file_override = config_file_override
96
+ end
97
+
98
+ def root
99
+ '.'
100
+ end
101
+
102
+ end
103
+ include InstanceMethods
104
+ end
105
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ require 'one_apm/support/library_detection'
4
+
5
+ module OneApm
6
+ class Probe
7
+ module Instrumentation
8
+
9
+ # install instrumentations for the current framework
10
+ def install_instrumentation
11
+ return if @instrumented
12
+
13
+ @instrumented = true
14
+
15
+ # Instrumentation for the key code points inside rails for monitoring by OneApm.
16
+ # note this file is loaded only if the oneapm agent is enabled (through config/oneapm.yml)
17
+ instrumentation_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'inst'))
18
+ Dir.glob("#{instrumentation_path}/**/*.rb").each do |inst_file|
19
+ load_instrumentation_files inst_file
20
+ end
21
+ detect_dependencies
22
+ OneApm::Agent.logger.info "Finished instrumentation"
23
+ end
24
+
25
+ def load_instrumentation_files pattern
26
+ Dir.glob(pattern) { |file| require_instrumentation(file.to_s) }
27
+ end
28
+
29
+ def detect_dependencies
30
+ LibraryDetection.detect!
31
+ end
32
+
33
+ # require specified instrumentation
34
+ def require_instrumentation file
35
+ require file
36
+ rescue => e
37
+ ::OneApm::Agent.logger.warn "Error loading instrumentation file '#{file}':", e
38
+ end
39
+
40
+ def install_shim
41
+ # Once we install instrumentation, you can't undo that by installing the shim.
42
+ if @instrumented
43
+ OneApm::Agent.logger.error "Cannot install the Agent shim after instrumentation has already been installed!"
44
+ OneApm::Agent.logger.error caller.join("\n")
45
+ else
46
+ OneApm::Agent.instance = OneApm::Agent::ShimAgent.instance
47
+ end
48
+ end
49
+
50
+ def add_instrumentation pattern
51
+ if @instrumented
52
+ load_instrumentation_files pattern
53
+ else
54
+ @instrumentation_files << pattern
55
+ end
56
+ end
57
+ end
58
+ include Instrumentation
59
+ end
60
+ end
@@ -0,0 +1,144 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rack'
4
+ require 'one_apm/rack/middleware_base'
5
+ require 'one_apm/rack/middleware_wrapper'
6
+
7
+ module OneApm::Rack
8
+ class BrowserMonitoring < MiddlewareBase
9
+
10
+ SCAN_LIMIT = 50_000
11
+ ALREADY_INSTRUMENTED_KEY = "oneapm.browser_monitoring_already_instrumented"
12
+
13
+ CHARSET_RE = /<\s*meta[^>]+charset\s*=[^>]*>/im.freeze
14
+ X_UA_COMPATIBLE_RE = /<\s*meta[^>]+http-equiv\s*=\s*['"]x-ua-compatible['"][^>]*>/im.freeze
15
+
16
+ def traced_call(env)
17
+ result = @app.call(env) # [status, headers, response]
18
+
19
+ js_to_inject = OneApm::Agent.browser_timing_header
20
+ if (js_to_inject != "") && should_instrument?(env, result[0], result[1])
21
+ response_string = autoinstrument_source(result[2], result[1], js_to_inject)
22
+
23
+ env[ALREADY_INSTRUMENTED_KEY] = true
24
+ if response_string
25
+ response = Rack::Response.new(response_string, result[0], result[1])
26
+ response.finish
27
+ else
28
+ result
29
+ end
30
+ else
31
+ result
32
+ end
33
+ end
34
+
35
+ def should_instrument?(env, status, headers)
36
+ OneApm::Agent.config[:'browser_monitoring.auto_instrument'] &&
37
+ status == 200 &&
38
+ !env[ALREADY_INSTRUMENTED_KEY] &&
39
+ is_html?(headers) &&
40
+ !is_attachment?(headers) &&
41
+ !is_streaming?(env)
42
+ end
43
+
44
+ def is_html?(headers)
45
+ headers["Content-Type"] && headers["Content-Type"].include?("text/html")
46
+ end
47
+
48
+ def is_attachment?(headers)
49
+ headers['Content-Disposition'].to_s.include?('attachment')
50
+ end
51
+
52
+ def is_streaming?(env)
53
+ return false unless defined?(ActionController::Live)
54
+
55
+ env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
56
+ end
57
+
58
+ def autoinstrument_source(response, headers, js_to_inject)
59
+ source = gather_source(response)
60
+ close_old_response(response)
61
+ return nil unless source
62
+
63
+ # Only scan the first 50k (roughly) then give up.
64
+ beginning_of_source = source[0..SCAN_LIMIT]
65
+
66
+ if body_start = find_body_start(beginning_of_source)
67
+ meta_tag_positions = [
68
+ find_x_ua_compatible_position(beginning_of_source),
69
+ find_charset_position(beginning_of_source)
70
+ ].compact
71
+
72
+ if !meta_tag_positions.empty?
73
+ insertion_index = meta_tag_positions.max
74
+ else
75
+ insertion_index = find_end_of_head_open(beginning_of_source) || body_start
76
+ end
77
+
78
+ if insertion_index
79
+ source = source[0...insertion_index] <<
80
+ js_to_inject <<
81
+ source[insertion_index..-1]
82
+ else
83
+ OneApm::Agent.logger.debug "Skipping RUM instrumentation. Could not properly determine location to inject script."
84
+ end
85
+ else
86
+ msg = "Skipping RUM instrumentation. Unable to find <body> tag in first #{SCAN_LIMIT} bytes of document."
87
+ OneApm::Agent.logger.log_once(:warn, :rum_insertion_failure, msg)
88
+ OneApm::Agent.logger.debug(msg)
89
+ end
90
+
91
+ if headers['Content-Length']
92
+ headers['Content-Length'] = calculate_content_length(source).to_s
93
+ end
94
+
95
+ source
96
+ rescue => e
97
+ OneApm::Agent.logger.debug "Skipping RUM instrumentation on exception.", e
98
+ nil
99
+ end
100
+
101
+ def gather_source(response)
102
+ source = nil
103
+ response.each {|fragment| source ? (source << fragment.to_s) : (source = fragment.to_s)}
104
+ source
105
+ end
106
+
107
+ # Per "The Response > The Body" section of Rack spec, we should close
108
+ # if our response is able. http://rack.rubyforge.org/doc/SPEC.html
109
+ def close_old_response(response)
110
+ if response.respond_to?(:close)
111
+ response.close
112
+ end
113
+ end
114
+
115
+ def find_body_start(beginning_of_source)
116
+ beginning_of_source.index("<body")
117
+ end
118
+
119
+ def find_x_ua_compatible_position(beginning_of_source)
120
+ match = X_UA_COMPATIBLE_RE.match(beginning_of_source)
121
+ match.end(0) if match
122
+ end
123
+
124
+ def find_charset_position(beginning_of_source)
125
+ match = CHARSET_RE.match(beginning_of_source)
126
+ match.end(0) if match
127
+ end
128
+
129
+ def find_end_of_head_open(beginning_of_source)
130
+ head_open = beginning_of_source.index("<head")
131
+ beginning_of_source.index(">", head_open) + 1 if head_open
132
+ end
133
+
134
+ # String does not respond to 'bytesize' in 1.8.6. Fortunately String#length
135
+ # returns bytes rather than characters in 1.8.6 so we can use that instead.
136
+ def calculate_content_length(source)
137
+ if source.respond_to?(:bytesize)
138
+ source.bytesize
139
+ else
140
+ source.length
141
+ end
142
+ end
143
+ end
144
+ end