appoptics_apm 4.2.7 → 4.3.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 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