logstash_rails 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --require spec_helper
2
+ --order random
3
+ --colour
4
+ --format nested
5
+ -b
data/Gemfile CHANGED
@@ -10,7 +10,6 @@ group :development do
10
10
  end
11
11
 
12
12
  group :test do
13
- gem 'minitest', require: 'minitest/autorun'
13
+ gem 'rspec'
14
14
  gem 'fakeredis'
15
- gem 'mocha', require: false
16
15
  end
data/README.md CHANGED
@@ -1,49 +1,86 @@
1
- # LogstashRails [![Code Climate](https://codeclimate.com/github/cmertz/logstash_rails.png)](https://codeclimate.com/github/cmertz/logstash_rails) [![Build Status](https://secure.travis-ci.org/cmertz/logstash_rails.png)](http://travis-ci.org/cmertz/logstash_rails) [![Dependency Status](https://gemnasium.com/cmertz/logstash_rails.png)](https://gemnasium.com/cmertz/logstash_rails) [![Coverage Status](https://coveralls.io/repos/cmertz/logstash_rails/badge.png)](https://coveralls.io/r/cmertz/logstash_rails)
1
+ # LogstashRails
2
+ [![Gem Version](https://badge.fury.io/rb/logstash_rails.png)](http://badge.fury.io/rb/logstash_rails)
3
+ [![Build Status](https://secure.travis-ci.org/cmertz/logstash_rails.png)](http://travis-ci.org/cmertz/logstash_rails)
4
+ [![Coverage Status](https://coveralls.io/repos/cmertz/logstash_rails/badge.png)](https://coveralls.io/r/cmertz/logstash_rails)
5
+ [![Code Climate](https://codeclimate.com/github/cmertz/logstash_rails.png)](https://codeclimate.com/github/cmertz/logstash_rails)
6
+ [![Dependency Status](https://gemnasium.com/cmertz/logstash_rails.png)](https://gemnasium.com/cmertz/logstash_rails)
2
7
 
3
- Send Logstash events from a Rails application to Redis.
8
+ Send events from Rails to Logstash without logger foo.
4
9
 
5
- ## Installation
10
+ ## Contents
6
11
 
7
- In your applications Gemfile:
12
+ * [Usage](#usage)
13
+ * [Configuration](#configurtion)
14
+ * [Examples](#examples)
15
+ * [Contributing](#contributing)
8
16
 
9
- ```ruby
10
- gem 'logstash_rails'
11
- ```
12
17
 
13
- For the latest version:
18
+ ## Usage
19
+
20
+ Add logstash-rails to your applications `Gemfile`
14
21
 
15
22
  ```ruby
16
- gem 'logstash_rails', github: 'cmertz/logstash_rails'
23
+ gem 'logstash_rails'
17
24
  ```
18
25
 
19
- Provide an initializer (e.g. config/initializers/logstash_rails.rb) for
20
- specific configuration.
26
+ and provide an initializer for configuration.
27
+
21
28
 
22
29
  ### Configuration
23
30
 
24
- **LogstashRails.config** takes a redis connection, the redis key for the list
25
- to push to and a flag that enables to catch all events (i.e. /.\*/)
31
+ `LogstashRails.config` takes an options hash with the following options:
32
+
33
+ * __transport__
34
+
35
+ redis is the only available transport atm
36
+
37
+ * __logger__
38
+
39
+ logger to use in case of exceptions while pushing events to the transport
40
+
41
+ * __events__
42
+
43
+ list of event name patterns to subscribe to. `Regex` and `String` is
44
+ supported.
45
+
46
+ * __transport options__
47
+
48
+ transport specific options e.g. _host_, _port_ and *redis_key*
49
+
50
+
51
+ ### Examples
26
52
 
27
53
  The most basic configuration looks like:
28
54
 
29
55
  ```ruby
30
- LogstashRails.config(Redis.new)
56
+ LogstashRails.config(transport: :redis)
31
57
  ```
32
58
 
33
- This will connect to the redis server on localhost, use 'logstash' (default) as
34
- key for the redis list to push to and subscribe to all events.
59
+ This will will connect to a redis server on _localhost:6379_, use _logstash_ as
60
+ key for the redis list to push to and subscribe to _all events_.
35
61
 
36
62
  A more complete example looks like:
37
63
 
38
64
  ```ruby
39
65
  if Rails.env.production?
40
- redis = Redis.new(host: '1.2.3.4', port: 12345)
41
- LogstashRails.config(redis, 'my_key', false)
42
- LogstashRails.subscribe('process_action.action_controller')
66
+ LogstashRails.config(
67
+ transport: redis,
68
+ host: '1.2.3.4',
69
+ port: 12345,
70
+ redis_key: 'my_key',
71
+ events: [/action_controller/]
72
+ )
43
73
  end
44
74
  ```
45
75
 
76
+ This will only subscribe to events from `ActionController`.
77
+
46
78
 
47
- ## TODO
79
+ ## Contributing
48
80
 
49
- * more independent from Rails i.e. check defined?(Rails) and provide fallbacks (for logger and application name)
81
+ 1. Fork it.
82
+ 2. Create a branch (`git checkout -b my_feature`)
83
+ 3. Commit your changes (`git commit -am "Added ..."`)
84
+ 4. Push to the branch (`git push origin my_feature`)
85
+ 5. Open a Pull Request
86
+ 6. Enjoy a refreshing Diet Coke and wait
data/Rakefile CHANGED
@@ -1,13 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
- require 'rake/testtask'
3
2
  require 'yard/rake/yardoc_task'
3
+ require 'rspec/core/rake_task'
4
4
 
5
- Rake::TestTask.new do |t|
6
- t.libs.push "lib"
7
- t.libs.push "spec"
8
- t.test_files = FileList['spec/*_spec.rb']
9
- t.verbose = false
10
- end
5
+ RSpec::Core::RakeTask.new(:test)
11
6
 
12
7
  YARD::Rake::YardocTask.new do |t|
13
8
  t.name = 'doc'
@@ -1,64 +1,20 @@
1
- require 'logstash_rails/formatter'
2
1
  require 'active_support'
2
+ require 'active_support/core_ext/string'
3
3
 
4
- module LogstashRails
5
- class << self
6
-
7
- # configures LogstashRails
8
- #
9
- # @param redis
10
- # @param key [String]
11
- # @param handle_all [Boolean]
12
- #
13
- def config(redis, key = 'logstash', handle_all = true)
14
- unless handle_all.is_a?(TrueClass) || handle_all.is_a?(FalseClass)
15
- raise ArgumentError
16
- end
17
-
18
- raise ArgumentError unless key.is_a?(String)
19
-
20
- raise ArgumentError unless redis
21
-
22
- @redis = redis
23
- @key = key
24
-
25
- subscribe(/.*/) if handle_all
26
- end
4
+ require 'logstash_rails/configuration_base'
27
5
 
28
- # subscribes LogstashRails to an ActiveSupport notification
29
- #
30
- # @param event_type [String|Regexp]
31
- #
32
- def subscribe(event_type)
33
- @subscriptions ||= {}
34
-
35
- @subscriptions[event_type] = ActiveSupport::Notifications.subscribe(event_type) do |*args|
36
- push(*args)
37
- end
38
- end
39
-
40
- # unsubscribe LogstashRails form an ActiveSupport notification
41
- #
42
- # @param event_type [String|Regexp] this must be the equal to the event_type that was subscribed with
43
- #
44
- def unsubscribe(event_type)
45
- ActiveSupport::Notifications.unsubscribe(@subscriptions[event_type])
46
- end
47
-
48
- private
6
+ Dir[File.join(File.dirname(__FILE__), 'logstash_rails', '*.rb')].each do |file|
7
+ require file
8
+ end
49
9
 
50
- def push(event_type, *args)
51
- begin
52
- @redis.rpush(@key, Formatter.format(event_type, *args))
53
- rescue
54
- log $!
55
- end
56
- end
10
+ module LogstashRails
11
+ extend self
57
12
 
58
- def log(exception)
59
- msg = exception.message + "\n " + exception.backtrace.join("\n ")
60
- Rails.logger.error(msg)
61
- end
13
+ def config(options)
14
+ transport = options.fetch(:transport)
15
+ transport = transport.to_s.camelize.to_sym
62
16
 
17
+ LogstashRails::Transport.const_get(transport).new(options)
63
18
  end
19
+
64
20
  end
@@ -0,0 +1,45 @@
1
+ module LogstashRails
2
+ class ConfigurationBase
3
+
4
+ def initialize(options)
5
+ @events = options[:events] || [/.*/]
6
+ @logger = options[:logger]
7
+
8
+ if defined?(Rails)
9
+ @logger ||= Rails.logger
10
+ end
11
+
12
+ subscribe
13
+ end
14
+
15
+ def destroy
16
+ return unless @subscriptions
17
+
18
+ @subscriptions.each do |subscription|
19
+ ActiveSupport::Notifications.unsubscribe(subscription)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def subscribe
26
+ @subscriptions = @events.map do |event|
27
+ ActiveSupport::Notifications.subscribe(event) do |*args|
28
+ json_event = Formatter.format(*args)
29
+
30
+ begin
31
+ push(json_event)
32
+ rescue
33
+ log($!)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def log(exception)
40
+ msg = exception.message + "\n " + exception.backtrace.join("\n ")
41
+ @logger.error(msg) if @logger
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'transport', '*.rb')].each do |file|
2
+ require file
3
+ end
4
+
5
+ module LogstashRails
6
+ module Transport
7
+ def self.get(transport)
8
+ constant_name = transport.to_s.camelize.to_sym
9
+ LogstashRails::Transport.const_get(constant_name)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module LogstashRails
2
+ module Transport
3
+ class LogstashTcp < ConfigurationBase
4
+
5
+ def initialize(options)
6
+ super
7
+
8
+ host = options[:host] || 'localhost'
9
+ port = options.fetch(:port)
10
+
11
+ @socket = TCPSocket.new(host, port)
12
+ end
13
+
14
+ def push(json_event)
15
+ @socket.write(json_event)
16
+ end
17
+
18
+ def destroy
19
+ super
20
+ @socket.close
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module LogstashRails
2
+ module Transport
3
+ class LogstashUdp < ConfigurationBase
4
+
5
+ def initialize(options = {})
6
+ super
7
+
8
+ host = options[:host] || 'localhost'
9
+ port = options[:port] || 9999
10
+
11
+ @socket = UDPSocket.new.tap{|s| s.connect(host, port) }
12
+ end
13
+
14
+ def push(json_event)
15
+ @socket.write(json_event)
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module LogstashRails
2
+ module Transport
3
+ class Redis < LogstashRails::ConfigurationBase
4
+
5
+ def initialize(options)
6
+ host = options[:host] || '127.0.0.1'
7
+ port = options[:port] || 6379
8
+ redis_key = options[:redis_key] || 'logstash'
9
+
10
+ @redis = ::Redis.new(host: host, port: port)
11
+ @redis_key = redis_key
12
+
13
+ super
14
+ end
15
+
16
+ def push(json_event)
17
+ unless @redis.rpush(@redis_key, json_event)
18
+ raise "could not send event to redis"
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module LogstashRails
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -7,14 +7,13 @@ Gem::Specification.new do |gem|
7
7
  gem.version = LogstashRails::VERSION
8
8
  gem.authors = ["cmertz"]
9
9
  gem.email = ["chris@nimel.de"]
10
- gem.description = %q{Send Logstash events from a Rails application to Redis}
11
- gem.summary = %q{Send Logstash events from a Rails application to Redis}
12
- gem.homepage = ""
10
+ gem.summary = %q{Send events from Rails to Logstash without logger foo.}
11
+ gem.description = %q{Send events from Rails to Logstash without logger foo.}
12
+ gem.homepage = "https://github.com/cmertz/logstash_rails"
13
13
  gem.license = "GPL"
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.test_files = gem.files.grep(%r{^spec/})
18
17
  gem.require_paths = ["lib"]
19
18
 
20
19
  gem.add_dependency('logstash-event')
@@ -0,0 +1,33 @@
1
+ describe LogstashRails::ConfigurationBase do
2
+
3
+ subject do
4
+ LogstashRails
5
+ end
6
+
7
+ it 'raises if no transport is specified' do
8
+ expect { subject.config({}) }.to raise_error(KeyError)
9
+ end
10
+
11
+ it 'handles all events by default' do
12
+ config = subject.config(transport: :redis)
13
+
14
+ config.should_receive(:push)
15
+
16
+ ActiveSupport::Notifications.instrument('foobar_event')
17
+
18
+ config.destroy
19
+ end
20
+
21
+ it 'logs exceptions if a logger is given' do
22
+ logger = mock(:logger)
23
+ config = subject.config(transport: :redis, logger: logger)
24
+ config.stub(:push).and_raise(ArgumentError.new)
25
+
26
+ logger.should_receive(:error)
27
+
28
+ ActiveSupport::Notifications.instrument('foobar_event')
29
+
30
+ config.destroy
31
+ end
32
+
33
+ end
@@ -1,23 +1,17 @@
1
- require 'spec_helper'
2
-
3
1
  describe 'generated logstash event' do
4
2
 
5
3
  before do
6
4
  Redis::Connection::Memory.reset_all_databases
7
- LogstashRails.config(redis)
5
+ LogstashRails.config(transport: :redis, redis: Redis.new, redis_key: 'logstash')
8
6
  ActiveSupport::Notifications.instrument("process_action.action_controller")
9
7
  end
10
8
 
11
- def redis
12
- Redis.new
13
- end
14
-
15
9
  it 'is parsebale json' do
16
- JSON.parse(redis.lpop('logstash'))
10
+ JSON.parse(Redis.new.lpop('logstash'))
17
11
  end
18
12
 
19
13
  it 'has the event type as message' do
20
- JSON.parse(redis.lpop('logstash'))['@message'].must_equal "process_action.action_controller"
14
+ JSON.parse(Redis.new.lpop('logstash'))['@message'].should eq "process_action.action_controller"
21
15
  end
22
16
 
23
17
  end
@@ -0,0 +1,31 @@
1
+ describe LogstashRails::Transport::LogstashTcp do
2
+
3
+ before do
4
+ @server = TCPServer.new(9000)
5
+
6
+ @thread = Thread.new do
7
+ client = @server.accept
8
+ @received = client.gets
9
+ client.close
10
+ end
11
+ end
12
+
13
+ after do
14
+ @server.close
15
+ end
16
+
17
+ let :logstash_tcp do
18
+ LogstashRails::Transport::LogstashTcp.new(port: 9000)
19
+ end
20
+
21
+ it do
22
+ logstash_tcp.should respond_to :push
23
+ end
24
+
25
+ it 'sends data over tcp' do
26
+ logstash_tcp.push 'toto'
27
+ logstash_tcp.destroy
28
+ @thread.join
29
+ @received.should eq 'toto'
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ describe LogstashRails::Transport::LogstashUdp do
2
+ subject do
3
+ LogstashRails::Transport::LogstashUdp.new
4
+ end
5
+
6
+ it { should respond_to :push }
7
+ end
@@ -0,0 +1,22 @@
1
+ describe LogstashRails::Transport::Redis do
2
+
3
+ before do
4
+ Redis::Connection::Memory.reset_all_databases
5
+ end
6
+
7
+ subject do
8
+ LogstashRails::Transport::Redis.new(
9
+ redis: Redis.new,
10
+ redis_key: 'logstash'
11
+ )
12
+ end
13
+
14
+ it { should respond_to :push }
15
+
16
+ it 'writes events to a redis list' do
17
+ subject.push('foobar_event')
18
+
19
+ Redis.new.lpop('logstash').should eq 'foobar_event'
20
+ end
21
+
22
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-05 00:00:00.000000000 Z
12
+ date: 2013-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: logstash-event
@@ -59,7 +59,7 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- description: Send Logstash events from a Rails application to Redis
62
+ description: Send events from Rails to Logstash without logger foo.
63
63
  email:
64
64
  - chris@nimel.de
65
65
  executables: []
@@ -67,21 +67,28 @@ extensions: []
67
67
  extra_rdoc_files: []
68
68
  files:
69
69
  - .gitignore
70
+ - .rspec
70
71
  - .travis.yml
71
72
  - Gemfile
72
73
  - LICENSE.txt
73
74
  - README.md
74
75
  - Rakefile
75
76
  - lib/logstash_rails.rb
77
+ - lib/logstash_rails/configuration_base.rb
76
78
  - lib/logstash_rails/formatter.rb
79
+ - lib/logstash_rails/transport.rb
80
+ - lib/logstash_rails/transport/logstash_tcp.rb
81
+ - lib/logstash_rails/transport/logstash_udp.rb
82
+ - lib/logstash_rails/transport/redis.rb
77
83
  - lib/logstash_rails/version.rb
78
84
  - logstash_rails.gemspec
79
- - spec/config_spec.rb
80
- - spec/error_spec.rb
81
- - spec/event_spec.rb
85
+ - spec/lib/logstash_rails/configuration_spec.rb
86
+ - spec/lib/logstash_rails/formatter_spec.rb
87
+ - spec/lib/logstash_rails/transport/logstash_tcp_spec.rb
88
+ - spec/lib/logstash_rails/transport/logstash_udp_spec.rb
89
+ - spec/lib/logstash_rails/transport/redis_spec.rb
82
90
  - spec/spec_helper.rb
83
- - spec/subscription_spec.rb
84
- homepage: ''
91
+ homepage: https://github.com/cmertz/logstash_rails
85
92
  licenses:
86
93
  - GPL
87
94
  post_install_message:
@@ -96,7 +103,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
103
  version: '0'
97
104
  segments:
98
105
  - 0
99
- hash: -4390785812541147448
106
+ hash: 133620392481037059
100
107
  required_rubygems_version: !ruby/object:Gem::Requirement
101
108
  none: false
102
109
  requirements:
@@ -105,17 +112,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
112
  version: '0'
106
113
  segments:
107
114
  - 0
108
- hash: -4390785812541147448
115
+ hash: 133620392481037059
109
116
  requirements: []
110
117
  rubyforge_project:
111
118
  rubygems_version: 1.8.25
112
119
  signing_key:
113
120
  specification_version: 3
114
- summary: Send Logstash events from a Rails application to Redis
121
+ summary: Send events from Rails to Logstash without logger foo.
115
122
  test_files:
116
- - spec/config_spec.rb
117
- - spec/error_spec.rb
118
- - spec/event_spec.rb
123
+ - spec/lib/logstash_rails/configuration_spec.rb
124
+ - spec/lib/logstash_rails/formatter_spec.rb
125
+ - spec/lib/logstash_rails/transport/logstash_tcp_spec.rb
126
+ - spec/lib/logstash_rails/transport/logstash_udp_spec.rb
127
+ - spec/lib/logstash_rails/transport/redis_spec.rb
119
128
  - spec/spec_helper.rb
120
- - spec/subscription_spec.rb
121
129
  has_rdoc:
data/spec/config_spec.rb DELETED
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'LogstashRails.config' do
4
-
5
- def redis
6
- Redis.new
7
- end
8
-
9
- it 'raises an ArgumentError if the handle_all flag is not a boolean' do
10
- lambda do
11
- LogstashRails.config(redis, 'fookey', 'somerandomstring')
12
- end.must_raise(ArgumentError)
13
- end
14
-
15
- it 'raises an ArgumentError if the key is not a string' do
16
- lambda do
17
- LogstashRails.config(redis, 123, true)
18
- end.must_raise(ArgumentError)
19
- end
20
-
21
- it 'raises an ArgumentError if redis is nil' do
22
- lambda do
23
- LogstashRails.config(nil, 'fookey', true)
24
- end.must_raise(ArgumentError)
25
- end
26
-
27
- end
data/spec/error_spec.rb DELETED
@@ -1,16 +0,0 @@
1
- require 'spec_helper'
2
- require 'mocha/setup'
3
-
4
- describe 'error behaviour' do
5
-
6
- it 'logs exception traces to the Rails logger' do
7
- logger = MiniTest::Mock.new
8
- logger.expect(:error, nil, [String])
9
- LogstashRails.stubs(:log).returns(logger)
10
-
11
- LogstashRails.config(1)
12
-
13
- ActiveSupport::Notifications.instrument("process_action.action_controller")
14
- end
15
-
16
- end
@@ -1,57 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe LogstashRails do
4
-
5
- before do
6
- Redis::Connection::Memory.reset_all_databases
7
- end
8
-
9
- def redis
10
- Redis.new
11
- end
12
-
13
- it 'handles all events by default' do
14
- LogstashRails.config(redis)
15
-
16
- ActiveSupport::Notifications.instrument("process_action.action_controller")
17
-
18
- redis.lpop('logstash').wont_be_nil
19
- end
20
-
21
- it 'does not handle events unless told to' do
22
- LogstashRails.config(redis, 'logtstash', false)
23
-
24
- ActiveSupport::Notifications.instrument("process_action.action_controller")
25
-
26
- redis.lpop('logstash').must_be_nil
27
- end
28
-
29
- it 'handles events explicitly subscribed to' do
30
- LogstashRails.config(redis, 'logstash', false)
31
- LogstashRails.subscribe("process_action.action_controller")
32
-
33
- ActiveSupport::Notifications.instrument("process_action.action_controller")
34
-
35
- redis.lpop('logstash').wont_be_nil
36
- end
37
-
38
- it 'can be unsubscribed from events' do
39
- LogstashRails.config(redis, 'logtstash', false)
40
- LogstashRails.subscribe("process_action.action_controller")
41
- LogstashRails.unsubscribe("process_action.action_controller")
42
-
43
- ActiveSupport::Notifications.instrument("process_action.action_controller")
44
-
45
- redis.lpop('logstash').must_be_nil
46
- end
47
-
48
- it 'uses the provided redis key' do
49
- LogstashRails.config(redis, 'foorediskey', false)
50
- LogstashRails.subscribe("process_action.action_controller")
51
-
52
- ActiveSupport::Notifications.instrument("process_action.action_controller")
53
-
54
- redis.lpop('foorediskey').wont_be_nil
55
- end
56
-
57
- end