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.
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.rb +7 -0
  34. data/lib/oboe/README +2 -0
  35. data/lib/oboe/backward_compatibility.rb +59 -0
  36. data/lib/oboe/inst/rack.rb +11 -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.rb +62 -0
  41. data/lib/traceview/api.rb +18 -0
  42. data/lib/traceview/api/layerinit.rb +51 -0
  43. data/lib/traceview/api/logging.rb +209 -0
  44. data/lib/traceview/api/memcache.rb +31 -0
  45. data/lib/traceview/api/profiling.rb +50 -0
  46. data/lib/traceview/api/tracing.rb +135 -0
  47. data/lib/traceview/api/util.rb +121 -0
  48. data/lib/traceview/base.rb +225 -0
  49. data/lib/traceview/config.rb +238 -0
  50. data/lib/traceview/frameworks/grape.rb +97 -0
  51. data/lib/traceview/frameworks/padrino.rb +64 -0
  52. data/lib/traceview/frameworks/padrino/templates.rb +58 -0
  53. data/lib/traceview/frameworks/rails.rb +145 -0
  54. data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
  55. data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
  56. data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
  57. data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
  58. data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
  59. data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
  60. data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
  61. data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
  62. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  63. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
  64. data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
  65. data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
  66. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
  67. data/lib/traceview/frameworks/sinatra.rb +95 -0
  68. data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
  69. data/lib/traceview/inst/cassandra.rb +279 -0
  70. data/lib/traceview/inst/dalli.rb +86 -0
  71. data/lib/traceview/inst/em-http-request.rb +99 -0
  72. data/lib/traceview/inst/excon.rb +111 -0
  73. data/lib/traceview/inst/faraday.rb +73 -0
  74. data/lib/traceview/inst/http.rb +87 -0
  75. data/lib/traceview/inst/httpclient.rb +173 -0
  76. data/lib/traceview/inst/memcache.rb +102 -0
  77. data/lib/traceview/inst/memcached.rb +94 -0
  78. data/lib/traceview/inst/mongo.rb +238 -0
  79. data/lib/traceview/inst/moped.rb +474 -0
  80. data/lib/traceview/inst/rack.rb +122 -0
  81. data/lib/traceview/inst/redis.rb +271 -0
  82. data/lib/traceview/inst/resque.rb +192 -0
  83. data/lib/traceview/inst/rest-client.rb +38 -0
  84. data/lib/traceview/inst/sequel.rb +162 -0
  85. data/lib/traceview/inst/typhoeus.rb +102 -0
  86. data/lib/traceview/instrumentation.rb +21 -0
  87. data/lib/traceview/loading.rb +94 -0
  88. data/lib/traceview/logger.rb +41 -0
  89. data/lib/traceview/method_profiling.rb +84 -0
  90. data/lib/traceview/ruby.rb +36 -0
  91. data/lib/traceview/support.rb +113 -0
  92. data/lib/traceview/thread_local.rb +26 -0
  93. data/lib/traceview/util.rb +250 -0
  94. data/lib/traceview/version.rb +16 -0
  95. data/lib/traceview/xtrace.rb +90 -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 +250 -0
