appoptics_apm 4.2.7 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d859819610b985d65fe379af2f65e3ffec0627acff6dd9be4e243597f8e0574
4
- data.tar.gz: 5ec8816746382d1a301c81e450cdf63a53f8b77bff6a3495187c6806d43bf01f
3
+ metadata.gz: 170c3e8f35f9e439942788b3a801282c4a1deaee3090e8957bc76bdf9a209915
4
+ data.tar.gz: 4e23ef886ee0f9358dfba882bc35e0258b229b0c5fa617055345216e85376999
5
5
  SHA512:
6
- metadata.gz: f2d1084a46dda8a0d2cb0a7f3f931125d81ad89caa85cce06bf50c19de9a286c819730f03844a882bcc433217cfe55ec8511b52618468c92160fd1e09dd669ed
7
- data.tar.gz: f4e3043a915cdd562de21dc881ae2bf54c8b2dd48fb95d6c4e5a86d039dc0070f6a9c970fb252f096ce32fc15161ada8a44aa0060c38688972740646a1065628
6
+ metadata.gz: 2fa70bacf8b44352826eb859bd687385a801fb1ea3c3289f8c7e79cff251ec6e05bbeb6510780af9b61a25376c171265a4308118da84c975a7a3d6a8ac803f3a
7
+ data.tar.gz: 763038da0e769d87d450d356fb517db8e908d337c0c989a9ae91a278fe7d42f09355b9c06a2f394dd5a30c0ff513587aeb65db24fcc828b186baacc629700470
@@ -11,9 +11,9 @@ env:
11
11
  - DBTYPE=mysql
12
12
 
13
13
  rvm:
14
- - 2.5.1
15
- - 2.4.4
16
- - 2.3.6
14
+ - 2.5.3
15
+ - 2.4.5
16
+ - 2.3.8
17
17
  # - jruby-9.0.5.0
18
18
 
19
19
  gemfile:
@@ -23,7 +23,7 @@ gemfile:
23
23
  - gemfiles/instrumentation_mocked_oldgems.gemfile
24
24
  - gemfiles/frameworks.gemfile
25
25
  - gemfiles/rails52.gemfile
26
- # - gemfiles/rails51.gemfile
26
+ - gemfiles/rails51.gemfile
27
27
  - gemfiles/rails42.gemfile
28
28
  ## - gemfiles/rails32.gemfile # We currently are not supporting Rails 3.2
29
29
  - gemfiles/delayed_job.gemfile
@@ -31,9 +31,9 @@ gemfile:
31
31
 
32
32
  matrix:
33
33
  exclude:
34
- - rvm: 2.5.1
34
+ - rvm: 2.5.3
35
35
  env: DBTYPE=mysql
36
- - rvm: 2.4.4
36
+ - rvm: 2.4.5
37
37
  env: DBTYPE=mysql
38
38
 
39
39
  - gemfile: gemfiles/unit.gemfile
@@ -72,10 +72,10 @@ matrix:
72
72
 
73
73
  # Rails 3.2 is not compatible with Ruby >= 2.4
74
74
  # We currently are not supporting Rails 3.2
75
- - rvm: 2.5.1
76
- gemfile: gemfiles/rails32.gemfile
77
- - rvm: 2.4.4
78
- gemfile: gemfiles/rails32.gemfile
75
+ # - rvm: 2.5.1
76
+ # gemfile: gemfiles/rails32.gemfile
77
+ # - rvm: 2.4.4
78
+ # gemfile: gemfiles/rails32.gemfile
79
79
 
80
80
  # - rvm: jruby-9.0.5.0
81
81
  # gemfile: gemfiles/delayed_job.gemfile
data/Rakefile CHANGED
@@ -96,7 +96,7 @@ task :fetch_ext_deps do
96
96
  open(remote_file, 'rb') do |rf|
97
97
  content = rf.read
