traceview 3.0.0-java

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 (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rubocop.yml +5 -0
  4. data/.travis.yml +58 -0
  5. data/Appraisals +10 -0
  6. data/CHANGELOG.md +490 -0
  7. data/CONFIG.md +16 -0
  8. data/Gemfile +95 -0
  9. data/LICENSE +199 -0
  10. data/README.md +380 -0
  11. data/Rakefile +109 -0
  12. data/examples/DNT.md +35 -0
  13. data/examples/carrying_context.rb +225 -0
  14. data/examples/instrumenting_metal_controller.rb +8 -0
  15. data/examples/puma_on_heroku_config.rb +17 -0
  16. data/examples/tracing_async_threads.rb +125 -0
  17. data/examples/tracing_background_jobs.rb +52 -0
  18. data/examples/tracing_forked_processes.rb +100 -0
  19. data/examples/unicorn_on_heroku_config.rb +28 -0
  20. data/ext/oboe_metal/extconf.rb +61 -0
  21. data/ext/oboe_metal/noop/noop.c +7 -0
  22. data/ext/oboe_metal/src/bson/bson.h +221 -0
  23. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  24. data/ext/oboe_metal/src/oboe.h +275 -0
  25. data/ext/oboe_metal/src/oboe.hpp +352 -0
  26. data/ext/oboe_metal/src/oboe_wrap.cxx +3886 -0
  27. data/ext/oboe_metal/tests/test.rb +11 -0
  28. data/gemfiles/mongo.gemfile +33 -0
  29. data/gemfiles/moped.gemfile +33 -0
  30. data/get_version.rb +5 -0
  31. data/init.rb +4 -0
  32. data/lib/joboe_metal.rb +206 -0
  33. data/lib/oboe/README +2 -0
  34. data/lib/oboe/backward_compatibility.rb +59 -0
  35. data/lib/oboe/inst/rack.rb +11 -0
  36. data/lib/oboe.rb +7 -0
  37. data/lib/oboe_metal.rb +151 -0
  38. data/lib/rails/generators/traceview/install_generator.rb +76 -0
  39. data/lib/rails/generators/traceview/templates/traceview_initializer.rb +159 -0
  40. data/lib/traceview/api/layerinit.rb +51 -0
  41. data/lib/traceview/api/logging.rb +209 -0
  42. data/lib/traceview/api/memcache.rb +31 -0
  43. data/lib/traceview/api/profiling.rb +50 -0
  44. data/lib/traceview/api/tracing.rb +135 -0
  45. data/lib/traceview/api/util.rb +121 -0
  46. data/lib/traceview/api.rb +18 -0
  47. data/lib/traceview/base.rb +225 -0
  48. data/lib/traceview/config.rb +238 -0
  49. data/lib/traceview/frameworks/grape.rb +97 -0
  50. data/lib/traceview/frameworks/padrino/templates.rb +58 -0
  51. data/lib/traceview/frameworks/padrino.rb +64 -0
  52. data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
  53. data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
  54. data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
  55. data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
  56. data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
  57. data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
  58. data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
  59. data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
  60. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  61. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
  62. data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
  63. data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
  64. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
  65. data/lib/traceview/frameworks/rails.rb +145 -0
  66. data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
  67. data/lib/traceview/frameworks/sinatra.rb +95 -0
  68. data/lib/traceview/inst/cassandra.rb +279 -0
  69. data/lib/traceview/inst/dalli.rb +86 -0
  70. data/lib/traceview/inst/em-http-request.rb +99 -0
  71. data/lib/traceview/inst/excon.rb +111 -0
  72. data/lib/traceview/inst/faraday.rb +73 -0
  73. data/lib/traceview/inst/http.rb +87 -0
  74. data/lib/traceview/inst/httpclient.rb +173 -0
  75. data/lib/traceview/inst/memcache.rb +102 -0
  76. data/lib/traceview/inst/memcached.rb +94 -0
  77. data/lib/traceview/inst/mongo.rb +238 -0
  78. data/lib/traceview/inst/moped.rb +474 -0
  79. data/lib/traceview/inst/rack.rb +122 -0
  80. data/lib/traceview/inst/redis.rb +271 -0
  81. data/lib/traceview/inst/resque.rb +192 -0
  82. data/lib/traceview/inst/rest-client.rb +38 -0
  83. data/lib/traceview/inst/sequel.rb +162 -0
  84. data/lib/traceview/inst/typhoeus.rb +102 -0
  85. data/lib/traceview/instrumentation.rb +21 -0
  86. data/lib/traceview/loading.rb +94 -0
  87. data/lib/traceview/logger.rb +41 -0
  88. data/lib/traceview/method_profiling.rb +84 -0
  89. data/lib/traceview/ruby.rb +36 -0
  90. data/lib/traceview/support.rb +113 -0
  91. data/lib/traceview/thread_local.rb +26 -0
  92. data/lib/traceview/util.rb +250 -0
  93. data/lib/traceview/version.rb +16 -0
  94. data/lib/traceview/xtrace.rb +90 -0
  95. data/lib/traceview.rb +62 -0
  96. data/test/frameworks/apps/grape_nested.rb +30 -0
  97. data/test/frameworks/apps/grape_simple.rb +24 -0
  98. data/test/frameworks/apps/padrino_simple.rb +45 -0
  99. data/test/frameworks/apps/sinatra_simple.rb +24 -0
  100. data/test/frameworks/grape_test.rb +142 -0
  101. data/test/frameworks/padrino_test.rb +30 -0
  102. data/test/frameworks/sinatra_test.rb +30 -0
  103. data/test/instrumentation/cassandra_test.rb +380 -0
  104. data/test/instrumentation/dalli_test.rb +171 -0
  105. data/test/instrumentation/em_http_request_test.rb +86 -0
  106. data/test/instrumentation/excon_test.rb +207 -0
  107. data/test/instrumentation/faraday_test.rb +235 -0
  108. data/test/instrumentation/http_test.rb +140 -0
  109. data/test/instrumentation/httpclient_test.rb +296 -0
  110. data/test/instrumentation/memcache_test.rb +251 -0
  111. data/test/instrumentation/memcached_test.rb +226 -0
  112. data/test/instrumentation/mongo_test.rb +462 -0
  113. data/test/instrumentation/moped_test.rb +496 -0
  114. data/test/instrumentation/rack_test.rb +116 -0
  115. data/test/instrumentation/redis_hashes_test.rb +265 -0
  116. data/test/instrumentation/redis_keys_test.rb +318 -0
  117. data/test/instrumentation/redis_lists_test.rb +310 -0
  118. data/test/instrumentation/redis_misc_test.rb +160 -0
  119. data/test/instrumentation/redis_sets_test.rb +293 -0
  120. data/test/instrumentation/redis_sortedsets_test.rb +325 -0
  121. data/test/instrumentation/redis_strings_test.rb +333 -0
  122. data/test/instrumentation/resque_test.rb +62 -0
  123. data/test/instrumentation/rest-client_test.rb +294 -0
  124. data/test/instrumentation/sequel_mysql2_test.rb +326 -0
  125. data/test/instrumentation/sequel_mysql_test.rb +326 -0
  126. data/test/instrumentation/sequel_pg_test.rb +330 -0
  127. data/test/instrumentation/typhoeus_test.rb +285 -0
  128. data/test/minitest_helper.rb +187 -0
  129. data/test/profiling/method_test.rb +198 -0
  130. data/test/servers/rackapp_8101.rb +22 -0
  131. data/test/support/backcompat_test.rb +269 -0
  132. data/test/support/config_test.rb +128 -0
  133. data/test/support/dnt_test.rb +73 -0
  134. data/test/support/liboboe_settings_test.rb +104 -0
  135. data/test/support/xtrace_test.rb +35 -0
  136. data/traceview.gemspec +29 -0
  137. metadata +248 -0
@@ -0,0 +1,117 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Inst
6
+ module ConnectionAdapters
7
+ module Utils
8
+
9
+ def extract_trace_details(sql, name = nil, binds = [])
10
+ opts = {}
11
+
12
+ begin
13
+ if TraceView::Config[:sanitize_sql]
14
+ # Sanitize SQL and don't report binds
15
+ opts[:Query] = sql.gsub(/\'[\s\S][^\']*\'/, '?')
16
+ else
17
+ # Report raw SQL and any binds if they exist
18
+ opts[:Query] = sql.to_s
19
+ opts[:QueryArgs] = binds.map { |col, val| type_cast(val, col) } unless binds.empty?
20
+ end
21
+
22
+ opts[:Name] = name.to_s if name
23
+ opts[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:active_record][:collect_backtraces]
24
+
25
+ if ::Rails::VERSION::MAJOR == 2
26
+ config = ::Rails.configuration.database_configuration[::Rails.env]
27
+ else
28
+ config = ::Rails.application.config.database_configuration[::Rails.env]
29
+ end
30
+
31
+ opts[:Database] = config['database'] if config.key?('database')
32
+ opts[:RemoteHost] = config['host'] if config.key?('host')
33
+ opts[:Flavor] = config['adapter'] if config.key?('adapter')
34
+ rescue StandardError => e
35
+ TraceView.logger.debug "Exception raised capturing ActiveRecord KVs: #{e.inspect}"
36
+ TraceView.logger.debug e.backtrace.join('\n')
37
+ end
38
+
39
+ return opts || {}
40
+ end
41
+
42
+ # We don't want to trace framework caches. Only instrument SQL that
43
+ # directly hits the database.
44
+ def ignore_payload?(name)
45
+ %w(SCHEMA EXPLAIN CACHE).include?(name.to_s) ||
46
+ (name && name.to_sym == :skip_logging) ||
47
+ name == 'ActiveRecord::SchemaMigration Load'
48
+ end
49
+
50
+ # def cfg
51
+ # @config
52
+ # end
53
+
54
+ def execute_with_traceview(sql, name = nil)
55
+ if TraceView.tracing? && !ignore_payload?(name)
56
+
57
+ opts = extract_trace_details(sql, name)
58
+ TraceView::API.trace('activerecord', opts || {}) do
59
+ execute_without_traceview(sql, name)
60
+ end
61
+ else
62
+ execute_without_traceview(sql, name)
63
+ end
64
+ end
65
+
66
+ def exec_query_with_traceview(sql, name = nil, binds = [])
67
+ if TraceView.tracing? && !ignore_payload?(name)
68
+
69
+ opts = extract_trace_details(sql, name, binds)
70
+ TraceView::API.trace('activerecord', opts || {}) do
71
+ exec_query_without_traceview(sql, name, binds)
72
+ end
73
+ else
74
+ exec_query_without_traceview(sql, name, binds)
75
+ end
76
+ end
77
+
78
+ def exec_delete_with_traceview(sql, name = nil, binds = [])
79
+ if TraceView.tracing? && !ignore_payload?(name)
80
+
81
+ opts = extract_trace_details(sql, name, binds)
82
+ TraceView::API.trace('activerecord', opts || {}) do
83
+ exec_delete_without_traceview(sql, name, binds)
84
+ end
85
+ else
86
+ exec_delete_without_traceview(sql, name, binds)
87
+ end
88
+ end
89
+
90
+ def exec_insert_with_traceview(sql, name = nil, binds = [], *args)
91
+ if TraceView.tracing? && !ignore_payload?(name)
92
+
93
+ opts = extract_trace_details(sql, name, binds)
94
+ TraceView::API.trace('activerecord', opts || {}) do
95
+ exec_insert_without_traceview(sql, name, binds, *args)
96
+ end
97
+ else
98
+ exec_insert_without_traceview(sql, name, binds, *args)
99
+ end
100
+ end
101
+
102
+ def begin_db_transaction_with_traceview
103
+ if TraceView.tracing?
104
+ opts = {}
105
+
106
+ opts[:Query] = 'BEGIN'
107
+ TraceView::API.trace('activerecord', opts || {}) do
108
+ begin_db_transaction_without_traceview
109
+ end
110
+ else
111
+ begin_db_transaction_without_traceview
112
+ end
113
+ end
114
+ end # Utils
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,145 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Rails
6
+ module Helpers
7
+ extend ActiveSupport::Concern if defined?(::Rails) and ::Rails::VERSION::MAJOR > 2
8
+
9
+ @@rum_xhr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_ajax_header.js.erb')
10
+ @@rum_hdr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_header.js.erb')
11
+ @@rum_ftr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_footer.js.erb')
12
+
13
+ def traceview_rum_header
14
+ begin
15
+ return unless TraceView::Config.rum_id
16
+ if TraceView.tracing?
17
+ if request.xhr?
18
+ return raw(ERB.new(@@rum_xhr_tmpl).result)
19
+ else
20
+ return raw(ERB.new(@@rum_hdr_tmpl).result)
21
+ end
22
+ end
23
+ rescue StandardError => e
24
+ TraceView.logger.warn "traceview_rum_header: #{e.message}."
25
+ return ""
26
+ end
27
+ end
28
+
29
+ def traceview_rum_footer
30
+ begin
31
+ return unless TraceView::Config.rum_id
32
+ if TraceView.tracing?
33
+ # Even though the footer template is named xxxx.erb, there are no ERB tags in it so we'll
34
+ # skip that step for now
35
+ return raw(@@rum_ftr_tmpl)
36
+ end
37
+ rescue StandardError => e
38
+ TraceView.logger.warn "traceview_rum_footer: #{e.message}."
39
+ return ""
40
+ end
41
+ end
42
+ end # Helpers
43
+
44
+ def self.load_initializer
45
+ # Force load the TraceView Rails initializer if there is one
46
+ # Prefer traceview.rb but give priority to the legacy tracelytics.rb if it exists
47
+ if ::Rails::VERSION::MAJOR > 2
48
+ rails_root = "#{::Rails.root.to_s}"
49
+ else
50
+ rails_root = "#{RAILS_ROOT}"
51
+ end
52
+
53
+ #
54
+ # We've been through 3 initializer names. Try each one.
55
+ #
56
+ if File.exists?("#{rails_root}/config/initializers/tracelytics.rb")
57
+ tr_initializer = "#{rails_root}/config/initializers/tracelytics.rb"
58
+
59
+ elsif File.exists?("#{rails_root}/config/initializers/oboe.rb")
60
+ tr_initializer = "#{rails_root}/config/initializers/oboe.rb"
61
+
62
+ else
63
+ tr_initializer = "#{rails_root}/config/initializers/traceview.rb"
64
+ end
65
+ require tr_initializer if File.exists?(tr_initializer)
66
+ end
67
+
68
+ def self.load_instrumentation
69
+ # Load the Rails specific instrumentation
70
+ pattern = File.join(File.dirname(__FILE__), 'rails/inst', '*.rb')
71
+ Dir.glob(pattern) do |f|
72
+ begin
73
+ require f
74
+ rescue => e
75
+ TraceView.logger.error "[traceview/loading] Error loading rails insrumentation file '#{f}' : #{e}"
76
+ end
77
+ end
78
+
79
+ TraceView.logger.info "TraceView gem #{TraceView::Version::STRING} successfully loaded."
80
+ end
81
+
82
+ def self.include_helpers
83
+ # TBD: This would make the helpers available to controllers which is occasionally desired.
84
+ # ActiveSupport.on_load(:action_controller) do
85
+ # include TraceView::Rails::Helpers
86
+ # end
87
+ if ::Rails::VERSION::MAJOR > 2
88
+ ActiveSupport.on_load(:action_view) do
89
+ include TraceView::Rails::Helpers
90
+ end
91
+ else
92
+ ActionView::Base.send :include, TraceView::Rails::Helpers
93
+ end
94
+ end
95
+
96
+ end # Rails
97
+ end # TraceView
98
+
99
+ if defined?(::Rails)
100
+ require 'traceview/inst/rack'
101
+
102
+ if ::Rails::VERSION::MAJOR > 2
103
+ module TraceView
104
+ class Railtie < ::Rails::Railtie
105
+
106
+ initializer 'traceview.helpers' do
107
+ TraceView::Rails.include_helpers
108
+ end
109
+
110
+ initializer 'traceview.rack' do |app|
111
+ TraceView.logger.info "[traceview/loading] Instrumenting rack" if TraceView::Config[:verbose]
112
+ app.config.middleware.insert 0, "TraceView::Rack"
113
+ end
114
+
115
+ config.after_initialize do
116
+ TraceView.logger = ::Rails.logger if ::Rails.logger
117
+
118
+ TraceView::Loading.load_access_key
119
+ TraceView::Inst.load_instrumentation
120
+ TraceView::Rails.load_instrumentation
121
+
122
+ # Report __Init after fork when in Heroku
123
+ TraceView::API.report_init unless TraceView.heroku?
124
+ end
125
+ end
126
+ end
127
+ else
128
+ TraceView.logger = ::Rails.logger if ::Rails.logger
129
+
130
+ TraceView::Rails.load_initializer
131
+ TraceView::Loading.load_access_key
132
+
133
+ Rails.configuration.after_initialize do
134
+ TraceView.logger.info "[traceview/loading] Instrumenting rack" if TraceView::Config[:verbose]
135
+ Rails.configuration.middleware.insert 0, "TraceView::Rack"
136
+
137
+ TraceView::Inst.load_instrumentation
138
+ TraceView::Rails.load_instrumentation
139
+ TraceView::Rails.include_helpers
140
+
141
+ # Report __Init after fork when in Heroku
142
+ TraceView::API.report_init unless TraceView.heroku?
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Sinatra
6
+ module Templates
7
+ def self.included(klass)
8
+ ::TraceView::Util.method_alias(klass, :render, ::Sinatra::Templates)
9
+ end
10
+
11
+ def render_with_traceview(engine, data, options = {}, locals = {}, &block)
12
+ if TraceView.tracing?
13
+ report_kvs = {}
14
+
15
+ report_kvs[:engine] = engine
16
+ report_kvs[:template] = data
17
+
18
+ if TraceView.tracing_layer_op?('render')
19
+ # For recursive calls to :render (for sub-partials and layouts),
20
+ # use method profiling.
21
+ begin
22
+ name = data
23
+ report_kvs[:FunctionName] = :render
24
+ report_kvs[:Class] = :Templates
25
+ report_kvs[:Module] = 'Sinatra::Templates'
26
+ report_kvs[:File] = __FILE__
27
+ report_kvs[:LineNumber] = __LINE__
28
+ rescue StandardError => e
29
+ ::TraceView.logger.debug e.message
30
+ ::TraceView.logger.debug e.backtrace.join(", ")
31
+ end
32
+
33
+ TraceView::API.profile(name, report_kvs, false) do
34
+ render_without_traceview(engine, data, options, locals, &block)
35
+ end
36
+
37
+ else
38
+ # Fall back to the raw tracing API so we can pass KVs
39
+ # back on exit (a limitation of the TraceView::API.trace
40
+ # block method) This removes the need for an info
41
+ # event to send additonal KVs
42
+ ::TraceView::API.log_entry('render', {}, 'render')
43
+
44
+ begin
45
+ render_without_traceview(engine, data, options, locals, &block)
46
+ ensure
47
+ ::TraceView::API.log_exit('render', report_kvs)
48
+ end
49
+ end
50
+ else
51
+ render_without_traceview(engine, data, options, locals, &block)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,95 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Sinatra
6
+ module Base
7
+ def self.included(klass)
8
+ ::TraceView::Util.method_alias(klass, :dispatch!, ::Sinatra::Base)
9
+ ::TraceView::Util.method_alias(klass, :handle_exception!, ::Sinatra::Base)
10
+ end
11
+
12
+ def dispatch_with_traceview
13
+ if TraceView.tracing?
14
+ report_kvs = {}
15
+
16
+ report_kvs[:Controller] = self.class
17
+ report_kvs[:Action] = env['PATH_INFO']
18
+
19
+ # Fall back to the raw tracing API so we can pass KVs
20
+ # back on exit (a limitation of the TraceView::API.trace
21
+ # block method) This removes the need for an info
22
+ # event to send additonal KVs
23
+ ::TraceView::API.log_entry('sinatra', {})
24
+
25
+ begin
26
+ dispatch_without_traceview
27
+ ensure
28
+ ::TraceView::API.log_exit('sinatra', report_kvs)
29
+ end
30
+ else
31
+ dispatch_without_traceview
32
+ end
33
+ end
34
+
35
+ def handle_exception_with_traceview(boom)
36
+ TraceView::API.log_exception(nil, boom) if TraceView.tracing?
37
+ handle_exception_without_traceview(boom)
38
+ end
39
+
40
+ @@rum_xhr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_ajax_header.js.erb')
41
+ @@rum_hdr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_header.js.erb')
42
+ @@rum_ftr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_footer.js.erb')
43
+
44
+ def traceview_rum_header
45
+ return unless TraceView::Config.rum_id
46
+ if TraceView.tracing?
47
+ if request.xhr?
48
+ return ERB.new(@@rum_xhr_tmpl).result
49
+ else
50
+ return ERB.new(@@rum_hdr_tmpl).result
51
+ end
52
+ end
53
+ rescue StandardError => e
54
+ TraceView.logger.warn "traceview_rum_header: #{e.message}."
55
+ return ''
56
+ end
57
+
58
+ def traceview_rum_footer
59
+ return unless TraceView::Config.rum_id
60
+ if TraceView.tracing?
61
+ # Even though the footer template is named xxxx.erb, there are no ERB tags in it so we'll
62
+ # skip that step for now
63
+ return @@rum_ftr_tmpl
64
+ end
65
+ rescue StandardError => e
66
+ TraceView.logger.warn "traceview_rum_footer: #{e.message}."
67
+ return ''
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ if defined?(::Sinatra)
74
+ require 'traceview/inst/rack'
75
+ require 'traceview/frameworks/sinatra/templates'
76
+
77
+ TraceView.logger.info '[traceview/loading] Instrumenting Sinatra' if TraceView::Config[:verbose]
78
+
79
+ TraceView::Loading.load_access_key
80
+ TraceView::Inst.load_instrumentation
81
+
82
+ ::Sinatra::Base.use TraceView::Rack
83
+
84
+ # When in the gem TEST environment, we load this instrumentation regardless.
85
+ # Otherwise, only when Padrino isn't around.
86
+ unless defined?(::Padrino) and not (ENV.key?('TRACEVIEW_GEM_TEST'))
87
+ # Padrino has 'enhanced' routes and rendering so the Sinatra
88
+ # instrumentation won't work anyways. Only load for pure Sinatra apps.
89
+ ::TraceView::Util.send_include(::Sinatra::Base, ::TraceView::Sinatra::Base)
90
+ ::TraceView::Util.send_include(::Sinatra::Templates, ::TraceView::Sinatra::Templates)
91
+
92
+ # Report __Init after fork when in Heroku
93
+ TraceView::API.report_init unless TraceView.heroku?
94
+ end
95
+ end
@@ -0,0 +1,279 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Inst
6
+ module Cassandra
7
+ def extract_trace_details(op, column_family, keys, args, options = {})
8
+ report_kvs = {}
9
+
10
+ begin
11
+ report_kvs[:Op] = op.to_s
12
+ report_kvs[:Cf] = column_family.to_s if column_family
13
+ report_kvs[:Key] = keys.inspect if keys
14
+
15
+ # Open issue - how to handle multiple Cassandra servers
16
+ report_kvs[:RemoteHost], report_kvs[:RemotePort] = @servers.first.split(':')
17
+
18
+ report_kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:cassandra][:collect_backtraces]
19
+
20
+ if options.empty? && args.is_a?(Array)
21
+ options = args.last if args.last.is_a?(Hash)
22
+ end
23
+
24
+ unless options.empty?
25
+ [:start_key, :finish_key, :key_count, :batch_size, :columns, :count, :start,
26
+ :stop, :finish, :finished, :reversed, :consistency, :ttl].each do |k|
27
+ report_kvs[k.to_s.capitalize] = options[k] if options.key?(k)
28
+ end
29
+
30
+ if op == :get_indexed_slices
31
+ index_clause = columns_and_options[:index_clause] || {}
32
+ unless index_clause.empty?
33
+ [:column_name, :value, :comparison].each do |k|
34
+ report_kvs[k.to_s.capitalize] = index_clause[k] if index_clause.key?(k)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ rescue
40
+ end
41
+
42
+ report_kvs
43
+ end
44
+
45
+ def insert_with_traceview(column_family, key, hash, options = {})
46
+ return insert_without_traceview(column_family, key, hash, options = {}) unless TraceView.tracing?
47
+
48
+ report_kvs = extract_trace_details(:insert, column_family, key, hash, options)
49
+
50
+ TraceView::API.trace('cassandra', report_kvs) do
51
+ insert_without_traceview(column_family, key, hash, options = {})
52
+ end
53
+ end
54
+
55
+ def remove_with_traceview(column_family, key, *columns_and_options)
56
+ return send :remove_without_traceview, *args unless TraceView.tracing?
57
+
58
+ args = [column_family, key] + columns_and_options
59
+ report_kvs = extract_trace_details(:remove, column_family, key, columns_and_options)
60
+
61
+ TraceView::API.trace('cassandra', report_kvs) do
62
+ send :remove_without_traceview, *args
63
+ end
64
+ end
65
+
66
+ def count_columns_with_traceview(column_family, key, *columns_and_options)
67
+ return send :count_columns_without_traceview, *args unless TraceView.tracing?
68
+
69
+ args = [column_family, key] + columns_and_options
70
+ report_kvs = extract_trace_details(:count_columns, column_family, key, columns_and_options)
71
+
72
+ TraceView::API.trace('cassandra', report_kvs) do
73
+ send :count_columns_without_traceview, *args
74
+ end
75
+ end
76
+
77
+ def get_columns_with_traceview(column_family, key, *columns_and_options)
78
+ args = [column_family, key] + columns_and_options
79
+
80
+ if TraceView.tracing? && !TraceView.tracing_layer_op?(:multi_get_columns)
81
+ report_kvs = extract_trace_details(:get_columns, column_family, key, columns_and_options)
82
+
83
+ TraceView::API.trace('cassandra', report_kvs) do
84
+ send :get_columns_without_traceview, *args
85
+ end
86
+ else
87
+ send :get_columns_without_traceview, *args
88
+ end
89
+ end
90
+
91
+ def multi_get_columns_with_traceview(column_family, key, *columns_and_options)
92
+ return send :multi_get_columns_without_traceview, *args unless TraceView.tracing?
93
+
94
+ args = [column_family, key] + columns_and_options
95
+ report_kvs = extract_trace_details(:multi_get_columns, column_family, key, columns_and_options)
96
+
97
+ TraceView::API.trace('cassandra', report_kvs, :multi_get_columns) do
98
+ send :multi_get_columns_without_traceview, *args
99
+ end
100
+ end
101
+
102
+ def get_with_traceview(column_family, key, *columns_and_options)
103
+ return send :get_without_traceview, *args unless TraceView.tracing?
104
+
105
+ args = [column_family, key] + columns_and_options
106
+ report_kvs = extract_trace_details(:get, column_family, key, columns_and_options)
107
+
108
+ TraceView::API.trace('cassandra', report_kvs, :get) do
109
+ send :get_without_traceview, *args
110
+ end
111
+ end
112
+
113
+ def multi_get_with_traceview(column_family, key, *columns_and_options)
114
+ args = [column_family, key] + columns_and_options
115
+
116
+ if TraceView.tracing? && !TraceView.tracing_layer_op?(:get)
117
+ report_kvs = extract_trace_details(:multi_get, column_family, key, columns_and_options)
118
+
119
+ TraceView::API.trace('cassandra', report_kvs) do
120
+ send :multi_get_without_traceview, *args
121
+ end
122
+ else
123
+ send :multi_get_without_traceview, *args
124
+ end
125
+ end
126
+
127
+ def exists_with_traceview?(column_family, key, *columns_and_options)
128
+ return send :exists_without_traceview?, *args unless TraceView.tracing?
129
+
130
+ args = [column_family, key] + columns_and_options
131
+ report_kvs = extract_trace_details(:exists?, column_family, key, columns_and_options)
132
+
133
+ TraceView::API.trace('cassandra', report_kvs) do
134
+ send :exists_without_traceview?, *args
135
+ end
136
+ end
137
+
138
+ def get_range_single_with_traceview(column_family, options = {})
139
+ if TraceView.tracing? && !TraceView.tracing_layer_op?(:get_range_batch)
140
+ report_kvs = extract_trace_details(:get_range_single, column_family, nil, nil)
141
+
142
+ TraceView::API.trace('cassandra', report_kvs) do
143
+ get_range_single_without_traceview(column_family, options)
144
+ end
145
+ else
146
+ get_range_single_without_traceview(column_family, options)
147
+ end
148
+ end
149
+
150
+ def get_range_batch_with_traceview(column_family, options = {})
151
+ return get_range_batch_without_traceview(column_family, options) unless TraceView.tracing?
152
+
153
+ report_kvs = extract_trace_details(:get_range_batch, column_family, nil, nil)
154
+
155
+ TraceView::API.trace('cassandra', report_kvs, :get_range_batch) do
156
+ get_range_batch_without_traceview(column_family, options)
157
+ end
158
+ end
159
+
160
+ def get_indexed_slices_with_traceview(column_family, index_clause, *columns_and_options)
161
+ return send :get_indexed_slices_without_traceview, *args unless TraceView.tracing?
162
+
163
+ args = [column_family, index_clause] + columns_and_options
164
+ report_kvs = extract_trace_details(:get_indexed_slices, column_family, nil, columns_and_options)
165
+
166
+ TraceView::API.trace('cassandra', report_kvs) do
167
+ send :get_indexed_slices_without_traceview, *args
168
+ end
169
+ end
170
+
171
+ def create_index_with_traceview(keyspace, column_family, column_name, validation_class)
172
+ unless TraceView.tracing?
173
+ return create_index_without_traceview(keyspace, column_family, column_name, validation_class)
174
+ end
175
+
176
+ report_kvs = extract_trace_details(:create_index, column_family, nil, nil)
177
+ begin
178
+ report_kvs[:Keyspace] = keyspace.to_s
179
+ report_kvs[:Column_name] = column_name.to_s
180
+ report_kvs[:Validation_class] = validation_class.to_s
181
+ rescue
182
+ end
183
+
184
+ TraceView::API.trace('cassandra', report_kvs) do
185
+ create_index_without_traceview(keyspace, column_family, column_name, validation_class)
186
+ end
187
+ end
188
+
189
+ def drop_index_with_traceview(keyspace, column_family, column_name)
190
+ return drop_index_without_traceview(keyspace, column_family, column_name) unless TraceView.tracing?
191
+
192
+ report_kvs = extract_trace_details(:drop_index, column_family, nil, nil)
193
+ begin
194
+ report_kvs[:Keyspace] = keyspace.to_s
195
+ report_kvs[:Column_name] = column_name.to_s
196
+ rescue
197
+ end
198
+
199
+ TraceView::API.trace('cassandra', report_kvs) do
200
+ drop_index_without_traceview(keyspace, column_family, column_name)
201
+ end
202
+ end
203
+
204
+ def add_column_family_with_traceview(cf_def)
205
+ return add_column_family_without_traceview(cf_def) unless TraceView.tracing?
206
+
207
+ report_kvs = extract_trace_details(:add_column_family, nil, nil, nil)
208
+ begin
209
+ report_kvs[:Cf] = cf_def[:name] if cf_def.is_a?(Hash) && cf_def.key?(:name)
210
+ rescue
211
+ end
212
+
213
+ TraceView::API.trace('cassandra', report_kvs) do
214
+ add_column_family_without_traceview(cf_def)
215
+ end
216
+ end
217
+
218
+ def drop_column_family_with_traceview(column_family)
219
+ return drop_column_family_without_traceview(column_family) unless TraceView.tracing?
220
+
221
+ report_kvs = extract_trace_details(:drop_column_family, column_family, nil, nil)
222
+
223
+ TraceView::API.trace('cassandra', report_kvs) do
224
+ drop_column_family_without_traceview(column_family)
225
+ end
226
+ end
227
+
228
+ def add_keyspace_with_traceview(ks_def)
229
+ return add_keyspace_without_traceview(ks_def) unless TraceView.tracing?
230
+
231
+ report_kvs = extract_trace_details(:add_keyspace, nil, nil, nil)
232
+ report_kvs[:Name] = ks_def.name rescue ''
233
+
234
+ TraceView::API.trace('cassandra', report_kvs) do
235
+ add_keyspace_without_traceview(ks_def)
236
+ end
237
+ end
238
+
239
+ def drop_keyspace_with_traceview(keyspace)
240
+ return drop_keyspace_without_traceview(keyspace) unless TraceView.tracing?
241
+
242
+ report_kvs = extract_trace_details(:drop_keyspace, nil, nil, nil)
243
+ report_kvs[:Name] = keyspace.to_s rescue ''
244
+
245
+ TraceView::API.trace('cassandra', report_kvs) do
246
+ drop_keyspace_without_traceview(keyspace)
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ if defined?(::Cassandra) && TraceView::Config[:cassandra][:enabled]
254
+ TraceView.logger.info '[traceview/loading] Instrumenting cassandra' if TraceView::Config[:verbose]
255
+
256
+ class ::Cassandra
257
+ include TraceView::Inst::Cassandra
258
+
259
+ [:insert, :remove, :count_columns, :get_columns, :multi_get_columns, :get,
260
+ :multi_get, :get_range_single, :get_range_batch, :get_indexed_slices,
261
+ :create_index, :drop_index, :add_column_family, :drop_column_family,
262
+ :add_keyspace, :drop_keyspace].each do |m|
263
+ if method_defined?(m)
264
+ class_eval "alias #{m}_without_traceview #{m}"
265
+ class_eval "alias #{m} #{m}_with_traceview"
266
+ else TraceView.logger.warn "[traceview/loading] Couldn't properly instrument Cassandra (#{m}). Partial traces may occur."
267
+ end
268
+ end
269
+
270
+ # Special case handler for question mark methods
271
+ if method_defined?(:exists?)
272
+ alias exists_without_traceview? exists?
273
+ alias exists? exists_with_traceview?
274
+ else TraceView.logger.warn '[traceview/loading] Couldn\'t properly instrument Cassandra (exists?). Partial traces may occur.'
275
+ end
276
+ end # class Cassandra
277
+ end
278
+
279
+