appoptics_apm 4.8.4 → 4.9.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
- SHA1:
3
- metadata.gz: 37478c40a16c8636f4589a15e63db8d1b2eb0eae
4
- data.tar.gz: 2f2ac3b316e00963c42593680e638ecfc1792e3b
2
+ SHA256:
3
+ metadata.gz: c4b87b6581745b8485f7ddb38f17cb6eab85244a950e7d67cecfe0e97cdbd0bc
4
+ data.tar.gz: dce765afa7ceb92b523c448cd9b1b10efc1b6c5bb0f2f92842dc6af3c1934b27
5
5
  SHA512:
6
- metadata.gz: f695fc74e9f23d799709c32faab13b8c8c56e2f7da34b6968a5f085daf964927d3c98ffcadc49be6ab181fb66a872a4ec97d121468f01ed205c449e0d0873abc
7
- data.tar.gz: 730addb2cda57f6555d4965656cfeb1e753e32e7886e13cc1714c8b97b094664c4d0702a5494dc49ea7c266de6c101b25c4927a82ed652822890a581e45550b0
6
+ metadata.gz: d9b446519730872b09136e9b80e546a68dce40abf52fbb0e5ac139244c6ed3c7fa8ef45eb855714d8e11924886d0b972aa04332cec6342339c65772f5b7aec0f
7
+ data.tar.gz: 80df368e2ed2c868348ba5e7e9b24dfa2498d6f0cb703d568fbf8310879d06fee5ac59187a70747f04c040d4d54df2b8925faa856dc5a01b036375f21edacfbe
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
1
  oboe*.gem
