strumbar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ notifications:
5
+ email:
6
+ recipients:
7
+ - anordman@majorleaguegaming.com
8
+ - mwilson@majorleaguegaming.com
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in strumbar.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Andrew Nordman
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,74 @@
1
+ # Strumbar [![Build Status](https://secure.travis-ci.org/agoragames/strumbar.png)](http://travis-ci.org/agoragames/strumbar)
2
+
3
+ Strumbar is a wrapper around ActiveSupport::Notifications with preconfigurations
4
+ for basic instrumentation to be sent to statsd.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'strumbar'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install strumbar
19
+
20
+ ## Usage
21
+
22
+
23
+ Configuration:
24
+
25
+ ``` ruby
26
+ Strumbar.configure do |config|
27
+ config.port = 80
28
+ config.host = 'instrument.majorleaguegaming.com'
29
+ config.application = 'instrument'
30
+ end
31
+ ```
32
+
33
+ Adding this alone causes basic instrumentation data to be sent to the Statsd
34
+ server broken down by your application and will be visible in the dashboard.
35
+ If you are happy with that, you're done. Adding custom instrumentation that is
36
+ specific to your application is incredibly simple. Strumbar is a wrapper around
37
+ ActiveSupport::Notifications.
38
+
39
+ ``` ruby
40
+ Strumbar.subscribe /something_cool/ do |client, event|
41
+ client.increment 'something_cool_counter'
42
+ end
43
+ ```
44
+
45
+ Client is an instance of `Strumbar::Client` and wraps around Statsd::Client for
46
+ namespacing and syntactic sugar.
47
+
48
+ By default, it will subscribe to runtime data for `process_action.action_controller`
49
+ and the sql load time in `sql.active_record`.
50
+
51
+ In case you get tired of typing `ActiveSupport::Notifications.instrument` you can use the helpful sugar `Strumbar` provides:
52
+
53
+ ```ruby
54
+ Strumbar.strum 'view.render', payload do
55
+ render :text => "I'm monitored!"
56
+ end
57
+ ```
58
+
59
+
60
+ ## Default Instruments
61
+
62
+ Strumbar takes the approach of auto-detecting the libraries being used and
63
+ loading default instrumentation subscriptions. Currently, this list includes:
64
+
65
+ - ActionController
66
+ - ActiveRecord
67
+ - Redis
68
+
69
+ More default instrumentation defaults will be added.
70
+
71
+ ## Authors
72
+
73
+ Written by [Andrew Nordman](https://github.com/cadwallion) and [Matthew Wilson](https://github.com/hypomodern)
74
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = 'spec/**/*_spec.rb'
8
+ spec.rspec_opts = ['--backtrace']
9
+ # spec.ruby_opts = ['-w']
10
+ end
11
+
12
+ task :default => :spec
13
+ task :test => :spec
@@ -0,0 +1,22 @@
1
+ require 'statsd'
2
+
3
+ module Strumbar
4
+ class Client < ::Statsd::Client
5
+ def initialize host, port
6
+ @host = host
7
+ @port = port
8
+ end
9
+
10
+ def timing stat, time, sample_rate = 1
11
+ super "#{Strumbar.application}.#{stat}", time, sample_rate
12
+ end
13
+
14
+ def increment stat, sample_rate = 1
15
+ super "#{Strumbar.application}.#{stat}", sample_rate
16
+ end
17
+
18
+ def decrement stat, sample_rate = 1
19
+ super "##{Strumbar.application}.#{stat}", sample_rate
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ module Strumbar
2
+ class Configuration
3
+ attr_accessor :port, :host, :application
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ module Strumbar
2
+ module Instrumentation
3
+ module ActionController
4
+ def self.load
5
+ Strumbar.subscribe /process_action.action_controller/ do |client, event|
6
+ key = "#{event.payload[:controller]}.#{event.payload[:action]}"
7
+
8
+ client.timing "#{key}.total_time", event.duration
9
+ client.timing "#{key}.view_time", event.payload[:view_runtime]
10
+ client.timing "#{key}.db_time", event.payload[:db_runtime]
11
+
12
+ client.increment "#{key}.status.#{event.payload[:status]}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module Strumbar
2
+ module Instrumentation
3
+ module ActiveRecord
4
+ def self.load
5
+ Strumbar.subscribe /sql.active_record/ do |client, event|
6
+ client.timing 'query_log', event.duration
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ module Strumbar
2
+ module Instrumentation
3
+ module Redis
4
+ def self.load
5
+ Strumbar.subscribe 'query.redis' do |client, event|
6
+ client.increment 'query.redis'
7
+ client.increment 'failure.redis' if event.payload[:failure]
8
+
9
+ client.timing "#{event.payload[:command]}.redis", event.duration
10
+ end
11
+
12
+ unless ::Redis::Client.instance_methods.include? :call_with_instrumentation
13
+ ::Redis::Client.class_eval do
14
+ def call_with_instrumentation command, &block
15
+ Strumbar.strum 'query.redis', command: command do |payload|
16
+ call_without_instrumentation command, &block
17
+ begin
18
+ reply = call_without_instrumentation command, &block
19
+ payload[:failure] = false
20
+ rescue CommandError
21
+ payload[:failure] = true
22
+ raise
23
+ end
24
+
25
+ reply
26
+ end
27
+ end
28
+
29
+ alias_method :call_without_instrumentation, :call
30
+ alias_method :call, :call_with_instrumentation
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Strumbar
2
+ module Instrumentation
3
+ autoload :Redis, 'strumbar/instrumentation/redis'
4
+ autoload :ActionController, 'strumbar/instrumentation/action_controller'
5
+ autoload :ActiveRecord, 'strumbar/instrumentation/active_record'
6
+
7
+ def self.load
8
+ Strumbar::Instrumentation::ActionController.load if defined? ::ActionController
9
+ Strumbar::Instrumentation::ActiveRecord.load if defined? ::ActiveRecord
10
+ Strumbar::Instrumentation::Redis.load if defined? ::Redis
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Strumbar
2
+ VERSION = "0.0.1"
3
+ end
data/lib/strumbar.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'strumbar/version'
2
+ require 'strumbar/configuration'
3
+ require 'strumbar/client'
4
+ require 'strumbar/instrumentation'
5
+
6
+ require 'active_support'
7
+ require 'active_support/core_ext/object/try'
8
+
9
+ module Strumbar
10
+ class << self
11
+ attr_reader :configuration
12
+
13
+ def configure
14
+ @configuration = Configuration.new
15
+ yield @configuration
16
+ Instrumentation.load
17
+ end
18
+
19
+ def client
20
+ @client ||= Client.new host, port
21
+ end
22
+
23
+ def host
24
+ configuration.try(:host) || 'localhost'
25
+ end
26
+
27
+ def port
28
+ configuration.try(:port) || 8125
29
+ end
30
+
31
+ def application
32
+ configuration.try(:application) || 'my_awesome_app'
33
+ end
34
+
35
+ def subscribe identifier
36
+ ActiveSupport::Notifications.subscribe identifier do |*args|
37
+ event = ActiveSupport::Notifications::Event.new(*args)
38
+ yield client, event
39
+ end
40
+ end
41
+
42
+ def strum event, payload, &block
43
+ ActiveSupport::Notifications.instrument event, payload, &block
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Strumbar::Instrumentation::Redis do
4
+ before do
5
+ class Redis
6
+ class Client
7
+ def call command, &block
8
+
9
+ end
10
+
11
+ def validate
12
+ true
13
+ end
14
+ end
15
+ end
16
+ Strumbar::Instrumentation::Redis.load
17
+ end
18
+
19
+ after do
20
+ ActiveSupport::Notifications.unsubscribe('query.redis')
21
+ Object.send :remove_const, :Redis
22
+ end
23
+
24
+ it 'adds a wrapper around Redis#call to instrument redis calls' do
25
+ Strumbar.should_receive(:strum).with('query.redis', { command: 'SET' })
26
+ Redis::Client.new.call 'SET'
27
+ end
28
+
29
+ it 'subscribes to query.redis notifications' do
30
+ Strumbar.client.should_receive(:increment).with('query.redis')
31
+ Strumbar.strum 'query.redis', {}
32
+ end
33
+
34
+ it 'passes blocks in #call accordingly' do
35
+ client = Redis::Client.new
36
+ client.call 'foo'
37
+ end
38
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Strumbar::Instrumentation do
4
+ describe '#load' do
5
+ def undefine klass
6
+ Object.send :remove_const, klass
7
+ end
8
+
9
+ it 'loads the ActionController subscription if ActionController is defined' do
10
+
11
+ ActionController = true
12
+
13
+ Strumbar::Instrumentation::ActionController.should_receive :load
14
+ Strumbar::Instrumentation.load
15
+
16
+ undefine :ActionController
17
+ end
18
+
19
+ it 'does not load ActionController subscription if not defined' do
20
+ Strumbar::Instrumentation::ActionController.should_not_receive :load
21
+ Strumbar::Instrumentation.load
22
+ end
23
+
24
+ it 'loads the ActiveRecord subscription if ActiveRecord is loaded' do
25
+ ActiveRecord = true
26
+
27
+ Strumbar::Instrumentation::ActiveRecord.should_receive :load
28
+ Strumbar::Instrumentation.load
29
+
30
+ undefine :ActiveRecord
31
+ end
32
+
33
+ it 'does not load ActiveRecord subscription if not defined' do
34
+ Strumbar::Instrumentation::ActiveRecord.should_not_receive :load
35
+ Strumbar::Instrumentation.load
36
+ end
37
+
38
+ it 'loads the Redis subscription if Redis is defined' do
39
+ class Redis
40
+ class Client
41
+ def process ; end
42
+ end
43
+ end
44
+
45
+ Strumbar::Instrumentation::Redis.should_receive :load
46
+ Strumbar::Instrumentation.load
47
+
48
+ undefine :Redis
49
+ end
50
+
51
+ it 'does not load Redis subscription if not defined' do
52
+ Strumbar::Instrumentation::Redis.should_not_receive :load
53
+ Strumbar::Instrumentation.load
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'strumbar'
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe Strumbar do
4
+ it 'loads' do
5
+ true
6
+ end
7
+
8
+ after do
9
+ Strumbar.instance_variable_set(:@configuration, nil)
10
+ end
11
+
12
+ describe '#client' do
13
+ after do
14
+ Strumbar.instance_variable_set(:@client, nil)
15
+ end
16
+
17
+ it { Strumbar.client.should be_a_kind_of Strumbar::Client }
18
+
19
+ it 'defaults host to localhost' do
20
+ Strumbar.client.host.should == 'localhost'
21
+ end
22
+
23
+ it 'defaults port to 8125' do
24
+ Strumbar.client.port.should == 8125
25
+ end
26
+
27
+ it 'uses the Strumbar configuration if configuration is present' do
28
+ Strumbar.configure do |config|
29
+ config.port = 12345
30
+ config.host = '127.0.0.1'
31
+ end
32
+
33
+ Strumbar.client.port.should == 12345
34
+ Strumbar.client.host.should == '127.0.0.1'
35
+ end
36
+ end
37
+
38
+ describe '#configure' do
39
+ it 'yields a Configuration object' do
40
+ Strumbar.configure do |config|
41
+ config.should be_a_kind_of Strumbar::Configuration
42
+ end
43
+ end
44
+
45
+ it 'loads relevant Instrumentation' do
46
+ Strumbar::Instrumentation.should_receive(:load)
47
+ Strumbar.configure { |c| }
48
+ end
49
+
50
+ it 'assigns the configuration object to Strumbar' do
51
+ @config_object = nil
52
+ Strumbar.configure do |config|
53
+ config.port = 12345
54
+ config.host = '127.0.0.1'
55
+ @config_object = config
56
+ end
57
+
58
+ Strumbar.configuration.should == @config_object
59
+ end
60
+ end
61
+
62
+ describe "#application" do
63
+ it "returns the configured value" do
64
+ Strumbar.configure { |c| c.application = "foobar" }
65
+ Strumbar.application.should == "foobar"
66
+ end
67
+ it "defaults to something comically bad so you'll change it" do
68
+ Strumbar.application.should == "my_awesome_app"
69
+ end
70
+ end
71
+
72
+ describe "#host" do
73
+ it "returns the configured value" do
74
+ Strumbar.configure { |c| c.host = "statsd.app" }
75
+ Strumbar.host.should == "statsd.app"
76
+ end
77
+ it "defaults to localhost" do
78
+ Strumbar.host.should == "localhost"
79
+ end
80
+ end
81
+
82
+ describe "#port" do
83
+ it "returns the configured port" do
84
+ Strumbar.configure { |c| c.port = 9999 }
85
+ Strumbar.port.should == 9999
86
+ end
87
+ it "defaults to 8125" do
88
+ Strumbar.port.should == 8125
89
+ end
90
+ end
91
+
92
+ describe '#subscribe' do
93
+ it 'should wrap ActiveSupport::Notifications' do
94
+ ActiveSupport::Notifications.should_receive(:subscribe).with('foo')
95
+ Strumbar.subscribe 'foo'
96
+ end
97
+
98
+ it 'should yield an event and client on instrument call' do
99
+ Strumbar.subscribe 'foo' do |client, event|
100
+ event.should be_a_kind_of ActiveSupport::Notifications::Event
101
+ client.should be_a_kind_of Strumbar::Client
102
+ end
103
+ ActiveSupport::Notifications.instrument 'foo'
104
+ end
105
+ end
106
+
107
+ describe "#strum" do
108
+ it "is syntactic sugar for ActiveSupport::Notifications.instrument" do
109
+ ActiveSupport::Notifications.should_receive(:instrument).with("event_name", { :payload => :yeah })
110
+ Strumbar.strum("event_name", { payload: :yeah })
111
+ end
112
+ it "handles the block correctly and all that jazz" do
113
+ foo = nil
114
+ ActiveSupport::Notifications.should_receive(:instrument).and_yield
115
+ Strumbar.strum("mah.event", {}) do
116
+ foo = 7
117
+ end
118
+ foo.should == 7
119
+ end
120
+ end
121
+ end
data/strumbar.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/strumbar/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Andrew Nordman", "Matthew Wilson"]
6
+ gem.email = ["anordman@majorleaguegaming.com", "mwilson@majorleaguegaming.com"]
7
+ gem.description = %q{An instrumentation utility.}
8
+ gem.summary = %q{Helper library to strum along in your application.}
9
+ gem.homepage = "http://instrument.majorleaguegaming.com"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "strumbar"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Strumbar::VERSION
17
+
18
+ gem.add_dependency 'activesupport'
19
+ gem.add_dependency 'statsd'
20
+
21
+ gem.add_development_dependency 'rspec'
22
+ gem.add_development_dependency 'rake'
23
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: strumbar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrew Nordman
9
+ - Matthew Wilson
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-04-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: &70176768352560 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70176768352560
26
+ - !ruby/object:Gem::Dependency
27
+ name: statsd
28
+ requirement: &70176768351540 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70176768351540
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ requirement: &70176768365400 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *70176768365400
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ requirement: &70176768363780 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *70176768363780
59
+ description: An instrumentation utility.
60
+ email:
61
+ - anordman@majorleaguegaming.com
62
+ - mwilson@majorleaguegaming.com
63
+ executables: []
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - .gitignore
68
+ - .travis.yml
69
+ - Gemfile
70
+ - LICENSE
71
+ - README.md
72
+ - Rakefile
73
+ - lib/strumbar.rb
74
+ - lib/strumbar/client.rb
75
+ - lib/strumbar/configuration.rb
76
+ - lib/strumbar/instrumentation.rb
77
+ - lib/strumbar/instrumentation/action_controller.rb
78
+ - lib/strumbar/instrumentation/active_record.rb
79
+ - lib/strumbar/instrumentation/redis.rb
80
+ - lib/strumbar/version.rb
81
+ - spec/instrumentation/redis_spec.rb
82
+ - spec/instrumentation_spec.rb
83
+ - spec/spec_helper.rb
84
+ - spec/strumbar_spec.rb
85
+ - strumbar.gemspec
86
+ homepage: http://instrument.majorleaguegaming.com
87
+ licenses: []
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ segments:
99
+ - 0
100
+ hash: -4388880023280648677
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ segments:
108
+ - 0
109
+ hash: -4388880023280648677
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 1.8.17
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: Helper library to strum along in your application.
116
+ test_files:
117
+ - spec/instrumentation/redis_spec.rb
118
+ - spec/instrumentation_spec.rb
119
+ - spec/spec_helper.rb
120
+ - spec/strumbar_spec.rb