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,121 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ require 'pp'
5
+
6
+ module TraceView
7
+ module API
8
+ ##
9
+ # General utility methods for the gem
10
+ module Util
11
+ BACKTRACE_CUTOFF = 200
12
+
13
+ # Internal: Check whether the provided key is reserved or not. Reserved
14
+ # keys are either keys that are handled by liboboe calls or the traceview gem.
15
+ #
16
+ # key - the key to check.
17
+ #
18
+ # Return a boolean indicating whether or not key is reserved.
19
+ def valid_key?(key)
20
+ !%w(Label Layer Edge Timestamp Timestamp_u).include? key.to_s
21
+ end
22
+
23
+ # Internal: Get the current backtrace.
24
+ #
25
+ # ignore - Number of frames to ignore at the end of the backtrace. Use
26
+ # when you know how many layers deep in oboe the call is being
27
+ # made.
28
+ #
29
+ # Returns a string with each frame of the backtrace separated by '\r\n'.
30
+ #
31
+ # FIXME: ignore is not currently used (see BACKTRACE_CUTOFF)
32
+ def backtrace(_ignore = 1)
33
+ trim_backtrace(Kernel.caller).join("\r\n")
34
+ end
35
+
36
+ # Internal: Trim a backtrace to a manageable size
37
+ #
38
+ # backtrace - the backtrace (an array of stack frames/from Kernel.caller)
39
+ #
40
+ # Returns a trimmed backtrace
41
+ def trim_backtrace(backtrace)
42
+ return backtrace unless backtrace.is_a?(Array)
43
+
44
+ length = backtrace.size
45
+ if length > BACKTRACE_CUTOFF
46
+ # Trim backtraces by getting the first 180 and last 20 lines
47
+ trimmed = backtrace[0, 180] + ['...[snip]...'] + backtrace[length - 20, 20]
48
+ else
49
+ trimmed = backtrace
50
+ end
51
+ trimmed
52
+ end
53
+
54
+ # Internal: Check if a host is blacklisted from tracing
55
+ #
56
+ # addr_port - the addr_port from Net::HTTP although this method
57
+ # can be used from any component in reality
58
+ #
59
+ # Returns a boolean on blacklisted state
60
+ def blacklisted?(addr_port)
61
+ return false unless TraceView::Config.blacklist
62
+
63
+ # Ensure that the blacklist is an array
64
+ unless TraceView::Config.blacklist.is_a?(Array)
65
+ val = TraceView::Config[:blacklist]
66
+ TraceView::Config[:blacklist] = [val.to_s]
67
+ end
68
+
69
+ TraceView::Config.blacklist.each do |h|
70
+ return true if addr_port.to_s.match(h.to_s)
71
+ end
72
+
73
+ false
74
+ end
75
+
76
+ # Internal: Pretty print a list of arguments for reporting
77
+ #
78
+ # args - the list of arguments to work on
79
+ #
80
+ # Returns a pretty string representation of arguments
81
+ def pps(*args)
82
+ old_out = $stdout
83
+ begin
84
+ s = StringIO.new
85
+ $stdout = s
86
+ pp(*args)
87
+ ensure
88
+ $stdout = old_out
89
+ end
90
+ s.string
91
+ end
92
+
93
+ # Internal: Determine a string to report representing klass
94
+ #
95
+ # args - an instance of a Class, a Class or a Module
96
+ #
97
+ # Returns a string representation of klass
98
+ def get_class_name(klass)
99
+ kv = {}
100
+
101
+ if klass.to_s =~ /::/
102
+ klass.class.to_s.rpartition('::').last
103
+ else
104
+ if klass.is_a?(Class) && klass.is_a?(Module)
105
+ # Class
106
+ kv['Class'] = klass.to_s
107
+
108
+ elsif (!klass.is_a?(Class) && !klass.is_a?(Module))
109
+ # Class instance
110
+ kv['Class'] = klass.class.to_s
111
+
112
+ else
113
+ # Module
114
+ kv['Module'] = klass.to_s
115
+ end
116
+ end
117
+ kv
118
+ end
119
+ end
120
+ end
121
+ 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,225 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ # Constants from liboboe
5
+ OBOE_TRACE_NEVER = 0
6
+ OBOE_TRACE_ALWAYS = 1
7
+ OBOE_TRACE_THROUGH = 2
8
+
9
+ OBOE_SAMPLE_RATE_SOURCE_FILE = 1
10
+ OBOE_SAMPLE_RATE_SOURCE_DEFAULT = 2
11
+ OBOE_SAMPLE_RATE_SOURCE_OBOE = 3
12
+ OBOE_SAMPLE_RATE_SOURCE_LAST_OBOE = 4
13
+ OBOE_SAMPLE_RATE_SOURCE_DEFAULT_MISCONFIGURED = 5
14
+ OBOE_SAMPLE_RATE_SOURCE_OBOE_DEFAULT = 6
15
+
16
+ # Masks for bitwise ops
17
+ ZERO_MASK = 0b0000000000000000000000000000
18
+
19
+ SAMPLE_RATE_MASK = 0b0000111111111111111111111111
20
+ SAMPLE_SOURCE_MASK = 0b1111000000000000000000000000
21
+
22
+ ZERO_SAMPLE_RATE_MASK = 0b1111000000000000000000000000
23
+ ZERO_SAMPLE_SOURCE_MASK = 0b0000111111111111111111111111
24
+
25
+ ##
26
+ # This module is the base module for the various implementations of TraceView reporting.
27
+ # Current variations as of 2014-09-10 are a c-extension, JRuby (using TraceView Java
28
+ # instrumentation) and a Heroku c-extension (with embedded tracelyzer)
29
+ module TraceViewBase
30
+ extend ::TraceView::ThreadLocal
31
+
32
+ attr_accessor :reporter
33
+ attr_accessor :loaded
34
+ thread_local :sample_source
35
+ thread_local :sample_rate
36
+ thread_local :layer
37
+ thread_local :layer_op
38
+
39
+ # The following accessors indicate the incoming tracing state received
40
+ # by the rack layer. These are primarily used to identify state
41
+ # between the Ruby and JTraceView instrumentation under JRuby.
42
+ #
43
+ # This is because that even though there may be an incoming
44
+ # X-Trace request header, tracing may have already been started
45
+ # by Joboe. Such a scenario occurs when the application is being
46
+ # hosted by a Java container (such as Tomcat or Glassfish) and
47
+ # JTraceView has already initiated tracing. In this case, we shouldn't
48
+ # pickup the X-Trace context in the X-Trace header and we shouldn't
49
+ # set the outgoing response X-Trace header or clear context.
50
+ # Yeah I know. Yuck.
51
+
52
+ # Occurs only on Jruby. Indicates that Joboe (the java instrumentation)
53
+ # has already started tracing before it hit the JRuby instrumentation.
54
+ thread_local :has_incoming_context
55
+
56
+ # Indicates the existence of a valid X-Trace request header
57
+ thread_local :has_xtrace_header
58
+
59
+ # This indicates that this trace was continued from
60
+ # an incoming X-Trace request header or in the case
61
+ # of JRuby, a trace already started by JTraceView.
62
+ thread_local :is_continued_trace
63
+
64
+ ##
65
+ # extended
66
+ #
67
+ # Invoked when this module is extended.
68
+ # e.g. extend TraceViewBase
69
+ #
70
+ def self.extended(cls)
71
+ cls.loaded = true
72
+
73
+ # This gives us pretty accessors with questions marks at the end
74
+ # e.g. is_continued_trace --> is_continued_trace?
75
+ TraceView.methods.select{ |m| m =~ /^is_|^has_/ }.each do |c|
76
+ unless c =~ /\?$|=$/
77
+ # TraceView.logger.debug "aliasing #{c}? to #{c}"
78
+ alias_method "#{c}?", c
79
+ end
80
+ end
81
+ end
82
+
83
+ ##
84
+ # pickup_context
85
+ #
86
+ # Determines whether we should pickup context
87
+ # from an incoming X-Trace request header. The answer
88
+ # is generally yes but there are cases in JRuby under
89
+ # Tomcat (or Glassfish etc.) where tracing may have
90
+ # been already started by the Java instrumentation (Joboe)
91
+ # in which case we don't want to do this.
92
+ #
93
+ def pickup_context?(xtrace)
94
+ return false unless TraceView::XTrace.valid?(xtrace)
95
+
96
+ if defined?(JRUBY_VERSION) && TraceView.tracing?
97
+ return false
98
+ else
99
+ return true
100
+ end
101
+ end
102
+
103
+ ##
104
+ # tracing_layer?
105
+ #
106
+ # Queries the thread local variable about the current
107
+ # layer being traced. This is used in cases of recursive
108
+ # operation tracing or one instrumented operation calling another.
109
+ #
110
+ def tracing_layer?(layer)
111
+ return TraceView.layer == layer
112
+ end
113
+
114
+ ##
115
+ # tracing_layer_op?
116
+ #
117
+ # Queries the thread local variable about the current
118
+ # operation being traced. This is used in cases of recursive
119
+ # operation tracing or one instrumented operation calling another.
120
+ #
121
+ # In such cases, we only want to trace the outermost operation.
122
+ #
123
+ def tracing_layer_op?(operation)
124
+ if operation.is_a?(Array)
125
+ return operation.include?(TraceView.layer_op)
126
+ else
127
+ return TraceView.layer_op == operation
128
+ end
129
+ end
130
+
131
+ ##
132
+ # Returns true if the tracing_mode is set to always.
133
+ # False otherwise
134
+ #
135
+ def always?
136
+ TraceView::Config[:tracing_mode].to_s == 'always'
137
+ end
138
+
139
+ ##
140
+ # Returns true if the tracing_mode is set to never.
141
+ # False otherwise
142
+ #
143
+ def never?
144
+ TraceView::Config[:tracing_mode].to_s == 'never'
145
+ end
146
+
147
+ ##
148
+ # Returns true if the tracing_mode is set to always or through.
149
+ # False otherwise
150
+ #
151
+ def passthrough?
152
+ %w(always through).include?(TraceView::Config[:tracing_mode])
153
+ end
154
+
155
+ ##
156
+ # Returns true if the tracing_mode is set to through.
157
+ # False otherwise
158
+ #
159
+ def through?
160
+ TraceView::Config[:tracing_mode] == 'through'
161
+ end
162
+
163
+ ##
164
+ # Returns true if we are currently tracing a request
165
+ # False otherwise
166
+ #
167
+ def tracing?
168
+ return false unless TraceView.loaded
169
+
170
+ TraceView::Context.isValid && !TraceView.never?
171
+ end
172
+
173
+ def log(layer, label, options = {})
174
+ # WARN: TraceView.log will be deprecated in a future release. Please use TraceView::API.log instead.
175
+ TraceView::API.log(layer, label, options)
176
+ end
177
+
178
+ def heroku?
179
+ ENV.key?('TRACEVIEW_URL')
180
+ end
181
+
182
+ ##
183
+ # Determines if we are running under a forking webserver
184
+ #
185
+ def forking_webserver?
186
+ if (defined?(::Unicorn) && ($PROGRAM_NAME =~ /unicorn/i)) ||
187
+ (defined?(::Puma) && ($PROGRAM_NAME =~ /puma/i))
188
+ true
189
+ else
190
+ false
191
+ end
192
+ end
193
+
194
+ ##
195
+ # Indicates whether a supported framework is in use
196
+ # or not
197
+ #
198
+ def framework?
199
+ defined?(::Rails) or defined?(::Sinatra) or defined?(::Padrino) or defined?(::Grape)
200
+ end
201
+
202
+ ##
203
+ # These methods should be implemented by the descendants
204
+ # (Oboe_metal, JOboe_metal (JRuby), Heroku_metal)
205
+ #
206
+ def sample?(_opts = {})
207
+ fail 'sample? should be implemented by metal layer.'
208
+ end
209
+
210
+ def log(_layer, _label, _options = {})
211
+ fail 'log should be implemented by metal layer.'
212
+ end
213
+
214
+ def set_tracing_mode(_mode)
215
+ fail 'set_tracing_mode should be implemented by metal layer.'
216
+ end
217
+
218
+ def set_sample_rate(_rate)
219
+ fail 'set_sample_rate should be implemented by metal layer.'
220
+ end
221
+ end
222
+
223
+ module TraceView
224
+ extend TraceViewBase
225
+ end
@@ -0,0 +1,238 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ ##
6
+ # This module exposes a nested configuration hash that can be used to
7
+ # configure and/or modify the functionality of the traceview gem.
8
+ #
9
+ # Use TraceView::Config.show to view the entire nested hash.
10
+ #
11
+ module Config
12
+ @@config = {}
13
+
14
+ @@instrumentation = [:action_controller, :action_view, :active_record,
15
+ :cassandra, :dalli, :em_http_request, :excon, :faraday,
16
+ :grape, :httpclient, :nethttp, :memcached, :memcache, :mongo,
17
+ :moped, :rack, :redis, :resque, :rest_client, :sequel,
18
+ :typhoeus]
19
+
20
+ # Subgrouping of instrumentation
21
+ @@http_clients = [:excon, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
22
+
23
+ ##
24
+ # Return the raw nested hash.
25
+ #
26
+ def self.show
27
+ @@config
28
+ end
29
+
30
+ def self.initialize(_data = {})
31
+ # Setup default instrumentation values
32
+ @@instrumentation.each do |k|
33
+ @@config[k] = {}
34
+ @@config[k][:enabled] = true
35
+ @@config[k][:collect_backtraces] = false
36
+ @@config[k][:log_args] = true
37
+ end
38
+
39
+ # Beta instrumentation disabled by default
40
+ TraceView::Config[:em_http_request][:enabled] = false
41
+
42
+ # Set collect_backtraces defaults
43
+ TraceView::Config[:action_controller][:collect_backtraces] = true
44
+ TraceView::Config[:active_record][:collect_backtraces] = true
45
+ TraceView::Config[:action_view][:collect_backtraces] = true
46
+ TraceView::Config[:cassandra][:collect_backtraces] = true
47
+ TraceView::Config[:dalli][:collect_backtraces] = false
48
+ TraceView::Config[:em_http_request][:collect_backtraces] = false
49
+ TraceView::Config[:excon][:collect_backtraces] = true
50
+ TraceView::Config[:faraday][:collect_backtraces] = false
51
+ TraceView::Config[:grape][:collect_backtraces] = true
52
+ TraceView::Config[:httpclient][:collect_backtraces] = true
53
+ TraceView::Config[:memcache][:collect_backtraces] = false
54
+ TraceView::Config[:memcached][:collect_backtraces] = false
55
+ TraceView::Config[:mongo][:collect_backtraces] = true
56
+ TraceView::Config[:moped][:collect_backtraces] = true
57
+ TraceView::Config[:nethttp][:collect_backtraces] = true
58
+ TraceView::Config[:redis][:collect_backtraces] = false
59
+ TraceView::Config[:resque][:collect_backtraces] = true
60
+ TraceView::Config[:rest_client][:collect_backtraces] = false
61
+ TraceView::Config[:sequel][:collect_backtraces] = true
62
+ TraceView::Config[:typhoeus][:collect_backtraces] = false
63
+
64
+ # Special instrument specific flags
65
+ #
66
+ # :link_workers - associates enqueue operations with the jobs they queue by piggybacking
67
+ # an additional argument that is stripped prior to job proecessing
68
+ # !!Note: Make sure both the queue side and the Resque workers are instrumented
69
+ # or jobs will fail
70
+ # (Default: false)
71
+ @@config[:resque][:link_workers] = false
72
+
73
+ # Setup an empty host blacklist (see: TraceView::API::Util.blacklisted?)
74
+ @@config[:blacklist] = []
75
+
76
+ # Access Key is empty until loaded from config file or env var
77
+ @@config[:access_key] = ''
78
+
79
+ # Logging of outgoing HTTP query args
80
+ #
81
+ # This optionally disables the logging of query args of outgoing
82
+ # HTTP clients such as Net::HTTP, excon, typhoeus and others.
83
+ #
84
+ # This flag is global to all HTTP client instrumentation.
85
+ #
86
+ # To configure this on a per instrumentation basis, set this
87
+ # option to true and instead disable the instrumenstation specific
88
+ # option <tt>log_args</tt>:
89
+ #
90
+ # TraceView::Config[:nethttp][:log_args] = false
91
+ # TraceView::Config[:excon][:log_args] = false
92
+ # TraceView::Config[:typhoeus][:log_args] = true
93
+ #
94
+ @@config[:include_url_query_params] = true
95
+
96
+ # Logging of incoming HTTP query args
97
+ #
98
+ # This optionally disables the logging of incoming URL request
99
+ # query args.
100
+ #
101
+ # This flag is global and currently only affects the Rack
102
+ # instrumentation which reports incoming request URLs and
103
+ # query args by default.
104
+ @@config[:include_remote_url_params] = true
105
+
106
+ # The TraceView Ruby gem has the ability to sanitize query literals
107
+ # from SQL statements. By default this is disabled. Enable to
108
+ # avoid collecting and reporting query literals to TraceView.
109
+ @@config[:sanitize_sql] = false
110
+
111
+ # Do Not Trace
112
+ # These two values allow you to configure specific URL patterns to
113
+ # never be traced. By default, this is set to common static file
114
+ # extensions but you may want to customize this list for your needs.
115
+ #
116
+ # dnt_regexp and dnt_opts is passed to Regexp.new to create
117
+ # a regular expression object. That is then used to match against
118
+ # the incoming request path.
119
+ #
120
+ # The path string originates from the rack layer and is retrieved
121
+ # as follows:
122
+ #
123
+ # req = ::Rack::Request.new(env)
124
+ # path = URI.unescape(req.path)
125
+ #
126
+ # Usage:
127
+ # TraceView::Config[:dnt_regexp] = "lobster$"
128
+ # TraceView::Config[:dnt_opts] = Regexp::IGNORECASE
129
+ #
130
+ # This will ignore all requests that end with the string lobster
131
+ # regardless of case
132
+ #
133
+ # Requests with positive matches (non nil) will not be traced.
134
+ # See lib/traceview/util.rb: TraceView::Util.static_asset?
135
+ #
136
+ @@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)$"
137
+ @@config[:dnt_opts] = Regexp::IGNORECASE
138
+
139
+ # In Rails, raised exceptions with rescue handlers via
140
+ # <tt>rescue_from</tt> are not reported to the TraceView
141
+ # dashboard by default. Setting this value to true will
142
+ # report all raised exception regardless.
143
+ @@config[:report_rescued_errors] = false
144
+
145
+ # Environment support for OpenShift.
146
+ if ENV.key?('OPENSHIFT_TRACEVIEW_TLYZER_IP')
147
+ # We're running on OpenShift
148
+ @@config[:tracing_mode] = 'always'
149
+ @@config[:reporter_host] = ENV['OPENSHIFT_TRACEVIEW_TLYZER_IP']
150
+ @@config[:reporter_port] = ENV['OPENSHIFT_TRACEVIEW_TLYZER_PORT']
151
+ else
152
+ # The default configuration
153
+ @@config[:tracing_mode] = 'through'
154
+ @@config[:reporter_host] = '127.0.0.1'
155
+ @@config[:reporter_port] = '7831'
156
+ end
157
+
158
+ @@config[:verbose] = ENV.key?('TRACEVIEW_GEM_VERBOSE') ? true : false
159
+ end
160
+
161
+ def self.update!(data)
162
+ data.each do |key, value|
163
+ self[key] = value
164
+ end
165
+ end
166
+
167
+ def self.merge!(data)
168
+ self.update!(data)
169
+ end
170
+
171
+ def self.[](key)
172
+ @@config[key.to_sym]
173
+ end
174
+
175
+ def self.[]=(key, value)
176
+ @@config[key.to_sym] = value
177
+
178
+ if key == :sampling_rate
179
+ TraceView.logger.warn 'sampling_rate is not a supported setting for TraceView::Config. ' \
180
+ 'Please use :sample_rate.'
181
+
182
+ elsif key == :sample_rate
183
+ unless value.is_a?(Integer) || value.is_a?(Float)
184
+ fail 'traceview :sample_rate must be a number between 1 and 1000000 (1m)'
185
+ end
186
+
187
+ # Validate :sample_rate value
188
+ unless value.between?(1, 1e6)
189
+ fail 'traceview :sample_rate must be between 1 and 1000000 (1m)'
190
+ end
191
+
192
+ # Assure value is an integer
193
+ @@config[key.to_sym] = value.to_i
194
+ TraceView.set_sample_rate(value) if TraceView.loaded
195
+
196
+ elsif key == :include_url_query_params
197
+ # Obey the global flag and update all of the per instrumentation
198
+ # <tt>:log_args</tt> values.
199
+ @@http_clients.each do |i|
200
+ @@config[i][:log_args] = value
201
+ end
202
+
203
+ elsif key == :include_remote_url_params
204
+ # Obey the global flag and update all of the per instrumentation
205
+ # <tt>:log_args</tt> values.
206
+ @@config[:rack][:log_args] = value
207
+ end
208
+
209
+ # Update liboboe if updating :tracing_mode
210
+ if key == :tracing_mode
211
+ TraceView.set_tracing_mode(value) if TraceView.loaded
212
+ end
213
+ end
214
+
215
+ def self.method_missing(sym, *args)
216
+ class_var_name = "@@#{sym}"
217
+
218
+ if sym.to_s =~ /(.+)=$/
219
+ self[$1] = args.first
220
+ else
221
+ # Try part of the @@config hash first
222
+ if @@config.key?(sym)
223
+ self[sym]
224
+
225
+ # Then try as a class variable
226
+ elsif self.class_variable_defined?(class_var_name.to_sym)
227
+ self.class_eval(class_var_name)
228
+
229
+ # Congrats - You've won a brand new nil...
230
+ else
231
+ nil
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ TraceView::Config.initialize
@@ -0,0 +1,97 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module TraceView
5
+ module Grape
6
+ module API
7
+ def self.extended(klass)
8
+ ::TraceView::Util.class_method_alias(klass, :inherited, ::Grape::API)
9
+ end
10
+
11
+ def inherited_with_traceview(subclass)
12
+ inherited_without_traceview(subclass)
13
+
14
+ subclass.use ::TraceView::Rack
15
+ end
16
+ end
17
+
18
+ module Endpoint
19
+ def self.included(klass)
20
+ ::TraceView::Util.method_alias(klass, :run, ::Grape::Endpoint)
21
+ end
22
+
23
+ def run_with_traceview(env)
24
+ if TraceView.tracing?
25
+ report_kvs = {}
26
+
27
+ report_kvs[:Controller] = self.class
28
+ report_kvs[:Action] = env['PATH_INFO']
29
+
30
+ # Fall back to the raw tracing API so we can pass KVs
31
+ # back on exit (a limitation of the TraceView::API.trace
32
+ # block method) This removes the need for an info
33
+ # event to send additonal KVs
34
+ ::TraceView::API.log_entry('grape', {})
35
+
36
+ begin
37
+ run_without_traceview(env)
38
+ ensure
39
+ ::TraceView::API.log_exit('grape', report_kvs)
40
+ end
41
+ else
42
+ run_without_traceview(env)
43
+ end
44
+ end
45
+ end
46
+
47
+ module Middleware
48
+ module Error
49
+ def self.included(klass)
50
+ ::TraceView::Util.method_alias(klass, :error_response, ::Grape::Middleware::Error)
51
+ end
52
+
53
+ def error_response_with_traceview(error = {})
54
+ status, headers, body = error_response_without_traceview(error)
55
+
56
+ if TraceView.tracing?
57
+ # Since Grape uses throw/catch and not Exceptions, we manually log
58
+ # the error here.
59
+ kvs = {}
60
+ kvs[:ErrorClass] = 'GrapeError'
61
+ kvs[:ErrorMsg] = error[:message] ? error[:message] : "No message given."
62
+ kvs[:Backtrace] = ::TraceView::API.backtrace if TraceView::Config[:grape][:collect_backtraces]
63
+
64
+ ::TraceView::API.log(nil, 'error', kvs)
65
+
66
+ # Since calls to error() are handled similar to abort in Grape. We
67
+ # manually log the rack exit here since the original code won't
68
+ # be returned to
69
+ xtrace = TraceView::API.log_end('rack', :Status => status)
70
+
71
+ if headers && TraceView::XTrace.valid?(xtrace)
72
+ unless defined?(JRUBY_VERSION) && TraceView.is_continued_trace?
73
+ headers['X-Trace'] = xtrace if headers.is_a?(Hash)
74
+ end
75
+ end
76
+ end
77
+
78
+ [status, headers, body]
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ if defined?(::Grape)
86
+ require 'traceview/inst/rack'
87
+
88
+ TraceView.logger.info "[traceview/loading] Instrumenting Grape" if TraceView::Config[:verbose]
89
+
90
+ TraceView::Loading.load_access_key
91
+ TraceView::Inst.load_instrumentation
92
+
93
+ ::TraceView::Util.send_extend(::Grape::API, ::TraceView::Grape::API)
94
+ ::TraceView::Util.send_include(::Grape::Endpoint, ::TraceView::Grape::Endpoint)
95
+ ::TraceView::Util.send_include(::Grape::Middleware::Error, ::TraceView::Grape::Middleware::Error)
96
+ end
97
+