appoptics_apm_mnfst 4.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +5 -0
  3. data/.github/ISSUE_TEMPLATE/bug-or-feature-request.md +16 -0
  4. data/.gitignore +29 -0
  5. data/.rubocop.yml +8 -0
  6. data/.travis.yml +121 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +769 -0
  9. data/CONFIG.md +33 -0
  10. data/Gemfile +29 -0
  11. data/LICENSE +193 -0
  12. data/README.md +393 -0
  13. data/Rakefile +230 -0
  14. data/appoptics_apm.gemspec +61 -0
  15. data/bin/appoptics_apm_config +15 -0
  16. data/build_gem.sh +15 -0
  17. data/build_gem_upload_to_packagecloud.sh +20 -0
  18. data/examples/SDK/01_basic_tracing.rb +67 -0
  19. data/examples/carrying_context.rb +220 -0
  20. data/ext/oboe_metal/extconf.rb +114 -0
  21. data/ext/oboe_metal/lib/.keep +0 -0
  22. data/ext/oboe_metal/noop/noop.c +7 -0
  23. data/ext/oboe_metal/src/VERSION +1 -0
  24. data/init.rb +4 -0
  25. data/lib/appoptics_apm.rb +76 -0
  26. data/lib/appoptics_apm/api.rb +20 -0
  27. data/lib/appoptics_apm/api/layerinit.rb +41 -0
  28. data/lib/appoptics_apm/api/logging.rb +375 -0
  29. data/lib/appoptics_apm/api/memcache.rb +37 -0
  30. data/lib/appoptics_apm/api/metrics.rb +55 -0
  31. data/lib/appoptics_apm/api/profiling.rb +203 -0
  32. data/lib/appoptics_apm/api/tracing.rb +53 -0
  33. data/lib/appoptics_apm/api/util.rb +122 -0
  34. data/lib/appoptics_apm/base.rb +230 -0
  35. data/lib/appoptics_apm/config.rb +254 -0
  36. data/lib/appoptics_apm/frameworks/grape.rb +97 -0
  37. data/lib/appoptics_apm/frameworks/padrino.rb +108 -0
  38. data/lib/appoptics_apm/frameworks/rails.rb +94 -0
  39. data/lib/appoptics_apm/frameworks/rails/inst/action_controller.rb +104 -0
  40. data/lib/appoptics_apm/frameworks/rails/inst/action_controller3.rb +55 -0
  41. data/lib/appoptics_apm/frameworks/rails/inst/action_controller4.rb +48 -0
  42. data/lib/appoptics_apm/frameworks/rails/inst/action_controller5.rb +50 -0
  43. data/lib/appoptics_apm/frameworks/rails/inst/action_controller_api.rb +50 -0
  44. data/lib/appoptics_apm/frameworks/rails/inst/action_view.rb +58 -0
  45. data/lib/appoptics_apm/frameworks/rails/inst/action_view_30.rb +50 -0
  46. data/lib/appoptics_apm/frameworks/rails/inst/active_record.rb +27 -0
  47. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  48. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/mysql2.rb +29 -0
  49. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/postgresql.rb +31 -0
  50. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils.rb +119 -0
  51. data/lib/appoptics_apm/frameworks/rails/inst/connection_adapters/utils5x.rb +108 -0
  52. data/lib/appoptics_apm/frameworks/sinatra.rb +125 -0
  53. data/lib/appoptics_apm/inst/bunny-client.rb +148 -0
  54. data/lib/appoptics_apm/inst/bunny-consumer.rb +89 -0
  55. data/lib/appoptics_apm/inst/curb.rb +330 -0
  56. data/lib/appoptics_apm/inst/dalli.rb +85 -0
  57. data/lib/appoptics_apm/inst/delayed_job.rb +92 -0
  58. data/lib/appoptics_apm/inst/em-http-request.rb +101 -0
  59. data/lib/appoptics_apm/inst/excon.rb +125 -0
  60. data/lib/appoptics_apm/inst/faraday.rb +94 -0
  61. data/lib/appoptics_apm/inst/grpc_client.rb +162 -0
  62. data/lib/appoptics_apm/inst/grpc_server.rb +120 -0
  63. data/lib/appoptics_apm/inst/http.rb +73 -0
  64. data/lib/appoptics_apm/inst/httpclient.rb +174 -0
  65. data/lib/appoptics_apm/inst/memcached.rb +86 -0
  66. data/lib/appoptics_apm/inst/mongo.rb +246 -0
  67. data/lib/appoptics_apm/inst/mongo2.rb +225 -0
  68. data/lib/appoptics_apm/inst/moped.rb +466 -0
  69. data/lib/appoptics_apm/inst/rack.rb +199 -0
  70. data/lib/appoptics_apm/inst/redis.rb +275 -0
  71. data/lib/appoptics_apm/inst/resque.rb +151 -0
  72. data/lib/appoptics_apm/inst/rest-client.rb +48 -0
  73. data/lib/appoptics_apm/inst/sequel.rb +178 -0
  74. data/lib/appoptics_apm/inst/sidekiq-client.rb +55 -0
  75. data/lib/appoptics_apm/inst/sidekiq-worker.rb +65 -0
  76. data/lib/appoptics_apm/inst/twitter-cassandra.rb +294 -0
  77. data/lib/appoptics_apm/inst/typhoeus.rb +108 -0
  78. data/lib/appoptics_apm/instrumentation.rb +22 -0
  79. data/lib/appoptics_apm/legacy_method_profiling.rb +90 -0
  80. data/lib/appoptics_apm/loading.rb +65 -0
  81. data/lib/appoptics_apm/logger.rb +42 -0
  82. data/lib/appoptics_apm/method_profiling.rb +33 -0
  83. data/lib/appoptics_apm/noop/README.md +9 -0
  84. data/lib/appoptics_apm/noop/context.rb +26 -0
  85. data/lib/appoptics_apm/noop/metadata.rb +22 -0
  86. data/lib/appoptics_apm/ruby.rb +35 -0
  87. data/lib/appoptics_apm/sdk/custom_metrics.rb +92 -0
  88. data/lib/appoptics_apm/sdk/tracing.rb +315 -0
  89. data/lib/appoptics_apm/support.rb +119 -0
  90. data/lib/appoptics_apm/test.rb +94 -0
  91. data/lib/appoptics_apm/thread_local.rb +26 -0
  92. data/lib/appoptics_apm/util.rb +319 -0
  93. data/lib/appoptics_apm/version.rb +15 -0
  94. data/lib/appoptics_apm/xtrace.rb +103 -0
  95. data/lib/joboe_metal.rb +212 -0
  96. data/lib/oboe.rb +7 -0
  97. data/lib/oboe/README +2 -0
  98. data/lib/oboe/backward_compatibility.rb +80 -0
  99. data/lib/oboe/inst/rack.rb +11 -0
  100. data/lib/oboe_metal.rb +198 -0
  101. data/lib/rails/generators/appoptics_apm/install_generator.rb +45 -0
  102. data/lib/rails/generators/appoptics_apm/templates/appoptics_apm_initializer.rb +265 -0
  103. data/yardoc_frontpage.md +26 -0
  104. metadata +266 -0
