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.
- checksums.yaml +7 -0
- data/.dockerignore +5 -0
- data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
- data/.gitignore +29 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +121 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Gemfile +29 -0
- data/LICENSE +193 -0
- data/README.md +393 -0
- data/Rakefile +230 -0
- data/appoptics_apm.gemspec +61 -0
- data/bin/appoptics_apm_config +15 -0
- data/build_gem.sh +15 -0
- data/build_gem_upload_to_packagecloud.sh +20 -0
- data/examples/SDK/01_basic_tracing.rb +67 -0
- data/examples/carrying_context.rb +220 -0
- data/ext/oboe_metal/extconf.rb +114 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/noop/noop.c +7 -0
- data/ext/oboe_metal/src/VERSION +1 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm.rb +76 -0
- data/lib/appoptics_apm/api.rb +20 -0
- data/lib/appoptics_apm/api/layerinit.rb +41 -0
- data/lib/appoptics_apm/api/logging.rb +375 -0
- data/lib/appoptics_apm/api/memcache.rb +37 -0
- data/lib/appoptics_apm/api/metrics.rb +55 -0
- data/lib/appoptics_apm/api/profiling.rb +203 -0
- data/lib/appoptics_apm/api/tracing.rb +53 -0
- data/lib/appoptics_apm/api/util.rb +122 -0
- data/lib/appoptics_apm/base.rb +230 -0
- data/lib/appoptics_apm/config.rb +254 -0
- data/lib/appoptics_apm/frameworks/grape.rb +97 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
- data/lib/appoptics_apm/frameworks/rails.rb +94 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
- data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
- data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +108 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +125 -0
- data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
- data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
- data/lib/appoptics_apm/inst/curb.rb +330 -0
- data/lib/appoptics_apm/inst/dalli.rb +85 -0
- data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
- data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
- data/lib/appoptics_apm/inst/excon.rb +125 -0
- data/lib/appoptics_apm/inst/faraday.rb +94 -0
- data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
- data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
- data/lib/appoptics_apm/inst/http.rb +73 -0
- data/lib/appoptics_apm/inst/httpclient.rb +174 -0
- data/lib/appoptics_apm/inst/memcached.rb +86 -0
- data/lib/appoptics_apm/inst/mongo.rb +246 -0
- data/lib/appoptics_apm/inst/mongo2.rb +225 -0
- data/lib/appoptics_apm/inst/moped.rb +466 -0
- data/lib/appoptics_apm/inst/rack.rb +199 -0
- data/lib/appoptics_apm/inst/redis.rb +275 -0
- data/lib/appoptics_apm/inst/resque.rb +151 -0
- data/lib/appoptics_apm/inst/rest-client.rb +48 -0
- data/lib/appoptics_apm/inst/sequel.rb +178 -0
- data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
- data/lib/appoptics_apm/inst/sidekiq-worker.rb +65 -0
- data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
- data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
- data/lib/appoptics_apm/instrumentation.rb +22 -0
- data/lib/appoptics_apm/legacy_method_profiling.rb +90 -0
- data/lib/appoptics_apm/loading.rb +65 -0
- data/lib/appoptics_apm/logger.rb +42 -0
- data/lib/appoptics_apm/method_profiling.rb +33 -0
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +26 -0
- data/lib/appoptics_apm/noop/metadata.rb +22 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
- data/lib/appoptics_apm/sdk/tracing.rb +315 -0
- data/lib/appoptics_apm/support.rb +119 -0
- data/lib/appoptics_apm/test.rb +94 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +319 -0
- data/lib/appoptics_apm/version.rb +15 -0
- data/lib/appoptics_apm/xtrace.rb +103 -0
- data/lib/joboe_metal.rb +212 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe/README +2 -0
- data/lib/oboe/backward_compatibility.rb +80 -0
- data/lib/oboe/inst/rack.rb +11 -0
- data/lib/oboe_metal.rb +198 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
- data/yardoc_frontpage.md +26 -0
- 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
|
data/lib/joboe_metal.rb
ADDED
|
@@ -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
|
data/lib/oboe.rb
ADDED
data/lib/oboe/README
ADDED
|
@@ -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
|
data/lib/oboe_metal.rb
ADDED
|
@@ -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
|