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,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
|