traceview 3.1.0-java → 3.2.1-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ab475ce550edae53924cbe72eaf7b93e337df71
4
- data.tar.gz: 12ee03213258aa59f4fd7641247db417833cde06
3
+ metadata.gz: 96c087aab94a58d443be7e150a674f72cffbf110
4
+ data.tar.gz: 08616ab412adefe991cc489aecb9c960c64dc8db
5
5
  SHA512:
6
- metadata.gz: c3f934605ce6a37c9e5b11d6d9490a01c279b104b6a4fe055bc8db4f76d63bf95df4591081b81534d8505d4c2fc2b5bffab4227bb1b6340253df5c03a6742943
7
- data.tar.gz: c4a2ea84c0a5e861f7878304fb59aa66d3f9f47165bc909dd25ff95c74f745cd72984473d6e5955f8f3ceb9357a16a2b9f48715bd461bbe3ea546e62a33e8a20
6
+ metadata.gz: 8f950a8ad1c44cf89064f94c4eb17b26020a74e2c1156af6e4cb8cfc1c80612e0e96aefb4576bcff8ffab3908e0358a0c2d3edd0338c69cc2fd44215e6b0100d
7
+ data.tar.gz: 311bb5d286c6eef95149a6807f81334117a727ab1d440c773442c6d7c6ce6e8e647bfad93742b2ac1e227245b6d2aba988533d279404eabbf9482c9c91b66690
data/.travis.yml CHANGED
@@ -63,8 +63,8 @@ before_install:
63
63
  - sudo service cassandra start
64
64
 
65
65
  install:
66
- - wget https://www.tracelytics.com/install_tracelytics.sh
67
- - sudo sh ./install_tracelytics.sh f51e2a43-0ee5-4851-8a54-825773b3218e
66
+ - wget https://files.appneta.com/install_appneta.sh
67
+ - sudo sh ./install_appneta.sh f51e2a43-0ee5-4851-8a54-825773b3218e
68
68
  - sudo apt-get install -y tracelytics-java-agent
69
69
 
70
70
  before_script:
data/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ https://github.com/appneta/oboe-ruby/releases
4
4
 
5
5
  Dates in this file are in the format MM/DD/YYYY.
6
6
 
7
+ # traceview 3.2.0
8
+
9
+ This minor release adds the following:
10
+
11
+ * New and improved method profiling: #135
12
+ * Fix URL Query config: #136
13
+
14
+ Pushed to Rubygems:
15
+
16
+ https://rubygems.org/gems/traceview/versions/3.2.0
17
+ https://rubygems.org/gems/traceview/versions/3.2.0-java
18
+
7
19
  # traceview 3.1.0
8
20
 
9
21
  This minor release adds the following:
data/lib/traceview.rb CHANGED
@@ -40,6 +40,7 @@ begin
40
40
 
41
41
  require 'traceview/config'
42
42
  require 'traceview/loading'
43
+ require 'traceview/legacy_method_profiling'
43
44
  require 'traceview/method_profiling'
44
45
 
45
46
  if TraceView.loaded
@@ -45,6 +45,152 @@ module TraceView
45
45
  TraceView::API.log(nil, 'profile_exit', exit_kvs)
46
46
  end
47
47
  end
