appoptics_apm_mnfst 4.5.2

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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
  4. data/.gitignore +29 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +121 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +769 -0
  9. data/CONFIG.md +33 -0
  10. data/Gemfile +29 -0
  11. data/LICENSE +193 -0
  12. data/README.md +393 -0
  13. data/Rakefile +230 -0
  14. data/appoptics_apm.gemspec +61 -0
  15. data/bin/appoptics_apm_config +15 -0
  16. data/build_gem.sh +15 -0
  17. data/build_gem_upload_to_packagecloud.sh +20 -0
  18. data/examples/SDK/01_basic_tracing.rb +67 -0
  19. data/examples/carrying_context.rb +220 -0
  20. data/ext/oboe_metal/extconf.rb +114 -0
  21. data/ext/oboe_metal/lib/.keep +0 -0
  22. data/ext/oboe_metal/noop/noop.c +7 -0
  23. data/ext/oboe_metal/src/VERSION +1 -0
  24. data/init.rb +4 -0
  25. data/lib/appoptics_apm.rb +76 -0
  26. data/lib/appoptics_apm/api.rb +20 -0
  27. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  28. data/lib/appoptics_apm/api/logging.rb +375 -0
  29. data/lib/appoptics_apm/api/memcache.rb +37 -0
  30. data/lib/appoptics_apm/api/metrics.rb +55 -0
  31. data/lib/appoptics_apm/api/profiling.rb +203 -0
  32. data/lib/appoptics_apm/api/tracing.rb +53 -0
  33. data/lib/appoptics_apm/api/util.rb +122 -0
  34. data/lib/appoptics_apm/base.rb +230 -0
  35. data/lib/appoptics_apm/config.rb +254 -0
  36. data/lib/appoptics_apm/frameworks/grape.rb +97 -0
  37. data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
  38. data/lib/appoptics_apm/frameworks/rails.rb +94 -0
  39. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  40. data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -0
  41. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  42. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  43. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  44. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
  45. data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
  46. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  47. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  48. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  49. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  50. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  51. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +108 -0
  52. data/lib/appoptics_apm/frameworks/sinatra.rb +125 -0
  53. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  54. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  55. data/lib/appoptics_apm/inst/curb.rb +330 -0
  56. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  57. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  58. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  59. data/lib/appoptics_apm/inst/excon.rb +125 -0
  60. data/lib/appoptics_apm/inst/faraday.rb +94 -0
  61. data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
  62. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  63. data/lib/appoptics_apm/inst/http.rb +73 -0
  64. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  65. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  66. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  67. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  68. data/lib/appoptics_apm/inst/moped.rb +466 -0
  69. data/lib/appoptics_apm/inst/rack.rb +199 -0
  70. data/lib/appoptics_apm/inst/redis.rb +275 -0
  71. data/lib/appoptics_apm/inst/resque.rb +151 -0
  72. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  73. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  74. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  75. data/lib/appoptics_apm/inst/sidekiq-worker.rb +65 -0
  76. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  77. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  78. data/lib/appoptics_apm/instrumentation.rb +22 -0
  79. data/lib/appoptics_apm/legacy_method_profiling.rb +90 -0
  80. data/lib/appoptics_apm/loading.rb +65 -0
  81. data/lib/appoptics_apm/logger.rb +42 -0
  82. data/lib/appoptics_apm/method_profiling.rb +33 -0
  83. data/lib/appoptics_apm/noop/README.md +9 -0
  84. data/lib/appoptics_apm/noop/context.rb +26 -0
  85. data/lib/appoptics_apm/noop/metadata.rb +22 -0
  86. data/lib/appoptics_apm/ruby.rb +35 -0
  87. data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
  88. data/lib/appoptics_apm/sdk/tracing.rb +315 -0
  89. data/lib/appoptics_apm/support.rb +119 -0
  90. data/lib/appoptics_apm/test.rb +94 -0
  91. data/lib/appoptics_apm/thread_local.rb +26 -0
  92. data/lib/appoptics_apm/util.rb +319 -0
  93. data/lib/appoptics_apm/version.rb +15 -0
  94. data/lib/appoptics_apm/xtrace.rb +103 -0
  95. data/lib/joboe_metal.rb +212 -0
  96. data/lib/oboe.rb +7 -0
  97. data/lib/oboe/README +2 -0
  98. data/lib/oboe/backward_compatibility.rb +80 -0
  99. data/lib/oboe/inst/rack.rb +11 -0
  100. data/lib/oboe_metal.rb +198 -0
  101. data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
  102. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
  103. data/yardoc_frontpage.md +26 -0
  104. metadata +266 -0
