appoptics_apm_mnfst 4.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/Rakefile
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'rake/testtask'
|
8
|
+
require 'appoptics_apm/test'
|
9
|
+
|
10
|
+
Rake::TestTask.new do |t|
|
11
|
+
t.verbose = false
|
12
|
+
t.warning = false
|
13
|
+
t.ruby_opts = []
|
14
|
+
t.libs << 'test'
|
15
|
+
|
16
|
+
# Since we support so many libraries and frameworks, tests
|
17
|
+
# runs are segmented into gemfiles that have different
|
18
|
+
# sets and versions of gems (libraries and frameworks).
|
19
|
+
#
|
20
|
+
# Here we detect the Gemfile the tests are being run against
|
21
|
+
# and load the appropriate tests.
|
22
|
+
#
|
23
|
+
case AppOpticsAPM::Test.gemfile
|
24
|
+
when /delayed_job/
|
25
|
+
require 'delayed/tasks'
|
26
|
+
t.test_files = FileList['test/queues/delayed_job*_test.rb']
|
27
|
+
when /rails/
|
28
|
+
# Pre-load rails to get the major version number
|
29
|
+
require 'rails'
|
30
|
+
|
31
|
+
if Rails::VERSION::MAJOR == 5
|
32
|
+
t.test_files = FileList["test/frameworks/rails#{Rails::VERSION::MAJOR}x_test.rb"] +
|
33
|
+
FileList["test/frameworks/rails#{Rails::VERSION::MAJOR}x_api_test.rb"]
|
34
|
+
else
|
35
|
+
t.test_files = FileList["test/frameworks/rails#{Rails::VERSION::MAJOR}x_test.rb"]
|
36
|
+
end
|
37
|
+
|
38
|
+
when /frameworks/
|
39
|
+
t.test_files = FileList['test/frameworks/sinatra*_test.rb'] +
|
40
|
+
FileList['test/frameworks/padrino*_test.rb'] +
|
41
|
+
FileList['test/frameworks/grape*_test.rb']
|
42
|
+
when /libraries/
|
43
|
+
t.test_files = FileList['test/support/*_test.rb'] +
|
44
|
+
FileList['test/reporter/*_test.rb'] +
|
45
|
+
FileList['test/instrumentation/*_test.rb'] +
|
46
|
+
FileList['test/profiling/*_test.rb'] -
|
47
|
+
['test/instrumentation/twitter-cassandra_test.rb']
|
48
|
+
when /instrumentation_mocked/
|
49
|
+
# WebMock is interfering with other tests, so these have to run separately
|
50
|
+
t.test_files = FileList['test/mocked/*_test.rb']
|
51
|
+
when /noop/
|
52
|
+
t.test_files = FileList['test/noop/*_test.rb']
|
53
|
+
when /unit/
|
54
|
+
t.test_files = FileList['test/unit/*_test.rb'] +
|
55
|
+
FileList['test/unit/*/*_test.rb']
|
56
|
+
end
|
57
|
+
|
58
|
+
if defined?(JRUBY_VERSION)
|
59
|
+
t.ruby_opts << ['-J-javaagent:/usr/local/tracelytics/tracelyticsagent.jar']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Run all test suites defined by travis"
|
64
|
+
task "docker_tests" do
|
65
|
+
Dir.chdir('test/run_tests')
|
66
|
+
exec('docker-compose run --service-ports ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh test')
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "Start docker container for testing and debugging"
|
70
|
+
task "docker" do
|
71
|
+
Dir.chdir('test/run_tests')
|
72
|
+
exec('docker-compose run --service-ports ruby_appoptics /code/ruby-appoptics/test/run_tests/ruby_setup.sh bash')
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "Fetch extension dependency files"
|
76
|
+
task :fetch_ext_deps do
|
77
|
+
swig_version = %x{swig -version} rescue ''
|
78
|
+
swig_version = swig_version.scan(/swig version 3.0.\d*/i)
|
79
|
+
if swig_version.empty?
|
80
|
+
$stderr.puts '== ERROR ================================================================='
|
81
|
+
$stderr.puts "Could not find required swig version 3.0.*, found #{swig_version.inspect}"
|
82
|
+
$stderr.puts 'Please install swig "~ 3.0.8" and try again.'
|
83
|
+
$stderr.puts '=========================================================================='
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
|
87
|
+
# The c-lib version is different from the gem version
|
88
|
+
oboe_version = ENV['OBOE_VERSION'] || 'latest'
|
89
|
+
oboe_s3_dir = "https://s3-us-west-2.amazonaws.com/rc-files-t2/c-lib/#{oboe_version}"
|
90
|
+
ext_src_dir = File.expand_path('ext/oboe_metal/src')
|
91
|
+
|
92
|
+
# VERSION is used by extconf.rb to download the correct liboboe when installing the gem
|
93
|
+
remote_file = File.join(oboe_s3_dir, 'VERSION')
|
94
|
+
local_file = File.join(ext_src_dir, 'VERSION')
|
95
|
+
puts "fetching #{remote_file} to #{local_file}"
|
96
|
+
open(remote_file, 'rb') do |rf|
|
97
|
+
content = rf.read
|
98
|
+
File.open(local_file, 'wb') { |f| f.puts content }
|
99
|
+
puts "!!!!!!! C-Lib VERSION: #{content.strip} !!!!!!!!"
|
100
|
+
end
|
101
|
+
|
102
|
+
# oboe and bson header files
|
103
|
+
FileUtils.mkdir_p(File.join(ext_src_dir, 'bson'))
|
104
|
+
%w(oboe.h oboe.hpp oboe_debug.h oboe.i bson/bson.h bson/platform_hacks.h).each do |filename|
|
105
|
+
remote_file = File.join(oboe_s3_dir, 'include', filename)
|
106
|
+
local_file = File.join(ext_src_dir, filename)
|
107
|
+
|
108
|
+
puts "fetching #{remote_file} to #{local_file}"
|
109
|
+
open(remote_file, 'rb') do |rf|
|
110
|
+
content = rf.read
|
111
|
+
File.open(local_file, 'wb') { |f| f.puts content }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
FileUtils.cd(ext_src_dir) do
|
116
|
+
system('swig -c++ -ruby -module oboe_metal oboe.i')
|
117
|
+
FileUtils.rm('oboe.i')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "Build the gem's c extension"
|
122
|
+
task :compile do
|
123
|
+
if !defined?(JRUBY_VERSION)
|
124
|
+
puts "== Building the c extension against Ruby #{RUBY_VERSION}"
|
125
|
+
|
126
|
+
pwd = Dir.pwd
|
127
|
+
ext_dir = File.expand_path('ext/oboe_metal')
|
128
|
+
final_so = File.expand_path('lib/oboe_metal.so')
|
129
|
+
so_file = File.expand_path('ext/oboe_metal/oboe_metal.so')
|
130
|
+
|
131
|
+
Dir.chdir ext_dir
|
132
|
+
ENV['APPOPTICS_FROM_S3'] = 'true'
|
133
|
+
cmd = [Gem.ruby, 'extconf.rb']
|
134
|
+
sh cmd.join(' ')
|
135
|
+
sh '/usr/bin/env make'
|
136
|
+
|
137
|
+
File.delete(final_so) if File.exist?(final_so)
|
138
|
+
|
139
|
+
if File.exist?(so_file)
|
140
|
+
FileUtils.mv(so_file, final_so)
|
141
|
+
Dir.chdir(pwd)
|
142
|
+
puts "== Extension built and moved to #{final_so}"
|
143
|
+
else
|
144
|
+
Dir.chdir(pwd)
|
145
|
+
puts '!! Extension failed to build (see above). Have the required binary and header files been fetched?'
|
146
|
+
puts '!! Try the tasks in this order: clean > fetch_ext_deps > compile.'
|
147
|
+
end
|
148
|
+
else
|
149
|
+
puts '== Nothing to do under JRuby.'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
desc 'Clean up extension build files'
|
154
|
+
task :clean do
|
155
|
+
if !defined?(JRUBY_VERSION)
|
156
|
+
pwd = Dir.pwd
|
157
|
+
ext_dir = File.expand_path('ext/oboe_metal')
|
158
|
+
symlinks = [
|
159
|
+
File.expand_path('lib/oboe_metal.so'),
|
160
|
+
File.expand_path('ext/oboe_metal/lib/liboboe.so'),
|
161
|
+
File.expand_path('ext/oboe_metal/lib/liboboe-1.0.so.0')
|
162
|
+
]
|
163
|
+
|
164
|
+
symlinks.each do |symlink|
|
165
|
+
FileUtils.rm_f symlink
|
166
|
+
end
|
167
|
+
Dir.chdir ext_dir
|
168
|
+
sh '/usr/bin/env make clean' if File.exist? 'Makefile'
|
169
|
+
|
170
|
+
Dir.chdir pwd
|
171
|
+
else
|
172
|
+
puts '== Nothing to do under JRuby.'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
desc 'Remove all built files and extensions'
|
177
|
+
task :distclean do
|
178
|
+
if !defined?(JRUBY_VERSION)
|
179
|
+
pwd = Dir.pwd
|
180
|
+
ext_dir = File.expand_path('ext/oboe_metal')
|
181
|
+
mkmf_log = File.expand_path('ext/oboe_metal/mkmf.log')
|
182
|
+
symlinks = [
|
183
|
+
File.expand_path('lib/oboe_metal.so'),
|
184
|
+
File.expand_path('ext/oboe_metal/lib/liboboe.so'),
|
185
|
+
File.expand_path('ext/oboe_metal/lib/liboboe-1.0.so.0')
|
186
|
+
]
|
187
|
+
|
188
|
+
if File.exist? mkmf_log
|
189
|
+
symlinks.each do |symlink|
|
190
|
+
FileUtils.rm_f symlink
|
191
|
+
end
|
192
|
+
Dir.chdir ext_dir
|
193
|
+
sh '/usr/bin/env make distclean' if File.exist? 'Makefile'
|
194
|
+
|
195
|
+
Dir.chdir pwd
|
196
|
+
else
|
197
|
+
puts 'Nothing to distclean. (nothing built yet?)'
|
198
|
+
end
|
199
|
+
else
|
200
|
+
puts '== Nothing to do under JRuby.'
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
desc "Rebuild the gem's c extension"
|
205
|
+
task :recompile => [:distclean, :compile]
|
206
|
+
|
207
|
+
task :environment do
|
208
|
+
ENV['APPOPTICS_GEM_VERBOSE'] = 'true'
|
209
|
+
|
210
|
+
Bundler.require(:default, :development)
|
211
|
+
AppOpticsAPM::Config[:tracing_mode] = :always
|
212
|
+
AppOpticsAPM::Test.load_extras
|
213
|
+
|
214
|
+
if AppOpticsAPM::Test.gemfile?(:delayed_job)
|
215
|
+
require 'delayed/tasks'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
task :console => :environment do
|
220
|
+
ARGV.clear
|
221
|
+
if AppOpticsAPM::Test.gemfile?(:delayed_job)
|
222
|
+
require './test/servers/delayed_job'
|
223
|
+
end
|
224
|
+
Pry.start
|
225
|
+
end
|
226
|
+
|
227
|
+
# Used when testing Resque locally
|
228
|
+
task 'resque:setup' => :environment do
|
229
|
+
require 'resque/tasks'
|
230
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "appoptics_apm/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = %q{appoptics_apm_mnfst}
|
6
|
+
s.version = AppOpticsAPM::Version::STRING
|
7
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
8
|
+
|
9
|
+
s.license = "Librato Open License, Version 1.0"
|
10
|
+
|
11
|
+
s.authors = ["Maia Engeli", "Peter Giacomo Lombardo", "Spiros Eliopoulos"]
|
12
|
+
s.email = %q{support@appoptics.com}
|
13
|
+
s.homepage = %q{https://www.appoptics.com/}
|
14
|
+
s.summary = %q{AppOptics APM performance instrumentation gem for Ruby}
|
15
|
+
s.description = <<-EOF
|
16
|
+
Automatic tracing and metrics for Ruby applications. Get started at appoptics.com. @AppOptics
|
17
|
+
EOF
|
18
|
+
|
19
|
+
s.metadata = {
|
20
|
+
'changelog_uri' => 'https://github.com/appoptics/appoptics-apm-ruby/releases',
|
21
|
+
'documentation_uri' => 'https://docs.appoptics.com/kb/apm_tracing/ruby/',
|
22
|
+
'homepage_uri' => 'https://www.appoptics.com/',
|
23
|
+
'source_code_uri' => 'https://github.com/appoptics/appoptics-apm-ruby',
|
24
|
+
}
|
25
|
+
|
26
|
+
s.extra_rdoc_files = ['LICENSE']
|
27
|
+
s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|gemfiles)/}) }
|
28
|
+
s.files += ['ext/oboe_metal/src/oboe.h',
|
29
|
+
'ext/oboe_metal/src/oboe.hpp',
|
30
|
+
'ext/oboe_metal/src/oboe_debug.h',
|
31
|
+
'ext/oboe_metal/src/oboe_wrap.cxx',
|
32
|
+
'ext/oboe_metal/src/bson/bson.h',
|
33
|
+
'ext/oboe_metal/src/bson/platform_hacks.h',
|
34
|
+
'ext/oboe_metal/src/VERSION']
|
35
|
+
|
36
|
+
# TODO this is commented out util we can actually provide gems for different platforms
|
37
|
+
# it will create a gem that goes into noop on Darwin and other unsupported platforms
|
38
|
+
# s.platform = defined?(JRUBY_VERSION) ? 'java' : Gem::Platform::CURRENT
|
39
|
+
|
40
|
+
s.extensions = ['ext/oboe_metal/extconf.rb'] unless defined?(JRUBY_VERSION)
|
41
|
+
|
42
|
+
s.add_runtime_dependency('json', '>= 0')
|
43
|
+
s.add_runtime_dependency('no_proxy_fix', '~> 0.1.2', '>= 0.1.2')
|
44
|
+
|
45
|
+
# Development dependencies used in gem development & testing
|
46
|
+
s.add_development_dependency('rake', '>= 0.9.0')
|
47
|
+
s.add_development_dependency('simplecov', '>= 0.16.0') if ENV["SIMPLECOV_COVERAGE"]
|
48
|
+
s.add_development_dependency('simplecov-console', '>= 0.4.0') if ENV["SIMPLECOV_COVERAGE"]
|
49
|
+
|
50
|
+
unless defined?(JRUBY_VERSION)
|
51
|
+
s.add_development_dependency('byebug', '>= 8.0.0')
|
52
|
+
s.add_development_dependency('pry', '>= 0.10.0')
|
53
|
+
s.add_development_dependency('pry-byebug', '>= 3.0.0')
|
54
|
+
s.add_development_dependency('minitest-hooks', '>= 1.5.0')
|
55
|
+
else
|
56
|
+
s.add_development_dependency('pry', '>= 0.10.0')
|
57
|
+
end
|
58
|
+
|
59
|
+
s.required_ruby_version = '>= 2.0.0'
|
60
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
61
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# execute this with `bundle exec appoptics_apm_config`
|
5
|
+
# copies the configuration template file into the current directory
|
6
|
+
#
|
7
|
+
|
8
|
+
puts "Copying the configuration template file to appoptics_apm_config_tmp.rb"
|
9
|
+
puts "Edit and save as appoptics_apm_config.rb"
|
10
|
+
|
11
|
+
target_file = File.join(Dir.pwd, 'appoptics_apm_config_tmp.rb')
|
12
|
+
temp_orig = File.join(File.dirname(File.dirname(__FILE__)),
|
13
|
+
'lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb')
|
14
|
+
|
15
|
+
FileUtils.copy(temp_orig, target_file)
|
data/build_gem.sh
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
# builds the appoptics_apm gem for MRI.
|
3
|
+
|
4
|
+
# we currently only build for MRI, no JRuby
|
5
|
+
echo -e "\n=== building for MRI ===\n"
|
6
|
+
rm -f Gemfile.lock
|
7
|
+
bundle install
|
8
|
+
bundle exec rake distclean
|
9
|
+
bundle exec rake fetch_ext_deps
|
10
|
+
gem build appoptics_apm.gemspec
|
11
|
+
|
12
|
+
echo -e "\n=== built gems ===\n"
|
13
|
+
ls -la appoptics_apm*.gem
|
14
|
+
|
15
|
+
echo -e "\n=== publish to rubygems via: gem push <gem> ===\n"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# build the gem,
|
4
|
+
# oboe/c-lib version can be given as optional parameter
|
5
|
+
if [ "$1" != "" ]; then
|
6
|
+
OBOE_VERSION=$1 ./build_gem.sh
|
7
|
+
else
|
8
|
+
./build_gem.sh
|
9
|
+
fi
|
10
|
+
|
11
|
+
# save current rbenv setting and switch to 2.4.1 for the package_cloud commands
|
12
|
+
current_ruby=`rbenv global`
|
13
|
+
rbenv global 2.4.1
|
14
|
+
|
15
|
+
# prerequisite: package_cloud token needs to be in ~/.packagecloud
|
16
|
+
gem=`ls -dt1 appoptics_apm-[^pre]*.gem | head -1`
|
17
|
+
package_cloud push solarwinds/appoptics-apm-ruby $gem
|
18
|
+
|
19
|
+
# restore ruby version
|
20
|
+
rbenv global $current_ruby
|
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
###############################################################
|
3
|
+
# BASIC TRACING EXAMPLES
|
4
|
+
###############################################################
|
5
|
+
|
6
|
+
# set APPOPTICS_SERVICE_KEY and run with
|
7
|
+
# `bundle exec ruby 01_basic_tracing.rb`
|
8
|
+
|
9
|
+
require 'appoptics_apm'
|
10
|
+
unless AppopticsAPM::SDK.appoptics_ready(10_000)
|
11
|
+
puts "aborting!!! Agent not ready after 10 seconds"
|
12
|
+
exit false
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
###############################################################
|
17
|
+
# Starting a trace and adding a span
|
18
|
+
###############################################################
|
19
|
+
|
20
|
+
# USE CASE:
|
21
|
+
# You may want to either trace a piece of your own code or a
|
22
|
+
# call to a method from a gem that isn't auto-instrumented by
|
23
|
+
# appoptics_apm
|
24
|
+
|
25
|
+
# The first example will not create a span, because no trace has
|
26
|
+
# been started, but the second and third ones will.
|
27
|
+
|
28
|
+
# The string argument is the name for the span
|
29
|
+
|
30
|
+
##
|
31
|
+
# AppOpticsAPM::SDK.trace()
|
32
|
+
# most of the time this is the method you need. It adds a span
|
33
|
+
# to a trace that has probably been started by rack.
|
34
|
+
|
35
|
+
# Example 1
|
36
|
+
def do_work
|
37
|
+
42
|
38
|
+
end
|
39
|
+
|
40
|
+
AppOpticsAPM::SDK.trace('simple_span') do
|
41
|
+
do_work
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# AppOpticsAPM::SDK.start_trace()
|
46
|
+
# This method starts a trace. It is handy for background jobs,
|
47
|
+
# workers, or scripts, that are not part of a rack application
|
48
|
+
|
49
|
+
# Example 2
|
50
|
+
AppOpticsAPM::SDK.start_trace('outer_span') do
|
51
|
+
|
52
|
+
AppOpticsAPM::SDK.trace('simple_span') do
|
53
|
+
do_work
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# Example 3
|
59
|
+
def do_traced_work
|
60
|
+
AppOpticsAPM::SDK.trace('simple_span_2') do
|
61
|
+
do_work
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
AppOpticsAPM::SDK.start_trace('outer_span_2') do
|
66
|
+
do_traced_work
|
67
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
###############################################################
|
2
|
+
# A brief overview of AppOpticsAPM tracing context
|
3
|
+
###############################################################
|
4
|
+
#
|
5
|
+
# Tracing context is the state held when AppOpticsAPM is instrumenting a
|
6
|
+
# transaction, block, request etc.. This context is advanced as
|
7
|
+
# new blocks are instrumented and this chain of context is used
|
8
|
+
# by AppOpticsAPM to later reassemble performance data to be displayed
|
9
|
+
# in the AppOptics dashboard.
|
10
|
+
#
|
11
|
+
# Tracing context is non-existent until established by calling
|
12
|
+
# `AppOpticsAPM::API.start_trace` or `AppOpticsAPM::API.log_start`. Those methods
|
13
|
+
# are part of the high-level and low-level API respectively.
|
14
|
+
#
|
15
|
+
# After a tracing context is established, that context can be
|
16
|
+
# continued by calling `AppOpticsAPM::API.trace` or `AppOpticsAPM::API.log_entry`.
|
17
|
+
# These methods will advance an existing context but not start
|
18
|
+
# new one.
|
19
|
+
#
|
20
|
+
# For example, when a web request comes into a stack, a tracing
|
21
|
+
# context is established using `AppOpticsAPM::API.log_start` as the request
|
22
|
+
# enters through the rack middleware via `AppOpticsAPM::Rack`.
|
23
|
+
#
|
24
|
+
# That tracing context is then continued using `AppOpticsAPM::API.trace` or
|
25
|
+
# `AppOpticsAPM::API.log_entry` for each subsequent layer such as Rails,
|
26
|
+
# ActiveRecord, Redis, Memcache, ActionView, Mongo (etc...) until
|
27
|
+
# finally request processing is complete and the tracing context
|
28
|
+
# is cleared (AppOpticsAPM::Context.clear)
|
29
|
+
#
|
30
|
+
|
31
|
+
###############################################################
|
32
|
+
# Carrying Context
|
33
|
+
###############################################################
|
34
|
+
#
|
35
|
+
# The tracing context exists in the form of an X-Trace string and
|
36
|
+
# can be retrieved using 'AppOpticsAPM::Context.toString'
|
37
|
+
#
|
38
|
+
# xtrace = AppOpticsAPM::Context.toString
|
39
|
+
#
|
40
|
+
# => "1B4EDAB9E028CA3C81BCD57CC4644B4C4AE239C7B713F0BCB9FAD6D562"
|
41
|
+
#
|
42
|
+
# Tracing context can also be picked up from a pre-existing
|
43
|
+
# X-Trace string:
|
44
|
+
#
|
45
|
+
# xtrace = "1B4EDAB9E028CA3C81BCD57CC4644B4C4AE239C7B713F0BCB9FAD6D562"
|
46
|
+
#
|
47
|
+
# AppOpticsAPM::Context.fromString(xtrace)
|
48
|
+
#
|
49
|
+
# With these two methods, context can be passed across threads,
|
50
|
+
# processes (via fork) and in requests (such as external HTTP
|
51
|
+
# requests where the X-Trace is inserted in request headers).
|
52
|
+
#
|
53
|
+
#
|
54
|
+
|
55
|
+
###############################################################
|
56
|
+
# Two Options for Spawned Tracing
|
57
|
+
###############################################################
|
58
|
+
#
|
59
|
+
# When your application needs to instrument code that forks,
|
60
|
+
# spawns a thread or does something in-parallel, you have the
|
61
|
+
# option to either link those child traces to the parent or
|
62
|
+
# trace them as individuals (but with identifying information).
|
63
|
+
#
|
64
|
+
# Linking parent and child has it's benefits as in the
|
65
|
+
# AppOptics dashboard, you will see how a process may spawn
|
66
|
+
# a task in parallel and in a single view see the performance
|
67
|
+
# of both.
|
68
|
+
#
|
69
|
+
# The limitation of this is that this is only useful if your
|
70
|
+
# parent process spawns only a limited number of child traces.
|
71
|
+
#
|
72
|
+
# If your parent process is spawning many child tasks (e.g.
|
73
|
+
# twenty, hundreds, thousands or more) it's best to trace those
|
74
|
+
# child tasks as individuals and pass in identifier Key-Values
|
75
|
+
# (such as task ID, job ID etc..)
|
76
|
+
#
|
77
|
+
# In the examples below, I show implementations of both linked
|
78
|
+
# asynchronous traces and separated independent traces.
|
79
|
+
|
80
|
+
###############################################################
|
81
|
+
# Thread - with separated traces
|
82
|
+
###############################################################
|
83
|
+
|
84
|
+
AppOpticsAPM::API.log_start('parent')
|
85
|
+
|
86
|
+
# Get the work to be done
|
87
|
+
job = get_work
|
88
|
+
|
89
|
+
Thread.new do
|
90
|
+
# This is a new thread so there is no pre-existing context so
|
91
|
+
# we'll call `AppOpticsAPM::API.log_start` to start a new trace context.
|
92
|
+
AppOpticsAPM::API.log_start('worker_thread', :job_id => job.id)
|
93
|
+
|
94
|
+
# Do the work
|
95
|
+
do_the_work(job)
|
96
|
+
|
97
|
+
AppOpticsAPM::API.log_end('worker_thread')
|
98
|
+
end
|
99
|
+
|
100
|
+
AppOpticsAPM::API.log_end('parent')
|
101
|
+
|
102
|
+
###############################################################
|
103
|
+
#
|
104
|
+
# This will generate two independent traces with the following
|
105
|
+
# topology.
|
106
|
+
#
|
107
|
+
# 'parent'
|
108
|
+
# ------------------------------------------------------------
|
109
|
+
#
|
110
|
+
# 'worker_thread'
|
111
|
+
# ------------------------------------------------------------
|
112
|
+
#
|
113
|
+
|
114
|
+
###############################################################
|
115
|
+
# Thread - with linked asynchronous traces
|
116
|
+
###############################################################
|
117
|
+
|
118
|
+
# Since the following example spawns a thread without waiting
|
119
|
+
# for it to return, we carry over the context and we mark the
|
120
|
+
# trace generated in that thread to be asynchronous using
|
121
|
+
# the `Async` flag.
|
122
|
+
|
123
|
+
AppOpticsAPM::API.log_start('parent')
|
124
|
+
|
125
|
+
# Save the context to be imported in spawned thread
|
126
|
+
tracing_context = AppOpticsAPM::Context.toString
|
127
|
+
|
128
|
+
# Get the work to be done
|
129
|
+
job = get_work
|
130
|
+
|
131
|
+
Thread.new do
|
132
|
+
# Restore context
|
133
|
+
AppOpticsAPM::Context.fromString(tracing_context)
|
134
|
+
|
135
|
+
AppOpticsAPM::API.log_entry('worker_thread')
|
136
|
+
|
137
|
+
# Do the work
|
138
|
+
do_the_work(job)
|
139
|
+
|
140
|
+
AppOpticsAPM::API.log_exit('worker_thread', :Async => 1)
|
141
|
+
end
|
142
|
+
|
143
|
+
AppOpticsAPM::API.log_end('parent')
|
144
|
+
|
145
|
+
###############################################################
|
146
|
+
#
|
147
|
+
# This will generate a single trace with an asynchronous
|
148
|
+
# branch like the following
|
149
|
+
#
|
150
|
+
# 'parent'
|
151
|
+
# ------------------------------------------------------------
|
152
|
+
# \
|
153
|
+
# \
|
154
|
+
# ------------------------------------------------------
|
155
|
+
# 'worker_thread'
|
156
|
+
#
|
157
|
+
|
158
|
+
###############################################################
|
159
|
+
# Process via fork - with separated traces
|
160
|
+
###############################################################
|
161
|
+
|
162
|
+
AppOpticsAPM::API.start_trace('parent_process') do
|
163
|
+
# Get some work to process
|
164
|
+
job = get_job
|
165
|
+
|
166
|
+
# fork process to handle work
|
167
|
+
fork do
|
168
|
+
# Since fork does a complete process copy, the tracing_context still exists
|
169
|
+
# so we have to clear it and start again.
|
170
|
+
AppOpticsAPM::Context.clear
|
171
|
+
|
172
|
+
AppOpticsAPM::API.start_trace('worker_process', nil, :job_id => job.id) do
|
173
|
+
do_work(job)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
###############################################################
|
180
|
+
#
|
181
|
+
# This will generate two independent traces:
|
182
|
+
#
|
183
|
+
# 'parent_process'
|
184
|
+
# ------------------------------------------------------------
|
185
|
+
#
|
186
|
+
# 'worker_process'
|
187
|
+
# ------------------------------------------------------------
|
188
|
+
#
|
189
|
+
###############################################################
|
190
|
+
# Process via fork - with linked asynchronous traces
|
191
|
+
###############################################################
|
192
|
+
|
193
|
+
AppOpticsAPM::API.start_trace('parent_process') do
|
194
|
+
# Get some work to process
|
195
|
+
job = get_job
|
196
|
+
|
197
|
+
# fork process to handle work
|
198
|
+
fork do
|
199
|
+
# Since fork does a complete process copy, the tracing_context still exists
|
200
|
+
# although we'll have to mark these traces as asynchronous to denote
|
201
|
+
# that it has split off from the main program flow
|
202
|
+
|
203
|
+
AppOpticsAPM::API.trace('worker_process', :Async => 1) do
|
204
|
+
do_work(job)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
###############################################################
|
210
|
+
#
|
211
|
+
# This will generate a single trace with an asynchronous
|
212
|
+
# branch like the following
|
213
|
+
#
|
214
|
+
# 'parent_process'
|
215
|
+
# ------------------------------------------------------------
|
216
|
+
# \
|
217
|
+
# \
|
218
|
+
# ------------------------------------------------------
|
219
|
+
# 'worker_process'
|
220
|
+
#
|