48
+
49
+ ##
50
+ # Public: Profile a method on a class or module. That method can be of any (accessible)
51
+ # type (instance, singleton, private, protected etc.).
52
+ #
53
+ # klass - the class or module that has the method to profile
54
+ # method - the method to profile. Can be singleton, instance, private etc...
55
+ # opts - a hash specifying the one or more of the following options:
56
+ # * :arguments - report the arguments passed to <tt>method</tt> on each profile (default: false)
57
+ # * :result - report the return value of <tt>method</tt> on each profile (default: false)
58
+ # * :backtrace - report the return value of <tt>method</tt> on each profile (default: false)
59
+ # * :name - alternate name for the profile reported in the dashboard (default: method name)
60
+ # extra_kvs - a hash containing any additional KVs you would like reported with the profile
61
+ #
62
+ # Example
63
+ #
64
+ # opts = {}
65
+ # opts[:backtrace] = true
66
+ # opts[:arguments] = false
67
+ # opts[:name] = :array_sort
68
+ #
69
+ # TraceView::API.profile_method(Array, :sort, opts)
70
+ #
71
+ def profile_method(klass, method, opts = {}, extra_kvs = {})
72
+
73
+ # If we're on an unsupported platform (ahem Mac), just act
74
+ # like we did something to nicely play the no-op part.
75
+ return true unless TraceView.loaded
76
+
77
+ if RUBY_VERSION < '1.9.3'
78
+ TraceView.logger.warn "[traceview/error] profile_method: Use the legacy method profiling for Ruby versions before 1.9.3"
79
+ return false
80
+
81
+ elsif !klass.is_a?(Module)
82
+ TraceView.logger.warn "[traceview/error] profile_method: Not sure what to do with #{klass}. Send a class or module."
83
+ return false
84
+
85
+ elsif !method.is_a?(Symbol)
86
+ if method.is_a?(String)
87
+ method = method.to_sym
88
+ else
89
+ TraceView.logger.warn "[traceview/error] profile_method: Not sure what to do with #{method}. Send a string or symbol for method."
90
+ return false
91
+ end
92
+ end
93
+
94
+ instance_method = klass.instance_methods.include?(method) || klass.private_instance_methods.include?(method)
95
+ class_method = klass.singleton_methods.include?(method)
96
+
97
+ # Make sure the request klass::method exists
98
+ if !instance_method && !class_method
99
+ TraceView.logger.warn "[traceview/error] profile_method: Can't instrument #{klass}.#{method} as it doesn't seem to exist."
100
+ TraceView.logger.warn "[traceview/error] #{__FILE__}:#{__LINE__}"
101
+ return false
102
+ end
103
+
104
+ # Strip '!' or '?' from method if present
105
+ safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
106
+ safe_method_name ||= method
107
+
108
+ without_traceview = "#{safe_method_name}_without_traceview"
109
+ with_traceview = "#{safe_method_name}_with_traceview"
110
+
111
+ # Check if already profiled
112
+ if klass.instance_methods.include?(with_traceview.to_sym) ||
113
+ klass.singleton_methods.include?(with_traceview.to_sym)
114
+ TraceView.logger.warn "[traceview/error] profile_method: #{klass}::#{method} already profiled."
115
+ TraceView.logger.warn "[traceview/error] profile_method: #{__FILE__}:#{__LINE__}"
116
+ return false
117
+ end
118
+
119
+ source_location = []
120
+ if instance_method
121
+ ::TraceView::Util.send_include(klass, ::TraceView::MethodProfiling)
122
+ source_location = klass.instance_method(method).source_location
123
+ elsif class_method
124
+ ::TraceView::Util.send_extend(klass, ::TraceView::MethodProfiling)
125
+ source_location = klass.method(method).source_location
126
+ end
127
+
128
+ report_kvs = collect_profile_kvs(klass, method, opts, extra_kvs, source_location)
129
+ report_kvs[:MethodName] = safe_method_name
130
+
131
+ if instance_method
132
+ klass.class_eval do
133
+ define_method(with_traceview) { | *args, &block |
134
+ profile_wrapper(without_traceview, report_kvs, opts, *args, &block)
135
+ }
136
+
137
+ alias_method without_traceview, "#{method}"
138
+ alias_method "#{method}", with_traceview
139
+ end
140
+ elsif class_method
141
+ klass.define_singleton_method(with_traceview) { | *args, &block |
142
+ profile_wrapper(without_traceview, report_kvs, opts, *args, &block)
143
+ }
144
+
145
+ klass.singleton_class.class_eval do
146
+ alias_method without_traceview, "#{method}"
147
+ alias_method "#{method}", with_traceview
148
+ end
149
+ end
150
+ true
151
+ end
152
+
153
+ private
154
+
155
+ ##
156
+ # Private: Helper method to aggregate KVs to report
157
+ #
158
+ # klass - the class or module that has the method to profile
159
+ # method - the method to profile. Can be singleton, instance, private etc...
160
+ # opts - a hash specifying the one or more of the following options:
161
+ # * :arguments - report the arguments passed to <tt>method</tt> on each profile (default: false)
162
+ # * :result - report the return value of <tt>method</tt> on each profile (default: false)
163
+ # * :backtrace - report the return value of <tt>method</tt> on each profile (default: false)
164
+ # * :name - alternate name for the profile reported in the dashboard (default: method name)
165
+ # extra_kvs - a hash containing any additional KVs you would like reported with the profile
166
+ # source_location - array returned from klass.method(:name).source_location
167
+ #
168
+ def collect_profile_kvs(klass, method, opts, extra_kvs, source_location)
169
+ report_kvs = {}
170
+ report_kvs[:Language] ||= :ruby
171
+ report_kvs[:ProfileName] ||= opts[:name] ? opts[:name] : method
172
+
173
+ if klass.is_a?(Class)
174
+ report_kvs[:Class] = klass.to_s
175
+ else
176
+ report_kvs[:Module] = klass.to_s
177
+ end
178
+
179
+ # If this is a Rails Controller, report the KVs
180
+ if defined?(::AbstractController::Base) && klass.ancestors.include?(::AbstractController::Base)
181
+ report_kvs[:Controller] = klass.to_s
182
+ report_kvs[:Action] = method.to_s
183
+ end
184
+
185
+ # We won't have access to this info for native methods (those not defined in Ruby).
186
+ if source_location.is_a?(Array) && source_location.length == 2
187
+ report_kvs[:File] = source_location[0]
188
+ report_kvs[:LineNumber] = source_location[1]
189
+ end
190
+
191
+ # Merge in any extra_kvs requested
192
+ report_kvs.merge!(extra_kvs)
193
+ end
48
194
  end