2
- Gemfile.lock
2
+ *.lock
3
3
  gemfiles/*.lock
4
4
  .ruby-version
5
5
  *~
@@ -27,3 +27,7 @@ coverage
27
27
  doc
28
28
  .*byebug*
29
29
  gemfiles/vendor*
30
+ scrap.rb
31
+ scarp_gemfile
32
+ .irbrc
33
+ *.code-workspace
@@ -98,9 +98,9 @@ matrix:
98
98
  # - sudo service cassandra start
99
99
 
100
100
  install:
101
- - curl -LO http://kent.dl.sourceforge.net/project/swig/swig/swig-3.0.8/swig-3.0.8.tar.gz
102
- - tar xzf swig-3.0.8.tar.gz
103
- - pushd swig-3.0.8
101
+ - curl -LO http://kent.dl.sourceforge.net/project/swig/swig/swig-3.0.12/swig-3.0.12.tar.gz
102
+ - tar xzf swig-3.0.12.tar.gz
103
+ - pushd swig-3.0.12
104
104
  - ./configure && make && sudo make install
105
105
  - popd
106
106
 
@@ -111,8 +111,8 @@ before_script:
111
111
  - export APPOPTICS_REPORTER_FILE_SINGLE=false
112
112
  - export APPOPTICS_TOKEN_BUCKET_CAPACITY=1000
113
113
  - export APPOPTICS_TOKEN_BUCKET_RATE=1000
114
- - export OBOE_VERSION=5.1.1
115
- - bundle --jobs=3 --retry=3
114
+
115
+ - bundle update --jobs=3 --retry=3
116
116
  - bundle exec rake clean fetch compile
117
117
  - psql -c 'create database travis_ci_test;' -U postgres
118
118
  - mysql -e 'create database travis_ci_test;'
data/CONFIG.md CHANGED
@@ -17,7 +17,7 @@ Name | Description | Default
17
17
 
18
18
  Name | Description | Default
19
19
  ---- | ----------- | -------
20
- `APPOPTICS_GEM_TEST` | puts the gem in test mode. Traces are written to /tmp/trace_output.bson. | `false`
20
+ `APPOPTICS_GEM_TEST` | puts the gem in test mode to avoid restarting certain background services used in testing. `false`
21
21
  `DBTYPE` | For tests on Ruby on Rails, specifies the database type to test against. `postgres`, `mysql` and `mysql2` are valid options. | `postgres`
22
22
  `APPOPTICS_CASSANDRA_SERVER` | specifies the Cassandra server to test against. | `127.0.0.1:9160`
23
23
  `APPOPTICS_MONGO_SERVER` | specifies the Mongo server to test against. | `127.0.0.1:27017`
data/Rakefile CHANGED
@@ -59,76 +59,77 @@ Rake::TestTask.new do |t|
59
59
  end
60
60
 
61
61
  if defined?(JRUBY_VERSION)
62
- t.ruby_opts << ['-J-javaagent:/usr/local/tracelytics/tracelyticsagent.jar']
62
+ t.ruby_opts << ['-J-javaagent:/usr/local/tracelytics/tracelyticsagent.jar']
63
+ end
63
64
  end
64
- end
65
-
66
- desc "Run all test suites defined by travis"
67
- task "docker_tests" do
68
- Dir.chdir('test/run_tests')
69
- exec('docker-compose run --rm ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh test --remove-orphans')
70
- end
71
65
 
72
- desc "Start docker container for testing and debugging"
73
- task "docker" do
74
- Dir.chdir('test/run_tests')
75
- exec('docker-compose run --rm ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh bash --remove-orphans')
76
- end
77
66
 
78
- desc "Stop all containers that were started for testing and debugging"
79
- task "docker_down" do
80
- Dir.chdir('test/run_tests')
81
- exec('docker-compose down')
82
- end
67
+ desc "Run all test suites defined by travis"
68
+ task "docker_tests" do
69
+ Dir.chdir('test/run_tests')
70
+ exec('docker-compose run ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh test --remove-orphans')
71
+ end
83
72
 
84
- desc "Fetch extension dependency files"
85
- task :fetch_ext_deps do
86
- swig_version = %x{swig -version} rescue ''
87
- swig_version = swig_version.scan(/swig version [34]/i)
88
- if swig_version.empty?
89
- $stderr.puts '== ERROR ================================================================='
90
- $stderr.puts "Could not find required swig version >= 3.0.8, found #{swig_version.inspect}"
91
- $stderr.puts 'Please install swig ">= 3.0.8" and try again.'
92
- $stderr.puts '=========================================================================='
93
- raise
73
+ desc "Start docker container for testing and debugging"
74
+ task "docker" do
75
+ Dir.chdir('test/run_tests')
76
+ exec('docker-compose run ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh bash --remove-orphans')
94
77
  end
95
78
 
96
- # The c-lib version is different from the gem version
97
- oboe_version = ENV['OBOE_VERSION'] || 'latest'
98
- oboe_s3_dir = "https://s3-us-west-2.amazonaws.com/rc-files-t2/c-lib/#{oboe_version}"
99
- ext_src_dir = File.expand_path('ext/oboe_metal/src')
100
-
101
- # VERSION is used by extconf.rb to download the correct liboboe when installing the gem
102
- remote_file = File.join(oboe_s3_dir, 'VERSION')
103
- local_file = File.join(ext_src_dir, 'VERSION')
104
- puts "fetching #{remote_file} to #{local_file}"
105
- open(remote_file, 'rb') do |rf|
106
- content = rf.read
107
- File.open(local_file, 'wb') { |f| f.puts content }
108
- puts "!!!!!!! C-Lib VERSION: #{content.strip} !!!!!!!!"
79
+ desc "Stop all containers that were started for testing and debugging"
80
+ task "docker_down" do
81
+ Dir.chdir('test/run_tests')
82
+ exec('docker-compose down')
109
83
  end
110
84
 
111
- # oboe and bson header files
112
- FileUtils.mkdir_p(File.join(ext_src_dir, 'bson'))
113
- %w(oboe.h oboe.hpp oboe_debug.h oboe.i bson/bson.h bson/platform_hacks.h).each do |filename|
114
- # %w(oboe.h oboe_debug.h bson/bson.h bson/platform_hacks.h).each do |filename|
115
- remote_file = File.join(oboe_s3_dir, 'include', filename)
116
- local_file = File.join(ext_src_dir, filename)
85
+ desc "Fetch extension dependency files"
86
+ task :fetch_ext_deps do
87
+ swig_version = %x{swig -version} rescue ''
88
+ swig_version = swig_version.scan(/swig version [34].0.\d*/i)
89
+ if swig_version.empty?
90
+ $stderr.puts '== ERROR ================================================================='
91
+ $stderr.puts "Could not find required swig version >3.0.8, found #{swig_version.inspect}"
92
+ $stderr.puts 'Please install swig "~ 3.0.12" and try again.'
93
+ $stderr.puts '=========================================================================='
94
+ raise
95
+ end
117
96
 
97
+ # The c-lib version is different from the gem version
98
+ oboe_version = ENV['OBOE_VERSION'] || 'latest'
99
+ oboe_s3_dir = "https://s3-us-west-2.amazonaws.com/rc-files-t2/c-lib/#{oboe_version}"
100
+ ext_src_dir = File.expand_path('ext/oboe_metal/src')
101
+
102
+ # VERSION is used by extconf.rb to download the correct liboboe when installing the gem
103
+ remote_file = File.join(oboe_s3_dir, 'VERSION')
104
+ local_file = File.join(ext_src_dir, 'VERSION')
118
105
  puts "fetching #{remote_file} to #{local_file}"
119
106
  open(remote_file, 'rb') do |rf|
120
107
  content = rf.read
121
108
  File.open(local_file, 'wb') { |f| f.puts content }
109
+ puts "!!!!!!! C-Lib VERSION: #{content.strip} !!!!!!!!"
122
110
  end
123
- end
124
111
 
