blamescope 0.0.3
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 +14 -0
- data/.rspec +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +70 -0
- data/Rakefile +5 -0
- data/bin/blamescope +9 -0
- data/blamescope.gemspec +28 -0
- data/lib/blamescope.rb +70 -0
- data/lib/blamescope/middleware.rb +19 -0
- data/lib/blamescope/server.rb +80 -0
- data/lib/blamescope/trackable.rb +64 -0
- data/lib/blamescope/version.rb +3 -0
- data/spec/blamescope/middleware_spec.rb +22 -0
- data/spec/blamescope/server_spec.rb +54 -0
- data/spec/blamescope/trackable_spec.rb +62 -0
- data/spec/blamescope_spec.rb +33 -0
- data/spec/spec_helper.rb +9 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0f0301896ebca21df7ef26fb732142ffe3ad8f3d
|
4
|
+
data.tar.gz: ebbe482c0b14d987baa3e9341eaffdc484c417e8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 387c2232c674bec8635d2cdacedd89f9353b52373f9aeb931c827d6f40962a33d20d949024d31a824c4741f1acd4cd3a9301ad9491eef9b102b4c7f3218ac679
|
7
|
+
data.tar.gz: 623534cec783f7fd61e99786005566e6cf0beadc52b6d1081a0677ff062a43dea2fe2c5abc0c2fb00c66ce2560b682c4f1447fce7736d31899ccf825142d1260
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 vladnik
|
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,70 @@
|
|
1
|
+
# BlameScope
|
2
|
+
|
3
|
+
Track events per user
|
4
|
+
|
5
|
+
[](https://travis-ci.org/Demandbase/blamescope)
|
6
|
+
[](https://codeclimate.com/github/Demandbase/blamescope)
|
7
|
+
[](https://codeclimate.com/github/Demandbase/blamescope)
|
8
|
+
|
9
|
+
### Client mode
|
10
|
+
|
11
|
+
Rails setup
|
12
|
+
|
13
|
+
# config/application.rb
|
14
|
+
config.middleware.use Blamescope::Middleware, rabbit: 'amqp://user:pass@host:port/vhost'
|
15
|
+
|
16
|
+
Rack setup
|
17
|
+
|
18
|
+
# config.ru
|
19
|
+
use Blamescope::Middleware, rabbit: 'amqp://user:pass@host:port/vhost'
|
20
|
+
|
21
|
+
#### Usage
|
22
|
+
|
23
|
+
class User < ActiveRecord::Base
|
24
|
+
include Blamescope
|
25
|
+
|
26
|
+
blame_activerecord # Tracks create, update and delete action
|
27
|
+
def custom_action
|
28
|
+
# Some action
|
29
|
+
end
|
30
|
+
blame_method :custom_action
|
31
|
+
end
|
32
|
+
|
33
|
+
At the current time it adds such methods:
|
34
|
+
* blame_activerecord - track create, update, delete of ActiveRecord model
|
35
|
+
* blame_method - track specific method
|
36
|
+
* blame_methods - track multiple methods
|
37
|
+
|
38
|
+
You can also track static methods and Devise is the only authorization it supports.
|
39
|
+
|
40
|
+
### Server mode
|
41
|
+
|
42
|
+
blamescope -d postgres://user:password@host/database -r amqp://user:pass@host:port/vhost
|
43
|
+
|
44
|
+
## Installation
|
45
|
+
|
46
|
+
Add this line to your application's Gemfile:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
gem 'blamescope'
|
50
|
+
```
|
51
|
+
|
52
|
+
And then execute:
|
53
|
+
|
54
|
+
$ bundle
|
55
|
+
|
56
|
+
Or install it yourself as:
|
57
|
+
|
58
|
+
$ gem install blamescope
|
59
|
+
|
60
|
+
## Usage
|
61
|
+
|
62
|
+
TODO: Write usage instructions here
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
1. Fork it ( https://github.com/[my-github-username]/blamescope/fork )
|
67
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
68
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
69
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
70
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/blamescope
ADDED
data/blamescope.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'blamescope/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "blamescope"
|
8
|
+
spec.version = Blamescope::VERSION
|
9
|
+
spec.authors = ["Volodymyr Ladnik"]
|
10
|
+
spec.email = ["vladnik@demandbase.com"]
|
11
|
+
spec.summary = %q{Track events per user}
|
12
|
+
spec.description = %q{Find whom to blame for broken stuff}
|
13
|
+
spec.homepage = "https://github.com/Demandbase/blamescope"
|
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_dependency "bunny"
|
22
|
+
spec.add_dependency "pg"
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
end
|
data/lib/blamescope.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require "bunny"
|
2
|
+
require "blamescope/version"
|
3
|
+
require "blamescope/middleware"
|
4
|
+
require "blamescope/trackable"
|
5
|
+
require "blamescope/server"
|
6
|
+
|
7
|
+
#
|
8
|
+
# Blamescope module
|
9
|
+
#
|
10
|
+
# @author Volodymyr Ladnik
|
11
|
+
#
|
12
|
+
module Blamescope
|
13
|
+
class << self
|
14
|
+
attr_accessor :exchange
|
15
|
+
|
16
|
+
def included(base)
|
17
|
+
base.extend(Trackable)
|
18
|
+
base.class.extend(Trackable)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Configure Blamescope
|
23
|
+
# @param [Hash] config
|
24
|
+
# @option config [String] :rabbit Rabbit connection in format amqp://user:pass@host:port/vhost
|
25
|
+
#
|
26
|
+
def configure(config)
|
27
|
+
self.exchange = rabbit_connection(config[:rabbit])[:exchange]
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Get current user
|
32
|
+
#
|
33
|
+
# @return [String] user email
|
34
|
+
def user
|
35
|
+
env = Thread.current[:env]
|
36
|
+
if env && env['warden']
|
37
|
+
env['warden'].user.email
|
38
|
+
else
|
39
|
+
"#{ENV['USER']}@#{Socket.gethostname}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Send event
|
45
|
+
# @param [type] attrs event attributes
|
46
|
+
# @option attrs [String] :model current class name
|
47
|
+
# @option attrs [String] :action current method
|
48
|
+
# @option attrs [String] :attrs object attributes
|
49
|
+
#
|
50
|
+
def emit(attrs)
|
51
|
+
attrs[:email] ||= user
|
52
|
+
exchange.publish(attrs.to_json)
|
53
|
+
rescue Bunny::ConnectionClosedError
|
54
|
+
puts "Bunny is down: couldn't send #{attrs[:action]} action for #{attrs[:model]} model"
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Create RabbitMQ connection
|
59
|
+
# @param config [String] Rabbit connection in format amqp://user:pass@host:port/vhost
|
60
|
+
#
|
61
|
+
# @return [Hash] rabbit connection, channel and exchange
|
62
|
+
def rabbit_connection(config)
|
63
|
+
conn = Bunny.new(config)
|
64
|
+
conn.start
|
65
|
+
channel = conn.create_channel
|
66
|
+
exchange = channel.fanout("blamescope")
|
67
|
+
{conn: conn, channel: channel, exchange: exchange}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Blamescope
|
2
|
+
#
|
3
|
+
# Rack middleware to intercept request environment
|
4
|
+
#
|
5
|
+
# @author Volodymyr Ladnik
|
6
|
+
#
|
7
|
+
class Middleware
|
8
|
+
|
9
|
+
def initialize(app, config = nil)
|
10
|
+
@app = app
|
11
|
+
Blamescope.configure(config) if config
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
Thread.current[:env] = env
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require "pg"
|
2
|
+
require "json"
|
3
|
+
require "uri"
|
4
|
+
require "optparse"
|
5
|
+
|
6
|
+
module Blamescope
|
7
|
+
class Server
|
8
|
+
TABLE_QUERY = <<-EOS
|
9
|
+
CREATE TABLE IF NOT EXISTS blamescope (
|
10
|
+
id serial NOT NULL,
|
11
|
+
email character varying(255),
|
12
|
+
action character varying(255),
|
13
|
+
model character varying(255),
|
14
|
+
attributes json,
|
15
|
+
created_at timestamp without time zone,
|
16
|
+
CONSTRAINT blamescope_pkey PRIMARY KEY (id)
|
17
|
+
);
|
18
|
+
EOS
|
19
|
+
|
20
|
+
def self.start(options = {})
|
21
|
+
# Parse options
|
22
|
+
optparse = OptionParser.new do |opts|
|
23
|
+
opts.banner = "Usage: blamescope [options]"
|
24
|
+
opts.on("-d", "--database CONF", "Database connection in format postgres://user:password@host/database") do |d|
|
25
|
+
options[:database] = d
|
26
|
+
end
|
27
|
+
opts.on("-r", "--rabbit CONF", "RabbitMQ connection in format amqp://user:pass@host:port/vhost") do |r|
|
28
|
+
options[:rabbit] = r
|
29
|
+
end
|
30
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
31
|
+
options[:verbose] = v
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
optparse.parse!
|
36
|
+
if options[:database] && options[:rabbit]
|
37
|
+
new.listen(options)
|
38
|
+
else
|
39
|
+
puts optparse
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def listen(config)
|
44
|
+
rabbit = rabbit_connection(config[:rabbit])
|
45
|
+
db = postgres_connection(config[:database])
|
46
|
+
rabbit[:queue].subscribe(block: true) do |delivery_info, properties, body|
|
47
|
+
store_event(db, body)
|
48
|
+
end
|
49
|
+
rescue Interrupt => _
|
50
|
+
rabbit[:channel].close
|
51
|
+
rabbit[:conn].close
|
52
|
+
end
|
53
|
+
|
54
|
+
def store_event(db, body, time = Time.now.utc)
|
55
|
+
event = JSON.parse(body)
|
56
|
+
db.exec_prepared('insert_event', [event['email'], event['action'], event['model'], event['attrs'].to_json, time])
|
57
|
+
end
|
58
|
+
|
59
|
+
def rabbit_connection(config)
|
60
|
+
rabbit = Blamescope.rabbit_connection(config)
|
61
|
+
queue = rabbit[:channel].queue("", exclusive: true)
|
62
|
+
queue.bind(rabbit[:exchange])
|
63
|
+
rabbit[:queue] = queue
|
64
|
+
return rabbit
|
65
|
+
end
|
66
|
+
|
67
|
+
def postgres_connection(config)
|
68
|
+
config = URI.parse(config)
|
69
|
+
params = {host: config.host, dbname: config.path[1..-1]}
|
70
|
+
params[:user] = config.user if config.user
|
71
|
+
params[:password] = config.password if config.password
|
72
|
+
params[:port] = config.port if config.port
|
73
|
+
conn = PG.connect(params)
|
74
|
+
conn.exec(TABLE_QUERY)
|
75
|
+
conn.prepare("insert_event", "INSERT INTO blamescope (email, action, model, attributes, created_at)
|
76
|
+
VALUES ($1, $2, $3, $4, $5)")
|
77
|
+
return conn
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# Trackable module
|
3
|
+
#
|
4
|
+
# @author Volodymyr Ladnik
|
5
|
+
#
|
6
|
+
module Blamescope
|
7
|
+
module Trackable
|
8
|
+
|
9
|
+
#
|
10
|
+
# Send event for model
|
11
|
+
# @param model [Object] current object
|
12
|
+
# @param method_name [String|Symbol] method invoked
|
13
|
+
#
|
14
|
+
# @return [type] [description]
|
15
|
+
def self.send_event(model, method_name)
|
16
|
+
class_name = model.class == Class ? model.name : model.class.name
|
17
|
+
attrs = {}
|
18
|
+
attrs[:id] = model.id if model.respond_to? :id
|
19
|
+
if model.respond_to? :name
|
20
|
+
attrs[:name] = model.name
|
21
|
+
elsif model.respond_to? :title
|
22
|
+
attrs[:title] = model.title
|
23
|
+
end
|
24
|
+
Blamescope.emit(model: class_name, action: method_name, attrs: attrs)
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Track method
|
29
|
+
# @param name [String|Symbol] method name
|
30
|
+
#
|
31
|
+
def blame_method method_name
|
32
|
+
alias_method "original_#{method_name}", method_name
|
33
|
+
define_method method_name do |*args, &block|
|
34
|
+
Blamescope::Trackable.send_event(self, method_name)
|
35
|
+
send("original_#{method_name}", *args, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Track multiple methods
|
41
|
+
# @param *names [String|Symbol] method name
|
42
|
+
#
|
43
|
+
def blame_methods *names
|
44
|
+
names.each do |name|
|
45
|
+
blame_method(name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Track ActiveRecord model
|
51
|
+
#
|
52
|
+
def blame_activerecord
|
53
|
+
after_create do
|
54
|
+
Blamescope::Trackable.send_event(self, :create)
|
55
|
+
end
|
56
|
+
after_update do
|
57
|
+
Blamescope::Trackable.send_event(self, :update)
|
58
|
+
end
|
59
|
+
after_destroy do
|
60
|
+
Blamescope::Trackable.send_event(self, :delete)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Blamescope
|
4
|
+
describe Middleware do
|
5
|
+
describe "::new" do
|
6
|
+
it "should configure application" do
|
7
|
+
expect(Blamescope).to receive(:configure).with(:config)
|
8
|
+
Middleware.new(:app, :config)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#call" do
|
13
|
+
it "should set environment from request" do
|
14
|
+
app = double('app')
|
15
|
+
expect(Thread).to receive_message_chain(:current, :[]=).with(:env, :env)
|
16
|
+
expect(app).to receive(:call).with(:env)
|
17
|
+
subject = Middleware.new(app)
|
18
|
+
subject.call(:env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Blamescope
|
4
|
+
describe Server do
|
5
|
+
describe "::start" do
|
6
|
+
it "should initialize server if options provided" do
|
7
|
+
options = {database: 'db_url', rabbit: 'rabbit_url'}
|
8
|
+
expect(Server).to receive_message_chain(:new, :listen).with(options)
|
9
|
+
Server.start(options)
|
10
|
+
end
|
11
|
+
it "shouldn't initialize server if any option missing" do
|
12
|
+
expect(Server).to receive(:puts).twice
|
13
|
+
expect(Server).not_to receive(:new)
|
14
|
+
Server.start(database: 'db_url')
|
15
|
+
Server.start(rabbit: 'rabbit_url')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#listen" do
|
20
|
+
it "should listen for events" do
|
21
|
+
subject = Server.new
|
22
|
+
queue = double('rabbit queue')
|
23
|
+
expect(queue).to receive(:subscribe).and_yield(:info, :properties,:body)
|
24
|
+
expect(subject).to receive(:rabbit_connection).with(:rabbit).and_return(queue: queue)
|
25
|
+
expect(subject).to receive(:postgres_connection).with(:database).and_return(:db)
|
26
|
+
expect(subject).to receive(:store_event).with(:db, :body)
|
27
|
+
subject.listen(rabbit: :rabbit, database: :database)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should close channel and connection on interrupt" do
|
31
|
+
subject = Server.new
|
32
|
+
queue = double('rabbit queue')
|
33
|
+
expect(queue).to receive(:subscribe).and_raise(Interrupt)
|
34
|
+
channel = double('rabbit channel')
|
35
|
+
expect(channel).to receive(:close)
|
36
|
+
conn = double('rabbit connection')
|
37
|
+
expect(conn).to receive(:close)
|
38
|
+
expect(subject).to receive(:rabbit_connection).with(:rabbit).and_return(queue: queue, channel: channel, conn: conn)
|
39
|
+
expect(subject).to receive(:postgres_connection).with(:database).and_return(:db)
|
40
|
+
subject.listen(rabbit: :rabbit, database: :database)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
describe "#store_event" do
|
44
|
+
it "should store event" do
|
45
|
+
time = Time.now.utc
|
46
|
+
db = double('database connection')
|
47
|
+
expect(db).to receive(:exec_prepared).with('insert_event',
|
48
|
+
['user@example.com', 'create', 'User', '{"id":1}', time])
|
49
|
+
subject = Server.new
|
50
|
+
subject.store_event(db, {email: 'user@example.com', action: 'create', model: 'User', attrs: {id: 1}}.to_json, time)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestClass
|
4
|
+
include Blamescope
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def static_method arg
|
8
|
+
'static response'
|
9
|
+
end
|
10
|
+
blame_method :static_method
|
11
|
+
end
|
12
|
+
|
13
|
+
def create arg1, arg2
|
14
|
+
'create result'
|
15
|
+
end
|
16
|
+
blame_method :create
|
17
|
+
|
18
|
+
def update arg1, &block
|
19
|
+
return 'block given' if block_given?
|
20
|
+
end
|
21
|
+
blame_method :update
|
22
|
+
|
23
|
+
def name
|
24
|
+
'some name'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module Blamescope
|
29
|
+
describe Trackable do
|
30
|
+
describe "#blame_method" do
|
31
|
+
it "should work with multiple arguments" do
|
32
|
+
instance = TestClass.new
|
33
|
+
expect(Blamescope::Trackable).to receive(:send_event).with(instance, :create)
|
34
|
+
expect(instance).to receive(:original_create).with(:arg1,:arg2).and_call_original
|
35
|
+
expect(instance.create(:arg1,:arg2)).to eq('create result')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should work with block of code" do
|
39
|
+
instance = TestClass.new
|
40
|
+
expect(Blamescope::Trackable).to receive(:send_event).with(instance, :update)
|
41
|
+
expect(instance).to receive(:original_update).with(:arg1).and_call_original
|
42
|
+
expect(instance.update(:arg1){ block }).to eq('block given')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "::blame_method" do
|
47
|
+
it "should work with static methods" do
|
48
|
+
expect(Blamescope::Trackable).to receive(:send_event).with(TestClass, :static_method)
|
49
|
+
expect(TestClass).to receive(:original_static_method).with(:arg1).and_call_original
|
50
|
+
expect(TestClass.static_method(:arg1)).to eq('static response')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#blame_methods" do
|
55
|
+
it "should invoke #track_method for each argument" do
|
56
|
+
expect(TestClass).to receive(:blame_method).with(:first)
|
57
|
+
expect(TestClass).to receive(:blame_method).with(:second)
|
58
|
+
TestClass.blame_methods :first, :second
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blamescope do
|
4
|
+
describe "#configure" do
|
5
|
+
it "should create connection" do
|
6
|
+
expect(Blamescope).to receive(:rabbit_connection).with(:config).and_return(exchange: :exchange)
|
7
|
+
Blamescope.configure(rabbit: :config)
|
8
|
+
expect(Blamescope.exchange).to eq(:exchange)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#user" do
|
13
|
+
it "should get user from warden key" do
|
14
|
+
warden = double('warden')
|
15
|
+
allow(warden).to receive_message_chain(:user, email: 'user@example.com')
|
16
|
+
Thread.current[:env] = {'warden' => warden }
|
17
|
+
expect(Blamescope.user).to eq('user@example.com')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should use system user if warden is not available" do
|
21
|
+
Thread.current[:env] = nil
|
22
|
+
expect(Blamescope.user).to eq("#{ENV['USER']}@#{Socket.gethostname}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#emit" do
|
27
|
+
it "should publish event" do
|
28
|
+
allow(Blamescope).to receive(:user).and_return('user@example.com')
|
29
|
+
expect(Blamescope).to receive_message_chain(:exchange, :publish).with({model:'USER', email: 'user@example.com'}.to_json)
|
30
|
+
Blamescope.emit(model: 'USER')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blamescope
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Volodymyr Ladnik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bunny
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pg
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: codeclimate-test-reporter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Find whom to blame for broken stuff
|
112
|
+
email:
|
113
|
+
- vladnik@demandbase.com
|
114
|
+
executables:
|
115
|
+
- blamescope
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- .gitignore
|
120
|
+
- .rspec
|
121
|
+
- .travis.yml
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- bin/blamescope
|
127
|
+
- blamescope.gemspec
|
128
|
+
- lib/blamescope.rb
|
129
|
+
- lib/blamescope/middleware.rb
|
130
|
+
- lib/blamescope/server.rb
|
131
|
+
- lib/blamescope/trackable.rb
|
132
|
+
- lib/blamescope/version.rb
|
133
|
+
- spec/blamescope/middleware_spec.rb
|
134
|
+
- spec/blamescope/server_spec.rb
|
135
|
+
- spec/blamescope/trackable_spec.rb
|
136
|
+
- spec/blamescope_spec.rb
|
137
|
+
- spec/spec_helper.rb
|
138
|
+
homepage: https://github.com/Demandbase/blamescope
|
139
|
+
licenses:
|
140
|
+
- MIT
|
141
|
+
metadata: {}
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 2.2.2
|
159
|
+
signing_key:
|
160
|
+
specification_version: 4
|
161
|
+
summary: Track events per user
|
162
|
+
test_files:
|
163
|
+
- spec/blamescope/middleware_spec.rb
|
164
|
+
- spec/blamescope/server_spec.rb
|
165
|
+
- spec/blamescope/trackable_spec.rb
|
166
|
+
- spec/blamescope_spec.rb
|
167
|
+
- spec/spec_helper.rb
|