49
195
  end
50
196
  end
@@ -22,15 +22,16 @@ module TraceView
22
22
 
23
23
  # Internal: Get the current backtrace.
24
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
25
+ # ignore - Number of frames to ignore at the top of the backtrace. Use
26
+ # when you know how many layers deep in the key call is being
27
27
  # made.
28
28
  #
29
29
  # Returns a string with each frame of the backtrace separated by '\r\n'.
30
30
  #
31
- # FIXME: ignore is not currently used (see BACKTRACE_CUTOFF)
32
- def backtrace(_ignore = 1)
33
- trim_backtrace(Kernel.caller).join("\r\n")
31
+ def backtrace(ignore = 0)
32
+ bt = Kernel.caller
33
+ bt.slice!(0, ignore)
34
+ trim_backtrace(bt).join("\r\n")
34
35
  end
35
36
 
36
37
  # Internal: Trim a backtrace to a manageable size
@@ -168,9 +168,8 @@ module TraceViewBase
168
168
  # False otherwise
169
169
  #
170
170
  def tracing?
171
- return false unless TraceView.loaded
172
-
173
- TraceView::Context.isValid && !TraceView.never?
171
+ return false if !TraceView.loaded || TraceView.never?
172
+ TraceView::Context.isValid
174
173
  end
175
174
 
176
175
  def log(layer, label, options = {})
@@ -18,7 +18,7 @@ module TraceView
18
18
  :typhoeus]
19
19
 
20
20
  # Subgrouping of instrumentation
