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,114 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
require 'mkmf'
|
|
5
|
+
require 'rbconfig'
|
|
6
|
+
require 'open-uri'
|
|
7
|
+
require 'no_proxy_fix'
|
|
8
|
+
|
|
9
|
+
ext_dir = File.expand_path(File.dirname(__FILE__))
|
|
10
|
+
|
|
11
|
+
# Check if we're running in JRuby
|
|
12
|
+
jruby = defined?(JRUBY_VERSION) ? true : false
|
|
13
|
+
|
|
14
|
+
# Set the mkmf lib paths so we have no issues linking to
|
|
15
|
+
# the AppOpticsAPM libs.
|
|
16
|
+
ao_lib_dir = File.join(ext_dir, 'lib')
|
|
17
|
+
ao_include = File.join(ext_dir, 'src')
|
|
18
|
+
|
|
19
|
+
# Download the appropriate liboboe from S3(via rake for testing) or files.appoptics.com (production)
|
|
20
|
+
version = File.read(File.join(ao_include, 'VERSION')).chomp
|
|
21
|
+
if ENV['APPOPTICS_FROM_S3'].to_s.downcase == 'true'
|
|
22
|
+
ao_path = File.join('https://s3-us-west-2.amazonaws.com/rc-files-t2/c-lib/', version)
|
|
23
|
+
puts "Fetching c-lib from S3"
|
|
24
|
+
else
|
|
25
|
+
ao_path = File.join('https://files.appoptics.com/c-lib', version)
|
|
26
|
+
end
|
|
27
|
+
ao_arch = `ldd --version 2>&1` =~ /musl/ ? 'alpine-x86_64' : 'x86_64'
|
|
28
|
+
ao_clib = "liboboe-1.0-#{ao_arch}.so.0.0.0"
|
|
29
|
+
ao_item = File.join(ao_path, ao_clib)
|
|
30
|
+
ao_checksum_item = "#{ao_item}.sha256"
|
|
31
|
+
clib = File.join(ao_lib_dir, ao_clib)
|
|
32
|
+
|
|
33
|
+
retries = 3
|
|
34
|
+
success = false
|
|
35
|
+
while retries > 0
|
|
36
|
+
begin
|
|
37
|
+
# download
|
|
38
|
+
download = open(ao_item, 'rb')
|
|
39
|
+
IO.copy_stream(download, clib)
|
|
40
|
+
|
|
41
|
+
checksum = open(ao_checksum_item, 'r').read.chomp
|
|
42
|
+
clib_checksum = Digest::SHA256.file(clib).hexdigest
|
|
43
|
+
|
|
44
|
+
# verify_checksum
|
|
45
|
+
if clib_checksum != checksum
|
|
46
|
+
$stderr.puts '== ERROR ================================================================='
|
|
47
|
+
$stderr.puts 'Checksum Verification failed for the c-extension of the appoptics_apm gem.'
|
|
48
|
+
$stderr.puts 'appoptics_apm will not instrument the code. No tracing will occur.'
|
|
49
|
+
$stderr.puts 'Contact support@appoptics.com if the problem persists.'
|
|
50
|
+
$stderr.puts '=========================================================================='
|
|
51
|
+
create_makefile('oboe_noop', 'noop')
|
|
52
|
+
retries = 0
|
|
53
|
+
else
|
|
54
|
+
success = true
|
|
55
|
+
retries = 0
|
|
56
|
+
end
|
|
57
|
+
rescue => e
|
|
58
|
+
File.write(clib, '')
|
|
59
|
+
retries -= 1
|
|
60
|
+
if retries == 0
|
|
61
|
+
$stderr.puts '== ERROR =========================================================='
|
|
62
|
+
$stderr.puts 'Download of the c-extension for the appoptics_apm gem failed.'
|
|
63
|
+
$stderr.puts 'appoptics_apm will not instrument the code. No tracing will occur.'
|
|
64
|
+
$stderr.puts 'Contact support@appoptics.com if the problem persists.'
|
|
65
|
+
$stderr.puts "error:\n#{e.message}"
|
|
66
|
+
$stderr.puts '==================================================================='
|
|
67
|
+
create_makefile('oboe_noop', 'noop')
|
|
68
|
+
end
|
|
69
|
+
sleep 0.5
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if success
|
|
74
|
+
# Create relative symlinks for the AppOpticsAPM library
|
|
75
|
+
Dir.chdir(ao_lib_dir) do
|
|
76
|
+
File.symlink(ao_clib, 'liboboe.so')
|
|
77
|
+
File.symlink(ao_clib, 'liboboe-1.0.so.0')
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
dir_config('oboe', 'src', 'lib')
|
|
81
|
+
|
|
82
|
+
# create Makefile
|
|
83
|
+
if jruby || ENV.key?('APPOPTICS_URL')
|
|
84
|
+
# Build the noop extension under JRuby and Heroku.
|
|
85
|
+
# The oboe-heroku gem builds it's own c extension which links to
|
|
86
|
+
# libs specific to a Heroku dyno
|
|
87
|
+
# FIXME: For JRuby we need to remove the c extension entirely
|
|
88
|
+
create_makefile('oboe_noop', 'noop')
|
|
89
|
+
|
|
90
|
+
elsif have_library('oboe', 'oboe_config_get_revision', 'oboe.h')
|
|
91
|
+
|
|
92
|
+
$libs = append_library($libs, 'oboe')
|
|
93
|
+
$libs = append_library($libs, 'stdc++')
|
|
94
|
+
|
|
95
|
+
$CFLAGS << " #{ENV['CFLAGS']}"
|
|
96
|
+
$CPPFLAGS << " #{ENV['CPPFLAGS']}"
|
|
97
|
+
$LIBS << " #{ENV['LIBS']}"
|
|
98
|
+
$LDFLAGS << " #{ENV['LDFLAGS']} '-Wl,-rpath=$$ORIGIN/../ext/oboe_metal/lib'"
|
|
99
|
+
|
|
100
|
+
create_makefile('oboe_metal', 'src')
|
|
101
|
+
|
|
102
|
+
else
|
|
103
|
+
$stderr.puts '== ERROR ========================================================='
|
|
104
|
+
if have_library('oboe')
|
|
105
|
+
$stderr.puts "The c-library either needs to be updated or doesn't match the OS."
|
|
106
|
+
$stderr.puts 'No tracing will occur.'
|
|
107
|
+
else
|
|
108
|
+
$stderr.puts 'Could not find a matching c-library. No tracing will occur.'
|
|
109
|
+
end
|
|
110
|
+
$stderr.puts 'Contact support@appoptics.com if the problem persists.'
|
|
111
|
+
$stderr.puts '=================================================================='
|
|
112
|
+
create_makefile('oboe_noop', 'noop')
|
|
113
|
+
end
|
|
114
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.0
|
data/init.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'openssl'
|
|
6
|
+
require 'appoptics_apm/version'
|
|
7
|
+
require 'appoptics_apm/thread_local'
|
|
8
|
+
require 'appoptics_apm/logger'
|
|
9
|
+
require 'appoptics_apm/util'
|
|
10
|
+
require 'appoptics_apm/xtrace'
|
|
11
|
+
require 'appoptics_apm/support'
|
|
12
|
+
require 'appoptics_apm/base'
|
|
13
|
+
AppOpticsAPM.loaded = false
|
|
14
|
+
|
|
15
|
+
require 'appoptics_apm/config'
|
|
16
|
+
AppOpticsAPM::Config.load_config_file
|
|
17
|
+
|
|
18
|
+
begin
|
|
19
|
+
if RUBY_PLATFORM == 'java'
|
|
20
|
+
require '/usr/local/tracelytics/tracelyticsagent.jar'
|
|
21
|
+
require 'joboe_metal'
|
|
22
|
+
elsif RUBY_PLATFORM =~ /linux/
|
|
23
|
+
require_relative './oboe_metal.so'
|
|
24
|
+
require 'oboe_metal.rb' # sets AppOpticsAPM.loaded = true if successful
|
|
25
|
+
else
|
|
26
|
+
$stderr.puts '==================================================================='
|
|
27
|
+
$stderr.puts "AppOptics warning: Platform #{RUBY_PLATFORM} not yet supported."
|
|
28
|
+
$stderr.puts 'see: https://docs.appoptics.com/kb/apm_tracing/supported_platforms/'
|
|
29
|
+
$stderr.puts 'Tracing disabled.'
|
|
30
|
+
$stderr.puts 'Contact support@appoptics.com if this is unexpected.'
|
|
31
|
+
$stderr.puts '==================================================================='
|
|
32
|
+
end
|
|
33
|
+
rescue LoadError => e
|
|
34
|
+
unless ENV['RAILS_GROUP'] == 'assets' or ENV['IGNORE_APPOPTICS_WARNING']
|
|
35
|
+
$stderr.puts '=============================================================='
|
|
36
|
+
$stderr.puts 'Missing AppOpticsAPM libraries. Tracing disabled.'
|
|
37
|
+
$stderr.puts "Error: #{e.message}"
|
|
38
|
+
$stderr.puts 'See: https://docs.appoptics.com/kb/apm_tracing/ruby/'
|
|
39
|
+
$stderr.puts '=============================================================='
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# appoptics_apm/loading can set AppOpticsAPM.loaded = false if the service key is not working
|
|
44
|
+
require 'appoptics_apm/loading'
|
|
45
|
+
require 'appoptics_apm/legacy_method_profiling'
|
|
46
|
+
require 'appoptics_apm/method_profiling'
|
|
47
|
+
|
|
48
|
+
if AppOpticsAPM.loaded
|
|
49
|
+
# tracing mode is configured via config file but can only be set once we have oboe_metal loaded
|
|
50
|
+
AppOpticsAPM.set_tracing_mode(AppOpticsAPM::Config[:tracing_mode].to_sym)
|
|
51
|
+
require 'appoptics_apm/instrumentation'
|
|
52
|
+
|
|
53
|
+
# Frameworks
|
|
54
|
+
require 'appoptics_apm/frameworks/rails'
|
|
55
|
+
require 'appoptics_apm/frameworks/sinatra'
|
|
56
|
+
require 'appoptics_apm/frameworks/padrino'
|
|
57
|
+
require 'appoptics_apm/frameworks/grape'
|
|
58
|
+
else
|
|
59
|
+
$stderr.puts '=============================================================='
|
|
60
|
+
$stderr.puts 'AppOpticsAPM not loaded. Tracing disabled.'
|
|
61
|
+
$stderr.puts 'Service Key may be wrong or missing.'
|
|
62
|
+
$stderr.puts '=============================================================='
|
|
63
|
+
require 'appoptics_apm/noop/context'
|
|
64
|
+
require 'appoptics_apm/noop/metadata'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Load Ruby module last. If there is no framework detected,
|
|
68
|
+
# it will load all of the Ruby instrumentation
|
|
69
|
+
require 'appoptics_apm/ruby'
|
|
70
|
+
require 'oboe/backward_compatibility'
|
|
71
|
+
|
|
72
|
+
require 'appoptics_apm/test' if ENV['APPOPTICS_GEM_TEST']
|
|
73
|
+
rescue => e
|
|
74
|
+
$stderr.puts "[appoptics_apm/error] Problem loading: #{e.inspect}"
|
|
75
|
+
$stderr.puts e.backtrace
|
|
76
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
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::Profiling
|
|
10
|
+
extend AppOpticsAPM::API::LayerInit
|
|
11
|
+
extend AppOpticsAPM::API::Util
|
|
12
|
+
|
|
13
|
+
require_relative './sdk/tracing'
|
|
14
|
+
require_relative './sdk/custom_metrics'
|
|
15
|
+
|
|
16
|
+
extend AppOpticsAPM::SDK::Tracing
|
|
17
|
+
extend AppOpticsAPM::SDK::CustomMetrics
|
|
18
|
+
extend AppOpticsAPM::API::Tracing
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2016 SolarWinds, LLC.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#++
|
|
5
|
+
|
|
6
|
+
module AppOpticsAPM
|
|
7
|
+
module API
|
|
8
|
+
##
|
|
9
|
+
# Provides methods related to layer initialization and reporting
|
|
10
|
+
module LayerInit #:nodoc:
|
|
11
|
+
# Internal: Report that instrumentation for the given layer has been
|
|
12
|
+
# installed, as well as the version of instrumentation and version of
|
|
13
|
+
# layer.
|
|
14
|
+
#
|
|
15
|
+
def report_init(layer = :rack) #:nodoc:
|
|
16
|
+
# Don't send __Init in test or if AppOpticsAPM
|
|
17
|
+
# isn't fully loaded (e.g. missing c-extension)
|
|
18
|
+
return if ENV.key?('APPOPTICS_GEM_TEST') || !AppOpticsAPM.loaded
|
|
19
|
+
|
|
20
|
+
platform_info = AppOpticsAPM::Util.build_init_report
|
|
21
|
+
log_init(layer, platform_info)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# :nodoc:
|
|
26
|
+
# Deprecated:
|
|
27
|
+
# force_trace has been deprecated and will be removed in a subsequent version.
|
|
28
|
+
#
|
|
29
|
+
def force_trace
|
|
30
|
+
AppOpticsAPM.logger.warn '[appoptics_apm/api] AppOpticsAPM::API::LayerInit.force_trace has been deprecated and will be ' \
|
|
31
|
+
'removed in a subsequent version.'
|
|
32
|
+
|
|
33
|
+
saved_mode = AppOpticsAPM::Config[:tracing_mode]
|
|
34
|
+
AppOpticsAPM::Config[:tracing_mode] = :always
|
|
35
|
+
yield
|
|
36
|
+
ensure
|
|
37
|
+
AppOpticsAPM::Config[:tracing_mode] = saved_mode
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,375 @@
|
|
|
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
|
|
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
|
+
opts.merge!(:Backtrace => exception.backtrace.join("\r\n")) if exception.backtrace
|
|
84
|
+
|
|
85
|
+
exception.instance_variable_set(:@exn_logged, true)
|
|
86
|
+
log(layer, :error, opts)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
##
|
|
90
|
+
# Public: Decide whether or not to start a trace, and report an entry event
|
|
91
|
+
# appropriately.
|
|
92
|
+
#
|
|
93
|
+
# ==== Arguments
|
|
94
|
+
#
|
|
95
|
+
# * +layer+ - The layer the reported event belongs to
|
|
96
|
+
# * +xtrace+ - An xtrace metadata string, or nil. Used for cross-application tracing.
|
|
97
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
98
|
+
#
|
|
99
|
+
# ==== Example
|
|
100
|
+
#
|
|
101
|
+
# AppOpticsAPM::API.log_start(:layer_name, nil, { :id => @user.id })
|
|
102
|
+
#
|
|
103
|
+
# Returns an xtrace metadata string if we are tracing
|
|
104
|
+
def log_start(layer, xtrace = nil, opts = {})
|
|
105
|
+
return if !AppOpticsAPM.loaded || (opts.key?(:URL) && AppOpticsAPM::Util.static_asset?(opts[:URL]))
|
|
106
|
+
|
|
107
|
+
#--
|
|
108
|
+
# Is the below necessary? Only on JRuby? Could there be an existing context but not x-trace header?
|
|
109
|
+
# See discussion at:
|
|
110
|
+
# https://github.com/librato/ruby-tracelytics/pull/6/files?diff=split#r131029135
|
|
111
|
+
#
|
|
112
|
+
# Used by JRuby/Java webservers such as Tomcat
|
|
113
|
+
# AppOpticsAPM::Context.fromString(xtrace) if AppOpticsAPM.pickup_context?(xtrace)
|
|
114
|
+
|
|
115
|
+
# if AppOpticsAPM.tracing?
|
|
116
|
+
# # Pre-existing context. Either we inherited context from an
|
|
117
|
+
# # incoming X-Trace request header or under JRuby, Joboe started
|
|
118
|
+
# # tracing before the JRuby code was called (e.g. Tomcat)
|
|
119
|
+
# AppOpticsAPM.is_continued_trace = true
|
|
120
|
+
|
|
121
|
+
# if AppOpticsAPM.has_xtrace_header
|
|
122
|
+
# opts[:TraceOrigin] = :continued_header
|
|
123
|
+
# elsif AppOpticsAPM.has_incoming_context
|
|
124
|
+
# opts[:TraceOrigin] = :continued_context
|
|
125
|
+
# else
|
|
126
|
+
# opts[:TraceOrigin] = :continued
|
|
127
|
+
# end
|
|
128
|
+
|
|
129
|
+
# return log_entry(layer, opts)
|
|
130
|
+
# end
|
|
131
|
+
#++
|
|
132
|
+
|
|
133
|
+
# This is a bit ugly, but here is the best place to reset the layer_op thread local var.
|
|
134
|
+
AppOpticsAPM.layer_op = nil unless AppOpticsAPM::Context.isValid
|
|
135
|
+
|
|
136
|
+
if AppOpticsAPM.sample?(opts.merge(:xtrace => xtrace))
|
|
137
|
+
# Yes, we're sampling this request
|
|
138
|
+
# Probablistic tracing of a subset of requests based off of
|
|
139
|
+
# sample rate and sample source
|
|
140
|
+
opts[:SampleRate] = AppOpticsAPM.sample_rate
|
|
141
|
+
opts[:SampleSource] = AppOpticsAPM.sample_source
|
|
142
|
+
opts[:TraceOrigin] = :always_sampled
|
|
143
|
+
|
|
144
|
+
if xtrace_v2?(xtrace)
|
|
145
|
+
# continue valid incoming xtrace
|
|
146
|
+
# use it for current context, ensuring sample bit is set
|
|
147
|
+
AppOpticsAPM::XTrace.set_sampled(xtrace)
|
|
148
|
+
|
|
149
|
+
md = AppOpticsAPM::Metadata.fromString(xtrace)
|
|
150
|
+
AppOpticsAPM::Context.fromString(xtrace)
|
|
151
|
+
log_event(layer, :entry, md.createEvent, opts)
|
|
152
|
+
else
|
|
153
|
+
# discard invalid incoming xtrace
|
|
154
|
+
# create a new context, ensuring sample bit set
|
|
155
|
+
md = AppOpticsAPM::Metadata.makeRandom(true)
|
|
156
|
+
AppOpticsAPM::Context.set(md)
|
|
157
|
+
log_event(layer, :entry, AppOpticsAPM::Event.startTrace(md), opts)
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
# No, we're not sampling this request
|
|
161
|
+
# set the context but don't log the event
|
|
162
|
+
if xtrace_v2?(xtrace)
|
|
163
|
+
# continue valid incoming xtrace
|
|
164
|
+
# use it for current context, ensuring sample bit is not set
|
|
165
|
+
AppOpticsAPM::XTrace.unset_sampled(xtrace)
|
|
166
|
+
AppOpticsAPM::Context.fromString(xtrace)
|
|
167
|
+
else
|
|
168
|
+
# discard invalid incoming xtrace
|
|
169
|
+
# create a new context, ensuring sample bit not set
|
|
170
|
+
md = AppOpticsAPM::Metadata.makeRandom(false)
|
|
171
|
+
AppOpticsAPM::Context.fromString(md.toString)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
AppOpticsAPM::Context.toString
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Public: Report an exit event and potentially clear the tracing context.
|
|
179
|
+
#
|
|
180
|
+
# ==== Arguments
|
|
181
|
+
#
|
|
182
|
+
# * +layer+ - The layer the reported event belongs to
|
|
183
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
184
|
+
#
|
|
185
|
+
# ==== Example
|
|
186
|
+
#
|
|
187
|
+
# AppOpticsAPM::API.log_end(:layer_name, { :id => @user.id })
|
|
188
|
+
#
|
|
189
|
+
# Returns an xtrace metadata string if we are tracing
|
|
190
|
+
def log_end(layer, opts = {}, event = nil)
|
|
191
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
|
192
|
+
|
|
193
|
+
event ||= AppOpticsAPM::Context.createEvent
|
|
194
|
+
log_event(layer, :exit, event, opts)
|
|
195
|
+
ensure
|
|
196
|
+
# FIXME has_incoming_context commented out, it has importance for JRuby only but breaks Ruby tests
|
|
197
|
+
AppOpticsAPM::Context.clear # unless AppOpticsAPM.has_incoming_context?
|
|
198
|
+
AppOpticsAPM.transaction_name = nil
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
##
|
|
202
|
+
# Public: Log an entry event
|
|
203
|
+
#
|
|
204
|
+
# A helper method to create and log an entry event
|
|
205
|
+
#
|
|
206
|
+
# ==== Arguments
|
|
207
|
+
#
|
|
208
|
+
# * +layer+ - The layer the reported event belongs to
|
|
209
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
210
|
+
# * +op+ - To identify the current operation being traced. Used to avoid double tracing recursive calls.
|
|
211
|
+
#
|
|
212
|
+
# ==== Example
|
|
213
|
+
#
|
|
214
|
+
# AppOpticsAPM::API.log_entry(:layer_name, { :id => @user.id })
|
|
215
|
+
#
|
|
216
|
+
# Returns an xtrace metadata string if we are tracing
|
|
217
|
+
def log_entry(layer, opts = {}, op = nil)
|
|
218
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
|
219
|
+
|
|
220
|
+
AppOpticsAPM.layer_op = (AppOpticsAPM.layer_op || []) << op.to_sym if op
|
|
221
|
+
log_event(layer, :entry, AppOpticsAPM::Context.createEvent, opts)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
##
|
|
225
|
+
# Public: Log an info event
|
|
226
|
+
#
|
|
227
|
+
# A helper method to create and log an info event
|
|
228
|
+
#
|
|
229
|
+
# ==== Arguments
|
|
230
|
+
#
|
|
231
|
+
# * +layer+ - The layer the reported event belongs to
|
|
232
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
233
|
+
#
|
|
234
|
+
# ==== Example
|
|
235
|
+
#
|
|
236
|
+
# AppOpticsAPM::API.log_info(:layer_name, { :id => @user.id })
|
|
237
|
+
#
|
|
238
|
+
# Returns an xtrace metadata string if we are tracing
|
|
239
|
+
def log_info(layer, opts = {})
|
|
240
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
|
241
|
+
|
|
242
|
+
log_event(layer, :info, AppOpticsAPM::Context.createEvent, opts)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
##
|
|
246
|
+
# Public: Log an exit event
|
|
247
|
+
#
|
|
248
|
+
# A helper method to create and log an exit event
|
|
249
|
+
#
|
|
250
|
+
# ==== Arguments
|
|
251
|
+
#
|
|
252
|
+
# * +layer+ - The layer the reported event belongs to
|
|
253
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
254
|
+
# * +op+ - Used to avoid double tracing recursive calls, needs to be true in +log_exit+ that corresponds to a
|
|
255
|
+
# +log_entry+
|
|
256
|
+
#
|
|
257
|
+
# ==== Example
|
|
258
|
+
#
|
|
259
|
+
# AppOpticsAPM::API.log_exit(:layer_name, { :id => @user.id })
|
|
260
|
+
#
|
|
261
|
+
# Returns an xtrace metadata string if we are tracing
|
|
262
|
+
def log_exit(layer, opts = {}, op = nil)
|
|
263
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
|
264
|
+
|
|
265
|
+
AppOpticsAPM.layer_op.pop if op && AppOpticsAPM.layer_op.is_a?(Array) && AppOpticsAPM.layer_op.last == op.to_sym
|
|
266
|
+
|
|
267
|
+
log_event(layer, :exit, AppOpticsAPM::Context.createEvent, opts)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
##
|
|
271
|
+
# Public: Log an exit event from multiple requests
|
|
272
|
+
#
|
|
273
|
+
# A helper method to create and log an info event
|
|
274
|
+
# If we return from a request that faned out multiple requests
|
|
275
|
+
# we can add the collected X-Traces to the exit event
|
|
276
|
+
#
|
|
277
|
+
# ==== Arguments
|
|
278
|
+
#
|
|
279
|
+
# * +layer+ - The layer the reported event belongs to
|
|
280
|
+
# * +traces+ - An array with X-Trace strings returned from the requests
|
|
281
|
+
#
|
|
282
|
+
def log_multi_exit(layer, traces)
|
|
283
|
+
return AppOpticsAPM::Context.toString unless AppOpticsAPM.tracing?
|
|
284
|
+
task_id = AppOpticsAPM::XTrace.task_id(AppOpticsAPM::Context.toString)
|
|
285
|
+
event = AppOpticsAPM::Context.createEvent
|
|
286
|
+
traces.each do |trace|
|
|
287
|
+
event.addEdgeStr(trace) if AppOpticsAPM::XTrace.task_id(trace) == task_id
|
|
288
|
+
end
|
|
289
|
+
log_event(layer, :exit, event)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
##
|
|
293
|
+
#:nodoc:
|
|
294
|
+
# Internal: Reports agent init to the collector
|
|
295
|
+
#
|
|
296
|
+
# ==== Arguments
|
|
297
|
+
#
|
|
298
|
+
# * +layer+ - The layer the reported event belongs to
|
|
299
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event
|
|
300
|
+
def log_init(layer = :rack, opts = {})
|
|
301
|
+
context = AppOpticsAPM::Metadata.makeRandom
|
|
302
|
+
return AppOpticsAPM::Context.toString unless context.isValid
|
|
303
|
+
|
|
304
|
+
event = context.createEvent
|
|
305
|
+
event.addInfo(APPOPTICS_STR_LAYER, layer.to_s)
|
|
306
|
+
event.addInfo(APPOPTICS_STR_LABEL, 'single')
|
|
307
|
+
opts.each do |k, v|
|
|
308
|
+
event.addInfo(k, v.to_s)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
AppOpticsAPM::Reporter.sendStatus(event, context)
|
|
312
|
+
AppOpticsAPM::Context.toString
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
private
|
|
316
|
+
|
|
317
|
+
##
|
|
318
|
+
#:nodoc:
|
|
319
|
+
# @private
|
|
320
|
+
# Internal: Report an event.
|
|
321
|
+
#
|
|
322
|
+
# ==== Arguments
|
|
323
|
+
#
|
|
324
|
+
# * +layer+ - The layer the reported event belongs to
|
|
325
|
+
# * +label+ - The label for the reported event. See API documentation for reserved labels and usage.
|
|
326
|
+
# * +event+ - The pre-existing AppOpticsAPM context event. See AppOpticsAPM::Context.createEvent
|
|
327
|
+
# * +opts+ - A hash containing key/value pairs that will be reported along with this event (optional).
|
|
328
|
+
#
|
|
329
|
+
# ==== Example
|
|
330
|
+
#
|
|
331
|
+
# entry = AppOpticsAPM::Context.createEvent
|
|
332
|
+
# AppOpticsAPM::API.log_event(:layer_name, 'entry', entry_event, { :id => @user.id })
|
|
333
|
+
#
|
|
334
|
+
# exit_event = AppOpticsAPM::Context.createEvent
|
|
335
|
+
# exit_event.addEdge(entry.getMetadata)
|
|
336
|
+
# AppOpticsAPM::API.log_event(:layer_name, 'exit', exit_event, { :id => @user.id })
|
|
337
|
+
#
|
|
338
|
+
def log_event(layer, label, event, opts = {})
|
|
339
|
+
event.addInfo(APPOPTICS_STR_LAYER, layer.to_s.freeze) if layer
|
|
340
|
+
event.addInfo(APPOPTICS_STR_LABEL, label.to_s.freeze)
|
|
341
|
+
|
|
342
|
+
AppOpticsAPM.layer = layer.to_sym if label == :entry
|
|
343
|
+
AppOpticsAPM.layer = nil if label == :exit
|
|
344
|
+
|
|
345
|
+
opts.each do |k, v|
|
|
346
|
+
value = nil
|
|
347
|
+
|
|
348
|
+
next unless valid_key? k
|
|
349
|
+
|
|
350
|
+
if @@ints_or_nil.include?(v.class)
|
|
351
|
+
value = v
|
|
352
|
+
elsif v.class == Set
|
|
353
|
+
value = v.to_a.to_s
|
|
354
|
+
else
|
|
355
|
+
value = v.to_s if v.respond_to?(:to_s)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
begin
|
|
359
|
+
event.addInfo(k.to_s, value)
|
|
360
|
+
rescue ArgumentError => e
|
|
361
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] Couldn't add event KV: #{k} => #{v.class}"
|
|
362
|
+
AppOpticsAPM.logger.debug "[appoptics_apm/debug] #{e.message}"
|
|
363
|
+
end
|
|
364
|
+
end if !opts.nil? && opts.any?
|
|
365
|
+
|
|
366
|
+
AppOpticsAPM::Reporter.sendReport(event)
|
|
367
|
+
AppOpticsAPM::Context.toString
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# need to set the context to public, otherwise the following `extends` will be private in api.rb
|
|
371
|
+
public
|
|
372
|
+
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
end
|