traceview 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +58 -0
- data/Appraisals +10 -0
- data/CHANGELOG.md +490 -0
- data/CONFIG.md +16 -0
- data/Gemfile +95 -0
- data/LICENSE +199 -0
- data/README.md +380 -0
- data/Rakefile +109 -0
- data/examples/DNT.md +35 -0
- data/examples/carrying_context.rb +225 -0
- data/examples/instrumenting_metal_controller.rb +8 -0
- data/examples/puma_on_heroku_config.rb +17 -0
- data/examples/tracing_async_threads.rb +125 -0
- data/examples/tracing_background_jobs.rb +52 -0
- data/examples/tracing_forked_processes.rb +100 -0
- data/examples/unicorn_on_heroku_config.rb +28 -0
- data/ext/oboe_metal/extconf.rb +61 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/bson/bson.h +221 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/oboe.h +275 -0
- data/ext/oboe_metal/src/oboe.hpp +352 -0
- data/ext/oboe_metal/src/oboe_wrap.cxx +3886 -0
- data/ext/oboe_metal/tests/test.rb +11 -0
- data/gemfiles/mongo.gemfile +33 -0
- data/gemfiles/moped.gemfile +33 -0
- data/get_version.rb +5 -0
- data/init.rb +4 -0
- data/lib/joboe_metal.rb +206 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +59 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe_metal.rb +151 -0
- data/lib/rails/generators/traceview/install_generator.rb +76 -0
- data/lib/rails/generators/traceview/templates/traceview_initializer.rb +159 -0
- data/lib/traceview.rb +62 -0
- data/lib/traceview/api.rb +18 -0
- data/lib/traceview/api/layerinit.rb +51 -0
- data/lib/traceview/api/logging.rb +209 -0
- data/lib/traceview/api/memcache.rb +31 -0
- data/lib/traceview/api/profiling.rb +50 -0
- data/lib/traceview/api/tracing.rb +135 -0
- data/lib/traceview/api/util.rb +121 -0
- data/lib/traceview/base.rb +225 -0
- data/lib/traceview/config.rb +238 -0
- data/lib/traceview/frameworks/grape.rb +97 -0
- data/lib/traceview/frameworks/padrino.rb +64 -0
- data/lib/traceview/frameworks/padrino/templates.rb +58 -0
- data/lib/traceview/frameworks/rails.rb +145 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
- data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
- data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
- data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
- data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
- data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
- data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
- data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
- data/lib/traceview/frameworks/sinatra.rb +95 -0
- data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
- data/lib/traceview/inst/cassandra.rb +279 -0
- data/lib/traceview/inst/dalli.rb +86 -0
- data/lib/traceview/inst/em-http-request.rb +99 -0
- data/lib/traceview/inst/excon.rb +111 -0
- data/lib/traceview/inst/faraday.rb +73 -0
- data/lib/traceview/inst/http.rb +87 -0
- data/lib/traceview/inst/httpclient.rb +173 -0
- data/lib/traceview/inst/memcache.rb +102 -0
- data/lib/traceview/inst/memcached.rb +94 -0
- data/lib/traceview/inst/mongo.rb +238 -0
- data/lib/traceview/inst/moped.rb +474 -0
- data/lib/traceview/inst/rack.rb +122 -0
- data/lib/traceview/inst/redis.rb +271 -0
- data/lib/traceview/inst/resque.rb +192 -0
- data/lib/traceview/inst/rest-client.rb +38 -0
- data/lib/traceview/inst/sequel.rb +162 -0
- data/lib/traceview/inst/typhoeus.rb +102 -0
- data/lib/traceview/instrumentation.rb +21 -0
- data/lib/traceview/loading.rb +94 -0
- data/lib/traceview/logger.rb +41 -0
- data/lib/traceview/method_profiling.rb +84 -0
- data/lib/traceview/ruby.rb +36 -0
- data/lib/traceview/support.rb +113 -0
- data/lib/traceview/thread_local.rb +26 -0
- data/lib/traceview/util.rb +250 -0
- data/lib/traceview/version.rb +16 -0
- data/lib/traceview/xtrace.rb +90 -0
- data/test/frameworks/apps/grape_nested.rb +30 -0
- data/test/frameworks/apps/grape_simple.rb +24 -0
- data/test/frameworks/apps/padrino_simple.rb +45 -0
- data/test/frameworks/apps/sinatra_simple.rb +24 -0
- data/test/frameworks/grape_test.rb +142 -0
- data/test/frameworks/padrino_test.rb +30 -0
- data/test/frameworks/sinatra_test.rb +30 -0
- data/test/instrumentation/cassandra_test.rb +380 -0
- data/test/instrumentation/dalli_test.rb +171 -0
- data/test/instrumentation/em_http_request_test.rb +86 -0
- data/test/instrumentation/excon_test.rb +207 -0
- data/test/instrumentation/faraday_test.rb +235 -0
- data/test/instrumentation/http_test.rb +140 -0
- data/test/instrumentation/httpclient_test.rb +296 -0
- data/test/instrumentation/memcache_test.rb +251 -0
- data/test/instrumentation/memcached_test.rb +226 -0
- data/test/instrumentation/mongo_test.rb +462 -0
- data/test/instrumentation/moped_test.rb +496 -0
- data/test/instrumentation/rack_test.rb +116 -0
- data/test/instrumentation/redis_hashes_test.rb +265 -0
- data/test/instrumentation/redis_keys_test.rb +318 -0
- data/test/instrumentation/redis_lists_test.rb +310 -0
- data/test/instrumentation/redis_misc_test.rb +160 -0
- data/test/instrumentation/redis_sets_test.rb +293 -0
- data/test/instrumentation/redis_sortedsets_test.rb +325 -0
- data/test/instrumentation/redis_strings_test.rb +333 -0
- data/test/instrumentation/resque_test.rb +62 -0
- data/test/instrumentation/rest-client_test.rb +294 -0
- data/test/instrumentation/sequel_mysql2_test.rb +326 -0
- data/test/instrumentation/sequel_mysql_test.rb +326 -0
- data/test/instrumentation/sequel_pg_test.rb +330 -0
- data/test/instrumentation/typhoeus_test.rb +285 -0
- data/test/minitest_helper.rb +187 -0
- data/test/profiling/method_test.rb +198 -0
- data/test/servers/rackapp_8101.rb +22 -0
- data/test/support/backcompat_test.rb +269 -0
- data/test/support/config_test.rb +128 -0
- data/test/support/dnt_test.rb +73 -0
- data/test/support/liboboe_settings_test.rb +104 -0
- data/test/support/xtrace_test.rb +35 -0
- data/traceview.gemspec +29 -0
- metadata +250 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Copyright (c) 2015 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module Inst
|
|
6
|
+
module RestClientRequest
|
|
7
|
+
def self.included(klass)
|
|
8
|
+
::TraceView::Util.method_alias(klass, :execute, ::RestClient::Request)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# execute_with_traceview
|
|
13
|
+
#
|
|
14
|
+
# The wrapper method for RestClient::Request.execute
|
|
15
|
+
#
|
|
16
|
+
def execute_with_traceview & block
|
|
17
|
+
kvs = {}
|
|
18
|
+
kvs['Backtrace'] = TraceView::API.backtrace if TraceView::Config[:rest_client][:collect_backtraces]
|
|
19
|
+
TraceView::API.log_entry("rest-client", kvs)
|
|
20
|
+
|
|
21
|
+
# The core rest-client call
|
|
22
|
+
execute_without_traceview(&block)
|
|
23
|
+
rescue => e
|
|
24
|
+
TraceView::API.log_exception('rest-client', e)
|
|
25
|
+
raise e
|
|
26
|
+
ensure
|
|
27
|
+
TraceView::API.log_exit("rest-client")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if TraceView::Config[:rest_client][:enabled]
|
|
34
|
+
if defined?(::RestClient)
|
|
35
|
+
TraceView.logger.info '[traceview/loading] Instrumenting rest-client' if TraceView::Config[:verbose]
|
|
36
|
+
::TraceView::Util.send_include(::RestClient::Request, ::TraceView::Inst::RestClientRequest)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Copyright (c) 2015 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module Inst
|
|
6
|
+
module Sequel
|
|
7
|
+
def extract_trace_details(sql, opts)
|
|
8
|
+
kvs = {}
|
|
9
|
+
|
|
10
|
+
if TraceView::Config[:sanitize_sql]
|
|
11
|
+
# Sanitize SQL and don't report binds
|
|
12
|
+
if sql.is_a?(Symbol)
|
|
13
|
+
kvs[:Query] = sql
|
|
14
|
+
else
|
|
15
|
+
kvs[:Query] = sql.gsub(/('[\s\S][^\']*\'|\d*\.\d*)/, '?')
|
|
16
|
+
end
|
|
17
|
+
else
|
|
18
|
+
# Report raw SQL and any binds if they exist
|
|
19
|
+
kvs[:Query] = sql.to_s
|
|
20
|
+
kvs[:QueryArgs] = opts[:arguments] if opts.is_a?(Hash) and opts.key?(:arguments)
|
|
21
|
+
end
|
|
22
|
+
kvs[:IsPreparedStatement] = true if sql.is_a?(Symbol)
|
|
23
|
+
|
|
24
|
+
kvs[:Backtrace] = TraceView::API.backtrace if TraceView::Config[:sequel][:collect_backtraces]
|
|
25
|
+
|
|
26
|
+
if ::Sequel::VERSION < '3.41.0' && !(self.class.to_s =~ /Dataset$/)
|
|
27
|
+
db_opts = @opts
|
|
28
|
+
elsif @pool
|
|
29
|
+
db_opts = @pool.db.opts
|
|
30
|
+
else
|
|
31
|
+
db_opts = @db.opts
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
kvs[:Database] = db_opts[:database]
|
|
35
|
+
kvs[:RemoteHost] = db_opts[:host]
|
|
36
|
+
kvs[:RemotePort] = db_opts[:port] if db_opts.key?(:port)
|
|
37
|
+
kvs[:Flavor] = db_opts[:adapter]
|
|
38
|
+
rescue => e
|
|
39
|
+
TraceView.logger.debug "[traceview/debug Error capturing Sequel KVs: #{e.message}" if TraceView::Config[:verbose]
|
|
40
|
+
ensure
|
|
41
|
+
return kvs
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module SequelDatabase
|
|
46
|
+
def self.included(klass)
|
|
47
|
+
::TraceView::Util.method_alias(klass, :run, ::Sequel::Database)
|
|
48
|
+
::TraceView::Util.method_alias(klass, :execute_ddl, ::Sequel::Database)
|
|
49
|
+
::TraceView::Util.method_alias(klass, :execute_dui, ::Sequel::Database)
|
|
50
|
+
::TraceView::Util.method_alias(klass, :execute_insert, ::Sequel::Database)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def run_with_traceview(sql, opts=::Sequel::OPTS)
|
|
54
|
+
kvs = extract_trace_details(sql, opts)
|
|
55
|
+
|
|
56
|
+
TraceView::API.log_entry('sequel', kvs)
|
|
57
|
+
|
|
58
|
+
run_without_traceview(sql, opts)
|
|
59
|
+
rescue => e
|
|
60
|
+
TraceView::API.log_exception('sequel', e)
|
|
61
|
+
raise e
|
|
62
|
+
ensure
|
|
63
|
+
TraceView::API.log_exit('sequel')
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def exec_with_traceview(method, sql, opts=::Sequel::OPTS, &block)
|
|
67
|
+
kvs = extract_trace_details(sql, opts)
|
|
68
|
+
|
|
69
|
+
TraceView::API.log_entry('sequel', kvs)
|
|
70
|
+
|
|
71
|
+
send(method, sql, opts, &block)
|
|
72
|
+
rescue => e
|
|
73
|
+
TraceView::API.log_exception('sequel', e)
|
|
74
|
+
raise e
|
|
75
|
+
ensure
|
|
76
|
+
TraceView::API.log_exit('sequel')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def execute_ddl_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
80
|
+
# If we're already tracing a sequel operation, then this call likely came
|
|
81
|
+
# from Sequel::Dataset. In this case, just pass it on.
|
|
82
|
+
return execute_ddl_without_traceview(sql, opts, &block) if TraceView.tracing_layer?('sequel')
|
|
83
|
+
|
|
84
|
+
exec_with_traceview(:execute_ddl_without_traceview, sql, opts, &block)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def execute_dui_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
88
|
+
# If we're already tracing a sequel operation, then this call likely came
|
|
89
|
+
# from Sequel::Dataset. In this case, just pass it on.
|
|
90
|
+
return execute_dui_without_traceview(sql, opts, &block) if TraceView.tracing_layer?('sequel')
|
|
91
|
+
|
|
92
|
+
exec_with_traceview(:execute_dui_without_traceview, sql, opts, &block)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def execute_insert_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
96
|
+
# If we're already tracing a sequel operation, then this call likely came
|
|
97
|
+
# from Sequel::Dataset. In this case, just pass it on.
|
|
98
|
+
return execute_insert_without_traceview(sql, opts, &block) if TraceView.tracing_layer?('sequel')
|
|
99
|
+
|
|
100
|
+
exec_with_traceview(:execute_insert_without_traceview, sql, opts, &block)
|
|
101
|
+
end
|
|
102
|
+
end # module SequelDatabase
|
|
103
|
+
|
|
104
|
+
module SequelDataset
|
|
105
|
+
|
|
106
|
+
def self.included(klass)
|
|
107
|
+
::TraceView::Util.method_alias(klass, :execute, ::Sequel::Dataset)
|
|
108
|
+
::TraceView::Util.method_alias(klass, :execute_ddl, ::Sequel::Dataset)
|
|
109
|
+
::TraceView::Util.method_alias(klass, :execute_dui, ::Sequel::Dataset)
|
|
110
|
+
::TraceView::Util.method_alias(klass, :execute_insert, ::Sequel::Dataset)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def exec_with_traceview(method, sql, opts=::Sequel::OPTS, &block)
|
|
114
|
+
kvs = extract_trace_details(sql, opts)
|
|
115
|
+
|
|
116
|
+
TraceView::API.log_entry('sequel', kvs)
|
|
117
|
+
|
|
118
|
+
send(method, sql, opts, &block)
|
|
119
|
+
rescue => e
|
|
120
|
+
TraceView::API.log_exception('sequel', e)
|
|
121
|
+
raise e
|
|
122
|
+
ensure
|
|
123
|
+
TraceView::API.log_exit('sequel')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def execute_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
127
|
+
exec_with_traceview(:execute_without_traceview, sql, opts, &block)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def execute_ddl_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
131
|
+
exec_with_traceview(:execute_ddl_without_traceview, sql, opts, &block)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def execute_dui_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
135
|
+
exec_with_traceview(:execute_dui_without_traceview, sql, opts, &block)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def execute_insert_with_traceview(sql, opts=::Sequel::OPTS, &block)
|
|
139
|
+
exec_with_traceview(:execute_insert_without_traceview, sql, opts, &block)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end # module SequelDataset
|
|
143
|
+
end # module Inst
|
|
144
|
+
end # module TraceView
|
|
145
|
+
|
|
146
|
+
if TraceView::Config[:sequel][:enabled]
|
|
147
|
+
if defined?(::Sequel) && ::Sequel::VERSION < "4.0.0"
|
|
148
|
+
# For versions before 4.0.0, Sequel::OPTS wasn't defined.
|
|
149
|
+
# Define it as an empty hash for backwards compatibility.
|
|
150
|
+
module ::Sequel
|
|
151
|
+
OPTS = {}
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
if defined?(::Sequel)
|
|
156
|
+
TraceView.logger.info '[traceview/loading] Instrumenting sequel' if TraceView::Config[:verbose]
|
|
157
|
+
::TraceView::Util.send_include(::Sequel::Database, ::TraceView::Inst::Sequel)
|
|
158
|
+
::TraceView::Util.send_include(::Sequel::Database, ::TraceView::Inst::SequelDatabase)
|
|
159
|
+
::TraceView::Util.send_include(::Sequel::Dataset, ::TraceView::Inst::Sequel)
|
|
160
|
+
::TraceView::Util.send_include(::Sequel::Dataset, ::TraceView::Inst::SequelDataset)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Copyright (c) 2015 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
module Inst
|
|
6
|
+
module TyphoeusRequestOps
|
|
7
|
+
|
|
8
|
+
def self.included(klass)
|
|
9
|
+
::TraceView::Util.method_alias(klass, :run, ::Typhoeus::Request::Operations)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run_with_traceview
|
|
13
|
+
return run_without_traceview unless TraceView.tracing?
|
|
14
|
+
|
|
15
|
+
TraceView::API.log_entry('typhoeus')
|
|
16
|
+
|
|
17
|
+
# Prepare X-Trace header handling
|
|
18
|
+
blacklisted = TraceView::API.blacklisted?(url)
|
|
19
|
+
context = TraceView::Context.toString
|
|
20
|
+
task_id = TraceView::XTrace.task_id(context)
|
|
21
|
+
options[:headers]['X-Trace'] = context unless blacklisted
|
|
22
|
+
|
|
23
|
+
response = run_without_traceview
|
|
24
|
+
|
|
25
|
+
if response.code == 0
|
|
26
|
+
TraceView::API.log('typhoeus', 'error', { :ErrorClass => response.return_code,
|
|
27
|
+
:ErrorMsg => response.return_message })
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
kvs = {}
|
|
31
|
+
kvs['IsService'] = 1
|
|
32
|
+
kvs[:HTTPStatus] = response.code
|
|
33
|
+
kvs['Backtrace'] = TraceView::API.backtrace if TraceView::Config[:typhoeus][:collect_backtraces]
|
|
34
|
+
|
|
35
|
+
uri = URI(response.effective_url)
|
|
36
|
+
|
|
37
|
+
# Conditionally log query params
|
|
38
|
+
if TraceView::Config[:typhoeus][:log_args]
|
|
39
|
+
kvs['RemoteURL'] = uri.to_s
|
|
40
|
+
else
|
|
41
|
+
kvs['RemoteURL'] = uri.to_s.split('?').first
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
kvs['HTTPMethod'] = ::TraceView::Util.upcase(options[:method])
|
|
45
|
+
kvs['Blacklisted'] = true if blacklisted
|
|
46
|
+
|
|
47
|
+
# Re-attach net::http edge unless it's blacklisted or if we don't have a
|
|
48
|
+
# valid X-Trace header
|
|
49
|
+
unless blacklisted
|
|
50
|
+
xtrace = response.headers['X-Trace']
|
|
51
|
+
|
|
52
|
+
if xtrace && TraceView::XTrace.valid?(xtrace) && TraceView.tracing?
|
|
53
|
+
|
|
54
|
+
# Assure that we received back a valid X-Trace with the same task_id
|
|
55
|
+
if task_id == TraceView::XTrace.task_id(xtrace)
|
|
56
|
+
TraceView::Context.fromString(xtrace)
|
|
57
|
+
else
|
|
58
|
+
TraceView.logger.debug "Mismatched returned X-Trace ID: #{xtrace}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
TraceView::API.log('typhoeus', 'info', kvs)
|
|
64
|
+
response
|
|
65
|
+
rescue => e
|
|
66
|
+
TraceView::API.log_exception('typhoeus', e)
|
|
67
|
+
raise e
|
|
68
|
+
ensure
|
|
69
|
+
TraceView::API.log_exit('typhoeus')
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
module TyphoeusHydraRunnable
|
|
74
|
+
def self.included(klass)
|
|
75
|
+
::TraceView::Util.method_alias(klass, :run, ::Typhoeus::Hydra)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def run_with_traceview
|
|
79
|
+
kvs = {}
|
|
80
|
+
|
|
81
|
+
kvs[:queued_requests] = queued_requests.count
|
|
82
|
+
kvs[:max_concurrency] = max_concurrency
|
|
83
|
+
|
|
84
|
+
# FIXME: Until we figure out a strategy to deal with libcurl internal
|
|
85
|
+
# threading and Ethon's use of easy handles, here we just do a simple
|
|
86
|
+
# trace of the hydra run.
|
|
87
|
+
TraceView::API.trace("typhoeus_hydra", kvs) do
|
|
88
|
+
run_without_traceview
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
if TraceView::Config[:typhoeus][:enabled]
|
|
97
|
+
if defined?(::Typhoeus)
|
|
98
|
+
TraceView.logger.info '[traceview/loading] Instrumenting typhoeus' if TraceView::Config[:verbose]
|
|
99
|
+
::TraceView::Util.send_include(::Typhoeus::Request::Operations, ::TraceView::Inst::TyphoeusRequestOps)
|
|
100
|
+
::TraceView::Util.send_include(::Typhoeus::Hydra, ::TraceView::Inst::TyphoeusHydraRunnable)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module TraceView
|
|
5
|
+
##
|
|
6
|
+
# The Inst module holds all of the instrumentation extensions for various
|
|
7
|
+
# libraries suchs as Redis, Dalli and Resque.
|
|
8
|
+
module Inst
|
|
9
|
+
def self.load_instrumentation
|
|
10
|
+
# Load the general instrumentation
|
|
11
|
+
pattern = File.join(File.dirname(__FILE__), 'inst', '*.rb')
|
|
12
|
+
Dir.glob(pattern) do |f|
|
|
13
|
+
begin
|
|
14
|
+
require f
|
|
15
|
+
rescue => e
|
|
16
|
+
TraceView.logger.error "[traceview/loading] Error loading instrumentation file '#{f}' : #{e}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'digest/sha1'
|
|
5
|
+
|
|
6
|
+
module TraceView
|
|
7
|
+
module Util
|
|
8
|
+
##
|
|
9
|
+
# This module is used solely for RUM ID calculation
|
|
10
|
+
#
|
|
11
|
+
module Base64URL
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
def encode(bin)
|
|
15
|
+
c = [bin].pack('m0').gsub(/\=+\Z/, '').tr('+/', '-_').rstrip
|
|
16
|
+
m = c.size % 4
|
|
17
|
+
c += '=' * (4 - m) if m != 0
|
|
18
|
+
c
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def decode(bin)
|
|
22
|
+
m = bin.size % 4
|
|
23
|
+
bin += '=' * (4 - m) if m != 0
|
|
24
|
+
bin.tr('-_', '+/').unpack('m0').first
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# This module houses all of the loading functionality for the traceview gem.
|
|
31
|
+
#
|
|
32
|
+
# Note that this does not necessarily _have_ to include initialization routines
|
|
33
|
+
# (although it can).
|
|
34
|
+
#
|
|
35
|
+
# Actual initialization is often separated out as it can be dependent on on the state
|
|
36
|
+
# of the stack boot process. e.g. code requiring that initializers, frameworks or
|
|
37
|
+
# instrumented libraries are already loaded...
|
|
38
|
+
#
|
|
39
|
+
module Loading
|
|
40
|
+
##
|
|
41
|
+
# Load the TraceView access key (either from system configuration file
|
|
42
|
+
# or environment variable) and calculate internal RUM ID
|
|
43
|
+
#
|
|
44
|
+
def self.load_access_key
|
|
45
|
+
if ENV.key?('TRACEVIEW_CUUID')
|
|
46
|
+
# Preferably get access key from environment (e.g. Heroku)
|
|
47
|
+
TraceView::Config[:access_key] = ENV['TRACEVIEW_CUUID']
|
|
48
|
+
TraceView::Config[:rum_id] = TraceView::Util::Base64URL.encode(Digest::SHA1.digest('RUM' + TraceView::Config[:access_key]))
|
|
49
|
+
else
|
|
50
|
+
# ..else read from system-wide configuration file
|
|
51
|
+
if TraceView::Config.access_key.empty?
|
|
52
|
+
config_file = '/etc/tracelytics.conf'
|
|
53
|
+
return unless File.exist?(config_file)
|
|
54
|
+
|
|
55
|
+
File.open(config_file).each do |line|
|
|
56
|
+
if line =~ /^tracelyzer.access_key=/ || line =~ /^access_key/
|
|
57
|
+
bits = line.split(/=/)
|
|
58
|
+
TraceView::Config[:access_key] = bits[1].strip
|
|
59
|
+
TraceView::Config[:rum_id] = TraceView::Util::Base64URL.encode(Digest::SHA1.digest('RUM' + TraceView::Config[:access_key]))
|
|
60
|
+
break
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
rescue StandardError => e
|
|
66
|
+
TraceView.logger.error "Trouble obtaining access_key and rum_id: #{e.inspect}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Load the traceview tracing API
|
|
71
|
+
#
|
|
72
|
+
def self.require_api
|
|
73
|
+
pattern = File.join(File.dirname(__FILE__), 'api', '*.rb')
|
|
74
|
+
Dir.glob(pattern) do |f|
|
|
75
|
+
require f
|
|
76
|
+
end
|
|
77
|
+
require 'traceview/api'
|
|
78
|
+
|
|
79
|
+
begin
|
|
80
|
+
TraceView::API.extend_with_tracing
|
|
81
|
+
rescue LoadError => e
|
|
82
|
+
TraceView.logger.fatal "[traceview/error] Couldn't load api: #{e.message}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
TraceView::Loading.require_api
|
|
89
|
+
|
|
90
|
+
# Auto-start the Reporter unless we running Unicorn on Heroku
|
|
91
|
+
# In that case, we start the reporters after fork
|
|
92
|
+
unless TraceView.heroku? && TraceView.forking_webserver?
|
|
93
|
+
TraceView::Reporter.start if TraceView.loaded
|
|
94
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright (c) 2013 AppNeta, Inc.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'logger'
|
|
5
|
+
|
|
6
|
+
module TraceView
|
|
7
|
+
class << self
|
|
8
|
+
attr_accessor :logger
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Logger
|
|
12
|
+
# Fatal message
|
|
13
|
+
def fatal(string, exception = nil)
|
|
14
|
+
TraceView.logger.fatal(string) if TraceView.logger
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Error message
|
|
18
|
+
def error(msg, exception = nil)
|
|
19
|
+
TraceView.logger.error(string) if TraceView.logger
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Warn message
|
|
23
|
+
def warn(msg, exception = nil)
|
|
24
|
+
TraceView.logger.warn(string) if TraceView.logger
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Info message
|
|
28
|
+
def info(msg, exception = nil)
|
|
29
|
+
TraceView.logger.info(string) if TraceView.logger
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Debug message
|
|
33
|
+
def debug(msg, exception = nil)
|
|
34
|
+
TraceView.logger.debug(string) if TraceView.logger
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
TraceView.logger = Logger.new(STDERR)
|
|
41
|
+
|