98
98
  File.open(local_file, 'wb') { |f| f.puts content }
99
- puts "C-Lib VERSION: #{content}"
99
+ puts "!!!!!!! C-Lib VERSION: #{content.strip} !!!!!!!!"
100
100
  end
101
101
 
102
102
  # oboe and bson header files
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.add_development_dependency('byebug', '>= 8.0.0')
43
43
  s.add_development_dependency('pry', '>= 0.10.0')
44
44
  s.add_development_dependency('pry-byebug', '>= 3.0.0')
45
+ s.add_development_dependency('minitest-hooks', '>= 1.5.0')
45
46
  else
46
47
  s.add_development_dependency('pry', '>= 0.10.0')
47
48
  end
@@ -62,6 +62,7 @@ while retries > 0
62
62
  $stderr.puts 'Download of the c-extension for the appoptics_apm gem failed.'
63
63
  $stderr.puts 'appoptics_apm will not instrument the code. No tracing will occur.'
64
64
  $stderr.puts 'Contact support@appoptics.com if the problem persists.'
65
+ $stderr.puts "error:\n#{e.message}"
65
66
  $stderr.puts '==================================================================='
66
67
  create_makefile('oboe_noop', 'noop')
67
68
  end
@@ -1 +1 @@
1
- 3.1.4
1
+ 3.2.0
@@ -76,6 +76,7 @@ module AppOpticsAPM
76
76
  return AppOpticsAPM::Context.toString
77
77
  end
78
78
 
79
+ exception.message << exception.class.name if exception.message.length < 4
79
80
  opts.merge!(:Spec => 'error',
80
81
  :ErrorClass => exception.class.name,
81
82
  :ErrorMsg => exception.message)
@@ -23,7 +23,7 @@ module AppOpticsAPM
23
23
  yield
24
24
  ensure
25
25
  duration =(1000 * 1000 * (Time.now - start)).round(0)
26
- transaction_name = determine_transaction_name(span)
26
+ transaction_name = determine_transaction_name(span, kvs)
27
27
  kvs[:TransactionName] = AppOpticsAPM::Span.createSpan(transaction_name, nil, duration)
28
28
  AppOpticsAPM.transaction_name = nil
29
29
  end
@@ -31,16 +31,23 @@ module AppOpticsAPM
31
31
  private
32
32
 
33
33
  ##
34
- # Determine the transaction name to be set on the trace
34
+ # Determine the transaction name to be set on the trace.
35
35
  #
36
36
  # === Argument:
37
- # * +opts+ (hash) the value of :TransactionName will be set as custom transaction name
37
+ # * +span+ the name of the current span (used to construct a transaction name if none is defined)
38
+ # * +kvs+ (hash, optional) the hash that may have values for 'Controller' and 'Action'
38
39
  #
39
40
  # === Returns:
40
- # (string) the current transaction name
41
+ # (string) the determined transaction name
41
42
  #
42
- def determine_transaction_name(span)
43
- AppOpticsAPM.transaction_name || AppOpticsAPM::SDK.set_transaction_name("custom-#{span}")
43
+ def determine_transaction_name(span, kvs = {})
44
+ if AppOpticsAPM.transaction_name
45
+ AppOpticsAPM.transaction_name
46
+ elsif kvs['Controller'] && kvs['Action']
47
+ [kvs['Controller'], kvs['Action']].join('.')
48
+ else
49
+ "custom-#{span}"
50
+ end
44
51
  end
45
52
 
46
53
  end
@@ -14,7 +14,7 @@ module AppOpticsAPM
14
14
  @@instrumentation = [:action_controller, :action_controller_api, :action_view,
15
15
  :active_record, :bunnyclient, :bunnyconsumer, :cassandra, :curb,
16
16
  :dalli, :delayed_jobclient, :delayed_jobworker,
17
- :em_http_request, :excon, :faraday, :grape,
17
+ :em_http_request, :excon, :faraday, :grpc_client, :grape,
18
18
  :httpclient, :nethttp, :memcached, :mongo, :moped, :rack, :redis,
19
19
  :resqueclient, :resqueworker, :rest_client,
20
20
  :sequel, :sidekiqclient, :sidekiqworker, :typhoeus]
