logstasher 0.5.0 → 0.5.2

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZGM0Y2IzY2FhZmU1OGI4ZGY3NmRhMWI4ZjBlMjY0ZGI4YTdjNDYzOA==
4
+ NDFjMDY1Nzc2ODM1NzA2NjlmNzZlMjIyZmVhNmVjNjZkMWZjZmUzZQ==
5
5
  data.tar.gz: !binary |-
6
- Y2NjYTljN2IwMGJhYjYwYjQ0ZDExMWU5OWYzNDcyZTRkOWI5YjViOA==
6
+ OWJmOWU3ODQzMjU2OWM5ZTk4ZmMxYjkxZjM0ZDJhZjkzNTg0MmE5Mw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NjE1NmIxYzcwZDU4ODc4MGM3NmVlNjE4NzlhMzFiMjZjMTk3OTY4N2E3NDk1
10
- Yjk0YzAyZjU5NDY4ZjY1YzE4MzljYjU3MTM1YzJiMTE4ZjgyNmQzMzBjZDVj
11
- NTA5NzlmNWNmMjczYmM4YjdhYTQyMDVhMDFkNWU4MjVhMmY2N2E=
9
+ ODQ0NWM2NmMxMTRmNGIzOTdlMzlhOTZjYzE0ZjVhZGZiYjZhZDc5NmE1NWJm
10
+ OGFiYWRhNWI5ZjJjOWEzZjhjMmIxMGQ2N2ZlYWY0MTE1NjI0YmQzN2MxMTM1
11
+ ZGJiMDY5ZDg5Nzg0YmFkZWUxNzIxMTRhYTY3ZjUyMTQzZDI2N2Q=
12
12
  data.tar.gz: !binary |-
