appoptics_apm 4.1.1 → 4.1.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 +4 -4
- data/Dockerfile_test +4 -1
- data/appoptics_apm.gemspec +1 -1
- data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +1 -1
- data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +1 -1
- data/lib/appoptics_apm/version.rb +1 -1
- data/ruby_setup.sh +1 -1
- metadata +2 -10
- data/examples/DNT.md +0 -35
- data/examples/carrying_context.rb +0 -220
- data/examples/instrumenting_metal_controller.rb +0 -8
- data/examples/puma_on_heroku_config.rb +0 -17
- data/examples/tracing_async_threads.rb +0 -124
- data/examples/tracing_background_jobs.rb +0 -53
- data/examples/tracing_forked_processes.rb +0 -99
- data/examples/unicorn_on_heroku_config.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 279e04ea7b50365f82a752e34561e98553accfbf
|
4
|
+
data.tar.gz: 6c164062efc035368cec63f422689ae0317b8986
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58716fc2e035939241428b70b45ce5e090238c71758d72fa9b29e2fbdc11fd34f89e97d5a44d6f769d8a3edf80f6ce4e02aaea6e3b1a4b001778970cf43a81ca
|
7
|
+
data.tar.gz: aacc0674ebe52dda370cec24c6a194a4e57bc0e41dddbae3e9e93b0565350f96d42a41119fe895e4148741bfe7262a7396e1c513242a2e6f4d6303f2f3d0022f
|
data/Dockerfile_test
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
FROM ubuntu:16.04
|
2
2
|
|
3
|
+
# to use with ./run_tests_docker.rb
|
4
|
+
# docker build -f Dockerfile-test -t ruby_appoptics_apm .
|
5
|
+
|
3
6
|
# install OS packages
|
4
7
|
RUN apt-get update \
|
5
8
|
&& apt-get install -y --no-install-recommends \
|
@@ -36,7 +39,7 @@ RUN . ~/.profile \
|
|
36
39
|
&& rbenv install 2.3.6 \
|
37
40
|
&& rbenv install 2.4.3 \
|
38
41
|
&& rbenv install 2.5.0
|
39
|
-
|
42
|
+
&& rbenv install jruby-9.1.16.0
|
40
43
|
|
41
44
|
# install swig 3.0.8
|
42
45
|
RUN curl -SL http://kent.dl.sourceforge.net/project/swig/swig/swig-3.0.8/swig-3.0.8.tar.gz \
|
data/appoptics_apm.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.description = %q{The AppOpticsAPM gem provides performance instrumentation for MRI Ruby and related frameworks.}
|
16
16
|
|
17
17
|
s.extra_rdoc_files = ["LICENSE"]
|
18
|
-
s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|gemfiles)/}) }
|
18
|
+
s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|gemfiles|examples)/}) }
|
19
19
|
s.files += ['ext/oboe_metal/src/oboe.h',
|
20
20
|
'ext/oboe_metal/src/oboe.hpp',
|
21
21
|
'ext/oboe_metal/src/oboe_debug.h',
|
@@ -18,7 +18,7 @@ module AppOpticsAPM
|
|
18
18
|
:Action => self.action_name
|
19
19
|
}
|
20
20
|
request.env['appoptics_apm.controller'] = kvs[:Controller]
|
21
|
-
request.env['appoptics_apm.action'] = kvs[:
|
21
|
+
request.env['appoptics_apm.action'] = kvs[:Action]
|
22
22
|
|
23
23
|
return super(method_name, *args) unless AppOpticsAPM.tracing?
|
24
24
|
begin
|
@@ -7,7 +7,7 @@ require 'appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql'
|
|
7
7
|
|
8
8
|
if AppOpticsAPM::Config[:active_record][:enabled] && !defined?(JRUBY_VERSION)
|
9
9
|
begin
|
10
|
-
adapter = ActiveRecord::Base.
|
10
|
+
adapter = ActiveRecord::Base.configurations[Rails.env]['adapter']
|
11
11
|
|
12
12
|
if Rails::VERSION::MAJOR < 5
|
13
13
|
require 'appoptics_apm/frameworks/rails/inst/connection_adapters/utils'
|
data/ruby_setup.sh
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# used by run_tests_docker.sh
|
4
4
|
# call with:
|
5
5
|
# docker-compose run --service-ports ruby_appoptics_apm /code/ruby-appoptics_apm/ruby_setup.sh <ruby-version> <gemfile> <DBNAME=mysql2> <true|false>
|
6
|
-
# docker-compose run --service-ports ruby_appoptics_apm /code/ruby-appoptics_apm/ruby_setup.sh 2.4.
|
6
|
+
# docker-compose run --service-ports ruby_appoptics_apm /code/ruby-appoptics_apm/ruby_setup.sh 2.4.3 gemfiles/libraries.gemfile
|
7
7
|
|
8
8
|
cd /code/ruby-appoptics_apm/
|
9
9
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appoptics_apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maia Engeli
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-05-
|
13
|
+
date: 2018-05-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -133,14 +133,6 @@ files:
|
|
133
133
|
- build_gems.sh
|
134
134
|
- config/initializers/.keep
|
135
135
|
- docker-compose.yml
|
136
|
-
- examples/DNT.md
|
137
|
-
- examples/carrying_context.rb
|
138
|
-
- examples/instrumenting_metal_controller.rb
|
139
|
-
- examples/puma_on_heroku_config.rb
|
140
|
-
- examples/tracing_async_threads.rb
|
141
|
-
- examples/tracing_background_jobs.rb
|
142
|
-
- examples/tracing_forked_processes.rb
|
143
|
-
- examples/unicorn_on_heroku_config.rb
|
144
136
|
- ext/oboe_metal/extconf.rb
|
145
137
|
- ext/oboe_metal/lib/.keep
|
146
138
|
- ext/oboe_metal/noop/noop.c
|
data/examples/DNT.md
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
By default, the AppOpticsAPM gem will not trace routes with extensions
|
2
|
-
for common static files. Examples of such files may be images,
|
3
|
-
javascript, pdfs and text files.
|
4
|
-
|
5
|
-
This is done by using the regular expression stored in
|
6
|
-
`AppOpticsAPM::Config[:dnt_regexp]`:
|
7
|
-
|
8
|
-
.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|ttf|woff|svg|less)$
|
9
|
-
|
10
|
-
This string is used as a regular expression and is tested against
|
11
|
-
candidate URLs to be instrumented.
|
12
|
-
|
13
|
-
To replace the pattern in use, you can update this regular expression
|
14
|
-
string. Here are some examples.
|
15
|
-
|
16
|
-
If you prefer that you want your javascript and CSS files instrumented,
|
17
|
-
you can update `AppOpticsAPM::Config[:dnt_regexp]` with an updated regexp
|
18
|
-
pattern (without the "js" and "css" entries):
|
19
|
-
|
20
|
-
.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|flv|swf|ttf|woff|svg|less)$
|
21
|
-
|
22
|
-
If you prefer to not instrument all javascript files except for one
|
23
|
-
named `show.js`, you could put this assignment into your initializer,
|
24
|
-
rackup file or application.rb (note that this example uses a standard
|
25
|
-
regexp [negative
|
26
|
-
look-behind](http://www.regular-expressions.info/lookaround.html) that
|
27
|
-
isn't supported in Ruby 1.8):
|
28
|
-
|
29
|
-
AppOpticsAPM::Config[:dnt_regexp] = "(\.js$)(?<!show.js)"
|
30
|
-
|
31
|
-
Since this pattern is used with the standard Ruby Regexp class, you can
|
32
|
-
use any Regexp supported pattern. See the documentation on Ruby Regexp
|
33
|
-
[here](https://www.omniref.com/ruby/2.2.0/symbols/Regexp?d=380181456&n=0#doc_uncollapsed=true&d=380181456&n=0)
|
34
|
-
or you can also view the oboe gem [source code documentation for this
|
35
|
-
feature](https://github.com/tracelytics/ruby-appoptics/blob/master/lib/appoptics/config.rb#L129).
|
@@ -1,220 +0,0 @@
|
|
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
|
-
#
|
@@ -1,17 +0,0 @@
|
|
1
|
-
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
|
2
|
-
threads_count = Integer(ENV['MAX_THREADS'] || 5)
|
3
|
-
threads threads_count, threads_count
|
4
|
-
|
5
|
-
preload_app!
|
6
|
-
|
7
|
-
rackup DefaultRackup
|
8
|
-
port ENV['PORT'] || 3000
|
9
|
-
environment ENV['RACK_ENV'] || 'development'
|
10
|
-
|
11
|
-
on_worker_boot do
|
12
|
-
::AppOpticsAPM.reconnect! if defined?(::AppOpticsAPM)
|
13
|
-
end
|
14
|
-
|
15
|
-
on_worker_shutdown do
|
16
|
-
::AppOpticsAPM.disconnect! if defined?(::AppOpticsAPM)
|
17
|
-
end
|
@@ -1,124 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# This sample demonstrates how to instrument a main loop that
|
3
|
-
# retrieves work and spawn threads that do the actual work
|
4
|
-
#
|
5
|
-
|
6
|
-
require 'math'
|
7
|
-
require 'oboe'
|
8
|
-
|
9
|
-
AppOpticsAPM::Config[:tracing_mode] = :always
|
10
|
-
AppOpticsAPM::Config[:verbose] = true
|
11
|
-
|
12
|
-
# The parent process/loop which collects data
|
13
|
-
Kernel.loop do
|
14
|
-
|
15
|
-
# For each loop, we instrument the work retrieval. These traces
|
16
|
-
# will show up as layer 'get_the_work'.
|
17
|
-
AppOpticsAPM::API.start_trace('get_the_work') do
|
18
|
-
work = get_the_work
|
19
|
-
|
20
|
-
# Loop through work and pass to `do_the_work` method
|
21
|
-
# that spawns a thread each time
|
22
|
-
work.each do |j|
|
23
|
-
|
24
|
-
# In the new Thread block, the AppOpticsAPM tracing context isn't there
|
25
|
-
# so we carry it over manually and pass it to the `start_trace`
|
26
|
-
# method.
|
27
|
-
|
28
|
-
# In the AppOptics dashboard, this will show up as parent traces
|
29
|
-
# (layer 'get_the_work') with child traces (layer 'do_the_work').
|
30
|
-
|
31
|
-
tracing_context = AppOpticsAPM::Context.toString
|
32
|
-
|
33
|
-
Thread.new do
|
34
|
-
result = nil
|
35
|
-
|
36
|
-
AppOpticsAPM::API.start_trace('do_the_work', tracing_context, :Async => 1) do
|
37
|
-
result = do_the_work(j)
|
38
|
-
end
|
39
|
-
|
40
|
-
result
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
sleep 5
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
##
|
49
|
-
# get_the_work
|
50
|
-
#
|
51
|
-
# Method to retrieve work to do
|
52
|
-
#
|
53
|
-
def get_the_work
|
54
|
-
# We'll just return random integers as a
|
55
|
-
# fake work load
|
56
|
-
w = []
|
57
|
-
w << rand(25)
|
58
|
-
w << rand(25)
|
59
|
-
w << rand(25)
|
60
|
-
end
|
61
|
-
|
62
|
-
##
|
63
|
-
# do_the_work
|
64
|
-
#
|
65
|
-
# The work-horse method
|
66
|
-
#
|
67
|
-
def do_the_work(job_to_do)
|
68
|
-
i = job_to_do
|
69
|
-
i * Math::PI
|
70
|
-
end
|
71
|
-
|
72
|
-
####################################################
|
73
|
-
# Notes
|
74
|
-
####################################################
|
75
|
-
|
76
|
-
# The above code generates a trace for each loop of the parent data collection process.
|
77
|
-
# Those traces have the layer name of `get_the_work` and will show up in the AppOptics
|
78
|
-
# dashboard as such.
|
79
|
-
#
|
80
|
-
# Then as threads are spawned to process individual bits of work, we carry over the
|
81
|
-
# `tracing_context` and start a new asynchronous trace using `start_trace`. (An
|
82
|
-
# asynchronous trace is noted by passing the `Async` Hash key with a value of `1`).
|
83
|
-
#
|
84
|
-
# In the AppOptics dashboard, the two traces (parent and child; or one to many) will
|
85
|
-
# be linked and displayed together as a single trace.
|
86
|
-
|
87
|
-
####################################################
|
88
|
-
# Caveats
|
89
|
-
####################################################
|
90
|
-
|
91
|
-
# If the main loop is retrieving many jobs (work) to process on each loop then
|
92
|
-
# linking the traces may not be the best strategy as such large relationships
|
93
|
-
# are difficult to display correctly in the AppOptics dashboard and provide little
|
94
|
-
# added value.
|
95
|
-
#
|
96
|
-
# If there are more than 8 - 12 threads spawned from each loop, then you may want to consider
|
97
|
-
# NOT carrying over tracing context into the spawned threads.
|
98
|
-
#
|
99
|
-
# In this case, you can simply omit `tracing_context` and passing it to `start_trace` in
|
100
|
-
# the `Thread.new` block. (lines 32 + 37). Also remove the `{ Async => 1 }` Hash!
|
101
|
-
#
|
102
|
-
# This will produce two sets of traces with two the layer names 'get_the_work' +
|
103
|
-
# 'do_the_work'.
|
104
|
-
#
|
105
|
-
# In the AppOptics dashboard, you can then separate or unify these traces into
|
106
|
-
# independent applications. e.g. job processor, data retrieval, thread worker etc...
|
107
|
-
#
|
108
|
-
# An implementation of the work loop without carrying over tracing context would look
|
109
|
-
# like the following:
|
110
|
-
#
|
111
|
-
# work.each do |j|
|
112
|
-
# Thread.new do
|
113
|
-
# result = nil
|
114
|
-
#
|
115
|
-
# AppOpticsAPM::API.start_trace('do_the_work') do
|
116
|
-
# result = do_the_work(j)
|
117
|
-
# end
|
118
|
-
#
|
119
|
-
# result
|
120
|
-
# end
|
121
|
-
# end
|
122
|
-
#
|
123
|
-
# If anything isn't clear, please don't hesitate to reach us at support (support@appoptics.com).
|
124
|
-
#
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
|
4
|
-
Bundler.require
|
5
|
-
|
6
|
-
# Make sure oboe is at the bottom of your Gemfile.
|
7
|
-
# This is likely redundant but just in case.
|
8
|
-
require 'oboe'
|
9
|
-
|
10
|
-
# Tracing mode can be 'never' or 'always'
|
11
|
-
AppOpticsAPM::Config[:tracing_mode] = 'always'
|
12
|
-
|
13
|
-
#
|
14
|
-
# Update April 9, 2015 - this is done automagically now
|
15
|
-
# and doesn't have to be called manually
|
16
|
-
#
|
17
|
-
# Load library instrumentation to auto-capture stuff we know about...
|
18
|
-
# e.g. ActiveRecord, Cassandra, Dalli, Redis, Memcache, Mongo
|
19
|
-
# AppOpticsAPM::Ruby.load
|
20
|
-
|
21
|
-
# Some KVs to report to the dashboard
|
22
|
-
report_kvs = {}
|
23
|
-
report_kvs[:command_line_params] = ARGV.to_s
|
24
|
-
report_kvs[:user_id] = `whoami`
|
25
|
-
|
26
|
-
AppOpticsAPM::API.start_trace('my_background_job', nil, report_kvs) do
|
27
|
-
#
|
28
|
-
# Initialization code
|
29
|
-
#
|
30
|
-
|
31
|
-
tasks = get_all_tasks
|
32
|
-
|
33
|
-
tasks.each do |t|
|
34
|
-
# Optional: Here we embed another 'trace' to separate actual
|
35
|
-
# work for each task. In the APPOPTICS dashboard, this will show
|
36
|
-
# up as a large 'my_background_job' parent layer with many
|
37
|
-
# child 'task" layers.
|
38
|
-
AppOpticsAPM::API.trace('task', :task_id => t.id) do
|
39
|
-
t.perform
|
40
|
-
end
|
41
|
-
end
|
42
|
-
#
|
43
|
-
# cleanup code
|
44
|
-
#
|
45
|
-
end
|
46
|
-
|
47
|
-
# Note that we use 'start_trace' in the outer block and 'trace' for
|
48
|
-
# any sub-blocks of code we wish to instrument. The arguments for
|
49
|
-
# both methods vary slightly.
|
50
|
-
#
|
51
|
-
# TODO update location of the following doc
|
52
|
-
# Details in RubyDoc:
|
53
|
-
# https://www.omniref.com/ruby/gems/oboe/2.7.10.1/symbols/AppOpticsAPM::API::Tracing#tab=Methods
|
@@ -1,99 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# This sample demonstrates how to instrument a main loop that
|
3
|
-
# retrieves work and calls fork to do the actual work
|
4
|
-
#
|
5
|
-
|
6
|
-
require 'math'
|
7
|
-
require 'oboe'
|
8
|
-
|
9
|
-
AppOpticsAPM::Config[:tracing_mode] = :always
|
10
|
-
AppOpticsAPM::Config[:verbose] = true
|
11
|
-
|
12
|
-
# The parent process/loop which collects data
|
13
|
-
Kernel.loop do
|
14
|
-
# For each loop, we instrument the work retrieval. These traces
|
15
|
-
# will show up as layer 'get_the_work'.
|
16
|
-
AppOpticsAPM::API.start_trace('get_the_work') do
|
17
|
-
work = get_the_work
|
18
|
-
|
19
|
-
# Loop through work and pass to `do_the_work` method
|
20
|
-
# that spawns a thread each time
|
21
|
-
work.each do |job|
|
22
|
-
fork do
|
23
|
-
# Since the context is copied from the parent process, we clear it
|
24
|
-
# and start a new trace via `AppOpticsAPM::API.start_trace`.
|
25
|
-
AppOpticsAPM::Context.clear
|
26
|
-
result = nil
|
27
|
-
|
28
|
-
AppOpticsAPM::API.start_trace('do_the_work', nil, :job_id => job.id) do
|
29
|
-
result = do_the_work(job)
|
30
|
-
end
|
31
|
-
|
32
|
-
result
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
##
|
39
|
-
# get_the_work
|
40
|
-
#
|
41
|
-
# Method to retrieve work to do
|
42
|
-
#
|
43
|
-
def get_the_work
|
44
|
-
# We'll just return random integers as a
|
45
|
-
# fake work load
|
46
|
-
w = []
|
47
|
-
w << rand(25)
|
48
|
-
w << rand(25)
|
49
|
-
w << rand(25)
|
50
|
-
end
|
51
|
-
|
52
|
-
##
|
53
|
-
# do_the_work
|
54
|
-
#
|
55
|
-
# The work-horse method
|
56
|
-
#
|
57
|
-
def do_the_work(job_to_do)
|
58
|
-
i = job_to_do
|
59
|
-
i * Math::PI
|
60
|
-
end
|
61
|
-
|
62
|
-
#########################################################################
|
63
|
-
# Notes
|
64
|
-
#########################################################################
|
65
|
-
|
66
|
-
# If your parent process only forks a small number of processes per loop (< 5..10),
|
67
|
-
# you may want to mark the child traces as asynchronous and have them directly
|
68
|
-
# linked to the parent tracing context.
|
69
|
-
#
|
70
|
-
# The benefit of this is that instead of having two independent traces (parent
|
71
|
-
# and child), you will have a single view of the parent trace showing the
|
72
|
-
# spawned child process and it's performance in the AppOptics dashboard.
|
73
|
-
#
|
74
|
-
# To do this:
|
75
|
-
# 1. Don't clear the context in the child process
|
76
|
-
# 2. Use `AppOpticsAPM::API.trace` instead
|
77
|
-
# 3. Pass the `Async` flag to mark this child as asynchronous
|
78
|
-
#
|
79
|
-
Kernel.loop do
|
80
|
-
AppOpticsAPM::API.start_trace('get_the_work') do
|
81
|
-
|
82
|
-
work = get_the_work
|
83
|
-
|
84
|
-
work.each do |job|
|
85
|
-
fork do
|
86
|
-
result = nil
|
87
|
-
# 1 Don't clear context
|
88
|
-
# 2 Use `AppOpticsAPM::API.trace` instead
|
89
|
-
# 3 Pass the Async flag
|
90
|
-
AppOpticsAPM::API.trace('do_the_work', {:job_id => job.id, :Async => 1 }) do
|
91
|
-
result = do_the_work(job)
|
92
|
-
end
|
93
|
-
|
94
|
-
result
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
sleep 5
|
99
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
|
2
|
-
timeout 15
|
3
|
-
preload_app true
|
4
|
-
|
5
|
-
before_fork do |server, worker|
|
6
|
-
Signal.trap 'TERM' do
|
7
|
-
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
|
8
|
-
Process.kill 'QUIT', Process.pid
|
9
|
-
end
|
10
|
-
|
11
|
-
defined?(ActiveRecord::Base) and
|
12
|
-
ActiveRecord::Base.connection.disconnect!
|
13
|
-
|
14
|
-
defined?(::AppOpticsAPM) and
|
15
|
-
::AppOpticsAPM.disconnect!
|
16
|
-
end
|
17
|
-
|
18
|
-
after_fork do |server, worker|
|
19
|
-
Signal.trap 'TERM' do
|
20
|
-
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
|
21
|
-
end
|
22
|
-
|
23
|
-
defined?(ActiveRecord::Base) and
|
24
|
-
ActiveRecord::Base.establish_connection
|
25
|
-
|
26
|
-
defined?(::AppOpticsAPM) and
|
27
|
-
::AppOpticsAPM.reconnect!
|
28
|
-
end
|