@@ -60,7 +60,7 @@ module AppOpticsAPM
60
60
 
61
61
  # Since Grape uses throw/catch and not Exceptions, we have to create an exception here
62
62
  exception = GrapeError.new(error[:message] ? error[:message] : "No message given.")
63
- exception.set_backtrace(::AppOpticsAPM::API.backtrace) if AppOpticsAPM::Config[:grape][:collect_backtraces]
63
+ exception.set_backtrace(::AppOpticsAPM::API.backtrace)
64
64
 
65
65
  ::AppOpticsAPM::API.log_exception('rack', exception )
66
66
 
@@ -0,0 +1,161 @@
1
+ # Copyright (c) 2018 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ module GRPC
6
+
7
+ module ActiveCall
8
+ if defined? ::GRPC
9
+ StatusCodes = {}
10
+ ::GRPC::Core::StatusCodes.constants.each { |code| StatusCodes[::GRPC::Core::StatusCodes.const_get(code)] = code }
11
+ end
12
+
13
+ def self.included(klass)
14
+ ::AppOpticsAPM::Util.method_alias(klass, :request_response, ::GRPC::ActiveCall)
15
+ ::AppOpticsAPM::Util.method_alias(klass, :client_streamer, ::GRPC::ActiveCall)
16
+ ::AppOpticsAPM::Util.method_alias(klass, :server_streamer, ::GRPC::ActiveCall)
17
+ ::AppOpticsAPM::Util.method_alias(klass, :bidi_streamer, ::GRPC::ActiveCall)
18
+ end
19
+
20
+ def grpc_tags(method_type, method)
21
+ tags = { 'Spec' => 'rsc',
22
+ 'RemoteURL' => "grpc://#{peer}#{method}",
23
+ 'GRPCMethodType' => method_type,
24
+ 'IsService' => 'True'
25
+ }
26
+ tags['Backtrace'] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:grpc_client][:collect_backtraces]
27
+ tags
28
+ end
29
+
30
+ def request_response_with_appoptics(req, metadata: {})
31
+ unary_response(req, type: 'UNARY', metadata: metadata, without: :request_response_without_appoptics)
32
+ end
33
+
34
+ def client_streamer_with_appoptics(req, metadata: {})
35
+ unary_response(req, type: 'CLIENT_STREAMING', metadata: metadata, without: :client_streamer_without_appoptics)
36
+ end
37
+
38
+ def server_streamer_with_appoptics(req, metadata: {}, &blk)
39
+ @tags = grpc_tags('SERVER_STREAMING', metadata[:method] || metadata_to_send[:method])
40
+ AppOpticsAPM::API.log_entry('grpc_client', @tags)
41
+ metadata['x-trace'] = AppOpticsAPM::Context.toString
42
+ AppOpticsAPM::SDK.set_transaction_name(metadata[:method]) if AppOpticsAPM.transaction_name.nil?
43
+
44
+ patch_receive_and_check_status # need to patch this so that log_exit can be called after the enum is consumed
45
+
46
+ response = server_streamer_without_appoptics(req, metadata: metadata)
47
+ block_given? ? response.each { |r| yield r } : response
48
+ rescue => e
49
+ # this check is needed because the exception may have been logged in patch_receive_and_check_status
50
+ unless e.instance_variable_get(:@exn_logged)
51
+ context_from_incoming
52
+ AppOpticsAPM::API.log_exception('grpc_client', e)
53
+ AppOpticsAPM::API.log_exit('grpc_client', exit_tags(@tags))
54
+ end
55
+ raise e
56
+ end
57
+
58
+ def bidi_streamer_with_appoptics(req, metadata: {}, &blk)
59
+ @tags = grpc_tags('BIDI_STREAMING', metadata[:method] || metadata_to_send[:method])
60
+ AppOpticsAPM::API.log_entry('grpc_client', @tags)
61
+ metadata['x-trace'] = AppOpticsAPM::Context.toString
62
+ AppOpticsAPM::SDK.set_transaction_name(metadata[:method]) if AppOpticsAPM.transaction_name.nil?
63
+
64
+ patch_set_input_stream_done
65
+
66
+ response = bidi_streamer_without_appoptics(req, metadata: metadata)
67
+ block_given? ? response.each { |r| yield r } : response
68
+ rescue => e
69
+ unless e.instance_variable_get(:@exn_logged)
70
+ context_from_incoming
71
+ AppOpticsAPM::API.log_exception('grpc_client', e)
72
+ AppOpticsAPM::API.log_exit('grpc_client', exit_tags(@tags))
73
+ end
74
+ raise e
75
+ end
76
+
77
+ private
78
+
79
+ def unary_response(req, type: , metadata: , without:)
80
+ tags = grpc_tags(type, metadata[:method] || metadata_to_send[:method])
81
+ AppOpticsAPM::SDK.trace('grpc_client', tags) do
82
+ metadata['x-trace'] = AppOpticsAPM::Context.toString
83
+ AppOpticsAPM::SDK.set_transaction_name(metadata[:method]) if AppOpticsAPM.transaction_name.nil?
84
+ begin
85
+ send(without, req, metadata: metadata)
86
+ ensure
87
+ exit_tags(tags)
88
+ context_from_incoming
89
+ end
90
+ end
91
+ end
92
+
93
+ def patch_receive_and_check_status
94
+ def self.receive_and_check_status # need to patch this so that log_exit can be called after the enum is consumed
95
+ super
96
+ context_from_incoming
97
+ rescue => e
98
+ context_from_incoming
99
+ AppOpticsAPM::API.log_exception('grpc_client', e)
100
+ raise e
101
+ ensure
102
+ AppOpticsAPM::API.log_exit('grpc_client', exit_tags(@tags))
103
+ end
104
+ end
105
+
106
+ def patch_set_input_stream_done
107
+ # need to patch this instance method so that log_exit can be called after the enum is consumed
108
+ def self.set_input_stream_done
109
+ return if status.nil?
110
+ context_from_incoming
111
+ if status.code > 0
112
+ AppOpticsAPM::API.log_exception('grpc_client', $!)
113
+ end
114
+ AppOpticsAPM::API.log_exit('grpc_client', exit_tags(@tags))
115
+ super
116
+ end
117
+ end
118
+
119
+ def context_from_incoming
120
+ xtrace ||= @call.trailing_metadata['x-trace'] if @call.trailing_metadata && @call.trailing_metadata['x-trace']
121
+ xtrace ||= @call.metadata['x-trace'] if @call.metadata && @call.metadata['x-trace']
122
+ AppOpticsAPM::Context.fromString(xtrace) if xtrace
123
+ end
124
+
125
+ def exit_tags(tags)
126
+ # we need to translate the status.code, it is not the status.details we want, they are not matching 1:1
127
+ tags['GRPCStatus'] ||= @call.status ? StatusCodes[@call.status.code].to_s : 'UNKNOWN'
128
+ tags.delete('Backtrace')
129
+ tags
130
+ end
131
+ end
132
+
133
+ end
134
+ end
135
+
136
+ if defined?(::GRPC) && AppOpticsAPM::Config[:grpc_client][:enabled]
137
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting GRPC' if AppOpticsAPM::Config[:verbose]
138
+
139
+ # Client side is instrumented in ActiveCall and ClientStub
140
+ ::AppOpticsAPM::Util.send_include(::GRPC::ActiveCall, ::AppOpticsAPM::GRPC::ActiveCall)
141
+
142
+ GRPC_ClientStub_ops = [:request_response, :client_streamer, :server_streamer, :bidi_streamer]
143
+ module GRPC
144
+ class ClientStub
145
+ GRPC_ClientStub_ops.reject { |m| !method_defined?(m) }.each do |m|
146
+ define_method("#{m}_with_appoptics") do |method, req, marshal, unmarshal, deadline: nil,
147
+ return_op: false, parent: nil,
148
+ credentials: nil, metadata: {}, &blk|
149
+
150
+ metadata[:method] = method
151
+ return send("#{m}_without_appoptics", method, req, marshal, unmarshal, deadline: deadline,
152
+ return_op: return_op, parent: parent,
153
+ credentials: credentials, metadata: metadata, &blk)
154
+ end
155
+
156
+ ::AppOpticsAPM::Util.method_alias(::GRPC::ClientStub, m)
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -174,7 +174,7 @@ if AppOpticsAPM.loaded
174
174
  def transaction_name(env)