@@ -0,0 +1,33 @@
1
+ # AppOpticsAPM Gem Configuration
2
+
3
+ ## Environment Variables
4
+
5
+ The following environment variables are detected by the appoptics_apm gem and affect how the gem functions.
6
+
7
+ ### General
8
+
9
+ Name | Description | Default
10
+ ---- | ----------- | -------
11
+ `APPOPTICS_SERVICE_KEY` | API token + service name combination, mandatory for metrics and traces to show in my.appoptics.com |
12
+ `IGNORE_APPOPTICS_WARNING` | tells the appoptics_apm gem to __not__ output the _missing AppOpticsAPM libraries_ message on stack initialization | `false`
13
+ `APPOPTICS_GEM_VERBOSE` | sets the verbose flag (`AppOpticsAPM::Config[:verbose]`) early in the gem loading process which may output valuable information | `false`
14
+ `APPOPTICS_CUUID` | Allows specifying the customer ID via environment variable to override/bypass the value in `/etc/tracelytics.conf` | `nil`
15
+
16
+ # Related to Tests
17
+
18
+ Name | Description | Default
19
+ ---- | ----------- | -------
20
+ `APPOPTICS_GEM_TEST` | puts the gem in test mode. Traces are written to /tmp/trace_output.bson. | `false`
21
+ `DBTYPE` | For tests on Ruby on Rails, specifies the database type to test against. `postgres`, `mysql` and `mysql2` are valid options. | `postgres`
22
+ `APPOPTICS_CASSANDRA_SERVER` | specifies the Cassandra server to test against. | `127.0.0.1:9160`
23
+ `APPOPTICS_MONGO_SERVER` | specifies the Mongo server to test against. | `127.0.0.1:27017`
24
+ `APPOPTICS_RABBITMQ_SERVER` | specifies the RabbitMQ server to test against. | `127.0.0.1`
25
+ `APPOPTICS_RABBITMQ_PORT` | port for the RabbitMQ connection. | `5672`
26
+ `APPOPTICS_RABBITMQ_USERNAME` | username for the RabbitMQ connection | `guest`
27
+ `APPOPTICS_RABBITMQ_PASSWORD` | password for the RabbitMQ connection | `guest`
28
+
29
+ ## AppOpticsAPM::Config
30
+
31
+ `AppOpticsAPM::Config` is a nested hash used by the appoptics_apm gem to store preferences and switches.
32
+
33
+ See [this Rails generator template file](https://github.com/librato/ruby-appoptics/blob/master/lib/rails/generators/appoptics_apm/templates/appoptics_initializer.rb) for documentation on all of the supported values.
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'rake'
5
+ gem 'minitest'
6
+ gem 'minitest-reporters', '< 1.0.18'
7
+ gem 'minitest-debugger', :require => false
8
+ gem 'rack-test'
9
+ gem 'puma'
10
+ gem 'bson'
11
+ gem 'webmock' if RUBY_VERSION >= '2.0.0'
12
+ gem 'mocha'
13
+ gem 'rubocop', require: false
14
+ gem 'ruby-prof'
15
+ gem 'benchmark-ips'
16
+ gem 'ruby-debug', :platforms => :jruby
17
+ gem 'debugger', :platform => :mri_19
18
+ gem 'byebug', :platforms => [:mri_22, :mri_23, :mri_24]
19
+ gem 'pry'
20
+ gem 'pry-byebug', :platforms => [:mri_22, :mri_23, :mri_24]
21
+ end
22
+
23
+ if defined?(JRUBY_VERSION)
24
+ gem 'sinatra', :require => false
25
+ else
26
+ gem 'sinatra'
27
+ end
28
+
29
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,193 @@
1
+ Librato Open License
2
+ Version 1.0, October, 2016
3
+
4
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
5
+
6
+ 1. Definitions.
7
+
8
+ "License" shall mean the terms and conditions for use, reproduction, and
9
+ distribution as defined by Sections 1 through 11 of this document.
10
+
11
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright
12
+ owner that is granting the License. Licensor can include Librato as an
13
+ original contributor to the Work as defined below.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all other entities
16
+ that control, are controlled by, or are under common control with that entity.
17
+ For the purposes of this definition, "control" means (i) the power, direct or
18
+ indirect, to cause the direction or management of such entity, whether by
19
+ contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
+ outstanding shares, or (iii) beneficial ownership of such entity.
21
+
22
+ "You" (or "Your") shall mean an individual or Legal Entity exercising
23
+ permissions granted by this License.
24
+
25
+ "Source" form shall mean the preferred form for making modifications, including
26
+ but not limited to software source code, documentation source, and
27
+ configuration files.
28
+
29
+ "Object" form shall mean any form resulting from mechanical transformation or
30
+ translation of a Source form, including but not limited to compiled object
31
+ code, generated documentation, and conversions to other media types.
32
+
33
+ "Work" shall mean the work of authorship, whether in Source or Object form,
34
+ made available under the License, as indicated by a copyright notice that is
35
+ included in or attached to the work.
36
+
37
+ "Derivative Works" shall mean any work, whether in Source or Object form, that
38
+ is based on (or derived from) the Work and for which the editorial revisions,
39
+ annotations, elaborations, or other modifications represent, as a whole, an
40
+ original work of authorship. For the purposes of this License, Derivative Works
41
+ shall not include works that remain separable from, or merely link (or bind by
42
+ name) to the interfaces of, the Work and Derivative Works thereof.
43
+
44
+ "Contribution" shall mean any work of authorship, including the original
45
+ version of the Work and any modifications or additions to that Work or
46
+ Derivative Works thereof, that is intentionally submitted to Licensor for
47
+ inclusion in the Work by the copyright owner or by an individual or Legal
48
+ Entity authorized to submit on behalf of the copyright owner. For the purposes
49
+ of this definition, "submitted" means any form of electronic, verbal, or
50
+ written communication sent to the Licensor or its representatives, including
51
+ but not limited to communication on electronic mailing lists, source code
52
+ control systems, and issue tracking systems that are managed by, or on behalf
53
+ of, the Licensor for the purpose of discussing and improving the Work, but
54
+ excluding communication that is conspicuously marked or otherwise designated in
55
+ writing by the copyright owner as "Not a Contribution."
56
+
57
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58
+ of whom a Contribution has been received by Licensor and subsequently
59
+ incorporated within the Work.
60
+
61
+ 2. Grant of Copyright License.
62
+
63
+ Subject to the terms and conditions of this License, each Contributor hereby
64
+ grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65
+ irrevocable copyright license to reproduce, prepare Derivative Works of,
66
+ publicly display, publicly perform, sublicense, and distribute the Work and
67
+ such Derivative Works in Source or Object form.
68
+
69
+ 3. Grant of Patent License.
70
+
71
+ Subject to the terms and conditions of this License, each Contributor hereby
72
+ grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73
+ irrevocable (except as stated in this section) patent license to make, have
74
+ made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75
+ such license applies only to those patent claims licensable by such Contributor
76
+ that are necessarily infringed by their Contribution(s) alone or by combination
77
+ of their Contribution(s) with the Work to which such Contribution(s) was
78
+ submitted. If You institute patent litigation against any entity (including a
79
+ cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80
+ Contribution incorporated within the Work constitutes direct or contributory
81
+ patent infringement, then any patent licenses granted to You under this License
82
+ for that Work shall terminate as of the date such litigation is filed.
83
+
84
+ Each time You convey a covered Work, the recipient automatically receives a
85
+ license from the original Licensor(s), to run, modify and propagate that work,
86
+ subject to this License. You are not responsible for enforcing compliance by
87
+ third parties with this License.
88
+
89
+ You may not impose any further restrictions on the exercise of the rights
90
+ granted or affirmed under this License. For example, you may not impose a
91
+ license fee, royalty, or other charge for exercise of rights granted under this
92
+ License, and you may not initiate litigation (including a cross-claim or
93
+ counterclaim in a lawsuit) alleging that any patent claim is infringed by
94
+ making, using, selling, offering for sale, or importing the Work or any portion
95
+ of it.
96
+
97
+ 4. Redistribution.
98
+
99
+ You may reproduce and distribute copies of the Work or Derivative Works thereof
100
+ in any medium, with or without modifications, and in Source or Object form,
101
+ provided that You meet the following conditions:
102
+
103
+ 1. You must give any other recipients of the Work or Derivative Works a copy
104
+ of this License; and
105
+ 2. You must cause any modified files to carry prominent notices stating that
106
+ You changed the files; and
107
+ 3. You must retain, in the Source form of any Derivative Works that You
108
+ distribute, all copyright, patent, trademark, and attribution notices from the
109
+ Source form of the Work, excluding those notices that do not pertain to any
110
+ part of the Derivative Works; and
111
+ 4. If the Work includes a "NOTICE" text file as part of its distribution,
112
+ then any Derivative Works that You distribute must include a readable copy of
113
+ the attribution notices contained within such NOTICE file, excluding those
114
+ notices that do not pertain to any part of the Derivative Works, in at least
115
+ one of the following places: within a NOTICE text file distributed as part of
116
+ the Derivative Works; within the Source form or documentation, if provided
117
+ along with the Derivative Works; or, within a display generated by the
118
+ Derivative Works, if and wherever such third-party notices normally appear. The
119
+ contents of the NOTICE file are for informational purposes only and do not
120
+ modify the License. You may add Your own attribution notices within Derivative
121
+ Works that You distribute, alongside or as an addendum to the NOTICE text from
122
+ the Work, provided that such additional attribution notices cannot be construed
123
+ as modifying the License.
124
+
125
+ You may add Your own copyright statement to Your modifications and may provide
126
+ additional or different license terms and conditions for use, reproduction, or
127
+ distribution of Your modifications, or for any such Derivative Works as a
128
+ whole, provided Your use, reproduction, and distribution of the Work otherwise
129
+ complies with the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions.
132
+
133
+ Unless You explicitly state otherwise, any Contribution intentionally submitted
134
+ for inclusion in the Work by You to the Licensor shall be under the terms and
135
+ conditions of this License, without any additional terms or conditions.
136
+ Notwithstanding the above, nothing herein shall supersede or modify the terms
137
+ of any separate license agreement you may have executed with Licensor regarding
138
+ such Contributions.
139
+
140
+ 6. Trademarks.
141
+
142
+ This License does not grant permission to use the trade names, trademarks,
143
+ service marks, or product names of the Licensor, except as required for
144
+ reasonable and customary use in describing the origin of the Work and
145
+ reproducing the content of the NOTICE file.
146
+
147
+ 7. Disclaimer of Warranty.
148
+
149
+ Unless required by applicable law or agreed to in writing, Licensor provides
150
+ the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
151
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
152
+ including, without limitation, any warranties or conditions of TITLE,
153
+ NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
154
+ solely responsible for determining the appropriateness of using or
155
+ redistributing the Work and assume any risks associated with Your exercise of
156
+ permissions under this License.
157
+
158
+ 8. Limitation of Liability.
159
+
160
+ In no event and under no legal theory, whether in tort (including negligence),
161
+ contract, or otherwise, unless required by applicable law (such as deliberate
162
+ and grossly negligent acts) or agreed to in writing, shall any Contributor be
163
+ liable to You for damages, including any direct, indirect, special, incidental,
164
+ or consequential damages of any character arising as a result of this License
165
+ or out of the use or inability to use the Work (including but not limited to
166
+ damages for loss of goodwill, work stoppage, computer failure or malfunction,
167
+ or any and all other commercial damages or losses), even if such Contributor
168
+ has been advised of the possibility of such damages.
169
+
170
+ 9. Accepting Warranty or Additional Liability.
171
+
172
+ While redistributing the Work or Derivative Works thereof, You may choose to
173
+ offer, and charge a fee for, acceptance of support, warranty, indemnity, or
174
+ other liability obligations and/or rights consistent with this License.
175
+ However, in accepting such obligations, You may act only on Your own behalf and
176
+ on Your sole responsibility, not on behalf of any other Contributor, and only
177
+ if You agree to indemnify, defend, and hold each Contributor harmless for any
178
+ liability incurred by, or claims asserted against, such Contributor by reason
179
+ of your accepting any such warranty or additional liability.
180
+
181
+ 10. Noncompetition
182
+
183
+ You may install and execute the Work only in conjunction with the direct use of
184
+ Librato software. This Work, any file or any derivative thereof shall not be
185
+ used in conjunction with any product that competes with any Librato software.
186
+
187
+ 11. Termination
188
+
189
+ The License stated above is automatically terminated and revoked if you exceed
190
+ its scope or violate any of the terms of this License or any related License or
191
+ notice.
192
+
193
+ END OF TERMS AND CONDITIONS
@@ -0,0 +1,393 @@
1
+ # Welcome to the AppOpticsAPM Ruby Gem
2
+
3
+ The appoptics_apm gem provides [AppOptics APM](https://www.appoptics.com/) performance instrumentation for Ruby.
4
+
5
+ ![Ruby AppOpticsAPM](https://docs.appoptics.com/_images/ruby_trace.png)
6
+
7
+ It has the ability to report performance metrics on an array of libraries, databases and frameworks such as Rails,
8
+ Mongo, Memcache, ActiveRecord, Cassandra, Rack, Resque
9
+ [and more](https://docs.appoptics.com/kb/apm_tracing/ruby/support-matrix/).
10
+
11
+ It requires an [AppOptics](https://www.appoptics.com/) account to view metrics. Get yours,
12
+ [it's free](https://my.appoptics.com/sign_up).
13
+
14
+ [![Gem Version](https://badge.fury.io/rb/appoptics_apm.svg)](https://badge.fury.io/rb/appoptics_apm)
15
+ [![Build Status](https://travis-ci.org/appoptics/appoptics-apm-ruby.png?branch=master)](https://travis-ci.org/appoptics/appoptics-apm-ruby)
16
+ [![Maintainability](https://api.codeclimate.com/v1/badges/ac7f36241a23a3a82fc5/maintainability)](https://codeclimate.com/github/appoptics/appoptics-apm-ruby/maintainability)
17
+
18
+ _Note: The repository is now at https://github.com/appoptics/appoptics-apm-ruby Please update your github remotes with
19
+ `git remote set-url origin git@github.com:appoptics/appoptics-apm-ruby.git`._
20
+
21
+ # Documentation
22
+
23
+ * [AppOptics Knowledge Base](https://docs.appoptics.com/kb/apm_tracing/ruby)
24
+
25
+ # Installation
26
+
27
+ _Before installing the gem below, make sure that you have the
28
+ [dependencies](http://docs.appoptics.com/kb/apm_tracing/ruby/install#dependencies) installed on your host first._
29
+
30
+ The appoptics_apm gem is [available on Rubygems](https://rubygems.org/gems/appoptics_apm) and can be installed with:
31
+
32
+ ```bash
33
+ gem install appoptics_apm
34
+ ```
35
+
36
+ or added to **the end** of your Gemfile and running `bundle install`:
37
+
38
+ ```ruby
39
+ gem 'appoptics_apm'
40
+ ```
41
+
42
+ # Running
43
+
44
+ Make sure to set `APPOPTICS_SERVICE_KEY` in the environment from where the app or service is run, e.g:
45
+ ```
46
+ export APPOPTICS_SERVICE_KEY=795fb4947d15275d208c49cfd2412d4a5bf38742045b47236c94c4fe5f5b17c7:<your_app_name>
47
+ ```
48
+
49
+ ## Rails
50
+
51
+ ![Ruby on Rails](https://docs.appoptics.com/_images/rails.png)
52
+
53
+ No special steps are needed to instrument Ruby on Rails. Once part of the bundle, the appoptics gem will automatically
54
+ detect Rails and instrument on stack initialization.
55
+
56
+ ### The Install Generator
57
+
58
+ The appoptics_apm gem provides a Rails generator used to seed an initializer where you can configure and control
59
+ `tracing_mode` and [other options](http://docs.appoptics.com/kb/apm_tracing/ruby/configure).
60
+
61
+ To run the install generator run:
62
+
63
+ ```bash
64
+ bundle exec rails generate appoptics_apm:install
65
+ ```
66
+
67
+ After the prompts, this will create an initializer: `config/initializers/appoptics_apm.rb`.
68
+
69
+ ## Sinatra
70
+
71
+ ![Sinatra](https://docs.appoptics.com/_images/sinatra.png)
72
+
73
+ You can instrument your Sinatra application by adding the following code to your `config.ru` Rackup file:
74
+
75
+ ```ruby
76
+ # If you're not using Bundler.require. Make sure this is done
77
+ # after the Sinatra require directive.
78
+ require 'appoptics_apm'
79
+ ```
80
+
81
+ Make sure that the appoptics_apm gem is loaded _after_ Sinatra either by listing `gem 'appoptics_apm'` after Sinatra in
82
+ your Gemfile or calling the `require 'appoptics_gem'` directive after Sinatra is loaded.
83
+
84
+ With this, the appoptics_apm gem will automatically detect Sinatra on boot and instrument key components.
85
+
86
+ ## Padrino
87
+
88
+ ![Padrino](https://docs.appoptics.com/_images/padrino.svg)
89
+
90
+ As long as the appoptics_apm gem is in your `Gemfile` (inserted after the `gem 'padrino'` directive) and you are calling
91
+ `Bundler.require`, the appoptics_apm gem will automatically instrument Padrino applications.
92
+
93
+ If you need to set `AppOpticsAPM::Config` values on stack boot, you can do so by adding the following
94
+ to your `config/boot.rb` file:
95
+
96
+ ```ruby
97
+ Padrino.before_load do
98
+ # Verbose output of instrumentation initialization
99
+ AppOpticsAPM
100
+ end
101
+ ```
102
+
103
+ ## Grape
104
+
105
+ ![Grape](https://docs.appoptics.com/_images/grape.png)
106
+
107
+ You can instrument your Grape application by adding the following code to your `config.ru` Rackup file:
108
+
109
+ ```ruby
110
+ # If you're not using Bundler.require. Make sure this is done
111
+ # after the Grape require directive.
112
+ require 'appoptics_apm'
113
+
114
+ ...
115
+
116
+ class App < Grape::API
117
+ use AppOpticsAPM::Rack
118
+ end
119
+ ```
120
+
121
+ Make sure that the appoptics gem is loaded _after_ Grape either by listing `gem 'appoptics_apm'` after Grape in your
122
+ Gemfile or calling the `require 'appoptics_apm'` directive after Grape is loaded.
123
+
124
+ You must explicitly tell your Grape application to use AppOpticsAPM::Rack for tracing to occur.
125
+
126
+
127
+ # SDK for Custom Tracing
128
+
129
+ The appoptics_apm gem has the ability to instrument any arbitrary Ruby application or script.
130
+
131
+ ```ruby
132
+ require 'rubygems'
133
+ require 'bundler'
134
+
135
+ Bundler.require
136
+
137
+ require 'appoptics_apm'
138
+ ```
139
+
140
+ You can add even more visibility into any part of your application or scripts by adding custom instrumentation.
141
+
142
+ ## AppOpticsAPM::SDK.trace
143
+ You can instrument any arbitrary block of code using `AppOpticsAPM::SDK.trace`.
144
+
145
+ ```ruby
146
+ # layer_name will show up in the AppOptics app dashboard
147
+ layer_name = 'subsystemX'
148
+
149
+ # report_kvs are a set of information Key/Value pairs that are sent to
150
+ # AppOptics dashboard along with the performance metrics. These KV
151
+ # pairs are used to report request, environment and/or client specific
152
+ # information.
153
+
154
+ report_kvs = {}
155
+ report_kvs[:mykey] = @client.id
156
+
157
+ AppOpticsAPM::SDK.trace(layer_name, report_kvs) do
158
+ # the block of code to be traced
159
+ end
160
+ ```
161
+
162
+ `AppOpticsAPM::SDK.trace` is used within the context of a request. It will follow the upstream state of the request
163
+ being traced. i.e. the block of code will only be traced when the parent request is being traced.
164
+
165
+ This tracing state of a request can also be queried by using `AppOpticsAPM.tracing?`.
166
+
167
+ ## AppOpticsAPM::SDK.start_trace
168
+
169
+ If you need to instrument code outside the context of a request (such as a cron job, background job or an arbitrary
170
+ ruby script), use `AppOpticsAPM::SDK.start_trace` instead which will initiate a new trace based on configuration and
171
+ probability (based on the sample rate).
172
+
173
+
174
+
175
+ ### Example
176
+
177
+ ```ruby
178
+ require 'rubygems'
179
+ require 'bundler'
180
+
181
+ Bundler.require
182
+
183
+ # Make sure appoptics_apm is at the bottom of your Gemfile.
184
+ # This is likely redundant but just in case.
185
+ require 'appoptics_apm'
186
+
187
+
188
+ # Tracing mode can be 'never', 'through' (to follow upstream) or 'always'
189
+ AppOpticsAPM::Config[:tracing_mode] = 'always'
190
+
191
+ #
192
+ # Update April 9, 2015 - this is done automagically now
193
+ # and doesn't have to be called manually
194
+ #
195
+ # Load library instrumentation to auto-capture stuff we know about...
196
+ # e.g. ActiveRecord, Cassandra, Dalli, Redis, memcache, mongo
197
+ # TraceView::Ruby.load
198
+
199
+ # Some KVs to report to the dashboard
200
+ report_kvs = {}
201
+ report_kvs[:command_line_params] = ARGV.to_s
202
+ report_kvs[:user_id] = `whoami`
203
+
204
+ AppOpticsAPM::SDK.start_trace('my_background_job', nil, report_kvs ) do
205
+ #
206
+ # Initialization code
207
+ #
208
+
209
+ tasks = get_all_tasks
210
+
211
+ tasks.each do |t|
212
+ # Optional: Here we embed another 'trace' to separate actual
213
+ # work for each task. In the traces dashboard this will show
214
+ # up as a large 'my_background_job' parent layer with many
215
+ # child 'task' layers.
216
+ AppOpticsAPM::SDK.trace('task', { :task_id => t.id }) do
217
+ t.perform
218
+ end
219
+ end
220
+
221
+ #
222
+ # cleanup code
223
+ #
224
+ end
225
+
226
+
227
+ # Note that we use 'start_trace' in the outer block and 'trace' for
228
+ # any sub-blocks of code we wish to instrument. The arguments for
229
+ # both methods vary slightly.
230
+ ```
231
+
232
+ Find more details in the [RubyDoc page](https://www.rubydoc.info/gems/appoptics_apm/AppOpticsAPM/SDK) on how to use the Tracing SDK in an independent Ruby script.
233
+
234
+ # Support
235
+
236
+ If you find a bug or would like to request an enhancement, feel free to contact our tech support
237
+ [support@appoptics.com](support@appoptics.com).
238
+
239
+ # Contributing
240
+
241
+ You are obviously a person of great sense and intelligence. We happily appreciate all contributions to the appoptics
242
+ gem whether it is documentation, a bug fix, new instrumentation for a library or framework or anything else we haven't
243
+ thought of.
244
+
245
+ We welcome you to send us PRs. We also humbly request that any new instrumentation submissions have corresponding tests
246
+ that accompany them. This way we don't break any of your additions when we (and others) make changes after the fact.
247
+
248
+
249
+ ## Layout of the Gem
250
+
251
+ The appoptics gem uses a standard gem layout. Here are the notable directories.
252
+
253
+ lib/appoptics/inst # Auto load directory for various instrumented libraries
254
+ lib/appoptics/frameworks # Framework instrumentation directory
255
+ lib/appoptics/frameworks/rails # Files specific to Rails instrumentation
256
+ lib/rails # A Rails required directory for the Rails install generator
257
+ lib/api # The AppOpticsAPM Tracing API: layers, logging, tracing
258
+ ext/oboe_metal # The Ruby c extension that links against the system liboboe library
259
+
260
+ ## Building the Gem
261
+
262
+ The appoptics gem is built with the standard `gem build` command passing in the gemspec:
263
+
264
+ ```bash
265
+ gem build appoptics_apm.gemspec
266
+ ```
267
+
268
+ ## Writing Custom Instrumentation
269
+
270
+ Custom instrumentation for a library, database or other service can be authored fairly easily. Generally,
271
+ instrumentation of a library is done by wrapping select operations of that library and timing their execution using the
272
+ AppOpticsAPM Tracing SDK which then reports the metrics to the users' AppOptics dashboard.
273
+
274
+ Here, I'll use a stripped down version of the Dalli instrumentation (`lib/appoptics/inst/dalli.rb`) as a quick example
275
+ of how to instrument a client library (the dalli gem).
276
+
277
+ The Dalli gem nicely routes all memcache operations through a single `perform` operation. Wrapping this method allows
278
+ us to capture all Dalli operations called by an application.
279
+
280
+ First, we define a module (AppOpticsAPM::Inst::Dalli) and our own custom `perform_with_appoptics` method that we will
281
+ use as a wrapper around Dalli's `perform` method. We also declare an `included` method which automatically gets called
282
+ when this module is included by another.
283
+ See [`Module#included` Ruby reference documentation](https://devdocs.io/ruby~2.5/module#method-i-included).
284
+
285
+ ```ruby
286
+ module AppOpticsAPM
287
+ module Inst
288
+ module Dalli
289
+ include AppOpticsAPM::API::Memcache
290
+
291
+ def self.included(cls)
292
+ cls.class_eval do
293
+ if ::Dalli::Client.private_method_defined? :perform
294
+ alias perform_without_appoptics perform
295
+ alias perform perform_with_appoptics
296
+ end
297
+ end
298
+ end
299
+
300
+ def perform_with_appoptics(*all_args, &blk)
301
+ op, key, *args = *all_args
302
+
303
+ if AppOpticsAPM.tracing?
304
+ opts = {}
305
+ opts[:KVOp] = op
306
+ opts[:KVKey] = key
307
+
308
+ AppOpticsAPM::SDK.trace('memcache', opts || {}) do
309
+ result = perform_without_appoptics(*all_args, &blk)
310
+ if op == :get and key.class == String
311
+ AppOpticsAPM::API.log_info('memcache', { :KVHit => memcache_hit?(result) })
312
+ end
313
+ result
314
+ end
315
+ else
316
+ perform_without_appoptics(*all_args, &blk)
317
+ end
318
+ end
319
+
320
+ end
321
+ end
322
+ end
323
+ ```
324
+
325
+ Second, we tail onto the end of the instrumentation file a simple `::Dalli::Client.module_eval` call to tell the Dalli
326
+ module to include our newly defined instrumentation module. Doing this will invoke our previously defined `included` method.
327
+
328
+ ```ruby
329
+ if defined?(Dalli) and AppOpticsAPM::Config[:dalli][:enabled]
330
+ ::Dalli::Client.module_eval do
331
+ include AppOpticsAPM::Inst::Dalli
332
+ end
333
+ end
334
+ ```
335
+
336
+ Third, in our wrapper method, we capture the arguments passed in, collect the operation and key information into a local
337
+ hash and then invoke the `AppOpticsAPM::SDK.trace` method to time the execution of the original operation.
338
+
339
+ The `AppOpticsAPM::SDK.trace` method calls Dalli's native operation and reports the timing metrics and your custom
340
+ `report_kvs` up to AppOptics servers to be shown on the user's dashboard.
341
+
342
+ Some other tips and guidelines:
343
+
344
+ * You can point your Gemfile directly at your cloned appoptics gem source by using
345
+ `gem 'appoptics', :path => '/path/to/ruby-appoptics'`
346
+
347
+ * If instrumenting a library, database or service, place your new instrumentation file into the `lib/appoptics/inst/`
348
+ directory. From there, the appoptics gem will detect it and automatically load the instrumentation file.
349
+
350
+ * If instrumenting a new framework, place your instrumentation file in `lib/appoptics/frameworks`. Refer to the Rails
351
+ instrumentation for on ideas on how to load the appoptics gem correctly in your framework.
352
+
353
+ * Review other existing instrumentation similar to the one you wish to author. `lib/appoptics/inst/` is a great place
354
+ to start.
355
+
356
+ * Depending on the configured `:sample_rate`, not all requests will be traced. Use `AppOpticsAPM.tracing?` to determine
357
+ of this is a request that is being traced.
358
+
359
+ * Performance is paramount. Make sure that your wrapped methods don't slow down users applications.
360
+
361
+ * Include tests with your instrumentation. See `test/instrumentation/` for some examples of existing instrumentation
362
+ tests.
363
+
364
+ ## Compiling the C extension
365
+
366
+ The appoptics gem utilizes a C extension to interface with a core library bundled in with the gem which handles
367
+ reporting the trace and performance data back to AppOptics servers.
368
+
369
+ C extensions are usually built on `gem install` but when working out of a local git repository, it's required that you
370
+ manually build this C extension for the gem to function.
371
+
372
+ To make this simpler, we've included a few rake tasks to automate this process:
373
+
374
+ ```bash
375
+ rake compile # Build the gem's c extension
376
+ rake distclean # Remove all built files and extensions
377
+ rake recompile # Rebuild the gem's c extension
378
+ ```
379
+
380
+ To see the code related to the C extension, take a look at `ext/oboe_metal/extconf.rb` for details.
381
+
382
+ You can read more about Ruby gems with C extensions in the
383
+ [Rubygems Guides](http://guides.rubygems.org/gems-with-extensions/).
384
+
385
+ ## Running the Tests
386
+
387
+ See the README in the test directory.
388
+
389
+ # License
390
+
391
+ Copyright (c) 2018 SolarWinds, LLC
392
+
393
+ Released under the [Librato Open License](https://docs.appoptics.com/kb/apm_tracing/librato-open-license/)