125
- FileUtils.cd(ext_src_dir) do
126
- system('swig -c++ -ruby -module oboe_metal oboe.i')
127
- FileUtils.rm('oboe.i')
112
+ # oboe and bson header files
113
+ FileUtils.mkdir_p(File.join(ext_src_dir, 'bson'))
114
+ %w(oboe.h oboe.hpp oboe_debug.h oboe.i bson/bson.h bson/platform_hacks.h).each do |filename|
115
+ # %w(oboe.h oboe_debug.h bson/bson.h bson/platform_hacks.h).each do |filename|
116
+ remote_file = File.join(oboe_s3_dir, 'include', filename)
117
+ local_file = File.join(ext_src_dir, filename)
118
+
119
+ puts "fetching #{remote_file} to #{local_file}"
120
+ open(remote_file, 'rb') do |rf|
121
+ content = rf.read
122
+ File.open(local_file, 'wb') { |f| f.puts content }
123
+ end
124
+ end
125
+
126
+ FileUtils.cd(ext_src_dir) do
127
+ system('swig -c++ -ruby -module oboe_metal oboe.i')
128
+ FileUtils.rm('oboe.i')
129
+ end
128
130
  end
129
- end
130
131
 
131
- task :fetch => :fetch_ext_deps
132
+ task :fetch => :fetch_ext_deps
132
133
 
133
134
  desc "Build the gem's c extension"
134
135
  task :compile do
@@ -141,7 +142,7 @@ task :compile do
141
142
  so_file = File.expand_path('ext/oboe_metal/oboe_metal.so')
142
143
 
143
144
  Dir.chdir ext_dir
144
- ENV['APPOPTICS_FROM_S3'] = 'true'
145
+ # ENV['APPOPTICS_FROM_S3'] = 'true'
145
146
  cmd = [Gem.ruby, 'extconf.rb']
146
147
  sh cmd.join(' ')
147
148
  sh '/usr/bin/env make'
@@ -179,6 +180,7 @@ task :clean do
179
180
  Dir.chdir ext_dir
180
181
  sh '/usr/bin/env make clean' if File.exist? 'Makefile'
181
182
 
183
+ FileUtils.rm_f "src/oboe_wrap.cxx"
182
184
  Dir.chdir pwd
183
185
  else
184
186
  puts '== Nothing to do under JRuby.'
@@ -54,6 +54,6 @@ Automatic tracing and metrics for Ruby applications. Get started at appoptics.co
54
54
  s.add_development_dependency('benchmark-ips', '>= 2.7.2')
55
55
  end
56
56
 
57
- s.required_ruby_version = '>= 2.0.0'
57
+ s.required_ruby_version = '>= 2.4.0'
58
58
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
59
59
  end
@@ -1 +1 @@
1
- 5.1.1
1
+ 6.0.0
@@ -49,6 +49,7 @@ begin
49
49
  if AppOpticsAPM.loaded
50
50
  require 'appoptics_apm/instrumentation'
51
51
  require 'appoptics_apm/support/transaction_metrics'
52
+ require 'appoptics_apm/support/x_trace_options'
52
53
 
53
54
  # Frameworks
54
55
  require 'appoptics_apm/frameworks/rails'
@@ -16,13 +16,16 @@ module AppOpticsAPM
16
16
  @@instrumentation = [:action_controller, :action_controller_api, :action_view,
17
17
  :active_record, :bunnyclient, :bunnyconsumer, :cassandra, :curb,
18
18
  :dalli, :delayed_jobclient, :delayed_jobworker,
19
- :em_http_request, :excon, :faraday, :grpc_client, :grpc_server, :grape,
19
+ # :em_http_request,
20
+ :excon, :faraday, :grpc_client, :grpc_server, :grape,
20
21
  :httpclient, :nethttp, :memcached, :mongo, :moped, :padrino, :rack, :redis,
21
22
  :resqueclient, :resqueworker, :rest_client,
22
23
  :sequel, :sidekiqclient, :sidekiqworker, :sinatra, :typhoeus]
23
24
 
24
25
  # Subgrouping of instrumentation
