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,15 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ ##
6
+ # The current version of the gem. Used mainly by
7
+ # appoptics_apm.gemspec during gem build process
8
+ module Version
9
+ MAJOR = 4
10
+ MINOR = 5
11
+ PATCH = 2
12
+
13
+ STRING = [MAJOR, MINOR, PATCH].compact.join('.')
14
+ end
15
+ end
@@ -0,0 +1,103 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module AppOpticsAPM
5
+ ##
6
+ # Methods to act on, manipulate or investigate an X-Trace
7
+ # value
8
+ module XTrace
9
+ class << self
10
+ ##
11
+ # AppOpticsAPM::XTrace.valid?
12
+ #
13
+ # Perform basic validation on a potential X-Trace ID
14
+ #
15
+ def valid?(xtrace)
16
+ # Shouldn't be nil
17
+ return false unless xtrace
18
+
19
+ # The X-Trace ID shouldn't be an initialized empty ID
20
+ return false if (xtrace =~ /^2b0000000/i) == 0
21
+
22
+ # Valid X-Trace IDs have a length of 60 bytes and start with '2b'
23
+ return false unless xtrace.length == 60 && (xtrace =~ /^2b/i) == 0
24
+
25
+ true
26
+ rescue StandardError => e
27
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
28
+ AppOpticsAPM.logger.debug e.backtrace
29
+ false
30
+ end
31
+
32
+ def sampled?(xtrace)
33
+ valid?(xtrace) && xtrace[59].to_i & 1 == 1
34
+ end
35
+
36
+ def set_sampled(xtrace)
37
+ xtrace[59] = (xtrace[59].hex | 1).to_s(16).upcase
38
+ end
39
+
40
+ def unset_sampled(xtrace)
41
+ xtrace[59] = (~(~xtrace[59].hex | 1)).to_s(16).upcase
42
+ end
43
+
44
+ ##
45
+ # AppOpticsAPM::XTrace.task_id
46
+ #
47
+ # Extract and return the task_id portion of an X-Trace ID
48
+ #
49
+ def task_id(xtrace)
50
+ return nil unless AppOpticsAPM::XTrace.valid?(xtrace)
51
+
52
+ xtrace[2..41]
53
+ rescue StandardError => e
54
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
55
+ AppOpticsAPM.logger.debug e.backtrace
56
+ return nil
57
+ end
58
+
59
+ ##
60
+ # AppOpticsAPM::XTrace.edge_id
61
+ #
62
+ # Extract and return the edge_id portion of an X-Trace ID
63
+ #
64
+ def edge_id(xtrace)
65
+ return nil unless AppOpticsAPM::XTrace.valid?(xtrace)
66
+
67
+ xtrace[42..57]
68
+ rescue StandardError => e
69
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
70
+ AppOpticsAPM.logger.debug e.backtrace
71
+ return nil
72
+ end
73
+
74
+ ##
75
+ # continue_service_context
76
+ #
77
+ # In the case of service calls such as external HTTP requests, we
78
+ # pass along X-Trace headers so that request context can be maintained
79
+ # across servers and applications.
80
+ #
81
+ # Remote requests can return a X-Trace header in which case we want
82
+ # to pickup on and continue the context in most cases.
83
+ #
84
+ # @start is the context just before the outgoing request
85
+ #
86
+ # @finish is the context returned to us (as an HTTP response header
87
+ # if that be the case)
88
+ #
89
+ def continue_service_context(start, finish)
90
+ if AppOpticsAPM::XTrace.valid?(finish) && AppOpticsAPM.tracing?
91
+
92
+ # Assure that we received back a valid X-Trace with the same task_id
93
+ # and the sampling bit is set, otherwise it is a response from a non-sampling service
94
+ if AppOpticsAPM::XTrace.task_id(start) == AppOpticsAPM::XTrace.task_id(finish) && AppOpticsAPM::XTrace.sampled?(finish)
95
+ AppOpticsAPM::Context.fromString(finish)
96
+ else
97
+ AppOpticsAPM.logger.debug "[XTrace] Sampling flag unset or mismatched start and finish ids:\n#{start}\n#{finish}"
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,212 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ module Oboe_metal
5
+ include_package 'com.tracelytics.joboe'
6
+ java_import 'com.tracelytics.joboe.LayerUtil'
7
+ java_import 'com.tracelytics.joboe.SettingsReader'
8
+ java_import 'com.tracelytics.joboe.Context'
9
+ java_import 'com.tracelytics.joboe.Event'
10
+ java_import 'com.tracelytics.agent.Agent'
11
+
12
+ class Context
13
+ class << self
14
+ def toString
15
+ getMetadata.toHexString
16
+ end
17
+
18
+ def fromString(xtrace)
19
+ Context.setMetadata(xtrace)
20
+ end
21
+
22
+ def clear
23
+ clearMetadata
24
+ end
25
+
26
+ def get
27
+ getMetadata
28
+ end
29
+ end
30
+ end
31
+
32
+ module EventUtil
33
+ def self.metadataString(evt)
34
+ evt.getMetadata.toHexString
35
+ end
36
+ end
37
+
38
+ def UdpReporter
39
+ Java::ComTracelyticsJoboe
40
+ end
41
+
42
+ module Metadata
43
+ Java::ComTracelyticsJoboeMetaData
44
+ end
45
+
46
+ module Reporter
47
+ class << self
48
+ ##
49
+ # start
50
+ #
51
+ # Start the AppOpticsAPM Reporter
52
+ #
53
+ def start
54
+ return unless AppOpticsAPM.loaded
55
+
56
+ if ENV.key?('APPOPTICS_GEM_TEST')
57
+ AppOpticsAPM.reporter = Java::ComTracelyticsJoboe::ReporterFactory.getInstance.buildTestReporter(false)
58
+ else
59
+ AppOpticsAPM.reporter = Java::ComTracelyticsJoboe::ReporterFactory.getInstance.buildUdpReporter
60
+ end
61
+
62
+ begin
63
+ # Import the tracing mode and sample rate settings
64
+ # from the Java agent (user configured in
65
+ # /usr/local/tracelytics/javaagent.json when under JRuby)
66
+ cfg = LayerUtil.getLocalSampleRate(nil, nil)
67
+
68
+ if cfg.hasSampleStartFlag
69
+ AppOpticsAPM::Config.tracing_mode = :always
70
+ else
71
+ AppOpticsAPM::Config.tracing_mode = :never
72
+ end
73
+
74
+ AppOpticsAPM.sample_rate = cfg.getSampleRate
75
+ AppOpticsAPM::Config.sample_rate = cfg.sampleRate
76
+ AppOpticsAPM::Config.sample_source = cfg.sampleRateSourceValue
77
+ rescue => e
78
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] Couldn't retrieve/acces joboe sampleRateCfg"
79
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{e.message}"
80
+ end
81
+
82
+ # Only report __Init from here if we are not instrumenting a framework.
83
+ # Otherwise, frameworks will handle reporting __Init after full initialization
84
+ unless defined?(::Rails) || defined?(::Sinatra) || defined?(::Padrino) || defined?(::Grape)
85
+ AppOpticsAPM::API.report_init unless ENV.key?('APPOPTICS_GEM_TEST')
86
+ end
87
+ end
88
+
89
+ ##
90
+ # restart
91
+ #
92
+ # This is a nil method for AppOpticsAPM under Java. It is maintained only
93
+ # for compability across interfaces.
94
+ #
95
+ def restart
96
+ AppOpticsAPM.logger.warn "[appoptics_apm/reporter] Reporter.restart isn't supported under JRuby"
97
+ end
98
+
99
+ ##
100
+ # clear_all_traces
101
+ #
102
+ # Truncates the trace output file to zero
103
+ #
104
+ def clear_all_traces
105
+ AppOpticsAPM.reporter.reset if AppOpticsAPM.loaded
106
+ end
107
+
108
+ ##
109
+ # get_all_traces
110
+ #
111
+ # Retrieves all traces written to the trace file
112
+ #
113
+ def get_all_traces
114
+ return [] unless AppOpticsAPM.loaded
115
+
116
+ # Joboe TestReporter returns a Java::ComTracelyticsExtEbson::DefaultDocument
117
+ # document for traces which doesn't correctly support things like has_key? which
118
+ # raises an unhandled exception on non-existent key (duh). Here we convert
119
+ # the Java::ComTracelyticsExtEbson::DefaultDocument doc to a pure array of Ruby
120
+ # hashes
121
+ traces = []
122
+ AppOpticsAPM.reporter.getSentEventsAsBsonDocument.to_a.each do |e|
123
+ t = {}
124
+ e.each_pair { |k, v|
125
+ t[k] = v
126
+ }
127
+ traces << t
128
+ end
129
+ traces
130
+ end
131
+
132
+ def sendReport(evt)
133
+ evt.report(AppOpticsAPM.reporter)
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ module AppOpticsAPM
140
+ extend AppOpticsAPMBase
141
+ include Oboe_metal
142
+
143
+ class << self
144
+ def sample?(opts = {})
145
+ begin
146
+ # Return false if no-op mode
147
+ return false unless AppOpticsAPM.loaded
148
+
149
+ return true if ENV.key?('APPOPTICS_GEM_TEST')
150
+
151
+ # Validation to make Joboe happy. Assure that we have the KVs and that they
152
+ # are not empty strings.
153
+ opts[:xtrace] = nil if opts[:xtrace].is_a?(String) && opts[:xtrace].empty?
154
+
155
+ opts[:xtrace] ||= nil
156
+
157
+ sr_cfg = Java::ComTracelyticsJoboe::LayerUtil.shouldTraceRequest(APPOPTICS_STR_BLANK, { 'X-Trace' => opts[:xtrace] })
158
+
159
+ # Store the returned SampleRateConfig into AppOpticsAPM::Config
160
+ if sr_cfg
161
+ begin
162
+ AppOpticsAPM::Config.sample_rate = sr_cfg.sampleRate
163
+ AppOpticsAPM::Config.sample_source = sr_cfg.sampleRateSourceValue
164
+ # If we fail here, we do so quietly. This was we don't spam logs
165
+ # on every request
166
+ end
167
+ else
168
+ AppOpticsAPM.sample_rate = -1
169
+ AppOpticsAPM.sample_source = -1
170
+ end
171
+
172
+ sr_cfg ? true : false
173
+ rescue => e
174
+ AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{e.message}"
175
+ false
176
+ end
177
+ end
178
+
179
+ def set_tracing_mode(_mode)
180
+ AppOpticsAPM.logger.warn '[appoptics_apm/joboe] When using JRuby set the tracing mode in /usr/local/tracelytics/javaagent.json instead'
181
+ end
182
+
183
+ def set_sample_rate(_rate)
184
+ # N/A
185
+ end
186
+ end
187
+ end
188
+
189
+ # Assure that the Joboe Java Agent was loaded via premain
190
+ case Java::ComTracelyticsAgent::Agent.getStatus
191
+ when Java::ComTracelyticsAgent::Agent::AgentStatus::INITIALIZED_SUCCESSFUL
192
+ AppOpticsAPM.loaded = true
193
+
194
+ when Java::ComTracelyticsAgent::Agent::AgentStatus::INITIALIZED_FAILED
195
+ AppOpticsAPM.loaded = false
196
+ $stderr.puts '=============================================================='
197
+ $stderr.puts 'AppOpticsAPM Java Agent not initialized properly.'
198
+ $stderr.puts 'Possibly misconfigured? Going into no-op mode.'
199
+ $stderr.puts 'http://docs.appoptics.solarwinds.com/Instrumentation/other-instrumentation-modules.html#jruby'
200
+ $stderr.puts '=============================================================='
201
+
202
+ when Java::ComTracelyticsAgent::Agent::AgentStatus::UNINITIALIZED
203
+ AppOpticsAPM.loaded = false
204
+ $stderr.puts '=============================================================='
205
+ $stderr.puts 'AppOpticsAPM Java Agent not loaded. Going into no-op mode.'
206
+ $stderr.puts 'To preload the AppOpticsAPM java agent see:'
207
+ $stderr.puts 'http://docs.appoptics.solarwinds.com/Instrumentation/other-instrumentation-modules.html#jruby'
208
+ $stderr.puts '=============================================================='
209
+
210
+ else
211
+ AppOpticsAPM.loaded = false
212
+ end
@@ -0,0 +1,7 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ # This module is provided for backward compatibility.
5
+ # It simply redirects to the appoptics_apm module which will
6
+ # also load backward compatibility support.
7
+ require 'appoptics_apm'
@@ -0,0 +1,2 @@
1
+ This directory is kept for backward compatibility for applications
2
+ making calls to Oboe modules.
@@ -0,0 +1,80 @@
1
+ require 'appoptics_apm/thread_local'
2
+
3
+ module Oboe
4
+ extend AppOpticsAPMBase
5
+ if AppOpticsAPM.loaded
6
+ include Oboe_metal
7
+ end
8
+
9
+ #
10
+ # Support for Oboe::API calls
11
+ #
12
+ module API
13
+ include AppOpticsAPM::API
14
+ extend AppOpticsAPM::ThreadLocal
15
+ thread_local :deprecation_notified
16
+
17
+ def self.method_missing(sym, *args, &blk)
18
+ # Notify of deprecation only once
19
+ unless @deprecated_notified
20
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Note that Oboe::API has been renamed to AppOpticsAPM::API. (#{sym}:#{args})"
21
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] Oboe::API will be deprecated in a future version.'
22
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Caller: #{Kernel.caller[0]}"
23
+ @deprecated_notified = true
24
+ end
25
+ AppOpticsAPM::API.send(sym, *args, &blk)
26
+ end
27
+ end
28
+
29
+
30
+ #
31
+ # Support for Oboe::Config calls
32
+ #
33
+ module Config
34
+ extend AppOpticsAPM::ThreadLocal
35
+ thread_local :deprecation_notified
36
+
37
+ def self.method_missing(sym, *args)
38
+ # Notify of deprecation only once
39
+ unless @deprecated_notified
40
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Note that Oboe::Config has been renamed to AppOpticsAPM::Config. (#{sym}:#{args})"
41
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] Oboe::Config will be deprecated in a future version.'
42
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Caller: #{Kernel.caller[0]}"
43
+ @deprecated_notified = true
44
+ end
45
+ AppOpticsAPM::Config.send(sym, *args)
46
+ end
47
+ end
48
+
49
+ #
50
+ # Support for legacy Oboe::Ruby.load calls
51
+ #
52
+ module Ruby
53
+ extend AppOpticsAPM::ThreadLocal
54
+ thread_local :deprecation_notified
55
+
56
+ def self.method_missing(sym, *args)
57
+ # Notify of deprecation only once
58
+ unless @deprecated_notified
59
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Note that Oboe::Ruby has been renamed to AppOpticsAPM::Ruby. (#{sym}:#{args})"
60
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] Oboe::Ruby will be deprecated in a future version.'
61
+ AppOpticsAPM.logger.warn "[appoptics_apm/warn] Caller: #{Kernel.caller[0]}"
62
+ @deprecated_notified = true
63
+ end
64
+ AppOpticsAPM::Ruby.send(sym, *args)
65
+ end
66
+ end
67
+ end
68
+
69
+ #
70
+ # Support for OboeMethodProfiling
71
+ #
72
+ module OboeMethodProfiling
73
+ def self.included(klass)
74
+ klass.extend ClassMethods
75
+ end
76
+
77
+ module ClassMethods
78
+ include AppOpticsAPMMethodProfiling::ClassMethods
79
+ end
80
+ end
@@ -0,0 +1,11 @@
1
+ require 'appoptics_apm/inst/rack'
2
+
3
+ module Oboe
4
+ class Rack < AppOpticsAPM::Rack
5
+ # This simply makes Oboe::Rack available (and a clone of AppOpticsAPM::Rack) for
6
+ # backward compatibility
7
+ #
8
+ # Provided for pre-existing apps (sinatra, padrino, grape etc..) that may still
9
+ # call `use Oboe::Rack`
10
+ end
11
+ end
@@ -0,0 +1,198 @@
1
+ # Copyright (c) 2016 SolarWinds, LLC.
2
+ # All rights reserved.
3
+
4
+ require 'thread'
5
+
6
+ # Disable docs and Camelcase warns since we're implementing
7
+ # an interface here. See OboeBase for details.
8
+ # rubocop:disable Style/Documentation, Style/MethodName
9
+ module AppOpticsAPM
10
+ extend AppOpticsAPMBase
11
+ include Oboe_metal
12
+
13
+ class Reporter
14
+ class << self
15
+ ##
16
+ # start
17
+ #
18
+ # Start the AppOpticsAPM Reporter
19
+ #
20
+ def start
21
+ return unless AppOpticsAPM.loaded
22
+
23
+ begin
24
+ options = []
25
+
26
+ ENV['APPOPTICS_REPORTER'] = 'file' if ENV.key?('APPOPTICS_GEM_TEST')
27
+
28
+ case ENV['APPOPTICS_REPORTER']
29
+ when 'file'
30
+ ENV['APPOPTICS_REPORTER_FILE'] = TRACE_FILE
31
+ when 'udp'
32
+ ENV['APPOPTICS_REPORTER_UDP'] = "#{AppOpticsAPM::Config[:reporter_host]}:#{AppOpticsAPM::Config[:reporter_port]}"
33
+ else # default is ssl, service_key is mandatory
34
+ return unless valid_service_key?
35
+ # Oboe will override these settings if there are env settings for them
36
+ options << AppOpticsAPM::Config[:service_key].to_s
37
+ options << AppOpticsAPM::Config[:hostname_alias].to_s
38
+ options << AppOpticsAPM::Config[:debug_level] unless AppOpticsAPM::Config[:debug_level].nil?
39
+ end
40
+ AppOpticsAPM.reporter = Oboe_metal::Reporter.new(*options)
41
+
42
+ # Only report __Init from here if we are not instrumenting a framework.
43
+ # Otherwise, frameworks will handle reporting __Init after full initialization
44
+ unless defined?(::Rails) || defined?(::Sinatra) || defined?(::Padrino) || defined?(::Grape)
45
+ AppOpticsAPM::API.report_init
46
+ end
47
+
48
+ rescue => e
49
+ $stderr.puts e.message
50
+ raise
51
+ end
52
+ end
53
+ alias :restart :start
54
+
55
+ def valid_service_key?
56
+ service_key = (ENV['APPOPTICS_SERVICE_KEY'] || AppOpticsAPM::Config[:service_key]).to_s
57
+ if service_key == ''
58
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] APPOPTICS_SERVICE_KEY not set. Cannot submit data.'
59
+ AppOpticsAPM.loaded = false
60
+ return false
61
+ elsif service_key !~ /^[0-9a-fA-F]{64}:[-.:_?\\\/\w ]{1,255}$/
62
+ AppOpticsAPM.logger.warn '[appoptics_apm/warn] APPOPTICS_SERVICE_KEY problem. No service name or api token in wrong format. Cannot submit data.'
63
+ AppOpticsAPM.loaded = false
64
+ return false
65
+ end
66
+ true
67
+ end
68
+ ##
69
+ # sendReport
70
+ #
71
+ # Send the report for the given event
72
+ #
73
+ def sendReport(evt)
74
+ AppOpticsAPM.reporter.sendReport(evt)
75
+ end
76
+
77
+ ##
78
+ # sendStatus
79
+ #
80
+ # Send the report for the given event
81
+ #
82
+ def sendStatus(evt, context = nil)
83
+ AppOpticsAPM.reporter.sendStatus(evt, context)
84
+ end
85
+
86
+ ##
87
+ # clear_all_traces
88
+ #
89
+ # Truncates the trace output file to zero
90
+ #
91
+ def clear_all_traces
92
+ File.truncate(TRACE_FILE, 0)
93
+ end
94
+
95
+ ##
96
+ # get_all_traces
97
+ #
98
+ # Retrieves all traces written to the trace file
99
+ #
100
+ def get_all_traces
101
+ io = File.open(TRACE_FILE, 'r')
102
+ contents = io.readlines(nil)
103
+
104
+ return contents if contents.empty?
105
+
106
+ traces = []
107
+
108
+ #
109
+ # We use Gem.loaded_spec because older versions of the bson
110
+ # gem didn't even have a version embedded in the gem. If the
111
+ # gem isn't in the bundle, it should rightfully error out
112
+ # anyways.
113
+ #
114
+ if Gem.loaded_specs['bson'].version.to_s < '4.0'
115
+ s = StringIO.new(contents[0])
116
+
117
+ until s.eof?
118
+ traces << if ::BSON.respond_to? :read_bson_document
119
+ BSON.read_bson_document(s)
120
+ else
121
+ BSON::Document.from_bson(s)
122
+ end
123
+ end
124
+ else
125
+ bbb = BSON::ByteBuffer.new(contents[0])
126
+ until bbb.length == 0
127
+ traces << Hash.from_bson(bbb)
128
+ end
129
+ end
130
+
131
+ traces
132
+ end
133
+ end
134
+ end
135
+
136
+ module EventUtil
137
+ def self.metadataString(evt)
138
+ evt.metadataString
139
+ end
140
+ end
141
+
142
+ class << self
143
+ def sample?(opts = {})
144
+ # Return false if no-op mode
145
+ return false unless AppOpticsAPM.loaded
146
+
147
+ # Assure defaults since SWIG enforces Strings
148
+ xtrace = opts[:xtrace] ? opts[:xtrace].to_s.strip : APPOPTICS_STR_BLANK
149
+
150
+ # the first arg has changed to be the service name, blank means to use the default (from the service key)
151
+ rv = AppOpticsAPM::Context.sampleRequest(APPOPTICS_STR_BLANK, xtrace)
152
+
153
+ if rv == 0
154
+ AppOpticsAPM.sample_rate = -1
155
+ AppOpticsAPM.sample_source = -1
156
+ false
157
+ else
158
+ # liboboe version > 1.3.1 returning a bit masked integer with SampleRate and
159
+ # source embedded
160
+ AppOpticsAPM.sample_rate = (rv & SAMPLE_RATE_MASK)
161
+ AppOpticsAPM.sample_source = (rv & SAMPLE_SOURCE_MASK) >> 24
162
+ true
163
+ end
164
+ rescue StandardError => e
165
+ AppOpticsAPM.logger.debug "[oboe/error] sample? error: #{e.inspect}"
166
+ false
167
+ end
168
+
169
+ def set_tracing_mode(mode)
170
+ return unless AppOpticsAPM.loaded
171
+
172
+ value = mode.to_sym
173
+
174
+ case value
175
+ when :never
176
+ AppOpticsAPM::Context.setTracingMode(APPOPTICS_TRACE_NEVER)
177
+
178
+ when :always
179
+ AppOpticsAPM::Context.setTracingMode(APPOPTICS_TRACE_ALWAYS)
180
+
181
+ else
182
+ AppOpticsAPM.logger.fatal "[oboe/error] Invalid tracing mode set: #{mode}"
183
+ AppOpticsAPM::Context.setTracingMode(APPOPTICS_TRACE_NEVER)
184
+ end
185
+ end
186
+
187
+ def set_sample_rate(rate)
188
+ return unless AppOpticsAPM.loaded
189
+
190
+ # Update liboboe with the new SampleRate value
191
+ AppOpticsAPM::Context.setDefaultSampleRate(rate.to_i)
192
+ end
193
+ end
194
+ end
195
+ # rubocop:enable Style/Documentation
196
+
197
+ AppOpticsAPM.loaded = true
198
+ AppOpticsAPM.config_lock = Mutex.new