appoptics-api-ruby 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +25 -0
  5. data/CHANGELOG.md +184 -0
  6. data/Gemfile +36 -0
  7. data/LICENSE +24 -0
  8. data/README.md +271 -0
  9. data/Rakefile +63 -0
  10. data/appoptics-api-ruby.gemspec +31 -0
  11. data/benchmarks/array_vs_set.rb +29 -0
  12. data/certs/librato-public.pem +20 -0
  13. data/examples/simple.rb +24 -0
  14. data/examples/submit_every.rb +27 -0
  15. data/lib/appoptics/metrics.rb +95 -0
  16. data/lib/appoptics/metrics/aggregator.rb +138 -0
  17. data/lib/appoptics/metrics/annotator.rb +145 -0
  18. data/lib/appoptics/metrics/client.rb +361 -0
  19. data/lib/appoptics/metrics/collection.rb +43 -0
  20. data/lib/appoptics/metrics/connection.rb +101 -0
  21. data/lib/appoptics/metrics/errors.rb +32 -0
  22. data/lib/appoptics/metrics/middleware/count_requests.rb +28 -0
  23. data/lib/appoptics/metrics/middleware/expects_status.rb +38 -0
  24. data/lib/appoptics/metrics/middleware/request_body.rb +18 -0
  25. data/lib/appoptics/metrics/middleware/retry.rb +31 -0
  26. data/lib/appoptics/metrics/persistence.rb +2 -0
  27. data/lib/appoptics/metrics/persistence/direct.rb +73 -0
  28. data/lib/appoptics/metrics/persistence/test.rb +27 -0
  29. data/lib/appoptics/metrics/processor.rb +130 -0
  30. data/lib/appoptics/metrics/queue.rb +191 -0
  31. data/lib/appoptics/metrics/smart_json.rb +43 -0
  32. data/lib/appoptics/metrics/util.rb +25 -0
  33. data/lib/appoptics/metrics/version.rb +5 -0
  34. data/spec/integration/metrics/annotator_spec.rb +190 -0
  35. data/spec/integration/metrics/connection_spec.rb +14 -0
  36. data/spec/integration/metrics/middleware/count_requests_spec.rb +28 -0
  37. data/spec/integration/metrics/queue_spec.rb +96 -0
  38. data/spec/integration/metrics_spec.rb +375 -0
  39. data/spec/rackups/status.ru +30 -0
  40. data/spec/spec_helper.rb +88 -0
  41. data/spec/unit/metrics/aggregator_spec.rb +417 -0
  42. data/spec/unit/metrics/client_spec.rb +127 -0
  43. data/spec/unit/metrics/connection_spec.rb +113 -0
  44. data/spec/unit/metrics/queue/autosubmission_spec.rb +57 -0
  45. data/spec/unit/metrics/queue_spec.rb +593 -0
  46. data/spec/unit/metrics/smart_json_spec.rb +79 -0
  47. data/spec/unit/metrics/util_spec.rb +23 -0
  48. data/spec/unit/metrics_spec.rb +63 -0
  49. metadata +135 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ab5f2ec4dda081acffb747cb10f167f17751850e