25
- @@http_clients = [:curb, :excon, :em_http_request, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
26
+ @@http_clients = [:curb, :excon,
27
+ # :em_http_request,
28
+ :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
26
29
 
27
30
  ##
28
31
  # load_config_file
@@ -240,11 +243,15 @@ module AppOpticsAPM
240
243
  end
241
244
 
242
245
  elsif key == :tracing_mode
243
- # CAN'T DO THIS ANYMORE, ALL TRACING COMMUNICATION TO OBOE
246
+ # CAN'T DO `set_tracing_mode` ANYMORE, ALL TRACING COMMUNICATION TO OBOE
244
247
  # IS NOW HANDLED BY TransactionSettings
245
248
  # AppOpticsAPM.set_tracing_mode(value.to_sym) if AppOpticsAPM.loaded
246
249
 
247
- # Make sure that the mode is stored as a symbol
250
+ # Make sure that the mode is stored as a symbol
251
+ @@config[key.to_sym] = value.to_sym
252
+
253
+ elsif key == :trigger_tracing_mode
254
+ # Make sure that the mode is stored as a symbol
248
255
  @@config[key.to_sym] = value.to_sym
249
256
  end
250
257
  end
@@ -27,30 +27,30 @@ if AppOpticsAPM.loaded
27
27
  end
28
28
 
29
29
  def call(env)
30
- incoming = AppOpticsAPM::Context.isValid
31
30
 
32
31
  # In the case of nested Ruby apps such as Grape inside of Rails
33
32
  # or Grape inside of Grape, each app has it's own instance
34
33
  # of rack middleware. We want to avoid tracing rack more than once
35
34
  return @app.call(env) if AppOpticsAPM.tracing? && AppOpticsAPM.layer == :rack
36
35
 
36
+ incoming = AppOpticsAPM::Context.isValid
37
37
  AppOpticsAPM.transaction_name = nil
38
38
 
39
39
  url = env['PATH_INFO']
40
+ options = AppOpticsAPM::XTraceOptions.new(env['HTTP_X_TRACE_OPTIONS'], env['HTTP_X_TRACE_OPTIONS_SIGNATURE'])
40
41
  xtrace = AppOpticsAPM::XTrace.valid?(env['HTTP_X_TRACE']) ? (env['HTTP_X_TRACE']) : nil
41
-
42
- settings = AppOpticsAPM::TransactionSettings.new(url, xtrace)
43
-
44
- # AppOpticsAPM.logger.warn "%%% FILTER: #{settings} %%%"
42
+ settings = AppOpticsAPM::TransactionSettings.new(url, xtrace, options)
45
43
 
46
44
  response =
47
45
  propagate_xtrace(env, settings, xtrace) do
48
- sample(env, settings) do
46
+ sample(env, settings, options) do
49
47
  AppOpticsAPM::TransactionMetrics.metrics(env, settings) do
50
48
  @app.call(env)
51
49
  end
52
50
  end
53
51
  end || [500, {}, nil]
52
+ options.add_response_header(response[1], settings)
53
+
54
54
  AppOpticsAPM::Context.clear unless incoming
55
55
  response
56
56
  rescue
@@ -66,7 +66,7 @@ if AppOpticsAPM.loaded
66
66
 
67
67
  private
68
68
 
69
- def collect(env, settings)
69
+ def collect(env)
70
70
  req = ::Rack::Request.new(env)
71
71
  report_kvs = {}
72
72
 
@@ -84,8 +84,6 @@ if AppOpticsAPM.loaded
84
84
 
85
85
  report_kvs[:URL] = AppOpticsAPM::Config[:rack][:log_args] ? ::CGI.unescape(req.fullpath) : ::CGI.unescape(req.path)
86
86
  report_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:rack][:collect_backtraces]
87
- report_kvs[:SampleRate] = settings.rate
88
- report_kvs[:SampleSource] = settings.source
89
87
 
90
88
  # Report any request queue'ing headers. Report as 'Request-Start' or the summed Queue-Time
91
89
  report_kvs[:'Request-Start'] = env['HTTP_X_REQUEST_START'] if env.key?('HTTP_X_REQUEST_START')
@@ -126,11 +124,13 @@ if AppOpticsAPM.loaded
126
124
  [status, headers, response]
127
125
  end
128
126
 
129
- def sample(env, settings)
127
+ def sample(env, settings, options)
130
128
  xtrace = env['HTTP_X_TRACE']
131
129
  if settings.do_sample
132
130
  begin
133
- report_kvs = collect(env, settings)
131
+ report_kvs = collect(env)
132
+ settings.add_kvs(report_kvs)
133
+ options&.add_kvs(report_kvs, settings)
134
134
 
135
135
  AppOpticsAPM::API.log_start(:rack, xtrace, report_kvs, settings)
136
136
 
@@ -8,7 +8,7 @@ module AppOpticsAPM
8
8
  class OboeInitOptions
9
9
  include Singleton
10
10
 
11
- attr_reader :reporter, :host, :service_name # exposing these mainly for testing
11
+ attr_reader :reporter, :host, :service_name, :ec2_md_timeout # exposing these mainly for testing
12
12
 
13
13
  # TODO decide if these globals are useful when testing
14
14
  # OBOE_HOSTNAME_ALIAS = 0
@@ -69,6 +69,8 @@ module AppOpticsAPM
69
69
  @token_bucket_rate = (ENV['APPOPTICS_TOKEN_BUCKET_RATE'] || -1).to_i
70
70
  # use single files in file reporter for each event
71
71
  @file_single = (ENV['APPOPTICS_REPORTER_FILE_SINGLE'].to_s.downcase == 'true') ? 1 : 0
72
+ # timeout for ec2 metadata
73
+ @ec2_md_timeout = read_and_validate_ec2_md_timeout
72
74
  end
73
75
 
74
76
  def re_init # for testing with changed ENV vars
@@ -94,7 +96,8 @@ module AppOpticsAPM
94
96
  @histogram_precision,
95
97
  @token_bucket_capacity,
96
98
  @token_bucket_rate,
97
- @file_single
99
+ @file_single,
100
+ @ec2_md_timeout
98
101
  ]