@@ -0,0 +1,76 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.join(File.dirname(__FILE__), 'templates')
7
+ desc "Copies an oboe initializer files to your application."
8
+
9
+ def copy_initializer
10
+ # Set defaults
11
+ @tracing_mode = 'through'
12
+ @sample_rate = '300000'
13
+ @verbose = 'false'
14
+
15
+ print_header
16
+
17
+ while true do
18
+ print_body
19
+
20
+ user_tracing_mode = ask shell.set_color "* Tracing Mode? [through]:", :yellow
21
+ user_tracing_mode.downcase!
22
+
23
+ break if user_tracing_mode.blank?
24
+ valid = ['always', 'through', 'never'].include?(user_tracing_mode)
25
+
26
+ say shell.set_color "Valid values are 'always', 'through' or 'never'", :red, :bold unless valid
27
+ if valid
28
+ @tracing_mode = user_tracing_mode
29
+ break
30
+ end
31
+ end
32
+
33
+ print_footer
34
+
35
+ template "oboe_initializer.rb", "config/initializers/traceview.rb"
36
+ end
37
+
38
+ private
39
+
40
+ def print_header
41
+ say ""
42
+ say shell.set_color "Welcome to the TraceView Ruby instrumentation setup.", :green, :bold
43
+ say ""
44
+ say "To instrument your Rails application, you can setup your tracing strategy here."
45
+ say ""
46
+ say shell.set_color "Documentation Links", :magenta
47
+ say "-------------------"
48
+ say ""
49
+ say "Details on configuring your sample rate:"
50
+ say "https://support.appneta.com/cloud/configuring-sampling"
51
+ say ""
52
+ say "More information on instrumenting Ruby applications can be found here:"
53
+ say "https://support.appneta.com/cloud/installing-ruby-instrumentation"
54
+ end
55
+
56
+ def print_body
57
+ say ""
58
+ say shell.set_color "Tracing Mode", :magenta
59
+ say "------------"
60
+ say "Tracing Mode determines when traces should be initiated for incoming requests. Valid"
61
+ say "options are #{shell.set_color "always", :yellow}, #{shell.set_color "through", :yellow} (when using an instrumented Apache or Nginx) and #{shell.set_color "never", :yellow}."
62
+ say ""
63
+ say "If you're not using an instrumented Apache or Nginx, set this directive to #{shell.set_color "always", :yellow} in"
64
+ say "order to initiate tracing from Ruby."
65
+ say ""
66
+ end
67
+
68
+ def print_footer
69
+ say ""
70
+ say "You can change configuration values in the future by modifying config/initializers/traceview.rb"
71
+ say ""
72
+ say "Thanks! Creating the TraceView initializer..."
73
+ say ""
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,159 @@
1
+ # AppNeta TraceView Initializer (the oboe gem)
2
+ # http://www.appneta.com/products/traceview/
3
+ #
4
+ # More information on instrumenting Ruby applications can be found here:
5
+ # https://support.appneta.com/cloud/installing-ruby-instrumentation
6
+
7
+ if defined?(TraceView::Config)
8
+ # Tracing Mode determines when traces should be initiated for incoming requests. Valid
9
+ # options are always, through (when using an instrumented Apache or Nginx) and never.
10
+ #
11
+ # If you're not using an instrumented Apache or Nginx, set this directive to always in
12
+ # order to initiate tracing from Ruby.
13
+ TraceView::Config[:tracing_mode] = '<%= @tracing_mode %>'
14
+
15
+ # Verbose output of instrumentation initialization
16
+ # TraceView::Config[:verbose] = <%= @verbose %>
17
+
18
+ # Logging of outgoing HTTP query args
19
+ #
20
+ # This optionally disables the logging of query args of outgoing
21
+ # HTTP clients such as Net::HTTP, excon, typhoeus and others.
22
+ #
23
+ # This flag is global to all HTTP client instrumentation.
24
+ #
25
+ # To configure this on a per instrumentation basis, set this
26
+ # option to true and instead disable the instrumenstation specific
27
+ # option <tt>log_args</tt>:
28
+ #
29
+ # TraceView::Config[:nethttp][:log_args] = false
30
+ # TraceView::Config[:excon][:log_args] = false
31
+ # TraceView::Config[:typhoeus][:log_args] = true
32
+ #
33
+ TraceView::Config[:include_url_query_params] = true
34
+
35
+ # Logging of incoming HTTP query args
36
+ #
37
+ # This optionally disables the logging of incoming URL request
38
+ # query args.
39
+ #
40
+ # This flag is global and currently only affects the Rack
41
+ # instrumentation which reports incoming request URLs and
42
+ # query args by default.
43
+ TraceView::Config[:include_remote_url_params] = true
44
+
45
+ # The oboe Ruby client has the ability to sanitize query literals
46
+ # from SQL statements. By default this is disabled. Enable to
47
+ # avoid collecting and reporting query literals to TraceView.
48
+ # TraceView::Config[:sanitize_sql] = false
49
+
50
+ # Do Not Trace
51
+ # These two values allow you to configure specific URL patterns to
52
+ # never be traced. By default, this is set to common static file
53
+ # extensions but you may want to customize this list for your needs.
54
+ #
55
+ # dnt_regexp and dnt_opts is passed to Regexp.new to create
56
+ # a regular expression object. That is then used to match against
57
+ # the incoming request path.
58
+ #
59
+ # The path string originates from the rack layer and is retrieved
60
+ # as follows:
61
+ #
62
+ # req = ::Rack::Request.new(env)
63
+ # path = URI.unescape(req.path)
64
+ #
65
+ # Usage:
66
+ # TraceView::Config[:dnt_regexp] = "lobster$"
67
+ # TraceView::Config[:dnt_opts] = Regexp::IGNORECASE
68
+ #
69
+ # This will ignore all requests that end with the string lobster
70
+ # regardless of case
71
+ #
72
+ # Requests with positive matches (non nil) will not be traced.
73
+ # See lib/oboe/util.rb: TraceView::Util.static_asset?
74
+ #
75
+ # TraceView::Config[:dnt_regexp] = "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|ttf|woff|svg|less)$"
76
+ # TraceView::Config[:dnt_opts] = Regexp::IGNORECASE
77
+
78
+ #
79
+ # Rails Exception Logging
80
+ #
81
+ # In Rails, raised exceptions with rescue handlers via
82
+ # <tt>rescue_from</tt> are not reported to the TraceView
83
+ # dashboard by default. Setting this value to true will
84
+ # report all raised exception regardless.
85
+ #
86
+ # TraceView::Config[:report_rescued_errors] = false
87
+ #
88
+
89
+ #
90
+ # Enabling/Disabling Instrumentation
91
+ #
92
+ # If you're having trouble with one of the instrumentation libraries, they
93
+ # can be individually disabled here by setting the :enabled
94
+ # value to false:
95
+ #
96
+ # TraceView::Config[:action_controller][:enabled] = true
97
+ # TraceView::Config[:active_record][:enabled] = true
98
+ # TraceView::Config[:action_view][:enabled] = true
99
+ # TraceView::Config[:cassandra][:enabled] = true
100
+ # TraceView::Config[:dalli][:enabled] = true
101
+ # TraceView::Config[:excon][:enabled] = true
102
+ # TraceView::Config[:em_http_request][:enabled] = true
103
+ # TraceView::Config[:faraday][:enabled] = true
104
+ # TraceView::Config[:httpclient][:enabled] = true
105
+ # TraceView::Config[:memcache][:enabled] = true
106
+ # TraceView::Config[:memcached][:enabled] = true
107
+ # TraceView::Config[:mongo][:enabled] = true
108
+ # TraceView::Config[:moped][:enabled] = true
109
+ # TraceView::Config[:nethttp][:enabled] = true
110
+ # TraceView::Config[:redis][:enabled] = true
111
+ # TraceView::Config[:resque][:enabled] = true
112
+ # TraceView::Config[:rest_client][:enabled] = true
113
+ # TraceView::Config[:sequel][:enabled] = true
114
+ # TraceView::Config[:typhoeus][:enabled] = true
115
+ #
116
+
117
+ #
118
+ # Enabling/Disabling Backtrace Collection
119
+ #
120
+ # Instrumentation can optionally collect backtraces as they collect
121
+ # performance metrics. Note that this has a negative impact on
122
+ # performance but can be useful when trying to locate the source of
123
+ # a certain call or operation.
124
+ #
125
+ # TraceView::Config[:action_controller][:collect_backtraces] = true
126
+ # TraceView::Config[:active_record][:collect_backtraces] = true
127
+ # TraceView::Config[:action_view][:collect_backtraces] = true
128
+ # TraceView::Config[:cassandra][:collect_backtraces] = true
129
+ # TraceView::Config[:dalli][:collect_backtraces] = false
130
+ # TraceView::Config[:excon][:collect_backtraces] = false
131
+ # TraceView::Config[:em_http_request][:collect_backtraces] = true
132
+ # TraceView::Config[:faraday][:collect_backtraces] = false
133
+ # TraceView::Config[:httpclient][:collect_backtraces] = false
134
+ # TraceView::Config[:memcache][:collect_backtraces] = false
135
+ # TraceView::Config[:memcached][:collect_backtraces] = false
136
+ # TraceView::Config[:mongo][:collect_backtraces] = true
137
+ # TraceView::Config[:moped][:collect_backtraces] = true
138
+ # TraceView::Config[:nethttp][:collect_backtraces] = true
139
+ # TraceView::Config[:redis][:collect_backtraces] = false
140
+ # TraceView::Config[:resque][:collect_backtraces] = true
141
+ # TraceView::Config[:rest_client][:collect_backtraces] = true
142
+ # TraceView::Config[:sequel][:collect_backtraces] = true
143
+ # TraceView::Config[:typhoeus][:collect_backtraces] = false
144
+ #
145
+
146
+ #
147
+ # Resque Options
148
+ #
149
+ # :link_workers - associates Resque enqueue operations with the jobs they queue by piggybacking
150
+ # an additional argument on the Redis queue that is stripped prior to job
151
+ # processing
152
+ # !!! Note: Make sure both the enqueue side and the Resque workers are instrumented
153
+ # before enabling this or jobs will fail !!!
154
+ # (Default: false)
155
+ # TraceView::Config[:resque][:link_workers] = false
156
+ #
157
+ # Set to true to disable Resque argument logging (Default: false)
158
+ # TraceView::Config[:resque][:log_args] = false
159
+ end
data/lib/traceview.rb ADDED
@@ -0,0 +1,62 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ # Backward compatibility for supported environment variables
5
+ ENV['TRACEVIEW_GEM_VERBOSE'] = ENV['OBOE_GEM_VERBOSE'] if ENV.key?('OBOE_GEM_VERBOSE')
6
+ ENV['TRACEVIEW_GEM_TEST'] = ENV['OBOE_GEM_TEST'] if ENV.key?('OBOE_GEM_TEST')
7
+
8
+ begin
9
+ require 'traceview/version'
10
+ require 'traceview/thread_local'
11
+ require 'traceview/logger'
12
+ require 'traceview/util'
13
+ require 'traceview/xtrace'
14
+ require 'traceview/support'
15
+
16
+ # If OboeHeroku is already defined then we are in a PaaS environment
17
+ # with an alternate metal (see the oboe-heroku gem)
18
+ unless defined?(OboeHeroku)
19
+ require 'traceview/base'
20
+
21
+ begin
22
+ if RUBY_PLATFORM == 'java'
23
+ require '/usr/local/tracelytics/tracelyticsagent.jar'
24
+ require 'joboe_metal'
25
+ else
26
+ require "oboe_metal.so"
27
+ require "oboe_metal.rb"
28
+ end
29
+ rescue LoadError
30
+ TraceView.loaded = false
31
+
32
+ unless ENV['RAILS_GROUP'] == 'assets' or ENV['IGNORE_TRACEVIEW_WARNING']
33
+ $stderr.puts '=============================================================='
34
+ $stderr.puts 'Missing TraceView libraries. Tracing disabled.'
35
+ $stderr.puts 'See: http://bit.ly/1DaNOjw'
36
+ $stderr.puts '=============================================================='
37
+ end
38
+ end
39
+ end
40
+
41
+ require 'traceview/config'
42
+ require 'traceview/loading'
43
+
44
+ if TraceView.loaded
45
+ require 'traceview/method_profiling'
46
+ require 'traceview/instrumentation'
47
+
48
+ # Frameworks
49
+ require 'traceview/frameworks/rails'
50
+ require 'traceview/frameworks/sinatra'
51
+ require 'traceview/frameworks/padrino'
52
+ require 'traceview/frameworks/grape'
53
+ end
54
+
55
+ # Load Ruby module last. If there is no framework detected,
56
+ # it will load all of the Ruby instrumentation
57
+ require 'traceview/ruby'
58
+ require 'oboe/backward_compatibility'
59
+ rescue => e
60
+ $stderr.puts "[traceview/error] Problem loading: #{e.inspect}"
61
+ $stderr.puts e.backtrace
62
+ end
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ ##
6
+ # This module implements the TraceView tracing API.
7
+ # See: https://github.com/appneta/oboe-ruby#the-tracing-api
8
+ # and/or: http://rdoc.info/gems/oboe/Oboe/API/Tracing
9
+ module API
10
+ def self.extend_with_tracing
11
+ extend TraceView::API::Logging
12
+ extend TraceView::API::Tracing
13
+ extend TraceView::API::Profiling
14
+ extend TraceView::API::LayerInit
15
+ end
16
+ extend TraceView::API::Util
17
+ end
18
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module API
6
+ ##
7
+ # Provides methods related to layer initialization and reporting
8
+ module LayerInit
9
+ # Internal: Report that instrumentation for the given layer has been
10
+ # installed, as well as the version of instrumentation and version of
11
+ # layer.
12
+ #
13
+ def report_init(layer = 'rack')
14
+ # Don't send __Init in development or test
15
+ return if %w(development test).include? ENV['RACK_ENV']
16
+
17
+ # Don't send __Init if the c-extension hasn't loaded
18
+ return unless TraceView.loaded
19
+
20
+ platform_info = TraceView::Util.build_init_report
21
+
22
+ # If already tracing, save and clear the context. Restore it after
23
+ # the __Init is sent
24
+ context = nil
25
+
26
+ if TraceView.tracing?
27
+ context = TraceView::Context.toString
28
+ TraceView::Context.clear
29
+ end
30
+
31
+ start_trace(layer, nil, platform_info.merge('Force' => true)) {}
32
+
33
+ TraceView::Context.fromString(context) if context
34
+ end
35
+
36
+ ##
37
+ # force_trace has been deprecated and will be removed in a subsequent version.
38
+ #
39
+ def force_trace
40
+ TraceView.logger.warn 'TraceView::API::LayerInit.force_trace has been deprecated and will be ' \
41
+ 'removed in a subsequent version.'
42
+
43
+ saved_mode = TraceView::Config[:tracing_mode]
44
+ TraceView::Config[:tracing_mode] = 'always'
45
+ yield
46
+ ensure
47
+ TraceView::Config[:tracing_mode] = saved_mode
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,209 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module API
6
+ ##
7
+ # This modules provides the X-Trace logging facilities.
8
+ module Logging
9
+ # Public: Report an event in an active trace.
10
+ #
11
+ # layer - The layer the reported event belongs to
12
+ # label - The label for the reported event. See API documentation for
13
+ # reserved labels and usage.
14
+ # opts - A hash containing key/value pairs that will be reported along
15
+ # with this event (optional).
16
+ #
17
+ # Example
18
+ #
19
+ # log('logical_layer', 'entry')
20
+ # log('logical_layer', 'info', { :list_length => 20 })
21
+ # log('logical_layer', 'exit')
22
+ #
23
+ # Returns nothing.
24
+ def log(layer, label, opts = {})
25
+ if TraceView.loaded
26
+ log_event(layer, label, TraceView::Context.createEvent, opts)
27
+ end
28
+ end
29
+
30
+ # Public: Report an exception.
31
+ #
32
+ # layer - The layer the reported event belongs to
33
+ # exn - The exception to report
34
+ #
35
+ # Example
36
+ #
37
+ # begin
38
+ # function_without_traceview()
39
+ # rescue Exception => e
40
+ # log_exception('rails', e)
41
+ # raise
42
+ # end
43
+ #
44
+ # Returns nothing.
45
+ def log_exception(layer, exn)
46
+ return if !TraceView.loaded || exn.instance_variable_get(:@oboe_logged)
47
+
48
+ kvs = { :ErrorClass => exn.class.name,
49
+ :ErrorMsg => exn.message,
50
+ :Backtrace => exn.backtrace.join("\r\n") }
51
+
52
+ exn.instance_variable_set(:@oboe_logged, true)
53
+ log(layer, 'error', kvs)
54
+ end
55
+
56
+ # Public: Decide whether or not to start a trace, and report an event
57
+ # appropriately.
58
+ #
59
+ # layer - The layer the reported event belongs to
60
+ # xtrace - An xtrace metadata string, or nil.
61
+ # opts - A hash containing key/value pairs that will be reported along
62
+ # with this event (optional).
63
+ #
64
+ # Returns nothing.
65
+ def log_start(layer, xtrace = nil, opts = {})
66
+ return if !TraceView.loaded || TraceView.never? ||
67
+ (opts.key?(:URL) && ::TraceView::Util.static_asset?(opts[:URL]))
68
+
69
+ TraceView::Context.fromString(xtrace) if TraceView.pickup_context?(xtrace)
70
+
71
+ if TraceView.tracing?
72
+ # Pre-existing context. Either we inherited context from an
73
+ # incoming X-Trace request header or under JRuby, Joboe started
74
+ # tracing before the JRuby code was called (e.g. Tomcat)
75
+ TraceView.is_continued_trace = true
76
+
77
+ if TraceView.has_xtrace_header
78
+ opts[:TraceOrigin] = :continued_header
79
+ elsif TraceView.has_incoming_context
80
+ opts[:TraceOrigin] = :continued_context
81
+ else
82
+ opts[:TraceOrigin] = :continued
83
+ end
84
+
85
+ log_entry(layer, opts)
86
+
87
+ elsif opts.key?('Force')
88
+ # Forced tracing: used by __Init reporting
89
+ opts[:TraceOrigin] = :forced
90
+ log_event(layer, 'entry', TraceView::Context.startTrace, opts)
91
+
92
+ elsif TraceView.sample?(opts.merge(:layer => layer, :xtrace => xtrace))
93
+ # Probablistic tracing of a subset of requests based off of
94
+ # sample rate and sample source
95
+ opts[:SampleRate] = TraceView.sample_rate
96
+ opts[:SampleSource] = TraceView.sample_source
97
+ opts[:TraceOrigin] = :always_sampled
98
+
99
+ log_event(layer, 'entry', TraceView::Context.startTrace, opts)
100
+ end
101
+ end
102
+
103
+ # Public: Report an exit event.
104
+ #
105
+ # layer - The layer the reported event belongs to
106
+ #
107
+ # Returns an xtrace metadata string
108
+ def log_end(layer, opts = {})
109
+ if TraceView.loaded
110
+ log_event(layer, 'exit', TraceView::Context.createEvent, opts)
111
+ xtrace = TraceView::Context.toString
112
+ TraceView::Context.clear unless TraceView.has_incoming_context?
113
+ xtrace
114
+ end
115
+ end
116
+
117
+ ##
118
+ # Public: Log an entry event
119
+ #
120
+ # A helper method to create and log an
121
+ # entry event
122
+ #
123
+ # Returns an xtrace metadata string
124
+ def log_entry(layer, kvs = {}, op = nil)
125
+ if TraceView.loaded
126
+ TraceView.layer_op = op if op
127
+ log_event(layer, 'entry', TraceView::Context.createEvent, kvs)
128
+ end
129
+ end
130
+
131
+ ##
132
+ # Public: Log an info event
133
+ #
134
+ # A helper method to create and log an
135
+ # info event
136
+ #
137
+ # Returns an xtrace metadata string
138
+ def log_info(layer, kvs = {})
139
+ if TraceView.loaded
140
+ log_event(layer, 'info', TraceView::Context.createEvent, kvs)
141
+ end
142
+ end
143
+
144
+ ##
145
+ # Public: Log an exit event
146
+ #
147
+ # A helper method to create and log an
148
+ # exit event
149
+ #
150
+ # Returns an xtrace metadata string
151
+ def log_exit(layer, kvs = {}, op = nil)
152
+ if TraceView.loaded
153
+ TraceView.layer_op = nil if op
154
+ log_event(layer, 'exit', TraceView::Context.createEvent, kvs)
155
+ end
156
+ end
157
+
158
+ # Internal: Report an event.
159
+ #
160
+ # layer - The layer the reported event belongs to
161
+ # label - The label for the reported event. See API documentation for
162
+ # reserved labels and usage.
163
+ # opts - A hash containing key/value pairs that will be reported along
164
+ # with this event (optional).
165
+ #
166
+ # Examples
167
+ #
168
+ # entry = TraceView::Context.createEvent
169
+ # log_event('rails', 'entry', exit, { :controller => 'user', :action => 'index' })
170
+ # exit = TraceView::Context.createEvent
171
+ # exit.addEdge(entry.getMetadata)
172
+ # log_event('rails', 'exit', exit)
173
+ #
174
+ # Returns nothing.
175
+ def log_event(layer, label, event, opts = {})
176
+ if TraceView.loaded
177
+ event.addInfo('Layer', layer.to_s) if layer
178
+ event.addInfo('Label', label.to_s)
179
+
180
+ TraceView.layer = layer if label == 'entry'
181
+ TraceView.layer = nil if label == 'exit'
182
+
183
+ opts.each do |k, v|
184
+ value = nil
185
+
186
+ if valid_key? k
187
+ if [Integer, Float, Fixnum, NilClass, String].include?(v.class)
188
+ value = v
189
+ elsif v.class == Set
190
+ value = v.to_a.to_s
191
+ else
192
+ value = v.to_s if v.respond_to?(:to_s)
193
+ end
194
+
195
+ begin
196
+ event.addInfo(k.to_s, value)
197
+ rescue ArgumentError => e
198
+ TraceView.logger.debug "[TraceView/debug] Couldn't add event KV: #{k.to_s} => #{v.class}"
199
+ TraceView.logger.debug "[TraceView/debug] #{e.message}"
200
+ end
201
+ end
202
+ end if !opts.nil? && opts.any?
203
+
204
+ TraceView::Reporter.sendReport(event)
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end