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.
- 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/README +2 -0
- data/lib/oboe/backward_compatibility.rb +59 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe.rb +7 -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/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/api.rb +18 -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/templates.rb +58 -0
- data/lib/traceview/frameworks/padrino.rb +64 -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/rails.rb +145 -0
- data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
- data/lib/traceview/frameworks/sinatra.rb +95 -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/lib/traceview.rb +62 -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 +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
|
+
|