appoptics_apm_mnfst 4.5.2

Sign up to get free protection for your applications and to get access to all the features.
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