appoptics_apm 4.12.1 → 4.12.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,8 +12,10 @@ It requires an [AppOptics](https://www.appoptics.com/) account to view metrics.
12
12
  [it's free](https://my.appoptics.com/sign_up).
13
13
 
14
14
  [![Gem Version](https://badge.fury.io/rb/appoptics_apm.svg)](https://badge.fury.io/rb/appoptics_apm)
15
- [![Build Status](https://travis-ci.org/appoptics/appoptics-apm-ruby.png?branch=master)](https://travis-ci.org/appoptics/appoptics-apm-ruby)
16
- [![Maintainability](https://api.codeclimate.com/v1/badges/ac7f36241a23a3a82fc5/maintainability)](https://codeclimate.com/github/appoptics/appoptics-apm-ruby/maintainability)
15
+
16
+ [comment]: <> ([![Build Status]&#40;https://travis-ci.org/appoptics/appoptics-apm-ruby.png?branch=master&#41;]&#40;https://travis-ci.org/appoptics/appoptics-apm-ruby&#41;)
17
+
18
+ [comment]: <> ([![Maintainability]&#40;https://api.codeclimate.com/v1/badges/ac7f36241a23a3a82fc5/maintainability&#41;]&#40;https://codeclimate.com/github/appoptics/appoptics-apm-ruby/maintainability&#41;)
17
19
 
18
20
  _Note: The repository is now at https://github.com/appoptics/appoptics-apm-ruby Please update your github remotes with
19
21
  `git remote set-url origin git@github.com:appoptics/appoptics-apm-ruby.git`._
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.version = AppOpticsAPM::Version::STRING
7
7
  s.date = Time.now.strftime('%Y-%m-%d')
8
8
 
9
- s.license = "Librato Open License, Version 1.0, https://bit.ly/2Kmm0mN"
9
+ s.license = "Apache-2.0"
10
10
 
11
11
  s.authors = ["Maia Engeli", "Peter Giacomo Lombardo", "Spiros Eliopoulos"]
12
12
  s.email = %q{support@appoptics.com}
@@ -26,9 +26,10 @@ Automatic tracing and metrics for Ruby applications. Get started at appoptics.co
26
26
  s.extra_rdoc_files = ['LICENSE']
27
27
  s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|gemfiles)/}) }
28
28
  s.files += ['ext/oboe_metal/src/oboe.h',
29
- 'ext/oboe_metal/src/oboe.hpp',
29
+ 'ext/oboe_metal/src/oboe_api.cpp',
30
+ 'ext/oboe_metal/src/oboe_api.hpp',
30
31
  'ext/oboe_metal/src/oboe_debug.h',
31
- 'ext/oboe_metal/src/oboe_wrap.cxx',
32
+ 'ext/oboe_metal/src/oboe_swig_wrap.cc',
32
33
  'ext/oboe_metal/src/bson/bson.h',
33
34
  'ext/oboe_metal/src/bson/platform_hacks.h',
34
35
  'ext/oboe_metal/src/VERSION']
@@ -5,7 +5,7 @@ inspired by: https://dev.to/wataash/how-to-create-and-debug-ruby-gem-with-c-nati
5
5
 
6
6
  ## install ruby with sources
7
7
 
8
- rbenv is your friend ;) 😄 -k means keep sources
8
+ rbenv is your friend ;) -k means keep sources
9
9
 
10
10
  ```
11
11
  rbenv install -k 2.6.3
@@ -66,4 +66,4 @@ Some inspiring examples here:
66
66
 
67
67
  https://jvns.ca/blog/2016/06/12/a-weird-system-call-process-vm-readv/
68
68
 
69
- https://medium.com/@zanker/finding-a-ruby-bug-with-gdb-56d6b321bc86
69
+ https://medium.com/@zanker/finding-a-ruby-bug-with-gdb-56d6b321bc86
@@ -8,6 +8,16 @@ require 'rbconfig'
8
8
  require 'open-uri'
9
9
  require 'no_proxy_fix'
10
10
 
11
+ CONFIG['warnflags'] = CONFIG['warnflags'].gsub(/-Wdeclaration-after-statement/, '')
12
+ .gsub(/-Wimplicit-function-declaration/, '')
13
+ .gsub(/-Wimplicit-int/, '')
14
+ .gsub(/-Wno-tautological-compare/, '')
15
+ .gsub(/-Wno-self-assign/, '')
16
+ .gsub(/-Wno-parentheses-equality/, '')
17
+ .gsub(/-Wno-constant-logical-operand/, '')
18
+ .gsub(/-Wno-cast-function-type/, '')
19
+ init_mkmf(CONFIG)
20
+
11
21
  ext_dir = File.expand_path(File.dirname(__FILE__))
12
22
 
13
23
  # Check if we're running in JRuby
@@ -21,7 +31,7 @@ ao_include = File.join(ext_dir, 'src')
21
31
  # Download the appropriate liboboe from S3(via rake for testing) or files.appoptics.com (production)
22
32
  version = File.read(File.join(ao_include, 'VERSION')).chomp
23
33
  if ENV['APPOPTICS_FROM_S3'].to_s.downcase == 'true'
24
- ao_path = File.join('https://s3-us-west-2.amazonaws.com/rc-files-t2/c-lib/', version)
34
+ ao_path = File.join('https://rc-files-t2.s3-us-west-2.amazonaws.com/c-lib/', version)
25
35
  puts 'Fetching c-lib from S3'
26
36
  else
27
37
  ao_path = File.join('https://files.appoptics.com/c-lib', version)
@@ -29,7 +39,13 @@ end
29
39
 
30
40
  ao_arch = 'x86_64'
31
41
  if File.exist?('/etc/alpine-release')
32
- version = open('/etc/alpine-release').read.chomp
42
+
43
+ if RUBY_VERSION < '2.5.0'
44
+ version = open('/etc/alpine-release').read.chomp
45
+ else
46
+ version = URI.open('/etc/alpine-release').read.chomp
47
+ end
48
+
33
49
  ao_arch =
34
50
  if Gem::Version.new(version) < Gem::Version.new('3.9')
35
51
  'alpine-libressl-x86_64'
@@ -48,13 +64,16 @@ success = false
48
64
  while retries > 0
49
65
  begin
50
66
  # download
51
- # TODO warning: calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open
52
- # ____ URI.open is not supported in 2.4.5, let's use open until we can deprecate 2.4.5
53
- download = open(ao_item, 'rb')
67
+ if RUBY_VERSION < '2.5.0'
68
+ download = open(ao_item, 'rb')
69
+ checksum = open(ao_checksum_item, 'r').read.chomp
70
+ else
71
+ download = URI.open(ao_item, 'rb')
72
+ checksum = URI.open(ao_checksum_item, 'r').read.chomp
73
+ end
54
74
  IO.copy_stream(download, clib)
55
-
56
- checksum = open(ao_checksum_item, 'r').read.chomp
57
75
  clib_checksum = Digest::SHA256.file(clib).hexdigest
76
+ download.close
58
77
 
59
78
  # verify_checksum
60
79
  if clib_checksum != checksum
@@ -77,7 +96,7 @@ while retries > 0
77
96
  $stderr.puts 'Download of the c-extension for the appoptics_apm gem failed.'
78
97
  $stderr.puts 'appoptics_apm will not instrument the code. No tracing will occur.'
79
98
  $stderr.puts 'Contact support@appoptics.com if the problem persists.'
80
- $stderr.puts "error:\n#{e.message}"
99
+ $stderr.puts "error: #{ao_item}\n#{e.message}"
81
100
  $stderr.puts '==================================================================='
82
101
  create_makefile('oboe_noop', 'noop')
83
102
  end
@@ -107,11 +126,21 @@ if success
107
126
  $libs = append_library($libs, 'stdc++')
108
127
 
109
128
  $CFLAGS << " #{ENV['CFLAGS']}"
110
- $CPPFLAGS << " #{ENV['CPPFLAGS']}"
129
+ # $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11"
130
+ # TODO for debugging: -pg -gdwarf-2, remove for production
131
+ # $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11 -pg -gdwarf-2 -I$$ORIGIN/../ext/oboe_metal/include -I$$ORIGIN/../ext/oboe_metal/src"
132
+ $CPPFLAGS << " #{ENV['CPPFLAGS']} -std=c++11 -I$$ORIGIN/../ext/oboe_metal/include"
111
133
  $LIBS << " #{ENV['LIBS']}"
112
- $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib'"
134
+ $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib' -pg -lrt"
135
+ # $LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib'"
136
+ $CXXFLAGS += " -std=c++11 "
137
+
138
+ # ____ include debug info, comment out when not debugging
139
+ # ____ -pg -> profiling info for gprof
140
+ # CONFIG["debugflags"] = "-ggdb3 -pg"
141
+ # CONFIG["optflags"] = "-O0"
113
142
 
114
- create_makefile('oboe_metal', 'src')
143
+ create_makefile('libappoptics_apm', 'src')
115
144
 
116
145
  else
117
146
  $stderr.puts '== ERROR ========================================================='
@@ -1 +1 @@
1
- 10.0.0
1
+ 10.1.0
@@ -0,0 +1,20 @@
1
+ #include <iostream>
2
+
3
+ #ifdef __cplusplus
4
+ extern "C" {
5
+ #endif
6
+
7
+ void Init_oboe_metal(void);
8
+
9
+ //void Init_profiling(void);
10
+
11
+ void Init_libappoptics_apm() {
12
+ Init_oboe_metal();
13
+ // std::cout << "*** oboe_metal initialized ***" << std::endl;
14
+ // Init_profiling();
15
+ // std::cout << "*** profiling intitialized ***" << std::endl;
16
+ }
17
+
18
+ #ifdef __cplusplus
19
+ }
20
+ #endif
data/lib/appoptics_apm.rb CHANGED
@@ -20,7 +20,7 @@ begin
20
20
  require '/usr/local/tracelytics/tracelyticsagent.jar'
21
21
  require 'joboe_metal'
22
22
  elsif RUBY_PLATFORM =~ /linux/
23
- require_relative './oboe_metal.so'
23
+ require_relative './libappoptics_apm.so'
24
24
  require 'appoptics_apm/oboe_init_options'
25
25
  require 'oboe_metal.rb' # sets AppOpticsAPM.loaded = true if successful
26
26
  else
@@ -22,9 +22,12 @@ module AppOpticsAPM
22
22
  start = Time.now
23
23
  yield
24
24
  ensure
25
+ # TODO send_metrics is currently used in grpc, sdk
26
+ # ____ the error (0,1) would have to be returned from yield
27
+ error = 0
25
28
  duration = (1000 * 1000 * (Time.now - start)).to_i
26
29
  transaction_name = determine_transaction_name(span, kvs)
27
- kvs[:TransactionName] = AppOpticsAPM::Span.createSpan(transaction_name, nil, duration)
30
+ kvs[:TransactionName] = AppOpticsAPM::Span.createSpan(transaction_name, nil, duration, error)
28
31
  AppOpticsAPM.transaction_name = nil
29
32
  end
30
33
 
@@ -6,35 +6,78 @@ if defined?(ActionView::Base) && AppOpticsAPM::Config[:action_view][:enabled]
6
6
  if Rails::VERSION::MAJOR >= 4
7
7
 
8
8
  AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting actionview' if AppOpticsAPM::Config[:verbose]
9
+ if ActionView.version >= Gem::Version.new('6.1.0') # the methods changed in this version
9
10
 
10
- ActionView::PartialRenderer.class_eval do
11
- alias :render_partial_without_appoptics :render_partial
12
- def render_partial(*args)
13
- entry_kvs = {}
14
- begin
15
- entry_kvs[:Partial] = AppOpticsAPM::Util.prettify(@options[:partial]) if @options.is_a?(Hash)
16
- rescue => e
17
- AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
11
+ ActionView::PartialRenderer.class_eval do
12
+ alias :render_partial_template_without_appoptics :render_partial_template
13
+
14
+ def render_partial_template(*args)
15
+ _, _, template, _, _ = args
16
+ entry_kvs = {}
17
+ begin
18
+ entry_kvs[:Partial] = template.virtual_path
19
+ rescue => e
20
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
21
+ end
22
+ AppOpticsAPM::SDK.trace(:partial, entry_kvs) do
23
+ entry_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_view][:collect_backtraces]
24
+ render_partial_template_without_appoptics(*args)
25
+ end
18
26
  end
27
+ end
28
+
29
+ ActionView::CollectionRenderer.class_eval do
30
+ alias :render_collection_without_appoptics :render_collection
19
31
 
20
- AppOpticsAPM::SDK.trace('partial', entry_kvs) do
21
- entry_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_view][:collect_backtraces]
22
- render_partial_without_appoptics(*args)
32
+ def render_collection(*args)
33
+ _, _, _, template, _, _ = args
34
+ entry_kvs = {}
35
+ begin
36
+ entry_kvs[:Partial] = template.virtual_path
37
+ rescue => e
38
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
39
+ end
40
+ AppOpticsAPM::SDK.trace(:collection, entry_kvs) do
41
+ entry_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_view][:collect_backtraces]
42
+ render_collection_without_appoptics(*args)
43
+ end
23
44
  end
24
45
  end
25
46
 
26
- alias :render_collection_without_appoptics :render_collection
27
- def render_collection(*args)
28
- entry_kvs = {}
29
- begin
30
- entry_kvs[:Partial] = AppOpticsAPM::Util.prettify(@path)
31
- rescue => e
32
- AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
47
+ else # Rails < 6.1.0
48
+
49
+ ActionView::PartialRenderer.class_eval do
50
+ alias :render_partial_without_appoptics :render_partial
51
+ def render_partial(*args)
52
+ template = @template || args[1]
53
+ entry_kvs = {}
54
+ begin
55
+ entry_kvs[:Partial] = template.virtual_path
56
+ # entry_kvs[:Partial] = AppOpticsAPM::Util.prettify(@options[:partial]) if @options.is_a?(Hash)
57
+ rescue => e
58
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
59
+ end
60
+
61
+ AppOpticsAPM::SDK.trace('partial', entry_kvs) do
62
+ entry_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_view][:collect_backtraces]
63
+ render_partial_without_appoptics(*args)
64
+ end
33
65
  end
34
66
 
35
- AppOpticsAPM::SDK.trace('collection', entry_kvs) do
36
- entry_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_view][:collect_backtraces]
37
- render_collection_without_appoptics(*args)
67
+ alias :render_collection_without_appoptics :render_collection
68
+ def render_collection(*args)
69
+ template = @template || args[1]
70
+ entry_kvs = {}
71
+ begin
72
+ entry_kvs[:Partial] = template.virtual_path
73
+ rescue => e
74
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}" if AppOpticsAPM::Config[:verbose]
75
+ end
76
+
77
+ AppOpticsAPM::SDK.trace('collection', entry_kvs) do
78
+ entry_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:action_view][:collect_backtraces]
79
+ render_collection_without_appoptics(*args)
80
+ end
38
81
  end
39
82
  end
40
83
 
@@ -4,70 +4,78 @@
4
4
  require 'net/http'
5
5
 
6
6
  if AppOpticsAPM::Config[:nethttp][:enabled]
7
-
8
- Net::HTTP.class_eval do
9
- def request_with_appoptics(*args, &block)
10
- # Avoid cross host tracing for blacklisted domains
11
- blacklisted = AppOpticsAPM::API.blacklisted?(addr_port)
12
-
13
- # If we're not tracing, just do a fast return. Since
14
- # net/http.request calls itself, only trace
15
- # once the http session has been started.
16
- if !AppOpticsAPM.tracing? || !started?
17
- unless blacklisted
18
- xtrace = AppOpticsAPM::Context.toString
19
- args[0]['X-Trace'] = xtrace if AppOpticsAPM::XTrace.valid?(xtrace)
20
- end
21
- return request_without_appoptics(*args, &block)
22
- end
23
-
24
- opts = {}
25
- AppOpticsAPM::API.trace(:'net-http', opts) do
26
- context = AppOpticsAPM::Context.toString
27
- # task_id = AppOpticsAPM::XTrace.task_id(context)
28
-
29
- # Collect KVs to report in the info event
30
- if args.respond_to?(:first) && args.first
31
- req = args.first
32
-
33
- opts[:Spec] = 'rsc'
34
- opts[:IsService] = 1
35
- opts[:RemoteURL] = "#{use_ssl? ? 'https' : 'http'}://#{addr_port}"
36
- opts[:RemoteURL] << (AppOpticsAPM::Config[:nethttp][:log_args] ? req.path : req.path.split('?').first)
37
- opts[:HTTPMethod] = req.method
38
- opts[:Blacklisted] = true if blacklisted
39
- opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:nethttp][:collect_backtraces]
40
-
41
- req['X-Trace'] = context unless blacklisted
42
- end
43
-
44
- begin
45
- # The actual net::http call
46
- resp = request_without_appoptics(*args, &block)
47
-
48
- # Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
49
- unless blacklisted
50
- xtrace = resp.get_fields('X-Trace')
51
- xtrace = xtrace[0] if xtrace && xtrace.is_a?(Array)
52
-
53
- AppOpticsAPM::XTrace.continue_service_context(context, xtrace)
7
+ module AppOpticsAPM
8
+ module Inst
9
+ module NetHttp
10
+ # Net::HTTP.class_eval do
11
+ # def request_with_appoptics(*args, &block)
12
+ def request(*args, &block)
13
+ # Avoid cross host tracing for blacklisted domains
14
+ blacklisted = AppOpticsAPM::API.blacklisted?(addr_port)
15
+
16
+ # If we're not tracing, just do a fast return. Since
17
+ # net/http.request calls itself, only trace
18
+ # once the http session has been started.
19
+ if !AppOpticsAPM.tracing? || !started?
20
+ if blacklisted # if the other site is blacklisted, we don't want to leak its X-trace
21
+ resp = super
22
+ resp.delete('X-Trace') # if resp['X-Trace']
23
+ return resp
24
+ else
25
+ xtrace = AppOpticsAPM::Context.toString
26
+ args[0]['X-Trace'] = xtrace if AppOpticsAPM::XTrace.valid?(xtrace)
27
+ return super
28
+ end
54
29
  end
55
30
 
56
- opts[:HTTPStatus] = resp.code
57
-
58
- # If we get a redirect, report the location header
59
- if ((300..308).to_a.include? resp.code.to_i) && resp.header["Location"]
60
- opts[:Location] = resp.header["Location"]
31
+ opts = {}
32
+ AppOpticsAPM::API.trace(:'net-http', opts) do
33
+ context = AppOpticsAPM::Context.toString
34
+
35
+ # Collect KVs to report in the exit event
36
+ if args.respond_to?(:first) && args.first
37
+ req = args.first
38
+
39
+ opts[:Spec] = 'rsc'
40
+ opts[:IsService] = 1
41
+ opts[:RemoteURL] = "#{use_ssl? ? 'https' : 'http'}://#{addr_port}"
42
+ opts[:RemoteURL] << (AppOpticsAPM::Config[:nethttp][:log_args] ? req.path : req.path.split('?').first)
43
+ opts[:HTTPMethod] = req.method
44
+ opts[:Blacklisted] = true if blacklisted
45
+ opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:nethttp][:collect_backtraces]
46
+
47
+ req['X-Trace'] = context unless blacklisted
48
+ end
49
+
50
+ begin
51
+ # The actual net::http call
52
+ resp = super
53
+ # Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
54
+ xtrace = resp.get_fields('X-Trace')
55
+ if blacklisted
56
+ # we don't want the x-trace if it is from a blacklisted address
57
+ resp.delete('X-Trace') # if xtrace
58
+ else
59
+ xtrace = xtrace[0] if xtrace && xtrace.is_a?(Array)
60
+ AppOpticsAPM::XTrace.continue_service_context(context, xtrace)
61
+ end
62
+
63
+ opts[:HTTPStatus] = resp.code
64
+
65
+ # If we get a redirect, report the location header
66
+ if ((300..308).to_a.include? resp.code.to_i) && resp.header["Location"]
67
+ opts[:Location] = resp.header["Location"]
68
+ end
69
+
70
+ next resp
71
+ end
61
72
  end
62
-
63
- next resp
64
73
  end
74
+
65
75
  end
66
76
  end
67
-
68
- alias request_without_appoptics request
69
- alias request request_with_appoptics
70
-
71
- AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting net/http' if AppOpticsAPM::Config[:verbose]
72
77
  end
78
+
79
+ Net::HTTP.prepend(AppOpticsAPM::Inst::NetHttp)
80
+ AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting net/http' if AppOpticsAPM::Config[:verbose]
73
81
  end
@@ -8,7 +8,7 @@ module AppOpticsAPM
8
8
  class OboeInitOptions
9
9
  include Singleton
10
10
 
11
- attr_reader :reporter, :host, :service_name, :ec2_md_timeout # exposing these mainly for testing
11
+ attr_reader :reporter, :host, :service_name, :ec2_md_timeout, :grpc_proxy # exposing these mainly for testing
12
12
 
13
13
  # TODO decide if these globals are useful when testing
14
14
  # OBOE_HOSTNAME_ALIAS = 0
@@ -71,6 +71,7 @@ module AppOpticsAPM
71
71
  @file_single = (ENV['APPOPTICS_REPORTER_FILE_SINGLE'].to_s.downcase == 'true') ? 1 : 0
72
72
  # timeout for ec2 metadata
73
73
  @ec2_md_timeout = read_and_validate_ec2_md_timeout
74
+ @grpc_proxy = read_and_validate_proxy
74
75
  end
75
76
 
76
77
  def re_init # for testing with changed ENV vars
@@ -97,7 +98,8 @@ module AppOpticsAPM
97
98
  @token_bucket_capacity,
98
99
  @token_bucket_rate,
99
100
  @file_single,
100
- @ec2_md_timeout
101
+ @ec2_md_timeout,
102
+ @grpc_proxy
101
103
  ]
102
104
  end
103
105
 
@@ -183,11 +185,23 @@ module AppOpticsAPM
183
185
  end
184
186
 
185
187
  def read_and_validate_ec2_md_timeout
186
- timeout = (ENV['APPOPTICS_EC2_METADATA_TIMEOUT'] || AppOpticsAPM::Config[:ec2_metadata_timeout])
188
+ timeout = ENV['APPOPTICS_EC2_METADATA_TIMEOUT'] || AppOpticsAPM::Config[:ec2_metadata_timeout]
187
189
  return 1000 unless timeout.is_a?(Integer) || timeout =~ /^\d+$/
188
190
  timeout = timeout.to_i
189
191
  return timeout.between?(0, 3000) ? timeout : 1000
190
192
  end
193
+
194
+ def read_and_validate_proxy
195
+ proxy = ENV['APPOPTICS_PROXY'] || AppOpticsAPM::Config[:http_proxy] || ''
196
+ return proxy if proxy == ''
197
+
198
+ unless proxy =~ /http:\/\/.*:\d+$/
199
+ AppOpticsAPM.logger.error "[appoptics_apm/oboe_options] APPOPTICS_PROXY/http_proxy doesn't start with 'http://', #{proxy}"
200
+ return '' # try without proxy, it may work, shouldn't crash but may not report
201
+ end
202
+
203
+ proxy
204
+ end
191
205
  end
192
206
  end
193
207