175
175
  if AppOpticsAPM.transaction_name
176
176
  AppOpticsAPM.transaction_name
177
- elsif env['appoptics_apm.controller'] || env['appoptics_apm.action']
177
+ elsif env['appoptics_apm.controller'] && env['appoptics_apm.action']
178
178
  [env['appoptics_apm.controller'], env['appoptics_apm.action']].join('.')
179
179
  end
180
180
  end
@@ -29,7 +29,7 @@ module AppOpticsAPM
29
29
 
30
30
  if response.code == 0
31
31
  exception = TyphoeusError.new(response.return_message)
32
- exception.set_backtrace(AppOpticsAPM::API.backtrace) if AppOpticsAPM::Config[:typhoeus][:collect_backtraces]
32
+ exception.set_backtrace(AppOpticsAPM::API.backtrace)
33
33
  AppOpticsAPM::API.log_exception(:typhoeus, exception)
34
34
  end
35
35
 
@@ -173,22 +173,16 @@ module AppOpticsAPM
173
173
  return yield unless AppOpticsAPM.loaded
174
174
 
175
175
  if AppOpticsAPM::Context.isValid # not an entry span!
176
- result = trace(span) { yield }
176
+ result = trace(span, opts) { yield }
177
177
  target['X-Trace'] = AppOpticsAPM::Context.toString
