yodeler 0.0.10 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +33 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/Guardfile +16 -0
- data/README.md +158 -67
- data/Rakefile +4 -21
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/yodeler/adapter_not_registered_error.rb +14 -0
- data/lib/yodeler/adapters/http_adapter.rb +51 -0
- data/lib/yodeler/adapters/memory_adapter.rb +23 -0
- data/lib/yodeler/adapters/void_adapter.rb +10 -0
- data/lib/yodeler/client.rb +166 -0
- data/lib/yodeler/duplicate_endpoint_name_error.rb +9 -0
- data/lib/yodeler/endpoint.rb +35 -0
- data/lib/yodeler/metric.rb +36 -0
- data/lib/yodeler/version.rb +1 -1
- data/lib/yodeler.rb +41 -106
- data/yodeler.gemspec +29 -0
- metadata +44 -102
- data/MIT-LICENSE +0 -20
- data/app/assets/javascripts/yodeler/application.js +0 -13
- data/app/assets/stylesheets/yodeler/application.css +0 -13
- data/app/controllers/yodeler/application_controller.rb +0 -4
- data/app/helpers/yodeler/application_helper.rb +0 -4
- data/app/views/layouts/yodeler/application.html.erb +0 -14
- data/config/routes.rb +0 -2
- data/lib/generators/yodeler/USAGE +0 -2
- data/lib/generators/yodeler/install_generator.rb +0 -23
- data/lib/generators/yodeler/templates/initializer.rb +0 -7
- data/lib/generators/yodeler/templates/migration.rb +0 -50
- data/lib/tasks/yodeler_tasks.rake +0 -4
- data/lib/yodeler/configuration.rb +0 -12
- data/lib/yodeler/engine.rb +0 -10
- data/lib/yodeler/listens_to_yodeler.rb +0 -32
- data/lib/yodeler/models/event.rb +0 -17
- data/lib/yodeler/models/event_type.rb +0 -6
- data/lib/yodeler/models/event_types/base.rb +0 -59
- data/lib/yodeler/models/event_types/noop_event_type.rb +0 -12
- data/lib/yodeler/models/notification.rb +0 -30
- data/lib/yodeler/models/subscription.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa2389240d853b1e917ca4741cd9d8ca0c9bde03
|
4
|
+
data.tar.gz: 43aae361bf5632fea1641a3914f2b5390759cffe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a081b0689cd5e2f0f2a3c192a54832459a0935f020aa7392a23ec3e4d9771fdff89280b120e57219e14507c597f38266ce71ae6150f67118ff7459fb42cf33be
|
7
|
+
data.tar.gz: 7eb2cd49a592a382610031303a10a1eeb4313c2893aa1c5d40e48ce0d7446dd04af2cd119aefaf5d2a5860f21f6252e4fa3401f6ef804f57f4b41ce4c6b9f1a7
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
---
|
2
|
+
engines:
|
3
|
+
brakeman:
|
4
|
+
enabled: false
|
5
|
+
bundler-audit:
|
6
|
+
enabled: true
|
7
|
+
duplication:
|
8
|
+
enabled: true
|
9
|
+
config:
|
10
|
+
languages:
|
11
|
+
- ruby
|
12
|
+
fixme:
|
13
|
+
enabled: true
|
14
|
+
rubocop:
|
15
|
+
enabled: true
|
16
|
+
ratings:
|
17
|
+
paths:
|
18
|
+
- Gemfile.lock
|
19
|
+
- "**.erb"
|
20
|
+
- "**.haml"
|
21
|
+
- "**.rb"
|
22
|
+
- "**.rhtml"
|
23
|
+
- "**.slim"
|
24
|
+
- "**.inc"
|
25
|
+
- "**.js"
|
26
|
+
- "**.jsx"
|
27
|
+
- "**.module"
|
28
|
+
- "**.php"
|
29
|
+
- "**.py"
|
30
|
+
exclude_paths:
|
31
|
+
- config/**/*
|
32
|
+
- db/**/*
|
33
|
+
- spec/**/*
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
2
|
+
require "guard/rspec/dsl"
|
3
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
4
|
+
|
5
|
+
# Feel free to open issues for suggestions and improvements
|
6
|
+
|
7
|
+
# RSpec files
|
8
|
+
rspec = dsl.rspec
|
9
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
10
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
11
|
+
watch(rspec.spec_files)
|
12
|
+
|
13
|
+
# Ruby files
|
14
|
+
ruby = dsl.ruby
|
15
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
16
|
+
end
|
data/README.md
CHANGED
@@ -1,106 +1,197 @@
|
|
1
|
-
Yodeler
|
2
|
-
=======
|
1
|
+
# Yodeler
|
3
2
|
|
4
|
-
|
3
|
+
A generic instrumentation library thats supports reporting to multiple endpoints via pluggable backend adapters.
|
5
4
|
|
6
|
-
|
5
|
+
Spoutin' off noise to whoever is listening.
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
![Build Status](https://travis-ci.org/coryodaniel/yodeler.svg "Build Status")
|
8
|
+
[![Test Coverage](https://codeclimate.com/github/coryodaniel/yodeler/badges/coverage.svg)](https://codeclimate.com/github/coryodaniel/yodeler/coverage)
|
9
|
+
[![Code Climate](https://codeclimate.com/github/coryodaniel/yodeler/badges/gpa.svg)](https://codeclimate.com/github/coryodaniel/yodeler)
|
11
10
|
|
11
|
+
## Installation
|
12
12
|
|
13
|
-
|
14
|
-
========
|
13
|
+
Add this line to your application's Gemfile:
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
* flexible payloads
|
20
|
-
|
21
|
-
|
22
|
-
What's wrong with XMPP?
|
23
|
-
=======================
|
15
|
+
```ruby
|
16
|
+
gem 'yodeler', '~>0.1.1'
|
17
|
+
```
|
24
18
|
|
25
|
-
|
19
|
+
And then execute:
|
26
20
|
|
27
|
-
|
21
|
+
$ bundle
|
28
22
|
|
29
|
-
|
23
|
+
Or install it yourself as:
|
30
24
|
|
31
|
-
|
25
|
+
$ gem install yodeler
|
32
26
|
|
27
|
+
## Usage
|
33
28
|
|
34
|
-
|
35
|
-
=====
|
29
|
+
### Configuration
|
36
30
|
|
31
|
+
#### Single endpoint
|
32
|
+
In ```config/initializers/yodeler.rb```
|
37
33
|
```ruby
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
}
|
34
|
+
Yodeler.configure do |client|
|
35
|
+
# if no endpoint name is given, it defaults to :default
|
36
|
+
client.adapter(:http) do |http|
|
37
|
+
http.path = '/events'
|
38
|
+
http.host = 'example.com'
|
39
|
+
# http.port = 80
|
40
|
+
# http.use_ssl = false
|
41
|
+
# http.default_params = {}
|
42
|
+
end
|
48
43
|
end
|
49
44
|
```
|
50
45
|
|
46
|
+
#### Multiple Endpoints
|
47
|
+
In ```config/initializers/yodeler.rb```
|
51
48
|
```ruby
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
# do your User#show as normal
|
49
|
+
|
50
|
+
Yodeler.configure do |client|
|
51
|
+
client.endpoint(:sales_reporting).adapter(:http) do |http|
|
52
|
+
http.path = '/events'
|
53
|
+
http.host = 'sales.example.com'
|
58
54
|
end
|
59
55
|
|
60
|
-
|
56
|
+
client.endpoint(:devops_reporting).adapter(:http) do |http|
|
57
|
+
http.path = '/events'
|
58
|
+
http.host = 'devops.example.com'
|
59
|
+
end
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
# by default, the client dispatches to the first registered endpoint
|
62
|
+
# you can change it to a different one
|
63
|
+
# Alternatively you can dispatch to a set of endpoints when dispatching a metric
|
64
|
+
# Yodeler.gauge('users.count', 35, to: [:sales_reporting, :devops_reporting])
|
65
|
+
client.default_endpoint_name = :devops_reporting
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
#### Full Configuration Example
|
70
|
+
In ```config/yodeler.yml```
|
71
|
+
```yaml
|
72
|
+
development:
|
73
|
+
auth_token: SOSECUREZ
|
74
|
+
sales_reporting:
|
75
|
+
host: localhost
|
76
|
+
port: 3030
|
77
|
+
devops_reporting:
|
78
|
+
host: localhost
|
79
|
+
port: 3031
|
80
|
+
```
|
81
|
+
|
82
|
+
In ```config/initializers/yodeler.rb```
|
83
|
+
```ruby
|
84
|
+
config = YAML.load(File.read("./config/yodeler.yml"))[Rails.env]
|
85
|
+
|
86
|
+
Yodeler.configure do |client|
|
87
|
+
client.endpoint(:sales_reporting).adapter(:http) do |http|
|
88
|
+
http.path = '/events'
|
89
|
+
http.host = config[:sales_reporting][:host]
|
90
|
+
http.port = config[:sales_reporting][:port]
|
91
|
+
http.default_params = {
|
92
|
+
auth_token: config[:auth_token]
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
client.endpoint(:devops_reporting).adapter(:http) do |http|
|
97
|
+
http.path = '/events'
|
98
|
+
http.host = config[:devops_reporting][:host]
|
99
|
+
http.port = config[:devops_reporting][:port]
|
100
|
+
http.default_params = {
|
101
|
+
auth_token: config[:auth_token]
|
102
|
+
}
|
103
|
+
|
104
|
+
# Overwrite the default http dispatcher or overwrite an individual metric dispatcher
|
105
|
+
# http.handle(:gauge){|url, metric, default_params| ... something cool ... }
|
106
|
+
http.handle(:default) do |url, metric, default_params|
|
107
|
+
# This is the default handler definition, but you could change it
|
108
|
+
HTTP.post(url, json: default_params.merge(metric.to_hash))
|
66
109
|
end
|
67
110
|
end
|
111
|
+
|
112
|
+
client.default_endpoint_name = :devops_reporting
|
68
113
|
end
|
114
|
+
|
69
115
|
```
|
70
116
|
|
117
|
+
#### [Dashing Example](https://github.com/shopify/dashing)
|
71
118
|
```ruby
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
119
|
+
Yodeler.configure do |client|
|
120
|
+
client.endpoint(:karma_widget).adapter(:http) do |http|
|
121
|
+
http.path = '/widgets/karma'
|
122
|
+
http.host = 'localhost'
|
123
|
+
http.default_params = {
|
124
|
+
auth_token: config[:auth_token]
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
client.endpoint(:user_count_widget).adapter(:http) do |http|
|
129
|
+
http.path = '/widgets/user_count'
|
130
|
+
http.host = 'localhost'
|
131
|
+
http.default_params = {
|
132
|
+
auth_token: config[:auth_token]
|
133
|
+
}
|
81
134
|
end
|
82
135
|
end
|
83
136
|
```
|
84
137
|
|
138
|
+
### Publishing Metrics and Events
|
85
139
|
|
86
|
-
|
87
|
-
==========================
|
140
|
+
#### All instrumentation methods support an options hash
|
88
141
|
|
142
|
+
* :prefix - [~String] :prefix your metric/event names
|
143
|
+
* :tags - [Array<String,Symbol>, String, Symbol] :tags ([]) array of tags to apply to metric/event
|
144
|
+
* :sample_rate - [Float] :sample_rate (1.0) The sample rate to use
|
145
|
+
* :to - [Array<Symbol>, Symbol] :to array of endpoint names to send the metric/event to. If not set will send to Yodeler::Client#default_endpoint_name
|
146
|
+
|
147
|
+
#### Gauge
|
89
148
|
```ruby
|
90
|
-
|
91
|
-
|
149
|
+
Yodeler.gauge 'user.count', 35
|
150
|
+
Yodeler.gauge 'user.count', 35, prefix: 'test'
|
151
|
+
Yodeler.gauge 'user.count', 35, sample_rate: 0.5
|
152
|
+
Yodeler.gauge 'user.count', 35, prefix: 'test', tags: ['cool']
|
153
|
+
Yodeler.gauge 'user.count', 35, to: [:devops_reporting, :sales_reporting]
|
154
|
+
```
|
92
155
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
156
|
+
#### Increment
|
157
|
+
```ruby
|
158
|
+
Yodeler.increment 'users.count'
|
159
|
+
Yodeler.increment 'users.count', to: [:devops_reporting, :sales_reporting]
|
160
|
+
Yodeler.increment 'revenue', 10_000
|
161
|
+
Yodeler.increment 'revenue', 10_000, to: [:devops_reporting, :sales_reporting]
|
162
|
+
|
163
|
+
```
|
97
164
|
|
98
|
-
|
99
|
-
|
100
|
-
|
165
|
+
#### Timing
|
166
|
+
```ruby
|
167
|
+
Yodeler.timing('eat.sandwich', {prefix: :test}) do
|
168
|
+
user.eat(sandwich)
|
169
|
+
end #=> returns result of block
|
101
170
|
|
171
|
+
Yodeler.timing 'eat.sandwich', 250 #in ms
|
172
|
+
Yodeler.timing 'eat.sandwich', 250, to: [:devops_reporting, :sales_reporting]
|
102
173
|
```
|
103
174
|
|
104
|
-
|
105
|
-
|
106
|
-
|
175
|
+
#### Event
|
176
|
+
```ruby
|
177
|
+
wizz_bang = {name: 'Wizz Bang 3000', image_url: 'http://example.com/wizzbang.jpg'}
|
178
|
+
Yodeler.publish 'product.sold', wizz_bang
|
179
|
+
Yodeler.publish 'product.sold', wizz_bang, prefix: 'ecommerce'
|
180
|
+
Yodeler.publish 'product.sold', wizz_bang, sample_rate: 0.25
|
181
|
+
Yodeler.publish 'product.sold', wizz_bang, to: [:devops_reporting, :sales_reporting]
|
182
|
+
```
|
183
|
+
|
184
|
+
## Development
|
185
|
+
|
186
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
187
|
+
|
188
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
189
|
+
|
190
|
+
## Contributing
|
191
|
+
|
192
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/coryodaniel/yodeler.
|
193
|
+
|
194
|
+
## TODOs
|
195
|
+
* [ ] Custom adapter documentation
|
196
|
+
* [ ] Client#format_options -> Metric.format_options
|
197
|
+
* [ ] Client#default_endpoint_name accept array of names
|
data/Rakefile
CHANGED
@@ -1,23 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
rescue LoadError
|
4
|
-
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir = 'rdoc'
|
11
|
-
rdoc.title = 'Yodeler'
|
12
|
-
rdoc.options << '--line-numbers'
|
13
|
-
rdoc.rdoc_files.include('README.rdoc')
|
14
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
-
end
|
16
|
-
|
17
|
-
APP_RAKEFILE = File.expand_path("../spec/test_app/Rakefile", __FILE__)
|
18
|
-
load 'rails/tasks/engine.rake'
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
Bundler::GemHelper.install_tasks
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
23
5
|
|
6
|
+
task :default => :spec
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "yodeler"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Yodeler
|
2
|
+
class AdapterNotRegisteredError < StandardError
|
3
|
+
attr_reader :name
|
4
|
+
def initialize(name:)
|
5
|
+
@name = name
|
6
|
+
msg = [
|
7
|
+
"No Yodeler Adapter registed for: ':#{name}'",
|
8
|
+
"Register an adapter with:",
|
9
|
+
"Yodeler.register_adapter(:#{name}, CustomAdapterClass)"
|
10
|
+
].join("\n")
|
11
|
+
super(msg)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'http'
|
2
|
+
|
3
|
+
module Yodeler::Adapters
|
4
|
+
class HttpAdapter
|
5
|
+
attr_accessor :host
|
6
|
+
attr_accessor :port
|
7
|
+
attr_accessor :path
|
8
|
+
attr_accessor :use_ssl
|
9
|
+
attr_accessor :default_params
|
10
|
+
|
11
|
+
def initialize(host=nil, port:nil, path:nil, use_ssl:false, params:{})
|
12
|
+
@host = host
|
13
|
+
@port = port
|
14
|
+
@path = path
|
15
|
+
@use_ssl = use_ssl
|
16
|
+
@default_params = params
|
17
|
+
@handlers = {}
|
18
|
+
|
19
|
+
handle(:default) do |url, metric, default_params|
|
20
|
+
HTTP.post(url, json: default_params.merge(metric.to_hash))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle(type, &block)
|
25
|
+
@handlers[type] = block
|
26
|
+
end
|
27
|
+
|
28
|
+
def dispatch(metric)
|
29
|
+
(@handlers[metric.type] || @handlers[:default]).call(url, metric, default_params)
|
30
|
+
end
|
31
|
+
|
32
|
+
def url
|
33
|
+
"#{protocol}://#{host_with_port}#{path}"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def host_with_port
|
38
|
+
if port
|
39
|
+
"#{host}:#{port}"
|
40
|
+
else
|
41
|
+
host
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def protocol
|
46
|
+
use_ssl ? :https : :http
|
47
|
+
end
|
48
|
+
|
49
|
+
Yodeler.register_adapter(:http, self)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Yodeler::Adapters
|
2
|
+
class MemoryAdapter
|
3
|
+
attr_reader :queue
|
4
|
+
attr_accessor :max_queue_size
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@max_queue_size = 1000
|
8
|
+
flush!
|
9
|
+
end
|
10
|
+
|
11
|
+
def flush!
|
12
|
+
@queue = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def dispatch(metric)
|
16
|
+
@queue << metric
|
17
|
+
@queue.shift if @queue.length > @max_queue_size
|
18
|
+
metric
|
19
|
+
end
|
20
|
+
|
21
|
+
Yodeler.register_adapter(:memory, self)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Yodeler
|
4
|
+
class Client
|
5
|
+
attr_accessor :default_endpoint_name
|
6
|
+
attr_accessor :default_prefix
|
7
|
+
attr_accessor :default_sample_rate
|
8
|
+
attr_reader :endpoints
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@endpoints = {}
|
12
|
+
@default_sample_rate = 1.0
|
13
|
+
@default_prefix = nil
|
14
|
+
@hostname = Socket.gethostname
|
15
|
+
end
|
16
|
+
|
17
|
+
# Register a new endpoint
|
18
|
+
#
|
19
|
+
# @param [Symbol|String] name of endpoint, must be unique
|
20
|
+
# @return [Yodeler::Endpoint]
|
21
|
+
def endpoint(name=:default, &block)
|
22
|
+
raise DuplicateEndpointNameError.new(name: name) if @endpoints[name]
|
23
|
+
@default_endpoint_name ||= name
|
24
|
+
@endpoints[name] = Endpoint.new(name,&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get the default endpoint
|
28
|
+
#
|
29
|
+
# @return [Yodeler::Endpoint] Get the default endpoint
|
30
|
+
def default_endpoint
|
31
|
+
@endpoints[default_endpoint_name]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Syntax sugar for creating the default endpoint and set the adapter
|
35
|
+
#
|
36
|
+
# Useful if you just have one endpoint and don't care about its name
|
37
|
+
# like during testing or for simple metric reporting scenarios
|
38
|
+
# ... is this useful or is it a big ol' booger?
|
39
|
+
#
|
40
|
+
# @param [Symbol] name registered adapter name
|
41
|
+
# @param [Type] &block configuration for adapter
|
42
|
+
# @return [~Yodeler::Adapters::Base] the adapter
|
43
|
+
def adapter(name ,&block)
|
44
|
+
endpoint() if @endpoints.empty?
|
45
|
+
default_endpoint.use(name, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set a gauge
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# client.gauge('users.count', 20_000_000)
|
52
|
+
# client.gauge('users.count', 20_000_000, { tags: %w(something) })
|
53
|
+
#
|
54
|
+
# @param [~String] name of the metric
|
55
|
+
# @param [~Fixnum] value of the metric
|
56
|
+
# @param [Hash] opts={} Examples {#format_options}
|
57
|
+
# @return [Yodeler::Metric, nil] the dispatched metric, nil if not sampled
|
58
|
+
def gauge(name, value, opts={})
|
59
|
+
dispatch(:gauge, name, value, opts)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Increment a counter
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# client.increment 'user.signup'
|
66
|
+
# client.increment 'user.signup', {}
|
67
|
+
# client.increment 'user.signup', 1, {}
|
68
|
+
#
|
69
|
+
# @param [~String] name of the metric
|
70
|
+
# @param [~Fixnum] value=1 of the metric
|
71
|
+
# @param [Hash] opts={} Examples {#format_options}
|
72
|
+
# @return [Yodeler::Metric, nil] the dispatched metric, nil if not sampled
|
73
|
+
def increment(name, value=1, opts={})
|
74
|
+
if value.kind_of?(Hash)
|
75
|
+
opts = value
|
76
|
+
value = 1
|
77
|
+
end
|
78
|
+
dispatch(:increment, name, value, opts)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Measure how long something takes
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# client.timing 'eat.sandwich', 250
|
85
|
+
# client.timing('eat.pizza') do
|
86
|
+
# user.eat(pizza) #=> THAT WAS QUICK FATSO!
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# @param [~String] name of the metric
|
90
|
+
# @param [~Fixnum] value time in ms
|
91
|
+
# @param [Hash] opts={} Examples {#format_options}
|
92
|
+
# @return [Yodeler::Metric, nil, Object]
|
93
|
+
# the dispatched metric, nil if not sampled
|
94
|
+
# if a block is given the result of the block is returned
|
95
|
+
def timing(name, value=nil, opts={})
|
96
|
+
if value.kind_of?(Hash)
|
97
|
+
opts = value
|
98
|
+
value = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
_retval = nil
|
102
|
+
|
103
|
+
if block_given?
|
104
|
+
start = Time.now
|
105
|
+
_retval = yield
|
106
|
+
value = Time.now - start
|
107
|
+
end
|
108
|
+
|
109
|
+
metric = dispatch(:timing, name, value, opts)
|
110
|
+
_retval || metric
|
111
|
+
end
|
112
|
+
|
113
|
+
# Publish an event
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# client.publish('item.sold', purchase.to_json)
|
117
|
+
# client.publish('user.sign_up', {name: user.name, avatar: user.image_url})
|
118
|
+
#
|
119
|
+
# @param [~String] name of the metric
|
120
|
+
# @param [~Hash] value of the metric
|
121
|
+
# @param [Hash] opts={} Examples {#format_options}
|
122
|
+
# @return [Yodeler::Metric, nil] the dispatched metric, nil if not sampled
|
123
|
+
def publish(name, payload, opts={})
|
124
|
+
dispatch(:event, name, payload, opts)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Formats/Defaults metric options
|
128
|
+
#
|
129
|
+
# @param [Hash] opts metric options
|
130
|
+
# @option opts [Array<String,Symbol>, String, Symbol] :tags ([]) array of tags to apply to metric/event
|
131
|
+
# @option opts [Float] :sample_rate (1.0) The sample rate to use
|
132
|
+
# @option opts [Array<Symbol>, Symbol] :to array of endpoint names to send the metric to. If not set will send to {Yodeler::Client#default_endpoint_name}
|
133
|
+
# @return [Hash] formatted, defaulted options
|
134
|
+
def format_options(opts)
|
135
|
+
endpoint_names = opts.delete(:to) || [default_endpoint_name]
|
136
|
+
tags = opts.delete(:tags)
|
137
|
+
prefix = opts.delete(:prefix) || default_prefix
|
138
|
+
|
139
|
+
{
|
140
|
+
prefix: prefix,
|
141
|
+
to: [endpoint_names].flatten.compact,
|
142
|
+
sample_rate: opts.delete(:sample_rate) || default_sample_rate,
|
143
|
+
tags: [tags].flatten.compact,
|
144
|
+
hostname: @hostname
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def dispatch(type, name, value, opts)
|
151
|
+
opts = format_options(opts)
|
152
|
+
destinations = opts.delete(:to)
|
153
|
+
metric = Metric.new(type, name, value, opts)
|
154
|
+
|
155
|
+
return nil unless metric.sample?
|
156
|
+
|
157
|
+
destinations.each do |endpoint_name|
|
158
|
+
if @endpoints[endpoint_name]
|
159
|
+
@endpoints[endpoint_name].adapter.dispatch(metric)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
metric
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|