99
102
  end
100
103
 
@@ -150,7 +153,7 @@ module AppOpticsAPM
150
153
  end
151
154
 
152
155
  def validate_token(token)
153
- if (token !~ /^[0-9a-fA-F]{64}|[0-9a-zA-Z_\-]{71}$/) && ENV['APPOPTICS_COLLECTOR'] != "sslcollector:12222"
156
+ if (token !~ /^[0-9a-fA-F]{64}|[0-9a-zA-Z_-]{71}$/) && ENV['APPOPTICS_COLLECTOR'] != "sslcollector:12222"
154
157
  masked = "#{token[0..3]}...#{token[-4..-1]}"
155
158
  AppOpticsAPM.logger.error "[appoptics_apm/oboe_options] APPOPTICS_SERVICE_KEY problem. API Token in wrong format. Masked token: #{masked}"
156
159
  return false
@@ -178,6 +181,13 @@ module AppOpticsAPM
178
181
  @service_name = service_name # instance variable used in testing
179
182
  true
180
183
  end
184
+
185
+ def read_and_validate_ec2_md_timeout
186
+ timeout = (ENV['APPOPTICS_EC2_METADATA_TIMEOUT'] || AppOpticsAPM::Config[:ec2_metadata_timeout])
187
+ return 1000 unless timeout.is_a?(Integer) || timeout =~ /^\d+$/
188
+ timeout = timeout.to_i
189
+ return timeout.between?(0, 3000) ? timeout : 1000
190
+ end
181
191
  end
182
192
  end
183
193
 
@@ -6,14 +6,9 @@ AO_TRACING_ENABLED = 1
6
6
  AO_TRACING_DISABLED = 0
7
7
  AO_TRACING_UNSET = -1
8
8
 
9
- AO_TRACING_DECISIONS_TRACING_DISABLED = -2
10
- AO_TRACING_DECISIONS_XTRACE_NOT_SAMPLED = -1
11
9
  AO_TRACING_DECISIONS_OK = 0
12
- AO_TRACING_DECISIONS_NULL_OUT = 1
13
- AO_TRACING_DECISIONS_NO_CONFIG = 2
14
- AO_TRACING_DECISIONS_REPORTER_NOT_READY = 3
15
- AO_TRACING_DECISIONS_NO_VALID_SETTINGS = 4
16
- AO_TRACING_DECISIONS_QUEUE_FULL = 5
10
+
11
+ OBOE_SETTINGS_UNSET = -1
17
12
 
18
13
  module AppOpticsAPM
19
14
  ##
@@ -21,13 +16,15 @@ module AppOpticsAPM
21
16
  #
22
17
  class TransactionSettings
23
18
 
24
- attr_accessor :do_metrics, :do_sample
25
- attr_reader :do_propagate, :rate, :source
19
+ attr_accessor :do_sample, :do_metrics
20
+ attr_reader :auth_msg, :do_propagate, :status_msg, :type, :source, :rate, :xtrace
21
+ #, :status
26
22
 
27
- def initialize(url = nil, xtrace = '')
23
+ def initialize(url = '', xtrace = '', options = nil)
28
24
  @do_metrics = false
29
25
  @do_sample = false
30
26
  @do_propagate = true
27
+ @xtrace = xtrace || ''
31
28
  tracing_mode = AO_TRACING_ENABLED
32
29
 
33
30
  if AppOpticsAPM::Context.isValid
@@ -46,14 +43,23 @@ module AppOpticsAPM
46
43
  tracing_mode = AO_TRACING_DISABLED
47
44
  end
48
45
 
49
- args = [xtrace || '']
46
+ args = [@xtrace]
50
47
  args << tracing_mode
51
- args << AppOpticsAPM::Config[:sample_rate] if AppOpticsAPM::Config[:sample_rate]&. >= 0
48
+ args << (AppOpticsAPM::Config[:sample_rate] || OBOE_SETTINGS_UNSET)
49
+
50
+ if options && (options.options || options.signature)
51
+ args << (options.trigger_trace ? 1 : 0)
52
+ args << (trigger_tracing_mode_disabled? ? 0 : 1)
53
+ args << options.options
54
+ args << options.signature
55
+ args << options.timestamp
56
+ end
52
57
 