21
- @@http_clients = [:curb, :excon, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
21
+ @@http_clients = [:curb, :excon, :em_http_request, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
22
22
 
23
23
  ##
24
24
  # Return the raw nested hash.
@@ -217,14 +217,14 @@ module TraceView
217
217
  elsif key == :include_url_query_params
218
218
  # Obey the global flag and update all of the per instrumentation
219
219
  # <tt>:log_args</tt> values.
220
- @@http_clients.each do |i|
221
- @@config[i][:log_args] = value
222
- end
220
+ @@config[:rack][:log_args] = value
223
221
 
224
222
  elsif key == :include_remote_url_params
225
223
  # Obey the global flag and update all of the per instrumentation
226
224
  # <tt>:log_args</tt> values.
227
- @@config[:rack][:log_args] = value
225
+ @@http_clients.each do |i|
226
+ @@config[i][:log_args] = value
227
+ end
228
228
  end
229
229
 
230
230
  # Update liboboe if updating :tracing_mode
@@ -0,0 +1,97 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ ##
5
+ # Provides the methods necessary for method profiling. Profiling
6
+ # results are sent to the TraceView dashboard.
7
+ #
8
+ # Example usage:
9
+ # class MyApp
10
+ # include TraceViewMethodProfiling
11
+ #
12
+ # def process_request()
13
+ # # The hard work
14
+ # end
15
+ #
16
+ # # call syntax: profile_method <method>, <profile_name>
17
+ # profile_method :process_request, 'request_processor'
18
+ # end
19
+ module TraceViewMethodProfiling
20
+ def self.included(klass)
21
+ klass.extend ClassMethods
22
+ end
23
+
24
+ module ClassMethods
25
+ def profile_method_noop(*args)
26
+ nil
27
+ end
28
+
29
+ def profile_method_real(method_name, profile_name, store_args = false, store_return = false, *_)
30
+ begin
31
+ # this only gets file and line where profiling is turned on, presumably
32
+ # right after the function definition. ruby 1.9 and 2.0 has nice introspection (Method.source_location)
33
+ # but its appears no such luck for ruby 1.8
34
+ file = ''
35
+ line = ''
36
+ if RUBY_VERSION >= '1.9'
37
+ info = instance_method(method_name).source_location
38
+ unless info.nil?
39
+ file = info[0].to_s
40
+ line = info[1].to_s
41
+ end
42
+ else
43
+ info = Kernel.caller[0].split(':')
44
+ file = info.first.to_s
45
+ line = info.last.to_s
46
+ end
47
+
48
+ # Safety: Make sure there are no quotes or double quotes to break the class_eval
49
+ file = file.gsub(/[\'\"]/, '')
50
+ line = line.gsub(/[\'\"]/, '')
51
+
52
+ # profiling via ruby-prof, is it possible to get return value of profiled code?
53
+ code = "def _traceview_profiled_#{method_name}(*args, &block)
54
+ entry_kvs = {}
55
+ entry_kvs['Language'] = 'ruby'
56
+ entry_kvs['ProfileName'] = '#{TraceView::Util.prettify(profile_name)}'
57
+ entry_kvs['FunctionName'] = '#{TraceView::Util.prettify(method_name)}'
58
+ entry_kvs['File'] = '#{file}'
59
+ entry_kvs['LineNumber'] = '#{line}'
60
+ entry_kvs['Args'] = TraceView::API.pps(*args) if #{store_args}
61
+ entry_kvs.merge!(::TraceView::API.get_class_name(self))
62
+
63
+ TraceView::API.log(nil, 'profile_entry', entry_kvs)
64
+
65
+ ret = _traceview_orig_#{method_name}(*args, &block)
66
+
67
+ exit_kvs = {}
68
+ exit_kvs['Language'] = 'ruby'
69
+ exit_kvs['ProfileName'] = '#{TraceView::Util.prettify(profile_name)}'
70
+ exit_kvs['ReturnValue'] = TraceView::API.pps(ret) if #{store_return}
71
+
72
+ TraceView::API.log(nil, 'profile_exit', exit_kvs)
73
+ ret
74
+ end"
75
+ rescue => e
76
+ TraceView.logger.warn "[traceview/warn] profile_method: #{e.inspect}"
77
+ end
78
+
79
+ begin
80
+ class_eval code, __FILE__, __LINE__
81
+ alias_method "_traceview_orig_#{method_name}", method_name
82
+ alias_method method_name, "_traceview_profiled_#{method_name}"
83
+ rescue => e
84
+ TraceView.logger.warn "[traceview/warn] Fatal error profiling method (#{method_name}): #{e.inspect}" if TraceView::Config[:verbose]
85
+ end
86
+ end
87
+
88
+ # This allows this module to be included and called even if the gem is in
89
+ # no-op mode (no base libraries).
90
+ if TraceView.loaded
91
+ alias :profile_method :profile_method_real
92
+ else
93
+ alias :profile_method :profile_method_noop
94
+ end
95
+
96
+ end
97
+ end
@@ -1,97 +1,25 @@
1
- # Copyright (c) 2013 AppNeta, Inc.
2
- # All rights reserved.
3
1
 
4
- ##
5
- # Provides the methods necessary for method profiling. Profiling
6
- # results are sent to the TraceView dashboard.
7
- #
8
- # Example usage:
9
- # class MyApp
10
- # include TraceViewMethodProfiling
11
- #
12
- # def process_request()
13
- # # The hard work
14
- # end
15
- #
16
- # # call syntax: profile_method <method>, <profile_name>
17
- # profile_method :process_request, 'request_processor'
18
- # end
19
- module TraceViewMethodProfiling
20
- def self.included(klass)
21
- klass.extend ClassMethods
22
- end
2
+ module TraceView
3
+ module MethodProfiling
4
+ def profile_wrapper(method, report_kvs, opts, *args, &block)
5
+ report_kvs[:Backtrace] = TraceView::API.backtrace(2) if opts[:backtrace]
6
+ report_kvs[:Arguments] = args if opts[:arguments]
23
7
 
24
- module ClassMethods
25
- def profile_method_noop(*args)
26
- nil
27
- end
8
+ TraceView::API.log(nil, 'profile_entry', report_kvs)
28
9
 
29
- def profile_method_real(method_name, profile_name, store_args = false, store_return = false, *_)
30
10
  begin
31
- # this only gets file and line where profiling is turned on, presumably
32
- # right after the function definition. ruby 1.9 and 2.0 has nice introspection (Method.source_location)
33
- # but its appears no such luck for ruby 1.8
34
- file = ''
35
- line = ''
36
- if RUBY_VERSION >= '1.9'
37
- info = instance_method(method_name).source_location
38
- unless info.nil?
39
- file = info[0].to_s
40
- line = info[1].to_s
41
- end
42
- else
43
- info = Kernel.caller[0].split(':')
44
- file = info.first.to_s
45
- line = info.last.to_s
46
- end
47
-
48
- # Safety: Make sure there are no quotes or double quotes to break the class_eval
49
- file = file.gsub(/[\'\"]/, '')
50
- line = line.gsub(/[\'\"]/, '')
51
-
52
- # profiling via ruby-prof, is it possible to get return value of profiled code?
53
- code = "def _traceview_profiled_#{method_name}(*args, &block)
54
- entry_kvs = {}
55
- entry_kvs['Language'] = 'ruby'
56
- entry_kvs['ProfileName'] = '#{TraceView::Util.prettify(profile_name)}'
57
- entry_kvs['FunctionName'] = '#{TraceView::Util.prettify(method_name)}'
58
- entry_kvs['File'] = '#{file}'
59
- entry_kvs['LineNumber'] = '#{line}'
60
- entry_kvs['Args'] = TraceView::API.pps(*args) if #{store_args}
61
- entry_kvs.merge!(::TraceView::API.get_class_name(self))
62
-
63
- TraceView::API.log(nil, 'profile_entry', entry_kvs)
64
-
65
- ret = _traceview_orig_#{method_name}(*args, &block)
66
-
67
- exit_kvs = {}
68
- exit_kvs['Language'] = 'ruby'
69
- exit_kvs['ProfileName'] = '#{TraceView::Util.prettify(profile_name)}'
70
- exit_kvs['ReturnValue'] = TraceView::API.pps(ret) if #{store_return}
71
-
72
- TraceView::API.log(nil, 'profile_exit', exit_kvs)
73
- ret
74
- end"
11
+ rv = self.send(method, *args, &block)
12
+ report_kvs[:ReturnValue] = rv if opts[:result]
13
+ rv
75
14
  rescue => e
76
- TraceView.logger.warn "[traceview/warn] profile_method: #{e.inspect}"
77
- end
78
-
79
- begin
80
- class_eval code, __FILE__, __LINE__
81
- alias_method "_traceview_orig_#{method_name}", method_name
82
- alias_method method_name, "_traceview_profiled_#{method_name}"
83
- rescue => e
84
- TraceView.logger.warn "[traceview/warn] Fatal error profiling method (#{method_name}): #{e.inspect}" if TraceView::Config[:verbose]
15
+ TraceView::API.log_exception(nil, e)
16
+ raise
17
+ ensure
18
+ report_kvs.delete(:Backtrace)
19
+ report_kvs.delete(:Controller)
20
+ report_kvs.delete(:Action)
21
+ TraceView::API.log(nil, 'profile_exit', report_kvs)
85
22
  end
86
23
  end
87
-
88
- # This allows this module to be included and called even if the gem is in
89
- # no-op mode (no base libraries).
90
- if TraceView.loaded
91
- alias :profile_method :profile_method_real
92
- else
93
- alias :profile_method :profile_method_noop
94
- end
95
-
96
24
  end
97
25
  end