appoptics_apm 4.8.4 → 4.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +7 -1
  3. data/.rubocop.yml +27 -6
  4. data/.travis.yml +24 -37
  5. data/.travis/bundle.sh +9 -0
  6. data/CONFIG.md +1 -1
  7. data/Gemfile +6 -6
  8. data/appoptics_apm.gemspec +6 -2
  9. data/examples/SDK/01_basic_tracing.rb +1 -1
  10. data/ext/oboe_metal/extconf.rb +6 -2
  11. data/ext/oboe_metal/noop/noop.c +2 -1
  12. data/ext/oboe_metal/src/VERSION +1 -1
  13. data/lib/appoptics_apm.rb +1 -3
  14. data/lib/appoptics_apm/api.rb +0 -1
  15. data/lib/appoptics_apm/api/logging.rb +6 -2
  16. data/lib/appoptics_apm/api/tracing.rb +4 -0
  17. data/lib/appoptics_apm/api/util.rb +5 -7
  18. data/lib/appoptics_apm/config.rb +16 -5
  19. data/lib/appoptics_apm/frameworks/grape.rb +3 -2
  20. data/lib/appoptics_apm/frameworks/padrino.rb +7 -37
  21. data/lib/appoptics_apm/frameworks/rails.rb +0 -1
  22. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +1 -1
  23. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +12 -25
  24. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +1 -1
  25. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +1 -1
  26. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +1 -1
  27. data/lib/appoptics_apm/frameworks/sinatra.rb +4 -33
  28. data/lib/appoptics_apm/inst/curb.rb +6 -6
  29. data/lib/appoptics_apm/inst/faraday.rb +16 -4
  30. data/lib/appoptics_apm/inst/graphql.rb +240 -0
  31. data/lib/appoptics_apm/inst/grpc_client.rb +1 -1
  32. data/lib/appoptics_apm/inst/rack.rb +11 -11
  33. data/lib/appoptics_apm/oboe_init_options.rb +13 -3
  34. data/lib/appoptics_apm/sdk/custom_metrics.rb +2 -0
  35. data/lib/appoptics_apm/sdk/logging.rb +1 -1
  36. data/lib/appoptics_apm/sdk/tracing.rb +120 -2
  37. data/lib/appoptics_apm/support/transaction_metrics.rb +2 -1
  38. data/lib/appoptics_apm/support/transaction_settings.rb +40 -15
  39. data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
  40. data/lib/appoptics_apm/version.rb +2 -2
  41. data/lib/appoptics_apm/xtrace.rb +7 -7
  42. data/lib/oboe_metal.rb +1 -1
  43. data/lib/rails/generators/appoptics_apm/install_generator.rb +23 -21
  44. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +68 -30
  45. metadata +40 -21
  46. data/Rakefile +0 -234
  47. data/build_gem.sh +0 -15
  48. data/build_gem_upload_to_packagecloud.sh +0 -15
  49. data/lib/appoptics_apm/api/profiling.rb +0 -203
  50. data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +0 -55
  51. data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +0 -50
  52. data/lib/appoptics_apm/legacy_method_profiling.rb +0 -90
  53. data/lib/appoptics_apm/method_profiling.rb +0 -33
  54. data/lib/oboe/README +0 -2
  55. data/lib/oboe/backward_compatibility.rb +0 -80
  56. data/lib/oboe/inst/rack.rb +0 -11
