appoptics_apm-zearn 4.13.1
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/.github/workflows/build_and_release_gem.yml +103 -0
- data/.github/workflows/build_for_packagecloud.yml +70 -0
- data/.github/workflows/docker-images.yml +47 -0
- data/.github/workflows/run_cpluplus_tests.yml +73 -0
- data/.github/workflows/run_tests.yml +168 -0
- data/.github/workflows/scripts/test_install.rb +23 -0
- data/.github/workflows/swig/swig-v4.0.2.tar.gz +0 -0
- data/.github/workflows/test_on_4_linux.yml +159 -0
- data/.gitignore +36 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +130 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +33 -0
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/README.md +393 -0
- data/appoptics_apm.gemspec +70 -0
- data/bin/appoptics_apm_config +15 -0
- data/examples/prepend.rb +13 -0
- data/examples/sdk_examples.rb +158 -0
- data/ext/oboe_metal/README.md +69 -0
- data/ext/oboe_metal/extconf.rb +151 -0
- data/ext/oboe_metal/lib/.keep +0 -0
- data/ext/oboe_metal/lib/liboboe-1.0-alpine-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/lib/liboboe-1.0-x86_64.so.0.0.0.sha256 +1 -0
- data/ext/oboe_metal/noop/noop.c +8 -0
- data/ext/oboe_metal/src/README.md +6 -0
- data/ext/oboe_metal/src/VERSION +2 -0
- data/ext/oboe_metal/src/bson/bson.h +220 -0
- data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
- data/ext/oboe_metal/src/frames.cc +246 -0
- data/ext/oboe_metal/src/frames.h +40 -0
- data/ext/oboe_metal/src/init_appoptics_apm.cc +21 -0
- data/ext/oboe_metal/src/logging.cc +95 -0
- data/ext/oboe_metal/src/logging.h +35 -0
- data/ext/oboe_metal/src/oboe.h +1156 -0
- data/ext/oboe_metal/src/oboe_api.cpp +652 -0
- data/ext/oboe_metal/src/oboe_api.hpp +431 -0
- data/ext/oboe_metal/src/oboe_debug.h +59 -0
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +7329 -0
- data/ext/oboe_metal/src/profiling.cc +435 -0
- data/ext/oboe_metal/src/profiling.h +78 -0
- data/ext/oboe_metal/test/CMakeLists.txt +53 -0
- data/ext/oboe_metal/test/FindGMock.cmake +43 -0
- data/ext/oboe_metal/test/README.md +56 -0
- data/ext/oboe_metal/test/frames_test.cc +164 -0
- data/ext/oboe_metal/test/profiling_test.cc +93 -0
- data/ext/oboe_metal/test/ruby_inc_dir.rb +8 -0
- data/ext/oboe_metal/test/ruby_prefix.rb +8 -0
- data/ext/oboe_metal/test/ruby_test_helper.rb +67 -0
- data/ext/oboe_metal/test/test.h +11 -0
- data/ext/oboe_metal/test/test_main.cc +32 -0
- data/init.rb +4 -0
- data/lib/appoptics_apm/api/layerinit.rb +41 -0
- data/lib/appoptics_apm/api/logging.rb +381 -0
- data/lib/appoptics_apm/api/memcache.rb +37 -0
- data/lib/appoptics_apm/api/metrics.rb +63 -0
- data/lib/appoptics_apm/api/tracing.rb +57 -0
- data/lib/appoptics_apm/api/util.rb +120 -0
- data/lib/appoptics_apm/api.rb +21 -0
- data/lib/appoptics_apm/base.rb +231 -0
- data/lib/appoptics_apm/config.rb +299 -0
- data/lib/appoptics_apm/frameworks/grape.rb +98 -0
- data/lib/appoptics_apm/frameworks/padrino.rb +78 -0
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -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_controller6.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 +88 -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 +114 -0
- data/lib/appoptics_apm/frameworks/rails/inst/logger_formatters.rb +27 -0
- data/lib/appoptics_apm/frameworks/rails.rb +100 -0
- data/lib/appoptics_apm/frameworks/sinatra.rb +96 -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 +332 -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 +106 -0
- data/lib/appoptics_apm/inst/graphql.rb +240 -0
- data/lib/appoptics_apm/inst/grpc_client.rb +159 -0
- data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
- data/lib/appoptics_apm/inst/http.rb +81 -0
- data/lib/appoptics_apm/inst/httpclient.rb +174 -0
- data/lib/appoptics_apm/inst/logger_formatter.rb +50 -0
- data/lib/appoptics_apm/inst/logging_log_event.rb +28 -0
- data/lib/appoptics_apm/inst/lumberjack_formatter.rb +13 -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 +182 -0
- data/lib/appoptics_apm/inst/rack_cache.rb +35 -0
- data/lib/appoptics_apm/inst/redis.rb +274 -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 +66 -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/loading.rb +65 -0
- data/lib/appoptics_apm/logger.rb +14 -0
- data/lib/appoptics_apm/noop/README.md +9 -0
- data/lib/appoptics_apm/noop/context.rb +27 -0
- data/lib/appoptics_apm/noop/metadata.rb +25 -0
- data/lib/appoptics_apm/noop/profiling.rb +21 -0
- data/lib/appoptics_apm/oboe_init_options.rb +211 -0
- data/lib/appoptics_apm/ruby.rb +35 -0
- data/lib/appoptics_apm/sdk/current_trace.rb +77 -0
- data/lib/appoptics_apm/sdk/custom_metrics.rb +94 -0
- data/lib/appoptics_apm/sdk/logging.rb +37 -0
- data/lib/appoptics_apm/sdk/tracing.rb +434 -0
- data/lib/appoptics_apm/support/profiling.rb +18 -0
- data/lib/appoptics_apm/support/transaction_metrics.rb +67 -0
- data/lib/appoptics_apm/support/transaction_settings.rb +219 -0
- data/lib/appoptics_apm/support/x_trace_options.rb +110 -0
- data/lib/appoptics_apm/support_report.rb +119 -0
- data/lib/appoptics_apm/test.rb +95 -0
- data/lib/appoptics_apm/thread_local.rb +26 -0
- data/lib/appoptics_apm/util.rb +326 -0
- data/lib/appoptics_apm/version.rb +16 -0
- data/lib/appoptics_apm/xtrace.rb +115 -0
- data/lib/appoptics_apm.rb +77 -0
- data/lib/joboe_metal.rb +212 -0
- data/lib/oboe.rb +7 -0
- data/lib/oboe_metal.rb +172 -0
- data/lib/rails/generators/appoptics_apm/install_generator.rb +47 -0
- data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +425 -0
- data/log/.keep +0 -0
- data/yardoc_frontpage.md +26 -0
- metadata +231 -0
@@ -0,0 +1,381 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
#++
|
5
|
+
|
6
|
+
# Make sure Set is loaded if possible.
|
7
|
+
begin
|
8
|
+
require 'set'
|
9
|
+
rescue LoadError
|
10
|
+
class Set; end # :nodoc:
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
module AppOpticsAPM
|
15
|
+
module API
|
16
|
+
##
|
17
|
+
# This modules provides the X-Trace logging facilities.
|
18
|
+
#
|
19
|
+
# These are the lower level methods, please see AppOpticsAPM::SDK
|
20
|
+
# for the higher level methods
|
21
|
+
#
|
22
|
+
# If using these directly make sure to always match a start/end and entry/exit to
|
23
|
+
# avoid broken traces.
|
24
|
+
module Logging
|
25
|
+
@@ints_or_nil = [Integer, Float, NilClass, String]
|
26
|
+
@@ints_or_nil << Fixnum unless RUBY_VERSION >= '2.4'
|
27
|
+
|
28
|
+
##
|
29
|
+
# Public: Report an event in an active trace.
|
30
|
+
#
|
31
|
+
# ==== Arguments
|
32
|
+
#
|
33
|
+
# * +layer+ - The layer the reported event belongs to
|
34
|
+
# * +label+ - The label for the reported event. See SDK documentation for reserved labels and usage.
|
35
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
36
|
+
# * +event+ - An event to be used instead of generating a new one (see also start_trace_with_target)
|
37
|
+
#
|
38
|
+
# ==== Example
|
39
|
+
#
|
40
|
+
# AppOpticsAPM::API.log('logical_layer', 'entry')
|
41
|
+
# AppOpticsAPM::API.log('logical_layer', 'info', { :list_length => 20 })
|
42
|
+
# AppOpticsAPM::API.log('logical_layer', 'exit')
|
43
|
+
#
|
44
|
+
# Returns nothing.
|
45
|
+
def log(layer, label, opts = {}, event = nil)
|
46
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
47
|
+
|
48
|
+
event ||= AppOpticsAPM::Context.createEvent
|
49
|
+
log_event(layer, label, event, opts)
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Public: Report an exception.
|
54
|
+
#
|
55
|
+
# ==== Arguments
|
56
|
+
#
|
57
|
+
# * +layer+ - The layer the reported event belongs to
|
58
|
+
# * +exception+ - The exception to report, responds to :message and :backtrace(optional)
|
59
|
+
# * +opts+ - Custom params if you want to log extra information
|
60
|
+
#
|
61
|
+
# ==== Example
|
62
|
+
#
|
63
|
+
# begin
|
64
|
+
# my_iffy_method
|
65
|
+
# rescue Exception => e
|
66
|
+
# AppOpticsAPM::API.log_exception('rails', e, { user: user_id })
|
67
|
+
# raise
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# Returns nothing.
|
71
|
+
def log_exception(layer, exception, opts = {})
|
72
|
+
return AppOpticsAPM::Context.toString if !AppOpticsAPM.tracing? || exception.instance_variable_get(:@exn_logged)
|
73
|
+
|
74
|
+
unless exception
|
75
|
+
AppOpticsAPM.logger.debug '[appoptics_apm/debug] log_exception called with nil exception'
|
76
|
+
return AppOpticsAPM::Context.toString
|
77
|
+
end
|
78
|
+
|
79
|
+
exception.message << exception.class.name if exception.message.length < 4
|
80
|
+
opts.merge!(:Spec => 'error',
|
81
|
+
:ErrorClass => exception.class.name,
|
82
|
+
:ErrorMsg => exception.message)
|
83
|
+
|
84
|
+
if exception.respond_to?(:backtrace) && exception.backtrace
|
85
|
+
opts.merge!(:Backtrace => exception.backtrace.join("\r\n"))
|
86
|
+
end
|
87
|
+
|
88
|
+
exception.instance_variable_set(:@exn_logged, true)
|
89
|
+
log(layer, :error, opts)
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Public: Start a trace depending on TransactionSettings
|
94
|
+
# or decide whether or not to start a trace, and report an entry event
|
95
|
+
# appropriately.
|
96
|
+
#
|
97
|
+
# ==== Arguments
|
98
|
+
#
|
99
|
+
# * +layer+ - The layer the reported event belongs to
|
100
|
+
# * +xtrace+ - An xtrace metadata string, or nil. Used for cross-application tracing.
|
101
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
102
|
+
# * +settings+ - An instance of TransactionSettings
|
103
|
+
#
|
104
|
+
# ==== Example
|
105
|
+
#
|
106
|
+
# AppOpticsAPM::API.log_start(:layer_name, nil, { :id => @user.id })
|
107
|
+
#
|
108
|
+
# Returns an xtrace metadata string if we are tracing
|
109
|
+
#
|
110
|
+
def log_start(layer, xtrace = nil, opts = {}, settings = nil)
|
111
|
+
return unless AppOpticsAPM.loaded
|
112
|
+
|
113
|
+
# check if tracing decision is already in effect and a Context created
|
114
|
+
return log_entry(layer, opts) if AppOpticsAPM::Context.isValid
|
115
|
+
|
116
|
+
# This is a bit ugly, but here is the best place to reset the layer_op thread local var.
|
117
|
+
AppOpticsAPM.layer_op = nil
|
118
|
+
|
119
|
+
xtrace = nil unless AppOpticsAPM::XTrace.valid?(xtrace)
|
120
|
+
|
121
|
+
settings ||= AppOpticsAPM::TransactionSettings.new(nil, xtrace)
|
122
|
+
|
123
|
+
if settings.do_sample
|
124
|
+
opts[:SampleRate] = settings.rate
|
125
|
+
opts[:SampleSource] = settings.source
|
126
|
+
|
127
|
+
AppOpticsAPM::XTrace.set_sampled(xtrace) if xtrace
|
128
|
+
event = create_start_event(xtrace)
|
129
|
+
log_event(layer, :entry, event, opts)
|
130
|
+
else
|
131
|
+
create_nontracing_context(xtrace)
|
132
|
+
AppOpticsAPM::Context.toString
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Public: Report an exit event and potentially clear the tracing context.
|
138
|
+
#
|
139
|
+
# ==== Arguments
|
140
|
+
#
|
141
|
+
# * +layer+ - The layer the reported event belongs to
|
142
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
143
|
+
#
|
144
|
+
# ==== Example
|
145
|
+
#
|
146
|
+
# AppOpticsAPM::API.log_end(:layer_name, { :id => @user.id })
|
147
|
+
#
|
148
|
+
# Returns an xtrace metadata string if we are tracing
|
149
|
+
#
|
150
|
+
def log_end(layer, opts = {}, event = nil)
|
151
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
152
|
+
|
153
|
+
event ||= AppOpticsAPM::Context.createEvent
|
154
|
+
log_event(layer, :exit, event, opts)
|
155
|
+
ensure
|
156
|
+
# FIXME has_incoming_context commented out, it has importance for JRuby only but breaks Ruby tests
|
157
|
+
AppOpticsAPM::Context.clear # unless AppOpticsAPM.has_incoming_context?
|
158
|
+
AppOpticsAPM.transaction_name = nil
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Public: Log an entry event
|
163
|
+
#
|
164
|
+
# A helper method to create and log an entry event
|
165
|
+
#
|
166
|
+
# ==== Arguments
|
167
|
+
#
|
168
|
+
# * +layer+ - The layer the reported event belongs to
|
169
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
170
|
+
# * +op+ - To identify the current operation being traced. Used to avoid double tracing recursive calls.
|
171
|
+
#
|
172
|
+
# ==== Example
|
173
|
+
#
|
174
|
+
# AppOpticsAPM::API.log_entry(:layer_name, { :id => @user.id })
|
175
|
+
#
|
176
|
+
# Returns an xtrace metadata string if we are tracing
|
177
|
+
#
|
178
|
+
def log_entry(layer, opts = {}, op = nil) #, event = nil)
|
179
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
180
|
+
|
181
|
+
if op
|
182
|
+
# check if re-entry but also add op to list for log_exit
|
183
|
+
re_entry = AppOpticsAPM.layer_op&.last == op.to_sym
|
184
|
+
AppOpticsAPM.layer_op = (AppOpticsAPM.layer_op || []) << op.to_sym
|
185
|
+
return AppOpticsAPM::Context.toString if re_entry
|
186
|
+
end
|
187
|
+
|
188
|
+
event ||= AppOpticsAPM::Context.createEvent
|
189
|
+
log_event(layer, :entry, event, opts)
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Public: Log an info event
|
194
|
+
#
|
195
|
+
# A helper method to create and log an info event
|
196
|
+
#
|
197
|
+
# ==== Arguments
|
198
|
+
#
|
199
|
+
# * +layer+ - The layer the reported event belongs to
|
200
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
201
|
+
#
|
202
|
+
# ==== Example
|
203
|
+
#
|
204
|
+
# AppOpticsAPM::API.log_info(:layer_name, { :id => @user.id })
|
205
|
+
#
|
206
|
+
# Returns an xtrace metadata string if we are tracing
|
207
|
+
#
|
208
|
+
def log_info(layer, opts = {})
|
209
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
210
|
+
|
211
|
+
opts[:Spec] = 'info'
|
212
|
+
log_event(layer, :info, AppOpticsAPM::Context.createEvent, opts)
|
213
|
+
end
|
214
|
+
|
215
|
+
##
|
216
|
+
# Public: Log an exit event
|
217
|
+
#
|
218
|
+
# A helper method to create and log an exit event
|
219
|
+
#
|
220
|
+
# ==== Arguments
|
221
|
+
#
|
222
|
+
# * +layer+ - The layer the reported event belongs to
|
223
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
224
|
+
# * +op+ - Used to avoid double tracing recursive calls, needs to be the same in +log_exit+ that corresponds to a
|
225
|
+
# +log_entry+
|
226
|
+
#
|
227
|
+
# ==== Example
|
228
|
+
#
|
229
|
+
# AppOpticsAPM::API.log_exit(:layer_name, { :id => @user.id })
|
230
|
+
#
|
231
|
+
# Returns an xtrace metadata string if we are tracing
|
232
|
+
def log_exit(layer, opts = {}, op = nil)
|
233
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
234
|
+
|
235
|
+
if op
|
236
|
+
if AppOpticsAPM.layer_op&.last == op.to_sym
|
237
|
+
AppOpticsAPM.layer_op.pop
|
238
|
+
else
|
239
|
+
AppOpticsAPM.logger.warn "[ruby/logging] op parameter of exit event doesn't correspond to an entry event op"
|
240
|
+
end
|
241
|
+
# check if the next op is the same, don't log event if so
|
242
|
+
return AppOpticsAPM::Context.toString if AppOpticsAPM.layer_op&.last == op.to_sym
|
243
|
+
end
|
244
|
+
|
245
|
+
log_event(layer, :exit, AppOpticsAPM::Context.createEvent, opts)
|
246
|
+
end
|
247
|
+
|
248
|
+
##
|
249
|
+
# Public: Log an exit event from multiple requests
|
250
|
+
#
|
251
|
+
# A helper method to create and log an info event
|
252
|
+
# If we return from a request that faned out multiple requests
|
253
|
+
# we can add the collected X-Traces to the exit event
|
254
|
+
#
|
255
|
+
# ==== Arguments
|
256
|
+
#
|
257
|
+
# * +layer+ - The layer the reported event belongs to
|
258
|
+
# * +traces+ - An array with X-Trace strings returned from the requests
|
259
|
+
#
|
260
|
+
def log_multi_exit(layer, traces)
|
261
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
262
|
+
task_id = AppOpticsAPM::XTrace.task_id(AppOpticsAPM::Context.toString)
|
263
|
+
event = AppOpticsAPM::Context.createEvent
|
264
|
+
traces.each do |trace|
|
265
|
+
event.addEdgeStr(trace) if AppOpticsAPM::XTrace.task_id(trace) == task_id
|
266
|
+
end
|
267
|
+
log_event(layer, :exit, event)
|
268
|
+
end
|
269
|
+
|
270
|
+
##
|
271
|
+
#:nodoc:
|
272
|
+
# Internal: Reports agent init to the collector
|
273
|
+
#
|
274
|
+
# ==== Arguments
|
275
|
+
#
|
276
|
+
# * +layer+ - The layer the reported event belongs to
|
277
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event
|
278
|
+
def log_init(layer = :rack, opts = {})
|
279
|
+
context = AppOpticsAPM::Metadata.makeRandom
|
280
|
+
return AppOpticsAPM::Context.toString unless context.isValid
|
281
|
+
|
282
|
+
event = context.createEvent
|
283
|
+
event.addInfo(APPOPTICS_STR_LAYER, layer.to_s)
|
284
|
+
event.addInfo(APPOPTICS_STR_LABEL, 'single')
|
285
|
+
opts.each do |k, v|
|
286
|
+
event.addInfo(k, v.to_s)
|
287
|
+
end
|
288
|
+
|
289
|
+
AppOpticsAPM::Reporter.sendStatus(event, context)
|
290
|
+
AppOpticsAPM::Context.toString
|
291
|
+
end
|
292
|
+
|
293
|
+
private
|
294
|
+
|
295
|
+
##
|
296
|
+
#:nodoc:
|
297
|
+
# @private
|
298
|
+
# Internal: Report an event.
|
299
|
+
#
|
300
|
+
# ==== Arguments
|
301
|
+
#
|
302
|
+
# * +layer+ - The layer the reported event belongs to
|
303
|
+
# * +label+ - The label for the reported event. See API documentation for reserved labels and usage.
|
304
|
+
# * +event+ - The pre-existing AppOpticsAPM context event. See AppOpticsAPM::Context.createEvent
|
305
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
306
|
+
#
|
307
|
+
# ==== Example
|
308
|
+
#
|
309
|
+
# entry = AppOpticsAPM::Context.createEvent
|
310
|
+
# AppOpticsAPM::API.log_event(:layer_name, 'entry', entry_event, { :id => @user.id })
|
311
|
+
#
|
312
|
+
# exit_event = AppOpticsAPM::Context.createEvent
|
313
|
+
# exit_event.addEdge(entry.getMetadata)
|
314
|
+
# AppOpticsAPM::API.log_event(:layer_name, 'exit', exit_event, { :id => @user.id })
|
315
|
+
#
|
316
|
+
def log_event(layer, label, event, opts = {})
|
317
|
+
event.addInfo(APPOPTICS_STR_LAYER, layer.to_s.freeze) if layer
|
318
|
+
event.addInfo(APPOPTICS_STR_LABEL, label.to_s.freeze)
|
319
|
+
|
320
|
+
AppOpticsAPM.layer = layer.to_sym if label == :entry
|
321
|
+
AppOpticsAPM.layer = nil if label == :exit
|
322
|
+
|
323
|
+
opts.each do |k, v|
|
324
|
+
value = nil
|
325
|
+
|
326
|
+
next unless valid_key? k
|
327
|
+
|
328
|
+
if @@ints_or_nil.include?(v.class)
|
329
|
+
value = v
|
330
|
+
elsif v.class == Set
|
331
|
+
value = v.to_a.to_s
|
332
|
+
else
|
333
|
+
value = v.to_s if v.respond_to?(:to_s)
|
334
|
+
end
|
335
|
+
|
336
|
+
begin
|
337
|
+
event.addInfo(k.to_s, value)
|
338
|
+
rescue ArgumentError => e
|
339
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] Couldn't add event KV: #{k} => #{v.class}"
|
340
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{e.message}"
|
341
|
+
end
|
342
|
+
end if !opts.nil? && opts.any?
|
343
|
+
|
344
|
+
AppOpticsAPM::Reporter.sendReport(event)
|
345
|
+
AppOpticsAPM::Context.toString
|
346
|
+
end
|
347
|
+
|
348
|
+
def create_start_event(xtrace = nil)
|
349
|
+
if AppOpticsAPM::XTrace.sampled?(xtrace)
|
350
|
+
md = AppOpticsAPM::Metadata.fromString(xtrace)
|
351
|
+
AppOpticsAPM::Context.fromString(xtrace)
|
352
|
+
md.createEvent
|
353
|
+
else
|
354
|
+
md = AppOpticsAPM::Metadata.makeRandom(true)
|
355
|
+
AppOpticsAPM::Context.set(md)
|
356
|
+
AppOpticsAPM::Event.startTrace(md)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
public
|
361
|
+
|
362
|
+
def create_nontracing_context(xtrace)
|
363
|
+
if AppOpticsAPM::XTrace.valid?(xtrace)
|
364
|
+
# continue valid incoming xtrace
|
365
|
+
# use it for current context, ensuring sample bit is not set
|
366
|
+
AppOpticsAPM::XTrace.unset_sampled(xtrace)
|
367
|
+
AppOpticsAPM::Context.fromString(xtrace)
|
368
|
+
else
|
369
|
+
# discard invalid incoming xtrace
|
370
|
+
# create a new context, ensuring sample bit not set
|
371
|
+
md = AppOpticsAPM::Metadata.makeRandom(false)
|
372
|
+
AppOpticsAPM::Context.fromString(md.toString)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# need to set the context to public, otherwise the following `extends` will be private in api.rb
|
377
|
+
public
|
378
|
+
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
#++
|
5
|
+
|
6
|
+
# TODO remove Memcache from API and into some Util module to be included in Modules that need
|
7
|
+
# ____ these methods
|
8
|
+
module AppOpticsAPM
|
9
|
+
module API
|
10
|
+
##
|
11
|
+
# Utility methods for the Memcache instrumentation
|
12
|
+
# currently used by dalli and memcached
|
13
|
+
module Memcache #:nodoc:
|
14
|
+
MEMCACHE_OPS = %w(add append cas decr decrement delete fetch get incr increment prepend replace set)
|
15
|
+
|
16
|
+
def memcache_hit?(result)
|
17
|
+
result.nil? ? 0 : 1
|
18
|
+
end
|
19
|
+
|
20
|
+
def remote_host(key)
|
21
|
+
return unless defined?(Lib.memcached_server_by_key) &&
|
22
|
+
defined?(@struct) && defined?(is_unix_socket?)
|
23
|
+
|
24
|
+
server_as_array = Lib.memcached_server_by_key(@struct, key.to_s)
|
25
|
+
|
26
|
+
return unless server_as_array.is_a?(Array)
|
27
|
+
|
28
|
+
server = server_as_array.first
|
29
|
+
if is_unix_socket?(server)
|
30
|
+
'localhost'
|
31
|
+
elsif defined?(server.hostname)
|
32
|
+
server.hostname
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright (c) 2019 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module API
|
6
|
+
module Metrics
|
7
|
+
|
8
|
+
##
|
9
|
+
# Internal: method to send duration for a transaction
|
10
|
+
# it checks if it can send metrics with the current transaction name
|
11
|
+
# or a default transaction name and sets the transaction name accordingly
|
12
|
+
#
|
13
|
+
# === Arguments:
|
14
|
+
#
|
15
|
+
# * +span+ the name of the current span (used to construct a transaction name if none is defined)
|
16
|
+
# * +kvs+ A hash containing key/value pairs, only the value of :TransactionName will be relevant
|
17
|
+
#
|
18
|
+
# === Returns:
|
19
|
+
# The result of the block.
|
20
|
+
#
|
21
|
+
# === Assigns:
|
22
|
+
# The transaction_name to kvs[:TransactionName]
|
23
|
+
|
24
|
+
def send_metrics(span, kvs)
|
25
|
+
start = Time.now
|
26
|
+
yield
|
27
|
+
ensure
|
28
|
+
# TODO send_metrics is currently used in grpc, sdk
|
29
|
+
# ____ the error (0,1) would have to be returned from yield
|
30
|
+
error = 0
|
31
|
+
duration = (1000 * 1000 * (Time.now - start)).to_i
|
32
|
+
transaction_name = determine_transaction_name(span, kvs)
|
33
|
+
kvs[:TransactionName] = AppOpticsAPM::Span.createSpan(transaction_name, nil, duration, error)
|
34
|
+
AppOpticsAPM.transaction_name = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
##
|
40
|
+
# Determine the transaction name to be set on the trace.
|
41
|
+
#
|
42
|
+
# === Argument:
|
43
|
+
# * +span+ the name of the current span (used to construct a transaction name if none is defined)
|
44
|
+
# * +kvs+ (hash, optional) the hash that may have values for 'Controller' and 'Action'
|
45
|
+
#
|
46
|
+
# === Returns:
|
47
|
+
# (string) the determined transaction name
|
48
|
+
#
|
49
|
+
def determine_transaction_name(span, kvs = {})
|
50
|
+
if AppOpticsAPM.transaction_name
|
51
|
+
AppOpticsAPM.transaction_name
|
52
|
+
elsif kvs['Controller'] && kvs['Action']
|
53
|
+
[kvs['Controller'], kvs['Action']].join('.')
|
54
|
+
elsif kvs[:Controller] && kvs[:Action]
|
55
|
+
[kvs[:Controller], kvs[:Action]].join('.')
|
56
|
+
else
|
57
|
+
"custom-#{span}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
module API
|
8
|
+
##
|
9
|
+
# Provides the higher-level tracing interface for the API
|
10
|
+
#
|
11
|
+
# The tracing methods have been moved to AppOpticsAPM::SDK and AppOpticsAPM::API extends all methods from the SDK
|
12
|
+
# except for start_trace.
|
13
|
+
# AppOpticsAPM::API.start_trace is kept for backwards compatibility because it returns an array
|
14
|
+
# whereas AppOpticsAPM::SDK.start_trace will only return the result of the block.
|
15
|
+
#
|
16
|
+
|
17
|
+
module Tracing
|
18
|
+
|
19
|
+
# Public: Collect metrics and start tracing a given block of code. A
|
20
|
+
# trace will be started depending on configuration and probability.
|
21
|
+
# Detect any exceptions thrown by the block and report errors.
|
22
|
+
#
|
23
|
+
# When start_trace returns control to the calling context, the trace will be
|
24
|
+
# completed and the tracing context will be cleared.
|
25
|
+
#
|
26
|
+
# ==== Arguments
|
27
|
+
#
|
28
|
+
# * +span+ - name for the span to be used as label in the trace view
|
29
|
+
# * +xtrace+ - (optional) incoming X-Trace identifier to be continued
|
30
|
+
# * +opts+ - (optional) hash containing key/value pairs that will be reported along
|
31
|
+
# with the first event of this span
|
32
|
+
#
|
33
|
+
# ==== Example
|
34
|
+
#
|
35
|
+
# def handle_request(request, response)
|
36
|
+
# # ... code that modifies request and response ...
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def handle_request_with_appoptics(request, response)
|
40
|
+
# start_trace('custom_span', nil, :TransactionName => 'handle_request') do
|
41
|
+
# handle_request(request, response)
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# Returns an array with the result of the block and the last xtrace used
|
46
|
+
def start_trace(span, xtrace = nil, opts = {})
|
47
|
+
target = {}
|
48
|
+
[start_trace_with_target(span, xtrace, target, opts) { yield }, target['X-Trace']]
|
49
|
+
end
|
50
|
+
|
51
|
+
def profile_method(*args)
|
52
|
+
AppOpticsAPM.logger.warn("DEPRECATED: AppOpticsAPM::API.profile_method is deprecated. Use: AppOpticsAPM::SDK::trace_method")
|
53
|
+
AppOpticsAPM::SDK.trace_method(*args)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
module AppOpticsAPM
|
9
|
+
module API
|
10
|
+
##
|
11
|
+
# General utility methods for the gem
|
12
|
+
module Util #:nodoc:
|
13
|
+
BACKTRACE_CUTOFF = 200
|
14
|
+
|
15
|
+
# Internal: Check whether the provided key is reserved or not. Reserved
|
16
|
+
# keys are either keys that are handled by liboboe calls or the appoptics_apm gem.
|
17
|
+
#
|
18
|
+
# key - the key to check.
|
19
|
+
#
|
20
|
+
# Return a boolean indicating whether or not key is reserved.
|
21
|
+
def valid_key?(key)
|
22
|
+
![:Label, :Layer, :Edge, :Timestamp, :Timestamp_u].include?(key.to_sym)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Internal: Get the current backtrace.
|
26
|
+
#
|
27
|
+
# from - int, from position in array of backtraces
|
28
|
+
# to - int, end position in array of backtraces, can be negative to count from the end
|
29
|
+
#
|
30
|
+
# Returns a string with each frame of the backtrace separated by '\r\n'.
|
31
|
+
#
|
32
|
+
def backtrace(from = 0, to = -1)
|
33
|
+
bt = Kernel.caller
|
34
|
+
trim_backtrace(bt[from..to]).join("\r\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Internal: Trim a backtrace to a manageable size
|
38
|
+
#
|
39
|
+
# backtrace - the backtrace (an array of stack frames/from Kernel.caller)
|
40
|
+
#
|
41
|
+
# Returns a trimmed backtrace
|
42
|
+
def trim_backtrace(backtrace)
|
43
|
+
return backtrace unless backtrace.is_a?(Array) && backtrace.size > BACKTRACE_CUTOFF
|
44
|
+
|
45
|
+
# Trim backtraces by getting the first 180 and last 20 lines
|
46
|
+
backtrace[0, 180] + ['...[snip]...'] + backtrace[backtrace.size - 20, 20]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Internal: Check if a host is blacklisted from tracing
|
50
|
+
#
|
51
|
+
# addr_port - the addr_port from Net::HTTP although this method
|
52
|
+
# can be used from any component in reality
|
53
|
+
#
|
54
|
+
# Returns a boolean on blacklisted state
|
55
|
+
def blacklisted?(addr_port)
|
56
|
+
return false unless AppOpticsAPM::Config.blacklist
|
57
|
+
|
58
|
+
# Ensure that the blacklist is an array
|
59
|
+
unless AppOpticsAPM::Config.blacklist.is_a?(Array)
|
60
|
+
val = AppOpticsAPM::Config[:blacklist]
|
61
|
+
AppOpticsAPM::Config[:blacklist] = [val.to_s]
|
62
|
+
end
|
63
|
+
|
64
|
+
AppOpticsAPM::Config.blacklist.each do |h|
|
65
|
+
return true if addr_port.to_s.match(h.to_s)
|
66
|
+
end
|
67
|
+
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
# Internal: Pretty print a list of arguments for reporting
|
72
|
+
#
|
73
|
+
# args - the list of arguments to work on
|
74
|
+
#
|
75
|
+
# Returns a pretty string representation of arguments
|
76
|
+
def pps(*args)
|
77
|
+
old_out = $stdout
|
78
|
+
begin
|
79
|
+
s = StringIO.new
|
80
|
+
$stdout = s
|
81
|
+
pp(*args)
|
82
|
+
ensure
|
83
|
+
$stdout = old_out
|
84
|
+
end
|
85
|
+
s.string
|
86
|
+
end
|
87
|
+
|
88
|
+
# Internal: Determine a string to report representing klass
|
89
|
+
#
|
90
|
+
# args - an instance of a Class, a Class or a Module
|
91
|
+
#
|
92
|
+
# Returns a string representation of klass
|
93
|
+
def get_class_name(klass)
|
94
|
+
kv = {}
|
95
|
+
|
96
|
+
if klass.to_s =~ /::/
|
97
|
+
klass.class.to_s.rpartition('::').last
|
98
|
+
else
|
99
|
+
if klass.is_a?(Class) && klass.is_a?(Module)
|
100
|
+
# Class
|
101
|
+
kv['Class'] = klass.to_s
|
102
|
+
|
103
|
+
elsif !klass.is_a?(Class) && !klass.is_a?(Module)
|
104
|
+
# Class instance
|
105
|
+
kv['Class'] = klass.class.to_s
|
106
|
+
|
107
|
+
else
|
108
|
+
# Module
|
109
|
+
kv['Module'] = klass.to_s
|
110
|
+
end
|
111
|
+
end
|
112
|
+
kv
|
113
|
+
end
|
114
|
+
|
115
|
+
def xtrace_v2?(xtr)
|
116
|
+
xtr && xtr.start_with?('2B')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
|
6
|
+
module API
|
7
|
+
extend AppOpticsAPM::API::Logging
|
8
|
+
extend AppOpticsAPM::API::Metrics
|
9
|
+
extend AppOpticsAPM::API::LayerInit
|
10
|
+
extend AppOpticsAPM::API::Util
|
11
|
+
|
12
|
+
require_relative './sdk/tracing'
|
13
|
+
require_relative './sdk/custom_metrics'
|
14
|
+
require_relative './sdk/current_trace'
|
15
|
+
require_relative './sdk/logging' # to make sure it is loaded <- not very elegant
|
16
|
+
|
17
|
+
extend AppOpticsAPM::SDK::Tracing
|
18
|
+
extend AppOpticsAPM::SDK::CustomMetrics
|
19
|
+
extend AppOpticsAPM::API::Tracing
|
20
|
+
end
|
21
|
+
end
|