@@ -0,0 +1,230 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ # Constants from liboboe
5
+ APPOPTICS_TRACE_NEVER = 0
6
+ APPOPTICS_TRACE_ALWAYS = 1
7
+
8
+ # OBOE_SAMPLE_RATE_SOURCE_FILE = 1
9
+ # OBOE_SAMPLE_RATE_SOURCE_DEFAULT = 2
10
+ # OBOE_SAMPLE_RATE_SOURCE_OBOE = 3
11
+ # OBOE_SAMPLE_RATE_SOURCE_LAST_OBOE = 4
12
+ # OBOE_SAMPLE_RATE_SOURCE_DEFAULT_MISCONFIGURED = 5
13
+ # OBOE_SAMPLE_RATE_SOURCE_OBOE_DEFAULT = 6
14
+
15
+ # Masks for bitwise ops
16
+ # ZERO_MASK = 0b0000000000000000000000000000
17
+
18
+ SAMPLE_RATE_MASK = 0b0000111111111111111111111111
19
+ SAMPLE_SOURCE_MASK = 0b1111000000000000000000000000
20
+
21
+ # ZERO_SAMPLE_RATE_MASK = 0b1111000000000000000000000000
22
+ # ZERO_SAMPLE_SOURCE_MASK = 0b0000111111111111111111111111
23
+
24
+ APPOPTICS_STR_BLANK = ''.freeze
25
+ APPOPTICS_STR_LAYER = 'Layer'.freeze
26
+ APPOPTICS_STR_LABEL = 'Label'.freeze
27
+
28
+ # Used in tests to store local trace data
29
+ TRACE_FILE = '/tmp/appoptics_traces.bson'.freeze
30
+
31
+ ##
32
+ # This module is the base module for the various implementations of AppOpticsAPM reporting.
33
+ # Current variations as of 2014-09-10 are a c-extension, JRuby (using AppOpticsAPM Java
34
+ # instrumentation) and a Heroku c-extension (with embedded tracelyzer)
35
+ module AppOpticsAPMBase
36
+ extend AppOpticsAPM::ThreadLocal
37
+
38
+ attr_accessor :reporter
39
+ attr_accessor :loaded
40
+ thread_local :sample_source
41
+ thread_local :sample_rate
42
+ thread_local :layer
43
+ thread_local :layer_op
44
+
45
+ # transaction_name is used for custom transaction naming
46
+ # It needs to be globally accessible, but is only set by the request processors of the different frameworks
47
+ # and read by rack
48
+ thread_local :transaction_name
49
+
50
+ # Semaphore used during the test suite to test
51
+ # global config options.
52
+ thread_local :config_lock
53
+
54
+ # The following accessors indicate the incoming tracing state received
55
+ # by the rack layer. These are primarily used to identify state
56
+ # between the Ruby and JAppOpticsAPM instrumentation under JRuby.
57
+ #
58
+ # This is because that even though there may be an incoming
59
+ # X-Trace request header, tracing may have already been started
60
+ # by Joboe. Such a scenario occurs when the application is being
61
+ # hosted by a Java container (such as Tomcat or Glassfish) and
62
+ # AppOpticsAPM has already initiated tracing. In this case, we shouldn't
63
+ # pickup the X-Trace context in the X-Trace header and we shouldn't
64
+ # set the outgoing response X-Trace header or clear context.
65
+ # Yeah I know. Yuck.
66
+
67
+ # Occurs only on Jruby. Indicates that Joboe (the java instrumentation)
68
+ # has already started tracing before it hit the JRuby instrumentation.
69
+ # It is used in Rack#call if there is a context when entering rack
70
+ thread_local :has_incoming_context
71
+
72
+ # Indicates the existence of a valid X-Trace request header
73
+ thread_local :has_xtrace_header
74
+
75
+ # This indicates that this trace was continued from
76
+ # an incoming X-Trace request header or in the case
77
+ # of JRuby, a trace already started by JAppOpticsAPM.
78
+ thread_local :is_continued_trace
79
+
80
+ ##
81
+ # extended
82
+ #
83
+ # Invoked when this module is extended.
84
+ # e.g. extend AppOpticsAPMBase
85
+ #
86
+ def self.extended(cls)
87
+ cls.loaded = true
88
+
89
+ # This gives us pretty accessors with questions marks at the end
90
+ # e.g. is_continued_trace --> is_continued_trace?
91
+ AppOpticsAPM.methods.select { |m| m =~ /^is_|^has_/ }.each do |c|
92
+ unless c =~ /\?$|=$/
93
+ # AppOpticsAPM.logger.debug "aliasing #{c}? to #{c}"
94
+ alias_method "#{c}?", c
95
+ end
96
+ end
97
+ end
98
+
99
+ ##
100
+ # pickup_context
101
+ #
102
+ # for JRUBY
103
+ # Determines whether we should pickup context
104
+ # from an incoming X-Trace request header. The answer
105
+ # is generally yes but there are cases in JRuby under
106
+ # Tomcat (or Glassfish etc.) where tracing may have
107
+ # been already started by the Java instrumentation (Joboe)
108
+ # in which case we don't want to do this.
109
+ #
110
+ def pickup_context?(xtrace)
111
+ return false unless AppOpticsAPM::XTrace.valid?(xtrace)
112
+
113
+ if defined?(JRUBY_VERSION) && AppOpticsAPM.tracing?
114
+ return false
115
+ else
116
+ return true
117
+ end
118
+ end
119
+
120
+ ##
121
+ # tracing_layer?
122
+ #
123
+ # Queries the thread local variable about the current
124
+ # layer being traced. This is used in cases of recursive
125
+ # operation tracing or one instrumented operation calling another.
126
+ #
127
+ def tracing_layer?(layer)
128
+ AppOpticsAPM.layer == layer.to_sym
129
+ end
130
+
131
+ ##
132
+ # tracing_layer_op?
133
+ #
134
+ # Queries the thread local variable about the current
135
+ # operation being traced. This is used in cases of recursive
136
+ # operation tracing or one instrumented operation calling another.
137
+ #
138
+ # In such cases, we only want to trace the outermost operation.
139
+ #
140
+ def tracing_layer_op?(operation)
141
+ unless AppOpticsAPM.layer_op.nil? || AppOpticsAPM.layer_op.is_a?(Array)
142
+ AppOpticsAPM.logger.error('[appopticsapm/logging] INTERNAL: layer_op should be nil or an array, please report to support@appoptics.com')
143
+ return false
144
+ end
145
+
146
+ return false if AppOpticsAPM.layer_op.nil? || AppOpticsAPM.layer_op.empty? || !operation.respond_to?(:to_sym)
147
+ AppOpticsAPM.layer_op.last == operation.to_sym
148
+ end
149
+
150
+ ##
151
+ # Returns true if the tracing_mode is set to always.
152
+ # False otherwise
153
+ #
154
+ def always?
155
+ AppOpticsAPM::Config[:tracing_mode] &&
156
+ AppOpticsAPM::Config[:tracing_mode].to_sym == :always
157
+ end
158
+
159
+ ##
160
+ # Returns true if the tracing_mode is set to never.
161
+ # False otherwise
162
+ #
163
+ def never?
164
+ AppOpticsAPM::Config[:tracing_mode] &&
165
+ AppOpticsAPM::Config[:tracing_mode].to_sym == :never
166
+ end
167
+
168
+ ##
169
+ # Returns true if we are currently tracing a request
170
+ # False otherwise
171
+ #
172
+ def tracing?
173
+ return false if !AppOpticsAPM.loaded || AppOpticsAPM.never?
174
+ AppOpticsAPM::Context.isSampled
175
+ end
176
+
177
+ def heroku?
178
+ ENV.key?('APPOPTICS_URL')
179
+ end
180
+
181
+ ##
182
+ # Determines if we are running under a forking webserver
183
+ #
184
+ def forking_webserver?
185
+ if (defined?(::Unicorn) && ($PROGRAM_NAME =~ /unicorn/i)) ||
186
+ (defined?(::Puma) && ($PROGRAM_NAME =~ /puma/i))
187
+ true
188
+ else
189
+ false
190
+ end
191
+ end
192
+
193
+ ##
194
+ # Indicates whether a supported framework is in use
195
+ # or not
196
+ #
197
+ def framework?
198
+ defined?(::Rails) || defined?(::Sinatra) || defined?(::Padrino) || defined?(::Grape)
199
+ end
200
+
201
+ ##
202
+ # These methods should be implemented by the descendants
203
+ # (Oboe_metal, JOboe_metal (JRuby), Heroku_metal)
204
+ #
205
+ def sample?(_opts = {})
206
+ fail 'sample? should be implemented by metal layer.'
207
+ end
208
+
209
+ def log(_layer, _label, _options = {})
210
+ fail 'log should be implemented by metal layer.'
211
+ end
212
+
213
+ def set_tracing_mode(_mode)
214
+ fail 'set_tracing_mode should be implemented by metal layer.'
215
+ end
216
+
217
+ def set_sample_rate(_rate)
218
+ fail 'set_sample_rate should be implemented by metal layer.'
219
+ end
220
+ end
221
+
222
+ module AppOpticsAPM
223
+ extend AppOpticsAPMBase
224
+ end
225
+
226
+ # Setup an alias so we don't bug users
227
+ # about single letter capitalization
228
+ AppopticsAPM = AppOpticsAPM
229
+ AppOpticsApm = AppOpticsAPM
230
+ AppopticsApm = AppOpticsAPM
@@ -0,0 +1,254 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ ##
6
+ # This module exposes a nested configuration hash that can be used to
7
+ # configure and/or modify the functionality of the appoptics_apm gem.
8
+ #
9
+ # Use AppOpticsAPM::Config.show to view the entire nested hash.
10
+ #
11
+ module Config
12
+ @@config = {}
13
+
14
+ @@instrumentation = [:action_controller, :action_controller_api, :action_view,
15
+ :active_record, :bunnyclient, :bunnyconsumer, :cassandra, :curb,
16
+ :dalli, :delayed_jobclient, :delayed_jobworker,
17
+ :em_http_request, :excon, :faraday, :grpc_client, :grpc_server, :grape,
18
+ :httpclient, :nethttp, :memcached, :mongo, :moped, :padrino, :rack, :redis,
19
+ :resqueclient, :resqueworker, :rest_client,
20
+ :sequel, :sidekiqclient, :sidekiqworker, :sinatra, :typhoeus]
21
+
22
+ # Subgrouping of instrumentation
23
+ @@http_clients = [:curb, :excon, :em_http_request, :faraday, :httpclient, :nethttp, :rest_client, :typhoeus]
24
+
25
+ ##
26
+ # load_config_file
27
+ #
28
+ # There are 3 possible locations for the config file:
29
+ # Rails default, ENV['APPOPTICS_APM_CONFIG_RUBY'], or the gem's default
30
+ #
31
+ # Hierarchie:
32
+ # 1 - Rails default: config/initializers/appoptics_apm.rb
33
+ # (also loaded by Rails, but we can't reliably determine if Rails is running)
34
+ # 2 - ENV['APPOPTICS_APM_CONFIG_RUBY']
35
+ # 3 - Gem default: <startup_dir>/appoptics_apm_config.rb
36
+ #
37
+ def self.load_config_file
38
+ config_files = []
39
+
40
+ # Check for the rails config file
41
+ config_file = File.join(Dir.pwd, 'config/initializers/appoptics_apm.rb')
42
+ config_files << config_file if File.exist?(config_file)
43
+
44
+ # Check for file set by env variable
45
+ if ENV.key?('APPOPTICS_APM_CONFIG_RUBY')
46
+ if File.exist?(ENV['APPOPTICS_APM_CONFIG_RUBY']) && !File.directory?(ENV['APPOPTICS_APM_CONFIG_RUBY'])
47
+ config_files << ENV['APPOPTICS_APM_CONFIG_RUBY']
48
+ elsif File.exist?(File.join(ENV['APPOPTICS_APM_CONFIG_RUBY'], 'appoptics_apm_config.rb'))
49
+ config_files << File.join(ENV['APPOPTICS_APM_CONFIG_RUBY'], 'appoptics_apm_config.rb')
50
+ else
51
+ $stderr.puts 'Could not find the configuration file set by the APPOPTICS_APM_CONFIG_RUBY environment variable:'
52
+ $stderr.puts "#{ENV['APPOPTICS_APM_CONFIG_RUBY']}"
53
+ end
54
+ end
55
+
56
+ # Check for default config file
57
+ config_file = File.join(Dir.pwd, 'appoptics_apm_config.rb')
58
+ config_files << config_file if File.exist?(config_file)
59
+
60
+ return if config_files.empty? # we use the defaults from the template in this case
61
+
62
+ if config_files.size > 1
63
+ $stderr.puts 'Found multiple configuration files, using the first one listed:'
64
+ config_files.each { |path| $stderr.puts " #{path}" }
65
+ end
66
+ load(config_files[0])
67
+ check_env_vars
68
+ end
69
+
70
+ # There are 4 variables that can be set in the config file or as env vars.
71
+ # Oboe will override vars passed in if it finds an environment variable
72
+ # :debug_level and :verbose need special consideration, because they are used in Ruby
73
+ def self.check_env_vars
74
+ unless (-1..6).include?(AppOpticsAPM::Config[:debug_level])
75
+ AppOpticsAPM::Config[:debug_level] = 3
76
+ end
77
+
78
+ # let's find and use the equivalent debug level for ruby
79
+ debug_level = ENV['APPOPTICS_DEBUG_LEVEL'] ? ENV['APPOPTICS_DEBUG_LEVEL'].to_i : AppOpticsAPM::Config[:debug_level]
80
+ if debug_level < 0
81
+ # there should be no logging if APPOPTICS_DEBUG_LEVEL == -1
82
+ # In Ruby level 5 is UNKNOWN and it can log, but level 6 is quiet
83
+ AppOpticsAPM.logger.level = 6
84
+ else
85
+ AppOpticsAPM.logger.level = [4 - debug_level, 0].max
86
+ end
87
+
88
+ # the verbose setting is only relevant for ruby, ENV['APPOPTICS_GEM_VERBOSE'] overrides
89
+ if ENV.key?('APPOPTICS_GEM_VERBOSE')
90
+ AppOpticsAPM::Config[:verbose] = ENV['APPOPTICS_GEM_VERBOSE'].downcase == 'true'
91
+ end
92
+ end
93
+
94
+ ##
95
+ # print_config
96
+ #
97
+ # print configurations one per line
98
+ # to create an output similar to the content of the config file
99
+ #
100
+ def self.print_config
101
+ AppOpticsAPM.logger.warn "# General configurations"
102
+ non_instrumentation = @@config.keys - @@instrumentation
103
+ non_instrumentation.each do |config|
104
+ AppOpticsAPM.logger.warn "AppOpticsAPM::Config[:#{config}] = #{@@config[config]}"
105
+ end
106
+
107
+ AppOpticsAPM.logger.warn "\n# Instrumentation specific configurations"
108
+ AppOpticsAPM.logger.warn "# Enabled/Disabled Instrumentation"
109
+ @@instrumentation.each do |config|
110
+ AppOpticsAPM.logger.warn "AppOpticsAPM::Config[:#{config}][:enabled] = #{@@config[config][:enabled]}"
111
+ end
112
+
113
+ AppOpticsAPM.logger.warn "\n# Enabled/Disabled Backtrace Collection"
114
+ @@instrumentation.each do |config|
115
+ AppOpticsAPM.logger.warn "AppOpticsAPM::Config[:#{config}][:collect_backtraces] = #{@@config[config][:collect_backtraces]}"
116
+ end
117
+
118
+ AppOpticsAPM.logger.warn "\n# Logging of outgoing HTTP query args"
119
+ @@instrumentation.each do |config|
120
+ AppOpticsAPM.logger.warn "AppOpticsAPM::Config[:#{config}][:log_args] = #{@@config[config][:log_args] || false}"
121
+ end
122
+
123
+ AppOpticsAPM.logger.warn "\n# Bunny Controller and Action"
124
+ AppOpticsAPM.logger.warn "AppOpticsAPM::Config[:bunnyconsumer][:controller] = #{@@config[:bunnyconsumer][:controller].inspect}"
125
+ AppOpticsAPM.logger.warn "AppOpticsAPM::Config[:bunnyconsumer][:action] = #{@@config[:bunnyconsumer][:action].inspect}"
126
+ nil
127
+ end
128
+
129
+ ##
130
+ # initialize
131
+ #
132
+ # Initializer method to set everything up with a default configuration.
133
+ # The defaults are read from the template configuration file.
134
+ #
135
+ # rubocop:disable Metrics/AbcSize
136
+ def self.initialize(_data = {})
137
+ @@instrumentation.each { |k| @@config[k] = {} }
138
+ @@config[:transaction_name] = {}
139
+
140
+ # Always load the template, it has all the keys and defaults defined,
141
+ # no guarantee of completeness in the user's config file
142
+ load(File.join(File.dirname(File.dirname(__FILE__)),
143
+ 'rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb'))
144
+
145
+ # to make sure we include the service_key if it is set as an ENV var
146
+ check_env_vars
147
+ end
148
+ # rubocop:enable Metrics/AbcSize
149
+
150
+ def self.update!(data)
151
+ data.each do |key, value|
152
+ self[key] = value
153
+ end
154
+ end
155
+
156
+ def self.merge!(data)
157
+ update!(data)
158
+ end
159
+
160
+ def self.[](key)
161
+ if key == :resque
162
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] :resque config is deprecated. It is now split into :resqueclient and :resqueworker.'
163
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Called from #{Kernel.caller[0]}"
164
+ end
165
+
166
+ @@config[key.to_sym]
167
+ end
168
+
169
+ ##
170
+ # []=
171
+ #
172
+ # Config variable assignment method. Here we validate and store the
173
+ # assigned value(s) and trigger any secondary action needed.
174
+ #
175
+ # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
176
+ def self.[]=(key, value)
177
+ @@config[key.to_sym] = value
178
+
179
+ if key == :sampling_rate
180
+ AppOpticsAPM.logger.warn '[appoptics_apm/config] sampling_rate is not a supported setting for AppOpticsAPM::Config. ' \
181
+ 'Please use :sample_rate.'
182
+
183
+ elsif key == :sample_rate
184
+ unless value.is_a?(Integer) || value.is_a?(Float)
185
+ AppOpticsAPM.logger.warn "[appoptics_apm/config] :sample_rate must be a number between 0 and 1000000 (1m) " \
186
+ "(provided: #{value}), corrected to 0"
187
+ value = 0
188
+ end
189
+
190
+ # Validate :sample_rate value
191
+ unless value.between?(0, 1e6)
192
+ value_1 = value
193
+ value = value_1 < 0 ? 0 : 1_000_000
194
+ AppOpticsAPM.logger.warn "[appoptics_apm/config] :sample_rate must be between 0 and 1000000 (1m) " \
195
+ "(provided: #{value_1}), corrected to #{value}"
196
+ end
197
+
198
+ # Assure value is an integer
199
+ @@config[key.to_sym] = value.to_i
200
+ AppOpticsAPM.set_sample_rate(value) if AppOpticsAPM.loaded
201
+
202
+ elsif key == :action_blacklist
203
+ AppOpticsAPM.logger.warn "[appoptics_apm/config] :action_blacklist has been deprecated and no longer functions."
204
+
205
+ elsif key == :resque
206
+ AppOpticsAPM.logger.warn "[appoptics_apm/config] :resque config is deprecated. It is now split into :resqueclient and :resqueworker."
207
+ AppOpticsAPM.logger.warn "[appoptics_apm/config] Called from #{Kernel.caller[0]}"
208
+
209
+ elsif key == :include_url_query_params # DEPRECATED
210
+ # Obey the global flag and update all of the per instrumentation
211
+ # <tt>:log_args</tt> values.
212
+ @@config[:rack][:log_args] = value
213
+
214
+ elsif key == :include_remote_url_params # DEPRECATED
215
+ # Obey the global flag and update all of the per instrumentation
216
+ # <tt>:log_args</tt> values.
217
+ @@http_clients.each do |i|
218
+ @@config[i][:log_args] = value
219
+ end
220
+
221
+ # Update liboboe if updating :tracing_mode
222
+ elsif key == :tracing_mode
223
+ AppOpticsAPM.set_tracing_mode(value.to_sym) if AppOpticsAPM.loaded
224
+
225
+ # Make sure that the mode is stored as a symbol
226
+ @@config[key.to_sym] = value.to_sym
227
+ end
228
+ end
229
+ # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
230
+
231
+ def self.method_missing(sym, *args)
232
+ class_var_name = "@@#{sym}"
233
+
234
+ if sym.to_s =~ /(.+)=$/
235
+ self[$1] = args.first
236
+ else
237
+ # Try part of the @@config hash first
238
+ if @@config.key?(sym)
239
+ self[sym]
240
+
241
+ # Then try as a class variable
242
+ elsif self.class_variable_defined?(class_var_name.to_sym)
243
+ self.class_eval(class_var_name)
244
+
245
+ # Congrats - You've won a brand new nil...
246
+ else
247
+ nil
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ AppOpticsAPM::Config.initialize