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.
Files changed (145) 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/.github/workflows/build_and_release_gem.yml +103 -0
  5. data/.github/workflows/build_for_packagecloud.yml +70 -0
  6. data/.github/workflows/docker-images.yml +47 -0
  7. data/.github/workflows/run_cpluplus_tests.yml +73 -0
  8. data/.github/workflows/run_tests.yml +168 -0
  9. data/.github/workflows/scripts/test_install.rb +23 -0
  10. data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
  11. data/.github/workflows/test_on_4_linux.yml +159 -0
  12. data/.gitignore +36 -0
  13. data/.rubocop.yml +29 -0
  14. data/.travis.yml +130 -0
  15. data/.yardopts +6 -0
  16. data/CHANGELOG.md +769 -0
  17. data/CONFIG.md +33 -0
  18. data/Gemfile +14 -0
  19. data/LICENSE +202 -0
  20. data/README.md +393 -0
  21. data/appoptics_apm.gemspec +70 -0
  22. data/bin/appoptics_apm_config +15 -0
  23. data/examples/prepend.rb +13 -0
  24. data/examples/sdk_examples.rb +158 -0
  25. data/ext/oboe_metal/README.md +69 -0
  26. data/ext/oboe_metal/extconf.rb +151 -0
  27. data/ext/oboe_metal/lib/.keep +0 -0
  28. data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
  29. data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
  30. data/ext/oboe_metal/noop/noop.c +8 -0
  31. data/ext/oboe_metal/src/README.md +6 -0
  32. data/ext/oboe_metal/src/VERSION +2 -0
  33. data/ext/oboe_metal/src/bson/bson.h +220 -0
  34. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  35. data/ext/oboe_metal/src/frames.cc +246 -0
  36. data/ext/oboe_metal/src/frames.h +40 -0
  37. data/ext/oboe_metal/src/init_appoptics_apm.cc +21 -0
  38. data/ext/oboe_metal/src/logging.cc +95 -0
  39. data/ext/oboe_metal/src/logging.h +35 -0
  40. data/ext/oboe_metal/src/oboe.h +1156 -0
  41. data/ext/oboe_metal/src/oboe_api.cpp +652 -0
  42. data/ext/oboe_metal/src/oboe_api.hpp +431 -0
  43. data/ext/oboe_metal/src/oboe_debug.h +59 -0
  44. data/ext/oboe_metal/src/oboe_swig_wrap.cc +7329 -0
  45. data/ext/oboe_metal/src/profiling.cc +435 -0
  46. data/ext/oboe_metal/src/profiling.h +78 -0
  47. data/ext/oboe_metal/test/CMakeLists.txt +53 -0
  48. data/ext/oboe_metal/test/FindGMock.cmake +43 -0
  49. data/ext/oboe_metal/test/README.md +56 -0
  50. data/ext/oboe_metal/test/frames_test.cc +164 -0
  51. data/ext/oboe_metal/test/profiling_test.cc +93 -0
  52. data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
  53. data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
  54. data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
  55. data/ext/oboe_metal/test/test.h +11 -0
  56. data/ext/oboe_metal/test/test_main.cc +32 -0
  57. data/init.rb +4 -0
  58. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  59. data/lib/appoptics_apm/api/logging.rb +381 -0
  60. data/lib/appoptics_apm/api/memcache.rb +37 -0
  61. data/lib/appoptics_apm/api/metrics.rb +63 -0
  62. data/lib/appoptics_apm/api/tracing.rb +57 -0
  63. data/lib/appoptics_apm/api/util.rb +120 -0
  64. data/lib/appoptics_apm/api.rb +21 -0
  65. data/lib/appoptics_apm/base.rb +231 -0
  66. data/lib/appoptics_apm/config.rb +299 -0
  67. data/lib/appoptics_apm/frameworks/grape.rb +98 -0
  68. data/lib/appoptics_apm/frameworks/padrino.rb +78 -0
  69. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  70. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  71. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  72. data/lib/appoptics_apm/frameworks/rails/inst/action_controller6.rb +50 -0
  73. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  74. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +88 -0
  75. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  76. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  77. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  78. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  79. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  80. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +114 -0
  81. data/lib/appoptics_apm/frameworks/rails/inst/logger_formatters.rb +27 -0
  82. data/lib/appoptics_apm/frameworks/rails.rb +100 -0
  83. data/lib/appoptics_apm/frameworks/sinatra.rb +96 -0
  84. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  85. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  86. data/lib/appoptics_apm/inst/curb.rb +332 -0
  87. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  88. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  89. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  90. data/lib/appoptics_apm/inst/excon.rb +125 -0
  91. data/lib/appoptics_apm/inst/faraday.rb +106 -0
  92. data/lib/appoptics_apm/inst/graphql.rb +240 -0
  93. data/lib/appoptics_apm/inst/grpc_client.rb +159 -0
  94. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  95. data/lib/appoptics_apm/inst/http.rb +81 -0
  96. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  97. data/lib/appoptics_apm/inst/logger_formatter.rb +50 -0
  98. data/lib/appoptics_apm/inst/logging_log_event.rb +28 -0
  99. data/lib/appoptics_apm/inst/lumberjack_formatter.rb +13 -0
  100. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  101. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  102. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  103. data/lib/appoptics_apm/inst/moped.rb +466 -0
  104. data/lib/appoptics_apm/inst/rack.rb +182 -0
  105. data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
  106. data/lib/appoptics_apm/inst/redis.rb +274 -0
  107. data/lib/appoptics_apm/inst/resque.rb +151 -0
  108. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  109. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  110. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  111. data/lib/appoptics_apm/inst/sidekiq-worker.rb +66 -0
  112. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  113. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  114. data/lib/appoptics_apm/instrumentation.rb +22 -0
  115. data/lib/appoptics_apm/loading.rb +65 -0
  116. data/lib/appoptics_apm/logger.rb +14 -0
  117. data/lib/appoptics_apm/noop/README.md +9 -0
  118. data/lib/appoptics_apm/noop/context.rb +27 -0
  119. data/lib/appoptics_apm/noop/metadata.rb +25 -0
  120. data/lib/appoptics_apm/noop/profiling.rb +21 -0
  121. data/lib/appoptics_apm/oboe_init_options.rb +211 -0
  122. data/lib/appoptics_apm/ruby.rb +35 -0
  123. data/lib/appoptics_apm/sdk/current_trace.rb +77 -0
  124. data/lib/appoptics_apm/sdk/custom_metrics.rb +94 -0
  125. data/lib/appoptics_apm/sdk/logging.rb +37 -0
  126. data/lib/appoptics_apm/sdk/tracing.rb +434 -0
  127. data/lib/appoptics_apm/support/profiling.rb +18 -0
  128. data/lib/appoptics_apm/support/transaction_metrics.rb +67 -0
  129. data/lib/appoptics_apm/support/transaction_settings.rb +219 -0
  130. data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
  131. data/lib/appoptics_apm/support_report.rb +119 -0
  132. data/lib/appoptics_apm/test.rb +95 -0
  133. data/lib/appoptics_apm/thread_local.rb +26 -0
  134. data/lib/appoptics_apm/util.rb +326 -0
  135. data/lib/appoptics_apm/version.rb +16 -0
  136. data/lib/appoptics_apm/xtrace.rb +115 -0
  137. data/lib/appoptics_apm.rb +77 -0
  138. data/lib/joboe_metal.rb +212 -0
  139. data/lib/oboe.rb +7 -0
  140. data/lib/oboe_metal.rb +172 -0
  141. data/lib/rails/generators/appoptics_apm/install_generator.rb +47 -0
  142. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +425 -0
  143. data/log/.keep +0 -0
  144. data/yardoc_frontpage.md +26 -0
  145. 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