stats_whisper 0.2.2.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 +7 -0
- data/.gitignore +16 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +84 -0
- data/Rakefile +2 -0
- data/lib/stats_whisper/backend/logger.rb +21 -0
- data/lib/stats_whisper/backend/statsd.rb +23 -0
- data/lib/stats_whisper/caller.rb +31 -0
- data/lib/stats_whisper/config.rb +29 -0
- data/lib/stats_whisper/environment.rb +30 -0
- data/lib/stats_whisper/middleware.rb +24 -0
- data/lib/stats_whisper/parser.rb +17 -0
- data/lib/stats_whisper/railtie.rb +14 -0
- data/lib/stats_whisper/version.rb +3 -0
- data/lib/stats_whisper.rb +18 -0
- data/spec/fixtures/config/whisper_config.yml +7 -0
- data/spec/integration/caller_spec.rb +42 -0
- data/spec/integration/config_spec.rb +23 -0
- data/spec/integration/statsd_helper.rb +8 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/unit/caller_spec.rb +31 -0
- data/spec/unit/config_spec.rb +80 -0
- data/spec/unit/environment_spec.rb +61 -0
- data/spec/unit/parser_spec.rb +40 -0
- data/stats_whisper.gemspec +26 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 87d40c243254727859766e1abf0e291891a7c967
|
4
|
+
data.tar.gz: 90af9b8d376f74ab09382f6408164c390cc7b44f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0603ade301144914f6cc028806715da291c0c2323d260baf900c2eae1dd2eed51e751e6185a2a68e0b4baa0eff1c88a8613dae2332653953046fda8e4a929c0e
|
7
|
+
data.tar.gz: e932f04a9484fbad367e19c7ce0375ac6a811bec72ceead2693f314363cd3b545f984293ac56405188e638cc0209b72dfbb0b97d52f7bc861972487382b4d88b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
stats_whisper
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Michal Pietrus
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# StatsWhisper
|
2
|
+
|
3
|
+
Short and simple piece of code to deal with stats gathering. It integrates Rails apps with StatsD and measures two fundamental values:
|
4
|
+
|
5
|
+
* Time of request execution (in ms) – each request is distinguished by its path, e.g: `/foo/bar` and `/bar/baz` are considered differently. It uses StatsD [time][1] metric type.
|
6
|
+
* Count of visits – a natural number of processed requests for the whole app. Basically it uses StatsD [counter][2] type.
|
7
|
+
|
8
|
+
As StatsD is mainly a network daemon to aggregate and send metrics, some another tool is needed for further processing or visualization, e.g. [Graphite][3].
|
9
|
+
|
10
|
+
Request paths are translated into Graphite metric pattern, e.g: `/foo/bar` becomes `app_name.foo.bar`. Moreover, for some particular paths replace operation is being done:
|
11
|
+
|
12
|
+
* `/en/foo/bar` => `app_name.foo.bar`;
|
13
|
+
* `/en` => `app_name.home_page`
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'stats_whisper'
|
21
|
+
```
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
$ gem install stats_whisper
|
30
|
+
|
31
|
+
## Configuration
|
32
|
+
|
33
|
+
This library comes with Rails initializer and is ready to use once added to Gemfile app stack. It distinguishes Rails environments and for development environment Rails logger is used. All remaining use StatsD and it is possible to define StatsD location with these environment variables:
|
34
|
+
|
35
|
+
* `STATSWHISPER_HOST` – contains hostname where StatsD is listening;
|
36
|
+
* `STATSWHISPER_PORT` – contains StatsD port .
|
37
|
+
|
38
|
+
You can use here [dotenv][4] gem.
|
39
|
+
|
40
|
+
|
41
|
+
### Request paths filtering
|
42
|
+
|
43
|
+
By default StatsWhisper listens for any request path and allows all of them to pass. It causes that all request paths are passed to Graphite, which may not be expected bahaviour, because one would be interested only in certain paths, hence it is possible to provide a whitelist to filter "garbage".
|
44
|
+
|
45
|
+
Whitelist is an array of regexp patterns provided in config file:
|
46
|
+
```
|
47
|
+
# Rails.root/config/whisper_config.yml
|
48
|
+
|
49
|
+
---
|
50
|
+
whitelist:
|
51
|
+
- ^/dashboard
|
52
|
+
- /(pl|en)/main
|
53
|
+
```
|
54
|
+
|
55
|
+
Then, these patterns are matched against current request path. If path matches, it is passed to StatsD. The whitelist applies only to timers so all requests are counted, even though they don't match.
|
56
|
+
|
57
|
+
### Adding app name
|
58
|
+
|
59
|
+
To add app name to the metric path, add `app_name` to config file, e.g:
|
60
|
+
|
61
|
+
```
|
62
|
+
# Rails.root/config/whisper_config.yml
|
63
|
+
|
64
|
+
---
|
65
|
+
app_name: cool_app
|
66
|
+
```
|
67
|
+
|
68
|
+
|
69
|
+
## TODO
|
70
|
+
|
71
|
+
* Add configurable parser rules, letting the user to define patterns to translate request paths into [Graphite][3] format.
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
1. Fork it ( https://github.com/[my-github-username]/stats_whisper/fork )
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create a new Pull Request
|
80
|
+
|
81
|
+
[1]: https://github.com/etsy/statsd/blob/master/docs/metric_types.md#timing
|
82
|
+
[2]: https://github.com/etsy/statsd/blob/master/docs/metric_types.md#counting
|
83
|
+
[3]: http://graphite.readthedocs.org/en/latest/overview.html
|
84
|
+
[4]: https://github.com/bkeepers/dotenv
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module StatsWhisper::Backend
|
2
|
+
|
3
|
+
class Logger
|
4
|
+
|
5
|
+
attr_accessor :logger
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@logger = StatsWhisper.logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def timing(path, timestamp)
|
12
|
+
collect_metric("#{path}:#{timestamp}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def collect_metric(metric)
|
16
|
+
StatsWhisper.logger.info "[StatsWhisper] #{metric}"
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :increment, :collect_metric
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'statsd-ruby'
|
2
|
+
|
3
|
+
module StatsWhisper::Backend
|
4
|
+
|
5
|
+
class StatsD
|
6
|
+
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@statsd, :increment, :timing
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@statsd = Statsd.new(hostname, port)
|
13
|
+
end
|
14
|
+
|
15
|
+
def hostname
|
16
|
+
ENV['STATSWHISPER_HOST'] || 'localhost'
|
17
|
+
end
|
18
|
+
|
19
|
+
def port
|
20
|
+
ENV['STATSWHISPER_PORT'] || 8125
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "environment"
|
2
|
+
require_relative "parser"
|
3
|
+
require_relative "config"
|
4
|
+
|
5
|
+
module StatsWhisper
|
6
|
+
|
7
|
+
module Caller
|
8
|
+
|
9
|
+
include Parser
|
10
|
+
include Config
|
11
|
+
|
12
|
+
def gather_stats(env, response_time)
|
13
|
+
|
14
|
+
if timing_allowed?(env["REQUEST_PATH"])
|
15
|
+
StatsWhisper.backend.timing(build_key(app_name, 'http', env["REQUEST_METHOD"],
|
16
|
+
parse(env["REQUEST_PATH"]),
|
17
|
+
'response_time'),
|
18
|
+
response_time)
|
19
|
+
end
|
20
|
+
StatsWhisper.backend.increment(build_key(app_name, 'http', 'visits'))
|
21
|
+
end
|
22
|
+
|
23
|
+
def timing_allowed?(request_path)
|
24
|
+
whitelist.empty? || whitelist.any? do |pattern|
|
25
|
+
Regexp.new(pattern) =~ request_path
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module StatsWhisper
|
4
|
+
module Config
|
5
|
+
|
6
|
+
def config
|
7
|
+
@config ||= load_config
|
8
|
+
end
|
9
|
+
|
10
|
+
def whitelist
|
11
|
+
config['whitelist'] || []
|
12
|
+
end
|
13
|
+
|
14
|
+
def app_name
|
15
|
+
config['app_name'] || 'foo'
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def load_config
|
21
|
+
begin
|
22
|
+
YAML.load(ERB.new(File.new(Rails.root.join("config", "whisper_config.yml")).read).result)
|
23
|
+
rescue Errno::ENOENT
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'config'
|
2
|
+
|
3
|
+
require_relative 'backend/logger'
|
4
|
+
require_relative 'backend/statsd'
|
5
|
+
|
6
|
+
|
7
|
+
module StatsWhisper
|
8
|
+
module Environment
|
9
|
+
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def backend
|
13
|
+
case environment
|
14
|
+
when 'production', 'staging', 'test'
|
15
|
+
Backend::StatsD.new
|
16
|
+
else
|
17
|
+
Backend::Logger.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def environment
|
22
|
+
if defined?(Rails)
|
23
|
+
Rails.env
|
24
|
+
else
|
25
|
+
ENV['RAILS_ENV'] || 'development'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'caller'
|
2
|
+
|
3
|
+
module StatsWhisper
|
4
|
+
class Middleware
|
5
|
+
|
6
|
+
include Caller
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
(status, headers, body), response_time = call_with_timing(env)
|
14
|
+
gather_stats(env, response_time)
|
15
|
+
[status, headers, body]
|
16
|
+
end
|
17
|
+
|
18
|
+
def call_with_timing(env)
|
19
|
+
start = Time.now
|
20
|
+
result = @app.call(env)
|
21
|
+
[result, ((Time.now - start) * 1000).round]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module StatsWhisper::Parser
|
2
|
+
|
3
|
+
def parse(path)
|
4
|
+
path = path.gsub(/\/(pl|en|(\d){4}\-(\d){4})/) do
|
5
|
+
if $'.empty?
|
6
|
+
'/'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
path.slice!(0) if path =~ /\/.+/
|
10
|
+
path.sub(/^\/$/, "home_page").gsub('/', '.')
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_key(*args)
|
14
|
+
args.join(".")
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "stats_whisper/middleware"
|
2
|
+
|
3
|
+
module StatsWhisper
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
|
6
|
+
initializer 'statsd-instrument.use_rails_logger' do
|
7
|
+
::StatsWhisper.logger = Rails.logger
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer "stats_whisper.insert_middleware" do |app|
|
11
|
+
app.config.middleware.use "StatsWhisper::Middleware"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "stats_whisper/version"
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
|
5
|
+
require 'stats_whisper/railtie' if defined?(Rails)
|
6
|
+
|
7
|
+
module StatsWhisper
|
8
|
+
extend self
|
9
|
+
|
10
|
+
attr_accessor :logger
|
11
|
+
attr_writer :backend
|
12
|
+
|
13
|
+
def backend
|
14
|
+
@backend ||= StatsWhisper::Environment.backend
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
StatsWhisper.logger = Logger.new($stderr)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stats_whisper/caller'
|
3
|
+
require_relative 'statsd_helper'
|
4
|
+
|
5
|
+
describe StatsWhisper::Caller do
|
6
|
+
subject { Class.new { extend StatsWhisper::Caller } }
|
7
|
+
|
8
|
+
before do
|
9
|
+
Rails = double(:root => Pathname.new("spec/fixtures"))
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
Object.send(:remove_const, :Rails)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#gather_stats" do
|
17
|
+
before do
|
18
|
+
allow(Rails).to receive(:env).and_return("production")
|
19
|
+
|
20
|
+
StatsWhisper.backend = StatsD.new
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it "adds timing stats" do
|
25
|
+
subject.gather_stats({'REQUEST_PATH' => '/en/main',
|
26
|
+
'REQUEST_METHOD' => 'GET'}, 234)
|
27
|
+
expect(StatsWhisper.backend.timing_key).to eq('bar.http.GET.main.response_time')
|
28
|
+
expect(StatsWhisper.backend.increment_key).to eq('bar.http.visits')
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#timing_allowed?" do
|
35
|
+
|
36
|
+
context "when whitelist is given" do
|
37
|
+
it "allows only certain paths" do
|
38
|
+
expect(subject.timing_allowed?("/en/main")).to eq(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stats_whisper/config'
|
3
|
+
|
4
|
+
describe StatsWhisper::Config do
|
5
|
+
subject { Class.new { extend StatsWhisper::Config } }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Rails = double(:root => Pathname.new("spec/fixtures"))
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
Object.send(:remove_const, :Rails)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#app_name" do
|
16
|
+
|
17
|
+
context "when config file is given" do
|
18
|
+
it "returns specified app name" do
|
19
|
+
expect(subject.app_name).to eq('bar')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'stats_whisper'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.expect_with :rspec do |expectations|
|
6
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
7
|
+
end
|
8
|
+
|
9
|
+
config.mock_with :rspec do |mocks|
|
10
|
+
mocks.verify_partial_doubles = true
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stats_whisper/caller'
|
3
|
+
|
4
|
+
describe StatsWhisper::Caller do
|
5
|
+
let(:ctxt) { Class.new { extend StatsWhisper::Caller } }
|
6
|
+
|
7
|
+
describe "#timing_allowed?" do
|
8
|
+
|
9
|
+
context "when whitelist is empty" do
|
10
|
+
it "allows to receive any path" do
|
11
|
+
allow(ctxt).to receive(:whitelist).and_return([])
|
12
|
+
expect(ctxt.timing_allowed?("/bleh/blah/ok")).to eq(true)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when whitelist is not empty" do
|
17
|
+
before do
|
18
|
+
allow(ctxt).to receive(:whitelist).and_return(["/home.*"])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "allows only certain paths" do
|
22
|
+
expect(ctxt.timing_allowed?("/home/page")).to eq(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "rejects not allowed paths" do
|
26
|
+
expect(ctxt.timing_allowed?("/dashboard")).to eq(false)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stats_whisper/config'
|
3
|
+
|
4
|
+
describe StatsWhisper::Config do
|
5
|
+
let(:ctxt) { Class.new { extend StatsWhisper::Config } }
|
6
|
+
|
7
|
+
describe "#whitelist" do
|
8
|
+
|
9
|
+
context "when whitelist in config is empty" do
|
10
|
+
before do
|
11
|
+
allow(ctxt).to receive(:config).and_return({})
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns an empty array" do
|
15
|
+
expect(ctxt.whitelist).to eq([])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when whitelist in config is not empty" do
|
20
|
+
before do
|
21
|
+
allow(ctxt).to receive(:config).and_return({'whitelist' => ['ok!']})
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns non-empty array" do
|
25
|
+
expect(ctxt.whitelist).not_to be_empty
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#app_name" do
|
31
|
+
context "when app_name in config is empty" do
|
32
|
+
before do
|
33
|
+
allow(ctxt).to receive(:config).and_return({})
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns default value" do
|
37
|
+
expect(ctxt.app_name).to eq('foo')
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when env variable is undefined" do
|
43
|
+
before do
|
44
|
+
allow(ctxt).to receive(:config).and_return({'app_name' => "cool_app"})
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns provided app name" do
|
48
|
+
expect(ctxt.app_name).to eq('cool_app')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#config" do
|
54
|
+
before do
|
55
|
+
Rails = double(:root => Pathname.new(fixtures_path))
|
56
|
+
end
|
57
|
+
|
58
|
+
after do
|
59
|
+
Object.send(:remove_const, :Rails)
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when config file is not present" do
|
63
|
+
let(:fixtures_path) { "spec/non_existing_fixtures" }
|
64
|
+
|
65
|
+
|
66
|
+
it "returns empty hash" do
|
67
|
+
expect(ctxt.config).to eq({})
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when config file is present" do
|
72
|
+
let(:fixtures_path) { "spec/fixtures" }
|
73
|
+
|
74
|
+
|
75
|
+
it "returns non empty hash" do
|
76
|
+
expect(ctxt.config).not_to be_empty
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stats_whisper/environment'
|
3
|
+
|
4
|
+
describe StatsWhisper::Environment do
|
5
|
+
let(:ctxt) { Class.new { extend StatsWhisper::Environment } }
|
6
|
+
|
7
|
+
|
8
|
+
describe "#backend" do
|
9
|
+
|
10
|
+
%w(production staging test).each do |env|
|
11
|
+
context "when environment is #{env}" do
|
12
|
+
before do
|
13
|
+
allow(ctxt).to receive(:environment).and_return(env)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns statsd backend' do
|
17
|
+
expect(ctxt.backend).to be_kind_of(StatsWhisper::Backend::StatsD)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when environment is some_cool_env" do
|
23
|
+
before do
|
24
|
+
allow(ctxt).to receive(:environment).and_return('some_cool_env')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns logger backend' do
|
28
|
+
expect(ctxt.backend).to be_kind_of(StatsWhisper::Backend::Logger)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#environment" do
|
34
|
+
|
35
|
+
context 'when Rails defined' do
|
36
|
+
before do
|
37
|
+
Rails = double(:env => 'test')
|
38
|
+
end
|
39
|
+
|
40
|
+
after do
|
41
|
+
Object.send(:remove_const, :Rails)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "reads env from Rails" do
|
45
|
+
expect(ctxt.environment).to eq('test')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when Rails undefined' do
|
50
|
+
|
51
|
+
it "reads env from ENV" do
|
52
|
+
allow(ENV).to receive(:[]).with("RAILS_ENV").and_return("test")
|
53
|
+
expect(ctxt.environment).to eq('test')
|
54
|
+
end
|
55
|
+
|
56
|
+
it "sets development if ENV is empty" do
|
57
|
+
expect(ctxt.environment).to eq('development')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stats_whisper/parser'
|
3
|
+
|
4
|
+
describe StatsWhisper::Parser do
|
5
|
+
let(:ctxt) { Class.new { extend StatsWhisper::Parser } }
|
6
|
+
|
7
|
+
describe "#parse" do
|
8
|
+
|
9
|
+
|
10
|
+
context "when req path is empty" do
|
11
|
+
it "resolves base uri" do
|
12
|
+
path = "/"
|
13
|
+
expect(ctxt.parse(path)).to eq("home_page")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when req path is root path" do
|
18
|
+
it "resolves root path" do
|
19
|
+
path = "/en"
|
20
|
+
expect(ctxt.parse(path)).to eq("home_page")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when req path points to a resource" do
|
25
|
+
it "resolves resource path" do
|
26
|
+
path = "/en/dashboard"
|
27
|
+
expect(ctxt.parse(path)).to eq("dashboard")
|
28
|
+
|
29
|
+
path = "/2015-2016/pl/treasuries/academy_units/offer"
|
30
|
+
expect(ctxt.parse(path)).to eq("treasuries.academy_units.offer")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#build_key" do
|
36
|
+
it "generates valid Graphite key" do
|
37
|
+
expect(ctxt.build_key("bleh", 'blah', "dash")).to eq("bleh.blah.dash")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'stats_whisper/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "stats_whisper"
|
8
|
+
spec.version = StatsWhisper::VERSION
|
9
|
+
spec.authors = ["Michal Pietrus"]
|
10
|
+
spec.email = ["blelump@martex.nom.pl"]
|
11
|
+
spec.summary = %q{A simple middleware to gather metrics and interact with StatsD.}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = "https://github.com/Opensoftware/stats_whisper"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", " ~> 3.3"
|
24
|
+
|
25
|
+
spec.add_dependency "statsd-ruby", "~> 1.2"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stats_whisper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michal Pietrus
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: statsd-ruby
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.2'
|
69
|
+
description: A simple middleware to gather metrics and interact with StatsD.
|
70
|
+
email:
|
71
|
+
- blelump@martex.nom.pl
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".ruby-gemset"
|
79
|
+
- ".ruby-version"
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- lib/stats_whisper.rb
|
85
|
+
- lib/stats_whisper/backend/logger.rb
|
86
|
+
- lib/stats_whisper/backend/statsd.rb
|
87
|
+
- lib/stats_whisper/caller.rb
|
88
|
+
- lib/stats_whisper/config.rb
|
89
|
+
- lib/stats_whisper/environment.rb
|
90
|
+
- lib/stats_whisper/middleware.rb
|
91
|
+
- lib/stats_whisper/parser.rb
|
92
|
+
- lib/stats_whisper/railtie.rb
|
93
|
+
- lib/stats_whisper/version.rb
|
94
|
+
- spec/fixtures/config/whisper_config.yml
|
95
|
+
- spec/integration/caller_spec.rb
|
96
|
+
- spec/integration/config_spec.rb
|
97
|
+
- spec/integration/statsd_helper.rb
|
98
|
+
- spec/spec_helper.rb
|
99
|
+
- spec/unit/caller_spec.rb
|
100
|
+
- spec/unit/config_spec.rb
|
101
|
+
- spec/unit/environment_spec.rb
|
102
|
+
- spec/unit/parser_spec.rb
|
103
|
+
- stats_whisper.gemspec
|
104
|
+
homepage: https://github.com/Opensoftware/stats_whisper
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.4.3
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: A simple middleware to gather metrics and interact with StatsD.
|
128
|
+
test_files:
|
129
|
+
- spec/fixtures/config/whisper_config.yml
|
130
|
+
- spec/integration/caller_spec.rb
|
131
|
+
- spec/integration/config_spec.rb
|
132
|
+
- spec/integration/statsd_helper.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
- spec/unit/caller_spec.rb
|
135
|
+
- spec/unit/config_spec.rb
|
136
|
+
- spec/unit/environment_spec.rb
|
137
|
+
- spec/unit/parser_spec.rb
|