4
+ data.tar.gz: 6f29021a2c15a03c19eb8a330e6df74a800c23e5
5
+ SHA512:
6
+ metadata.gz: b62cf09a2685a4f9b3feded918b24f2b52c476edcd096a077f2e75c0dcaacb9f1b1b28b45ea37c6a46027874253c051616479dc5d49e82d555956f7d8b85f07f
7
+ data.tar.gz: be366b70d620f0e576731c318163a6c10e4e8d76d8b4462969638bb5c4b2338ca16b0136d66de7f82da67dc8391896edab58ab55b91ea4a518e52e803ebe264a
@@ -0,0 +1,23 @@
1
+ .ruby-gemset
2
+ .ruby-version
3
+
4
+ .bundle
5
+ .DS_Store
6
+ Gemfile.lock
7
+ *.gem
8
+
9
+ # docs
10
+ rdoc
11
+ doc
12
+ .yardoc
13
+
14
+ # textmate
15
+ *.tmproj
16
+
17
+ # vim
18
+ *.swp
19
+
20
+ # rcov generated
21
+ coverage
22
+
23
+ test_env.sh
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,25 @@
1
+ # use container-based infrastructure
2
+ sudo: false
3
+
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.1.10
7
+ - 2.2.6
8
+ - 2.3.3
9
+ - 2.4.0
10
+ - jruby-19mode
11
+ # - rbx
12
+ - ruby-head
13
+
14
+ matrix:
15
+ allow_failures:
16
+ - rvm: ruby-head
17
+
18
+ branches:
19
+ except:
20
+ - /^v[0-9]/
21
+
22
+ notifications:
23
+ email:
24
+ on_failure: change
25
+ on_success: never
@@ -0,0 +1,184 @@
1
+ ## Changelog
2
+
3
+ ### Version 2.1.3
4
+ * Update to support the AppOptics API
5
+
6
+ ### Version 2.1.2
7
+ * Add `Faraday` 0.8.x support to `ExpectsStatus` (#138, George Ogata)
8
+
9
+ ### Version 2.1.1
10
+ * Fix `#empty?` to check queued payload (#137, Cyril David)
11
+
12
+ ### Version 2.1.0
13
+ * Add support for tagged measurements (#121)
14
+
15
+ ### Version 2.0.2
16
+ * Filter sensitive headers in exception output (#130, Yannick Schutz)
17
+
18
+ ### Version 2.0.1
19
+ * Fix SmartJSON delegation bug for ruby 2.3.1 (#123)
20
+
21
+ ### Version 2.0.0
22
+ * Remove support for deprecated methods (#117)
23
+ * Upgrade rspec from 2.6 to 3.5 (#118)
24
+ * Remove support for ruby 1.8 (#119)
25
+ * Remove `MultiJson` runtime dependency (#119)
26
+ * Relax `Faraday` runtime dependency (#119)
27
+
28
+ ### Version 1.6.1
29
+ * Fix bugs with listing sources (#116)
30
+
31
+ ### Version 1.6.0
32
+ * Add HTTP proxy support (#112) (Genki Sugawara)
33
+
34
+ ### Version 1.5.1
35
+ * Fix bug causing incompatible dates when annotating with block form (#109)
36
+
37
+ ### Version 1.5.0
38
+ * Add #get_composite for easier fetching of composite measurements
39
+
40
+ ### Version 1.4.0
41
+ * Add support for snapshots
42
+
43
+ ### Version 1.3.2
44
+ * Fix queue autosubmission to fire if needed after #merge! calls
45
+
46
+ ### Version 1.3.1
47
+ * Fix auto-chunking for large measurements sets with a global source
48
+
49
+ ### Version 1.3.0
50
+ * Add support for working with sources as a first-class entity
51
+
52
+ ### Version 1.2.0
53
+ * Give metric-facing methods more explicit names & deprecate priors
54
+ * Documentation improvements
55
+
56
+ ### Version 1.1.1
57
+ * Move gem sign code to rake task, fixes bug bundling in some environments
58
+
59
+ ### Version 1.1.0
60
+ * Add ability to update annotation events
61
+ * Add ability to fetch annotation events
62
+ * Add block form of annotation
63
+ * Add metric batch update support
64
+ * Add support for pattern-based metric deletes
65
+ * Add set of code examples
66
+ * Sign gem when building
67
+ * Documentation improvements
68
+
69
+ ### Version 1.0.4
70
+ * Ensure sane default timeouts for all requests
71
+
72
+ ### Version 1.0.3
73
+ * Fix bug where retries of POST requests could 400
74
+ * Network related exceptions capture response state better
75
+
76
+ ### Version 1.0.2
77
+ * Fix bug with some versions of MultiJson (Thomas Dippel)
78
+ * Use delegation for JSON handling
79
+ * Improve integration tests
80
+
81
+ ### Version 1.0.1
82
+ * Fix Forwardable dependency loading bug
83
+
84
+ ### Version 1.0.0
85
+ * Add support for annotation submission, listing, management
86
+ * Auto-convert Time objects anywhere a time is accepted
87
+ * Don't raise exception anymore for empty queue submission
88
+
89
+ ### Version 0.7.5
90
+ * Catch a broader range of connection failures for retrying
91
+ * Add Metrics.faraday_adapter config option (Mathieu Ravaux)
92
+
93
+ ### Version 0.7.4
94
+ * Support global measure_time option for Queues/Aggregators
95
+ * Support all versions of multi_json so we can relax version constraint
96
+
97
+ ### Version 0.7.3
98
+ * Allow prefixes to be changed after instantiation on Queues/Aggregators
99
+
100
+ ### Version 0.7.2
101
+ * Extend prefix option support to Aggregators
102
+
103
+ ### Version 0.7.1
104
+ * Add prefix option to Queues
105
+
106
+ ### Version 0.7.0
107
+ * Add ability to update metric properties (Christoph Bünte)
108
+ * Add ability to merge queue and aggregator data into a queue
109
+ * Aggregator supports custom source by measurement
110
+ * Add option to clear queued measurements after failed submit
111
+ * Custom user agent support
112
+ * Documentation improvements
113
+
114
+ ### Version 0.6.1
115
+ * Loosen restrictions to older versions of faraday and multi_json
116
+ * Fix symbol casting issue in jruby with metric delete
117
+ * client#new_queue now respects passed options
118
+ * Queue objects support default source properly
119
+
120
+ ### Version 0.6.0
121
+ * Add Aggregator class for aggregating measurements client-side
122
+ * Queue and Aggregator can auto-submit on a time interval
123
+ * Queue can auto-submit on a specified volume of measurements
124
+ * Support deleting individual metrics
125
+ * Validate user-specified measurement times
126
+ * Update to MultiJSON 1.3 syntax
127
+ * Run tests for rubinius and jruby in both 1.8 and 1.9 modes
128
+ * Include request body in output for failed requests
129
+ * Documentation improvements
130
+
131
+ ### Version 0.5.0
132
+ * Support using multiple accounts simultaneously via Client
133
+ * Switch network library to faraday for broader platform support and flexibility
134
+ * Automatically break large submissions into multiple requests for better performance
135
+ * Automatic retry support
136
+ * Consolidate connection functions in Connection
137
+ * Documentation improvements
138
+
139
+ ### Version 0.4.3
140
+ * Bump excon to 0.13x to fix proxy support
141
+
142
+ ### Version 0.4.2
143
+ * Fix SSL verify peer issues with JRuby (Sean Porter)
144
+
145
+ ### Version 0.4.1
146
+ * Fix issues with auth encoding whitespace
147
+
148
+ ### Version 0.4.0
149
+ * Add ability to set agent_identifier for use with developer program (Sean Porter)
150
+ * Documentation improvements
151
+
152
+ ### Version 0.3.1
153
+ * Upgrade excon to 0.9.5 to fix intermittent socket errors
154
+
155
+ ### Version 0.3.0
156
+ * Add auto-pagination support to metric listing (Nuno Valente)
157
+ * Add #size/#length to Queue objects (Michael Gorsuch)
158
+ * Add #empty? to Queue objects
159
+ * Remove deprecated .json extensions from API URIs
160
+ * Use new singular route for metric GETs
161
+ * README improvements
162
+ * Add #clear as alias to Queue's #flush
163
+ * Switch to multi_json for better cross-platform json handling
164
+ * Set up basic integration testing suite
165
+ * Improve testing rake tasks
166
+
167
+ ### Version 0.2.3
168
+ * Fix broken user-agent string in 1.8.7 (Sean Porter)
169
+ * Update outdated spec
170
+
171
+ ### Version 0.2.2
172
+ * Fix abstract persistence instantiation in Ruby 1.8/REE
173
+
174
+ ### Version 0.2.1
175
+ * Add better handling for start_time and end_time params when fetching measurements
176
+
177
+ ### Version 0.2.0
178
+ * Fix bug with stale excon connections not reconnecting
179
+ * Add custom User-Agent
180
+ * Items added to Queue objects have their measure_time set automatically
181
+ * Metric 'type' key can be string or symbol (Neil Mock)
182
+
183
+ ### Version 0.1.0
184
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,36 @@
1
+ source "https://rubygems.org"
2
+
3
+ platforms :jruby do
4
+ gem 'jruby-openssl'
5
+ end
6
+
7
+ platforms :ruby_19 do
8
+ # make available for yard under C rubies
9
+ gem 'redcarpet'
10
+ end
11
+
12
+ platforms :rbx do
13
+ # rubinius stdlib
14
+ gem 'rubysl', '~> 2.0'
15
+ gem 'rubinius-developer_tools'
16
+ end
17
+
18
+ gem 'rake'
19
+ gem 'aggregate'
20
+ gem 'faraday'
21
+
22
+ # docs
23
+ gem 'yard'
24
+
25
+ # debugging
26
+ gem 'pry'
27
+
28
+ # easily generate test data
29
+ gem 'quixote'
30
+
31
+ group :test do
32
+ gem 'rspec', '~> 3.5.0'
33
+ gem 'sinatra'
34
+ gem 'popen4'
35
+ gem 'multi_json'
36
+ end
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2017. Solarwinds, Inc.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of Solarwinds nor the names of project contributors
12
+ may be used to endorse or promote products derived from this software
13
+ without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL Solarwinds BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,271 @@
1
+ AppOptics API Ruby
2
+ =======
3
+
4
+ Ruby bindings for the AppOptics API
5
+
6
+ This gem provides granular control for scripting interactions with the API. It is well suited for integrations, scripts, workers & background jobs.
7
+
8
+ ## Installation
9
+
10
+ In your shell:
11
+
12
+ gem install appoptics-api-ruby
13
+
14
+ Then, in your application or script:
15
+
16
+ require 'appoptics/metrics'
17
+
18
+ ### Optional steps
19
+
20
+ For best performance we recommend installing [yajl-ruby](https://github.com/brianmario/yajl-ruby):
21
+
22
+ gem install yajl-ruby
23
+
24
+ If you are using jruby, you need to ensure [jruby-openssl](https://github.com/jruby/jruby-ossl) is available:
25
+
26
+ gem install jruby-openssl
27
+
28
+ ## Quick Start
29
+
30
+ If you are looking for the quickest possible route to getting a data into Metrics, you only need two lines:
31
+
32
+ Appoptics::Metrics.authenticate 'api_key'
33
+ Appoptics::Metrics.submit my_metric: { value: 42, tags: { host: 'localhost' } }
34
+
35
+ While this is all you need to get started, if you are sending a number of metrics regularly a queue may be easier/more performant so read on...
36
+
37
+
38
+ ## Authentication
39
+
40
+ Make sure you have [an account for AppOptics](https://www.appoptics.com/) and then authenticate with your email and API key (on your account page):
41
+
42
+ Appoptics::Metrics.authenticate 'api_key'
43
+
44
+
45
+ ## Sending Measurements
46
+
47
+ A measurement includes a metric name, value, and one or more tags. Tags include a name/value pair that describe a particular data stream. Each unique tag set creates an individual metric stream which can later be filtered and aggregated along.
48
+
49
+ Queue up a simple metric named `temperature`:
50
+
51
+ queue = Appoptics::Metrics::Queue.new
52
+ queue.add temperature: {value: 77, tags: { city: 'oakland' }}
53
+ queue.submit
54
+
55
+ ### Top-Level Tags
56
+
57
+ You can initialize `Queue` and/or `Aggregator` with top-level tags that will be applied to every measurement:
58
+
59
+ queue = Appoptics::Metrics::Queue.new(tags: { service: 'auth', environment: 'prod', host: 'auth-prod-1' })
60
+ queue.add my_metric: 10
61
+ queue.submit
62
+
63
+ ### Per-Measurement Tags
64
+
65
+ Optionally, you can submit per-measurement tags by passing a tags Hash when adding measurements:
66
+
67
+ queue.add my_other_metric: { value: 25, tags: { db: 'rr1' } }
68
+ queue.submit
69
+
70
+ For more information, visit the [API documentation](https://docs.appoptics.com/api/#create-a-measurement).
71
+
72
+
73
+ ## Querying Metrics
74
+
75
+ Get name and properties for all metrics you have in the system:
76
+
77
+ metrics = Appoptics::Metrics.metrics
78
+
79
+ Get only metrics whose name includes `time`:
80
+
81
+ metrics = Appoptics::Metrics.metrics name: 'time'
82
+
83
+
84
+ ## Retrieving Measurements
85
+
86
+ Get the series for `exceptions` in **production** grouped by **sum** within the **last hour**:
87
+
88
+ ```ruby
89
+ query = {
90
+ resolution: 1,
91
+ duration: 3600,
92
+ group_by: "environment",
93
+ group_by_function: "sum",
94
+ tags_search: "environment=prod*"
95
+ }
96
+ Appoptics::Metrics.get_series :exceptions, query
97
+ ```
98
+
99
+ For more information, visit the [API documentation](https://docs.appoptics.com/api/#retrieve-a-measurement).
100
+
101
+
102
+ ## Aggregate Measurements
103
+
104
+ If you are measuring something very frequently e.g. per-request in a web application (order mS) you may not want to send each individual measurement, but rather periodically send a [single aggregate measurement](https://docs.appoptics.com/api/#gauge-specific-parameters), spanning multiple seconds or even minutes. Use an `Aggregator` for this.
105
+
106
+ Aggregate a simple gauge metric named `response_latency`:
107
+
108
+ aggregator = Appoptics::Metrics::Aggregator.new
109
+ aggregator.add response_latency: 85.0
110
+ aggregator.add response_latency: 100.5
111
+ aggregator.add response_latency: 150.2
112
+ aggregator.add response_latency: 90.1
113
+ aggregator.add response_latency: 92.0
114
+
115
+ Which would result in a gauge measurement like:
116
+
117
+ {name: "response_latency", count: 5, sum: 517.8, min: 85.0, max: 150.2}
118
+
119
+ You can specify a source during aggregate construction:
120
+
121
+ aggregator = Appoptics::Metrics::Aggregator.new(tags: { service: 'auth', environment: 'prod', host: 'auth-prod-1' })
122
+
123
+ You can aggregate multiple metrics at once:
124
+
125
+ aggregator.add app_latency: 35.2, db_latency: 120.7
126
+
127
+ Send the currently aggregated metrics to Metrics:
128
+
129
+ aggregator.submit
130
+
131
+ ## Benchmarking
132
+
133
+ If you have operations in your application you want to record execution time for, both `Queue` and `Aggregator` support the `#time` method:
134
+
135
+ aggregator.time :my_measurement do
136
+ # do work...
137
+ end
138
+
139
+ The difference between the two is that `Queue` submits each timing measurement individually, while `Aggregator` submits a single timing measurement spanning all executions.
140
+
141
+ If you need extra attributes for a `Queue` timing measurement, simply add them on:
142
+
143
+ queue.time :my_measurement do
144
+ # do work...
145
+ end
146
+
147
+ ## Annotations
148
+
149
+ Annotation streams are a great way to track events like deploys, backups or anything else that might affect your system. They can be overlaid on any other metric stream so you can easily see the impact of changes.
150
+
151
+ At a minimum each annotation needs to be assigned to a stream and to have a title. Let's add an annotation for deploying `v45` of our app to the `deployments` stream:
152
+
153
+ Appoptics::Metrics.annotate :deployments, 'deployed v45'
154
+
155
+ There are a number of optional fields which can make annotations even more powerful:
156
+
157
+ Appoptics::Metrics.annotate :deployments, 'deployed v46', source: 'frontend',
158
+ start_time: 1354662596, end_time: 1354662608,
159
+ description: 'Deployed 6f3bc6e67682: fix lotsa bugs…'
160
+
161
+ You can also automatically annotate the start and end time of an action by using `annotate`'s block form:
162
+
163
+ Appoptics::Metrics.annotate :deployments, 'deployed v46' do
164
+ # do work..
165
+ end
166
+
167
+ More fine-grained control of annotations is available via the `Annotator` object:
168
+
169
+ annotator = Appoptics::Metrics::Annotator.new
170
+
171
+ # list annotation streams
172
+ streams = annotator.list
173
+
174
+ # fetch a list of events in the last hour from a stream
175
+ annotator.fetch :deployments, start_time: (Time.now.to_i-3600)
176
+
177
+ # delete an event
178
+ annotator.delete_event 'deployments', 23
179
+
180
+ See the documentation of `Annotator` for more details and examples of use.
181
+
182
+ ## Auto-Submitting Metrics
183
+
184
+ Both `Queue` and `Aggregator` support automatically submitting measurements on a given time interval:
185
+
186
+ # submit once per minute
187
+ timed_queue = Appoptics::Metrics::Queue.new(autosubmit_interval: 60)
188
+
189
+ # submit every 5 minutes
190
+ timed_aggregator = Appoptics::Metrics::Aggregator.new(autosubmit_interval: 300)
191
+
192
+ `Queue` also supports auto-submission based on measurement volume:
193
+
194
+ # submit when the 400th measurement is queued
195
+ volume_queue = Appoptics::Metrics::Queue.new(autosubmit_count: 400)
196
+
197
+ These options can also be combined for more flexible behavior.
198
+
199
+ Both options are driven by the addition of measurements. *If you are adding measurements irregularly (less than once per second), time-based submission may lag past your specified interval until the next measurement is added.*
200
+
201
+ If your goal is to collect metrics every _x_ seconds and submit them, [check out this code example](https://github.com/appoptics/appoptics-api-ruby/blob/master/examples/submit_every.rb).
202
+
203
+ ## Setting Metric Properties
204
+
205
+ Setting custom [properties](https://docs.appoptics.com/api/#metric-attributes) on your metrics is easy:
206
+
207
+ # assign a period and default color
208
+ Appoptics::Metrics.update_metric :temperature, period: 15, attributes: { color: 'F00' }
209
+
210
+ ## Deleting Metrics
211
+
212
+ If you ever need to remove a metric and all of its measurements, doing so is easy:
213
+
214
+ # delete the metrics 'temperature' and 'humidity'
215
+ Appoptics::Metrics.delete_metrics :temperature, :humidity
216
+
217
+ You can also delete using wildcards:
218
+
219
+ # delete metrics that start with cpu. except for cpu.free
220
+ Appoptics::Metrics.delete_metrics names: 'cpu.*', exclude: ['cpu.free']
221
+
222
+ Note that deleted metrics and their measurements are unrecoverable, so use with care.
223
+
224
+ ## Using Multiple Accounts Simultaneously
225
+
226
+ If you need to use metrics with multiple sets of authentication credentials simultaneously, you can do it with `Client`:
227
+
228
+ joe = Appoptics::Metrics::Client.new
229
+ joe.authenticate 'api_key1'
230
+
231
+ mike = Appoptics::Metrics::Client.new
232
+ mike.authenticate 'api_key2'
233
+
234
+ All of the same operations you can call directly from `Appoptics::Metrics` are available per-client:
235
+
236
+ # list Joe's metrics
237
+ joe.metrics
238
+
239
+ There are two ways to associate a new queue with a client:
240
+
241
+ # these are functionally equivalent
242
+ joe_queue = Appoptics::Metrics::Queue.new(client: joe)
243
+ joe_queue = joe.new_queue
244
+
245
+ Once the queue is associated you can use it normally:
246
+
247
+ joe_queue.add temperature: { value: 65.2, tags: { city: 'san francisco' } }
248
+ joe_queue.submit
249
+
250
+ ## Thread Safety
251
+
252
+ The `appoptics-api-ruby` gem currently does not do internal locking for thread safety. When used in multi-threaded applications, please add your own [mutexes](http://www.ruby-doc.org/core-2.0/Mutex.html) for sensitive operations.
253
+
254
+ ## More Information
255
+
256
+ `appoptics-api-ruby` is sufficiently complex that not everything can be documented in the README. Additional options are documented regularly in the codebase. You are encouraged to take a quick look through the [source](https://github.com/appoptics/appoptics-api-ruby) for more.
257
+
258
+ We also maintain a set of [examples of common uses](https://github.com/appoptics/appoptics-api-ruby/tree/master/examples) and appreciate contributions if you have them.
259
+
260
+ ## Contribution
261
+
262
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
263
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
264
+ * Fork the project and submit a pull request from a feature or bugfix branch.
265
+ * Please review our [code conventions](https://github.com/appoptics/appoptics-api-ruby/wiki/Code-Conventions).
266
+ * Please include specs. This is important so we don't break your changes unintentionally in a future version.
267
+ * Please don't modify the gemspec, Rakefile, version, or changelog. If you do change these files, please isolate a separate commit so we can cherry-pick around it.
268
+
269
+ ## Copyright
270
+
271
+ Copyright (c) 2011-2017 [Solarwinds, Inc.](http://www.solarwinds.com) See LICENSE for details.