appoptics_apm-zearn 4.13.1
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/.github/workflows/build_and_release_gem.yml +103 -0
- data/.github/workflows/build_for_packagecloud.yml +70 -0
- data/.github/workflows/docker-images.yml +47 -0
- data/.github/workflows/run_cpluplus_tests.yml +73 -0
- data/.github/workflows/run_tests.yml +168 -0
- data/.github/workflows/scripts/test_install.rb +23 -0
- data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
- data/.github/workflows/test_on_4_linux.yml +159 -0
- data/.gitignore +36 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +130 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/README.md +393 -0
- data/appoptics_apm.gemspec +70 -0
- data/bin/appoptics_apm_config +15 -0
- data/examples/prepend.rb +13 -0
- data/examples/sdk_examples.rb +158 -0
- data/ext/oboe_metal/README.md +69 -0
- data/ext/oboe_metal/extconf.rb +151 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/noop/noop.c +8 -0
- data/ext/oboe_metal/src/README.md +6 -0
- data/ext/oboe_metal/src/VERSION +2 -0
- data/ext/oboe_metal/src/bson/bson.h +220 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/frames.cc +246 -0
- data/ext/oboe_metal/src/frames.h +40 -0
- data/ext/oboe_metal/src/init_appoptics_apm.cc +21 -0
- data/ext/oboe_metal/src/logging.cc +95 -0
- data/ext/oboe_metal/src/logging.h +35 -0
- data/ext/oboe_metal/src/oboe.h +1156 -0
- data/ext/oboe_metal/src/oboe_api.cpp +652 -0
- data/ext/oboe_metal/src/oboe_api.hpp +431 -0
- data/ext/oboe_metal/src/oboe_debug.h +59 -0
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +7329 -0
- data/ext/oboe_metal/src/profiling.cc +435 -0
- data/ext/oboe_metal/src/profiling.h +78 -0
- data/ext/oboe_metal/test/CMakeLists.txt +53 -0
- data/ext/oboe_metal/test/FindGMock.cmake +43 -0
- data/ext/oboe_metal/test/README.md +56 -0
- data/ext/oboe_metal/test/frames_test.cc +164 -0
- data/ext/oboe_metal/test/profiling_test.cc +93 -0
- data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
- data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
- data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
- data/ext/oboe_metal/test/test.h +11 -0
- data/ext/oboe_metal/test/test_main.cc +32 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm/api/layerinit.rb +41 -0
- data/lib/appoptics_apm/api/logging.rb +381 -0
- data/lib/appoptics_apm/api/memcache.rb +37 -0
- data/lib/appoptics_apm/api/metrics.rb +63 -0
- data/lib/appoptics_apm/api/tracing.rb +57 -0
- data/lib/appoptics_apm/api/util.rb +120 -0
- data/lib/appoptics_apm/api.rb +21 -0
- data/lib/appoptics_apm/base.rb +231 -0
- data/lib/appoptics_apm/config.rb +299 -0
- data/lib/appoptics_apm/frameworks/grape.rb +98 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +78 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -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_controller6.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 +88 -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 +114 -0
- data/lib/appoptics_apm/frameworks/rails/inst/logger_formatters.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails.rb +100 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +96 -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 +332 -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 +106 -0
- data/lib/appoptics_apm/inst/graphql.rb +240 -0
- data/lib/appoptics_apm/inst/grpc_client.rb +159 -0
- data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
- data/lib/appoptics_apm/inst/http.rb +81 -0
- data/lib/appoptics_apm/inst/httpclient.rb +174 -0
- data/lib/appoptics_apm/inst/logger_formatter.rb +50 -0
- data/lib/appoptics_apm/inst/logging_log_event.rb +28 -0
- data/lib/appoptics_apm/inst/lumberjack_formatter.rb +13 -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 +182 -0
- data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
- data/lib/appoptics_apm/inst/redis.rb +274 -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 +66 -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/loading.rb +65 -0
- data/lib/appoptics_apm/logger.rb +14 -0
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +27 -0
- data/lib/appoptics_apm/noop/metadata.rb +25 -0
- data/lib/appoptics_apm/noop/profiling.rb +21 -0
- data/lib/appoptics_apm/oboe_init_options.rb +211 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/sdk/current_trace.rb +77 -0
- data/lib/appoptics_apm/sdk/custom_metrics.rb +94 -0
- data/lib/appoptics_apm/sdk/logging.rb +37 -0
- data/lib/appoptics_apm/sdk/tracing.rb +434 -0
- data/lib/appoptics_apm/support/profiling.rb +18 -0
- data/lib/appoptics_apm/support/transaction_metrics.rb +67 -0
- data/lib/appoptics_apm/support/transaction_settings.rb +219 -0
- data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
- data/lib/appoptics_apm/support_report.rb +119 -0
- data/lib/appoptics_apm/test.rb +95 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +326 -0
- data/lib/appoptics_apm/version.rb +16 -0
- data/lib/appoptics_apm/xtrace.rb +115 -0
- data/lib/appoptics_apm.rb +77 -0
- data/lib/joboe_metal.rb +212 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +172 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +47 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +425 -0
- data/log/.keep +0 -0
- data/yardoc_frontpage.md +26 -0
- metadata +231 -0
@@ -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,66 @@
|
|
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
|
+
# TODO remove completely once it is determined that this works without
|
39
|
+
# Something is happening across Celluloid threads where liboboe settings
|
40
|
+
# are being lost. So we re-set the tracing mode to assure
|
41
|
+
# we sample as desired. Setting the tracing mode will re-update
|
42
|
+
# the liboboe settings.
|
43
|
+
# AppOpticsAPM.set_tracing_mode(AppOpticsAPM::Config[:tracing_mode].to_sym)
|
44
|
+
|
45
|
+
# Continue the trace from the enqueue side?
|
46
|
+
if args[1].is_a?(Hash) && AppOpticsAPM::XTrace.valid?(args[1]['SourceTrace'])
|
47
|
+
report_kvs[:SourceTrace] = args[1]['SourceTrace']
|
48
|
+
end
|
49
|
+
|
50
|
+
AppOpticsAPM::SDK.start_trace(:'sidekiq-worker', nil, report_kvs) do
|
51
|
+
yield
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if defined?(Sidekiq) && AppOpticsAPM::Config[:sidekiqworker][:enabled]
|
58
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting sidekiq worker' if AppOpticsAPM::Config[:verbose]
|
59
|
+
|
60
|
+
Sidekiq.configure_server do |config|
|
61
|
+
config.server_middleware do |chain|
|
62
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Adding Sidekiq worker middleware' if AppOpticsAPM::Config[:verbose]
|
63
|
+
chain.add AppOpticsAPM::SidekiqWorker
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,294 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module Inst
|
6
|
+
module Cassandra
|
7
|
+
def extract_trace_details(op, column_family, keys, args, options = {})
|
8
|
+
report_kvs = {}
|
9
|
+
|
10
|
+
begin
|
11
|
+
report_kvs[:Op] = op.to_s
|
12
|
+
report_kvs[:Cf] = column_family.to_s if column_family
|
13
|
+
report_kvs[:Key] = keys.inspect if keys
|
14
|
+
|
15
|
+
# Open issue - how to handle multiple Cassandra servers
|
16
|
+
report_kvs[:RemoteHost], report_kvs[:RemotePort] = @servers.first.split(':')
|
17
|
+
|
18
|
+
report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:cassandra][:collect_backtraces]
|
19
|
+
|
20
|
+
if options.empty? && args.is_a?(Array)
|
21
|
+
options = args.last if args.last.is_a?(Hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
unless options.empty?
|
25
|
+
[:start_key, :finish_key, :key_count, :batch_size, :columns, :count, :start,
|
26
|
+
:stop, :finish, :finished, :reversed, :consistency, :ttl].each do |k|
|
27
|
+
report_kvs[k.to_s.capitalize] = options[k] if options.key?(k)
|
28
|
+
end
|
29
|
+
|
30
|
+
if op == :get_indexed_slices
|
31
|
+
index_clause = columns_and_options[:index_clause] || {}
|
32
|
+
unless index_clause.empty?
|
33
|
+
[:column_name, :value, :comparison].each do |k|
|
34
|
+
report_kvs[k.to_s.capitalize] = index_clause[k] if index_clause.key?(k)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
rescue => e
|
40
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
41
|
+
end
|
42
|
+
|
43
|
+
report_kvs
|
44
|
+
end
|
45
|
+
|
46
|
+
def insert_with_appoptics(column_family, key, hash, options = {})
|
47
|
+
return insert_without_appoptics(column_family, key, hash, options = {}) unless AppOpticsAPM.tracing?
|
48
|
+
|
49
|
+
report_kvs = extract_trace_details(:insert, column_family, key, hash, options)
|
50
|
+
|
51
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
52
|
+
insert_without_appoptics(column_family, key, hash, options = {})
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def remove_with_appoptics(column_family, key, *columns_and_options)
|
57
|
+
args = [column_family, key] + columns_and_options
|
58
|
+
|
59
|
+
return send :remove_without_appoptics, *args unless AppOpticsAPM.tracing?
|
60
|
+
|
61
|
+
report_kvs = extract_trace_details(:remove, column_family, key, columns_and_options)
|
62
|
+
|
63
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
64
|
+
send :remove_without_appoptics, *args
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def count_columns_with_appoptics(column_family, key, *columns_and_options)
|
69
|
+
args = [column_family, key] + columns_and_options
|
70
|
+
|
71
|
+
return send :count_columns_without_appoptics, *args unless AppOpticsAPM.tracing?
|
72
|
+
|
73
|
+
report_kvs = extract_trace_details(:count_columns, column_family, key, columns_and_options)
|
74
|
+
|
75
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
76
|
+
send :count_columns_without_appoptics, *args
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_columns_with_appoptics(column_family, key, *columns_and_options)
|
81
|
+
args = [column_family, key] + columns_and_options
|
82
|
+
|
83
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:multi_get_columns)
|
84
|
+
report_kvs = extract_trace_details(:get_columns, column_family, key, columns_and_options)
|
85
|
+
|
86
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
87
|
+
send :get_columns_without_appoptics, *args
|
88
|
+
end
|
89
|
+
else
|
90
|
+
send :get_columns_without_appoptics, *args
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def multi_get_columns_with_appoptics(column_family, key, *columns_and_options)
|
95
|
+
args = [column_family, key] + columns_and_options
|
96
|
+
|
97
|
+
return send :multi_get_columns_without_appoptics, *args unless AppOpticsAPM.tracing?
|
98
|
+
|
99
|
+
report_kvs = extract_trace_details(:multi_get_columns, column_family, key, columns_and_options)
|
100
|
+
|
101
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs, :multi_get_columns) do
|
102
|
+
send :multi_get_columns_without_appoptics, *args
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_with_appoptics(column_family, key, *columns_and_options)
|
107
|
+
args = [column_family, key] + columns_and_options
|
108
|
+
|
109
|
+
return send :get_without_appoptics, *args unless AppOpticsAPM.tracing?
|
110
|
+
|
111
|
+
report_kvs = extract_trace_details(:get, column_family, key, columns_and_options)
|
112
|
+
|
113
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs, :get) do
|
114
|
+
send :get_without_appoptics, *args
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def multi_get_with_appoptics(column_family, key, *columns_and_options)
|
119
|
+
args = [column_family, key] + columns_and_options
|
120
|
+
|
121
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:get)
|
122
|
+
report_kvs = extract_trace_details(:multi_get, column_family, key, columns_and_options)
|
123
|
+
|
124
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
125
|
+
send :multi_get_without_appoptics, *args
|
126
|
+
end
|
127
|
+
else
|
128
|
+
send :multi_get_without_appoptics, *args
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def exists_with_appoptics?(column_family, key, *columns_and_options)
|
133
|
+
args = [column_family, key] + columns_and_options
|
134
|
+
|
135
|
+
return send :exists_without_appoptics?, *args unless AppOpticsAPM.tracing?
|
136
|
+
|
137
|
+
report_kvs = extract_trace_details(:exists?, column_family, key, columns_and_options)
|
138
|
+
|
139
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
140
|
+
send :exists_without_appoptics?, *args
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_range_single_with_appoptics(column_family, options = {})
|
145
|
+
if AppOpticsAPM.tracing? && !AppOpticsAPM.tracing_layer_op?(:get_range_batch)
|
146
|
+
report_kvs = extract_trace_details(:get_range_single, column_family, nil, nil)
|
147
|
+
|
148
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
149
|
+
get_range_single_without_appoptics(column_family, options)
|
150
|
+
end
|
151
|
+
else
|
152
|
+
get_range_single_without_appoptics(column_family, options)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_range_batch_with_appoptics(column_family, options = {})
|
157
|
+
return get_range_batch_without_appoptics(column_family, options) unless AppOpticsAPM.tracing?
|
158
|
+
|
159
|
+
report_kvs = extract_trace_details(:get_range_batch, column_family, nil, nil)
|
160
|
+
|
161
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs, :get_range_batch) do
|
162
|
+
get_range_batch_without_appoptics(column_family, options)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_indexed_slices_with_appoptics(column_family, index_clause, *columns_and_options)
|
167
|
+
args = [column_family, index_clause] + columns_and_options
|
168
|
+
|
169
|
+
return send :get_indexed_slices_without_appoptics, *args unless AppOpticsAPM.tracing?
|
170
|
+
|
171
|
+
report_kvs = extract_trace_details(:get_indexed_slices, column_family, nil, columns_and_options)
|
172
|
+
|
173
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
174
|
+
send :get_indexed_slices_without_appoptics, *args
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def create_index_with_appoptics(keyspace, column_family, column_name, validation_class)
|
179
|
+
unless AppOpticsAPM.tracing?
|
180
|
+
return create_index_without_appoptics(keyspace, column_family, column_name, validation_class)
|
181
|
+
end
|
182
|
+
|
183
|
+
report_kvs = extract_trace_details(:create_index, column_family, nil, nil)
|
184
|
+
begin
|
185
|
+
report_kvs[:Keyspace] = keyspace.to_s
|
186
|
+
report_kvs[:Column_name] = column_name.to_s
|
187
|
+
report_kvs[:Validation_class] = validation_class.to_s
|
188
|
+
rescue => e
|
189
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
190
|
+
end
|
191
|
+
|
192
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
193
|
+
create_index_without_appoptics(keyspace, column_family, column_name, validation_class)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def drop_index_with_appoptics(keyspace, column_family, column_name)
|
198
|
+
return drop_index_without_appoptics(keyspace, column_family, column_name) unless AppOpticsAPM.tracing?
|
199
|
+
|
200
|
+
report_kvs = extract_trace_details(:drop_index, column_family, nil, nil)
|
201
|
+
begin
|
202
|
+
report_kvs[:Keyspace] = keyspace.to_s
|
203
|
+
report_kvs[:Column_name] = column_name.to_s
|
204
|
+
rescue => e
|
205
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
206
|
+
end
|
207
|
+
|
208
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
209
|
+
drop_index_without_appoptics(keyspace, column_family, column_name)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def add_column_family_with_appoptics(cf_def)
|
214
|
+
return add_column_family_without_appoptics(cf_def) unless AppOpticsAPM.tracing?
|
215
|
+
|
216
|
+
report_kvs = extract_trace_details(:add_column_family, nil, nil, nil)
|
217
|
+
begin
|
218
|
+
report_kvs[:Cf] = cf_def[:name] if cf_def.is_a?(Hash) && cf_def.key?(:name)
|
219
|
+
rescue => e
|
220
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
|
221
|
+
end
|
222
|
+
|
223
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
224
|
+
add_column_family_without_appoptics(cf_def)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def drop_column_family_with_appoptics(column_family)
|
229
|
+
return drop_column_family_without_appoptics(column_family) unless AppOpticsAPM.tracing?
|
230
|
+
|
231
|
+
report_kvs = extract_trace_details(:drop_column_family, column_family, nil, nil)
|
232
|
+
|
233
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
234
|
+
drop_column_family_without_appoptics(column_family)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def add_keyspace_with_appoptics(ks_def)
|
239
|
+
return add_keyspace_without_appoptics(ks_def) unless AppOpticsAPM.tracing?
|
240
|
+
|
241
|
+
report_kvs = extract_trace_details(:add_keyspace, nil, nil, nil)
|
242
|
+
report_kvs[:Name] = ks_def.name rescue ''
|
243
|
+
|
244
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
245
|
+
add_keyspace_without_appoptics(ks_def)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def drop_keyspace_with_appoptics(keyspace)
|
250
|
+
return drop_keyspace_without_appoptics(keyspace) unless AppOpticsAPM.tracing?
|
251
|
+
|
252
|
+
report_kvs = extract_trace_details(:drop_keyspace, nil, nil, nil)
|
253
|
+
report_kvs[:Name] = keyspace.to_s rescue ''
|
254
|
+
|
255
|
+
AppOpticsAPM::API.trace(:cassandra, report_kvs) do
|
256
|
+
drop_keyspace_without_appoptics(keyspace)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# There are two main Cassandra clients for Ruby. This one from Twitter
|
264
|
+
# and the other from datastax. This one defined Cassandra as a class
|
265
|
+
# and datastax defines it as a module. We use this to detect
|
266
|
+
# and differentiate between the client in use.
|
267
|
+
|
268
|
+
if defined?(Cassandra) && Cassandra.is_a?(Class) && AppOpticsAPM::Config[:cassandra][:enabled]
|
269
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting cassandra' if AppOpticsAPM::Config[:verbose]
|
270
|
+
|
271
|
+
class Cassandra
|
272
|
+
include AppOpticsAPM::Inst::Cassandra
|
273
|
+
|
274
|
+
[:insert, :remove, :count_columns, :get_columns, :multi_get_columns, :get,
|
275
|
+
:multi_get, :get_range_single, :get_range_batch, :get_indexed_slices,
|
276
|
+
:create_index, :drop_index, :add_column_family, :drop_column_family,
|
277
|
+
:add_keyspace, :drop_keyspace].each do |m|
|
278
|
+
if method_defined?(m)
|
279
|
+
class_eval "alias #{m}_without_appoptics #{m}"
|
280
|
+
class_eval "alias #{m} #{m}_with_appoptics"
|
281
|
+
else AppOpticsAPM.logger.warn "[appoptics_apm/loading] Couldn't properly instrument Cassandra (#{m}). Partial traces may occur."
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Special case handler for question mark methods
|
286
|
+
if method_defined?(:exists?)
|
287
|
+
alias exists_without_appoptics? exists?
|
288
|
+
alias exists? exists_with_appoptics?
|
289
|
+
else AppOpticsAPM.logger.warn '[appoptics_apm/loading] Couldn\'t properly instrument Cassandra (exists?). Partial traces may occur.'
|
290
|
+
end
|
291
|
+
end # class Cassandra
|
292
|
+
end
|
293
|
+
|
294
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
class TyphoeusError < StandardError; end
|
4
|
+
|
5
|
+
module AppOpticsAPM
|
6
|
+
module Inst
|
7
|
+
module TyphoeusRequestOps
|
8
|
+
|
9
|
+
def self.included(klass)
|
10
|
+
AppOpticsAPM::Util.method_alias(klass, :run, ::Typhoeus::Request::Operations)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run_with_appoptics
|
14
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(url)
|
15
|
+
unless AppOpticsAPM.tracing?
|
16
|
+
context = AppOpticsAPM::Context.toString
|
17
|
+
options[:headers]['X-Trace'] = context if AppOpticsAPM::XTrace.valid?(context) && !blacklisted
|
18
|
+
return run_without_appoptics
|
19
|
+
end
|
20
|
+
|
21
|
+
begin
|
22
|
+
AppOpticsAPM::API.log_entry(:typhoeus)
|
23
|
+
|
24
|
+
# Prepare X-Trace header handling
|
25
|
+
context = AppOpticsAPM::Context.toString
|
26
|
+
options[:headers]['X-Trace'] = context unless blacklisted
|
27
|
+
|
28
|
+
kvs = {}
|
29
|
+
kvs[:Spec] = 'rsc'
|
30
|
+
kvs[:IsService] = 1
|
31
|
+
kvs[:HTTPMethod] = AppOpticsAPM::Util.upcase(options[:method])
|
32
|
+
|
33
|
+
response = run_without_appoptics
|
34
|
+
|
35
|
+
# Re-attach edge unless it's blacklisted
|
36
|
+
# or if we don't have a valid X-Trace header
|
37
|
+
unless blacklisted
|
38
|
+
xtrace = response.headers['X-Trace']
|
39
|
+
AppOpticsAPM::XTrace.continue_service_context(context, xtrace)
|
40
|
+
end
|
41
|
+
|
42
|
+
if response.code == 0
|
43
|
+
exception = TyphoeusError.new(response.return_message)
|
44
|
+
exception.set_backtrace(AppOpticsAPM::API.backtrace)
|
45
|
+
AppOpticsAPM::API.log_exception(:typhoeus, exception)
|
46
|
+
end
|
47
|
+
|
48
|
+
kvs[:HTTPStatus] = response.code
|
49
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:typhoeus][:collect_backtraces]
|
50
|
+
# Conditionally log query params
|
51
|
+
uri = URI(response.effective_url)
|
52
|
+
kvs[:RemoteURL] = AppOpticsAPM::Config[:typhoeus][:log_args] ? uri.to_s : uri.to_s.split('?').first
|
53
|
+
kvs[:Blacklisted] = true if blacklisted
|
54
|
+
|
55
|
+
response
|
56
|
+
rescue => e
|
57
|
+
AppOpticsAPM::API.log_exception(:typhoeus, e)
|
58
|
+
raise e
|
59
|
+
ensure
|
60
|
+
AppOpticsAPM::API.log_exit(:typhoeus, kvs)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module TyphoeusHydraRunnable
|
66
|
+
def self.included(klass)
|
67
|
+
AppOpticsAPM::Util.method_alias(klass, :run, ::Typhoeus::Hydra)
|
68
|
+
end
|
69
|
+
|
70
|
+
def run_with_appoptics
|
71
|
+
unless AppOpticsAPM.tracing?
|
72
|
+
context = AppOpticsAPM::Context.toString
|
73
|
+
queued_requests.map do |request|
|
74
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(request.base_url)
|
75
|
+
request.options[:headers]['X-Trace'] = context if AppOpticsAPM::XTrace.valid?(context) && !blacklisted
|
76
|
+
end
|
77
|
+
return run_without_appoptics
|
78
|
+
end
|
79
|
+
|
80
|
+
kvs = {}
|
81
|
+
|
82
|
+
kvs[:queued_requests] = queued_requests.count
|
83
|
+
kvs[:max_concurrency] = max_concurrency
|
84
|
+
kvs[:Async] = 1
|
85
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:typhoeus][:collect_backtraces]
|
86
|
+
|
87
|
+
# FIXME: Until we figure out a strategy to deal with libcurl internal
|
88
|
+
# threading and Ethon's use of easy handles, here we just do a simple
|
89
|
+
# trace of the hydra run.
|
90
|
+
AppOpticsAPM::API.trace(:typhoeus_hydra, kvs) do
|
91
|
+
queued_requests.map do |request|
|
92
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(request.base_url)
|
93
|
+
request.options[:headers]['X-Trace'] = AppOpticsAPM::Context.toString unless blacklisted
|
94
|
+
end
|
95
|
+
|
96
|
+
run_without_appoptics
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if defined?(Typhoeus) && AppOpticsAPM::Config[:typhoeus][:enabled]
|
105
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting typhoeus' if AppOpticsAPM::Config[:verbose]
|
106
|
+
AppOpticsAPM::Util.send_include(Typhoeus::Request::Operations, AppOpticsAPM::Inst::TyphoeusRequestOps)
|
107
|
+
AppOpticsAPM::Util.send_include(Typhoeus::Hydra, AppOpticsAPM::Inst::TyphoeusHydraRunnable)
|
108
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
##
|
6
|
+
# The Inst module holds all of the instrumentation extensions for various
|
7
|
+
# libraries such as Redis, Dalli and Resque.
|
8
|
+
module Inst
|
9
|
+
def self.load_instrumentation
|
10
|
+
# Load the general instrumentation
|
11
|
+
pattern = File.join(File.dirname(__FILE__), 'inst', '*.rb')
|
12
|
+
Dir.glob(pattern) do |f|
|
13
|
+
begin
|
14
|
+
require f
|
15
|
+
rescue => e
|
16
|
+
AppOpticsAPM.logger.error "[appoptics_apm/loading] Error loading instrumentation file '#{f}' : #{e}"
|
17
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/loading] #{e.backtrace.first}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require 'digest/sha1'
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
module Util
|
8
|
+
##
|
9
|
+
# This module was used solely for the deprecated RUM ID calculation
|
10
|
+
# but may be useful in the future.
|
11
|
+
#
|
12
|
+
module Base64URL
|
13
|
+
module_function
|
14
|
+
|
15
|
+
def encode(bin)
|
16
|
+
c = [bin].pack('m0').gsub(/\=+\Z/, '').tr('+/', '-_').rstrip
|
17
|
+
m = c.size % 4
|
18
|
+
c += '=' * (4 - m) if m != 0
|
19
|
+
c
|
20
|
+
end
|
21
|
+
|
22
|
+
def decode(bin)
|
23
|
+
m = bin.size % 4
|
24
|
+
bin += '=' * (4 - m) if m != 0
|
25
|
+
bin.tr('-_', '+/').unpack('m0').first
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# This module houses all of the loading functionality for the appoptics_apm em.
|
32
|
+
|
33
|
+
# Note that this does not necessarily _have_ to include initialization routines
|
34
|
+
# (although it can).
|
35
|
+
#
|
36
|
+
# Actual initialization is often separated out as it can be dependent on on the state
|
37
|
+
# of the stack boot process. e.g. code requiring that initializers, frameworks or
|
38
|
+
# instrumented libraries are already loaded...
|
39
|
+
#
|
40
|
+
module Loading
|
41
|
+
##
|
42
|
+
# Load the appoptics_apm tracing API
|
43
|
+
#
|
44
|
+
def self.require_api
|
45
|
+
pattern = File.join(File.dirname(__FILE__), 'api', '*.rb')
|
46
|
+
Dir.glob(pattern) do |f|
|
47
|
+
require f
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
require 'appoptics_apm/api'
|
52
|
+
rescue LoadError => e
|
53
|
+
AppOpticsAPM.logger.fatal "[appoptics_apm/error] Couldn't load api: #{e.message}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
AppOpticsAPM::Loading.require_api
|
60
|
+
|
61
|
+
# Auto-start the Reporter unless we are running Unicorn on Heroku
|
62
|
+
# In that case, we start the reporters after fork
|
63
|
+
unless AppOpticsAPM.heroku? && AppOpticsAPM.forking_webserver?
|
64
|
+
AppOpticsAPM::Reporter.start if AppOpticsAPM.loaded
|
65
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
class << self
|
8
|
+
attr_accessor :logger
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
AppOpticsAPM.logger = Logger.new(STDERR)
|
13
|
+
# set log level to INFO to be consistent with the c-lib, DEBUG would be default
|
14
|
+
AppOpticsAPM.logger.level = Logger::INFO
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Here we can define modules and classes for noop mode.
|
2
|
+
|
3
|
+
Instead of polluting code with AppOpticsAPM.loaded conditionals
|
4
|
+
|
5
|
+
we load these classes when in noop mode and they expose noop behavior.
|
6
|
+
|
7
|
+
so far only one class is needed:
|
8
|
+
|
9
|
+
- AppOpticsAPM::Context and its toString() method from oboe
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright (c) 2019 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
####
|
5
|
+
# noop version of AppOpticsAPM::Context
|
6
|
+
#
|
7
|
+
#
|
8
|
+
|
9
|
+
module AppOpticsAPM
|
10
|
+
module Context
|
11
|
+
|
12
|
+
##
|
13
|
+
# noop version of :toString
|
14
|
+
# toString would return the current context (xtrace) as string
|
15
|
+
#
|
16
|
+
def self.toString
|
17
|
+
'2B0000000000000000000000000000000000000000000000000000000000'
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# noop version of :clear
|
22
|
+
#
|
23
|
+
def self.clear
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright (c) 2019 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
####
|
5
|
+
# noop version of AppOpticsAPM::Metadata
|
6
|
+
#
|
7
|
+
#
|
8
|
+
|
9
|
+
module AppOpticsAPM
|
10
|
+
class Metadata
|
11
|
+
|
12
|
+
##
|
13
|
+
# noop version of :makeRandom
|
14
|
+
#
|
15
|
+
# needs to return an object that responds to :isValid
|
16
|
+
#
|
17
|
+
def self.makeRandom
|
18
|
+
Metadata.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def isValid
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|