solarwinds_apm 5.0.0
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 +112 -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 +155 -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 +161 -0
- data/.gitignore +39 -0
- data/.rubocop.yml +29 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +769 -0
- data/CONFIG.md +31 -0
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/README.md +383 -0
- data/bin/solarwinds_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 +141 -0
- data/ext/oboe_metal/extconf_local.rb +75 -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 +247 -0
- data/ext/oboe_metal/src/frames.h +40 -0
- data/ext/oboe_metal/src/init_solarwinds_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 +1169 -0
- data/ext/oboe_metal/src/oboe_api.cpp +658 -0
- data/ext/oboe_metal/src/oboe_api.hpp +433 -0
- data/ext/oboe_metal/src/oboe_debug.h +59 -0
- data/ext/oboe_metal/src/oboe_swig_wrap.cc +7562 -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/oboe.rb +7 -0
- data/lib/oboe_metal.rb +172 -0
- data/lib/rails/generators/solarwinds_apm/install_generator.rb +47 -0
- data/lib/rails/generators/solarwinds_apm/templates/solarwinds_apm_initializer.rb +424 -0
- data/lib/solarwinds_apm/api/layerinit.rb +41 -0
- data/lib/solarwinds_apm/api/logging.rb +356 -0
- data/lib/solarwinds_apm/api/memcache.rb +37 -0
- data/lib/solarwinds_apm/api/metrics.rb +63 -0
- data/lib/solarwinds_apm/api/util.rb +98 -0
- data/lib/solarwinds_apm/api.rb +21 -0
- data/lib/solarwinds_apm/base.rb +160 -0
- data/lib/solarwinds_apm/config.rb +301 -0
- data/lib/solarwinds_apm/frameworks/grape.rb +96 -0
- data/lib/solarwinds_apm/frameworks/padrino.rb +78 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller.rb +100 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller5.rb +50 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/action_view.rb +88 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/active_record.rb +26 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +22 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +103 -0
- data/lib/solarwinds_apm/frameworks/rails/inst/logger_formatters.rb +14 -0
- data/lib/solarwinds_apm/frameworks/rails.rb +100 -0
- data/lib/solarwinds_apm/frameworks/sinatra.rb +96 -0
- data/lib/solarwinds_apm/inst/bunny-client.rb +157 -0
- data/lib/solarwinds_apm/inst/bunny-consumer.rb +102 -0
- data/lib/solarwinds_apm/inst/curb.rb +288 -0
- data/lib/solarwinds_apm/inst/dalli.rb +89 -0
- data/lib/solarwinds_apm/inst/delayed_job.rb +100 -0
- data/lib/solarwinds_apm/inst/excon.rb +113 -0
- data/lib/solarwinds_apm/inst/faraday.rb +96 -0
- data/lib/solarwinds_apm/inst/graphql.rb +206 -0
- data/lib/solarwinds_apm/inst/grpc_client.rb +147 -0
- data/lib/solarwinds_apm/inst/grpc_server.rb +119 -0
- data/lib/solarwinds_apm/inst/httpclient.rb +181 -0
- data/lib/solarwinds_apm/inst/logger_formatter.rb +46 -0
- data/lib/solarwinds_apm/inst/logging_log_event.rb +24 -0
- data/lib/solarwinds_apm/inst/lumberjack_formatter.rb +9 -0
- data/lib/solarwinds_apm/inst/memcached.rb +86 -0
- data/lib/solarwinds_apm/inst/mongo.rb +246 -0
- data/lib/solarwinds_apm/inst/mongo2.rb +225 -0
- data/lib/solarwinds_apm/inst/moped.rb +466 -0
- data/lib/solarwinds_apm/inst/net_http.rb +60 -0
- data/lib/solarwinds_apm/inst/rack.rb +217 -0
- data/lib/solarwinds_apm/inst/rack_cache.rb +35 -0
- data/lib/solarwinds_apm/inst/redis.rb +273 -0
- data/lib/solarwinds_apm/inst/resque.rb +129 -0
- data/lib/solarwinds_apm/inst/rest-client.rb +43 -0
- data/lib/solarwinds_apm/inst/sequel.rb +241 -0
- data/lib/solarwinds_apm/inst/sidekiq-client.rb +63 -0
- data/lib/solarwinds_apm/inst/sidekiq-worker.rb +64 -0
- data/lib/solarwinds_apm/inst/typhoeus.rb +90 -0
- data/lib/solarwinds_apm/instrumentation.rb +22 -0
- data/lib/solarwinds_apm/loading.rb +65 -0
- data/lib/solarwinds_apm/logger.rb +14 -0
- data/lib/solarwinds_apm/noop/README.md +9 -0
- data/lib/solarwinds_apm/noop/context.rb +26 -0
- data/lib/solarwinds_apm/noop/metadata.rb +25 -0
- data/lib/solarwinds_apm/noop/profiling.rb +21 -0
- data/lib/solarwinds_apm/oboe_init_options.rb +191 -0
- data/lib/solarwinds_apm/ruby.rb +35 -0
- data/lib/solarwinds_apm/sdk/current_trace_info.rb +123 -0
- data/lib/solarwinds_apm/sdk/custom_metrics.rb +94 -0
- data/lib/solarwinds_apm/sdk/logging.rb +37 -0
- data/lib/solarwinds_apm/sdk/trace_context_headers.rb +69 -0
- data/lib/solarwinds_apm/sdk/tracing.rb +432 -0
- data/lib/solarwinds_apm/support/profiling.rb +22 -0
- data/lib/solarwinds_apm/support/trace_context.rb +53 -0
- data/lib/solarwinds_apm/support/trace_state.rb +69 -0
- data/lib/solarwinds_apm/support/trace_string.rb +89 -0
- data/lib/solarwinds_apm/support/transaction_metrics.rb +67 -0
- data/lib/solarwinds_apm/support/transaction_settings.rb +233 -0
- data/lib/solarwinds_apm/support/x_trace_options.rb +113 -0
- data/lib/solarwinds_apm/support.rb +12 -0
- data/lib/solarwinds_apm/support_report.rb +113 -0
- data/lib/solarwinds_apm/test.rb +165 -0
- data/lib/solarwinds_apm/thread_local.rb +26 -0
- data/lib/solarwinds_apm/util.rb +334 -0
- data/lib/solarwinds_apm/version.rb +17 -0
- data/lib/solarwinds_apm.rb +72 -0
- data/log/.keep +0 -0
- data/log/postgresql/.keep +0 -0
- data/solarwinds_apm.gemspec +52 -0
- data/yardoc_frontpage.md +24 -0
- metadata +228 -0
|
@@ -0,0 +1,356 @@
|
|
|
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
|
+
module SolarWindsAPM
|
|
14
|
+
module API
|
|
15
|
+
##
|
|
16
|
+
# This modules provides the X-Trace logging facilities.
|
|
17
|
+
#
|
|
18
|
+
# These are the lower level methods, please see SolarWindsAPM::SDK
|
|
19
|
+
# for the higher level methods
|
|
20
|
+
#
|
|
21
|
+
# If using these directly make sure to always match a start/end and entry/exit to
|
|
22
|
+
# avoid broken traces.
|
|
23
|
+
module Logging
|
|
24
|
+
@@ints_or_nil = [Integer, Float, NilClass, String]
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Public: Report an event in an active trace.
|
|
28
|
+
#
|
|
29
|
+
# ==== Arguments
|
|
30
|
+
#
|
|
31
|
+
# * +layer+ - The layer the reported event belongs to
|
|
32
|
+
# * +label+ - The label for the reported event. See SDK documentation for reserved labels and usage.
|
|
33
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
34
|
+
# * +event+ - An event to be used instead of generating a new one (see also start_trace_with_target)
|
|
35
|
+
#
|
|
36
|
+
# ==== Example
|
|
37
|
+
#
|
|
38
|
+
# SolarWindsAPM::API.log('logical_layer', 'entry')
|
|
39
|
+
# SolarWindsAPM::API.log('logical_layer', 'info', { :list_length => 20 })
|
|
40
|
+
# SolarWindsAPM::API.log('logical_layer', 'exit')
|
|
41
|
+
#
|
|
42
|
+
# Returns nothing.
|
|
43
|
+
def log(layer, label, kvs = {}, event = nil)
|
|
44
|
+
return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
|
|
45
|
+
|
|
46
|
+
event ||= SolarWindsAPM::Context.createEvent
|
|
47
|
+
log_event(layer, label, event, kvs)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# Public: Report an exception.
|
|
52
|
+
#
|
|
53
|
+
# ==== Arguments
|
|
54
|
+
#
|
|
55
|
+
# * +layer+ - The layer the reported event belongs to
|
|
56
|
+
# * +exception+ - The exception to report, responds to :message and :backtrace(optional)
|
|
57
|
+
# * +kvs+ - Custom params if you want to log extra information
|
|
58
|
+
#
|
|
59
|
+
# ==== Example
|
|
60
|
+
#
|
|
61
|
+
# begin
|
|
62
|
+
# my_iffy_method
|
|
63
|
+
# rescue Exception => e
|
|
64
|
+
# SolarWindsAPM::API.log_exception('rails', e, { user: user_id })
|
|
65
|
+
# raise
|
|
66
|
+
# end
|
|
67
|
+
#
|
|
68
|
+
# Returns nothing.
|
|
69
|
+
def log_exception(layer, exception, kvs = {})
|
|
70
|
+
return SolarWindsAPM::Context.toString if !SolarWindsAPM.tracing? || exception.instance_variable_get(:@exn_logged)
|
|
71
|
+
|
|
72
|
+
unless exception
|
|
73
|
+
SolarWindsAPM.logger.debug '[solarwinds_apm/debug] log_exception called with nil exception'
|
|
74
|
+
return SolarWindsAPM::Context.toString
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
exception.message << exception.class.name if exception.message.length < 4
|
|
78
|
+
kvs.merge!(:Spec => 'error',
|
|
79
|
+
:ErrorClass => exception.class.name,
|
|
80
|
+
:ErrorMsg => exception.message)
|
|
81
|
+
|
|
82
|
+
if exception.respond_to?(:backtrace) && exception.backtrace
|
|
83
|
+
kvs.merge!(:Backtrace => exception.backtrace.join("\r\n"))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
exception.instance_variable_set(:@exn_logged, true)
|
|
87
|
+
log(layer, :error, kvs)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# Public: Start a trace depending on TransactionSettings
|
|
92
|
+
# or decide whether or not to start a trace, and report an entry event
|
|
93
|
+
# appropriately.
|
|
94
|
+
#
|
|
95
|
+
# ==== Arguments
|
|
96
|
+
#
|
|
97
|
+
# * +layer+ - The layer the reported event belongs to
|
|
98
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
99
|
+
# * +headers+ - the request headers, they may contain w3c trace_context data
|
|
100
|
+
# * +settings+ - An instance of TransactionSettings
|
|
101
|
+
# * +url+ - String of the current url, it may be configured to be excluded from tracing
|
|
102
|
+
#
|
|
103
|
+
# ==== Example
|
|
104
|
+
#
|
|
105
|
+
# SolarWindsAPM::API.log_start(:layer_name, { :id => @user.id })
|
|
106
|
+
#
|
|
107
|
+
# Returns a metadata string if we are tracing
|
|
108
|
+
#
|
|
109
|
+
def log_start(layer, kvs = {}, headers = {}, settings = nil, url = nil)
|
|
110
|
+
return unless SolarWindsAPM.loaded
|
|
111
|
+
|
|
112
|
+
# This is a bit ugly, but here is the best place to reset the layer_op thread local var.
|
|
113
|
+
SolarWindsAPM.layer_op = nil
|
|
114
|
+
|
|
115
|
+
settings ||= SolarWindsAPM::TransactionSettings.new(url, headers)
|
|
116
|
+
SolarWindsAPM.trace_context.add_traceinfo(kvs)
|
|
117
|
+
tracestring = SolarWindsAPM.trace_context.tracestring
|
|
118
|
+
|
|
119
|
+
if settings.do_sample
|
|
120
|
+
kvs[:SampleRate] = settings.rate
|
|
121
|
+
kvs[:SampleSource] = settings.source
|
|
122
|
+
|
|
123
|
+
SolarWindsAPM::TraceString.set_sampled(tracestring) if tracestring
|
|
124
|
+
event = create_start_event(tracestring)
|
|
125
|
+
log_event(layer, :entry, event, kvs)
|
|
126
|
+
else
|
|
127
|
+
create_nontracing_context(tracestring)
|
|
128
|
+
SolarWindsAPM::Context.toString
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
##
|
|
133
|
+
# Public: Report an exit event and potentially clear the tracing context.
|
|
134
|
+
#
|
|
135
|
+
# ==== Arguments
|
|
136
|
+
#
|
|
137
|
+
# * +layer+ - The layer the reported event belongs to
|
|
138
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
139
|
+
#
|
|
140
|
+
# ==== Example
|
|
141
|
+
#
|
|
142
|
+
# SolarWindsAPM::API.log_end(:layer_name, { :id => @user.id })
|
|
143
|
+
#
|
|
144
|
+
# Returns a metadata string if we are tracing
|
|
145
|
+
#
|
|
146
|
+
def log_end(layer, kvs = {}, event = nil)
|
|
147
|
+
return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
|
|
148
|
+
|
|
149
|
+
event ||= SolarWindsAPM::Context.createEvent
|
|
150
|
+
log_event(layer, :exit, event, kvs)
|
|
151
|
+
ensure
|
|
152
|
+
SolarWindsAPM::Context.clear
|
|
153
|
+
SolarWindsAPM.trace_context = nil
|
|
154
|
+
SolarWindsAPM.transaction_name = nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
##
|
|
158
|
+
# Public: Log an entry event
|
|
159
|
+
#
|
|
160
|
+
# A helper method to create and log an entry event
|
|
161
|
+
#
|
|
162
|
+
# ==== Arguments
|
|
163
|
+
#
|
|
164
|
+
# * +layer+ - The layer the reported event belongs to
|
|
165
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
166
|
+
# * +op+ - To identify the current operation being traced. Used to avoid double tracing recursive calls.
|
|
167
|
+
#
|
|
168
|
+
# ==== Example
|
|
169
|
+
#
|
|
170
|
+
# SolarWindsAPM::API.log_entry(:layer_name, { :id => @user.id })
|
|
171
|
+
#
|
|
172
|
+
# Returns a metadata string
|
|
173
|
+
#
|
|
174
|
+
def log_entry(layer, kvs = {}, op = nil)
|
|
175
|
+
return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
|
|
176
|
+
|
|
177
|
+
if op
|
|
178
|
+
# check if re-entry but also add op to list for log_exit
|
|
179
|
+
re_entry = SolarWindsAPM.layer_op&.last == op.to_sym
|
|
180
|
+
SolarWindsAPM.layer_op = (SolarWindsAPM.layer_op || []) << op.to_sym
|
|
181
|
+
return SolarWindsAPM::Context.toString if re_entry
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
event ||= SolarWindsAPM::Context.createEvent
|
|
185
|
+
log_event(layer, :entry, event, kvs)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
##
|
|
189
|
+
# Public: Log an info event
|
|
190
|
+
#
|
|
191
|
+
# A helper method to create and log an info event
|
|
192
|
+
#
|
|
193
|
+
# ==== Arguments
|
|
194
|
+
#
|
|
195
|
+
# * +layer+ - The layer the reported event belongs to
|
|
196
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
197
|
+
#
|
|
198
|
+
# ==== Example
|
|
199
|
+
#
|
|
200
|
+
# SolarWindsAPM::API.log_info(:layer_name, { :id => @user.id })
|
|
201
|
+
#
|
|
202
|
+
# Returns a metadata string if we are tracing
|
|
203
|
+
#
|
|
204
|
+
def log_info(layer, kvs = {})
|
|
205
|
+
return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
|
|
206
|
+
|
|
207
|
+
kvs[:Spec] = 'info'
|
|
208
|
+
log_event(layer, :info, SolarWindsAPM::Context.createEvent, kvs)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
##
|
|
212
|
+
# Public: Log an exit event
|
|
213
|
+
#
|
|
214
|
+
# A helper method to create and log an exit event
|
|
215
|
+
#
|
|
216
|
+
# ==== Arguments
|
|
217
|
+
#
|
|
218
|
+
# * +layer+ - The layer the reported event belongs to
|
|
219
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
220
|
+
# * +op+ - Used to avoid double tracing recursive calls, needs to be the same in +log_exit+ that corresponds to a
|
|
221
|
+
# +log_entry+
|
|
222
|
+
#
|
|
223
|
+
# ==== Example
|
|
224
|
+
#
|
|
225
|
+
# SolarWindsAPM::API.log_exit(:layer_name, { :id => @user.id })
|
|
226
|
+
#
|
|
227
|
+
# Returns a metadata string if we are tracing
|
|
228
|
+
def log_exit(layer, kvs = {}, op = nil)
|
|
229
|
+
return SolarWindsAPM::Context.toString unless SolarWindsAPM.tracing?
|
|
230
|
+
|
|
231
|
+
if op
|
|
232
|
+
if SolarWindsAPM.layer_op&.last == op.to_sym
|
|
233
|
+
SolarWindsAPM.layer_op.pop
|
|
234
|
+
else
|
|
235
|
+
SolarWindsAPM.logger.warn "[ruby/logging] op parameter of exit event doesn't correspond to an entry event op"
|
|
236
|
+
end
|
|
237
|
+
# check if the next op is the same, don't log event if so
|
|
238
|
+
return SolarWindsAPM::Context.toString if SolarWindsAPM.layer_op&.last == op.to_sym
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
log_event(layer, :exit, SolarWindsAPM::Context.createEvent, kvs)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
##
|
|
245
|
+
#:nodoc:
|
|
246
|
+
# Internal: Reports agent init to the collector
|
|
247
|
+
#
|
|
248
|
+
# ==== Arguments
|
|
249
|
+
#
|
|
250
|
+
# * +layer+ - The layer the reported event belongs to
|
|
251
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event
|
|
252
|
+
def log_init(layer = :rack, kvs = {})
|
|
253
|
+
context = SolarWindsAPM::Metadata.makeRandom
|
|
254
|
+
return SolarWindsAPM::Context.toString unless context.isValid
|
|
255
|
+
|
|
256
|
+
event = context.createEvent
|
|
257
|
+
event.addInfo(SW_APM_STR_LAYER, layer.to_s)
|
|
258
|
+
event.addInfo(SW_APM_STR_LABEL, 'single')
|
|
259
|
+
kvs.each do |k, v|
|
|
260
|
+
event.addInfo(k, v.to_s)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
SolarWindsAPM::Reporter.sendStatus(event, context)
|
|
264
|
+
SolarWindsAPM::Context.toString
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
private
|
|
268
|
+
|
|
269
|
+
##
|
|
270
|
+
#:nodoc:
|
|
271
|
+
# @private
|
|
272
|
+
# Internal: Report an event.
|
|
273
|
+
#
|
|
274
|
+
# ==== Arguments
|
|
275
|
+
#
|
|
276
|
+
# * +layer+ - The layer the reported event belongs to
|
|
277
|
+
# * +label+ - The label for the reported event. See API documentation for reserved labels and usage.
|
|
278
|
+
# * +event+ - The pre-existing SolarWindsAPM context event. See SolarWindsAPM::Context.createEvent
|
|
279
|
+
# * +kvs+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
280
|
+
#
|
|
281
|
+
# ==== Example
|
|
282
|
+
#
|
|
283
|
+
# entry = SolarWindsAPM::Context.createEvent
|
|
284
|
+
# SolarWindsAPM::API.log_event(:layer_name, 'entry', entry_event, { :id => @user.id })
|
|
285
|
+
#
|
|
286
|
+
# exit_event = SolarWindsAPM::Context.createEvent
|
|
287
|
+
# exit_event.addEdge(entry.getMetadata)
|
|
288
|
+
# SolarWindsAPM::API.log_event(:layer_name, 'exit', exit_event, { :id => @user.id })
|
|
289
|
+
#
|
|
290
|
+
def log_event(layer, label, event, kvs = {})
|
|
291
|
+
event.addInfo(SW_APM_STR_LAYER, layer.to_s.freeze) if layer
|
|
292
|
+
event.addInfo(SW_APM_STR_LABEL, label.to_s.freeze)
|
|
293
|
+
|
|
294
|
+
SolarWindsAPM.layer = layer.to_sym if label == :entry
|
|
295
|
+
SolarWindsAPM.layer = nil if label == :exit
|
|
296
|
+
|
|
297
|
+
kvs.each do |k, v|
|
|
298
|
+
value = nil
|
|
299
|
+
|
|
300
|
+
next unless valid_key? k
|
|
301
|
+
|
|
302
|
+
if @@ints_or_nil.include?(v.class)
|
|
303
|
+
value = v
|
|
304
|
+
elsif v.class == Set
|
|
305
|
+
value = v.to_a.to_s
|
|
306
|
+
else
|
|
307
|
+
value = v.to_s if v.respond_to?(:to_s)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
begin
|
|
311
|
+
event.addInfo(k.to_s, value)
|
|
312
|
+
rescue ArgumentError => e
|
|
313
|
+
SolarWindsAPM.logger.debug "[solarwinds_apm/debug] Couldn't add event KV: #{k} => #{v.class}"
|
|
314
|
+
SolarWindsAPM.logger.debug "[solarwinds_apm/debug] #{e.message}"
|
|
315
|
+
end
|
|
316
|
+
end if !kvs.nil? && kvs.any?
|
|
317
|
+
|
|
318
|
+
SolarWindsAPM::Reporter.sendReport(event)
|
|
319
|
+
SolarWindsAPM::Context.toString
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def create_start_event(tracestring = nil)
|
|
323
|
+
if SolarWindsAPM::TraceString.sampled?(tracestring)
|
|
324
|
+
md = SolarWindsAPM::Metadata.fromString(tracestring)
|
|
325
|
+
SolarWindsAPM::Context.fromString(tracestring)
|
|
326
|
+
md.createEvent
|
|
327
|
+
else
|
|
328
|
+
md = SolarWindsAPM::Metadata.makeRandom(true)
|
|
329
|
+
SolarWindsAPM::Context.set(md)
|
|
330
|
+
SolarWindsAPM::Event.startTrace(md)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
public
|
|
335
|
+
|
|
336
|
+
def create_nontracing_context(tracestring)
|
|
337
|
+
if SolarWindsAPM::TraceString.valid?(tracestring)
|
|
338
|
+
# continue valid incoming tracestring
|
|
339
|
+
# use it for current context, ensuring sample bit is not set
|
|
340
|
+
SolarWindsAPM::TraceString.unset_sampled(tracestring)
|
|
341
|
+
SolarWindsAPM::Context.fromString(tracestring)
|
|
342
|
+
else
|
|
343
|
+
# discard invalid incoming tracestring
|
|
344
|
+
# create a new context, ensuring sample bit not set
|
|
345
|
+
md = SolarWindsAPM::Metadata.makeRandom(false)
|
|
346
|
+
SolarWindsAPM::Context.fromString(md.toString)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
# need to set the module context to public, otherwise the following `extends` will be private in api.rb
|
|
351
|
+
|
|
352
|
+
public
|
|
353
|
+
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
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 SolarWindsAPM
|
|
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 SolarWindsAPM
|
|
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] = SolarWindsAPM::Span.createSpan(transaction_name, nil, duration, error)
|
|
34
|
+
SolarWindsAPM.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 SolarWindsAPM.transaction_name
|
|
51
|
+
SolarWindsAPM.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,98 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#++
|
|
5
|
+
|
|
6
|
+
require 'pp'
|
|
7
|
+
|
|
8
|
+
module SolarWindsAPM
|
|
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 solarwinds_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, :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: Pretty print a list of arguments for reporting
|
|
50
|
+
#
|
|
51
|
+
# args - the list of arguments to work on
|
|
52
|
+
#
|
|
53
|
+
# Returns a pretty string representation of arguments
|
|
54
|
+
def pps(*args)
|
|
55
|
+
old_out = $stdout
|
|
56
|
+
begin
|
|
57
|
+
s = StringIO.new
|
|
58
|
+
$stdout = s
|
|
59
|
+
pp(*args)
|
|
60
|
+
ensure
|
|
61
|
+
$stdout = old_out
|
|
62
|
+
end
|
|
63
|
+
s.string
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Internal: Determine a string to report representing klass
|
|
67
|
+
#
|
|
68
|
+
# args - an instance of a Class, a Class or a Module
|
|
69
|
+
#
|
|
70
|
+
# Returns a string representation of klass
|
|
71
|
+
def get_class_name(klass)
|
|
72
|
+
kv = {}
|
|
73
|
+
|
|
74
|
+
if klass.to_s =~ /::/
|
|
75
|
+
klass.class.to_s.rpartition('::').last
|
|
76
|
+
else
|
|
77
|
+
if klass.is_a?(Class) && klass.is_a?(Module)
|
|
78
|
+
# Class
|
|
79
|
+
kv['Class'] = klass.to_s
|
|
80
|
+
|
|
81
|
+
elsif !klass.is_a?(Class) && !klass.is_a?(Module)
|
|
82
|
+
# Class instance
|
|
83
|
+
kv['Class'] = klass.class.to_s
|
|
84
|
+
|
|
85
|
+
else
|
|
86
|
+
# Module
|
|
87
|
+
kv['Module'] = klass.to_s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
kv
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def xtrace_v2?(xtr)
|
|
94
|
+
xtr && xtr.start_with?('2B')
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
module SolarWindsAPM
|
|
5
|
+
|
|
6
|
+
module API
|
|
7
|
+
extend SolarWindsAPM::API::Logging
|
|
8
|
+
extend SolarWindsAPM::API::Metrics
|
|
9
|
+
extend SolarWindsAPM::API::LayerInit
|
|
10
|
+
extend SolarWindsAPM::API::Util
|
|
11
|
+
|
|
12
|
+
require_relative './sdk/trace_context_headers'
|
|
13
|
+
require_relative './sdk/tracing'
|
|
14
|
+
require_relative './sdk/custom_metrics'
|
|
15
|
+
require_relative './sdk/current_trace_info'
|
|
16
|
+
require_relative './sdk/logging' # to make sure it is loaded <- not very elegant
|
|
17
|
+
|
|
18
|
+
extend SolarWindsAPM::SDK::Tracing
|
|
19
|
+
extend SolarWindsAPM::SDK::CustomMetrics
|
|
20
|
+
end
|
|
21
|
+
end
|