53
- metrics, sample, @rate, @source, return_code = AppOpticsAPM::Context.getDecisions(*args)
58
+ metrics, sample, @rate, @source, @type, @auth, @status_msg, @auth_msg, @status =
59
+ AppOpticsAPM::Context.getDecisions(*args)
54
60
 
55
- if return_code > AO_TRACING_DECISIONS_OK
56
- AppOpticsAPM.logger.warn "[appoptics-apm/sample] Problem getting the sampling decisions, code: #{return_code}"
61
+ if @status > AO_TRACING_DECISIONS_OK
62
+ AppOpticsAPM.logger.warn "[appoptics-apm/sample] Problem getting the sampling decisions: #{@status_msg} code: #{@status}"
57
63
  end
58
64
 
59
65
  @do_metrics = metrics > 0
@@ -64,6 +70,20 @@ module AppOpticsAPM
64
70
  "do_propagate: #{do_propagate}, do_sample: #{do_sample}, do_metrics: #{do_metrics} rate: #{rate}, source: #{source}"
65
71
  end
66
72
 
73
+ def add_kvs(kvs)
74
+ kvs[:SampleRate] = @rate
75
+ kvs[:SampleSource] = @source
76
+ end
77
+
78
+ def triggered_trace?
79
+ @type == 1
80
+ end
81
+
82
+ def auth_ok?
83
+ # @auth is undefined if initialize is called with an existing context
84
+ !@auth || @auth < 1
85
+ end
86
+
67
87
  private
68
88
 
69
89
  ##
@@ -103,6 +123,11 @@ module AppOpticsAPM
103
123
  false
104
124
  end
105
125
 
126
+ def trigger_tracing_mode_disabled?
127
+ AppOpticsAPM::Config[:trigger_tracing_mode] &&
128
+ AppOpticsAPM::Config[:trigger_tracing_mode] == :disabled
129
+ end
130
+
106
131
  ##
107
132
  # asset?
108
133
  #
@@ -0,0 +1,110 @@
1
+ # Copyright (c) 2019 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+
5
+ module AppOpticsAPM
6
+ class XTraceOptions
7
+
8
+ attr_reader :options, :signature, :trigger_trace, :timestamp
9
+ attr_reader :pd_keys, :custom_kvs, :ignored # used in tests
10
+ ##
11
+ # Params:
12
+ # +options+ : An X-Trace-Options @options string
13
+ # +signature+ : hmac signature to pass on for verification
14
+ #
15
+ # populates:
16
+ # - @force_trace (true|false)
17
+ # - @app_id (as given by Pingdom)
18
+ # - @probe_id (as given by Pingdom)
19
+ # - @loc (2 characters given by Pingdom)
20
+ # - @custom_kvs (hash)
21
+ # - @ignored (array)
22
+ #
23
+ # split it up by ';' separator
24
+ # kv assignment by '='
25
+ # currently valid keys:
26
+ # - force_trace (valid: 0,1) unless we use just a kv
27
+ # - application_id (format defined by pingdom (no validation))
28
+ # - probe_id
29
+ # - custom_* (';=' not allowed in key), value (validate max. length)
30
+ # - ts (unix timestamp)
31
+ # - other keys will be reported in the response options as ignored
32
+
33
+ def initialize(options, signature = nil)
34
+ @options = options.dup
35
+ @signature = signature.dup
36
+ @trigger_trace = false
37
+ @custom_kvs = {}
38
+ @pd_keys = nil
39
+ @ignored = []
40
+ @timestamp = 0
41
+
42
+ options&.split(/;+/)&.each do |val|
43
+ k = val.split('=', 2)
44
+
45
+ next unless k[0] # it can be nil, eg when the header starts with ';'
46
+
47
+ k[0]&.strip!
48
+ case k[0]
49
+ when 'trigger-trace'
50
+ if k[1]
51
+ @ignored << 'trigger-trace'
52
+ else
53
+ @trigger_trace = true
54
+ end
55
+ when 'pd-keys'
56
+ if @pd_keys
57
+ AppOpticsAPM.logger.info "[appoptics_apm/x-trace-options] Duplicate key: #{k[0]}"
58
+ else
59
+ @pd_keys = k[1].strip
60
+ end
61
+ when /^custom-[^\s]*$/
62
+ if @custom_kvs[k[0]]
63
+ AppOpticsAPM.logger.info "[appoptics_apm/x-trace-options] Duplicate key: #{k[0]}"
64
+ else
65
+ @custom_kvs[k[0]] = k[1].strip
66
+ end
67
+ when 'ts'
68
+ if @timestamp > 0
69
+ AppOpticsAPM.logger.info "[appoptics_apm/x-trace-options] Duplicate key: #{k[0]}"
70
+ else
71
+ @timestamp = k[1].to_i
72
+ end
73
+ else
74
+ @ignored << k[0]
75
+ end
76
+ end
77
+ unless @ignored.empty?
78
+ msg = "[appoptics_apm/x-trace-options] Some keys were ignored: #{@ignored.join(',' )}"
79
+ AppOpticsAPM.logger.info(msg)
80
+ end
81
+ end
82
+
83
+ def add_kvs(kvs, settings)
84
+ return unless settings.auth_ok?
85
+
86
+ @custom_kvs.each { |k,v| kvs[k] = v } unless @custom_kvs.empty?
87
+ kvs['PDKeys'] = @pd_keys if @pd_keys
88
+ kvs['TriggeredTrace'] = true if settings.triggered_trace?
89
+ end
90
+
91
+ def add_response_header(headers, settings)
92
+ return unless options
93
+
94
+ response = []
95
+ response << "auth=#{settings.auth_msg}" if @signature
96
+ if settings.auth_ok?
97
+ if @trigger_trace
98
+ trigger_msg = !settings.xtrace.empty? && settings.type == 0 ? 'ignored' : settings.status_msg
99
+ else
100
+ trigger_msg = 'not-requested'
101
+ end
102
+ response << "trigger-trace=#{trigger_msg}"
103
+ response << "ignored=#{@ignored.join(',')}" unless @ignored.empty?
104
+ end
105
+
106
+ headers['X-Trace-Options-Response'] = response.join(';')
107
+ end
108
+
109
+ end
110
+ end
@@ -7,8 +7,8 @@ module AppOpticsAPM
7
7
  # appoptics_apm.gemspec during gem build process
