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.
- checksums.yaml +7 -0
- data/.gitignore +30 -0
- data/.rubocop.yml +725 -0
- data/Gemfile +3 -0
- data/Guardfile +7 -0
- data/LICENSE +1 -0
- data/README.md +3 -0
- data/config/cert/cacert.pem +1177 -0
- data/config/database.yml +5 -0
- data/lib/initializers/goliath.rb +11 -0
- data/lib/initializers/other.rb +1 -0
- data/lib/initializers/rails.rb +15 -0
- data/lib/one_apm/agent.rb +253 -0
- data/lib/one_apm/agent/agent.rb +283 -0
- data/lib/one_apm/agent/agent/connect.rb +175 -0
- data/lib/one_apm/agent/agent/container_data_manager.rb +218 -0
- data/lib/one_apm/agent/agent/forkable_dispatcher_functions.rb +96 -0
- data/lib/one_apm/agent/agent/helpers.rb +45 -0
- data/lib/one_apm/agent/agent/start.rb +226 -0
- data/lib/one_apm/agent/agent/start_worker_thread.rb +148 -0
- data/lib/one_apm/agent/busy_calculator.rb +115 -0
- data/lib/one_apm/agent/cross_app/cross_app_monitor.rb +181 -0
- data/lib/one_apm/agent/cross_app/cross_app_tracing.rb +336 -0
- data/lib/one_apm/agent/database.rb +308 -0
- data/lib/one_apm/agent/database/active_record_helper.rb +80 -0
- data/lib/one_apm/agent/database/obfuscation_helpers.rb +76 -0
- data/lib/one_apm/agent/database/obfuscator.rb +78 -0
- data/lib/one_apm/agent/database/postgres_explain_obfuscator.rb +45 -0
- data/lib/one_apm/agent/datastores.rb +175 -0
- data/lib/one_apm/agent/datastores/metric_helper.rb +83 -0
- data/lib/one_apm/agent/datastores/mongo.rb +27 -0
- data/lib/one_apm/agent/datastores/mongo/metric_translator.rb +189 -0
- data/lib/one_apm/agent/datastores/mongo/obfuscator.rb +37 -0
- data/lib/one_apm/agent/datastores/mongo/statement_formatter.rb +51 -0
- data/lib/one_apm/agent/event/event_listener.rb +40 -0
- data/lib/one_apm/agent/event/event_loop.rb +191 -0
- data/lib/one_apm/agent/event/worker_loop.rb +97 -0
- data/lib/one_apm/agent/harvester.rb +48 -0
- data/lib/one_apm/agent/inbound_request_monitor.rb +30 -0
- data/lib/one_apm/agent/javascript_instrumentor.rb +186 -0
- data/lib/one_apm/agent/pipe/pipe_channel_manager.rb +275 -0
- data/lib/one_apm/agent/pipe/pipe_service.rb +81 -0
- data/lib/one_apm/agent/sampler.rb +55 -0
- data/lib/one_apm/agent/sampler_collection.rb +65 -0
- data/lib/one_apm/agent/samplers/cpu_sampler.rb +49 -0
- data/lib/one_apm/agent/samplers/delayed_job_sampler.rb +109 -0
- data/lib/one_apm/agent/samplers/memory_sampler.rb +144 -0
- data/lib/one_apm/agent/samplers/object_sampler.rb +22 -0
- data/lib/one_apm/agent/samplers/vm_sampler.rb +124 -0
- data/lib/one_apm/agent/synthetics_monitor.rb +48 -0
- data/lib/one_apm/agent/threading/agent_thread.rb +74 -0
- data/lib/one_apm/agent/threading/backtrace_node.rb +133 -0
- data/lib/one_apm/agent/threading/backtrace_service.rb +259 -0
- data/lib/one_apm/agent/threading/thread_profile.rb +155 -0
- data/lib/one_apm/collector/collector/helper.rb +139 -0
- data/lib/one_apm/collector/collector/http_connection.rb +254 -0
- data/lib/one_apm/collector/collector/server_methods.rb +71 -0
- data/lib/one_apm/collector/collector_service.rb +123 -0
- data/lib/one_apm/collector/commands/agent_command.rb +17 -0
- data/lib/one_apm/collector/commands/thread_profiler_session.rb +108 -0
- data/lib/one_apm/collector/commands/xray_session.rb +53 -0
- data/lib/one_apm/collector/commands/xray_session_collection.rb +156 -0
- data/lib/one_apm/collector/containers/agent_command_router.rb +153 -0
- data/lib/one_apm/collector/containers/custom_event_aggregator.rb +94 -0
- data/lib/one_apm/collector/containers/error_collector.rb +349 -0
- data/lib/one_apm/collector/containers/sql_sampler.rb +331 -0
- data/lib/one_apm/collector/containers/stats_engine.rb +34 -0
- data/lib/one_apm/collector/containers/transaction_event_aggregator.rb +249 -0
- data/lib/one_apm/collector/containers/transaction_sampler.rb +352 -0
- data/lib/one_apm/collector/containers/utilization_data.rb +36 -0
- data/lib/one_apm/collector/stats_engine/gc_profiler.rb +106 -0
- data/lib/one_apm/collector/stats_engine/metric_stats.rb +243 -0
- data/lib/one_apm/collector/stats_engine/stats_hash.rb +105 -0
- data/lib/one_apm/configuration.rb +429 -0
- data/lib/one_apm/configuration/autostart.rb +41 -0
- data/lib/one_apm/configuration/default_source.rb +1026 -0
- data/lib/one_apm/configuration/environment_source.rb +113 -0
- data/lib/one_apm/configuration/high_security_source.rb +56 -0
- data/lib/one_apm/configuration/manual_source.rb +13 -0
- data/lib/one_apm/configuration/server_source.rb +60 -0
- data/lib/one_apm/configuration/yaml_source.rb +134 -0
- data/lib/one_apm/errors/agent_errors.rb +26 -0
- data/lib/one_apm/errors/internal_agent_error.rb +16 -0
- data/lib/one_apm/errors/noticed_error.rb +79 -0
- data/lib/one_apm/frameworks/external.rb +15 -0
- data/lib/one_apm/frameworks/rails.rb +103 -0
- data/lib/one_apm/frameworks/rails3.rb +37 -0
- data/lib/one_apm/frameworks/rails4.rb +21 -0
- data/lib/one_apm/frameworks/ruby.rb +21 -0
- data/lib/one_apm/frameworks/sinatra.rb +12 -0
- data/lib/one_apm/inst/3rd/active_merchant.rb +35 -0
- data/lib/one_apm/inst/3rd/acts_as_solr.rb +70 -0
- data/lib/one_apm/inst/3rd/authlogic.rb +23 -0
- data/lib/one_apm/inst/3rd/sunspot.rb +31 -0
- data/lib/one_apm/inst/background_job/active_job.rb +88 -0
- data/lib/one_apm/inst/background_job/delayed_job.rb +52 -0
- data/lib/one_apm/inst/background_job/delayed_job_injection.rb +8 -0
- data/lib/one_apm/inst/background_job/resque.rb +107 -0
- data/lib/one_apm/inst/background_job/sidekiq.rb +64 -0
- data/lib/one_apm/inst/dispatcher/passenger.rb +25 -0
- data/lib/one_apm/inst/dispatcher/rainbows.rb +23 -0
- data/lib/one_apm/inst/framework/grape.rb +94 -0
- data/lib/one_apm/inst/framework/padrino.rb +30 -0
- data/lib/one_apm/inst/framework/sinatra.rb +185 -0
- data/lib/one_apm/inst/framework/sinatra/ignorer.rb +50 -0
- data/lib/one_apm/inst/framework/sinatra/transaction_namer.rb +54 -0
- data/lib/one_apm/inst/http_clients/curb.rb +189 -0
- data/lib/one_apm/inst/http_clients/excon.rb +70 -0
- data/lib/one_apm/inst/http_clients/excon/connection.rb +31 -0
- data/lib/one_apm/inst/http_clients/excon/middleware.rb +55 -0
- data/lib/one_apm/inst/http_clients/httpclient.rb +44 -0
- data/lib/one_apm/inst/http_clients/net.rb +34 -0
- data/lib/one_apm/inst/http_clients/typhoeus.rb +76 -0
- data/lib/one_apm/inst/nosql/memcache.rb +134 -0
- data/lib/one_apm/inst/nosql/mongo.rb +126 -0
- data/lib/one_apm/inst/nosql/mongo_moped.rb +85 -0
- data/lib/one_apm/inst/nosql/redis.rb +83 -0
- data/lib/one_apm/inst/orm/active_record.rb +99 -0
- data/lib/one_apm/inst/orm/active_record_4.rb +28 -0
- data/lib/one_apm/inst/orm/data_mapper.rb +180 -0
- data/lib/one_apm/inst/orm/sequel.rb +47 -0
- data/lib/one_apm/inst/rack.rb +38 -0
- data/lib/one_apm/inst/rack/rack.rb +44 -0
- data/lib/one_apm/inst/rack/rack_builder.rb +51 -0
- data/lib/one_apm/inst/rails/action_controller.rb +118 -0
- data/lib/one_apm/inst/rails/action_web_service.rb +44 -0
- data/lib/one_apm/inst/rails/errors.rb +43 -0
- data/lib/one_apm/inst/rails3/action_controller.rb +172 -0
- data/lib/one_apm/inst/rails3/errors.rb +43 -0
- data/lib/one_apm/inst/rails4/action_controller.rb +27 -0
- data/lib/one_apm/inst/rails4/action_controller_subscriber.rb +121 -0
- data/lib/one_apm/inst/rails4/action_view.rb +23 -0
- data/lib/one_apm/inst/rails4/action_view_subscriber.rb +93 -0
- data/lib/one_apm/inst/rails4/active_record_subscriber.rb +96 -0
- data/lib/one_apm/inst/rails4/errors.rb +42 -0
- data/lib/one_apm/inst/rails_middleware.rb +40 -0
- data/lib/one_apm/inst/support/evented_subscriber.rb +98 -0
- data/lib/one_apm/inst/support/ignore_actions.rb +39 -0
- data/lib/one_apm/inst/support/queue_time.rb +76 -0
- data/lib/one_apm/inst/transaction_base.rb +405 -0
- data/lib/one_apm/logger/agent_logger.rb +206 -0
- data/lib/one_apm/logger/audit_logger.rb +78 -0
- data/lib/one_apm/logger/memory_logger.rb +50 -0
- data/lib/one_apm/logger/null_logger.rb +19 -0
- data/lib/one_apm/metrics/metric_data.rb +72 -0
- data/lib/one_apm/metrics/metric_spec.rb +82 -0
- data/lib/one_apm/metrics/stats.rb +173 -0
- data/lib/one_apm/probe.rb +16 -0
- data/lib/one_apm/probe/framework_loader.rb +53 -0
- data/lib/one_apm/probe/instance_methods.rb +105 -0
- data/lib/one_apm/probe/instrumentation.rb +60 -0
- data/lib/one_apm/rack/browser_monitoring.rb +144 -0
- data/lib/one_apm/rack/middleware_base.rb +27 -0
- data/lib/one_apm/rack/middleware_hooks.rb +17 -0
- data/lib/one_apm/rack/middleware_tracing.rb +81 -0
- data/lib/one_apm/rack/middleware_wrapper.rb +86 -0
- data/lib/one_apm/support/chained_call.rb +15 -0
- data/lib/one_apm/support/coerce.rb +81 -0
- data/lib/one_apm/support/collection_helper.rb +79 -0
- data/lib/one_apm/support/dotted_hash.rb +45 -0
- data/lib/one_apm/support/encoders.rb +34 -0
- data/lib/one_apm/support/environment_report.rb +127 -0
- data/lib/one_apm/support/event_buffer.rb +82 -0
- data/lib/one_apm/support/event_buffer/sampled_buffer.rb +45 -0
- data/lib/one_apm/support/event_buffer/sized_buffer.rb +21 -0
- data/lib/one_apm/support/event_buffer/synthetics_event_buffer.rb +40 -0
- data/lib/one_apm/support/helper.rb +49 -0
- data/lib/one_apm/support/hostname.rb +13 -0
- data/lib/one_apm/support/http_clients/curb_wrappers.rb +65 -0
- data/lib/one_apm/support/http_clients/excon_wrappers.rb +63 -0
- data/lib/one_apm/support/http_clients/httpclient_wrappers.rb +61 -0
- data/lib/one_apm/support/http_clients/net_http_wrappers.rb +48 -0
- data/lib/one_apm/support/http_clients/typhoeus_wrappers.rb +73 -0
- data/lib/one_apm/support/http_clients/uri_util.rb +39 -0
- data/lib/one_apm/support/json_marshaller.rb +68 -0
- data/lib/one_apm/support/json_wrapper.rb +130 -0
- data/lib/one_apm/support/language_support.rb +142 -0
- data/lib/one_apm/support/library_detection.rb +119 -0
- data/lib/one_apm/support/local_environment.rb +196 -0
- data/lib/one_apm/support/marshaller.rb +62 -0
- data/lib/one_apm/support/method_tracer.rb +334 -0
- data/lib/one_apm/support/method_tracer/helpers.rb +92 -0
- data/lib/one_apm/support/method_tracer/traced_method_stack.rb +103 -0
- data/lib/one_apm/support/obfuscator.rb +47 -0
- data/lib/one_apm/support/okjson.rb +601 -0
- data/lib/one_apm/support/parameter_filtering.rb +35 -0
- data/lib/one_apm/support/rules_engine.rb +56 -0
- data/lib/one_apm/support/rules_engine/replacement_rule.rb +80 -0
- data/lib/one_apm/support/rules_engine/segment_terms_rule.rb +46 -0
- data/lib/one_apm/support/server.rb +11 -0
- data/lib/one_apm/support/supported_versions.rb +257 -0
- data/lib/one_apm/support/system_info.rb +211 -0
- data/lib/one_apm/support/timer_lib.rb +29 -0
- data/lib/one_apm/support/version_number.rb +51 -0
- data/lib/one_apm/support/vm.rb +30 -0
- data/lib/one_apm/support/vm/jruby_vm.rb +38 -0
- data/lib/one_apm/support/vm/monotonic_gc_profiler.rb +43 -0
- data/lib/one_apm/support/vm/mri_vm.rb +85 -0
- data/lib/one_apm/support/vm/rubinius_vm.rb +129 -0
- data/lib/one_apm/support/vm/snapshot.rb +18 -0
- data/lib/one_apm/transaction.rb +336 -0
- data/lib/one_apm/transaction/class_methods.rb +132 -0
- data/lib/one_apm/transaction/instance_helpers.rb +82 -0
- data/lib/one_apm/transaction/metric_constants.rb +42 -0
- data/lib/one_apm/transaction/sample_buffer/force_persist_sample_buffer.rb +21 -0
- data/lib/one_apm/transaction/sample_buffer/slowest_sample_buffer.rb +21 -0
- data/lib/one_apm/transaction/sample_buffer/synthetics_sample_buffer.rb +21 -0
- data/lib/one_apm/transaction/sample_buffer/transaction_sample_buffer.rb +101 -0
- data/lib/one_apm/transaction/sample_buffer/xray_sample_buffer.rb +60 -0
- data/lib/one_apm/transaction/segment.rb +193 -0
- data/lib/one_apm/transaction/segment_summary.rb +51 -0
- data/lib/one_apm/transaction/thread_local_access.rb +73 -0
- data/lib/one_apm/transaction/transaction_analysis.rb +78 -0
- data/lib/one_apm/transaction/transaction_apdex.rb +20 -0
- data/lib/one_apm/transaction/transaction_cpu.rb +22 -0
- data/lib/one_apm/transaction/transaction_finish_append.rb +67 -0
- data/lib/one_apm/transaction/transaction_ignore.rb +33 -0
- data/lib/one_apm/transaction/transaction_jruby_functions.rb +40 -0
- data/lib/one_apm/transaction/transaction_metrics.rb +53 -0
- data/lib/one_apm/transaction/transaction_name.rb +90 -0
- data/lib/one_apm/transaction/transaction_namer.rb +49 -0
- data/lib/one_apm/transaction/transaction_sample.rb +204 -0
- data/lib/one_apm/transaction/transaction_sample_builder.rb +168 -0
- data/lib/one_apm/transaction/transaction_state.rb +149 -0
- data/lib/one_apm/transaction/transaction_summary.rb +28 -0
- data/lib/one_apm/transaction/transaction_synthetics.rb +40 -0
- data/lib/one_apm/transaction/transaction_timings.rb +54 -0
- data/lib/one_apm/version.rb +13 -0
- data/lib/oneapm_rpm.rb +16 -0
- data/lib/sequel/extensions/oneapm_instrumentation.rb +84 -0
- data/lib/sequel/plugins/oneapm_instrumentation.rb +66 -0
- data/oneapm.yml +135 -0
- data/oneapm_rpm.gemspec +58 -0
- 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
|