tingyun_rpm 1.1.4.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Guardfile +10 -0
- data/lib/ting_yun/agent.rb +1 -0
- data/lib/ting_yun/agent/agent.rb +16 -27
- data/lib/ting_yun/agent/collector/error_collector.rb +7 -18
- data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +26 -21
- data/lib/ting_yun/agent/collector/middle_ware_collector/cpu_sampler.rb +4 -9
- data/lib/ting_yun/agent/collector/sql_sampler.rb +32 -188
- data/lib/ting_yun/agent/collector/sql_sampler/slow_sql.rb +47 -0
- data/lib/ting_yun/agent/collector/sql_sampler/sql_trace.rb +73 -0
- data/lib/ting_yun/agent/collector/sql_sampler/transaction_sql_data.rb +26 -0
- data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +6 -5
- data/lib/ting_yun/agent/collector/stats_engine/stats_hash.rb +2 -2
- data/lib/ting_yun/agent/collector/transaction_sampler.rb +23 -159
- data/lib/ting_yun/agent/collector/transaction_sampler/class_method.rb +130 -0
- data/lib/ting_yun/agent/collector/transaction_sampler/slowest_sample_buffer.rb +1 -1
- data/lib/ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base.rb +1 -1
- data/lib/ting_yun/agent/cross_app/cross_app_monitor.rb +29 -79
- data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +36 -66
- data/lib/ting_yun/agent/database.rb +41 -349
- data/lib/ting_yun/agent/database/connection_manager.rb +44 -0
- data/lib/ting_yun/agent/database/explain_plan_helpers.rb +173 -0
- data/lib/ting_yun/agent/database/obfuscator.rb +151 -0
- data/lib/ting_yun/agent/database/statement.rb +70 -0
- data/lib/ting_yun/agent/event/event_loop.rb +1 -2
- data/lib/ting_yun/agent/instance_methods/connect.rb +8 -20
- data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +2 -3
- data/lib/ting_yun/agent/instance_methods/handle_errors.rb +6 -1
- data/lib/ting_yun/agent/instance_methods/start.rb +13 -81
- data/lib/ting_yun/agent/transaction.rb +48 -391
- data/lib/ting_yun/agent/transaction/apdex.rb +53 -0
- data/lib/ting_yun/agent/transaction/attributes.rb +2 -1
- data/lib/ting_yun/agent/transaction/class_method.rb +127 -0
- data/lib/ting_yun/agent/transaction/exceptions.rb +42 -0
- data/lib/ting_yun/agent/transaction/instance_method.rb +139 -0
- data/lib/ting_yun/agent/transaction/request_attributes.rb +9 -39
- data/lib/ting_yun/agent/transaction/trace.rb +7 -5
- data/lib/ting_yun/agent/transaction/trace_node.rb +1 -3
- data/lib/ting_yun/agent/transaction/traced_method_stack.rb +2 -3
- data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +6 -1
- data/lib/ting_yun/agent/transaction/transaction_state.rb +59 -17
- data/lib/ting_yun/agent/transaction/transaction_timings.rb +72 -0
- data/lib/ting_yun/configuration.rb +11 -0
- data/lib/ting_yun/configuration/default_source.rb +20 -17
- data/lib/ting_yun/configuration/manager.rb +50 -21
- data/lib/ting_yun/frameworks.rb +1 -0
- data/lib/ting_yun/frameworks/rails.rb +15 -0
- data/lib/ting_yun/instrumentation/active_record.rb +12 -18
- data/lib/ting_yun/instrumentation/middleware_tracing.rb +8 -14
- data/lib/ting_yun/instrumentation/mongo.rb +21 -27
- data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +7 -3
- data/lib/ting_yun/instrumentation/moped.rb +2 -2
- data/lib/ting_yun/instrumentation/net.rb +4 -5
- data/lib/ting_yun/instrumentation/rack.rb +1 -2
- data/lib/ting_yun/instrumentation/rails4/active_record_subscriber.rb +22 -20
- data/lib/ting_yun/instrumentation/redis.rb +2 -2
- data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +1 -1
- data/lib/ting_yun/instrumentation/support/external_error.rb +19 -16
- data/lib/ting_yun/instrumentation/support/javascript_instrumentor.rb +92 -0
- data/lib/ting_yun/instrumentation/support/thrift_helper.rb +73 -0
- data/lib/ting_yun/instrumentation/thrift.rb +19 -222
- data/lib/ting_yun/logger.rb +1 -0
- data/lib/ting_yun/logger/agent_logger.rb +11 -67
- data/lib/ting_yun/logger/create_logger_helper.rb +72 -0
- data/lib/ting_yun/metrics/metric_data.rb +9 -31
- data/lib/ting_yun/metrics/metric_spec.rb +11 -0
- data/lib/ting_yun/metrics/stats.rb +24 -1
- data/lib/ting_yun/middleware/agent_middleware.rb +28 -0
- data/lib/ting_yun/middleware/browser_monitoring.rb +111 -0
- data/lib/ting_yun/support/coerce.rb +1 -0
- data/lib/ting_yun/support/exception.rb +2 -33
- data/lib/ting_yun/support/local_environment.rb +7 -7
- data/lib/ting_yun/support/serialize/marshaller.rb +7 -25
- data/lib/ting_yun/ting_yun_service.rb +12 -9
- data/lib/ting_yun/ting_yun_service/connection.rb +3 -0
- data/lib/ting_yun/ting_yun_service/http.rb +4 -1
- data/lib/ting_yun/ting_yun_service/request.rb +5 -13
- data/lib/ting_yun/ting_yun_service/upload_service.rb +5 -7
- data/lib/ting_yun/version.rb +3 -5
- data/lib/tingyun_rpm.rb +12 -10
- data/tingyun_rpm.gemspec +3 -0
- metadata +49 -5
- data/.DS_Store +0 -0
- data/lib/ting_yun/agent/collector/base_sampler.rb +0 -2
data/lib/ting_yun/logger.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# This file is distributed under Ting Yun's license terms.
|
3
|
-
|
4
3
|
require 'thread'
|
5
4
|
require 'logger'
|
6
5
|
require 'ting_yun/logger/log_once'
|
7
6
|
require 'ting_yun/logger/memory_logger'
|
8
7
|
require 'ting_yun/support/hostname'
|
9
8
|
require 'ting_yun/logger/null_logger'
|
10
|
-
|
9
|
+
require 'ting_yun/logger/create_logger_helper'
|
11
10
|
|
12
11
|
module TingYun
|
13
12
|
module Logger
|
14
13
|
class AgentLogger
|
15
|
-
include LogOnce
|
14
|
+
include ::TingYun::Logger::LogOnce
|
15
|
+
include ::TingYun::Logger::CreateLoggerHelper
|
16
16
|
|
17
17
|
def initialize(root = "", override_logger=nil)
|
18
18
|
@already_logged_lock = Mutex.new
|
19
19
|
clear_already_logged
|
20
20
|
create_log(root, override_logger)
|
21
|
-
set_log_level
|
22
|
-
set_log_format
|
21
|
+
set_log_level
|
22
|
+
set_log_format
|
23
23
|
|
24
24
|
gather_startup_logs
|
25
25
|
end
|
@@ -64,9 +64,6 @@ module TingYun
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
def log_formatter=(formatter)
|
68
|
-
@log.formatter = formatter
|
69
|
-
end
|
70
67
|
|
71
68
|
private
|
72
69
|
|
@@ -102,67 +99,14 @@ module TingYun
|
|
102
99
|
nil
|
103
100
|
end
|
104
101
|
|
105
|
-
def check_log_file
|
106
|
-
unless File.exist? @file_path
|
107
|
-
begin
|
108
|
-
@log = ::Logger.new(@file_path)
|
109
|
-
set_log_format!
|
110
|
-
rescue => e
|
111
|
-
@log = ::Logger.new(STDOUT)
|
112
|
-
warn("check_log_file: Failed creating logger for file #{@file_path}, using standard out for logging.", e)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def create_log(root, override_logger)
|
118
|
-
if !override_logger.nil?
|
119
|
-
@log = override_logger
|
120
|
-
elsif ::TingYun::Agent.config[:'nbs.agent_enabled'] == false
|
121
|
-
create_null_logger
|
122
|
-
else
|
123
|
-
if wants_stdout?
|
124
|
-
@log = ::Logger.new(STDOUT)
|
125
|
-
else
|
126
|
-
create_log_to_file(root)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def create_log_to_file(root)
|
132
|
-
path = find_or_create_file_path(::TingYun::Agent.config[:agent_log_file_path], root)
|
133
|
-
if path.nil?
|
134
|
-
@log = ::Logger.new(STDOUT)
|
135
|
-
warn("Error creating log directory #{::TingYun::Agent.config[:agent_log_file_path]}, using standard out for logging.")
|
136
|
-
else
|
137
|
-
@file_path = "#{path}/#{::TingYun::Agent.config[:agent_log_file_name]}"
|
138
|
-
begin
|
139
|
-
@log = ::Logger.new(@file_path)
|
140
|
-
rescue => e
|
141
|
-
@log = ::Logger.new(STDOUT)
|
142
|
-
warn("Failed creating logger for file #{@file_path}, using standard out for logging.", e)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def create_null_logger
|
148
|
-
@log = ::TingYun::Logger::NullLogger.new
|
149
|
-
end
|
150
102
|
|
151
103
|
def wants_stdout?
|
152
104
|
::TingYun::Agent.config[:agent_log_file_name].upcase == "STDOUT"
|
153
105
|
end
|
154
106
|
|
155
|
-
def find_or_create_file_path(path_setting, root)
|
156
|
-
for abs_path in [File.expand_path(path_setting),
|
157
|
-
File.expand_path(File.join(root, path_setting))] do
|
158
|
-
if File.directory?(abs_path) || (Dir.mkdir(abs_path) rescue nil)
|
159
|
-
return abs_path[%r{^(.*?)/?$}]
|
160
|
-
end
|
161
|
-
end
|
162
|
-
nil
|
163
|
-
end
|
164
107
|
|
165
|
-
|
108
|
+
|
109
|
+
def set_log_level
|
166
110
|
@log.level = AgentLogger.log_level_for(::TingYun::Agent.config[:agent_log_level])
|
167
111
|
end
|
168
112
|
|
@@ -178,11 +122,11 @@ module TingYun
|
|
178
122
|
LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
|
179
123
|
end
|
180
124
|
|
181
|
-
def set_log_format
|
182
|
-
|
183
|
-
|
125
|
+
def set_log_format
|
126
|
+
hostname = TingYun::Support::Hostname.get
|
127
|
+
prefix = wants_stdout? ? '** [TingYun]' : ''
|
184
128
|
@log.formatter = Proc.new do |severity, timestamp, progname, msg|
|
185
|
-
"#{
|
129
|
+
"#{prefix}[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{hostname} (#{$$})] #{severity} : #{msg}\n"
|
186
130
|
end
|
187
131
|
end
|
188
132
|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TingYun
|
4
|
+
module Logger
|
5
|
+
module CreateLoggerHelper
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
def create_log(root, override_logger)
|
10
|
+
if !override_logger.nil?
|
11
|
+
@log = override_logger
|
12
|
+
elsif ::TingYun::Agent.config[:'nbs.agent_enabled'] == false
|
13
|
+
create_null_logger
|
14
|
+
else
|
15
|
+
if wants_stdout?
|
16
|
+
@log = ::Logger.new(STDOUT)
|
17
|
+
else
|
18
|
+
create_log_to_file(root)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def check_log_file
|
25
|
+
unless File.exist? @file_path
|
26
|
+
begin
|
27
|
+
@log = ::Logger.new(@file_path)
|
28
|
+
set_log_format
|
29
|
+
rescue => e
|
30
|
+
@log = ::Logger.new(STDOUT)
|
31
|
+
warn("check_log_file: Failed creating logger for file #{@file_path}, using standard out for logging.", e)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
def create_log_to_file(root)
|
39
|
+
path = find_or_create_file_path(::TingYun::Agent.config[:agent_log_file_path], root)
|
40
|
+
unless path
|
41
|
+
@log = ::Logger.new(STDOUT)
|
42
|
+
warn("Error creating log directory #{::TingYun::Agent.config[:agent_log_file_path]}, using standard out for logging.")
|
43
|
+
else
|
44
|
+
@file_path = "#{path}/#{::TingYun::Agent.config[:agent_log_file_name]}"
|
45
|
+
begin
|
46
|
+
@log = ::Logger.new(@file_path)
|
47
|
+
rescue => e
|
48
|
+
@log = ::Logger.new(STDOUT)
|
49
|
+
warn("Failed creating logger for file #{@file_path}, using standard out for logging.", e)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_null_logger
|
55
|
+
@log = ::TingYun::Logger::NullLogger.new
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def find_or_create_file_path(path_setting, root)
|
60
|
+
for abs_path in [File.expand_path(path_setting),
|
61
|
+
File.expand_path(File.join(root, path_setting))] do
|
62
|
+
if File.directory?(abs_path) || (FileUtils.mkdir_p(abs_path) rescue nil)
|
63
|
+
return abs_path[%r{^(.*?)/?$}]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# This file is distributed under Ting Yun's license terms.
|
3
3
|
|
4
|
-
|
4
|
+
|
5
5
|
|
6
6
|
module TingYun
|
7
7
|
module Metrics
|
@@ -16,8 +16,8 @@ module TingYun
|
|
16
16
|
|
17
17
|
def initialize(metric_spec, stats, metric_id)
|
18
18
|
@metric_spec = metric_spec
|
19
|
-
|
20
|
-
|
19
|
+
@stats = stats
|
20
|
+
@metric_id = metric_id
|
21
21
|
end
|
22
22
|
|
23
23
|
def eql?(o)
|
@@ -45,42 +45,20 @@ module TingYun
|
|
45
45
|
"#<MetricData metric_spec:#{metric_spec.inspect}, stats:#{stats.inspect}, metric_id:#{metric_id.inspect}>"
|
46
46
|
end
|
47
47
|
|
48
|
-
include TingYun::Support::Coerce
|
49
48
|
|
50
49
|
def to_collector_array(encoder=nil)
|
51
|
-
stat_key = metric_id ||
|
52
|
-
[
|
50
|
+
stat_key = metric_id || to_hash
|
51
|
+
[stat_key, metrics(stat_key)]
|
53
52
|
end
|
54
53
|
|
55
|
-
def
|
56
|
-
|
57
|
-
hash['calleeId'] = metric_spec.calleeId unless metric_spec.calleeId.nil?
|
58
|
-
hash['calleeName'] = metric_spec.calleeName unless metric_spec.calleeName.nil?
|
59
|
-
unless metric_spec.scope.empty?
|
60
|
-
hash['parent'] = metric_spec.scope
|
61
|
-
end
|
62
|
-
|
63
|
-
return hash
|
54
|
+
def to_hash
|
55
|
+
metric_spec.to_hash
|
64
56
|
end
|
65
57
|
|
66
58
|
def metrics(stat_key)
|
67
|
-
|
68
|
-
metrics = []
|
69
|
-
|
70
|
-
metrics << int(stats.call_count, stat_key)
|
71
|
-
if stats.max_call_time != 0.0 #apedx
|
72
|
-
metrics << float(stats.total_call_time, stat_key)
|
73
|
-
metrics << float(stats.total_exclusive_time, stat_key)
|
74
|
-
metrics << float(stats.max_call_time, stat_key)
|
75
|
-
end
|
76
|
-
|
77
|
-
if stats.min_call_time !=0.0 #
|
78
|
-
metrics << float(stats.min_call_time, stat_key)
|
79
|
-
metrics << float(stats.sum_of_squares, stat_key)
|
80
|
-
end
|
81
|
-
|
82
|
-
metrics
|
59
|
+
stats.metrics(stat_key)
|
83
60
|
end
|
61
|
+
|
84
62
|
end
|
85
63
|
end
|
86
64
|
end
|
@@ -82,6 +82,17 @@ module TingYun
|
|
82
82
|
return (self.scope || '') <=> (o.scope || '')
|
83
83
|
end
|
84
84
|
|
85
|
+
def to_hash
|
86
|
+
hash = { 'name' => name }
|
87
|
+
hash['calleeId'] = calleeId if calleeId
|
88
|
+
hash['calleeName'] = calleeName if calleeName
|
89
|
+
unless scope.empty?
|
90
|
+
hash['parent'] = scope
|
91
|
+
end
|
92
|
+
|
93
|
+
return hash
|
94
|
+
end
|
95
|
+
|
85
96
|
|
86
97
|
|
87
98
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# This file is distributed under Ting Yun's license terms.
|
3
|
+
require 'ting_yun/support/coerce'
|
3
4
|
|
4
5
|
module TingYun
|
5
6
|
module Metrics
|
@@ -78,6 +79,10 @@ module TingYun
|
|
78
79
|
}.to_json(*_)
|
79
80
|
end
|
80
81
|
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
81
86
|
def record(value=nil, aux=nil, &blk)
|
82
87
|
if blk
|
83
88
|
yield self
|
@@ -108,7 +113,6 @@ module TingYun
|
|
108
113
|
end
|
109
114
|
|
110
115
|
|
111
|
-
|
112
116
|
# record a single data point into the statistical gatherer. The gatherer
|
113
117
|
# will aggregate all data points collected over a specified period and upload
|
114
118
|
# its data to the TingYun server
|
@@ -142,6 +146,25 @@ module TingYun
|
|
142
146
|
)
|
143
147
|
end
|
144
148
|
|
149
|
+
include TingYun::Support::Coerce
|
150
|
+
|
151
|
+
def metrics(stat_key)
|
152
|
+
metrics = []
|
153
|
+
|
154
|
+
metrics << int(call_count, stat_key)
|
155
|
+
if max_call_time != 0.0 #apedx
|
156
|
+
metrics << float(total_call_time, stat_key)
|
157
|
+
metrics << float(total_exclusive_time, stat_key)
|
158
|
+
metrics << float(max_call_time, stat_key)
|
159
|
+
end
|
160
|
+
|
161
|
+
if min_call_time !=0.0 #
|
162
|
+
metrics << float(min_call_time, stat_key)
|
163
|
+
metrics << float(sum_of_squares, stat_key)
|
164
|
+
end
|
165
|
+
|
166
|
+
metrics
|
167
|
+
end
|
145
168
|
|
146
169
|
protected
|
147
170
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/instrumentation/middleware_proxy'
|
3
|
+
|
4
|
+
module TingYun
|
5
|
+
class AgentMiddleware
|
6
|
+
|
7
|
+
include TingYun::Instrumentation::MiddlewareTracing
|
8
|
+
|
9
|
+
attr_reader :transaction_options, :category, :target
|
10
|
+
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
@category = :middleware
|
14
|
+
@target = self
|
15
|
+
@transaction_options = {
|
16
|
+
:transaction_name => build_transaction_name
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_transaction_name
|
21
|
+
prefix = ::TingYun::Instrumentation::Support::TransactionNamer.prefix_for_category(nil, @category)
|
22
|
+
"#{prefix}#{self.class.name}/call"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/middleware/agent_middleware'
|
3
|
+
require 'ting_yun/instrumentation/support/javascript_instrumentor'
|
4
|
+
|
5
|
+
|
6
|
+
module TingYun
|
7
|
+
class BrowserMonitoring < AgentMiddleware
|
8
|
+
|
9
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
10
|
+
TEXT_HTML = 'text/html'.freeze
|
11
|
+
CONTENT_DISPOSITION = 'Content-Disposition'.freeze
|
12
|
+
ATTACHMENT = 'attachment'.freeze
|
13
|
+
|
14
|
+
SCAN_LIMIT = 64_000
|
15
|
+
|
16
|
+
TITLE_END = '</title>'.freeze
|
17
|
+
TITLE_END_CAPITAL = '</TITLE>'.freeze
|
18
|
+
HEAD_END = '<head>'.freeze
|
19
|
+
HEAD_END_CAPITAL = '<HEAD>'.freeze
|
20
|
+
|
21
|
+
GT = '>'.freeze
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
def traced_call(env)
|
27
|
+
result = @app.call(env) # [status, headers, response]
|
28
|
+
|
29
|
+
js_to_inject = TingYun::Instrumentation::Support::JavascriptInstrument.browser_timing_header
|
30
|
+
|
31
|
+
if (js_to_inject != '') && should_instrument?(env, result[0], result[1])
|
32
|
+
response_string = auto_instrument_source(result[2], js_to_inject)
|
33
|
+
|
34
|
+
env[ALREADY_INSTRUMENTED_KEY] = true
|
35
|
+
if response_string
|
36
|
+
response = Rack::Response.new(response_string, result[0], result[1])
|
37
|
+
response.finish
|
38
|
+
else
|
39
|
+
result
|
40
|
+
end
|
41
|
+
else
|
42
|
+
result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ALREADY_INSTRUMENTED_KEY = "tingyun.browser_monitoring_already_instrumented"
|
47
|
+
|
48
|
+
def should_instrument?(env, status, headers)
|
49
|
+
status == 200 &&
|
50
|
+
is_ajax?(env) &&
|
51
|
+
!env[ALREADY_INSTRUMENTED_KEY] &&
|
52
|
+
is_html?(headers) &&
|
53
|
+
!is_attachment?(headers)
|
54
|
+
end
|
55
|
+
|
56
|
+
def is_html?(headers)
|
57
|
+
headers[CONTENT_TYPE] && headers[CONTENT_TYPE].include?(TEXT_HTML)
|
58
|
+
end
|
59
|
+
|
60
|
+
def is_ajax?(env)
|
61
|
+
env["HTTP_X_REQUESTED_WITH"].nil?
|
62
|
+
end
|
63
|
+
|
64
|
+
def is_attachment?(headers)
|
65
|
+
headers[CONTENT_DISPOSITION] && headers[CONTENT_DISPOSITION].include?(ATTACHMENT)
|
66
|
+
end
|
67
|
+
|
68
|
+
def auto_instrument_source(response, js_to_inject)
|
69
|
+
source = gather_source(response)
|
70
|
+
close_old_response(response)
|
71
|
+
return nil unless source
|
72
|
+
|
73
|
+
beginning_of_source = source[0..SCAN_LIMIT]
|
74
|
+
insertion_index = find_tag_end(beginning_of_source)
|
75
|
+
|
76
|
+
if insertion_index
|
77
|
+
source = source[0...insertion_index] <<
|
78
|
+
js_to_inject <<
|
79
|
+
source[insertion_index..-1]
|
80
|
+
else
|
81
|
+
TingYun::Agent.logger.debug "Skipping RUM instrumentation. Could not properly determine location to inject script."
|
82
|
+
end
|
83
|
+
|
84
|
+
source
|
85
|
+
rescue => e
|
86
|
+
TingYun::Agent.logger.debug "Skipping RUM instrumentation on exception.", e
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def gather_source(response)
|
91
|
+
source = nil
|
92
|
+
response.each {|fragment| source ? (source << fragment.to_s) : (source = fragment.to_s)}
|
93
|
+
source
|
94
|
+
end
|
95
|
+
|
96
|
+
def close_old_response(response)
|
97
|
+
if response.respond_to?(:close)
|
98
|
+
response.close
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def find_tag_end(beginning_of_source)
|
103
|
+
tag_end = beginning_of_source.index(TITLE_END) ||
|
104
|
+
beginning_of_source.index(HEAD_END) ||
|
105
|
+
beginning_of_source.index(TITLE_END_CAPITAL) ||
|
106
|
+
beginning_of_source.index(HEAD_END_CAPITAL)
|
107
|
+
|
108
|
+
beginning_of_source.index(GT, tag_end) + 1 if tag_end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|