appoptics_apm_mnfst 4.5.2
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/.dockerignore +5 -0
- data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
- data/.gitignore +29 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +121 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Gemfile +29 -0
- data/LICENSE +193 -0
- data/README.md +393 -0
- data/Rakefile +230 -0
- data/appoptics_apm.gemspec +61 -0
- data/bin/appoptics_apm_config +15 -0
- data/build_gem.sh +15 -0
- data/build_gem_upload_to_packagecloud.sh +20 -0
- data/examples/SDK/01_basic_tracing.rb +67 -0
- data/examples/carrying_context.rb +220 -0
- data/ext/oboe_metal/extconf.rb +114 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/VERSION +1 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm.rb +76 -0
- data/lib/appoptics_apm/api.rb +20 -0
- data/lib/appoptics_apm/api/layerinit.rb +41 -0
- data/lib/appoptics_apm/api/logging.rb +375 -0
- data/lib/appoptics_apm/api/memcache.rb +37 -0
- data/lib/appoptics_apm/api/metrics.rb +55 -0
- data/lib/appoptics_apm/api/profiling.rb +203 -0
- data/lib/appoptics_apm/api/tracing.rb +53 -0
- data/lib/appoptics_apm/api/util.rb +122 -0
- data/lib/appoptics_apm/base.rb +230 -0
- data/lib/appoptics_apm/config.rb +254 -0
- data/lib/appoptics_apm/frameworks/grape.rb +97 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
- data/lib/appoptics_apm/frameworks/rails.rb +94 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +108 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +125 -0
- data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
- data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
- data/lib/appoptics_apm/inst/curb.rb +330 -0
- data/lib/appoptics_apm/inst/dalli.rb +85 -0
- data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
- data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
- data/lib/appoptics_apm/inst/excon.rb +125 -0
- data/lib/appoptics_apm/inst/faraday.rb +94 -0
- data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
- data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
- data/lib/appoptics_apm/inst/http.rb +73 -0
- data/lib/appoptics_apm/inst/httpclient.rb +174 -0
- data/lib/appoptics_apm/inst/memcached.rb +86 -0
- data/lib/appoptics_apm/inst/mongo.rb +246 -0
- data/lib/appoptics_apm/inst/mongo2.rb +225 -0
- data/lib/appoptics_apm/inst/moped.rb +466 -0
- data/lib/appoptics_apm/inst/rack.rb +199 -0
- data/lib/appoptics_apm/inst/redis.rb +275 -0
- data/lib/appoptics_apm/inst/resque.rb +151 -0
- data/lib/appoptics_apm/inst/rest-client.rb +48 -0
- data/lib/appoptics_apm/inst/sequel.rb +178 -0
- data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
- data/lib/appoptics_apm/inst/sidekiq-worker.rb +65 -0
- data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
- data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
- data/lib/appoptics_apm/instrumentation.rb +22 -0
- data/lib/appoptics_apm/legacy_method_profiling.rb +90 -0
- data/lib/appoptics_apm/loading.rb +65 -0
- data/lib/appoptics_apm/logger.rb +42 -0
- data/lib/appoptics_apm/method_profiling.rb +33 -0
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +26 -0
- data/lib/appoptics_apm/noop/metadata.rb +22 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
- data/lib/appoptics_apm/sdk/tracing.rb +315 -0
- data/lib/appoptics_apm/support.rb +119 -0
- data/lib/appoptics_apm/test.rb +94 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +319 -0
- data/lib/appoptics_apm/version.rb +15 -0
- data/lib/appoptics_apm/xtrace.rb +103 -0
- data/lib/joboe_metal.rb +212 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +80 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe_metal.rb +198 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
- data/yardoc_frontpage.md +26 -0
- metadata +266 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'socket'
|
|
5
|
+
require 'json'
|
|
6
|
+
|
|
7
|
+
module AppOpticsAPM
|
|
8
|
+
module Inst
|
|
9
|
+
module ResqueClient
|
|
10
|
+
def self.included(klass)
|
|
11
|
+
klass.send :extend, ::Resque
|
|
12
|
+
AppOpticsAPM::Util.method_alias(klass, :enqueue, ::Resque)
|
|
13
|
+
AppOpticsAPM::Util.method_alias(klass, :enqueue_to, ::Resque)
|
|
14
|
+
AppOpticsAPM::Util.method_alias(klass, :dequeue, ::Resque)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def extract_trace_details(op, klass, args)
|
|
18
|
+
report_kvs = {}
|
|
19
|
+
|
|
20
|
+
begin
|
|
21
|
+
report_kvs[:Spec] = :pushq
|
|
22
|
+
report_kvs[:Flavor] = :resque
|
|
23
|
+
report_kvs[:JobName] = klass.to_s
|
|
24
|
+
|
|
25
|
+
if AppOpticsAPM::Config[:resqueclient][:log_args]
|
|
26
|
+
kv_args = args.to_json
|
|
27
|
+
|
|
28
|
+
# Limit the argument json string to 1024 bytes
|
|
29
|
+
if kv_args.length > 1024
|
|
30
|
+
report_kvs[:Args] = kv_args[0..1023] + '...[snipped]'
|
|
31
|
+
else
|
|
32
|
+
report_kvs[:Args] = kv_args
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:resqueclient][:collect_backtraces]
|
|
36
|
+
report_kvs[:Queue] = klass.instance_variable_get(:@queue)
|
|
37
|
+
rescue => e
|
|
38
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
report_kvs
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def enqueue_with_appoptics(klass, *args)
|
|
45
|
+
if AppOpticsAPM.tracing?
|
|
46
|
+
report_kvs = extract_trace_details(:enqueue, klass, args)
|
|
47
|
+
|
|
48
|
+
AppOpticsAPM::API.trace(:'resque-client', report_kvs, :enqueue) do
|
|
49
|
+
enqueue_without_appoptics(klass, *args)
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
enqueue_without_appoptics(klass, *args)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def enqueue_to_with_appoptics(queue, klass, *args)
|
|
57
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:enqueue)
|
|
58
|
+
report_kvs = extract_trace_details(:enqueue_to, klass, args)
|
|
59
|
+
report_kvs[:Queue] = queue.to_s if queue
|
|
60
|
+
|
|
61
|
+
AppOpticsAPM::API.trace(:'resque-client', report_kvs) do
|
|
62
|
+
enqueue_to_without_appoptics(queue, klass, *args)
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
enqueue_to_without_appoptics(queue, klass, *args)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def dequeue_with_appoptics(klass, *args)
|
|
70
|
+
if AppOpticsAPM.tracing?
|
|
71
|
+
report_kvs = extract_trace_details(:dequeue, klass, args)
|
|
72
|
+
|
|
73
|
+
AppOpticsAPM::API.trace(:'resque-client', report_kvs) do
|
|
74
|
+
dequeue_without_appoptics(klass, *args)
|
|
75
|
+
end
|
|
76
|
+
else
|
|
77
|
+
dequeue_without_appoptics(klass, *args)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
module ResqueWorker
|
|
83
|
+
def self.included(klass)
|
|
84
|
+
AppOpticsAPM::Util.method_alias(klass, :perform, ::Resque::Worker)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def perform_with_appoptics(job)
|
|
88
|
+
report_kvs = {}
|
|
89
|
+
|
|
90
|
+
begin
|
|
91
|
+
report_kvs[:Spec] = :job
|
|
92
|
+
report_kvs[:Flavor] = :resque
|
|
93
|
+
report_kvs[:JobName] = job.payload['class'].to_s
|
|
94
|
+
report_kvs[:Queue] = job.queue
|
|
95
|
+
|
|
96
|
+
# Set these keys for the ability to separate out
|
|
97
|
+
# background tasks into a separate app on the server-side UI
|
|
98
|
+
|
|
99
|
+
report_kvs[:'HTTP-Host'] = Socket.gethostname
|
|
100
|
+
report_kvs[:Controller] = "Resque_#{job.queue}"
|
|
101
|
+
report_kvs[:Action] = job.payload['class'].to_s
|
|
102
|
+
report_kvs[:URL] = "/resque/#{job.queue}/#{job.payload['class']}"
|
|
103
|
+
|
|
104
|
+
if AppOpticsAPM::Config[:resqueworker][:log_args]
|
|
105
|
+
kv_args = job.payload['args'].to_json
|
|
106
|
+
|
|
107
|
+
# Limit the argument json string to 1024 bytes
|
|
108
|
+
if kv_args.length > 1024
|
|
109
|
+
report_kvs[:Args] = kv_args[0..1023] + '...[snipped]'
|
|
110
|
+
else
|
|
111
|
+
report_kvs[:Args] = kv_args
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:resqueworker][:collect_backtraces]
|
|
116
|
+
rescue => e
|
|
117
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
AppOpticsAPM::SDK.start_trace(:'resque-worker', nil, report_kvs) do
|
|
121
|
+
perform_without_appoptics(job)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
module ResqueJob
|
|
127
|
+
def self.included(klass)
|
|
128
|
+
AppOpticsAPM::Util.method_alias(klass, :fail, ::Resque::Job)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def fail_with_appoptics(exception)
|
|
132
|
+
if AppOpticsAPM.tracing?
|
|
133
|
+
AppOpticsAPM::API.log_exception(:resque, exception)
|
|
134
|
+
end
|
|
135
|
+
fail_without_appoptics(exception)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if defined?(Resque)
|
|
142
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting resque' if AppOpticsAPM::Config[:verbose]
|
|
143
|
+
|
|
144
|
+
AppOpticsAPM::Util.send_include(Resque, AppOpticsAPM::Inst::ResqueClient) if AppOpticsAPM::Config[:resqueclient][:enabled]
|
|
145
|
+
AppOpticsAPM::Util.send_include(Resque::Worker, AppOpticsAPM::Inst::ResqueWorker) if AppOpticsAPM::Config[:resqueworker][:enabled]
|
|
146
|
+
if AppOpticsAPM::Config[:resqueclient][:enabled] || AppOpticsAPM::Config[:resqueworker][:enabled]
|
|
147
|
+
AppOpticsAPM::Util.send_include(Resque::Job, AppOpticsAPM::Inst::ResqueJob)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module AppOpticsAPM
|
|
5
|
+
module Inst
|
|
6
|
+
module RestClientRequest
|
|
7
|
+
def self.included(klass)
|
|
8
|
+
AppOpticsAPM::Util.method_alias(klass, :execute, ::RestClient::Request)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# execute_with_appoptics
|
|
13
|
+
#
|
|
14
|
+
# The wrapper method for RestClient::Request.execute
|
|
15
|
+
#
|
|
16
|
+
def execute_with_appoptics(&block)
|
|
17
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(url)
|
|
18
|
+
|
|
19
|
+
unless AppOpticsAPM.tracing?
|
|
20
|
+
xtrace = AppOpticsAPM::Context.toString
|
|
21
|
+
@processed_headers['X-Trace'] = AppOpticsAPM::Context.toString if AppOpticsAPM::XTrace.valid?(xtrace) && !blacklisted
|
|
22
|
+
return execute_without_appoptics(&block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
kvs = {}
|
|
27
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:rest_client][:collect_backtraces]
|
|
28
|
+
AppOpticsAPM::API.log_entry('rest-client', kvs)
|
|
29
|
+
|
|
30
|
+
@processed_headers['X-Trace'] = AppOpticsAPM::Context.toString unless blacklisted
|
|
31
|
+
|
|
32
|
+
# The core rest-client call
|
|
33
|
+
execute_without_appoptics(&block)
|
|
34
|
+
rescue => e
|
|
35
|
+
AppOpticsAPM::API.log_exception('rest-client', e)
|
|
36
|
+
raise e
|
|
37
|
+
ensure
|
|
38
|
+
AppOpticsAPM::API.log_exit('rest-client')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if defined?(RestClient) && AppOpticsAPM::Config[:rest_client][:enabled]
|
|
46
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting rest-client' if AppOpticsAPM::Config[:verbose]
|
|
47
|
+
AppOpticsAPM::Util.send_include(RestClient::Request, AppOpticsAPM::Inst::RestClientRequest)
|
|
48
|
+
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module AppOpticsAPM
|
|
5
|
+
module Inst
|
|
6
|
+
##
|
|
7
|
+
# AppOpticsAPM::Inst::Sequel
|
|
8
|
+
#
|
|
9
|
+
# The common (shared) methods used by the AppOpticsAPM Sequel instrumentation
|
|
10
|
+
# across multiple modules/classes.
|
|
11
|
+
#
|
|
12
|
+
module Sequel
|
|
13
|
+
##
|
|
14
|
+
# extract_trace_details
|
|
15
|
+
#
|
|
16
|
+
# Given SQL and the options hash, this method extracts the interesting
|
|
17
|
+
# bits for reporting to the AppOptics dashboard.
|
|
18
|
+
#
|
|
19
|
+
def extract_trace_details(sql, opts)
|
|
20
|
+
kvs = {}
|
|
21
|
+
|
|
22
|
+
if !sql.is_a?(String)
|
|
23
|
+
kvs[:IsPreparedStatement] = true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if ::Sequel::VERSION > '4.36.0' && !sql.is_a?(String)
|
|
27
|
+
# In 4.37.0, sql was converted to a prepared statement object
|
|
28
|
+
sql = sql.prepared_sql unless sql.is_a?(Symbol)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if AppOpticsAPM::Config[:sanitize_sql]
|
|
32
|
+
# Sanitize SQL and don't report binds
|
|
33
|
+
if sql.is_a?(Symbol)
|
|
34
|
+
kvs[:Query] = sql
|
|
35
|
+
else
|
|
36
|
+
kvs[:Query] = AppOpticsAPM::Util.sanitize_sql(sql)
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
# Report raw SQL and any binds if they exist
|
|
40
|
+
kvs[:Query] = sql.to_s
|
|
41
|
+
kvs[:QueryArgs] = opts[:arguments] if opts.is_a?(Hash) && opts.key?(:arguments)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:sequel][:collect_backtraces]
|
|
45
|
+
|
|
46
|
+
if ::Sequel::VERSION < '3.41.0' && !(self.class.to_s =~ /Dataset$/)
|
|
47
|
+
db_opts = @opts
|
|
48
|
+
elsif @pool
|
|
49
|
+
db_opts = @pool.db.opts
|
|
50
|
+
else
|
|
51
|
+
db_opts = @db.opts
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
kvs[:Database] = db_opts[:database]
|
|
55
|
+
kvs[:RemoteHost] = db_opts[:host]
|
|
56
|
+
kvs[:RemotePort] = db_opts[:port] if db_opts.key?(:port)
|
|
57
|
+
kvs[:Flavor] = db_opts[:adapter]
|
|
58
|
+
rescue => e
|
|
59
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug Error capturing Sequel KVs: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
|
60
|
+
ensure
|
|
61
|
+
return kvs
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# exec_with_appoptics
|
|
66
|
+
#
|
|
67
|
+
# This method wraps and routes the call to the specified
|
|
68
|
+
# original method call
|
|
69
|
+
#
|
|
70
|
+
def exec_with_appoptics(method, sql, opts = ::Sequel::OPTS, &block)
|
|
71
|
+
if AppOpticsAPM.tracing?
|
|
72
|
+
kvs = extract_trace_details(sql, opts)
|
|
73
|
+
AppOpticsAPM::API.log_entry(:sequel, kvs)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
send(method, sql, opts, &block)
|
|
77
|
+
rescue => e
|
|
78
|
+
AppOpticsAPM::API.log_exception(:sequel, e)
|
|
79
|
+
raise e
|
|
80
|
+
ensure
|
|
81
|
+
AppOpticsAPM::API.log_exit(:sequel)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
module SequelDatabase
|
|
86
|
+
include AppOpticsAPM::Inst::Sequel
|
|
87
|
+
|
|
88
|
+
def self.included(klass)
|
|
89
|
+
AppOpticsAPM::Util.method_alias(klass, :run, ::Sequel::Database)
|
|
90
|
+
AppOpticsAPM::Util.method_alias(klass, :execute_ddl, ::Sequel::Database)
|
|
91
|
+
AppOpticsAPM::Util.method_alias(klass, :execute_dui, ::Sequel::Database)
|
|
92
|
+
AppOpticsAPM::Util.method_alias(klass, :execute_insert, ::Sequel::Database)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def run_with_appoptics(sql, opts = ::Sequel::OPTS)
|
|
96
|
+
if AppOpticsAPM.tracing?
|
|
97
|
+
kvs = extract_trace_details(sql, opts)
|
|
98
|
+
AppOpticsAPM::API.log_entry(:sequel, kvs)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
run_without_appoptics(sql, opts)
|
|
102
|
+
rescue => e
|
|
103
|
+
AppOpticsAPM::API.log_exception(:sequel, e)
|
|
104
|
+
raise e
|
|
105
|
+
ensure
|
|
106
|
+
AppOpticsAPM::API.log_exit(:sequel)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def execute_ddl_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
110
|
+
# If we're already tracing a sequel operation, then this call likely came
|
|
111
|
+
# from Sequel::Dataset. In this case, just pass it on.
|
|
112
|
+
return execute_ddl_without_appoptics(sql, opts, &block) if AppOpticsAPM.tracing_layer?(:sequel)
|
|
113
|
+
|
|
114
|
+
exec_with_appoptics(:execute_ddl_without_appoptics, sql, opts, &block)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def execute_dui_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
118
|
+
# If we're already tracing a sequel operation, then this call likely came
|
|
119
|
+
# from Sequel::Dataset. In this case, just pass it on.
|
|
120
|
+
return execute_dui_without_appoptics(sql, opts, &block) if AppOpticsAPM.tracing_layer?(:sequel)
|
|
121
|
+
|
|
122
|
+
exec_with_appoptics(:execute_dui_without_appoptics, sql, opts, &block)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def execute_insert_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
126
|
+
# If we're already tracing a sequel operation, then this call likely came
|
|
127
|
+
# from Sequel::Dataset. In this case, just pass it on.
|
|
128
|
+
return execute_insert_without_appoptics(sql, opts, &block) if AppOpticsAPM.tracing_layer?(:sequel)
|
|
129
|
+
|
|
130
|
+
exec_with_appoptics(:execute_insert_without_appoptics, sql, opts, &block)
|
|
131
|
+
end
|
|
132
|
+
end # module SequelDatabase
|
|
133
|
+
|
|
134
|
+
module SequelDataset
|
|
135
|
+
include AppOpticsAPM::Inst::Sequel
|
|
136
|
+
|
|
137
|
+
def self.included(klass)
|
|
138
|
+
AppOpticsAPM::Util.method_alias(klass, :execute, ::Sequel::Dataset)
|
|
139
|
+
AppOpticsAPM::Util.method_alias(klass, :execute_ddl, ::Sequel::Dataset)
|
|
140
|
+
AppOpticsAPM::Util.method_alias(klass, :execute_dui, ::Sequel::Dataset)
|
|
141
|
+
AppOpticsAPM::Util.method_alias(klass, :execute_insert, ::Sequel::Dataset)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def execute_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
145
|
+
exec_with_appoptics(:execute_without_appoptics, sql, opts, &block)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def execute_ddl_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
149
|
+
exec_with_appoptics(:execute_ddl_without_appoptics, sql, opts, &block)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def execute_dui_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
153
|
+
exec_with_appoptics(:execute_dui_without_appoptics, sql, opts, &block)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def execute_insert_with_appoptics(sql, opts = ::Sequel::OPTS, &block)
|
|
157
|
+
exec_with_appoptics(:execute_insert_without_appoptics, sql, opts, &block)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
end # module SequelDataset
|
|
161
|
+
end # module Inst
|
|
162
|
+
end # module AppOpticsAPM
|
|
163
|
+
|
|
164
|
+
if AppOpticsAPM::Config[:sequel][:enabled]
|
|
165
|
+
if defined?(::Sequel) && ::Sequel::VERSION < '4.0.0'
|
|
166
|
+
# For versions before 4.0.0, Sequel::OPTS wasn't defined.
|
|
167
|
+
# Define it as an empty hash for backwards compatibility.
|
|
168
|
+
module ::Sequel
|
|
169
|
+
OPTS = {}
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if defined?(::Sequel)
|
|
174
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting sequel' if AppOpticsAPM::Config[:verbose]
|
|
175
|
+
AppOpticsAPM::Util.send_include(::Sequel::Database, AppOpticsAPM::Inst::SequelDatabase)
|
|
176
|
+
AppOpticsAPM::Util.send_include(::Sequel::Dataset, AppOpticsAPM::Inst::SequelDataset)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module AppOpticsAPM
|
|
5
|
+
class SidekiqClient
|
|
6
|
+
def collect_kvs(args)
|
|
7
|
+
begin
|
|
8
|
+
# Attempt to collect up pertinent info. If we hit something unexpected,
|
|
9
|
+
# keep calm and instrument on.
|
|
10
|
+
|
|
11
|
+
report_kvs = {}
|
|
12
|
+
worker_class, msg, queue, _ = args
|
|
13
|
+
|
|
14
|
+
report_kvs[:Spec] = :pushq
|
|
15
|
+
report_kvs[:Flavor] = :sidekiq
|
|
16
|
+
report_kvs[:Queue] = queue
|
|
17
|
+
report_kvs[:Retry] = msg['retry']
|
|
18
|
+
report_kvs[:JobName] = msg['wrapped'] || worker_class
|
|
19
|
+
report_kvs[:MsgID] = msg['jid']
|
|
20
|
+
report_kvs[:Args] = msg['args'].to_s[0..1024] if AppOpticsAPM::Config[:sidekiqclient][:log_args]
|
|
21
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:sidekiqclient][:collect_backtraces]
|
|
22
|
+
rescue => e
|
|
23
|
+
AppOpticsAPM.logger.warn "[appoptics_apm/sidekiq] Non-fatal error capturing KVs: #{e.message}"
|
|
24
|
+
end
|
|
25
|
+
report_kvs
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def call(*args)
|
|
29
|
+
# args: 0: worker_class, 1: msg, 2: queue, 3: redis_pool
|
|
30
|
+
if AppOpticsAPM.tracing?
|
|
31
|
+
report_kvs = collect_kvs(args)
|
|
32
|
+
AppOpticsAPM::API.log_entry(:'sidekiq-client', report_kvs)
|
|
33
|
+
args[1]['SourceTrace'] = AppOpticsAPM::Context.toString
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
result = yield
|
|
37
|
+
rescue => e
|
|
38
|
+
AppOpticsAPM::API.log_exception(:'sidekiq-client', e, { :JobID => result['jid'] })
|
|
39
|
+
raise
|
|
40
|
+
ensure
|
|
41
|
+
AppOpticsAPM::API.log_exit(:'sidekiq-client', { :JobID => result['jid'] })
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if defined?(Sidekiq) && AppOpticsAPM::Config[:sidekiqclient][:enabled]
|
|
47
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting sidekiq client' if AppOpticsAPM::Config[:verbose]
|
|
48
|
+
|
|
49
|
+
Sidekiq.configure_client do |config|
|
|
50
|
+
config.client_middleware do |chain|
|
|
51
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Adding Sidekiq client middleware' if AppOpticsAPM::Config[:verbose]
|
|
52
|
+
chain.add AppOpticsAPM::SidekiqClient
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module AppOpticsAPM
|
|
5
|
+
class SidekiqWorker
|
|
6
|
+
def collect_kvs(args)
|
|
7
|
+
begin
|
|
8
|
+
# Attempt to collect up pertinent info. If we hit something unexpected,
|
|
9
|
+
# keep calm and instrument on.
|
|
10
|
+
report_kvs = {}
|
|
11
|
+
_worker, msg, queue = args
|
|
12
|
+
|
|
13
|
+
# Background Job Spec KVs
|
|
14
|
+
report_kvs[:Spec] = :job
|
|
15
|
+
report_kvs[:Flavor] = :sidekiq
|
|
16
|
+
report_kvs[:Queue] = queue
|
|
17
|
+
report_kvs[:Retry] = msg['retry']
|
|
18
|
+
report_kvs[:JobName] = msg['wrapped'] || msg['class']
|
|
19
|
+
report_kvs[:MsgID] = msg['jid']
|
|
20
|
+
report_kvs[:Args] = msg['args'].to_s[0..1024] if AppOpticsAPM::Config[:sidekiqworker][:log_args]
|
|
21
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:sidekiqworker][:collect_backtraces]
|
|
22
|
+
|
|
23
|
+
# Webserver Spec KVs
|
|
24
|
+
report_kvs[:'HTTP-Host'] = Socket.gethostname
|
|
25
|
+
report_kvs[:Controller] = "Sidekiq_#{queue}"
|
|
26
|
+
report_kvs[:Action] = msg['wrapped'] || msg['class']
|
|
27
|
+
report_kvs[:URL] = "/sidekiq/#{queue}/#{msg['wrapped'] || msg['class']}"
|
|
28
|
+
rescue => e
|
|
29
|
+
AppOpticsAPM.logger.warn "[appoptics_apm/sidekiq] Non-fatal error capturing KVs: #{e.message}"
|
|
30
|
+
end
|
|
31
|
+
report_kvs
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def call(*args)
|
|
35
|
+
# args: 0: worker, 1: msg, 2: queue
|
|
36
|
+
report_kvs = collect_kvs(args)
|
|
37
|
+
|
|
38
|
+
# Something is happening across Celluloid threads where liboboe settings
|
|
39
|
+
# are being lost. So we re-set the tracing mode to assure
|
|
40
|
+
# we sample as desired. Setting the tracing mode will re-update
|
|
41
|
+
# the liboboe settings.
|
|
42
|
+
AppOpticsAPM.set_tracing_mode(AppOpticsAPM::Config[:tracing_mode].to_sym)
|
|
43
|
+
|
|
44
|
+
# Continue the trace from the enqueue side?
|
|
45
|
+
if args[1].is_a?(Hash) && AppOpticsAPM::XTrace.valid?(args[1]['SourceTrace'])
|
|
46
|
+
report_kvs[:SourceTrace] = args[1]['SourceTrace']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
AppOpticsAPM::SDK.start_trace(:'sidekiq-worker', nil, report_kvs) do
|
|
50
|
+
yield
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if defined?(Sidekiq) && AppOpticsAPM::Config[:sidekiqworker][:enabled]
|
|
57
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting sidekiq worker' if AppOpticsAPM::Config[:verbose]
|
|
58
|
+
|
|
59
|
+
Sidekiq.configure_server do |config|
|
|
60
|
+
config.server_middleware do |chain|
|
|
61
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Adding Sidekiq worker middleware' if AppOpticsAPM::Config[:verbose]
|
|
62
|
+
chain.add AppOpticsAPM::SidekiqWorker
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|