13
- MDI0NDAwMGI4ZmYxNjJmMGRjYzRhMTM2NzhkOTgwOTFkOTg1MzQ1OWRlNTAw
14
- YThiNWM0YzA5NjQ2NDZiYzAyMmU2NmRhYTdjNDQwNzEzYzc3YThmNjZlYjBj
15
- NDU3NTFjZjkxYzg1MGM5NTIyODlhYjkwNDlkZGFkNjE2YWU2NDM=
13
+ YjhiZDMzM2Q4NGE0MmZhODM2YWU3NjNmNjU5OWU1NDQyNTdlNTEwNjUzNmFk
14
+ YzUzZTc5YjIxMTFlNTYwNjQyYmI2YWMzYjI2NDY3OTZlOGEzOTQ2MDE4OTVh
15
+ MDQyZjk0Mzk0YmM5YzRkZGU4MGRiNjg5MDBmZmJiODQzMzllYzc=
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  This gem is heavily inspired from [lograge](https://github.com/roidrage/lograge), but it's focused on one thing and one thing only. That's making your logs awesome like this:
5
5
 
6
- [![Awesome Logs](http://i.imgur.com/zZXWQNp.png)](http://i.imgur.com/zZXWQNp.png)
6
+ [![Awesome Logs](https://f.cloud.github.com/assets/830679/2407078/dcde03e8-aa82-11e3-85ac-8c5b3a86676e.png)](https://f.cloud.github.com/assets/830679/2407078/dcde03e8-aa82-11e3-85ac-8c5b3a86676e.png)
7
7
 
8
8
  How it's done ?
9
9
 
@@ -11,7 +11,9 @@ By, using these awesome tools:
11
11
  * [Logstash](http://logstash.net) - Store and index your logs
12
12
  * [Kibana](http://kibana.org/) - for awesome visualization. This is optional though, and you can use any other visualizer
13
13
 
14
- To know how to setup these tools - visit my [blog](http://shadabahmed.com/blog/2013/04/30/logstasher-for-awesome-rails-logging)
14
+ Update: Logstash now includes Kibana build in, so no need to separately install. Logstasher has been test with **logstash version 1.3.3**
15
+
16
+ See [quickstart](#quick-setup-for-logstash) for quickly setting up logstash
15
17
 
16
18
  ## About logstasher
17
19
 
@@ -92,6 +94,49 @@ Since some fields are very specific to your application for e.g. *user_name*, so
92
94
  end
93
95
  end
94
96
 
97
+ ## Listening to `ActiveSupport::Notifications` events
98
+
99
+ It is possible to listen to any `ActiveSupport::Notifications` events and store arbitrary data to be included in the final JSON log entry:
100
+
101
+ # In config/initializers/logstasher.rb
102
+
103
+ # Watch calls the block with the same arguments than any ActiveSupport::Notification, plus a store
104
+ LogStasher.watch('some.activesupport.notification') do |name, start, finish, id, payload, store|
105
+ # Do something
106
+ store[:count] = 42
107
+ end
108
+
109
+ Would change the log entry to:
110
+
111
+ ```
112
+ {"@source":"unknown","@tags":["request"],"@fields":{"method":"GET","path":"/","format":"html","controller":"file_servers","action":"index","status":200,"duration":28.34,"view":25.96,"db":0.88,"ip":"127.0.0.1","route":"file_servers#index", "parameters":"","ndapi_time":null,"uuid":"e81ecd178ed3b591099f4d489760dfb6","user":"shadab_ahmed@abc.com", "site":"internal","some.activesupport.notification":{"count":42}},"@timestamp":"2013-04-30T13:00:46.354500+00:00"}
113
+ ```
114
+
115
+ The store exposed to the blocked passed to `watch` is thread-safe, and reset after each request.
116
+ By default, the store is only shared between occurences of the same event.
117
+ You can easily share the same store between different types of notifications, by assigning them to the same event group:
118
+
119
+ # In config/initializers/logstasher.rb
120
+
121
+ LogStasher.watch('foo.notification', event_group: 'notification') do |*args, store|
122
+ # Shared store with 'bar.notification'
123
+ end
124
+
125
+ LogStasher.watch('bar.notification', event_group: 'notification') do |*args, store|
126
+ # Shared store with 'foo.notification'
127
+ end
128
+
129
+ ## Quick Setup for Logstash
130
+
131
+ * Download logstash from [logstash.net](http://www.logstash.net/)
132
+ * Use this sample config file: [quickstart.conf](https://github.com/shadabahmed/logstasher/raw/master/sample_logstash_configurations/quickstart.conf)
133
+ * Start logstash with the following command:
134
+ ```
135
+ java -jar logstash-1.3.3-flatjar.jar agent -f quickstart.conf -- web
136
+ ```
137
+ * Visit http://localhost:9292/ to see the Kibana interface and your parsed logs
138
+ * For advanced options see the latest logstash documentation at [logstash.net](http://www.logstash.net/) or visit my blog at (shadabahmed.com)[http://shadabahmed.com/blog/2013/04/30/logstasher-for-awesome-rails-logging] (slightly outdated but will sure give you ideas for distributed setup etc.)
139
+
95
140
  ## Versions
96
141
  All versions require Rails 3.0.x and higher and Ruby 1.9.2+. Tested on Rails 4 and Ruby 2.0
97
142
 
@@ -102,3 +147,7 @@ All versions require Rails 3.0.x and higher and Ruby 1.9.2+. Tested on Rails 4 a
102
147
  ## Copyright
103
148
 
104
149
  Copyright (c) 2013 Shadab Ahmed, released under the MIT license
150
+
151
+
152
+ [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/shadabahmed/logstasher/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
153
+
data/lib/logstasher.rb CHANGED
@@ -1,11 +1,14 @@
1
1
  require 'logstasher/version'
2
2
  require 'logstasher/log_subscriber'
3
+ require 'request_store'
3
4
  require 'active_support/core_ext/module/attribute_accessors'
4
5
  require 'active_support/core_ext/string/inflections'
5
6
  require 'active_support/ordered_options'
6
7
 
7
8
  module LogStasher
8
9
  extend self
10
+ STORE_KEY = :logstasher_data
11
+
9
12
  attr_accessor :logger, :enabled, :log_controller_parameters, :source
10
13
  # Setting the default to 'unknown' to define the default behaviour
11
14
  @source = 'unknown'
@@ -43,8 +46,12 @@ module LogStasher
43
46
  end
44
47
 
45
48
  def add_custom_fields(&block)
46
- ActionController::Metal.send(:define_method, :logtasher_add_custom_fields_to_payload, &block)
47
- ActionController::Base.send(:define_method, :logtasher_add_custom_fields_to_payload, &block)
49
+ wrapped_block = lambda do |fields|
50
+ LogStasher.custom_fields.concat(LogStasher.store.keys)
51
+ block.call(fields)
52
+ end
53
+ ActionController::Metal.send(:define_method, :logtasher_add_custom_fields_to_payload, &wrapped_block)
54
+ ActionController::Base.send(:define_method, :logtasher_add_custom_fields_to_payload, &wrapped_block)
48
55
  end
49
56
 
50
57
  def setup(app)
@@ -88,6 +95,22 @@ module LogStasher
88
95
  end
89
96
  end
90
97
 
98
+ def store
99
+ if RequestStore.store[STORE_KEY].nil?
100
+ # Get each store it's own private Hash instance.
101
+ RequestStore.store[STORE_KEY] = Hash.new { |hash, key| hash[key] = {} }
102
+ end
103
+ RequestStore.store[STORE_KEY]
104
+ end
105
+
106
+ def watch(event, opts = {}, &block)
107
+ event_group = opts[:event_group] || event
108
+ ActiveSupport::Notifications.subscribe(event) do |*args|
109
+ # Calling the processing block with the Notification args and the store
110
+ block.call(*args, store[event_group])
111
+ end
112
+ end
113
+
91
114
  %w( fatal error warn info debug unknown ).each do |severity|
92
115
  eval <<-EOM, nil, __FILE__, __LINE__ + 1
93
116
  def #{severity}(msg)
@@ -16,7 +16,7 @@ module ActionController
16
16
 
17
17
  ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
18
18
  result = super
19
-
19
+
20
20
  if self.respond_to?(:logtasher_add_custom_fields_to_payload)
21
21
  before_keys = raw_payload.keys.clone
22
22
  logtasher_add_custom_fields_to_payload(raw_payload)
@@ -24,9 +24,12 @@ module ActionController
24
24
  # Store all extra keys added to payload hash in payload itself. This is a thread safe way
25
25
  LogStasher.custom_fields += after_keys - before_keys
26
26
  end
27
-
27
+
28
28
  payload[:status] = response.status
29
29
  append_info_to_payload(payload)
30
+ LogStasher.store.each do |key, value|
31
+ payload[key] = value
32
+ end
30
33
  result
31
34
  end
32
35
  end
@@ -1,3 +1,3 @@
1
1
  module LogStasher
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.2"
3
3
  end
data/logstasher.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
  s.add_runtime_dependency "logstash-event", ["~> 1.1.0"]
21
+ s.add_runtime_dependency "request_store"
21
22
 
22
23
  # specify any dependencies here; for example:
23
24
  s.add_development_dependency "rspec"
@@ -0,0 +1,23 @@
1
+ input {
2
+ file {
3
+ type => "rails logs"
4
+ path => "/Users/shadab/test_project/logstash_development.log"
5
+ codec => json {
6
+ charset => "UTF-8"
7
+ }
8
+ }
9
+ }
10
+
11
+ output {
12
+ # Print each event to stdout.
13
+ stdout {
14
+ codec => rubydebug
15
+ }
16
+
17
+ elasticsearch {
18
+ # Setting 'embedded' will run a real elasticsearch server inside logstash.
19
+ # This option below saves you from having to run a separate process just
20
+ # for ElasticSearch, so you can get started quicker!
21
+ embedded => true
22
+ }
23
+ }
@@ -176,4 +176,40 @@ describe LogStasher do
176
176
  end
177
177
  end
178
178
  end
179
+
180
+ describe '.store' do
181
+ it "returns a new Hash for each key" do
182
+ expect(LogStasher.store['a'].object_id).to_not be(LogStasher.store['b'].object_id)
183
+ end
184
+
185
+ it "returns the same store if called several time with the same key" do
186
+ expect(LogStasher.store['a'].object_id).to be(LogStasher.store['a'].object_id)
187
+ end
188
+
189
+ end
190
+
191
+ describe ".watch" do
192
+ before(:each) { LogStasher.custom_fields = [] }
193
+
194
+ it "subscribes to the required event" do
195
+ ActiveSupport::Notifications.should_receive(:subscribe).with('event_name')
196
+ LogStasher.watch('event_name')
197
+ end
198
+
199
+ it 'executes the block when receiving an event' do
200
+ probe = lambda {}
201
+ LogStasher.watch('custom.event.foo', &probe)
202
+ expect(probe).to receive(:call)
203
+ ActiveSupport::Notifications.instrument('custom.event.foo', {})
204
+ end
205
+
206
+ describe "store" do
207
+ it 'stores the events in a store with the event\'s name' do
208
+ probe = lambda { |*args, store| store[:foo] = :bar }
209
+ LogStasher.watch('custom.event.bar', &probe)
210
+ ActiveSupport::Notifications.instrument('custom.event.bar', {})
211
+ LogStasher.store['custom.event.bar'].should == {:foo => :bar}
212
+ end
213
+ end
214
+ end
179
215
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstasher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shadab Ahmed
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-07 00:00:00.000000000 Z
11
+ date: 2014-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-event
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: request_store
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'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -88,6 +102,7 @@ files:
88
102
  - lib/logstasher/railtie.rb
89
103
  - lib/logstasher/version.rb
90
104
  - logstasher.gemspec
105
+ - sample_logstash_configurations/quickstart.conf
91
106
  - spec/lib/logstasher/device/redis_spec.rb
92
107
  - spec/lib/logstasher/log_subscriber_spec.rb
93
108
  - spec/lib/logstasher_spec.rb