178
178
  return result
179
179
  end
180
180
 
181
- # :TransactionName and 'TransactionName' need to be removed from opts
182
- # :TransactionName should only be sent after it is set by send_metrics
183
- transaction_name = opts.delete('TransactionName')
184
- transaction_name = opts.delete(:TransactionName) || transaction_name
185
- # This is the beginning of a transaction, therefore AppOpticsAPM.transaction_name
186
- # needs to be set to nil or whatever is provided in the opts
187
- AppOpticsAPM.transaction_name = transaction_name
188
-
181
+ transaction_name_from_opts(opts)
189
182
 
190
183
  AppOpticsAPM::API.log_start(span, xtrace, opts)
191
- exit_evt = AppOpticsAPM::Context.createEvent
184
+ # AppOpticsAPM::Event.startTrace creates an Event without an Edge
185
+ exit_evt = AppOpticsAPM::Event.startTrace(AppOpticsAPM::Context.get)
192
186
  result = begin
193
187
  AppOpticsAPM::API.send_metrics(span, opts) do
194
188
  target['X-Trace'] = AppOpticsAPM::EventUtil.metadataString(exit_evt)
@@ -308,6 +302,21 @@ module AppOpticsAPM
308
302
  # OBOE_SERVER_RESPONSE_CONNECT_ERROR 5
309
303
  AppopticsAPM::Context.isReady(wait_milliseconds) == 1
310
304
  end