8
8
  module Version
9
9
  MAJOR = 4 # breaking,
10
- MINOR = 8 # feature,
11
- PATCH = 4 # fix => BFF
10
+ MINOR = 9 # feature,
11
+ PATCH = 0 # fix => BFF
12
12
 
13
13
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
14
14
  end
@@ -50,7 +50,7 @@ if defined?(AppOpticsAPM::Config)
50
50
  AppOpticsAPM::Config[:verbose] = false
51
51
 
52
52
  #
53
- # Turn tracing on or off
53
+ # Turn Tracing on or off
54
54
  #
55
55
  # By default tracing is set to :enabled, the other option is :disabled.
56
56
  # :enabled means that sampling will be done according to the current
@@ -61,31 +61,41 @@ if defined?(AppOpticsAPM::Config)
61
61
  #
62
62
  AppOpticsAPM::Config[:tracing_mode] = :enabled
63
63
 
64
+ #
65
+ # Turn Trigger Tracing on or off
66
+ #
67
+ # By default trigger tracing is :enabled, the other option is :disabled.
68
+ # It allows to use the X-Trace-Options header to force a request to be
69
+ # traced (within rate limits set for trigger tracing)
70
+ #
71
+ AppOpticsAPM::Config[:trigger_tracing_mode] = :enabled
72
+
64
73
  #
65
74
  # Trace Context in Logs
66
75
  #
67
- # Configure if and when the traceId should be included in application logs.
76
+ # Configure if and when the Trace ID should be included in application logs.
68
77
  # Common Ruby and Rails loggers are auto-instrumented, so that they can include
69
- # the current traceId in log messages.
78
+ # the current Trace ID in log messages.
70
79
  #
71
80
  # The added string will look like: "ao.traceId=7435A9FE510AE4533414D425DADF4E180D2B4E36-0"
72
81
  # It ends in '-1' if the request is sampled and in '-0' otherwise.
73
82
  #
74
83
  # The following options are available:
75
84
  # :never (default)
76
- # :sampled only include the traceId of sampled requests
77
- # :traced include the traceId for all traced requests
78
- # :always always add a traceId, it will be '0000000000000000000000000000000000000000-0'
85
+ # :sampled only include the Trace ID of sampled requests
86
+ # :traced include the Trace ID for all traced requests
87
+ # :always always add a Trace ID, it will be '0000000000000000000000000000000000000000-0'
79
88
  # when there is no tracing context.
80
89
  #
81
90
  AppOpticsAPM::Config[:log_traceId] = :never
82
91
 
83
92
  #
84
- # Prepend domain to transaction name
93
+ # Prepend Domain to Transaction Name
85
94
  #
86
- # If this is set to `true` transaction names will be composed as `my.host.com/controller.action` instead of
87
- # `controller.action`. This configuration applies to all transaction names, whether deduced by the instrumentation
88
- # or implicitly set.
95
+ # If this is set to `true` transaction names will be composed as
96
+ # `my.host.com/controller.action` instead of `controller.action`.
97
+ # This configuration applies to all transaction names, whether deduced by the
98
+ # instrumentation or implicitly set.
89
99
  #