data/Rakefile DELETED
@@ -1,234 +0,0 @@
1
- #!/usr/bin/env rake
2
-
3
- require 'rubygems'
4
- require 'fileutils'
5
- require 'open-uri'
6
- require 'bundler/setup'
7
- require 'rake/testtask'
8
- require 'appoptics_apm/test'
9
-
10
- Rake::TestTask.new do |t|
11
- t.verbose = false
12
- t.warning = false
13
- t.ruby_opts = []
14
- t.libs << 'test'
15
-
16
- # Since we support so many libraries and frameworks, tests
17
- # runs are segmented into gemfiles that have different
18
- # sets and versions of gems (libraries and frameworks).
19
- #
20
- # Here we detect the Gemfile the tests are being run against
21
- # and load the appropriate tests.
22
- #
23
- case AppOpticsAPM::Test.gemfile
24
- when /delayed_job/
25
- require 'delayed/tasks'
26
- t.test_files = FileList['test/queues/delayed_job*_test.rb']
27
- when /rails/
28
- # Pre-load rails to get the major version number
29
- require 'rails'
30
-
31
- if Rails::VERSION::MAJOR == 5
32
- t.test_files = FileList["test/frameworks/rails#{Rails::VERSION::MAJOR}x_test.rb"] +
33
- FileList["test/frameworks/rails#{Rails::VERSION::MAJOR}x_api_test.rb"]
34
- elsif Rails::VERSION::MAJOR == 6
35
- t.test_files = FileList["test/frameworks/rails5x_test.rb"] +
36
- FileList["test/frameworks/rails5x_api_test.rb"]
37
- else
38
- t.test_files = FileList["test/frameworks/rails#{Rails::VERSION::MAJOR}x_test.rb"]
39
- end
40
-
41
- when /frameworks/
42
- t.test_files = FileList['test/frameworks/sinatra*_test.rb'] +
43
- FileList['test/frameworks/padrino*_test.rb'] +
44
- FileList['test/frameworks/grape*_test.rb']
45
- when /libraries/
46
- t.test_files = FileList['test/support/*_test.rb'] +
47
- FileList['test/reporter/*_test.rb'] +
48
- FileList['test/instrumentation/*_test.rb'] +
49
- FileList['test/profiling/*_test.rb'] -
50
- ['test/instrumentation/twitter-cassandra_test.rb']
51
- when /instrumentation_mocked/
52
- # WebMock is interfering with other tests, so these have to run separately
53
- t.test_files = FileList['test/mocked/*_test.rb']
54
- when /noop/
55
- t.test_files = FileList['test/noop/*_test.rb']
56
- when /unit/
57
- t.test_files = FileList['test/unit/*_test.rb'] +
58
- FileList['test/unit/*/*_test.rb']
59
- end
60
-
61
- if defined?(JRUBY_VERSION)
62
- t.ruby_opts << ['-J-javaagent:/usr/local/tracelytics/tracelyticsagent.jar']
63
- end
64
- end
65
-
66
- desc "Run all test suites defined by travis"
67
- task "docker_tests" do
68
- Dir.chdir('test/run_tests')
69
- exec('docker-compose run --rm ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh test --remove-orphans')
70
- end
71
-
72
- desc "Start docker container for testing and debugging"
73
- task "docker" do
74
- Dir.chdir('test/run_tests')
75
- exec('docker-compose run --rm ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh bash --remove-orphans')
76
- end
77
-
78
- desc "Stop all containers that were started for testing and debugging"
79
- task "docker_down" do
80
- Dir.chdir('test/run_tests')
81
- exec('docker-compose down')
82
- end
83
-
84
- desc "Fetch extension dependency files"
85
- task :fetch_ext_deps do
86
- swig_version = %x{swig -version} rescue ''
87
- swig_version = swig_version.scan(/swig version [34]/i)
88
- if swig_version.empty?
89
- $stderr.puts '== ERROR ================================================================='
90
- $stderr.puts "Could not find required swig version >= 3.0.8, found #{swig_version.inspect}"
91
- $stderr.puts 'Please install swig ">= 3.0.8" and try again.'
92
- $stderr.puts '=========================================================================='
93
- raise
94
- end
95
-
96
- # The c-lib version is different from the gem version
97
- oboe_version = ENV['OBOE_VERSION'] || 'latest'
98
- oboe_s3_dir = "https://s3-us-west-2.amazonaws.com/rc-files-t2/c-lib/#{oboe_version}"
99
- ext_src_dir = File.expand_path('ext/oboe_metal/src')
100
-
101
- # VERSION is used by extconf.rb to download the correct liboboe when installing the gem
102
- remote_file = File.join(oboe_s3_dir, 'VERSION')
103
- local_file = File.join(ext_src_dir, 'VERSION')
104
- puts "fetching #{remote_file} to #{local_file}"
105
- open(remote_file, 'rb') do |rf|
106
- content = rf.read
107
- File.open(local_file, 'wb') { |f| f.puts content }
108
- puts "!!!!!!! C-Lib VERSION: #{content.strip} !!!!!!!!"
109
- end
110
-
111
- # oboe and bson header files
112
- FileUtils.mkdir_p(File.join(ext_src_dir, 'bson'))
113
- %w(oboe.h oboe.hpp oboe_debug.h oboe.i bson/bson.h bson/platform_hacks.h).each do |filename|
114
- # %w(oboe.h oboe_debug.h bson/bson.h bson/platform_hacks.h).each do |filename|
115
- remote_file = File.join(oboe_s3_dir, 'include', filename)
116
- local_file = File.join(ext_src_dir, filename)
117
-
118
- puts "fetching #{remote_file} to #{local_file}"
119
- open(remote_file, 'rb') do |rf|
120
- content = rf.read
121
- File.open(local_file, 'wb') { |f| f.puts content }
122
- end
123
- end
124
-
125
- FileUtils.cd(ext_src_dir) do
126
- system('swig -c++ -ruby -module oboe_metal oboe.i')
127
- FileUtils.rm('oboe.i')
128
- end
129
- end
130
-
131
- task :fetch => :fetch_ext_deps
132
-
133
- desc "Build the gem's c extension"
134
- task :compile do
135
- if !defined?(JRUBY_VERSION)
136
- puts "== Building the c extension against Ruby #{RUBY_VERSION}"
137
-
138
- pwd = Dir.pwd
139
- ext_dir = File.expand_path('ext/oboe_metal')
140
- final_so = File.expand_path('lib/oboe_metal.so')
141
- so_file = File.expand_path('ext/oboe_metal/oboe_metal.so')
142
-
143
- Dir.chdir ext_dir
144
- ENV['APPOPTICS_FROM_S3'] = 'true'
145
- cmd = [Gem.ruby, 'extconf.rb']
146
- sh cmd.join(' ')
147
- sh '/usr/bin/env make'
148
-
149
- File.delete(final_so) if File.exist?(final_so)
150
-
151
- if File.exist?(so_file)
152
- FileUtils.mv(so_file, final_so)
153
- Dir.chdir(pwd)
154
- puts "== Extension built and moved to #{final_so}"
155
- else
156
- Dir.chdir(pwd)
157
- puts '!! Extension failed to build (see above). Have the required binary and header files been fetched?'
158
- puts '!! Try the tasks in this order: clean > fetch_ext_deps > compile.'
159
- end
160
- else
161
- puts '== Nothing to do under JRuby.'
162
- end
163
- end
164
-
165
- desc 'Clean up extension build files'
166
- task :clean do
167
- if !defined?(JRUBY_VERSION)
168
- pwd = Dir.pwd
169
- ext_dir = File.expand_path('ext/oboe_metal')
170
- symlinks = [
171
- File.expand_path('lib/oboe_metal.so'),
172
- File.expand_path('ext/oboe_metal/lib/liboboe.so'),
173
- File.expand_path('ext/oboe_metal/lib/liboboe-1.0.so.0')
174
- ]
175
-
176
- symlinks.each do |symlink|
177
- FileUtils.rm_f symlink
178
- end
179
- Dir.chdir ext_dir
180
- sh '/usr/bin/env make clean' if File.exist? 'Makefile'
181
-
182
- Dir.chdir pwd
183
- else
184
- puts '== Nothing to do under JRuby.'
185
- end
186
- end
187
-
188
- desc 'Remove all built files and extensions'
189
- task :distclean do
190
- if !defined?(JRUBY_VERSION)
191
- pwd = Dir.pwd
192
- ext_dir = File.expand_path('ext/oboe_metal')
193
- mkmf_log = File.expand_path('ext/oboe_metal/mkmf.log')
194
- symlinks = [
195
- File.expand_path('lib/oboe_metal.so'),
196
- File.expand_path('ext/oboe_metal/lib/liboboe.so'),
197
- File.expand_path('ext/oboe_metal/lib/liboboe-1.0.so.0')
198
- ]
199
-
200
- if File.exist? mkmf_log
201
- symlinks.each do |symlink|
202
- FileUtils.rm_f symlink
203
- end
204
- Dir.chdir ext_dir
205
- sh '/usr/bin/env make distclean' if File.exist? 'Makefile'
206
-
207
- Dir.chdir pwd
208
- else
209
- puts 'Nothing to distclean. (nothing built yet?)'
210
- end
211
- else
212
- puts '== Nothing to do under JRuby.'
213
- end
214
- end
215
-
216
- desc "Rebuild the gem's c extension"
217
- task :recompile => [:distclean, :compile]
218
-
219
- task :environment do
220
- ENV['APPOPTICS_GEM_VERBOSE'] = 'true'
221
-
222
- Bundler.require(:default, :development)
223
- AppOpticsAPM::Config[:tracing_mode] = :enabled
224
- AppOpticsAPM::Test.load_extras
225
-
226
- if AppOpticsAPM::Test.gemfile?(:delayed_job)
227
- require 'delayed/tasks'
228
- end
229
- end
230
-
231
- # Used when testing Resque locally
232
- task 'resque:setup' => :environment do
233
- require 'resque/tasks'
234
- end
data/build_gem.sh DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env bash
2
- # builds the appoptics_apm gem for MRI.
3
-
4
- # we currently only build for MRI, no JRuby
5
- echo -e "\n=== building for MRI ===\n"
6
- rm -f Gemfile.lock
7
- bundle install
8
- bundle exec rake distclean
9
- bundle exec rake fetch_ext_deps
10
- gem build appoptics_apm.gemspec
11
-
12
- echo -e "\n=== built gems ===\n"
13
- ls -la appoptics_apm*.gem
14
-
15
- echo -e "\n=== publish to rubygems via: gem push <gem> ===\n"
@@ -1,15 +0,0 @@
1
- #!/bin/bash
2
-
3
- # build the gem,
4
- # oboe/c-lib version can be given as optional parameter
5
- if [ "$1" != "" ]; then
6
- OBOE_VERSION=$1 ./build_gem.sh
7
- else
8
- ./build_gem.sh
9
- fi
10
-
11
- gem install package_cloud --no-document
12
-
13
- # prerequisite: package_cloud token needs to be in ~/.packagecloud
14
- gem=`ls -dt1 appoptics_apm-[^pre]*.gem | head -1`
15
- package_cloud push solarwinds/appoptics-apm-ruby $gem
@@ -1,203 +0,0 @@
1
- #--
2
- # Copyright (c) 2016 SolarWinds, LLC.
3
- # All rights reserved.
4
- #++
5
-
6
- module AppOpticsAPM
7
- module API
8
- ##
9
- # Module to create profiling traces for blocks of code or methods
10
- module Profiling
11
- ##
12
- # Public: Profile a given block of code. Detect any exceptions thrown by
13
- # the block and report errors.
14
- #
15
- # ==== Arguments
16
- #
17
- # * +profile_name+ - A name used to identify the block being profiled.
18
- # * +report_kvs+ - A hash containing key/value pairs that will be reported along
19
- # with the event of this profile (optional).
20
- # * +with_backtrace+ - Boolean to indicate whether a backtrace should
21
- # be collected with this trace event.
22
- #
23
- # ==== Example
24
- #
25
- # def computation(n)
26
- # AppOpticsAPM::API.profile('fib', { :n => n }) do
27
- # fib(n)
28
- # end
29
- # end
30
- #
31
- # Returns the result of the block.
32
- #
33
-
34
- def profile(profile_name, report_kvs = {}, with_backtrace = false)
35
- return yield unless AppOpticsAPM.tracing?
36
-
37
- begin
38
- report_kvs[:Language] ||= :ruby
39
- report_kvs[:ProfileName] ||= profile_name
40
- report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if with_backtrace
41
-
42
- AppOpticsAPM::API.log(nil, :profile_entry, report_kvs)
43
-
44
- begin
45
- yield
46
- rescue => e
47
- log_exception(nil, e)
48
- raise
49
- ensure
50
- exit_kvs = {}
51
- exit_kvs[:Language] = :ruby
52
- exit_kvs[:ProfileName] = report_kvs[:ProfileName]
53
-
54
- AppOpticsAPM::API.log(nil, :profile_exit, exit_kvs)
55
- end
56
- end
57
- end
58
-
59
- ##
60
- # Public: Add profiling to a method on a class or module. That method can be of any (accessible)
61
- # type (instance, singleton, private, protected etc.).
62
- #
63
- # ==== Arguments
64
- #
65
- # * +klass+ - the class or module that has the method to profile
66
- # * +method+ - the method to profile. Can be singleton, instance, private etc...
67
- # * +opts+ - a hash specifying the one or more of the following options:
68
- # * +:arguments+ - report the arguments passed to <tt>method</tt> on each profile (default: false)
69
- # * +:result+ - report the return value of <tt>method</tt> on each profile (default: false)
70
- # * +:backtrace+ - report the return value of <tt>method</tt> on each profile (default: false)
71
- # * +:name+ - alternate name for the profile reported in the dashboard (default: method name)
72
- # * +extra_kvs+ - a hash containing any additional key/value pairs you would like reported with the profile
73
- #
74
- # ==== Example
75
- #
76
- # opts = {}
77
- # opts[:backtrace] = true
78
- # opts[:arguments] = false
79
- # opts[:name] = :array_sort
80
- #
81
- # AppOpticsAPM::API.profile_method(Array, :sort, opts)
82
- #
83
- def profile_method(klass, method, opts = {}, extra_kvs = {})
84
- # If we're on an unsupported platform (ahem Mac), just act
85
- # like we did something to nicely play the no-op part.
86
- return true unless AppOpticsAPM.loaded
87
-
88
- if !klass.is_a?(Module)
89
- AppOpticsAPM.logger.warn "[appoptics_apm/error] profile_method: Not sure what to do with #{klass}. Send a class or module."
90
- return false
91
- end
92
-
93
- if method.is_a?(String)
94
- method = method.to_sym
95
- elsif !method.is_a?(Symbol)
96
- AppOpticsAPM.logger.warn "[appoptics_apm/error] profile_method: Not sure what to do with #{method}. Send a string or symbol for method."
97
- return false
98
- end
99
-
100
- instance_method = klass.instance_methods.include?(method) || klass.private_instance_methods.include?(method)
101
- class_method = klass.singleton_methods.include?(method)
102
-
103
- # Make sure the request klass::method exists
104
- if !instance_method && !class_method
105
- AppOpticsAPM.logger.warn "[appoptics_apm/error] profile_method: Can't instrument #{klass}.#{method} as it doesn't seem to exist."
106
- AppOpticsAPM.logger.warn "[appoptics_apm/error] #{__FILE__}:#{__LINE__}"
107
- return false
108
- end
109
-
110
- # Strip '!' or '?' from method if present
111
- safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
112
- safe_method_name ||= method
113
-
114
- without_appoptics = "#{safe_method_name}_without_appoptics"
115
- with_appoptics = "#{safe_method_name}_with_appoptics"
116
-
117
- # Check if already profiled
118
- if klass.instance_methods.include?(with_appoptics.to_sym) ||
119
- klass.singleton_methods.include?(with_appoptics.to_sym)
120
- AppOpticsAPM.logger.warn "[appoptics_apm/error] profile_method: #{klass}::#{method} already profiled."
121
- AppOpticsAPM.logger.warn "[appoptics_apm/error] profile_method: #{__FILE__}:#{__LINE__}"
122
- return false
123
- end
124
-
125
- source_location = []
126
- if instance_method
127
- AppOpticsAPM::Util.send_include(klass, AppOpticsAPM::MethodProfiling)
128
- source_location = klass.instance_method(method).source_location
129
- elsif class_method
130
- AppOpticsAPM::Util.send_extend(klass, AppOpticsAPM::MethodProfiling)
131
- source_location = klass.method(method).source_location
132
- end
133
-
134
- report_kvs = collect_profile_kvs(klass, method, opts, extra_kvs, source_location)
135
- report_kvs[:MethodName] = safe_method_name
136
-
137
- if instance_method
138
- klass.class_eval do
139
- define_method(with_appoptics) do |*args, &block|
140
- profile_wrapper(without_appoptics, report_kvs, opts, *args, &block)
141
- end
142
-
143
- alias_method without_appoptics, method.to_s
144
- alias_method method.to_s, with_appoptics
145
- end
146
- elsif class_method
147
- klass.define_singleton_method(with_appoptics) do |*args, &block|
148
- profile_wrapper(without_appoptics, report_kvs, opts, *args, &block)
149
- end
150
-
151
- klass.singleton_class.class_eval do
152
- alias_method without_appoptics, method.to_s
153
- alias_method method.to_s, with_appoptics
154
- end
155
- end
156
- true
157
- end
158
-
159
- private
160
-
161
- ##
162
- # Private: Helper method to aggregate KVs to report
163
- #
164
- # klass - the class or module that has the method to profile
165
- # method - the method to profile. Can be singleton, instance, private etc...
166
- # opts - a hash specifying the one or more of the following options:
167
- # * :arguments - report the arguments passed to <tt>method</tt> on each profile (default: false)
168
- # * :result - report the return value of <tt>method</tt> on each profile (default: false)
169
- # * :backtrace - report the return value of <tt>method</tt> on each profile (default: false)
170
- # * :name - alternate name for the profile reported in the dashboard (default: method name)
171
- # extra_kvs - a hash containing any additional KVs you would like reported with the profile
172
- # source_location - array returned from klass.method(:name).source_location
173
- #
174
- def collect_profile_kvs(klass, method, opts, extra_kvs, source_location)
175
- report_kvs = {}
176
- report_kvs[:Language] ||= :ruby
177
- report_kvs[:ProfileName] ||= opts[:name] ? opts[:name] : method
178
-
179
- klass.is_a?(Class) ? report_kvs[:Class] = klass.to_s : report_kvs[:Module] = klass.to_s
180
-
181
- # If this is a Rails Controller, report the KVs
182
- if defined?(::AbstractController::Base) && klass.ancestors.include?(::AbstractController::Base)
183
- report_kvs[:Controller] = klass.to_s
184
- report_kvs[:Action] = method.to_s
185
- end
186
-
187
- # We won't have access to this info for native methods (those not defined in Ruby).
188
- if source_location.is_a?(Array) && source_location.length == 2
189
- report_kvs[:File] = source_location[0]
190
- report_kvs[:LineNumber] = source_location[1]
191
- end
192
-
193
- # Merge in any extra_kvs requested
194
- report_kvs.merge!(extra_kvs)
195
- end
196
-
197
-
198
- # need to set the context to public, otherwise the following `extends` will be private in api.rb
199
- public
200
-
201
- end
202
- end
203
- end