traceview 3.0.0
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/.gitignore +10 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +58 -0
- data/Appraisals +10 -0
- data/CHANGELOG.md +490 -0
- data/CONFIG.md +16 -0
- data/Gemfile +95 -0
- data/LICENSE +199 -0
- data/README.md +380 -0
- data/Rakefile +109 -0
- data/examples/DNT.md +35 -0
- data/examples/carrying_context.rb +225 -0
- data/examples/instrumenting_metal_controller.rb +8 -0
- data/examples/puma_on_heroku_config.rb +17 -0
- data/examples/tracing_async_threads.rb +125 -0
- data/examples/tracing_background_jobs.rb +52 -0
- data/examples/tracing_forked_processes.rb +100 -0
- data/examples/unicorn_on_heroku_config.rb +28 -0
- data/ext/oboe_metal/extconf.rb +61 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/bson/bson.h +221 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/oboe.h +275 -0
- data/ext/oboe_metal/src/oboe.hpp +352 -0
- data/ext/oboe_metal/src/oboe_wrap.cxx +3886 -0
- data/ext/oboe_metal/tests/test.rb +11 -0
- data/gemfiles/mongo.gemfile +33 -0
- data/gemfiles/moped.gemfile +33 -0
- data/get_version.rb +5 -0
- data/init.rb +4 -0
- data/lib/joboe_metal.rb +206 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +59 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe_metal.rb +151 -0
- data/lib/rails/generators/traceview/install_generator.rb +76 -0
- data/lib/rails/generators/traceview/templates/traceview_initializer.rb +159 -0
- data/lib/traceview.rb +62 -0
- data/lib/traceview/api.rb +18 -0
- data/lib/traceview/api/layerinit.rb +51 -0
- data/lib/traceview/api/logging.rb +209 -0
- data/lib/traceview/api/memcache.rb +31 -0
- data/lib/traceview/api/profiling.rb +50 -0
- data/lib/traceview/api/tracing.rb +135 -0
- data/lib/traceview/api/util.rb +121 -0
- data/lib/traceview/base.rb +225 -0
- data/lib/traceview/config.rb +238 -0
- data/lib/traceview/frameworks/grape.rb +97 -0
- data/lib/traceview/frameworks/padrino.rb +64 -0
- data/lib/traceview/frameworks/padrino/templates.rb +58 -0
- data/lib/traceview/frameworks/rails.rb +145 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
- data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
- data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
- data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
- data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
- data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
- data/lib/traceview/frameworks/sinatra.rb +95 -0
- data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
- data/lib/traceview/inst/cassandra.rb +279 -0
- data/lib/traceview/inst/dalli.rb +86 -0
- data/lib/traceview/inst/em-http-request.rb +99 -0
- data/lib/traceview/inst/excon.rb +111 -0
- data/lib/traceview/inst/faraday.rb +73 -0
- data/lib/traceview/inst/http.rb +87 -0
- data/lib/traceview/inst/httpclient.rb +173 -0
- data/lib/traceview/inst/memcache.rb +102 -0
- data/lib/traceview/inst/memcached.rb +94 -0
- data/lib/traceview/inst/mongo.rb +238 -0
- data/lib/traceview/inst/moped.rb +474 -0
- data/lib/traceview/inst/rack.rb +122 -0
- data/lib/traceview/inst/redis.rb +271 -0
- data/lib/traceview/inst/resque.rb +192 -0
- data/lib/traceview/inst/rest-client.rb +38 -0
- data/lib/traceview/inst/sequel.rb +162 -0
- data/lib/traceview/inst/typhoeus.rb +102 -0
- data/lib/traceview/instrumentation.rb +21 -0
- data/lib/traceview/loading.rb +94 -0
- data/lib/traceview/logger.rb +41 -0
- data/lib/traceview/method_profiling.rb +84 -0
- data/lib/traceview/ruby.rb +36 -0
- data/lib/traceview/support.rb +113 -0
- data/lib/traceview/thread_local.rb +26 -0
- data/lib/traceview/util.rb +250 -0
- data/lib/traceview/version.rb +16 -0
- data/lib/traceview/xtrace.rb +90 -0
- data/test/frameworks/apps/grape_nested.rb +30 -0
- data/test/frameworks/apps/grape_simple.rb +24 -0
- data/test/frameworks/apps/padrino_simple.rb +45 -0
- data/test/frameworks/apps/sinatra_simple.rb +24 -0
- data/test/frameworks/grape_test.rb +142 -0
- data/test/frameworks/padrino_test.rb +30 -0
- data/test/frameworks/sinatra_test.rb +30 -0
- data/test/instrumentation/cassandra_test.rb +380 -0
- data/test/instrumentation/dalli_test.rb +171 -0
- data/test/instrumentation/em_http_request_test.rb +86 -0
- data/test/instrumentation/excon_test.rb +207 -0
- data/test/instrumentation/faraday_test.rb +235 -0
- data/test/instrumentation/http_test.rb +140 -0
- data/test/instrumentation/httpclient_test.rb +296 -0
- data/test/instrumentation/memcache_test.rb +251 -0
- data/test/instrumentation/memcached_test.rb +226 -0
- data/test/instrumentation/mongo_test.rb +462 -0
- data/test/instrumentation/moped_test.rb +496 -0
- data/test/instrumentation/rack_test.rb +116 -0
- data/test/instrumentation/redis_hashes_test.rb +265 -0
- data/test/instrumentation/redis_keys_test.rb +318 -0
- data/test/instrumentation/redis_lists_test.rb +310 -0
- data/test/instrumentation/redis_misc_test.rb +160 -0
- data/test/instrumentation/redis_sets_test.rb +293 -0
- data/test/instrumentation/redis_sortedsets_test.rb +325 -0
- data/test/instrumentation/redis_strings_test.rb +333 -0
- data/test/instrumentation/resque_test.rb +62 -0
- data/test/instrumentation/rest-client_test.rb +294 -0
- data/test/instrumentation/sequel_mysql2_test.rb +326 -0
- data/test/instrumentation/sequel_mysql_test.rb +326 -0
- data/test/instrumentation/sequel_pg_test.rb +330 -0
- data/test/instrumentation/typhoeus_test.rb +285 -0
- data/test/minitest_helper.rb +187 -0
- data/test/profiling/method_test.rb +198 -0
- data/test/servers/rackapp_8101.rb +22 -0
- data/test/support/backcompat_test.rb +269 -0
- data/test/support/config_test.rb +128 -0
- data/test/support/dnt_test.rb +73 -0
- data/test/support/liboboe_settings_test.rb +104 -0
- data/test/support/xtrace_test.rb +35 -0
- data/traceview.gemspec +29 -0
- metadata +250 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# Provides the methods necessary for method profiling. Profiling
|
|
6
|
+
# results are sent to the TraceView dashboard.
|
|
7
|
+
#
|
|
8
|
+
# Example usage:
|
|
9
|
+
# class MyApp
|
|
10
|
+
# include TraceViewMethodProfiling
|
|
11
|
+
#
|
|
12
|
+
# def process_request()
|
|
13
|
+
# # The hard work
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# # call syntax: profile_method <method>, <profile_name>
|
|
17
|
+
# profile_method :process_request, 'request_processor'
|
|
18
|
+
# end
|
|
19
|
+
module TraceViewMethodProfiling
|
|
20
|
+
def self.included(klass)
|
|
21
|
+
klass.extend ClassMethods
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module ClassMethods
|
|
25
|
+
def profile_method(method_name, profile_name, store_args = false, store_return = false, *_)
|
|
26
|
+
begin
|
|
27
|
+
# this only gets file and line where profiling is turned on, presumably
|
|
28
|
+
# right after the function definition. ruby 1.9 and 2.0 has nice introspection (Method.source_location)
|
|
29
|
+
# but its appears no such luck for ruby 1.8
|
|
30
|
+
file = ''
|
|
31
|
+
line = ''
|
|
32
|
+
if RUBY_VERSION >= '1.9'
|
|
33
|
+
info = instance_method(method_name).source_location
|
|
34
|
+
unless info.nil?
|
|
35
|
+
file = info[0].to_s
|
|
36
|
+
line = info[1].to_s
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
info = Kernel.caller[0].split(':')
|
|
40
|
+
file = info.first.to_s
|
|
41
|
+
line = info.last.to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Safety: Make sure there are no quotes or double quotes to break the class_eval
|
|
45
|
+
file = file.gsub(/[\'\"]/, '')
|
|
46
|
+
line = line.gsub(/[\'\"]/, '')
|
|
47
|
+
|
|
48
|
+
# profiling via ruby-prof, is it possible to get return value of profiled code?
|
|
49
|
+
code = "def _traceview_profiled_#{method_name}(*args, &block)
|
|
50
|
+
entry_kvs = {}
|
|
51
|
+
entry_kvs['Language'] = 'ruby'
|
|
52
|
+
entry_kvs['ProfileName'] = '#{TraceView::Util.prettify(profile_name)}'
|
|
53
|
+
entry_kvs['FunctionName'] = '#{TraceView::Util.prettify(method_name)}'
|
|
54
|
+
entry_kvs['File'] = '#{file}'
|
|
55
|
+
entry_kvs['LineNumber'] = '#{line}'
|
|
56
|
+
entry_kvs['Args'] = TraceView::API.pps(*args) if #{store_args}
|
|
57
|
+
entry_kvs.merge!(::TraceView::API.get_class_name(self))
|
|
58
|
+
|
|
59
|
+
TraceView::API.log(nil, 'profile_entry', entry_kvs)
|
|
60
|
+
|
|
61
|
+
ret = _traceview_orig_#{method_name}(*args, &block)
|
|
62
|
+
|
|
63
|
+
exit_kvs = {}
|
|
64
|
+
exit_kvs['Language'] = 'ruby'
|
|
65
|
+
exit_kvs['ProfileName'] = '#{TraceView::Util.prettify(profile_name)}'
|
|
66
|
+
exit_kvs['ReturnValue'] = TraceView::API.pps(ret) if #{store_return}
|
|
67
|
+
|
|
68
|
+
TraceView::API.log(nil, 'profile_exit', exit_kvs)
|
|
69
|
+
ret
|
|
70
|
+
end"
|
|
71
|
+
rescue => e
|
|
72
|
+
TraceView.logger.warn "[traceview/warn] profile_method: #{e.inspect}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
begin
|
|
76
|
+
class_eval code, __FILE__, __LINE__
|
|
77
|
+
alias_method "_traceview_orig_#{method_name}", method_name
|
|
78
|
+
alias_method method_name, "_traceview_profiled_#{method_name}"
|
|
79
|
+
rescue => e
|
|
80
|
+
TraceView.logger.warn "[traceview/warn] Fatal error profiling method (#{method_name}): #{e.inspect}" if TraceView::Config[:verbose]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
##
|
|
6
|
+
# This module provides a method to manually initialize the
|
|
7
|
+
# Ruby instrumentation. Normally this is done by detecting
|
|
8
|
+
# frameworks at load time and inserting initialization hooks.
|
|
9
|
+
module Ruby
|
|
10
|
+
class << self
|
|
11
|
+
def initialize
|
|
12
|
+
load
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# The core method to load Ruby instrumentation. Call this
|
|
17
|
+
# from raw Ruby scripts or in Ruby applications where a
|
|
18
|
+
# supported framework isn't being used. Supported frameworks
|
|
19
|
+
# will instead be detected at load time and initialization is
|
|
20
|
+
# automatic.
|
|
21
|
+
def load
|
|
22
|
+
# In case some apps call this manually, make sure
|
|
23
|
+
# that the gem is fully loaded and not in no-op
|
|
24
|
+
# mode (e.g. on unsupported platforms etc.)
|
|
25
|
+
if TraceView.loaded
|
|
26
|
+
TraceView::Loading.load_access_key
|
|
27
|
+
TraceView::Inst.load_instrumentation
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if TraceView.loaded and !TraceView.framework?
|
|
35
|
+
::TraceView::Ruby.load
|
|
36
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Copyright (c) 2014 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'rbconfig'
|
|
5
|
+
|
|
6
|
+
module TraceView
|
|
7
|
+
##
|
|
8
|
+
# This module is used to debug problematic setups and/or environments.
|
|
9
|
+
# Depending on the environment, output may be to stdout or the framework
|
|
10
|
+
# log file (e.g. log/production.log)
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# yesno
|
|
14
|
+
#
|
|
15
|
+
# Utility method to translate value/nil to "yes"/"no" strings
|
|
16
|
+
def self.yesno(x)
|
|
17
|
+
x ? "yes" : "no"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.support_report
|
|
21
|
+
TraceView.logger.warn "********************************************************"
|
|
22
|
+
TraceView.logger.warn "* BEGIN TraceView Support Report"
|
|
23
|
+
TraceView.logger.warn "* Please email the output of this report to traceviewsupport@appneta.com"
|
|
24
|
+
TraceView.logger.warn "********************************************************"
|
|
25
|
+
TraceView.logger.warn "Ruby: #{RUBY_DESCRIPTION}"
|
|
26
|
+
TraceView.logger.warn "$0: #{$0}"
|
|
27
|
+
TraceView.logger.warn "$1: #{$1}" unless $1.nil?
|
|
28
|
+
TraceView.logger.warn "$2: #{$2}" unless $2.nil?
|
|
29
|
+
TraceView.logger.warn "$3: #{$3}" unless $3.nil?
|
|
30
|
+
TraceView.logger.warn "$4: #{$4}" unless $4.nil?
|
|
31
|
+
TraceView.logger.warn "TraceView.loaded == #{TraceView.loaded}"
|
|
32
|
+
|
|
33
|
+
using_jruby = defined?(JRUBY_VERSION)
|
|
34
|
+
TraceView.logger.warn "Using JRuby?: #{yesno(using_jruby)}"
|
|
35
|
+
if using_jruby
|
|
36
|
+
TraceView.logger.warn "Jtraceview Agent Status: #{Java::ComTracelyticsAgent::Agent.getStatus}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
on_heroku = TraceView.heroku?
|
|
40
|
+
TraceView.logger.warn "On Heroku?: #{yesno(on_heroku)}"
|
|
41
|
+
if on_heroku
|
|
42
|
+
TraceView.logger.warn "TRACEVIEW_URL: #{ENV['TRACEVIEW_URL']}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
TraceView.logger.warn "TraceView::Ruby defined?: #{yesno(defined?(TraceView::Ruby))}"
|
|
46
|
+
TraceView.logger.warn "TraceView.reporter: #{TraceView.reporter}"
|
|
47
|
+
|
|
48
|
+
TraceView.logger.warn "********************************************************"
|
|
49
|
+
TraceView.logger.warn "* Frameworks"
|
|
50
|
+
TraceView.logger.warn "********************************************************"
|
|
51
|
+
|
|
52
|
+
using_rails = defined?(::Rails)
|
|
53
|
+
TraceView.logger.warn "Using Rails?: #{yesno(using_rails)}"
|
|
54
|
+
if using_rails
|
|
55
|
+
TraceView.logger.warn "TraceView::Rails loaded?: #{yesno(defined?(::TraceView::Rails))}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
using_sinatra = defined?(::Sinatra)
|
|
59
|
+
TraceView.logger.warn "Using Sinatra?: #{yesno(using_sinatra)}"
|
|
60
|
+
|
|
61
|
+
using_padrino = defined?(::Padrino)
|
|
62
|
+
TraceView.logger.warn "Using Padrino?: #{yesno(using_padrino)}"
|
|
63
|
+
|
|
64
|
+
using_grape = defined?(::Grape)
|
|
65
|
+
TraceView.logger.warn "Using Grape?: #{yesno(using_grape)}"
|
|
66
|
+
|
|
67
|
+
TraceView.logger.warn "********************************************************"
|
|
68
|
+
TraceView.logger.warn "* TraceView Libraries"
|
|
69
|
+
TraceView.logger.warn "********************************************************"
|
|
70
|
+
files = Dir.glob('/usr/lib/liboboe*')
|
|
71
|
+
if files.empty?
|
|
72
|
+
TraceView.logger.warn "Error: No liboboe libs!"
|
|
73
|
+
else
|
|
74
|
+
files.each { |f|
|
|
75
|
+
TraceView.logger.warn f
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
TraceView.logger.warn "********************************************************"
|
|
80
|
+
TraceView.logger.warn "* TraceView::Config Values"
|
|
81
|
+
TraceView.logger.warn "********************************************************"
|
|
82
|
+
TraceView::Config.show.each { |k,v|
|
|
83
|
+
TraceView.logger.warn "#{k}: #{v}"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
TraceView.logger.warn "********************************************************"
|
|
87
|
+
TraceView.logger.warn "* OS, Platform + Env"
|
|
88
|
+
TraceView.logger.warn "********************************************************"
|
|
89
|
+
TraceView.logger.warn RbConfig::CONFIG['host_os']
|
|
90
|
+
TraceView.logger.warn RbConfig::CONFIG['sitearch']
|
|
91
|
+
TraceView.logger.warn RbConfig::CONFIG['arch']
|
|
92
|
+
TraceView.logger.warn RUBY_PLATFORM
|
|
93
|
+
TraceView.logger.warn "RACK_ENV: #{ENV['RACK_ENV']}"
|
|
94
|
+
TraceView.logger.warn "RAILS_ENV: #{ENV['RAILS_ENV']}" if using_rails
|
|
95
|
+
|
|
96
|
+
TraceView.logger.warn "********************************************************"
|
|
97
|
+
TraceView.logger.warn "* Raw __Init KVs"
|
|
98
|
+
TraceView.logger.warn "********************************************************"
|
|
99
|
+
platform_info = TraceView::Util.build_init_report
|
|
100
|
+
platform_info.each { |k,v|
|
|
101
|
+
TraceView.logger.warn "#{k}: #{v}"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
TraceView.logger.warn "********************************************************"
|
|
105
|
+
TraceView.logger.warn "* END TraceView Support Report"
|
|
106
|
+
TraceView.logger.warn "* Support Email: traceviewsupport@appneta.com"
|
|
107
|
+
TraceView.logger.warn "* Support Portal: https://support.tv.appneta.com"
|
|
108
|
+
TraceView.logger.warn "* Freenode IRC: #appneta"
|
|
109
|
+
TraceView.logger.warn "* Github: https://github.com/appneta/traceview-ruby"
|
|
110
|
+
TraceView.logger.warn "********************************************************"
|
|
111
|
+
nil
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright (c) 2014 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
##
|
|
6
|
+
# Provides thread local storage for TraceView.
|
|
7
|
+
#
|
|
8
|
+
# Example usage:
|
|
9
|
+
# module TraceViewBase
|
|
10
|
+
# extend ::TraceView::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,250 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
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_traceview = "#{safe_method_name}_without_traceview"
|
|
38
|
+
with_traceview = "#{safe_method_name}_with_traceview"
|
|
39
|
+
|
|
40
|
+
# Only alias if we haven't done so already
|
|
41
|
+
unless cls.method_defined?(without_traceview.to_sym) ||
|
|
42
|
+
cls.private_method_defined?(without_traceview.to_sym)
|
|
43
|
+
|
|
44
|
+
cls.class_eval do
|
|
45
|
+
alias_method without_traceview, "#{method}"
|
|
46
|
+
alias_method "#{method}", with_traceview
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
TraceView.logger.warn "[traceview/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_traceview = "#{safe_method_name}_without_traceview"
|
|
70
|
+
with_traceview = "#{safe_method_name}_with_traceview"
|
|
71
|
+
|
|
72
|
+
# Only alias if we haven't done so already
|
|
73
|
+
unless cls.singleton_methods.include? without_traceview.to_sym
|
|
74
|
+
cls.singleton_class.send(:alias_method, without_traceview, "#{method}")
|
|
75
|
+
cls.singleton_class.send(:alias_method, "#{method}", with_traceview)
|
|
76
|
+
end
|
|
77
|
+
else TraceView.logger.warn "[traceview/loading] Couldn't properly instrument #{name}. Partial traces may occur."
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# send_extend
|
|
83
|
+
#
|
|
84
|
+
# Centralized utility method to send an extend call for an
|
|
85
|
+
# arbitrary class
|
|
86
|
+
def send_extend(target_cls, cls)
|
|
87
|
+
target_cls.send(:extend, cls) if defined?(target_cls)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# send_include
|
|
92
|
+
#
|
|
93
|
+
# Centralized utility method to send a include call for an
|
|
94
|
+
# arbitrary class
|
|
95
|
+
def send_include(target_cls, cls)
|
|
96
|
+
target_cls.send(:include, cls) if defined?(target_cls)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
# static_asset?
|
|
101
|
+
#
|
|
102
|
+
# Given a path, this method determines whether it is a static asset or not (based
|
|
103
|
+
# solely on filename)
|
|
104
|
+
#
|
|
105
|
+
def static_asset?(path)
|
|
106
|
+
(path =~ Regexp.new(TraceView::Config[:dnt_regexp], TraceView::Config[:dnt_opts]))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
##
|
|
110
|
+
# prettify
|
|
111
|
+
#
|
|
112
|
+
# Even to my surprise, 'prettify' is a real word:
|
|
113
|
+
# transitive v. To make pretty or prettier, especially in a superficial or insubstantial way.
|
|
114
|
+
# from The American Heritage Dictionary of the English Language, 4th Edition
|
|
115
|
+
#
|
|
116
|
+
# This method makes things 'purty' for reporting.
|
|
117
|
+
def prettify(x)
|
|
118
|
+
if (x.to_s =~ /^#</) == 0
|
|
119
|
+
x.class.to_s
|
|
120
|
+
else
|
|
121
|
+
x.to_s
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# upcase
|
|
127
|
+
#
|
|
128
|
+
# Occasionally, we want to send some values in all caps. This is true
|
|
129
|
+
# for things like HTTP scheme or method. This takes anything and does
|
|
130
|
+
# it's best to safely convert it to a string (if needed) and convert it
|
|
131
|
+
# to all uppercase.
|
|
132
|
+
def upcase(o)
|
|
133
|
+
if o.is_a?(String) || o.respond_to?(:to_s)
|
|
134
|
+
o.to_s.upcase
|
|
135
|
+
else
|
|
136
|
+
TraceView.logger.debug "[traceview/debug] TraceView::Util.upcase: could not convert #{o.class}"
|
|
137
|
+
"UNKNOWN"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
##
|
|
143
|
+
# to_query
|
|
144
|
+
#
|
|
145
|
+
# Used under Ruby 1.8.7 to convert a hash into a URL
|
|
146
|
+
# query. A backport of Hash#to_query.
|
|
147
|
+
#
|
|
148
|
+
def to_query(h)
|
|
149
|
+
return "" unless h.is_a?(Hash)
|
|
150
|
+
|
|
151
|
+
# If called from a newer Ruby, use the builtin.
|
|
152
|
+
return h.to_query if RUBY_VERSION >= '1.9.3'
|
|
153
|
+
|
|
154
|
+
result = []
|
|
155
|
+
|
|
156
|
+
h.each { |k, v| result.push (k.to_s + '=' + v.to_s) }
|
|
157
|
+
return result.sort.join('&')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# build_report
|
|
162
|
+
#
|
|
163
|
+
# Internal: Build a hash of KVs that reports on the status of the
|
|
164
|
+
# running environment. This is used on stack boot in __Init reporting
|
|
165
|
+
# and for TraceView.support_report.
|
|
166
|
+
def build_init_report
|
|
167
|
+
platform_info = { '__Init' => 1 }
|
|
168
|
+
|
|
169
|
+
begin
|
|
170
|
+
platform_info['Force'] = true
|
|
171
|
+
platform_info['Ruby.Platform.Version'] = RUBY_PLATFORM
|
|
172
|
+
platform_info['Ruby.Version'] = RUBY_VERSION
|
|
173
|
+
platform_info['Ruby.TraceView.Version'] = ::TraceView::Version::STRING
|
|
174
|
+
platform_info['RubyHeroku.TraceView.Version'] = ::TraceViewHeroku::Version::STRING if defined?(::TraceViewHeroku)
|
|
175
|
+
platform_info['Ruby.TraceMode.Version'] = ::TraceView::Config[:tracing_mode]
|
|
176
|
+
|
|
177
|
+
# Report the framework in use
|
|
178
|
+
if defined?(::RailsLts)
|
|
179
|
+
platform_info['Ruby.RailsLts.Version'] = "RailsLts-#{::RailsLts::VERSION}"
|
|
180
|
+
elsif defined?(::Rails)
|
|
181
|
+
platform_info['Ruby.Rails.Version'] = "Rails-#{::Rails.version}"
|
|
182
|
+
end
|
|
183
|
+
platform_info['Ruby.Grape.Version'] = "Grape-#{::Grape::VERSION}" if defined?(::Grape)
|
|
184
|
+
platform_info['Ruby.Cramp.Version'] = "Cramp-#{::Cramp::VERSION}" if defined?(::Cramp)
|
|
185
|
+
|
|
186
|
+
if defined?(::Padrino)
|
|
187
|
+
platform_info['Ruby.Padrino.Version'] = "Padrino-#{::Padrino::VERSION}"
|
|
188
|
+
elsif defined?(::Sinatra)
|
|
189
|
+
platform_info['Ruby.Sinatra.Version'] = "Sinatra-#{::Sinatra::VERSION}"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Report the instrumented libraries
|
|
193
|
+
platform_info['Ruby.Cassandra.Version'] = "Cassandra-#{::Cassandra.VERSION}" if defined?(::Cassandra)
|
|
194
|
+
platform_info['Ruby.Dalli.Version'] = "Dalli-#{::Dalli::VERSION}" if defined?(::Dalli)
|
|
195
|
+
platform_info['Ruby.Excon.Version'] = "Excon-#{::Excon::VERSION}" if defined?(::Excon::VERSION)
|
|
196
|
+
platform_info['Ruby.Faraday.Version'] = "Faraday-#{::Faraday::VERSION}" if defined?(::Faraday)
|
|
197
|
+
platform_info['Ruby.HTTPClient.Version'] = "HTTPClient-#{::HTTPClient::VERSION}" if defined?(::HTTPClient::VERSION)
|
|
198
|
+
platform_info['Ruby.MemCache.Version'] = "MemCache-#{::MemCache::VERSION}" if defined?(::MemCache)
|
|
199
|
+
platform_info['Ruby.Moped.Version'] = "Moped-#{::Moped::VERSION}" if defined?(::Moped)
|
|
200
|
+
platform_info['Ruby.Redis.Version'] = "Redis-#{::Redis::VERSION}" if defined?(::Redis)
|
|
201
|
+
platform_info['Ruby.Resque.Version'] = "Resque-#{::Resque::VERSION}" if defined?(::Resque)
|
|
202
|
+
platform_info['Ruby.RestClient.Version'] = "RestClient-#{::RestClient::VERSION}" if defined?(::RestClient::VERSION)
|
|
203
|
+
platform_info['Ruby.Typhoeus.Version'] = "Typhoeus-#{::Typhoeus::VERSION}" if defined?(::Typhoeus::VERSION)
|
|
204
|
+
|
|
205
|
+
# Special case since the Mongo 1.x driver doesn't embed the version number in the gem directly
|
|
206
|
+
if ::Gem.loaded_specs.key?('mongo')
|
|
207
|
+
platform_info['Ruby.Mongo.Version'] = "Mongo-#{::Gem.loaded_specs['mongo'].version}"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Report the DB adapter in use
|
|
211
|
+
platform_info['Ruby.Mysql.Version'] = Mysql::GemVersion::VERSION if defined?(Mysql::GemVersion::VERSION)
|
|
212
|
+
platform_info['Ruby.PG.Version'] = PG::VERSION if defined?(PG::VERSION)
|
|
213
|
+
platform_info['Ruby.Mysql2.Version'] = Mysql2::VERSION if defined?(Mysql2::VERSION)
|
|
214
|
+
platform_info['Ruby.Sequel.Version'] = ::Sequel::VERSION if defined?(::Sequel::VERSION)
|
|
215
|
+
|
|
216
|
+
# Report the server in use (if possible)
|
|
217
|
+
if defined?(::Unicorn)
|
|
218
|
+
platform_info['Ruby.AppContainer.Version'] = "Unicorn-#{::Unicorn::Const::UNICORN_VERSION}"
|
|
219
|
+
elsif defined?(::Puma)
|
|
220
|
+
platform_info['Ruby.AppContainer.Version'] = "Puma-#{::Puma::Const::PUMA_VERSION} (#{::Puma::Const::CODE_NAME})"
|
|
221
|
+
elsif defined?(::PhusionPassenger)
|
|
222
|
+
platform_info['Ruby.AppContainer.Version'] = "#{::PhusionPassenger::PACKAGE_NAME}-#{::PhusionPassenger::VERSION_STRING}"
|
|
223
|
+
elsif defined?(::Thin)
|
|
224
|
+
platform_info['Ruby.AppContainer.Version'] = "Thin-#{::Thin::VERSION::STRING} (#{::Thin::VERSION::CODENAME})"
|
|
225
|
+
elsif defined?(::Mongrel)
|
|
226
|
+
platform_info['Ruby.AppContainer.Version'] = "Mongrel-#{::Mongrel::Const::MONGREL_VERSION}"
|
|
227
|
+
elsif defined?(::Mongrel2)
|
|
228
|
+
platform_info['Ruby.AppContainer.Version'] = "Mongrel2-#{::Mongrel2::VERSION}"
|
|
229
|
+
elsif defined?(::Trinidad)
|
|
230
|
+
platform_info['Ruby.AppContainer.Version'] = "Trinidad-#{::Trinidad::VERSION}"
|
|
231
|
+
elsif defined?(::WEBrick::VERSION)
|
|
232
|
+
platform_info['Ruby.AppContainer.Version'] = "WEBrick-#{::WEBrick::VERSION}"
|
|
233
|
+
else
|
|
234
|
+
platform_info['Ruby.AppContainer.Version'] = File.basename($PROGRAM_NAME)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
rescue StandardError, ScriptError => e
|
|
238
|
+
# Also rescue ScriptError (aka SyntaxError) in case one of the expected
|
|
239
|
+
# version defines don't exist
|
|
240
|
+
|
|
241
|
+
platform_info['Error'] = "Error in build_report: #{e.message}"
|
|
242
|
+
|
|
243
|
+
TraceView.logger.warn "[traceview/warn] Error in build_init_report: #{e.message}"
|
|
244
|
+
TraceView.logger.debug e.backtrace
|
|
245
|
+
end
|
|
246
|
+
platform_info
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|