appoptics_apm_mnfst 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.dockerignore +5 -0
- data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
- data/.gitignore +29 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +121 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Gemfile +29 -0
- data/LICENSE +193 -0
- data/README.md +393 -0
- data/Rakefile +230 -0
- data/appoptics_apm.gemspec +61 -0
- data/bin/appoptics_apm_config +15 -0
- data/build_gem.sh +15 -0
- data/build_gem_upload_to_packagecloud.sh +20 -0
- data/examples/SDK/01_basic_tracing.rb +67 -0
- data/examples/carrying_context.rb +220 -0
- data/ext/oboe_metal/extconf.rb +114 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/VERSION +1 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm.rb +76 -0
- data/lib/appoptics_apm/api.rb +20 -0
- data/lib/appoptics_apm/api/layerinit.rb +41 -0
- data/lib/appoptics_apm/api/logging.rb +375 -0
- data/lib/appoptics_apm/api/memcache.rb +37 -0
- data/lib/appoptics_apm/api/metrics.rb +55 -0
- data/lib/appoptics_apm/api/profiling.rb +203 -0
- data/lib/appoptics_apm/api/tracing.rb +53 -0
- data/lib/appoptics_apm/api/util.rb +122 -0
- data/lib/appoptics_apm/base.rb +230 -0
- data/lib/appoptics_apm/config.rb +254 -0
- data/lib/appoptics_apm/frameworks/grape.rb +97 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
- data/lib/appoptics_apm/frameworks/rails.rb +94 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -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_controller_api.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -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 +108 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +125 -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 +330 -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 +94 -0
- data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
- data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
- data/lib/appoptics_apm/inst/http.rb +73 -0
- data/lib/appoptics_apm/inst/httpclient.rb +174 -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 +199 -0
- data/lib/appoptics_apm/inst/redis.rb +275 -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 +65 -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/legacy_method_profiling.rb +90 -0
- data/lib/appoptics_apm/loading.rb +65 -0
- data/lib/appoptics_apm/logger.rb +42 -0
- data/lib/appoptics_apm/method_profiling.rb +33 -0
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +26 -0
- data/lib/appoptics_apm/noop/metadata.rb +22 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
- data/lib/appoptics_apm/sdk/tracing.rb +315 -0
- data/lib/appoptics_apm/support.rb +119 -0
- data/lib/appoptics_apm/test.rb +94 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +319 -0
- data/lib/appoptics_apm/version.rb +15 -0
- data/lib/appoptics_apm/xtrace.rb +103 -0
- data/lib/joboe_metal.rb +212 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +80 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe_metal.rb +198 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
- data/yardoc_frontpage.md +26 -0
- metadata +266 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'rbconfig'
|
|
5
|
+
require 'logger'
|
|
6
|
+
|
|
7
|
+
module AppOpticsAPM
|
|
8
|
+
##
|
|
9
|
+
# This module is used to debug problematic setups and/or environments.
|
|
10
|
+
# Depending on the environment, output may be to stdout or the framework
|
|
11
|
+
# log file (e.g. log/production.log)
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# yesno
|
|
15
|
+
#
|
|
16
|
+
# Utility method to translate value/nil to "yes"/"no" strings
|
|
17
|
+
def self.yesno(x)
|
|
18
|
+
x ? 'yes' : 'no'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
22
|
+
def self.support_report
|
|
23
|
+
@logger_level = AppOpticsAPM.logger.level
|
|
24
|
+
AppOpticsAPM.logger.level = ::Logger::DEBUG
|
|
25
|
+
|
|
26
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
27
|
+
AppOpticsAPM.logger.warn '* BEGIN AppOpticsAPM Support Report'
|
|
28
|
+
AppOpticsAPM.logger.warn '* Please email the output of this report to support@appoptics.com'
|
|
29
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
30
|
+
AppOpticsAPM.logger.warn "Ruby: #{RUBY_DESCRIPTION}"
|
|
31
|
+
AppOpticsAPM.logger.warn "$0: #{$0}"
|
|
32
|
+
AppOpticsAPM.logger.warn "$1: #{$1}" unless $1.nil?
|
|
33
|
+
AppOpticsAPM.logger.warn "$2: #{$2}" unless $2.nil?
|
|
34
|
+
AppOpticsAPM.logger.warn "$3: #{$3}" unless $3.nil?
|
|
35
|
+
AppOpticsAPM.logger.warn "$4: #{$4}" unless $4.nil?
|
|
36
|
+
AppOpticsAPM.logger.warn "AppOpticsAPM.loaded == #{AppOpticsAPM.loaded}"
|
|
37
|
+
|
|
38
|
+
using_jruby = defined?(JRUBY_VERSION)
|
|
39
|
+
AppOpticsAPM.logger.warn "Using JRuby?: #{yesno(using_jruby)}"
|
|
40
|
+
if using_jruby
|
|
41
|
+
AppOpticsAPM.logger.warn "Joboe Agent Status: #{Java::ComTracelyticsAgent::Agent.getStatus}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
on_heroku = AppOpticsAPM.heroku?
|
|
45
|
+
AppOpticsAPM.logger.warn "On Heroku?: #{yesno(on_heroku)}"
|
|
46
|
+
if on_heroku
|
|
47
|
+
AppOpticsAPM.logger.warn "APPOPTICS_URL: #{ENV['APPOPTICS_URL']}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
AppOpticsAPM.logger.warn "AppOpticsAPM::Ruby defined?: #{yesno(defined?(AppOpticsAPM::Ruby))}"
|
|
51
|
+
AppOpticsAPM.logger.warn "AppOpticsAPM.reporter: #{AppOpticsAPM.reporter}"
|
|
52
|
+
|
|
53
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
54
|
+
AppOpticsAPM.logger.warn '* Frameworks'
|
|
55
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
56
|
+
|
|
57
|
+
using_rails = defined?(::Rails)
|
|
58
|
+
AppOpticsAPM.logger.warn "Using Rails?: #{yesno(using_rails)}"
|
|
59
|
+
if using_rails
|
|
60
|
+
AppOpticsAPM.logger.warn "AppOpticsAPM::Rails loaded?: #{yesno(defined?(AppOpticsAPM::Rails))}"
|
|
61
|
+
if defined?(AppOpticsAPM::Rack)
|
|
62
|
+
AppOpticsAPM.logger.warn "AppOpticsAPM::Rack middleware loaded?: #{yesno(::Rails.configuration.middleware.include? AppOpticsAPM::Rack)}"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
using_sinatra = defined?(::Sinatra)
|
|
67
|
+
AppOpticsAPM.logger.warn "Using Sinatra?: #{yesno(using_sinatra)}"
|
|
68
|
+
|
|
69
|
+
using_padrino = defined?(::Padrino)
|
|
70
|
+
AppOpticsAPM.logger.warn "Using Padrino?: #{yesno(using_padrino)}"
|
|
71
|
+
|
|
72
|
+
using_grape = defined?(::Grape)
|
|
73
|
+
AppOpticsAPM.logger.warn "Using Grape?: #{yesno(using_grape)}"
|
|
74
|
+
|
|
75
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
76
|
+
AppOpticsAPM.logger.warn '* ActiveRecord Adapter'
|
|
77
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
78
|
+
if defined?(::ActiveRecord)
|
|
79
|
+
if defined?(::ActiveRecord::Base.connection.adapter_name)
|
|
80
|
+
AppOpticsAPM.logger.warn "ActiveRecord adapter: #{::ActiveRecord::Base.connection.adapter_name}"
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
AppOpticsAPM.logger.warn 'No ActiveRecord'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
87
|
+
AppOpticsAPM.logger.warn '* AppOpticsAPM::Config Values'
|
|
88
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
89
|
+
AppOpticsAPM::Config.print_config
|
|
90
|
+
|
|
91
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
92
|
+
AppOpticsAPM.logger.warn '* OS, Platform + Env'
|
|
93
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
94
|
+
AppOpticsAPM.logger.warn "host_os: " + RbConfig::CONFIG['host_os']
|
|
95
|
+
AppOpticsAPM.logger.warn "sitearch: " + RbConfig::CONFIG['sitearch']
|
|
96
|
+
AppOpticsAPM.logger.warn "arch: " + RbConfig::CONFIG['arch']
|
|
97
|
+
AppOpticsAPM.logger.warn RUBY_PLATFORM
|
|
98
|
+
AppOpticsAPM.logger.warn "RACK_ENV: #{ENV['RACK_ENV']}"
|
|
99
|
+
AppOpticsAPM.logger.warn "RAILS_ENV: #{ENV['RAILS_ENV']}" if using_rails
|
|
100
|
+
|
|
101
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
102
|
+
AppOpticsAPM.logger.warn '* Raw __Init KVs'
|
|
103
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
104
|
+
platform_info = AppOpticsAPM::Util.build_init_report
|
|
105
|
+
platform_info.each { |k,v|
|
|
106
|
+
AppOpticsAPM.logger.warn "#{k}: #{v}"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
110
|
+
AppOpticsAPM.logger.warn '* END AppOpticsAPM Support Report'
|
|
111
|
+
AppOpticsAPM.logger.warn '* Support Email: support@appoptics.com'
|
|
112
|
+
AppOpticsAPM.logger.warn '* Github: https://github.com/librato/ruby-appoptics'
|
|
113
|
+
AppOpticsAPM.logger.warn '********************************************************'
|
|
114
|
+
|
|
115
|
+
AppOpticsAPM.logger.level = @logger_level
|
|
116
|
+
nil
|
|
117
|
+
end
|
|
118
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
119
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module AppOpticsAPM
|
|
5
|
+
module Test
|
|
6
|
+
class << self
|
|
7
|
+
##
|
|
8
|
+
# load_extras
|
|
9
|
+
#
|
|
10
|
+
# This method simply loads all the extras needed to run
|
|
11
|
+
# tests such as models, jobs etc...
|
|
12
|
+
#
|
|
13
|
+
def load_extras
|
|
14
|
+
# If we're using the libraries gemfile (with sidekiq and resque)
|
|
15
|
+
if AppOpticsAPM::Test.gemfile?(:libraries)
|
|
16
|
+
# Load all of the test workers
|
|
17
|
+
pattern = File.join(File.dirname(__FILE__), '../../test/jobs/**/', '*.rb')
|
|
18
|
+
Dir.glob(pattern) do |f|
|
|
19
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/test] Loading test job file: #{File.basename(f)}"
|
|
20
|
+
require f
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# gemfile?
|
|
27
|
+
#
|
|
28
|
+
# Method used to determine under which gemfile we're running.
|
|
29
|
+
# Pass <tt>name</tt> as the gemfile name only (without the
|
|
30
|
+
# .gemfile extension)
|
|
31
|
+
#
|
|
32
|
+
# returns true or fase depending on result
|
|
33
|
+
#
|
|
34
|
+
def gemfile?(name)
|
|
35
|
+
File.basename(ENV['BUNDLE_GEMFILE']) == (name.to_s + '.gemfile')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# gemfile
|
|
40
|
+
#
|
|
41
|
+
# Used to determine under which gemfile we are running. This
|
|
42
|
+
# method will return the name of the active gemfile
|
|
43
|
+
#
|
|
44
|
+
def gemfile
|
|
45
|
+
File.basename(ENV['BUNDLE_GEMFILE']).split('.').first
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# set_postgresql_env
|
|
50
|
+
#
|
|
51
|
+
# Used to set the postgresql specific DATABASE_URL env based
|
|
52
|
+
# on various conditions
|
|
53
|
+
def set_postgresql_env
|
|
54
|
+
if ENV.key?('TRAVIS_PSQL_PASS')
|
|
55
|
+
ENV['DATABASE_URL'] = "postgresql://postgres:#{ENV['TRAVIS_PSQL_PASS']}@127.0.0.1:5432/travis_ci_test"
|
|
56
|
+
elsif ENV.key?('DOCKER_PSQL_PASS')
|
|
57
|
+
ENV['DATABASE_URL'] = "postgresql://docker:#{ENV['DOCKER_PSQL_PASS']}@127.0.0.1:5432/travis_ci_test"
|
|
58
|
+
else
|
|
59
|
+
ENV['DATABASE_URL'] = 'postgresql://postgres@127.0.0.1:5432/travis_ci_test'
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# set_mysql_env
|
|
65
|
+
#
|
|
66
|
+
# Used to set the mysql specific DATABASE_URL env based
|
|
67
|
+
# on various conditions
|
|
68
|
+
def set_mysql_env
|
|
69
|
+
if ENV.key?('TRAVIS_MYSQL_PASS')
|
|
70
|
+
ENV['DATABASE_URL'] = "mysql://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test"
|
|
71
|
+
elsif ENV.key?('DOCKER_MYSQL_PASS')
|
|
72
|
+
ENV['DATABASE_URL'] = "mysql://root:#{ENV['DOCKER_MYSQL_PASS']}@mysql:3306/travis_ci_test"
|
|
73
|
+
else
|
|
74
|
+
ENV['DATABASE_URL'] = 'mysql://root@127.0.0.1:3306/travis_ci_test'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# set_mysql2_env
|
|
80
|
+
#
|
|
81
|
+
# Used to set the mysql specific DATABASE_URL env based
|
|
82
|
+
# on various conditions
|
|
83
|
+
def set_mysql2_env
|
|
84
|
+
if ENV.key?('TRAVIS_MYSQL_PASS')
|
|
85
|
+
ENV['DATABASE_URL'] = "mysql2://root:#{ENV['TRAVIS_MYSQL_PASS']}@127.0.0.1:3306/travis_ci_test"
|
|
86
|
+
elsif ENV.key?('DOCKER_MYSQL_PASS')
|
|
87
|
+
ENV['DATABASE_URL'] = "mysql2://root:#{ENV['DOCKER_MYSQL_PASS']}@mysql:3306/travis_ci_test"
|
|
88
|
+
else
|
|
89
|
+
ENV['DATABASE_URL'] = 'mysql2://root@127.0.0.1:3306/travis_ci_test'
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module AppOpticsAPM
|
|
5
|
+
##
|
|
6
|
+
# Provides thread local storage for AppOpticsAPM.
|
|
7
|
+
#
|
|
8
|
+
# Example usage:
|
|
9
|
+
# module AppOpticsAPMBase
|
|
10
|
+
# extend AppOpticsAPM::ThreadLocal
|
|
11
|
+
# thread_local :layer_op
|
|
12
|
+
# end
|
|
13
|
+
module ThreadLocal
|
|
14
|
+
def thread_local(name)
|
|
15
|
+
key = "__#{self}_#{name}__".intern
|
|
16
|
+
|
|
17
|
+
define_method(name) do
|
|
18
|
+
Thread.current[key]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
define_method(name.to_s + '=') do |value|
|
|
22
|
+
Thread.current[key] = value
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,319 @@
|
|
|
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
|
+
# static_asset?
|
|
102
|
+
#
|
|
103
|
+
# Given a path, this method determines whether it is a static asset or not (based
|
|
104
|
+
# solely on filename)
|
|
105
|
+
#
|
|
106
|
+
def static_asset?(path)
|
|
107
|
+
path =~ Regexp.new(AppOpticsAPM::Config[:dnt_regexp], AppOpticsAPM::Config[:dnt_opts])
|
|
108
|
+
rescue => e
|
|
109
|
+
AppOpticsAPM.logger.warn "[AppOpticsAPM/debug] Could not apply Regex.new to path. #{e.inspect}"
|
|
110
|
+
false
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# prettify
|
|
115
|
+
#
|
|
116
|
+
# Even to my surprise, 'prettify' is a real word:
|
|
117
|
+
# transitive v. To make pretty or prettier, especially in a superficial or insubstantial way.
|
|
118
|
+
# from The American Heritage Dictionary of the English Language, 4th Edition
|
|
119
|
+
#
|
|
120
|
+
# This method makes things 'purty' for reporting.
|
|
121
|
+
def prettify(x)
|
|
122
|
+
if (x.to_s =~ /^#</) == 0
|
|
123
|
+
x.class.to_s
|
|
124
|
+
else
|
|
125
|
+
x.to_s
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
##
|
|
130
|
+
# upcase
|
|
131
|
+
#
|
|
132
|
+
# Occasionally, we want to send some values in all caps. This is true
|
|
133
|
+
# for things like HTTP scheme or method. This takes anything and does
|
|
134
|
+
# it's best to safely convert it to a string (if needed) and convert it
|
|
135
|
+
# to all uppercase.
|
|
136
|
+
def upcase(o)
|
|
137
|
+
if o.is_a?(String) || o.respond_to?(:to_s)
|
|
138
|
+
o.to_s.upcase
|
|
139
|
+
else
|
|
140
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] AppOpticsAPM::Util.upcase: could not convert #{o.class}"
|
|
141
|
+
'UNKNOWN'
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
##
|
|
146
|
+
# to_query
|
|
147
|
+
#
|
|
148
|
+
# Used to convert a hash into a URL # query.
|
|
149
|
+
#
|
|
150
|
+
def to_query(h)
|
|
151
|
+
return '' unless h.is_a?(Hash)
|
|
152
|
+
|
|
153
|
+
result = []
|
|
154
|
+
|
|
155
|
+
h.each { |k, v| result.push(k.to_s + '=' + v.to_s) }
|
|
156
|
+
result.sort.join('&')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
# sanitize_sql
|
|
161
|
+
#
|
|
162
|
+
# Used to remove query literals from SQL. Used by all
|
|
163
|
+
# DB adapter instrumentation.
|
|
164
|
+
#
|
|
165
|
+
# The regular expression passed to String.gsub is configurable
|
|
166
|
+
# via AppOpticsAPM::Config[:sanitize_sql_regexp] and
|
|
167
|
+
# AppOpticsAPM::Config[:sanitize_sql_opts].
|
|
168
|
+
#
|
|
169
|
+
def sanitize_sql(sql)
|
|
170
|
+
return sql unless AppOpticsAPM::Config[:sanitize_sql]
|
|
171
|
+
|
|
172
|
+
regexp = Regexp.new(AppOpticsAPM::Config[:sanitize_sql_regexp], AppOpticsAPM::Config[:sanitize_sql_opts])
|
|
173
|
+
sql.gsub(/\\\'/,'').gsub(regexp, '?')
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
##
|
|
177
|
+
# legacy_build_init_report
|
|
178
|
+
#
|
|
179
|
+
# Internal: Build a hash of KVs that reports on the status of the
|
|
180
|
+
# running environment. This is used on stack boot in __Init reporting
|
|
181
|
+
# and for AppOpticsAPM.support_report.
|
|
182
|
+
#
|
|
183
|
+
# This legacy version of build_init_report is used for apps without Bundler.
|
|
184
|
+
#
|
|
185
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
186
|
+
#
|
|
187
|
+
# @deprecated Please use {#build_init_report} instead
|
|
188
|
+
def legacy_build_init_report
|
|
189
|
+
AppOpticsAPM.logger.warn '[appoptics_apm/warn] Oboe::API will be deprecated in a future version.'
|
|
190
|
+
platform_info = {}
|
|
191
|
+
|
|
192
|
+
begin
|
|
193
|
+
# Report the framework in use
|
|
194
|
+
if defined?(::RailsLts::VERSION)
|
|
195
|
+
platform_info['Ruby.RailsLts.Version'] = "RailsLts-#{::RailsLts::VERSION}"
|
|
196
|
+
elsif defined?(::Rails.version)
|
|
197
|
+
platform_info['Ruby.Rails.Version'] = "Rails-#{::Rails.version}"
|
|
198
|
+
end
|
|
199
|
+
platform_info['Ruby.Grape.Version'] = "Grape-#{::Grape::VERSION}" if defined?(::Grape::VERSION)
|
|
200
|
+
platform_info['Ruby.Cramp.Version'] = "Cramp-#{::Cramp::VERSION}" if defined?(::Cramp::VERSION)
|
|
201
|
+
|
|
202
|
+
if defined?(::Padrino::VERSION)
|
|
203
|
+
platform_info['Ruby.Padrino.Version'] = "Padrino-#{::Padrino::VERSION}"
|
|
204
|
+
elsif defined?(::Sinatra::VERSION)
|
|
205
|
+
platform_info['Ruby.Sinatra.Version'] = "Sinatra-#{::Sinatra::VERSION}"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Report the instrumented libraries
|
|
209
|
+
platform_info['Ruby.Cassandra.Version'] = "Cassandra-#{::Cassandra.VERSION}" if defined?(::Cassandra.VERSION)
|
|
210
|
+
platform_info['Ruby.Curb.Version'] = "Curb-#{::Curl::VERSION}" if defined?(::Curl::VERSION)
|
|
211
|
+
platform_info['Ruby.Dalli.Version'] = "Dalli-#{::Dalli::VERSION}" if defined?(::Dalli::VERSION)
|
|
212
|
+
platform_info['Ruby.Excon.Version'] = "Excon-#{::Excon::VERSION}" if defined?(::Excon::VERSION)
|
|
213
|
+
platform_info['Ruby.Faraday.Version'] = "Faraday-#{::Faraday::VERSION}" if defined?(::Faraday::VERSION)
|
|
214
|
+
platform_info['Ruby.HTTPClient.Version'] = "HTTPClient-#{::HTTPClient::VERSION}" if defined?(::HTTPClient::VERSION)
|
|
215
|
+
platform_info['Ruby.Memcached.Version'] = "Memcached-#{::Memcached::VERSION}" if defined?(::Memcached::VERSION)
|
|
216
|
+
platform_info['Ruby.Moped.Version'] = "Moped-#{::Moped::VERSION}" if defined?(::Moped::VERSION)
|
|
217
|
+
platform_info['Ruby.Redis.Version'] = "Redis-#{::Redis::VERSION}" if defined?(::Redis::VERSION)
|
|
218
|
+
platform_info['Ruby.Resque.Version'] = "Resque-#{::Resque::VERSION}" if defined?(::Resque::VERSION)
|
|
219
|
+
platform_info['Ruby.RestClient.Version'] = "RestClient-#{::RestClient::VERSION}" if defined?(::RestClient::VERSION)
|
|
220
|
+
platform_info['Ruby.Sidekiq.Version'] = "Sidekiq-#{::Sidekiq::VERSION}" if defined?(::Sidekiq::VERSION)
|
|
221
|
+
platform_info['Ruby.Typhoeus.Version'] = "Typhoeus-#{::Typhoeus::VERSION}" if defined?(::Typhoeus::VERSION)
|
|
222
|
+
|
|
223
|
+
if Gem.loaded_specs.key?('delayed_job')
|
|
224
|
+
# Oddly, DelayedJob doesn't have an embedded version number so we get it from the loaded
|
|
225
|
+
# gem specs.
|
|
226
|
+
version = Gem.loaded_specs['delayed_job'].version.to_s
|
|
227
|
+
platform_info['Ruby.DelayedJob.Version'] = "DelayedJob-#{version}"
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Special case since the Mongo 1.x driver doesn't embed the version number in the gem directly
|
|
231
|
+
if ::Gem.loaded_specs.key?('mongo')
|
|
232
|
+
platform_info['Ruby.Mongo.Version'] = "Mongo-#{::Gem.loaded_specs['mongo'].version}"
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Report the DB adapter in use
|
|
236
|
+
platform_info['Ruby.Mysql.Version'] = Mysql::GemVersion::VERSION if defined?(Mysql::GemVersion::VERSION)
|
|
237
|
+
platform_info['Ruby.PG.Version'] = PG::VERSION if defined?(PG::VERSION)
|
|
238
|
+
platform_info['Ruby.Mysql2.Version'] = Mysql2::VERSION if defined?(Mysql2::VERSION)
|
|
239
|
+
platform_info['Ruby.Sequel.Version'] = ::Sequel::VERSION if defined?(::Sequel::VERSION)
|
|
240
|
+
rescue StandardError, ScriptError => e
|
|
241
|
+
# Also rescue ScriptError (aka SyntaxError) in case one of the expected
|
|
242
|
+
# version defines don't exist
|
|
243
|
+
|
|
244
|
+
platform_info['Error'] = "Error in legacy_build_init_report: #{e.message}"
|
|
245
|
+
|
|
246
|
+
AppOpticsAPM.logger.warn "[appoptics_apm/warn] Error in legacy_build_init_report: #{e.message}"
|
|
247
|
+
AppOpticsAPM.logger.debug e.backtrace
|
|
248
|
+
end
|
|
249
|
+
platform_info
|
|
250
|
+
end
|
|
251
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
252
|
+
|
|
253
|
+
##
|
|
254
|
+
# build_init_report
|
|
255
|
+
#
|
|
256
|
+
# Internal: Build a hash of KVs that reports on the status of the
|
|
257
|
+
# running environment. This is used on stack boot in __Init reporting
|
|
258
|
+
# and for AppOpticsAPM.support_report.
|
|
259
|
+
#
|
|
260
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
261
|
+
def build_init_report
|
|
262
|
+
platform_info = { '__Init' => 1 }
|
|
263
|
+
|
|
264
|
+
begin
|
|
265
|
+
platform_info['Force'] = true
|
|
266
|
+
platform_info['Ruby.Platform.Version'] = RUBY_PLATFORM
|
|
267
|
+
platform_info['Ruby.Version'] = RUBY_VERSION
|
|
268
|
+
platform_info['Ruby.AppOptics.Version'] = AppOpticsAPM::Version::STRING
|
|
269
|
+
|
|
270
|
+
clib_version_file = File.join(Gem::Specification.find_by_name('appoptics_apm').gem_dir, 'ext', 'oboe_metal', 'src', 'VERSION')
|
|
271
|
+
platform_info['Ruby.clib.Version'] = File.read(clib_version_file).chomp
|
|
272
|
+
platform_info['RubyHeroku.AppOpticsAPM.Version'] = AppOpticsAPMHeroku::Version::STRING if defined?(AppOpticsAPMHeroku)
|
|
273
|
+
platform_info['Ruby.TraceMode.Version'] = AppOpticsAPM::Config[:tracing_mode]
|
|
274
|
+
|
|
275
|
+
# Collect up the loaded gems
|
|
276
|
+
if defined?(Gem) && Gem.respond_to?(:loaded_specs)
|
|
277
|
+
Gem.loaded_specs.each_pair { |k, v|
|
|
278
|
+
platform_info["Ruby.#{k}.Version"] = v.version.to_s
|
|
279
|
+
}
|
|
280
|
+
else
|
|
281
|
+
platform_info.merge!(legacy_build_init_report)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Report the server in use (if possible)
|
|
285
|
+
if defined?(::Unicorn::Const::UNICORN_VERSION)
|
|
286
|
+
platform_info['Ruby.AppContainer.Version'] = "Unicorn-#{::Unicorn::Const::UNICORN_VERSION}"
|
|
287
|
+
elsif defined?(::Puma::Const::PUMA_VERSION)
|
|
288
|
+
platform_info['Ruby.AppContainer.Version'] = "Puma-#{::Puma::Const::PUMA_VERSION} (#{::Puma::Const::CODE_NAME})"
|
|
289
|
+
elsif defined?(::PhusionPassenger::PACKAGE_NAME)
|
|
290
|
+
platform_info['Ruby.AppContainer.Version'] = "#{::PhusionPassenger::PACKAGE_NAME}-#{::PhusionPassenger::VERSION_STRING}"
|
|
291
|
+
elsif defined?(::Thin::VERSION::STRING)
|
|
292
|
+
platform_info['Ruby.AppContainer.Version'] = "Thin-#{::Thin::VERSION::STRING} (#{::Thin::VERSION::CODENAME})"
|
|
293
|
+
elsif defined?(::Mongrel::Const::MONGREL_VERSION)
|
|
294
|
+
platform_info['Ruby.AppContainer.Version'] = "Mongrel-#{::Mongrel::Const::MONGREL_VERSION}"
|
|
295
|
+
elsif defined?(::Mongrel2::VERSION)
|
|
296
|
+
platform_info['Ruby.AppContainer.Version'] = "Mongrel2-#{::Mongrel2::VERSION}"
|
|
297
|
+
elsif defined?(::Trinidad::VERSION)
|
|
298
|
+
platform_info['Ruby.AppContainer.Version'] = "Trinidad-#{::Trinidad::VERSION}"
|
|
299
|
+
elsif defined?(::WEBrick::VERSION)
|
|
300
|
+
platform_info['Ruby.AppContainer.Version'] = "WEBrick-#{::WEBrick::VERSION}"
|
|
301
|
+
else
|
|
302
|
+
platform_info['Ruby.AppContainer.Version'] = File.basename($PROGRAM_NAME)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
rescue StandardError, ScriptError => e
|
|
306
|
+
# Also rescue ScriptError (aka SyntaxError) in case one of the expected
|
|
307
|
+
# version defines don't exist
|
|
308
|
+
|
|
309
|
+
platform_info['Error'] = "Error in build_report: #{e.message}"
|
|
310
|
+
|
|
311
|
+
AppOpticsAPM.logger.warn "[appoptics_apm/warn] Error in build_init_report: #{e.message}"
|
|
312
|
+
AppOpticsAPM.logger.debug e.backtrace
|
|
313
|
+
end
|
|
314
|
+
platform_info
|
|
315
|
+
end
|
|
316
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|