305
+
306
+ private
307
+ # private method
308
+ #
309
+ # This should only be called at the beginning of a transaction,
310
+ # when AppOpticsAPM.transaction_name needs to be set to nil
311
+ # or whatever is provided in the opts
312
+ def transaction_name_from_opts(opts)
313
+ # :TransactionName and 'TransactionName' need to be removed from opts
314
+ # :TransactionName should only be sent after it is set by send_metrics
315
+ transaction_name = opts.delete('TransactionName')
316
+ transaction_name = opts.delete(:TransactionName) || transaction_name
317
+
318
+ AppOpticsAPM.transaction_name = transaction_name
319
+ end
311
320
  end
312
321
 
313
322
  extend Tracing
@@ -183,7 +183,10 @@ module AppOpticsAPM
183
183
  # This legacy version of build_init_report is used for apps without Bundler.
184
184
  #
185
185
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
186
+ #
187
+ # @deprecated Please use {#build_init_report} instead
186
188
  def legacy_build_init_report
189
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] Oboe::API will be deprecated in a future version.'
187
190
  platform_info = {}
188
191
 
189
192
  begin
@@ -7,8 +7,8 @@ module AppOpticsAPM
7
7
  # appoptics_apm.gemspec during gem build process
8
8
  module Version
9
9
  MAJOR = 4
10
- MINOR = 2
11
- PATCH = 7
10
+ MINOR = 3
11
+ PATCH = 0
12
12
 
13
13
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
14
14
  end
@@ -176,6 +176,7 @@ if defined?(AppOpticsAPM::Config)
176
176
  AppOpticsAPM::Config[:em_http_request][:enabled] = false
177
177
  AppOpticsAPM::Config[:excon][:enabled] = true
178
178
  AppOpticsAPM::Config[:faraday][:enabled] = true
179
+ AppOpticsAPM::Config[:grpc_client][:enabled] = true
179
180
  AppOpticsAPM::Config[:grape][:enabled] = true
180
181
  AppOpticsAPM::Config[:httpclient][:enabled] = true
181
182
  AppOpticsAPM::Config[:memcached][:enabled] = true
@@ -236,6 +237,7 @@ if defined?(AppOpticsAPM::Config)
236
237
  AppOpticsAPM::Config[:excon][:collect_backtraces] = true
237
238
  AppOpticsAPM::Config[:faraday][:collect_backtraces] = false
238
239
  AppOpticsAPM::Config[:grape][:collect_backtraces] = true
240
+ AppOpticsAPM::Config[:grpc_client][:collect_backtraces] = false
239
241
  AppOpticsAPM::Config[:httpclient][:collect_backtraces] = true
240
242
  AppOpticsAPM::Config[:memcached][:collect_backtraces] = false
241
243
  AppOpticsAPM::Config[:mongo][:collect_backtraces] = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appoptics_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.7
4
+ version: 4.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maia Engeli
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-09-24 00:00:00.000000000 Z
13
+ date: 2018-10-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -102,6 +102,20 @@ dependencies:
102
102
  - - ">="
103
103
  - !ruby/object:Gem::Version
104
104
  version: 3.0.0
105
+ - !ruby/object:Gem::Dependency
106
+ name: minitest-hooks
107
+ requirement: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: 1.5.0
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: 1.5.0
105
119
  description: The AppOpticsAPM gem provides performance instrumentation for MRI Ruby
106
120
  and related frameworks.
107
121
  email: support@appoptics.com
@@ -178,6 +192,7 @@ files:
178
192
  - lib/appoptics_apm/inst/em-http-request.rb
179
193
  - lib/appoptics_apm/inst/excon.rb
180
194
  - lib/appoptics_apm/inst/faraday.rb
195
+ - lib/appoptics_apm/inst/grpc_client.rb
181
196
  - lib/appoptics_apm/inst/http.rb
182
197
  - lib/appoptics_apm/inst/httpclient.rb
183
198
  - lib/appoptics_apm/inst/memcached.rb