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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
  4. data/.gitignore +29 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +121 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +769 -0
  9. data/CONFIG.md +33 -0
  10. data/Gemfile +29 -0
  11. data/LICENSE +193 -0
  12. data/README.md +393 -0
  13. data/Rakefile +230 -0
  14. data/appoptics_apm.gemspec +61 -0
  15. data/bin/appoptics_apm_config +15 -0
  16. data/build_gem.sh +15 -0
  17. data/build_gem_upload_to_packagecloud.sh +20 -0
  18. data/examples/SDK/01_basic_tracing.rb +67 -0
  19. data/examples/carrying_context.rb +220 -0
  20. data/ext/oboe_metal/extconf.rb +114 -0
  21. data/ext/oboe_metal/lib/.keep +0 -0
  22. data/ext/oboe_metal/noop/noop.c +7 -0
  23. data/ext/oboe_metal/src/VERSION +1 -0
  24. data/init.rb +4 -0
  25. data/lib/appoptics_apm.rb +76 -0
  26. data/lib/appoptics_apm/api.rb +20 -0
  27. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  28. data/lib/appoptics_apm/api/logging.rb +375 -0
  29. data/lib/appoptics_apm/api/memcache.rb +37 -0
  30. data/lib/appoptics_apm/api/metrics.rb +55 -0
  31. data/lib/appoptics_apm/api/profiling.rb +203 -0
  32. data/lib/appoptics_apm/api/tracing.rb +53 -0
  33. data/lib/appoptics_apm/api/util.rb +122 -0
  34. data/lib/appoptics_apm/base.rb +230 -0
  35. data/lib/appoptics_apm/config.rb +254 -0
  36. data/lib/appoptics_apm/frameworks/grape.rb +97 -0
  37. data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
  38. data/lib/appoptics_apm/frameworks/rails.rb +94 -0
  39. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  40. data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -0
  41. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  42. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  43. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  44. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
  45. data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
  46. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  47. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  48. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  49. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  50. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  51. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +108 -0
  52. data/lib/appoptics_apm/frameworks/sinatra.rb +125 -0
  53. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  54. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  55. data/lib/appoptics_apm/inst/curb.rb +330 -0
  56. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  57. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  58. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  59. data/lib/appoptics_apm/inst/excon.rb +125 -0
  60. data/lib/appoptics_apm/inst/faraday.rb +94 -0
  61. data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
  62. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  63. data/lib/appoptics_apm/inst/http.rb +73 -0
  64. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  65. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  66. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  67. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  68. data/lib/appoptics_apm/inst/moped.rb +466 -0
  69. data/lib/appoptics_apm/inst/rack.rb +199 -0
  70. data/lib/appoptics_apm/inst/redis.rb +275 -0
  71. data/lib/appoptics_apm/inst/resque.rb +151 -0
  72. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  73. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  74. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  75. data/lib/appoptics_apm/inst/sidekiq-worker.rb +65 -0
  76. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  77. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  78. data/lib/appoptics_apm/instrumentation.rb +22 -0
  79. data/lib/appoptics_apm/legacy_method_profiling.rb +90 -0
  80. data/lib/appoptics_apm/loading.rb +65 -0
  81. data/lib/appoptics_apm/logger.rb +42 -0
  82. data/lib/appoptics_apm/method_profiling.rb +33 -0
  83. data/lib/appoptics_apm/noop/README.md +9 -0
  84. data/lib/appoptics_apm/noop/context.rb +26 -0
  85. data/lib/appoptics_apm/noop/metadata.rb +22 -0
  86. data/lib/appoptics_apm/ruby.rb +35 -0
  87. data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
  88. data/lib/appoptics_apm/sdk/tracing.rb +315 -0
  89. data/lib/appoptics_apm/support.rb +119 -0
  90. data/lib/appoptics_apm/test.rb +94 -0
  91. data/lib/appoptics_apm/thread_local.rb +26 -0
  92. data/lib/appoptics_apm/util.rb +319 -0
  93. data/lib/appoptics_apm/version.rb +15 -0
  94. data/lib/appoptics_apm/xtrace.rb +103 -0
  95. data/lib/joboe_metal.rb +212 -0
  96. data/lib/oboe.rb +7 -0
  97. data/lib/oboe/README +2 -0
  98. data/lib/oboe/backward_compatibility.rb +80 -0
  99. data/lib/oboe/inst/rack.rb +11 -0
  100. data/lib/oboe_metal.rb +198 -0
  101. data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
  102. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
  103. data/yardoc_frontpage.md +26 -0
  104. 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