90
100
  AppOpticsAPM::Config[:transaction_name][:prepend_domain] = false
91
101
 
@@ -195,6 +205,21 @@ if defined?(AppOpticsAPM::Config)
195
205
  AppOpticsAPM::Config[:report_rescued_errors] = false
196
206
  #
197
207
 
208
+ #
209
+ # EC2 Metadata Fetching Timeout
210
+ #
211
+ # The timeout can be in the range 0 - 3000 (milliseconds)
212
+ # Setting to 0 milliseconds effectively disables fetching from
213
+ # the metadata URL (not waiting), and should only be used if
214
+ # not running on EC2 / Openstack to minimize agent start up time.
215
+ #
216
+ AppOpticsAPM::Config[:ec2_metadata_timeout] = 1000
217
+
218
+
219
+ #############################################
220
+ ## SETTINGS FOR INDIVIDUAL GEMS/FRAMEWORKS ##
221
+ #############################################
222
+
198
223
  #
199
224
  # Bunny Controller and Action
200
225
  #
@@ -235,7 +260,7 @@ if defined?(AppOpticsAPM::Config)
235
260
  AppOpticsAPM::Config[:dalli][:enabled] = true
236
261
  AppOpticsAPM::Config[:delayed_jobclient][:enabled] = true
237
262
  AppOpticsAPM::Config[:delayed_jobworker][:enabled] = true
238
- AppOpticsAPM::Config[:em_http_request][:enabled] = false
263
+ # AppOpticsAPM::Config[:em_http_request][:enabled] = false # not supported anymore
239
264
  AppOpticsAPM::Config[:excon][:enabled] = true
240
265
  AppOpticsAPM::Config[:faraday][:enabled] = true
241
266
  AppOpticsAPM::Config[:grpc_client][:enabled] = true
@@ -301,7 +326,7 @@ if defined?(AppOpticsAPM::Config)
301
326
  AppOpticsAPM::Config[:dalli][:collect_backtraces] = false
302
327
  AppOpticsAPM::Config[:delayed_jobclient][:collect_backtraces] = false
303
328
  AppOpticsAPM::Config[:delayed_jobworker][:collect_backtraces] = false
304
- AppOpticsAPM::Config[:em_http_request][:collect_backtraces] = true
329
+ # AppOpticsAPM::Config[:em_http_request][:collect_backtraces] = true # not supported anymore
305
330
  AppOpticsAPM::Config[:excon][:collect_backtraces] = true
306
331
  AppOpticsAPM::Config[:faraday][:collect_backtraces] = false
307
332
  AppOpticsAPM::Config[:grape][:collect_backtraces] = true
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', '~> 6.0.0'
4
+ gem 'puma'
5
+ gem 'pg'
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.8.4
4
+ version: 4.9.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: 2019-09-10 00:00:00.000000000 Z
13
+ date: 2019-09-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -117,6 +117,7 @@ files:
117
117
  - ".dockerignore"
118
118
  - ".github/ISSUE_TEMPLATE/bug-or-feature-request.md"
119
119
  - ".gitignore"
120
+ - ".irbrc"
120
121
  - ".rubocop.yml"
121
122
  - ".travis.yml"
122
123
  - ".yardopts"
@@ -218,6 +219,7 @@ files:
218
219
  - lib/appoptics_apm/sdk/tracing.rb
219
220
  - lib/appoptics_apm/support/transaction_metrics.rb
220
221
  - lib/appoptics_apm/support/transaction_settings.rb
222
+ - lib/appoptics_apm/support/x_trace_options.rb
221
223
  - lib/appoptics_apm/support_report.rb
222
224
  - lib/appoptics_apm/test.rb
223
225
  - lib/appoptics_apm/thread_local.rb
@@ -232,6 +234,10 @@ files:
232
234
  - lib/oboe_metal.rb
233
235
  - lib/rails/generators/appoptics_apm/install_generator.rb
234
236
  - lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb
237
+ - oboe.code-workspace
238
+ - scrap.rb
239
+ - scrap_gemfile
240
+ - scrap_gemfile.lock
235
241
  - yardoc_frontpage.md
236
242
  homepage: https://www.appoptics.com/
237
243
  licenses:
@@ -249,7 +255,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
249
255
  requirements:
250
256
  - - ">="
251
257
  - !ruby/object:Gem::Version
252
- version: 2.0.0
258
+ version: 2.4.0
253
259
  required_rubygems_version: !ruby/object:Gem::Requirement
254
260
  requirements:
255
261
  - - ">="
@@ -257,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
257
263
  version: '0'
258
264
  requirements: []
259
265
  rubyforge_project:
260
- rubygems_version: 2.6.11
266
+ rubygems_version: 2.7.6.2
261
267
  signing_key:
262
268
  specification_version: 4
263
269
  summary: AppOptics APM performance instrumentation gem for Ruby