yodeler 0.0.10 → 0.1.1
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/.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
|
+

|
8
|
+
[](https://codeclimate.com/github/coryodaniel/yodeler/coverage)
|
9
|
+
[](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
|