strumbar 0.0.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.
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