stackify-ruby-apm 1.14.8 → 1.16.0.beta1
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 +4 -4
- data/lib/stackify_apm/agent.rb +5 -4
- data/lib/stackify_apm/config.rb +40 -5
- data/lib/stackify_apm/context.rb +2 -1
- data/lib/stackify_apm/instrumenter.rb +4 -4
- data/lib/stackify_apm/instrumenter_helper.rb +12 -12
- data/lib/stackify_apm/logger/log_device.rb +2 -1
- data/lib/stackify_apm/middleware.rb +9 -10
- data/lib/stackify_apm/normalizers/active_record.rb +17 -3
- data/lib/stackify_apm/response_manipulator.rb +19 -14
- data/lib/stackify_apm/root_info.rb +2 -2
- data/lib/stackify_apm/span/context.rb +1 -1
- data/lib/stackify_apm/spies/action_dispatch.rb +26 -0
- data/lib/stackify_apm/spies/curb/easy.rb +16 -16
- data/lib/stackify_apm/spies/delayed_job.rb +2 -2
- data/lib/stackify_apm/spies/httpclient.rb +4 -4
- data/lib/stackify_apm/spies/sequel.rb +2 -2
- data/lib/stackify_apm/spies/sidekiq.rb +2 -2
- data/lib/stackify_apm/spies/sinatra.rb +14 -4
- data/lib/stackify_apm/spies/sucker_punch.rb +2 -2
- data/lib/stackify_apm/spies/tilt.rb +2 -2
- data/lib/stackify_apm/util.rb +86 -0
- data/lib/stackify_apm/version.rb +2 -2
- data/lib/stackify_ruby_apm.rb +56 -11
- data/stackify-ruby-apm.gemspec +51 -14
- metadata +68 -68
@@ -29,8 +29,8 @@ module StackifyRubyAPM
|
|
29
29
|
::Sequel::Database.class_eval do
|
30
30
|
alias_method 'log_connection_yield_without_apm', 'log_connection_yield'
|
31
31
|
|
32
|
-
def log_connection_yield(sql, *args, &block)
|
33
|
-
return log_connection_yield_without_apm(sql, *args, &block) unless StackifyRubyAPM.current_transaction
|
32
|
+
def log_connection_yield(sql, *args, **kwargs, &block)
|
33
|
+
return log_connection_yield_without_apm(sql, *args, **kwargs, &block) unless StackifyRubyAPM.current_transaction
|
34
34
|
|
35
35
|
name = summarize sql
|
36
36
|
db_adapter = ''
|
@@ -12,7 +12,7 @@ module StackifyRubyAPM
|
|
12
12
|
Sidekiq::Processor.class_eval do
|
13
13
|
alias_method 'process_without_apm', 'process'
|
14
14
|
|
15
|
-
def process(work, *args, &block)
|
15
|
+
def process(work, *args, **kwargs, &block)
|
16
16
|
ret = nil
|
17
17
|
begin
|
18
18
|
job = nil
|
@@ -24,7 +24,7 @@ module StackifyRubyAPM
|
|
24
24
|
job_hash = JSON.parse job
|
25
25
|
name = job_hash["class"]
|
26
26
|
transaction = StackifyRubyAPM.transaction name, 'TASK'
|
27
|
-
ret = process_without_apm(work, *args, &block)
|
27
|
+
ret = process_without_apm(work, *args, **kwargs, &block)
|
28
28
|
rescue StackifyRubyAPM::InternalError
|
29
29
|
raise # Don't report StackifyRubyAPM errors
|
30
30
|
rescue StandardError => e
|
@@ -11,11 +11,12 @@ module StackifyRubyAPM
|
|
11
11
|
::Sinatra::Base.class_eval do
|
12
12
|
alias_method 'dispatch_without_apm!', 'dispatch!'
|
13
13
|
alias_method 'compile_template_without_apm', 'compile_template'
|
14
|
+
alias_method 'route_eval_without_apm', 'route_eval'
|
14
15
|
|
15
16
|
# Sets transaction name from Sinatra env's route name
|
16
17
|
#
|
17
|
-
def dispatch!(*args, &block)
|
18
|
-
dispatch_without_apm!(*args, &block).tap do
|
18
|
+
def dispatch!(*args, **kwargs, &block)
|
19
|
+
dispatch_without_apm!(*args, **kwargs, &block).tap do
|
19
20
|
next unless (transaction = StackifyRubyAPM.current_transaction)
|
20
21
|
next unless (route = env['sinatra.route'])
|
21
22
|
|
@@ -25,14 +26,23 @@ module StackifyRubyAPM
|
|
25
26
|
|
26
27
|
# Tilt engine template
|
27
28
|
#
|
28
|
-
def compile_template(engine, data, opts, *args, &block)
|
29
|
+
def compile_template(engine, data, opts, *args, **kwargs, &block)
|
29
30
|
opts[:__stackify_apm_template_name] =
|
30
31
|
case data
|
31
32
|
when Symbol then data.to_s
|
32
33
|
else format('Inline %s', engine)
|
33
34
|
end
|
34
35
|
|
35
|
-
compile_template_without_apm(engine, data, opts, *args, &block)
|
36
|
+
compile_template_without_apm(engine, data, opts, *args, **kwargs, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def route_eval(*args, **kwargs, &block)
|
40
|
+
if defined?(StackifyRubyAPM.current_transaction)
|
41
|
+
if env.key?('sinatra.route')
|
42
|
+
StackifyRubyAPM.current_transaction.name = env['sinatra.route']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
route_eval_without_apm(*args, **kwargs, &block)
|
36
46
|
end
|
37
47
|
end
|
38
48
|
end
|
@@ -12,14 +12,14 @@ module StackifyRubyAPM
|
|
12
12
|
SuckerPunch::Job::ClassMethods.class_eval do
|
13
13
|
alias_method '__run_perform_without_elastic_apm', '__run_perform'
|
14
14
|
|
15
|
-
def __run_perform(*args)
|
15
|
+
def __run_perform(*args, **kwargs)
|
16
16
|
ret = nil
|
17
17
|
begin
|
18
18
|
name = "#{to_s}.perform"
|
19
19
|
ctx = StackifyRubyAPM::Context.new
|
20
20
|
ctx.category = 'SuckerPunch::Job'
|
21
21
|
transaction = StackifyRubyAPM.transaction name, 'TASK', context: ctx
|
22
|
-
ret = __run_perform_without_elastic_apm(*args)
|
22
|
+
ret = __run_perform_without_elastic_apm(*args, **kwargs)
|
23
23
|
rescue StackifyRubyAPM::InternalError
|
24
24
|
raise # Don't report StackifyRubyAPM errors
|
25
25
|
rescue StandardError => e
|
@@ -15,13 +15,13 @@ module StackifyRubyAPM
|
|
15
15
|
::Tilt::Template.class_eval do
|
16
16
|
alias_method 'render_without_apm', 'render'
|
17
17
|
|
18
|
-
def render(*args, &block)
|
18
|
+
def render(*args, **kwargs, &block)
|
19
19
|
name = options[:__stackify_apm_template_name] || 'Unknown template'
|
20
20
|
|
21
21
|
# Creates new span for Tilt templating
|
22
22
|
#
|
23
23
|
StackifyRubyAPM.span name, TYPE do
|
24
|
-
render_without_apm(*args, &block)
|
24
|
+
render_without_apm(*args, **kwargs, &block)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/lib/stackify_apm/util.rb
CHANGED
@@ -35,6 +35,92 @@ module StackifyRubyAPM
|
|
35
35
|
obj[i] = val.to_s
|
36
36
|
ary.push(obj)
|
37
37
|
end
|
38
|
+
|
39
|
+
URL_ID_REGEX = /^(\d+)$/
|
40
|
+
URL_GUID_REGEX = /^(?i)(\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b)$/
|
41
|
+
URL_EMAIL_REGEX = /^((([!#$%&'*+\-\/=?^_`{|}~\w])|([!#$%&'*+\-\/=?^_`{|}~\w][!#$%&'*+\-\/=?^_`{|}~\.\w]{0,}[!#$%&'*+\-\/=?^_`{|}~\w]))[@]\w+([-.]\w+)*\.\w+([-.]\w+)*)$/
|
42
|
+
URL_IP_REGEX = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
43
|
+
|
44
|
+
def self.maskReportingUrl(url)
|
45
|
+
parts = url.split('/', -1)
|
46
|
+
|
47
|
+
if (!parts.length)
|
48
|
+
return '/'
|
49
|
+
end
|
50
|
+
|
51
|
+
maskedParts = []
|
52
|
+
parts.each do |part|
|
53
|
+
maskedParts.push(maskString(part))
|
54
|
+
end
|
55
|
+
|
56
|
+
maskedUrl = maskedParts.join('/')
|
57
|
+
|
58
|
+
if (maskedUrl.length == 1)
|
59
|
+
return maskedUrl
|
60
|
+
end
|
61
|
+
|
62
|
+
if maskedUrl.end_with?('/')
|
63
|
+
trimmedUrl = maskedUrl.slice(0, maskedUrl.length-1)
|
64
|
+
if (!trimmedUrl.length)
|
65
|
+
return '/'
|
66
|
+
end
|
67
|
+
|
68
|
+
return trimmedUrl
|
69
|
+
end
|
70
|
+
|
71
|
+
maskedUrl
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.maskString(string)
|
75
|
+
return '{id}' if string =~ URL_ID_REGEX
|
76
|
+
return '{guid}' if string =~ URL_GUID_REGEX
|
77
|
+
return '{email}' if string =~ URL_EMAIL_REGEX
|
78
|
+
return '{ip}' if string =~ URL_IP_REGEX
|
79
|
+
|
80
|
+
if string.include? ';'
|
81
|
+
string_index = string.index(';');
|
82
|
+
return '' if (string_index <= 0)
|
83
|
+
return string[0..string.index(';')-1] if (string_index)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Default
|
87
|
+
string
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.fileExists?(dir_name)
|
91
|
+
# Ruby 3.2 changed File.exists to File.exist.
|
92
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")
|
93
|
+
return File.exists?(dir_name)
|
94
|
+
else
|
95
|
+
return File.exist?(dir_name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.checkOrCreateFolder(dir_name)
|
100
|
+
if (dir_name.to_s.empty?)
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
|
104
|
+
if (!fileExists?(dir_name))
|
105
|
+
umask = File.umask
|
106
|
+
File.umask(0)
|
107
|
+
FileUtils.mkdir_p(dir_name)
|
108
|
+
File.chmod(0777, dir_name)
|
109
|
+
File.umask(umask)
|
110
|
+
end
|
111
|
+
|
112
|
+
if (!fileExists?(dir_name))
|
113
|
+
puts "Util::Stackify Profiler unable to find [" + dir_name + "]"
|
114
|
+
return false
|
115
|
+
end
|
116
|
+
|
117
|
+
if (!File.writable?(dir_name))
|
118
|
+
puts "Util::Stackify Profiler unable to access/write [" + dir_name + "]"
|
119
|
+
return false
|
120
|
+
end
|
121
|
+
|
122
|
+
return true
|
123
|
+
end
|
38
124
|
end
|
39
125
|
end
|
40
126
|
require 'stackify_apm/util/inspector'
|
data/lib/stackify_apm/version.rb
CHANGED
data/lib/stackify_ruby_apm.rb
CHANGED
@@ -50,22 +50,67 @@ module StackifyRubyAPM
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def self.inject_rum_script
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
transaction_id = defined?(StackifyRubyAPM.current_transaction.id) ? StackifyRubyAPM.current_transaction.id : nil
|
53
|
+
transaction = defined?(StackifyRubyAPM.current_transaction) ? StackifyRubyAPM.current_transaction : nil
|
54
|
+
return '' unless transaction
|
55
|
+
|
56
|
+
transaction_id = defined?(transaction.id) ? transaction.id : nil
|
58
57
|
inject_flag = false
|
59
58
|
|
60
|
-
|
61
|
-
|
59
|
+
config = nil
|
60
|
+
if defined?(agent.config)
|
61
|
+
config = agent.config
|
62
|
+
end
|
63
|
+
|
64
|
+
return '' unless config
|
65
|
+
|
66
|
+
if transaction_id
|
67
|
+
inject_flag = true
|
68
|
+
end
|
69
|
+
|
70
|
+
return '' unless inject_flag
|
71
|
+
|
72
|
+
return '' if config.rum_script_url.to_s.empty? || config.rum_key.to_s.empty?
|
73
|
+
|
74
|
+
rum_settings = {
|
75
|
+
"ID" => transaction_id
|
76
|
+
}
|
77
|
+
|
78
|
+
if defined?(config.environment_name)
|
79
|
+
environment_name = 'Development'
|
80
|
+
if !config.environment_name.to_s.empty?
|
81
|
+
environment_name = config.environment_name
|
82
|
+
end
|
83
|
+
|
84
|
+
rum_settings["Env"] = Base64.strict_encode64(environment_name.encode('utf-8'))
|
85
|
+
end
|
86
|
+
|
87
|
+
application_name = config.application_name
|
88
|
+
return '' if application_name.to_s.empty?
|
89
|
+
|
90
|
+
rum_settings["Name"] = Base64.strict_encode64(application_name.strip.encode('utf-8'))
|
91
|
+
|
92
|
+
if defined?(transaction.name) && !transaction.name.to_s.empty?
|
93
|
+
reporting_url = Util.maskReportingUrl(transaction.name)
|
94
|
+
|
95
|
+
if defined?(transaction.context.request.method) && !transaction.context.request.nil? && !transaction.context.request.method.nil?
|
96
|
+
reporting_url = "#{transaction.context.request.method}-#{reporting_url}"
|
97
|
+
end
|
98
|
+
|
99
|
+
rum_settings["Trans"] = Base64.strict_encode64(reporting_url.encode('utf-8'))
|
62
100
|
end
|
63
101
|
|
64
|
-
return unless inject_flag
|
65
|
-
data_request_id = "V2|#{transaction_id}|#{client_id}|#{device_id}"
|
66
102
|
@rum_script_injected = true
|
67
|
-
|
68
|
-
|
103
|
+
|
104
|
+
if defined?(transaction.context)
|
105
|
+
transaction.context.rum = true
|
106
|
+
end
|
107
|
+
|
108
|
+
rum_content = "<script type=\"text/javascript\">(window.StackifySettings || (window.StackifySettings = #{rum_settings.to_json}))</script><script src=\"#{config.rum_script_url}\" data-key=\"#{config.rum_key}\" async></script>"
|
109
|
+
if rum_content.respond_to?(:html_safe)
|
110
|
+
rum_content.html_safe
|
111
|
+
else
|
112
|
+
rum_content
|
113
|
+
end
|
69
114
|
end
|
70
115
|
|
71
116
|
# Run the custom instrument
|
data/stackify-ruby-apm.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path('lib',
|
3
|
+
lib = File.expand_path('lib', File.dirname(__FILE__))
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'stackify_apm/version'
|
6
6
|
|
@@ -13,6 +13,9 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = 'http://www.stackify.com'
|
14
14
|
spec.license = 'Stackify'
|
15
15
|
|
16
|
+
# Set the minimum Ruby version required
|
17
|
+
spec.required_ruby_version = '>= 3.0.0'
|
18
|
+
|
16
19
|
git_tracked_files = `git ls-files -z`.split("\x0")
|
17
20
|
gem_ignored_files = `git ls-files -i -X .gemignore -z`.split("\x0")
|
18
21
|
spec.files = git_tracked_files - gem_ignored_files
|
@@ -22,10 +25,13 @@ Gem::Specification.new do |spec|
|
|
22
25
|
spec.require_paths = ['lib']
|
23
26
|
|
24
27
|
# rails
|
25
|
-
if RUBY_VERSION > '2.
|
28
|
+
if RUBY_VERSION > '2.9'
|
29
|
+
spec.add_development_dependency 'rails', '~> 6.1'
|
30
|
+
elsif RUBY_VERSION > '2.5'
|
26
31
|
spec.add_development_dependency 'rails', '~> 5.0'
|
27
32
|
else
|
28
33
|
spec.add_development_dependency 'rails', '~> 4.0'
|
34
|
+
spec.add_development_dependency 'sprockets', '~> 3.0'
|
29
35
|
end
|
30
36
|
|
31
37
|
# bigdecimal
|
@@ -33,32 +39,63 @@ Gem::Specification.new do |spec|
|
|
33
39
|
spec.add_development_dependency 'bigdecimal'
|
34
40
|
end
|
35
41
|
|
36
|
-
|
37
|
-
|
38
|
-
|
42
|
+
if RUBY_PLATFORM == 'i386-mingw32'
|
43
|
+
spec.add_development_dependency 'tzinfo-data'
|
44
|
+
end
|
45
|
+
|
46
|
+
if RUBY_VERSION > '2.9'
|
47
|
+
spec.add_development_dependency 'bundler', '~> 2.4.12'
|
48
|
+
else
|
49
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
50
|
+
end
|
51
|
+
|
52
|
+
if RUBY_VERSION > '2.9'
|
53
|
+
spec.add_development_dependency 'rake'
|
54
|
+
spec.add_development_dependency 'rspec', '3.9.0'
|
55
|
+
spec.add_development_dependency 'curb', '1.0.3'
|
56
|
+
spec.add_development_dependency 'pg'
|
57
|
+
spec.add_development_dependency 'sqlite3'
|
58
|
+
else
|
59
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
60
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
61
|
+
spec.add_development_dependency 'curb', '0.9.8'
|
62
|
+
spec.add_development_dependency 'pg', '~> 0.20'
|
63
|
+
spec.add_development_dependency 'sqlite3', '1.3.13'
|
64
|
+
spec.add_development_dependency('delegate_matcher', '~> 0.4') # for testing
|
65
|
+
end
|
66
|
+
|
67
|
+
|
39
68
|
spec.add_development_dependency 'activerecord'
|
40
|
-
spec.add_development_dependency 'curb', '0.9.8'
|
41
69
|
spec.add_development_dependency 'fakeredis'
|
42
70
|
spec.add_development_dependency 'http'
|
43
71
|
spec.add_development_dependency 'httpclient'
|
44
72
|
spec.add_development_dependency 'mongo'
|
45
73
|
spec.add_development_dependency 'mysql2'
|
46
|
-
|
74
|
+
|
47
75
|
spec.add_development_dependency 'rack-test'
|
48
76
|
spec.add_development_dependency 'rubocop'
|
49
77
|
spec.add_development_dependency 'sequel'
|
50
78
|
spec.add_development_dependency 'sinatra'
|
51
79
|
spec.add_development_dependency 'sinatra-activerecord'
|
52
|
-
|
80
|
+
|
53
81
|
spec.add_development_dependency 'stackify-api-ruby'
|
54
82
|
spec.add_development_dependency 'timecop'
|
55
83
|
spec.add_development_dependency 'to_bool'
|
56
84
|
spec.add_development_dependency 'webmock'
|
57
85
|
spec.add_development_dependency 'delayed_job'
|
58
86
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
87
|
+
if RUBY_VERSION > '2.9'
|
88
|
+
spec.add_dependency('concurrent-ruby')
|
89
|
+
spec.add_dependency('delegate_matcher')
|
90
|
+
spec.add_dependency('faraday')
|
91
|
+
spec.add_dependency('net_http_unix')
|
92
|
+
spec.add_dependency('rufus-scheduler')
|
93
|
+
else
|
94
|
+
spec.add_dependency('concurrent-ruby', '~> 1.0')
|
95
|
+
spec.add_dependency('delegate_matcher', '~> 0.4')
|
96
|
+
spec.add_dependency('faraday', '~> 0.8')
|
97
|
+
spec.add_dependency('net_http_unix', '~> 0.2')
|
98
|
+
spec.add_dependency('rufus-scheduler', '~> 3.0')
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|