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,120 @@
|
|
1
|
+
# Copyright (c) 2018 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module GRPC
|
6
|
+
|
7
|
+
if defined? ::GRPC
|
8
|
+
STATUSCODES = {}
|
9
|
+
::GRPC::Core::StatusCodes.constants.each { |code| STATUSCODES[::GRPC::Core::StatusCodes.const_get(code)] = code }
|
10
|
+
end
|
11
|
+
|
12
|
+
module RpcDesc
|
13
|
+
|
14
|
+
def self.included(klass)
|
15
|
+
::AppOpticsAPM::Util.method_alias(klass, :handle_request_response, ::GRPC::RpcDesc)
|
16
|
+
::AppOpticsAPM::Util.method_alias(klass, :handle_client_streamer, ::GRPC::RpcDesc)
|
17
|
+
::AppOpticsAPM::Util.method_alias(klass, :handle_server_streamer, ::GRPC::RpcDesc)
|
18
|
+
::AppOpticsAPM::Util.method_alias(klass, :handle_bidi_streamer, ::GRPC::RpcDesc)
|
19
|
+
::AppOpticsAPM::Util.method_alias(klass, :run_server_method, ::GRPC::RpcDesc)
|
20
|
+
end
|
21
|
+
|
22
|
+
def grpc_tags(active_call, mth)
|
23
|
+
tags = {
|
24
|
+
'Spec' => 'grpc_server',
|
25
|
+
'URL' => active_call.metadata['method'],
|
26
|
+
'Controller' => mth.owner.to_s,
|
27
|
+
'Action' => mth.name.to_s,
|
28
|
+
'HTTP-Host' => active_call.peer
|
29
|
+
}
|
30
|
+
|
31
|
+
if request_response?
|
32
|
+
tags['GRPCMethodType'] = 'UNARY'
|
33
|
+
elsif client_streamer?
|
34
|
+
tags['GRPCMethodType'] = 'CLIENT_STREAMING'
|
35
|
+
elsif server_streamer?
|
36
|
+
tags['GRPCMethodType'] = 'SERVER_STREAMING'
|
37
|
+
else # is a bidi_stream
|
38
|
+
tags['GRPCMethodType'] = 'BIDI_STREAMING'
|
39
|
+
end
|
40
|
+
|
41
|
+
tags
|
42
|
+
end
|
43
|
+
|
44
|
+
def handle_request_response_with_appoptics(active_call, mth, inter_ctx)
|
45
|
+
handle_call('handle_request_response_without_appoptics', active_call, mth, inter_ctx)
|
46
|
+
end
|
47
|
+
|
48
|
+
def handle_client_streamer_with_appoptics(active_call, mth, inter_ctx)
|
49
|
+
handle_call('handle_client_streamer_without_appoptics', active_call, mth, inter_ctx)
|
50
|
+
end
|
51
|
+
|
52
|
+
def handle_server_streamer_with_appoptics(active_call, mth, inter_ctx)
|
53
|
+
handle_call('handle_server_streamer_without_appoptics', active_call, mth, inter_ctx)
|
54
|
+
end
|
55
|
+
|
56
|
+
def handle_bidi_streamer_with_appoptics(active_call, mth, inter_ctx)
|
57
|
+
handle_call('handle_bidi_streamer_without_appoptics', active_call, mth, inter_ctx)
|
58
|
+
end
|
59
|
+
|
60
|
+
# status codes need to be determined in this lower method, because they may not get raised to the
|
61
|
+
# next instrumented method
|
62
|
+
def handle_call(without, active_call, mth, inter_ctx)
|
63
|
+
begin
|
64
|
+
send(without, active_call, mth, inter_ctx)
|
65
|
+
rescue ::GRPC::Core::CallError, ::GRPC::BadStatus, ::GRPC::Core::OutOfTime, StandardError, NotImplementedError => e
|
66
|
+
log_grpc_exception(active_call, e)
|
67
|
+
raise e
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def run_server_method_with_appoptics(active_call, mth, inter_ctx)
|
72
|
+
tags = grpc_tags(active_call, mth)
|
73
|
+
AppOpticsAPM::API.log_start('grpc-server', active_call.metadata['x-trace'], tags)
|
74
|
+
|
75
|
+
exit_event = AppOpticsAPM::Event.startTrace(AppOpticsAPM::Context.get)
|
76
|
+
active_call.merge_metadata_to_send({ 'x-trace' => exit_event.metadataString })
|
77
|
+
begin
|
78
|
+
AppOpticsAPM::API.send_metrics('grpc-server', tags) do
|
79
|
+
run_server_method_without_appoptics(active_call, mth, inter_ctx)
|
80
|
+
end
|
81
|
+
rescue => e
|
82
|
+
log_grpc_exception(active_call, e)
|
83
|
+
raise e
|
84
|
+
ensure
|
85
|
+
tags['GRPCStatus'] = active_call.metadata_to_send.delete('grpc_status')
|
86
|
+
tags['GRPCStatus'] ||= active_call.status ? AppOpticsAPM::GRPC::STATUSCODES[active_call.status.code].to_s : 'OK'
|
87
|
+
tags['Backtrace'] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:grpc_server][:collect_backtraces]
|
88
|
+
|
89
|
+
exit_event.addEdge(AppOpticsAPM::Context.get)
|
90
|
+
AppOpticsAPM::API.log_end('grpc-server', tags, exit_event)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def log_grpc_exception(active_call, e)
|
97
|
+
unless e.instance_variable_get(:@exn_logged)
|
98
|
+
AppOpticsAPM::API.log_exception('grpc-server', e)
|
99
|
+
|
100
|
+
unless active_call.metadata_sent
|
101
|
+
if e.class == ::GRPC::Core::OutOfTime
|
102
|
+
active_call.merge_metadata_to_send({ 'grpc_status' => 'DEADLINE_EXCEEDED' })
|
103
|
+
elsif e.respond_to?(:code)
|
104
|
+
active_call.merge_metadata_to_send({ 'grpc_status' => AppOpticsAPM::GRPC::STATUSCODES[e.code].to_s })
|
105
|
+
else
|
106
|
+
active_call.merge_metadata_to_send({ 'grpc_status' => 'UNKNOWN' })
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
if defined?(GRPC) && AppOpticsAPM::Config['grpc_server'][:enabled]
|
118
|
+
# server side is instrumented in RpcDesc
|
119
|
+
AppOpticsAPM::Util.send_include(GRPC::RpcDesc, AppOpticsAPM::GRPC::RpcDesc)
|
120
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
if AppOpticsAPM::Config[:nethttp][:enabled]
|
7
|
+
module AppOpticsAPM
|
8
|
+
module Inst
|
9
|
+
module NetHttp
|
10
|
+
# Net::HTTP.class_eval do
|
11
|
+
# def request_with_appoptics(*args, &block)
|
12
|
+
def request(*args, &block)
|
13
|
+
# Avoid cross host tracing for blacklisted domains
|
14
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(addr_port)
|
15
|
+
|
16
|
+
# If we're not tracing, just do a fast return. Since
|
17
|
+
# net/http.request calls itself, only trace
|
18
|
+
# once the http session has been started.
|
19
|
+
if !AppOpticsAPM.tracing? || !started?
|
20
|
+
if blacklisted # if the other site is blacklisted, we don't want to leak its X-trace
|
21
|
+
resp = super
|
22
|
+
resp.delete('X-Trace') # if resp['X-Trace']
|
23
|
+
return resp
|
24
|
+
else
|
25
|
+
xtrace = AppOpticsAPM::Context.toString
|
26
|
+
args[0]['X-Trace'] = xtrace if AppOpticsAPM::XTrace.valid?(xtrace)
|
27
|
+
return super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
opts = {}
|
32
|
+
AppOpticsAPM::API.trace(:'net-http', opts) do
|
33
|
+
context = AppOpticsAPM::Context.toString
|
34
|
+
|
35
|
+
# Collect KVs to report in the exit event
|
36
|
+
if args.respond_to?(:first) && args.first
|
37
|
+
req = args.first
|
38
|
+
|
39
|
+
opts[:Spec] = 'rsc'
|
40
|
+
opts[:IsService] = 1
|
41
|
+
opts[:RemoteURL] = "#{use_ssl? ? 'https' : 'http'}://#{addr_port}"
|
42
|
+
opts[:RemoteURL] << (AppOpticsAPM::Config[:nethttp][:log_args] ? req.path : req.path.split('?').first)
|
43
|
+
opts[:HTTPMethod] = req.method
|
44
|
+
opts[:Blacklisted] = true if blacklisted
|
45
|
+
opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:nethttp][:collect_backtraces]
|
46
|
+
|
47
|
+
req['X-Trace'] = context unless blacklisted
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
# The actual net::http call
|
52
|
+
resp = super
|
53
|
+
# Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
|
54
|
+
xtrace = resp.get_fields('X-Trace')
|
55
|
+
if blacklisted
|
56
|
+
# we don't want the x-trace if it is from a blacklisted address
|
57
|
+
resp.delete('X-Trace') # if xtrace
|
58
|
+
else
|
59
|
+
xtrace = xtrace[0] if xtrace && xtrace.is_a?(Array)
|
60
|
+
AppOpticsAPM::XTrace.continue_service_context(context, xtrace)
|
61
|
+
end
|
62
|
+
|
63
|
+
opts[:HTTPStatus] = resp.code
|
64
|
+
|
65
|
+
# If we get a redirect, report the location header
|
66
|
+
if ((300..308).to_a.include? resp.code.to_i) && resp.header["Location"]
|
67
|
+
opts[:Location] = resp.header["Location"]
|
68
|
+
end
|
69
|
+
|
70
|
+
next resp
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Net::HTTP.prepend(AppOpticsAPM::Inst::NetHttp)
|
80
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting net/http' if AppOpticsAPM::Config[:verbose]
|
81
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module Inst
|
6
|
+
module HTTPClient
|
7
|
+
def self.included(klass)
|
8
|
+
AppOpticsAPM::Util.method_alias(klass, :do_request, ::HTTPClient)
|
9
|
+
AppOpticsAPM::Util.method_alias(klass, :do_request_async, ::HTTPClient)
|
10
|
+
AppOpticsAPM::Util.method_alias(klass, :do_get_stream, ::HTTPClient)
|
11
|
+
end
|
12
|
+
|
13
|
+
def appoptics_collect(method, uri, query = nil)
|
14
|
+
kvs = {}
|
15
|
+
kvs[:Spec] = 'rsc'
|
16
|
+
kvs[:IsService] = 1
|
17
|
+
|
18
|
+
# Conditionally log URL query params
|
19
|
+
# Because of the hook points, the query arg can come in under <tt>query</tt>
|
20
|
+
# or as a part of <tt>uri</tt> (not both). Here we handle both cases.
|
21
|
+
if AppOpticsAPM::Config[:httpclient][:log_args]
|
22
|
+
if query
|
23
|
+
kvs[:RemoteURL] = uri.to_s + '?' + AppOpticsAPM::Util.to_query(query)
|
24
|
+
else
|
25
|
+
kvs[:RemoteURL] = uri.to_s
|
26
|
+
end
|
27
|
+
else
|
28
|
+
kvs[:RemoteURL] = uri.to_s.split('?').first
|
29
|
+
end
|
30
|
+
|
31
|
+
kvs[:HTTPMethod] = AppOpticsAPM::Util.upcase(method)
|
32
|
+
kvs
|
33
|
+
rescue => e
|
34
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] Error capturing httpclient KVs: #{e.message}"
|
35
|
+
AppOpticsAPM.logger.debug e.backtrace.join('\n') if AppOpticsAPM::Config[:verbose]
|
36
|
+
ensure
|
37
|
+
return kvs
|
38
|
+
end
|
39
|
+
|
40
|
+
def do_request_with_appoptics(method, uri, query, body, header, &block)
|
41
|
+
# Avoid cross host tracing for blacklisted domains
|
42
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(uri.hostname)
|
43
|
+
|
44
|
+
# If we're not tracing, just do a fast return.
|
45
|
+
unless AppOpticsAPM.tracing?
|
46
|
+
add_xtrace_header(header) unless blacklisted
|
47
|
+
return do_request_without_appoptics(method, uri, query, body, header, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
req_context = nil
|
52
|
+
response_context = nil
|
53
|
+
|
54
|
+
kvs = appoptics_collect(method, uri, query)
|
55
|
+
kvs[:Blacklisted] = true if blacklisted
|
56
|
+
|
57
|
+
AppOpticsAPM::API.log_entry(:httpclient, kvs)
|
58
|
+
kvs.clear
|
59
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:httpclient][:collect_backtraces]
|
60
|
+
|
61
|
+
req_context = add_xtrace_header(header) unless blacklisted
|
62
|
+
|
63
|
+
# The core httpclient call
|
64
|
+
response = do_request_without_appoptics(method, uri, query, body, header, &block)
|
65
|
+
|
66
|
+
response_context = response.headers['X-Trace']
|
67
|
+
kvs[:HTTPStatus] = response.status_code
|
68
|
+
|
69
|
+
# If we get a redirect, report the location header
|
70
|
+
if ((300..308).to_a.include? response.status.to_i) && response.headers.key?('Location')
|
71
|
+
kvs[:Location] = response.headers['Location']
|
72
|
+
end
|
73
|
+
|
74
|
+
if response_context && !blacklisted
|
75
|
+
AppOpticsAPM::XTrace.continue_service_context(req_context, response_context)
|
76
|
+
end
|
77
|
+
|
78
|
+
response
|
79
|
+
rescue => e
|
80
|
+
AppOpticsAPM::API.log_exception(:httpclient, e)
|
81
|
+
raise e
|
82
|
+
ensure
|
83
|
+
AppOpticsAPM::API.log_exit(:httpclient, kvs)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def do_request_async_with_appoptics(method, uri, query, body, header)
|
88
|
+
add_xtrace_header(header)
|
89
|
+
do_request_async_without_appoptics(method, uri, query, body, header)
|
90
|
+
end
|
91
|
+
|
92
|
+
def do_get_stream_with_appoptics(req, proxy, conn)
|
93
|
+
AppOpticsAPM::Context.fromString(req.header['X-Trace'].first) unless req.header['X-Trace'].empty?
|
94
|
+
# Avoid cross host tracing for blacklisted domains
|
95
|
+
uri = req.http_header.request_uri
|
96
|
+
blacklisted = AppOpticsAPM::API.blacklisted?(uri.hostname)
|
97
|
+
|
98
|
+
unless AppOpticsAPM.tracing?
|
99
|
+
req.header.delete('X-Trace') if blacklisted
|
100
|
+
return do_get_stream_without_appoptics(req, proxy, conn)
|
101
|
+
end
|
102
|
+
|
103
|
+
begin
|
104
|
+
response = nil
|
105
|
+
req_context = nil
|
106
|
+
method = req.http_header.request_method
|
107
|
+
|
108
|
+
kvs = appoptics_collect(method, uri)
|
109
|
+
kvs[:Blacklisted] = true if blacklisted
|
110
|
+
kvs[:Async] = 1
|
111
|
+
|
112
|
+
AppOpticsAPM::API.log_entry(:httpclient, kvs)
|
113
|
+
kvs.clear
|
114
|
+
kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:httpclient][:collect_backtraces]
|
115
|
+
|
116
|
+
blacklisted ? req.header.delete('X-Trace') : req_context = add_xtrace_header(req.header)
|
117
|
+
|
118
|
+
# The core httpclient call
|
119
|
+
result = do_get_stream_without_appoptics(req, proxy, conn)
|
120
|
+
|
121
|
+
# Older HTTPClient < 2.6.0 returns HTTPClient::Connection
|
122
|
+
if result.is_a?(::HTTP::Message)
|
123
|
+
response = result
|
124
|
+
else
|
125
|
+
response = conn.pop
|
126
|
+
end
|
127
|
+
|
128
|
+
response_context = response.headers['X-Trace']
|
129
|
+
kvs[:HTTPStatus] = response.status_code
|
130
|
+
|
131
|
+
# If we get a redirect, report the location header
|
132
|
+
if ((300..308).to_a.include? response.status.to_i) && response.headers.key?('Location')
|
133
|
+
kvs[:Location] = response.headers['Location']
|
134
|
+
end
|
135
|
+
|
136
|
+
if response_context && !blacklisted
|
137
|
+
AppOpticsAPM::XTrace.continue_service_context(req_context, response_context)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Older HTTPClient < 2.6.0 returns HTTPClient::Connection
|
141
|
+
conn.push response if result.is_a?(::HTTPClient::Connection)
|
142
|
+
result
|
143
|
+
rescue => e
|
144
|
+
AppOpticsAPM::API.log_exception(:httpclient, e)
|
145
|
+
raise e
|
146
|
+
ensure
|
147
|
+
AppOpticsAPM::API.log_exit(:httpclient, kvs)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def add_xtrace_header(headers)
|
154
|
+
req_context = AppOpticsAPM::Context.toString
|
155
|
+
return nil unless AppOpticsAPM::XTrace.valid?(req_context)
|
156
|
+
# Be aware of various ways to call/use httpclient
|
157
|
+
if headers.is_a?(Array)
|
158
|
+
headers.delete_if { |kv| kv[0] == 'X-Trace' }
|
159
|
+
headers.push ['X-Trace', req_context]
|
160
|
+
elsif headers.is_a?(Hash)
|
161
|
+
headers['X-Trace'] = req_context
|
162
|
+
elsif headers.is_a? HTTP::Message::Headers
|
163
|
+
headers.set('X-Trace', req_context)
|
164
|
+
end
|
165
|
+
req_context
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
if AppOpticsAPM::Config[:httpclient][:enabled] && defined?(HTTPClient)
|
172
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting httpclient' if AppOpticsAPM::Config[:verbose]
|
173
|
+
AppOpticsAPM::Util.send_include(HTTPClient, AppOpticsAPM::Inst::HTTPClient)
|
174
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright (c) 2019 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
module Logger
|
8
|
+
module Formatter
|
9
|
+
|
10
|
+
def call(severity, time, progname, msg)
|
11
|
+
return super if AppOpticsAPM::Config[:log_traceId] == :never
|
12
|
+
|
13
|
+
msg = insert_trace_id(msg)
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def insert_trace_id(msg)
|
20
|
+
return msg if msg =~ /ao(=>{:|\.){1}traceId/
|
21
|
+
|
22
|
+
current_trace = AppOpticsAPM::SDK.current_trace
|
23
|
+
if current_trace.log?
|
24
|
+
case msg
|
25
|
+
when ::String
|
26
|
+
msg = msg.strip.empty? ? msg : insert_before_empty_lines(msg, current_trace.for_log)
|
27
|
+
when ::Exception
|
28
|
+
# conversion to String copied from Logger::Formatter private method #msg2str
|
29
|
+
msg = ("#{msg.message} (#{msg.class}) #{current_trace.for_log}\n" <<
|
30
|
+
(msg.backtrace || []).join("\n"))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
msg
|
34
|
+
end
|
35
|
+
|
36
|
+
def insert_before_empty_lines(msg, for_log)
|
37
|
+
stripped = msg.rstrip
|
38
|
+
"#{stripped} #{for_log}#{msg[stripped.length..-1]}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if AppOpticsAPM.loaded
|
45
|
+
class Logger
|
46
|
+
class Formatter
|
47
|
+
prepend AppOpticsAPM::Logger::Formatter
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright (c) 2019 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require_relative 'logger_formatter'
|
5
|
+
|
6
|
+
module AppOpticsAPM
|
7
|
+
module Logging
|
8
|
+
module LogEvent
|
9
|
+
include AppOpticsAPM::Logger::Formatter # provides #insert_trace_id
|
10
|
+
|
11
|
+
def initialize(logger, level, data, caller_tracing )
|
12
|
+
return super if AppOpticsAPM::Config[:log_traceId] == :never
|
13
|
+
|
14
|
+
data = insert_trace_id(data)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if AppOpticsAPM.loaded && defined?(Logging::LogEvent)
|
23
|
+
module Logging
|
24
|
+
class LogEvent
|
25
|
+
prepend AppOpticsAPM::Logging::LogEvent
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Copyright (c) 2019 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
require_relative 'logger_formatter'
|
5
|
+
|
6
|
+
if AppOpticsAPM.loaded && defined?(Lumberjack::Formatter)
|
7
|
+
module Lumberjack
|
8
|
+
class Formatter
|
9
|
+
prepend AppOpticsAPM::Logger::Formatter
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
module AppOpticsAPM
|
5
|
+
module Inst
|
6
|
+
module Memcached
|
7
|
+
include AppOpticsAPM::API::Memcache
|
8
|
+
|
9
|
+
def self.included(cls)
|
10
|
+
AppOpticsAPM.logger.info '[appoptics_apm/loading] Instrumenting memcached' if AppOpticsAPM::Config[:verbose]
|
11
|
+
|
12
|
+
cls.class_eval do
|
13
|
+
MEMCACHE_OPS.reject { |m| !method_defined?(m) }.each do |m|
|
14
|
+
define_method("#{m}_with_appoptics") do |*args|
|
15
|
+
opts = { :KVOp => m }
|
16
|
+
|
17
|
+
if args.length && !args[0].is_a?(Array)
|
18
|
+
opts[:KVKey] = args[0].to_s
|
19
|
+
rhost = remote_host(args[0].to_s)
|
20
|
+
opts[:RemoteHost] = rhost if rhost
|
21
|
+
end
|
22
|
+
|
23
|
+
AppOpticsAPM::API.trace(:memcache, opts) do
|
24
|
+
result = send("#{m}_without_appoptics", *args)
|
25
|
+
|
26
|
+
opts[:KVHit] = memcache_hit?(result) if m == :get && args.length && args[0].class == String
|
27
|
+
opts[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:memcached][:collect_backtraces]
|
28
|
+
|
29
|
+
result
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class_eval "alias #{m}_without_appoptics #{m}"
|
34
|
+
class_eval "alias #{m} #{m}_with_appoptics"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end # module Memcached
|
40
|
+
|
41
|
+
module MemcachedRails
|
42
|
+
def self.included(cls)
|
43
|
+
cls.class_eval do
|
44
|
+
if ::Memcached::Rails.method_defined? :get_multi
|
45
|
+
alias get_multi_without_appoptics get_multi
|
46
|
+
alias get_multi get_multi_with_appoptics
|
47
|
+
elsif AppOpticsAPM::Config[:verbose]
|
48
|
+
AppOpticsAPM.logger.warn '[appoptics_apm/loading] Couldn\'t properly instrument Memcached. Partial traces may occur.'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_multi_with_appoptics(keys, raw = false)
|
54
|
+
if AppOpticsAPM.tracing?
|
55
|
+
layer_kvs = {}
|
56
|
+
layer_kvs[:KVOp] = :get_multi
|
57
|
+
|
58
|
+
AppOpticsAPM::API.trace(:memcache, layer_kvs || {}, :get_multi) do
|
59
|
+
layer_kvs[:KVKeyCount] = keys.flatten.length
|
60
|
+
|
61
|
+
values = get_multi_without_appoptics(keys, raw)
|
62
|
+
|
63
|
+
layer_kvs[:KVHitCount] = values.length
|
64
|
+
layer_kvs[:Backtrace] = AppOpticsAPM::API.backtrace if AppOpticsAPM::Config[:memcached][:collect_backtraces]
|
65
|
+
|
66
|
+
values
|
67
|
+
end
|
68
|
+
else
|
69
|
+
get_multi_without_appoptics(keys, raw)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end # module MemcachedRails
|
73
|
+
end # module Inst
|
74
|
+
end # module AppOpticsAPM
|
75
|
+
|
76
|
+
if defined?(Memcached) && AppOpticsAPM::Config[:memcached][:enabled]
|
77
|
+
Memcached.class_eval do
|
78
|
+
include AppOpticsAPM::Inst::Memcached
|
79
|
+
end
|
80
|
+
|
81
|
+
if defined?(Memcached::Rails)
|
82
|
+
Memcached::Rails.class_eval do
|
83
|
+
include AppOpticsAPM::Inst::MemcachedRails
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|