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,326 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ ##
6
+ # Provides utility methods for use while in the business
7
+ # of instrumenting code
8
+ module Util
9
+ class << self
10
+ def contextual_name(cls)
11
+ # Attempt to infer a contextual name if not indicated
12
+ #
13
+ # For example:
14
+ # ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.to_s.split(/::/).last
15
+ # => "AbstractMysqlAdapter"
16
+ #
17
+ cls.to_s.split(/::/).last
18
+ rescue
19
+ cls
20
+ end
21
+
22
+ ##
23
+ # method_alias
24
+ #
25
+ # Centralized utility method to alias a method on an arbitrary
26
+ # class or module.
27
+ #
28
+ def method_alias(cls, method, name = nil)
29
+ name ||= contextual_name(cls)
30
+
31
+ if cls.method_defined?(method.to_sym) || cls.private_method_defined?(method.to_sym)
32
+
33
+ # Strip '!' or '?' from method if present
34
+ safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
35
+ safe_method_name ||= method
36
+
37
+ without_appoptics = "#{safe_method_name}_without_appoptics"
38
+ with_appoptics = "#{safe_method_name}_with_appoptics"
39
+
40
+ # Only alias if we haven't done so already
41
+ unless cls.method_defined?(without_appoptics.to_sym) ||
42
+ cls.private_method_defined?(without_appoptics.to_sym)
43
+
44
+ cls.class_eval do
45
+ alias_method without_appoptics, method.to_s
46
+ alias_method method.to_s, with_appoptics
47
+ end
48
+ end
49
+ else
50
+ AppOpticsAPM.logger.warn "[appoptics_apm/loading] Couldn't properly instrument #{name}.#{method}. Partial traces may occur."
51
+ end
52
+ end
53
+
54
+ ##
55
+ # class_method_alias
56
+ #
57
+ # Centralized utility method to alias a class method on an arbitrary
58
+ # class or module
59
+ #
60
+ def class_method_alias(cls, method, name = nil)
61
+ name ||= contextual_name(cls)
62
+
63
+ if cls.singleton_methods.include? method.to_sym
64
+
65
+ # Strip '!' or '?' from method if present
66
+ safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
67
+ safe_method_name ||= method
68
+
69
+ without_appoptics = "#{safe_method_name}_without_appoptics"
70
+ with_appoptics = "#{safe_method_name}_with_appoptics"
71
+
72
+ # Only alias if we haven't done so already
73
+ unless cls.singleton_methods.include? without_appoptics.to_sym
74
+ cls.singleton_class.send(:alias_method, without_appoptics, method.to_s)
75
+ cls.singleton_class.send(:alias_method, method.to_s, with_appoptics)
76
+ end
77
+ else
78
+ AppOpticsAPM.logger.warn "[appoptics_apm/loading] Couldn't properly instrument #{name}. Partial traces may occur."
79
+ end
80
+ end
81
+
82
+ ##
83
+ # send_extend
84
+ #
85
+ # Centralized utility method to send an extend call for an
86
+ # arbitrary class
87
+ def send_extend(target_cls, cls)
88
+ target_cls.send(:extend, cls) if defined?(target_cls)
89
+ end
90
+
91
+ ##
92
+ # send_include
93
+ #
94
+ # Centralized utility method to send a include call for an
95
+ # arbitrary class
96
+ def send_include(target_cls, cls)
97
+ target_cls.send(:include, cls) if defined?(target_cls)
98
+ end
99
+
100
+ ##
101
+ # prettify
102
+ #
103
+ # Even to my surprise, 'prettify' is a real word:
104
+ # transitive v. To make pretty or prettier, especially in a superficial or insubstantial way.
105
+ # from The American Heritage Dictionary of the English Language, 4th Edition
106
+ #
107
+ # This method makes things 'purty' for reporting.
108
+ def prettify(x)
109
+ if (x.to_s =~ /^#</) == 0
110
+ x.class.to_s
111
+ else
112
+ x.to_s
113
+ end
114
+ end
115
+
116
+ ##
117
+ # upcase
118
+ #
119
+ # Occasionally, we want to send some values in all caps. This is true
120
+ # for things like HTTP scheme or method. This takes anything and does
121
+ # it's best to safely convert it to a string (if needed) and convert it
122
+ # to all uppercase.
123
+ def upcase(o)
124
+ if o.is_a?(String) || o.respond_to?(:to_s)
125
+ o.to_s.upcase
126
+ else
127
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] AppOpticsAPM::Util.upcase: could not convert #{o.class}"
128
+ 'UNKNOWN'
129
+ end
130
+ end
131
+
132
+ ##
133
+ # to_query
134
+ #
135
+ # Used to convert a hash into a URL # query.
136
+ #
137
+ def to_query(h)
138
+ return '' unless h.is_a?(Hash)
139
+
140
+ result = []
141
+
142
+ h.each { |k, v| result.push(k.to_s + '=' + v.to_s) }
143
+ result.sort.join('&')
144
+ end
145
+
146
+ ##
147
+ # sanitize_sql
148
+ #
149
+ # Used to remove query literals from SQL. Used by all
150
+ # DB adapter instrumentation.
151
+ #
152
+ # The regular expression passed to String.gsub is configurable
153
+ # via AppOpticsAPM::Config[:sanitize_sql_regexp] and
154
+ # AppOpticsAPM::Config[:sanitize_sql_opts].
155
+ #
156
+ def sanitize_sql(sql)
157
+ return sql unless AppOpticsAPM::Config[:sanitize_sql]
158
+
159
+ regexp = Regexp.new(AppOpticsAPM::Config[:sanitize_sql_regexp], AppOpticsAPM::Config[:sanitize_sql_opts])
160
+ sql.gsub(/\\\'/,'').gsub(regexp, '?')
161
+ end
162
+
163
+ ##
164
+ # deep_dup
165
+ #
166
+ # deep duplicate of array or hash
167
+ #
168
+ def deep_dup(obj)
169
+ if obj.is_a? Array
170
+ new_obj = []
171
+ obj.each do |v|
172
+ new_obj << deep_dup(v)
173
+ end
174
+ elsif obj.is_a? Hash
175
+ new_obj = {}
176
+ obj.each_pair do |key, value|
177
+ new_obj[key] = deep_dup(value)
178
+ end
179
+ end
180
+ end
181
+
182
+ ##
183
+ # legacy_build_init_report
184
+ #
185
+ # Internal: Build a hash of KVs that reports on the status of the
186
+ # running environment. This is used on stack boot in __Init reporting
187
+ # and for AppOpticsAPM.support_report.
188
+ #
189
+ # This legacy version of build_init_report is used for apps without Bundler.
190
+ #
191
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
192
+ #
193
+ # @deprecated Please use {#build_init_report} instead
194
+ def legacy_build_init_report
195
+ AppOpticsAPM.logger.warn '[appoptics_apm/deprecated] Oboe::API will be deprecated in a future version.'
196
+ platform_info = {}
197
+
198
+ begin
199
+ # Report the framework in use
200
+ if defined?(::RailsLts::VERSION)
201
+ platform_info['Ruby.RailsLts.Version'] = "RailsLts-#{::RailsLts::VERSION}"
202
+ elsif defined?(::Rails.version)
203
+ platform_info['Ruby.Rails.Version'] = "Rails-#{::Rails.version}"
204
+ end
205
+ platform_info['Ruby.Grape.Version'] = "Grape-#{::Grape::VERSION}" if defined?(::Grape::VERSION)
206
+ platform_info['Ruby.Cramp.Version'] = "Cramp-#{::Cramp::VERSION}" if defined?(::Cramp::VERSION)
207
+
208
+ if defined?(::Padrino::VERSION)
209
+ platform_info['Ruby.Padrino.Version'] = "Padrino-#{::Padrino::VERSION}"
210
+ elsif defined?(::Sinatra::VERSION)
211
+ platform_info['Ruby.Sinatra.Version'] = "Sinatra-#{::Sinatra::VERSION}"
212
+ end
213
+
214
+ # Report the instrumented libraries
215
+ platform_info['Ruby.Cassandra.Version'] = "Cassandra-#{::Cassandra.VERSION}" if defined?(::Cassandra.VERSION)
216
+ platform_info['Ruby.Curb.Version'] = "Curb-#{::Curl::VERSION}" if defined?(::Curl::VERSION)
217
+ platform_info['Ruby.Dalli.Version'] = "Dalli-#{::Dalli::VERSION}" if defined?(::Dalli::VERSION)
218
+ platform_info['Ruby.Excon.Version'] = "Excon-#{::Excon::VERSION}" if defined?(::Excon::VERSION)
219
+ platform_info['Ruby.Faraday.Version'] = "Faraday-#{::Faraday::VERSION}" if defined?(::Faraday::VERSION)
220
+ platform_info['Ruby.HTTPClient.Version'] = "HTTPClient-#{::HTTPClient::VERSION}" if defined?(::HTTPClient::VERSION)
221
+ platform_info['Ruby.Memcached.Version'] = "Memcached-#{::Memcached::VERSION}" if defined?(::Memcached::VERSION)
222
+ platform_info['Ruby.Moped.Version'] = "Moped-#{::Moped::VERSION}" if defined?(::Moped::VERSION)
223
+ platform_info['Ruby.Redis.Version'] = "Redis-#{::Redis::VERSION}" if defined?(::Redis::VERSION)
224
+ platform_info['Ruby.Resque.Version'] = "Resque-#{::Resque::VERSION}" if defined?(::Resque::VERSION)
225
+ platform_info['Ruby.RestClient.Version'] = "RestClient-#{::RestClient::VERSION}" if defined?(::RestClient::VERSION)
226
+ platform_info['Ruby.Sidekiq.Version'] = "Sidekiq-#{::Sidekiq::VERSION}" if defined?(::Sidekiq::VERSION)
227
+ platform_info['Ruby.Typhoeus.Version'] = "Typhoeus-#{::Typhoeus::VERSION}" if defined?(::Typhoeus::VERSION)
228
+
229
+ if Gem.loaded_specs.key?('delayed_job')
230
+ # Oddly, DelayedJob doesn't have an embedded version number so we get it from the loaded
231
+ # gem specs.
232
+ version = Gem.loaded_specs['delayed_job'].version.to_s
233
+ platform_info['Ruby.DelayedJob.Version'] = "DelayedJob-#{version}"
234
+ end
235
+
236
+ # Special case since the Mongo 1.x driver doesn't embed the version number in the gem directly
237
+ if ::Gem.loaded_specs.key?('mongo')
238
+ platform_info['Ruby.Mongo.Version'] = "Mongo-#{::Gem.loaded_specs['mongo'].version}"
239
+ end
240
+
241
+ # Report the DB adapter in use
242
+ platform_info['Ruby.Mysql.Version'] = Mysql::GemVersion::VERSION if defined?(Mysql::GemVersion::VERSION)
243
+ platform_info['Ruby.PG.Version'] = PG::VERSION if defined?(PG::VERSION)
244
+ platform_info['Ruby.Mysql2.Version'] = Mysql2::VERSION if defined?(Mysql2::VERSION)
245
+ platform_info['Ruby.Sequel.Version'] = ::Sequel::VERSION if defined?(::Sequel::VERSION)
246
+ rescue StandardError, ScriptError => e
247
+ # Also rescue ScriptError (aka SyntaxError) in case one of the expected
248
+ # version defines don't exist
249
+
250
+ platform_info['Error'] = "Error in legacy_build_init_report: #{e.message}"
251
+
252
+ AppOpticsAPM.logger.warn "[appoptics_apm/legacy] Error in legacy_build_init_report: #{e.message}"
253
+ AppOpticsAPM.logger.debug e.backtrace
254
+ end
255
+ platform_info
256
+ end
257
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
258
+
259
+ ##
260
+ # build_init_report
261
+ #
262
+ # Internal: Build a hash of KVs that reports on the status of the
263
+ # running environment. This is used on stack boot in __Init reporting
264
+ # and for AppOpticsAPM.support_report.
265
+ #
266
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
267
+ def build_init_report
268
+ platform_info = { '__Init' => 1 }
269
+
270
+ begin
271
+ platform_info['Force'] = true
272
+ platform_info['Ruby.Platform.Version'] = RUBY_PLATFORM
273
+ platform_info['Ruby.Version'] = RUBY_VERSION
274
+ platform_info['Ruby.AppOptics.Version'] = AppOpticsAPM::Version::STRING
275
+
276
+ # oboe not loaded yet, can't use oboe_api function to read oboe VERSION
277
+ clib_version_file = File.join(Gem::Specification.find_by_name('appoptics_apm').gem_dir, 'ext', 'oboe_metal', 'src', 'VERSION')
278
+ platform_info['Ruby.AppOpticsExtension.Version'] = File.read(clib_version_file).strip
279
+ platform_info['RubyHeroku.AppOpticsAPM.Version'] = AppOpticsAPMHeroku::Version::STRING if defined?(AppOpticsAPMHeroku)
280
+ platform_info['Ruby.TraceMode.Version'] = AppOpticsAPM::Config[:tracing_mode]
281
+
282
+ # Collect up the loaded gems
283
+ if defined?(Gem) && Gem.respond_to?(:loaded_specs)
284
+ Gem.loaded_specs.each_pair { |k, v|
285
+ platform_info["Ruby.#{k}.Version"] = v.version.to_s
286
+ }
287
+ else
288
+ platform_info.merge!(legacy_build_init_report)
289
+ end
290
+
291
+ # Report the server in use (if possible)
292
+ if defined?(::Unicorn::Const::UNICORN_VERSION)
293
+ platform_info['Ruby.AppContainer.Version'] = "Unicorn-#{::Unicorn::Const::UNICORN_VERSION}"
294
+ elsif defined?(::Puma::Const::PUMA_VERSION)
295
+ platform_info['Ruby.AppContainer.Version'] = "Puma-#{::Puma::Const::PUMA_VERSION} (#{::Puma::Const::CODE_NAME})"
296
+ elsif defined?(::PhusionPassenger::PACKAGE_NAME)
297
+ platform_info['Ruby.AppContainer.Version'] = "#{::PhusionPassenger::PACKAGE_NAME}-#{::PhusionPassenger::VERSION_STRING}"
298
+ elsif defined?(::Thin::VERSION::STRING)
299
+ platform_info['Ruby.AppContainer.Version'] = "Thin-#{::Thin::VERSION::STRING} (#{::Thin::VERSION::CODENAME})"
300
+ elsif defined?(::Mongrel::Const::MONGREL_VERSION)
301
+ platform_info['Ruby.AppContainer.Version'] = "Mongrel-#{::Mongrel::Const::MONGREL_VERSION}"
302
+ elsif defined?(::Mongrel2::VERSION)
303
+ platform_info['Ruby.AppContainer.Version'] = "Mongrel2-#{::Mongrel2::VERSION}"
304
+ elsif defined?(::Trinidad::VERSION)
305
+ platform_info['Ruby.AppContainer.Version'] = "Trinidad-#{::Trinidad::VERSION}"
306
+ elsif defined?(::WEBrick::VERSION)
307
+ platform_info['Ruby.AppContainer.Version'] = "WEBrick-#{::WEBrick::VERSION}"
308
+ else
309
+ platform_info['Ruby.AppContainer.Version'] = File.basename($PROGRAM_NAME)
310
+ end
311
+
312
+ rescue StandardError, ScriptError => e
313
+ # Also rescue ScriptError (aka SyntaxError) in case one of the expected
314
+ # version defines don't exist
315
+
316
+ platform_info['Error'] = "Error in build_report: #{e.message}"
317
+
318
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Error in build_init_report: #{e.message}"
319
+ AppOpticsAPM.logger.debug e.backtrace
320
+ end
321
+ platform_info
322
+ end
323
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
324
+ end
325
+ end
326
+ end
@@ -0,0 +1,16 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ ##
6
+ # The current version of the gem. Used mainly by
7
+ # appoptics_apm.gemspec during gem build process
8
+ module Version
9
+ MAJOR = 4 # breaking,
10
+ MINOR = 13 # feature,
11
+ PATCH = 1 # fix => BFF
12
+ PRE = nil
13
+
14
+ STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
15
+ end
16
+ end
@@ -0,0 +1,115 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ ##
6
+ # Methods to act on, manipulate or investigate an X-Trace
7
+ # value
8
+ #
9
+ # TODO add unit tests
10
+ class XTrace
11
+ class << self
12
+ ##
13
+ # AppOpticsAPM::XTrace.valid?
14
+ #
15
+ # Perform basic validation on a potential X-Trace Id
16
+ # returns true if it is from a valid context
17
+ #
18
+ def valid?(xtrace)
19
+ # Shouldn't be nil
20
+ return false unless xtrace
21
+
22
+ # The X-Trace ID shouldn't be an initialized empty ID
23
+ return false if (xtrace =~ /^2b0000000/i) == 0
24
+
25
+ # Valid X-Trace IDs have a length of 60 bytes and start with '2b'
26
+ xtrace.length == 60 && (xtrace =~ /^2b/i) == 0
27
+ rescue StandardError => e
28
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
29
+ AppOpticsAPM.logger.debug e.backtrace
30
+ false
31
+ end
32
+
33
+ def sampled?(xtrace)
34
+ valid?(xtrace) && xtrace[59].to_i & 1 == 1
35
+ end
36
+
37
+ def ok?(xtrace)
38
+ # Valid X-Trace IDs have a length of 60 bytes and start with '2b'
39
+ xtrace && xtrace.length == 60 && (xtrace =~ /^2b/i) == 0
40
+ rescue StandardError => e
41
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
42
+ AppOpticsAPM.logger.debug e.backtrace
43
+ false
44
+ end
45
+
46
+ def set_sampled(xtrace)
47
+ xtrace[59] = (xtrace[59].hex | 1).to_s(16).upcase
48
+ xtrace
49
+ end
50
+
51
+ def unset_sampled(xtrace)
52
+ xtrace[59] = (~(~xtrace[59].hex | 1)).to_s(16).upcase
53
+ xtrace
54
+ end
55
+
56
+ ##
57
+ # AppOpticsAPM::XTrace.task_id
58
+ #
59
+ # Extract and return the task_id portion of an X-Trace ID
60
+ #
61
+ def task_id(xtrace)
62
+ return nil unless ok?(xtrace)
63
+
64
+ xtrace[2..41]
65
+ rescue StandardError => e
66
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
67
+ AppOpticsAPM.logger.debug e.backtrace
68
+ return nil
69
+ end
70
+
71
+ ##
72
+ # AppOpticsAPM::XTrace.edge_id
73
+ #
74
+ # Extract and return the edge_id portion of an X-Trace ID
75
+ #
76
+ def edge_id(xtrace)
77
+ return nil unless AppOpticsAPM::XTrace.valid?(xtrace)
78
+
79
+ xtrace[42..57]
80
+ rescue StandardError => e
81
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
82
+ AppOpticsAPM.logger.debug e.backtrace
83
+ return nil
84
+ end
85
+
86
+ ##
87
+ # continue_service_context
88
+ #
89
+ # In the case of service calls such as external HTTP requests, we
90
+ # pass along X-Trace headers so that request context can be maintained
91
+ # across servers and applications.
92
+ #
93
+ # Remote requests can return a X-Trace header in which case we want
94
+ # to pickup and continue the context in most cases.
95
+ #
96
+ # +start+ is the context just before the outgoing request
97
+ # +finish+ is the context returned to us (as an HTTP response header
98
+ # if that be the case)
99
+ #
100
+ def continue_service_context(start_xtrace, end_xtrace)
101
+ if AppOpticsAPM::XTrace.valid?(end_xtrace) && AppOpticsAPM.tracing?
102
+
103
+ # Make sure that we received back a valid X-Trace with the same task_id
104
+ # and the sampling bit is set, otherwise it is a response from a non-sampling service
105
+ if AppOpticsAPM::XTrace.task_id(start_xtrace) == AppOpticsAPM::XTrace.task_id(end_xtrace) &&
106
+ AppOpticsAPM::XTrace.sampled?(end_xtrace)
107
+ AppOpticsAPM::Context.fromString(end_xtrace)
108
+ else
109
+ AppOpticsAPM.logger.debug "[XTrace] Sampling flag unset or mismatched start and finish ids:\n#{start_xtrace}\n#{end_xtrace}"
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,77 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ begin
5
+ require 'openssl'
6
+ require 'appoptics_apm/version'
7
+ require 'appoptics_apm/thread_local'
8
+ require 'appoptics_apm/logger'
9
+ require 'appoptics_apm/util'
10
+ require 'appoptics_apm/xtrace'
11
+ require 'appoptics_apm/support_report'
12
+ require 'appoptics_apm/base'
13
+ AppOpticsAPM.loaded = false
14
+
15
+ require 'appoptics_apm/config'
16
+ AppOpticsAPM::Config.load_config_file
17
+
18
+ begin
19
+ if RUBY_PLATFORM == 'java'
20
+ require '/usr/local/tracelytics/tracelyticsagent.jar'
21
+ require 'joboe_metal'
22
+ elsif RUBY_PLATFORM =~ /linux/
23
+ require_relative './libappoptics_apm.so'
24
+ require 'appoptics_apm/oboe_init_options'
25
+ require 'oboe_metal.rb' # sets AppOpticsAPM.loaded = true if successful
26
+ else
27
+ AppOpticsAPM.logger.warn '==================================================================='
28
+ AppOpticsAPM.logger.warn "AppOptics warning: Platform #{RUBY_PLATFORM} not yet supported."
29
+ AppOpticsAPM.logger.warn 'see: https://docs.appoptics.com/kb/apm_tracing/supported_platforms/'
30
+ AppOpticsAPM.logger.warn 'Tracing disabled.'
31
+ AppOpticsAPM.logger.warn 'Contact technicalsupport@solarwinds.com if this is unexpected.'
32
+ AppOpticsAPM.logger.warn '==================================================================='
33
+ end
34
+ rescue LoadError => e
35
+ unless ENV['RAILS_GROUP'] == 'assets' or ENV['IGNORE_APPOPTICS_WARNING']
36
+ AppOpticsAPM.logger.error '=============================================================='
37
+ AppOpticsAPM.logger.error 'Missing AppOpticsAPM libraries. Tracing disabled.'
38
+ AppOpticsAPM.logger.error "Error: #{e.message}"
39
+ AppOpticsAPM.logger.error 'See: https://docs.appoptics.com/kb/apm_tracing/ruby/'
40
+ AppOpticsAPM.logger.error '=============================================================='
41
+ end
42
+ end
43
+
44
+ # appoptics_apm/loading can set AppOpticsAPM.loaded = false if the service key is not working
45
+ require 'appoptics_apm/loading'
46
+
47
+ if AppOpticsAPM.loaded
48
+ require 'appoptics_apm/instrumentation'
49
+ require 'appoptics_apm/support/profiling'
50
+ require 'appoptics_apm/support/transaction_metrics'
51
+ require 'appoptics_apm/support/x_trace_options'
52
+
53
+ # Frameworks
54
+ require 'appoptics_apm/frameworks/rails'
55
+ require 'appoptics_apm/frameworks/sinatra'
56
+ require 'appoptics_apm/frameworks/padrino'
57
+ require 'appoptics_apm/frameworks/grape'
58
+ else
59
+ AppOpticsAPM.logger.warn '=============================================================='
60
+ AppOpticsAPM.logger.warn 'AppOpticsAPM not loaded. Tracing disabled.'
61
+ AppOpticsAPM.logger.warn 'There may be a problem with the service key or other settings.'
62
+ AppOpticsAPM.logger.warn 'Please check previous log messages.'
63
+ AppOpticsAPM.logger.warn '=============================================================='
64
+ require 'appoptics_apm/noop/context'
65
+ require 'appoptics_apm/noop/metadata'
66
+ require 'appoptics_apm/noop/profiling'
67
+ end
68
+
69
+ # Load Ruby module last. If there is no framework detected,
70
+ # it will load all of the Ruby instrumentation
71
+ require 'appoptics_apm/ruby'
72
+
73
+ require 'appoptics_apm/test' if ENV['APPOPTICS_GEM_TEST']
74
+ rescue => e
75
+ $stderr.puts "[appoptics_apm/error] Problem loading: #{e.inspect}"
76
+ $stderr.puts e.backtrace
77
+ end