logstasher 0.6.0 → 0.6.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.
- checksums.yaml +8 -8
- data/lib/logstasher/log_subscriber.rb +5 -4
- data/lib/logstasher/version.rb +1 -1
- metadata +6 -26
- data/.gitignore +0 -5
- data/.rspec +0 -2
- data/.travis.yml +0 -12
- data/Gemfile +0 -15
- data/Guardfile +0 -10
- data/README.md +0 -162
- data/Rakefile +0 -50
- data/logstasher.gemspec +0 -27
- data/sample_logstash_configurations/quickstart.conf +0 -23
- data/spec/lib/logstasher/device/redis_spec.rb +0 -79
- data/spec/lib/logstasher/instrumentation_spec.rb +0 -62
- data/spec/lib/logstasher/log_subscriber_spec.rb +0 -265
- data/spec/lib/logstasher_spec.rb +0 -263
- data/spec/spec_helper.rb +0 -52
- data/spec/support/sample_mailer.rb +0 -16
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YjJhNTIyM2IxMDc5NDU0ZmZjZTNlMzhlZTg1MTRkNzE4NDNkMDQ2OQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWI5OTI4ZDUzYThmMTM3NGJjNjUzY2VhYTc3ZTcwNWExMzFhNzdhZg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Y2FlMTgzZGMxMjk3MDFmOTE2NzM4YTc4ZjJmNTgwMGFmZmVhMTYyYzk5ZjM3
|
10
|
+
YzM1NDVlYjUxYWM5ZGE4OTJkOWU0ZTgxZjEzMWJlNGZhZTYxMzk0NDcxNTJl
|
11
|
+
MDcwMjgzMDQ0NTVmODVhYTEwZDE2ODFiNWJkYTg5NTgwYTMzYmM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
N2E4ZGM1NzU4MTIwZjZlM2RiNzY1NDhiMzE0ZjY1Yjg1YTQxMjA4YTcxNzMx
|
14
|
+
NmEwNTQwZWY0ODYxYzBmNzEwNzZlMDNlZTVkZjExYjlhZjRmYTY1YzcyNzVk
|
15
|
+
YzFhOTQwY2FhNjlkNmVkYzAyYmU0ZGE5ZDYxODI2OTJhYmQwNmM=
|
@@ -109,7 +109,12 @@ module LogStasher
|
|
109
109
|
process_event(event, ['mailer', 'process'])
|
110
110
|
end
|
111
111
|
|
112
|
+
def logger
|
113
|
+
LogStasher.logger
|
114
|
+
end
|
115
|
+
|
112
116
|
private
|
117
|
+
|
113
118
|
def process_event(event, tags)
|
114
119
|
data = LogStasher.request_context.merge(extract_metadata(event.payload))
|
115
120
|
event = LogStash::Event.new('@source' => LogStasher.source, '@fields' => data, '@tags' => tags)
|
@@ -119,9 +124,5 @@ module LogStasher
|
|
119
124
|
def extract_metadata(payload)
|
120
125
|
payload.slice(*MAILER_FIELDS)
|
121
126
|
end
|
122
|
-
|
123
|
-
def logger
|
124
|
-
LogStasher.logger
|
125
|
-
end
|
126
127
|
end
|
127
128
|
end
|
data/lib/logstasher/version.rb
CHANGED
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.6.
|
4
|
+
version: 0.6.1
|
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-
|
11
|
+
date: 2014-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logstash-event
|
@@ -87,13 +87,6 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- .gitignore
|
91
|
-
- .rspec
|
92
|
-
- .travis.yml
|
93
|
-
- Gemfile
|
94
|
-
- Guardfile
|
95
|
-
- README.md
|
96
|
-
- Rakefile
|
97
90
|
- lib/logstasher.rb
|
98
91
|
- lib/logstasher/device/redis.rb
|
99
92
|
- lib/logstasher/log_subscriber.rb
|
@@ -101,16 +94,9 @@ files:
|
|
101
94
|
- lib/logstasher/rails_ext/rack/logger.rb
|
102
95
|
- lib/logstasher/railtie.rb
|
103
96
|
- lib/logstasher/version.rb
|
104
|
-
- logstasher.gemspec
|
105
|
-
- sample_logstash_configurations/quickstart.conf
|
106
|
-
- spec/lib/logstasher/device/redis_spec.rb
|
107
|
-
- spec/lib/logstasher/instrumentation_spec.rb
|
108
|
-
- spec/lib/logstasher/log_subscriber_spec.rb
|
109
|
-
- spec/lib/logstasher_spec.rb
|
110
|
-
- spec/spec_helper.rb
|
111
|
-
- spec/support/sample_mailer.rb
|
112
97
|
homepage: https://github.com/shadabahmed/logstasher
|
113
|
-
licenses:
|
98
|
+
licenses:
|
99
|
+
- MIT
|
114
100
|
metadata: {}
|
115
101
|
post_install_message:
|
116
102
|
rdoc_options: []
|
@@ -127,15 +113,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
113
|
- !ruby/object:Gem::Version
|
128
114
|
version: '0'
|
129
115
|
requirements: []
|
130
|
-
rubyforge_project:
|
116
|
+
rubyforge_project:
|
131
117
|
rubygems_version: 2.2.2
|
132
118
|
signing_key:
|
133
119
|
specification_version: 4
|
134
120
|
summary: Awesome rails logs
|
135
|
-
test_files:
|
136
|
-
- spec/lib/logstasher/device/redis_spec.rb
|
137
|
-
- spec/lib/logstasher/instrumentation_spec.rb
|
138
|
-
- spec/lib/logstasher/log_subscriber_spec.rb
|
139
|
-
- spec/lib/logstasher_spec.rb
|
140
|
-
- spec/spec_helper.rb
|
141
|
-
- spec/support/sample_mailer.rb
|
121
|
+
test_files: []
|
data/.rspec
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in logstasher.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
group :test do
|
7
|
-
gem 'growl'
|
8
|
-
gem 'guard'
|
9
|
-
gem 'guard-rspec'
|
10
|
-
gem 'rails', "~> #{ENV["RAILS_VERSION"] || "3.2.0"}"
|
11
|
-
gem 'rb-fsevent', '~> 0.9'
|
12
|
-
gem 'rcov', :platforms => :mri_18
|
13
|
-
gem 'redis', :require => false
|
14
|
-
gem 'simplecov', :platforms => :mri_19, :require => false
|
15
|
-
end
|
data/Guardfile
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# A sample Guardfile
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
3
|
-
interactor :simple
|
4
|
-
|
5
|
-
guard 'rspec', :version => 2 do
|
6
|
-
watch(%r{^spec/.+_spec\.rb$})
|
7
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
8
|
-
watch('spec/spec_helper.rb') { "spec" }
|
9
|
-
end
|
10
|
-
|
data/README.md
DELETED
@@ -1,162 +0,0 @@
|
|
1
|
-
# Logstasher [](http://badge.fury.io/rb/logstasher) [](https://secure.travis-ci.org/shadabahmed/logstasher)
|
2
|
-
### Awesome Logging for Rails !!
|
3
|
-
|
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
|
-
|
6
|
-
[](https://f.cloud.github.com/assets/830679/2407078/dcde03e8-aa82-11e3-85ac-8c5b3a86676e.png)
|
7
|
-
|
8
|
-
How it's done ?
|
9
|
-
|
10
|
-
By, using these awesome tools:
|
11
|
-
* [Logstash](http://logstash.net) - Store and index your logs
|
12
|
-
* [Kibana](http://kibana.org/) - for awesome visualization. This is optional though, and you can use any other visualizer
|
13
|
-
|
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
|
17
|
-
|
18
|
-
## About logstasher
|
19
|
-
|
20
|
-
This gem purely focuses on how to generate logstash compatible logs i.e. *logstash json event format*, without any overhead. Infact, logstasher logs to a separate log file named `logstash_<environment>.log`.
|
21
|
-
The reason for this separation:
|
22
|
-
* To have a pure json log file
|
23
|
-
* Prevent any logger messages(e.g. info) getting into our pure json logs
|
24
|
-
|
25
|
-
Before **logstasher** :
|
26
|
-
|
27
|
-
```
|
28
|
-
Started GET "/login" for 10.109.10.135 at 2013-04-30 08:59:01 -0400
|
29
|
-
Processing by SessionsController#new as HTML
|
30
|
-
Rendered sessions/new.html.haml within layouts/application (4.3ms)
|
31
|
-
Rendered shared/_javascript.html.haml (0.6ms)
|
32
|
-
Rendered shared/_flashes.html.haml (0.2ms)
|
33
|
-
Rendered shared/_header.html.haml (52.9ms)
|
34
|
-
Rendered shared/_title.html.haml (0.2ms)
|
35
|
-
Rendered shared/_footer.html.haml (0.2ms)
|
36
|
-
Completed 200 OK in 532ms (Views: 62.4ms | ActiveRecord: 0.0ms | ND API: 0.0ms)
|
37
|
-
```
|
38
|
-
|
39
|
-
After **logstasher**:
|
40
|
-
|
41
|
-
```
|
42
|
-
{"@source":"unknown","@tags":["request"],"@fields":{"method":"GET","path":"/","format":"html","controller":"file_servers"
|
43
|
-
,"action":"index","status":200,"duration":28.34,"view":25.96,"db":0.88,"ip":"127.0.0.1","route":"file_servers#index",
|
44
|
-
"parameters":"","ndapi_time":null,"uuid":"e81ecd178ed3b591099f4d489760dfb6","user":"shadab_ahmed@abc.com",
|
45
|
-
"site":"internal"},"@timestamp":"2013-04-30T13:00:46.354500+00:00"}
|
46
|
-
```
|
47
|
-
|
48
|
-
By default, the older format rails request logs are disabled, though you can enable them.
|
49
|
-
|
50
|
-
## Installation
|
51
|
-
|
52
|
-
In your Gemfile:
|
53
|
-
|
54
|
-
gem 'logstasher'
|
55
|
-
|
56
|
-
### Configure your `<environment>.rb` e.g. `development.rb`
|
57
|
-
|
58
|
-
# Enable the logstasher logs for the current environment
|
59
|
-
config.logstasher.enabled = true
|
60
|
-
|
61
|
-
# This line is optional if you do not want to suppress app logs in your <environment>.log
|
62
|
-
config.logstasher.suppress_app_log = false
|
63
|
-
|
64
|
-
# This line is optional, it allows you to set a custom value for the @source field of the log event
|
65
|
-
config.logstasher.source = 'your.arbitrary.source'
|
66
|
-
|
67
|
-
## Logging params hash
|
68
|
-
|
69
|
-
Logstasher can be configured to log the contents of the params hash. When enabled, the contents of the params hash (minus the ActionController internal params)
|
70
|
-
will be added to the log as a deep hash. This can cause conflicts within the Elasticsearch mappings though, so should be enabled with care. Conflicts will occur
|
71
|
-
if different actions (or even different applications logging to the same Elasticsearch cluster) use the same params key, but with a different data type (e.g. a
|
72
|
-
string vs. a hash). This can lead to lost log entries. Enabling this can also significantly increase the size of the Elasticsearch indexes.
|
73
|
-
|
74
|
-
To enable this, add the following to your `<environment>.rb`
|
75
|
-
|
76
|
-
# Enable logging of controller params
|
77
|
-
config.logstasher.log_controller_parameters = true
|
78
|
-
|
79
|
-
## Adding custom fields to the log
|
80
|
-
|
81
|
-
Since some fields are very specific to your application for e.g. *user_name*, so it is left upto you, to add them. Here's how to add those fields to the logs:
|
82
|
-
|
83
|
-
# Create a file - config/initializers/logstasher.rb
|
84
|
-
|
85
|
-
if LogStasher.enabled
|
86
|
-
LogStasher.add_custom_fields do |fields|
|
87
|
-
# This block is run in application_controller context,
|
88
|
-
# so you have access to all controller methods
|
89
|
-
fields[:user] = current_user && current_user.mail
|
90
|
-
fields[:site] = request.path =~ /^\/api/ ? 'api' : 'user'
|
91
|
-
|
92
|
-
# If you are using custom instrumentation, just add it to logstasher custom fields
|
93
|
-
LogStasher.custom_fields << :myapi_runtime
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
## Logging ActionMailer events
|
98
|
-
|
99
|
-
Logstasher can easily log messages from `ActionMailer`, such as incoming/outgoing e-mails and e-mail content generation (Rails >= 4.1).
|
100
|
-
This functionality is automatically enabled. Since the relationship between a concrete HTTP request and a mailer invocation is lost
|
101
|
-
once in an `ActionMailer` instance method, global (per-request) state is kept to correlate HTTP requests and events from other parts
|
102
|
-
of rails, such as `ActionMailer`. Every time a request is invoked, a `request_id` key is added which is present on every `ActionMailer` event.
|
103
|
-
|
104
|
-
Note: Since mailers are executed within the lifetime of a request, they will show up in logs prior to the actual request.
|
105
|
-
|
106
|
-
## Listening to `ActiveSupport::Notifications` events
|
107
|
-
|
108
|
-
It is possible to listen to any `ActiveSupport::Notifications` events and store arbitrary data to be included in the final JSON log entry:
|
109
|
-
|
110
|
-
# In config/initializers/logstasher.rb
|
111
|
-
|
112
|
-
# Watch calls the block with the same arguments than any ActiveSupport::Notification, plus a store
|
113
|
-
LogStasher.watch('some.activesupport.notification') do |name, start, finish, id, payload, store|
|
114
|
-
# Do something
|
115
|
-
store[:count] = 42
|
116
|
-
end
|
117
|
-
|
118
|
-
Would change the log entry to:
|
119
|
-
|
120
|
-
```
|
121
|
-
{"@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"}
|
122
|
-
```
|
123
|
-
|
124
|
-
The store exposed to the blocked passed to `watch` is thread-safe, and reset after each request.
|
125
|
-
By default, the store is only shared between occurences of the same event.
|
126
|
-
You can easily share the same store between different types of notifications, by assigning them to the same event group:
|
127
|
-
|
128
|
-
# In config/initializers/logstasher.rb
|
129
|
-
|
130
|
-
LogStasher.watch('foo.notification', event_group: 'notification') do |*args, store|
|
131
|
-
# Shared store with 'bar.notification'
|
132
|
-
end
|
133
|
-
|
134
|
-
LogStasher.watch('bar.notification', event_group: 'notification') do |*args, store|
|
135
|
-
# Shared store with 'foo.notification'
|
136
|
-
end
|
137
|
-
|
138
|
-
## Quick Setup for Logstash
|
139
|
-
|
140
|
-
* Download logstash from [logstash.net](http://www.logstash.net/)
|
141
|
-
* Use this sample config file: [quickstart.conf](https://github.com/shadabahmed/logstasher/raw/master/sample_logstash_configurations/quickstart.conf)
|
142
|
-
* Start logstash with the following command:
|
143
|
-
```
|
144
|
-
java -jar logstash-1.3.3-flatjar.jar agent -f quickstart.conf -- web
|
145
|
-
```
|
146
|
-
* Visit http://localhost:9292/ to see the Kibana interface and your parsed logs
|
147
|
-
* 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.)
|
148
|
-
|
149
|
-
## Versions
|
150
|
-
All versions require Rails 3.0.x and higher and Ruby 1.9.2+. Tested on Rails 4 and Ruby 2.0
|
151
|
-
|
152
|
-
## Development
|
153
|
-
- Run tests - `rake`
|
154
|
-
- Generate test coverage report - `rake coverage`. Coverage report path - coverage/index.html
|
155
|
-
|
156
|
-
## Copyright
|
157
|
-
|
158
|
-
Copyright (c) 2013 Shadab Ahmed, released under the MIT license
|
159
|
-
|
160
|
-
|
161
|
-
[](https://bitdeli.com/free "Bitdeli Badge")
|
162
|
-
|
data/Rakefile
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
require 'rspec/core/rake_task'
|
3
|
-
|
4
|
-
# Add default task. When you type just rake command this would run. Travis CI runs this. Making this run spec
|
5
|
-
desc 'Default: run specs.'
|
6
|
-
task :default => :spec
|
7
|
-
|
8
|
-
# Defining spec task for running spec
|
9
|
-
desc "Run specs"
|
10
|
-
RSpec::Core::RakeTask.new('spec') do |spec|
|
11
|
-
# Pattern filr for spec files to run. This is default btw.
|
12
|
-
spec.pattern = "./spec/**/*_spec.rb"
|
13
|
-
end
|
14
|
-
|
15
|
-
# Run the rdoc task to generate rdocs for this gem
|
16
|
-
require 'rdoc/task'
|
17
|
-
RDoc::Task.new do |rdoc|
|
18
|
-
require "logstasher/version"
|
19
|
-
version = LogStasher::VERSION
|
20
|
-
|
21
|
-
rdoc.rdoc_dir = 'rdoc'
|
22
|
-
rdoc.title = "logstasher #{version}"
|
23
|
-
rdoc.rdoc_files.include('README*')
|
24
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
-
end
|
26
|
-
|
27
|
-
# Code coverage tasks. Different for Ruby 1.8 vs 1.9
|
28
|
-
if RUBY_VERSION =~ /^1\.8/
|
29
|
-
# Ruby 1.8 uses rcov for code coverage
|
30
|
-
RSpec::Core::RakeTask.new(:coverage) do |spec|
|
31
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
-
spec.rcov = true
|
33
|
-
spec.rcov_opts = %w{--exclude pkg\/,spec\/,features\/}
|
34
|
-
end
|
35
|
-
else
|
36
|
-
# Ruby 1.9+ using simplecov. Note: Simplecov config defined in spec_helper
|
37
|
-
desc "Code coverage detail"
|
38
|
-
task :coverage do
|
39
|
-
ENV['COVERAGE'] = "true"
|
40
|
-
Rake::Task['spec'].execute
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
task :console do
|
45
|
-
require 'irb'
|
46
|
-
require 'irb/completion'
|
47
|
-
require 'logstasher'
|
48
|
-
ARGV.clear
|
49
|
-
IRB.start
|
50
|
-
end
|
data/logstasher.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "logstasher/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "logstasher"
|
7
|
-
s.version = LogStasher::VERSION
|
8
|
-
s.authors = ["Shadab Ahmed"]
|
9
|
-
s.email = ["shadab.ansari@gmail.com"]
|
10
|
-
s.homepage = "https://github.com/shadabahmed/logstasher"
|
11
|
-
s.summary = %q{Awesome rails logs}
|
12
|
-
s.description = %q{Awesome rails logs}
|
13
|
-
|
14
|
-
s.rubyforge_project = "logstasher"
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = ["lib"]
|
20
|
-
s.add_runtime_dependency "logstash-event", ["~> 1.1.0"]
|
21
|
-
s.add_runtime_dependency "request_store"
|
22
|
-
|
23
|
-
# specify any dependencies here; for example:
|
24
|
-
s.add_development_dependency "rspec", [">= 2.14"]
|
25
|
-
s.add_development_dependency("bundler", [">= 1.0.0"])
|
26
|
-
s.add_development_dependency("rails", [">= 3.0"])
|
27
|
-
end
|
@@ -1,23 +0,0 @@
|
|
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
|
-
}
|
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'logstasher/device/redis'
|
4
|
-
|
5
|
-
describe LogStasher::Device::Redis do
|
6
|
-
|
7
|
-
let(:redis_mock) { double('Redis') }
|
8
|
-
|
9
|
-
let(:default_options) {{
|
10
|
-
key: 'logstash',
|
11
|
-
data_type: 'list'
|
12
|
-
}}
|
13
|
-
|
14
|
-
it 'has default options' do
|
15
|
-
device = LogStasher::Device::Redis.new
|
16
|
-
expect(device.options).to eq(default_options)
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'creates a redis instance' do
|
20
|
-
expect(::Redis).to receive(:new).with({})
|
21
|
-
LogStasher::Device::Redis.new()
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'assumes unknown options are for redis' do
|
25
|
-
expect(::Redis).to receive(:new).with(hash_including(db: '0'))
|
26
|
-
device = LogStasher::Device::Redis.new(db: '0')
|
27
|
-
expect(device.redis_options).to eq(db: '0')
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'has a key' do
|
31
|
-
device = LogStasher::Device::Redis.new(key: 'the_key')
|
32
|
-
expect(device.key).to eq('the_key')
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'has a data_type' do
|
36
|
-
device = LogStasher::Device::Redis.new(data_type: 'channel')
|
37
|
-
expect(device.data_type).to eq('channel')
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'does not allow unsupported data types' do
|
41
|
-
expect {
|
42
|
-
device = LogStasher::Device::Redis.new(data_type: 'blargh')
|
43
|
-
}.to raise_error()
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'quits the redis connection on #close' do
|
47
|
-
device = LogStasher::Device::Redis.new
|
48
|
-
expect(device.redis).to receive(:quit)
|
49
|
-
device.close
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'works as a logger device' do
|
53
|
-
device = LogStasher::Device::Redis.new
|
54
|
-
expect(device).to receive(:write).with('blargh')
|
55
|
-
logger = Logger.new(device)
|
56
|
-
logger << 'blargh'
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '#write' do
|
60
|
-
it "rpushes logs onto a list" do
|
61
|
-
device = LogStasher::Device::Redis.new(data_type: 'list')
|
62
|
-
expect(device.redis).to receive(:rpush).with('logstash', 'the log')
|
63
|
-
device.write('the log')
|
64
|
-
end
|
65
|
-
|
66
|
-
it "rpushes logs onto a custom key" do
|
67
|
-
device = LogStasher::Device::Redis.new(data_type: 'list', key: 'custom')
|
68
|
-
expect(device.redis).to receive(:rpush).with('custom', 'the log')
|
69
|
-
device.write('the log')
|
70
|
-
end
|
71
|
-
|
72
|
-
it "publishes logs onto a channel" do
|
73
|
-
device = LogStasher::Device::Redis.new(data_type: 'channel', key: 'custom')
|
74
|
-
expect(device.redis).to receive(:publish).with('custom', 'the log')
|
75
|
-
device.write('the log')
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'logstasher/rails_ext/action_controller/metal/instrumentation'
|
3
|
-
|
4
|
-
describe ActionController::Base do
|
5
|
-
before :each do
|
6
|
-
subject.request = ActionDispatch::TestRequest.new
|
7
|
-
subject.response = ActionDispatch::TestResponse.new
|
8
|
-
|
9
|
-
def subject.index(*args)
|
10
|
-
render text: 'OK'
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe ".process_action" do
|
15
|
-
it "adds default fields to payload" do
|
16
|
-
expect(LogStasher).to receive(:add_default_fields_to_payload).once
|
17
|
-
expect(LogStasher).to receive(:add_default_fields_to_request_context).once
|
18
|
-
subject.process_action(:index)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "creates the request context before processing" do
|
22
|
-
LogStasher.request_context[:some_key] = 'value'
|
23
|
-
expect(LogStasher).to receive(:clear_request_context).once.and_call_original
|
24
|
-
expect {
|
25
|
-
subject.process_action(:index)
|
26
|
-
}.to change { LogStasher.request_context }
|
27
|
-
end
|
28
|
-
|
29
|
-
it "notifies rails of a request coming in" do
|
30
|
-
expect(ActiveSupport::Notifications).to receive(:instrument).with("start_processing.action_controller", anything).once
|
31
|
-
expect(ActiveSupport::Notifications).to receive(:instrument).with("process_action.action_controller", anything).once
|
32
|
-
subject.process_action(:index)
|
33
|
-
end
|
34
|
-
|
35
|
-
context "request context has custom fields defined" do
|
36
|
-
before :each do
|
37
|
-
LogStasher.add_custom_fields_to_request_context do |fields|
|
38
|
-
fields[:some_field] = 'value'
|
39
|
-
end
|
40
|
-
|
41
|
-
ActiveSupport::Notifications.subscribe('process_action.action_controller') do |_, _, _, _, payload|
|
42
|
-
@payload = payload
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should retain the value in the request context" do
|
47
|
-
subject.process_action(:index)
|
48
|
-
end
|
49
|
-
|
50
|
-
after :each do
|
51
|
-
expect(@payload[:some_field]).to eq('value')
|
52
|
-
|
53
|
-
ActionController::Metal.class_eval do
|
54
|
-
undef logstasher_add_custom_fields_to_request_context
|
55
|
-
end
|
56
|
-
ActionController::Base.class_eval do
|
57
|
-
undef logstasher_add_custom_fields_to_request_context
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,265 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe LogStasher::RequestLogSubscriber do
|
4
|
-
let(:log_output) {StringIO.new}
|
5
|
-
let(:logger) {
|
6
|
-
logger = Logger.new(log_output)
|
7
|
-
logger.formatter = ->(_, _, _, msg) {
|
8
|
-
msg
|
9
|
-
}
|
10
|
-
def log_output.json
|
11
|
-
JSON.parse! self.string
|
12
|
-
end
|
13
|
-
logger
|
14
|
-
}
|
15
|
-
before do
|
16
|
-
LogStasher.logger = logger
|
17
|
-
LogStasher.log_controller_parameters = true
|
18
|
-
LogStasher.custom_fields = []
|
19
|
-
end
|
20
|
-
after do
|
21
|
-
LogStasher.log_controller_parameters = false
|
22
|
-
end
|
23
|
-
|
24
|
-
let(:subscriber) {LogStasher::RequestLogSubscriber.new}
|
25
|
-
let(:event) {
|
26
|
-
ActiveSupport::Notifications::Event.new(
|
27
|
-
'process_action.action_controller', Time.now, Time.now, 2, {
|
28
|
-
status: 200, format: 'application/json', method: 'GET', path: '/home?foo=bar', params: {
|
29
|
-
:controller => 'home', :action => 'index', 'foo' => 'bar'
|
30
|
-
}.with_indifferent_access, db_runtime: 0.02, view_runtime: 0.01
|
31
|
-
}
|
32
|
-
)
|
33
|
-
}
|
34
|
-
|
35
|
-
let(:redirect) {
|
36
|
-
ActiveSupport::Notifications::Event.new(
|
37
|
-
'redirect_to.action_controller', Time.now, Time.now, 1, location: 'http://example.com', status: 302
|
38
|
-
)
|
39
|
-
}
|
40
|
-
|
41
|
-
describe '.process_action' do
|
42
|
-
let!(:request_subscriber) { @request_subscriber ||= LogStasher::RequestLogSubscriber.new() }
|
43
|
-
let(:payload) { {} }
|
44
|
-
let(:event) { double(:payload => payload) }
|
45
|
-
let(:logger) { double }
|
46
|
-
let(:json) { "{\"@source\":\"unknown\",\"@tags\":[\"request\"],\"@fields\":{\"request\":true,\"status\":true,\"runtimes\":true,\"location\":true,\"exception\":true,\"custom\":true},\"@timestamp\":\"timestamp\"}\n" }
|
47
|
-
before do
|
48
|
-
allow(LogStasher).to receive(:logger).and_return(logger)
|
49
|
-
allow(LogStash::Time).to receive(:now).and_return('timestamp')
|
50
|
-
end
|
51
|
-
it 'calls all extractors and outputs the json' do
|
52
|
-
expect(request_subscriber).to receive(:extract_request).with(payload).and_return({:request => true})
|
53
|
-
expect(request_subscriber).to receive(:extract_status).with(payload).and_return({:status => true})
|
54
|
-
expect(request_subscriber).to receive(:runtimes).with(event).and_return({:runtimes => true})
|
55
|
-
expect(request_subscriber).to receive(:location).with(event).and_return({:location => true})
|
56
|
-
expect(request_subscriber).to receive(:extract_exception).with(payload).and_return({:exception => true})
|
57
|
-
expect(request_subscriber).to receive(:extract_custom_fields).with(payload).and_return({:custom => true})
|
58
|
-
expect(LogStasher.logger).to receive(:<<).with(json)
|
59
|
-
request_subscriber.process_action(event)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe 'logstasher output' do
|
64
|
-
|
65
|
-
it "should contain request tag" do
|
66
|
-
subscriber.process_action(event)
|
67
|
-
expect(log_output.json['@tags']).to include 'request'
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should contain HTTP method" do
|
71
|
-
subscriber.process_action(event)
|
72
|
-
expect(log_output.json['@fields']['method']).to eq 'GET'
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should include the path in the log output" do
|
76
|
-
subscriber.process_action(event)
|
77
|
-
expect(log_output.json['@fields']['path']).to eq '/home'
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should include the format in the log output" do
|
81
|
-
subscriber.process_action(event)
|
82
|
-
expect(log_output.json['@fields']['format']).to eq 'application/json'
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should include the status code" do
|
86
|
-
subscriber.process_action(event)
|
87
|
-
expect(log_output.json['@fields']['status']).to eq 200
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should include the controller" do
|
91
|
-
subscriber.process_action(event)
|
92
|
-
expect(log_output.json['@fields']['controller']).to eq 'home'
|
93
|
-
end
|
94
|
-
|
95
|
-
it "should include the action" do
|
96
|
-
subscriber.process_action(event)
|
97
|
-
expect(log_output.json['@fields']['action']).to eq 'index'
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should include the view rendering time" do
|
101
|
-
subscriber.process_action(event)
|
102
|
-
expect(log_output.json['@fields']['view']).to eq 0.01
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should include the database rendering time" do
|
106
|
-
subscriber.process_action(event)
|
107
|
-
expect(log_output.json['@fields']['db']).to eq 0.02
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should add a valid status when an exception occurred" do
|
111
|
-
begin
|
112
|
-
raise AbstractController::ActionNotFound.new('Could not find an action')
|
113
|
-
# working this in rescue to get access to $! variable
|
114
|
-
rescue
|
115
|
-
event.payload[:status] = nil
|
116
|
-
event.payload[:exception] = ['AbstractController::ActionNotFound', 'Route not found']
|
117
|
-
subscriber.process_action(event)
|
118
|
-
expect(log_output.json['@fields']['status']).to be >= 400
|
119
|
-
expect(log_output.json['@fields']['error']).to be =~ /AbstractController::ActionNotFound.*Route not found.*logstasher\/spec\/lib\/logstasher\/log_subscriber_spec\.rb/m
|
120
|
-
expect(log_output.json['@tags']).to include 'request'
|
121
|
-
expect(log_output.json['@tags']).to include 'exception'
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
it "should return an unknown status when no status or exception is found" do
|
126
|
-
event.payload[:status] = nil
|
127
|
-
event.payload[:exception] = nil
|
128
|
-
subscriber.process_action(event)
|
129
|
-
expect(log_output.json['@fields']['status']).to eq 0
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "with a redirect" do
|
133
|
-
before do
|
134
|
-
Thread.current[:logstasher_location] = "http://www.example.com"
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should add the location to the log line" do
|
138
|
-
subscriber.process_action(event)
|
139
|
-
expect(log_output.json['@fields']['location']).to eq 'http://www.example.com'
|
140
|
-
end
|
141
|
-
|
142
|
-
it "should remove the thread local variable" do
|
143
|
-
subscriber.process_action(event)
|
144
|
-
expect(Thread.current[:logstasher_location]).to be_nil
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should not include a location by default" do
|
149
|
-
subscriber.process_action(event)
|
150
|
-
expect(log_output.json['@fields']['location']).to be_nil
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe "with append_custom_params block specified" do
|
155
|
-
let(:request) { double(:remote_ip => '10.0.0.1', :env => {})}
|
156
|
-
it "should add default custom data to the output" do
|
157
|
-
allow(request).to receive_messages(:params => event.payload[:params])
|
158
|
-
LogStasher.add_default_fields_to_payload(event.payload, request)
|
159
|
-
subscriber.process_action(event)
|
160
|
-
expect(log_output.json['@fields']['ip']).to eq '10.0.0.1'
|
161
|
-
expect(log_output.json['@fields']['route']).to eq'home#index'
|
162
|
-
expect(log_output.json['@fields']['parameters']).to eq 'foo' => 'bar'
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
describe "with append_custom_params block specified" do
|
167
|
-
before do
|
168
|
-
allow(LogStasher).to receive(:add_custom_fields) do |&block|
|
169
|
-
@block = block
|
170
|
-
end
|
171
|
-
LogStasher.add_custom_fields do |payload|
|
172
|
-
payload[:user] = 'user'
|
173
|
-
end
|
174
|
-
LogStasher.custom_fields += [:user]
|
175
|
-
end
|
176
|
-
|
177
|
-
it "should add the custom data to the output" do
|
178
|
-
@block.call(event.payload)
|
179
|
-
subscriber.process_action(event)
|
180
|
-
expect(log_output.json['@fields']['user']).to eq 'user'
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
describe "when processing a redirect" do
|
185
|
-
it "should store the location in a thread local variable" do
|
186
|
-
subscriber.redirect_to(redirect)
|
187
|
-
expect(Thread.current[:logstasher_location]).to eq "http://example.com"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe LogStasher::MailerLogSubscriber do
|
193
|
-
let(:log_output) {StringIO.new}
|
194
|
-
let(:logger) {
|
195
|
-
logger = Logger.new(log_output)
|
196
|
-
logger.formatter = ->(_, _, _, msg) {
|
197
|
-
msg
|
198
|
-
}
|
199
|
-
def log_output.json
|
200
|
-
JSON.parse!(self.string.split("\n").last)
|
201
|
-
end
|
202
|
-
logger
|
203
|
-
}
|
204
|
-
|
205
|
-
before :all do
|
206
|
-
SampleMailer.delivery_method = :test
|
207
|
-
LogStasher::MailerLogSubscriber.attach_to(:action_mailer)
|
208
|
-
end
|
209
|
-
|
210
|
-
before do
|
211
|
-
LogStasher.logger = logger
|
212
|
-
expect(LogStasher.request_context).to receive(:merge).at_most(2).times.and_call_original
|
213
|
-
end
|
214
|
-
|
215
|
-
let :message do
|
216
|
-
Mail.new do
|
217
|
-
from 'some-dude@example.com'
|
218
|
-
to 'some-other-dude@example.com'
|
219
|
-
subject 'Goodbye'
|
220
|
-
body 'LOL'
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'receive an e-mail' do
|
225
|
-
SampleMailer.receive(message.encoded)
|
226
|
-
log_output.json.tap do |json|
|
227
|
-
expect(json['@source']).to eq(LogStasher.source)
|
228
|
-
expect(json['@tags']).to eq(['mailer', 'receive'])
|
229
|
-
json['@fields'].tap do |fields|
|
230
|
-
expect(fields['mailer']).to eq('SampleMailer')
|
231
|
-
expect(fields['from']).to eq(['some-dude@example.com'])
|
232
|
-
expect(fields['to']).to eq(['some-other-dude@example.com'])
|
233
|
-
expect(fields['message_id']).to eq(message.message_id)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'deliver an outgoing e-mail' do
|
239
|
-
email = SampleMailer.welcome
|
240
|
-
|
241
|
-
if version = ENV['RAILS_VERSION'] and version >= '4.1'
|
242
|
-
log_output.json.tap do |json|
|
243
|
-
expect(json['@source']).to eq(LogStasher.source)
|
244
|
-
expect(json['@tags']).to eq(['mailer', 'process'])
|
245
|
-
json['@fields'].tap do |fields|
|
246
|
-
expect(fields['mailer']).to eq('SampleMailer')
|
247
|
-
expect(fields['action']).to eq('welcome')
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
email.deliver
|
253
|
-
log_output.json.tap do |json|
|
254
|
-
expect(json['@source']).to eq(LogStasher.source)
|
255
|
-
expect(json['@tags']).to eq(['mailer', 'deliver'])
|
256
|
-
json['@fields'].tap do |fields|
|
257
|
-
expect(fields['mailer']).to eq('SampleMailer')
|
258
|
-
expect(fields['from']).to eq(['some-dude@example.com'])
|
259
|
-
expect(fields['to']).to eq(['some-other-dude@example.com'])
|
260
|
-
# Message-Id appears not to be yet available at this point in time.
|
261
|
-
expect(fields['message_id']).to be_nil
|
262
|
-
end
|
263
|
-
end
|
264
|
-
end
|
265
|
-
end
|
data/spec/lib/logstasher_spec.rb
DELETED
@@ -1,263 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe LogStasher do
|
4
|
-
describe "when removing Rails' log subscribers" do
|
5
|
-
after do
|
6
|
-
ActionController::LogSubscriber.attach_to :action_controller
|
7
|
-
ActionView::LogSubscriber.attach_to :action_view
|
8
|
-
ActionMailer::LogSubscriber.attach_to :action_mailer
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should remove subscribers for controller events" do
|
12
|
-
expect {
|
13
|
-
LogStasher.remove_existing_log_subscriptions
|
14
|
-
}.to change {
|
15
|
-
ActiveSupport::Notifications.notifier.listeners_for('process_action.action_controller')
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should remove subscribers for all events" do
|
20
|
-
expect {
|
21
|
-
LogStasher.remove_existing_log_subscriptions
|
22
|
-
}.to change {
|
23
|
-
ActiveSupport::Notifications.notifier.listeners_for('render_template.action_view')
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should remove subscribsers for mailer events" do
|
28
|
-
expect {
|
29
|
-
LogStasher.remove_existing_log_subscriptions
|
30
|
-
}.to change {
|
31
|
-
ActiveSupport::Notifications.notifier.listeners_for('deliver.action_mailer')
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
it "shouldn't remove subscribers that aren't from Rails" do
|
36
|
-
blk = -> {}
|
37
|
-
ActiveSupport::Notifications.subscribe("process_action.action_controller", &blk)
|
38
|
-
LogStasher.remove_existing_log_subscriptions
|
39
|
-
listeners = ActiveSupport::Notifications.notifier.listeners_for('process_action.action_controller')
|
40
|
-
expect(listeners).to_not be_empty
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe '.appened_default_info_to_payload' do
|
45
|
-
let(:params) { {'a' => '1', 'b' => 2, 'action' => 'action', 'controller' => 'test'}.with_indifferent_access }
|
46
|
-
let(:payload) { {:params => params} }
|
47
|
-
let(:request) { double(:params => params, :remote_ip => '10.0.0.1', :env => {})}
|
48
|
-
after do
|
49
|
-
LogStasher.custom_fields = []
|
50
|
-
LogStasher.log_controller_parameters = false
|
51
|
-
end
|
52
|
-
it 'appends default parameters to payload' do
|
53
|
-
LogStasher.log_controller_parameters = true
|
54
|
-
LogStasher.custom_fields = []
|
55
|
-
LogStasher.add_default_fields_to_payload(payload, request)
|
56
|
-
expect(payload[:ip]).to eq '10.0.0.1'
|
57
|
-
expect(payload[:route]).to eq 'test#action'
|
58
|
-
expect(payload[:parameters]).to eq 'a' => '1', 'b' => 2
|
59
|
-
expect(LogStasher.custom_fields).to eq [:ip, :route, :request_id, :parameters]
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'does not include parameters when not configured to' do
|
63
|
-
LogStasher.custom_fields = []
|
64
|
-
LogStasher.add_default_fields_to_payload(payload, request)
|
65
|
-
expect(payload).to_not have_key(:parameters)
|
66
|
-
expect(LogStasher.custom_fields).to eq [:ip, :route, :request_id]
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe '.append_custom_params' do
|
71
|
-
let(:block) { ->(_, _){} }
|
72
|
-
it 'defines a method in ActionController::Base' do
|
73
|
-
expect(ActionController::Base).to receive(:send).with(:define_method, :logtasher_add_custom_fields_to_payload, &block)
|
74
|
-
LogStasher.add_custom_fields(&block)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe '.add_custom_fields_to_request_context' do
|
79
|
-
let(:block) { ->(_, _){} }
|
80
|
-
it 'defines a method in ActionController::Base' do
|
81
|
-
expect(ActionController::Base).to receive(:send).with(:define_method, :logstasher_add_custom_fields_to_request_context, &block)
|
82
|
-
expect(ActionController::Metal).to receive(:send).with(:define_method, :logstasher_add_custom_fields_to_request_context, &block)
|
83
|
-
LogStasher.add_custom_fields_to_request_context(&block)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
describe '.add_default_fields_to_request_context' do
|
88
|
-
it 'adds a request_id to the request context' do
|
89
|
-
LogStasher.clear_request_context
|
90
|
-
LogStasher.add_default_fields_to_request_context(double(env: {'action_dispatch.request_id' => 'lol'}))
|
91
|
-
expect(LogStasher.request_context).to eq({ request_id: 'lol' })
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
shared_examples 'setup' do
|
96
|
-
let(:logstasher_source) { nil }
|
97
|
-
let(:logstasher_config) { double(:logger => logger, :log_level => 'warn', :log_controller_parameters => nil, :source => logstasher_source, :logger_path => logger_path) }
|
98
|
-
let(:config) { double(:logstasher => logstasher_config) }
|
99
|
-
let(:app) { double(:config => config) }
|
100
|
-
before do
|
101
|
-
@previous_source = LogStasher.source
|
102
|
-
allow(config).to receive_messages(:action_dispatch => double(:rack_cache => false))
|
103
|
-
allow_message_expectations_on_nil
|
104
|
-
end
|
105
|
-
after { LogStasher.source = @previous_source } # Need to restore old source for specs
|
106
|
-
it 'defines a method in ActionController::Base' do
|
107
|
-
expect(LogStasher).to receive(:require).with('logstasher/rails_ext/action_controller/metal/instrumentation')
|
108
|
-
expect(LogStasher).to receive(:require).with('logstash-event')
|
109
|
-
expect(LogStasher).to receive(:suppress_app_logs).with(app)
|
110
|
-
expect(LogStasher::RequestLogSubscriber).to receive(:attach_to).with(:action_controller)
|
111
|
-
expect(LogStasher::MailerLogSubscriber).to receive(:attach_to).with(:action_mailer)
|
112
|
-
expect(logger).to receive(:level=).with('warn')
|
113
|
-
LogStasher.setup(app)
|
114
|
-
expect(LogStasher.source).to eq (logstasher_source || 'unknown')
|
115
|
-
expect(LogStasher).to be_enabled
|
116
|
-
expect(LogStasher.custom_fields).to be_empty
|
117
|
-
expect(LogStasher.log_controller_parameters).to eq false
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe '.setup' do
|
122
|
-
let(:logger) { double }
|
123
|
-
let(:logger_path) { nil }
|
124
|
-
|
125
|
-
describe 'with source set' do
|
126
|
-
let(:logstasher_source) { 'foo' }
|
127
|
-
it_behaves_like 'setup'
|
128
|
-
end
|
129
|
-
|
130
|
-
describe 'without source set (default behaviour)' do
|
131
|
-
let(:logstasher_source) { nil }
|
132
|
-
it_behaves_like 'setup'
|
133
|
-
end
|
134
|
-
|
135
|
-
describe 'with customized logging' do
|
136
|
-
let(:logger) { nil }
|
137
|
-
|
138
|
-
context 'with no logger passed in' do
|
139
|
-
before { expect(LogStasher).to receive(:new_logger).with('/log/logstash_test.log') }
|
140
|
-
it_behaves_like 'setup'
|
141
|
-
end
|
142
|
-
|
143
|
-
context 'with custom logger path passed in' do
|
144
|
-
let(:logger_path) { double }
|
145
|
-
|
146
|
-
before { expect(LogStasher).to receive(:new_logger).with(logger_path) }
|
147
|
-
it_behaves_like 'setup'
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe '.suppress_app_logs' do
|
153
|
-
let(:logstasher_config){ double(:logstasher => double(:suppress_app_log => true))}
|
154
|
-
let(:app){ double(:config => logstasher_config)}
|
155
|
-
it 'removes existing subscription if enabled' do
|
156
|
-
expect(LogStasher).to receive(:require).with('logstasher/rails_ext/rack/logger')
|
157
|
-
expect(LogStasher).to receive(:remove_existing_log_subscriptions)
|
158
|
-
LogStasher.suppress_app_logs(app)
|
159
|
-
end
|
160
|
-
|
161
|
-
context 'when disabled' do
|
162
|
-
let(:logstasher_config){ double(:logstasher => double(:suppress_app_log => false)) }
|
163
|
-
it 'does not remove existing subscription' do
|
164
|
-
expect(LogStasher).to_not receive(:remove_existing_log_subscriptions)
|
165
|
-
LogStasher.suppress_app_logs(app)
|
166
|
-
end
|
167
|
-
|
168
|
-
describe "backward compatibility" do
|
169
|
-
context 'with spelling "supress_app_log"' do
|
170
|
-
let(:logstasher_config){ double(:logstasher => double(:suppress_app_log => nil, :supress_app_log => false)) }
|
171
|
-
it 'does not remove existing subscription' do
|
172
|
-
expect(LogStasher).to_not receive(:remove_existing_log_subscriptions)
|
173
|
-
LogStasher.suppress_app_logs(app)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
describe '.appended_params' do
|
181
|
-
it 'returns the stored var in current thread' do
|
182
|
-
Thread.current[:logstasher_custom_fields] = :test
|
183
|
-
expect(LogStasher.custom_fields).to eq :test
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
describe '.appended_params=' do
|
188
|
-
it 'returns the stored var in current thread' do
|
189
|
-
LogStasher.custom_fields = :test
|
190
|
-
expect(Thread.current[:logstasher_custom_fields]).to eq :test
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
describe '.log' do
|
195
|
-
let(:logger) { double() }
|
196
|
-
before do
|
197
|
-
LogStasher.logger = logger
|
198
|
-
allow(LogStash::Time).to receive_messages(:now => 'timestamp')
|
199
|
-
allow_message_expectations_on_nil
|
200
|
-
end
|
201
|
-
it 'adds to log with specified level' do
|
202
|
-
expect(logger).to receive(:send).with('warn?').and_return(true)
|
203
|
-
expect(logger).to receive(:send).with('warn',"{\"@source\":\"unknown\",\"@tags\":[\"log\"],\"@fields\":{\"message\":\"WARNING\",\"level\":\"warn\"},\"@timestamp\":\"timestamp\"}")
|
204
|
-
LogStasher.log('warn', 'WARNING')
|
205
|
-
end
|
206
|
-
context 'with a source specified' do
|
207
|
-
before :each do
|
208
|
-
LogStasher.source = 'foo'
|
209
|
-
end
|
210
|
-
it 'sets the correct source' do
|
211
|
-
expect(logger).to receive(:send).with('warn?').and_return(true)
|
212
|
-
expect(logger).to receive(:send).with('warn',"{\"@source\":\"foo\",\"@tags\":[\"log\"],\"@fields\":{\"message\":\"WARNING\",\"level\":\"warn\"},\"@timestamp\":\"timestamp\"}")
|
213
|
-
LogStasher.log('warn', 'WARNING')
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
%w( fatal error warn info debug unknown ).each do |severity|
|
219
|
-
describe ".#{severity}" do
|
220
|
-
let(:message) { "This is a #{severity} message" }
|
221
|
-
it 'should log with specified level' do
|
222
|
-
expect(LogStasher).to receive(:log).with(severity.to_sym, message)
|
223
|
-
LogStasher.send(severity, message )
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
describe '.store' do
|
229
|
-
it "returns a new Hash for each key" do
|
230
|
-
expect(LogStasher.store['a'].object_id).to_not be(LogStasher.store['b'].object_id)
|
231
|
-
end
|
232
|
-
|
233
|
-
it "returns the same store if called several time with the same key" do
|
234
|
-
expect(LogStasher.store['a'].object_id).to be(LogStasher.store['a'].object_id)
|
235
|
-
end
|
236
|
-
|
237
|
-
end
|
238
|
-
|
239
|
-
describe ".watch" do
|
240
|
-
before(:each) { LogStasher.custom_fields = [] }
|
241
|
-
|
242
|
-
it "subscribes to the required event" do
|
243
|
-
expect(ActiveSupport::Notifications).to receive(:subscribe).with('event_name')
|
244
|
-
LogStasher.watch('event_name')
|
245
|
-
end
|
246
|
-
|
247
|
-
it 'executes the block when receiving an event' do
|
248
|
-
probe = lambda {}
|
249
|
-
LogStasher.watch('custom.event.foo', &probe)
|
250
|
-
expect(probe).to receive(:call)
|
251
|
-
ActiveSupport::Notifications.instrument('custom.event.foo', {})
|
252
|
-
end
|
253
|
-
|
254
|
-
describe "store" do
|
255
|
-
it 'stores the events in a store with the event\'s name' do
|
256
|
-
probe = lambda { |*args, store| store[:foo] = :bar }
|
257
|
-
LogStasher.watch('custom.event.bar', &probe)
|
258
|
-
ActiveSupport::Notifications.instrument('custom.event.bar', {})
|
259
|
-
expect(LogStasher.store['custom.event.bar']).to eq :foo => :bar
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
# Notice there is a .rspec file in the root folder. It defines rspec arguments
|
2
|
-
|
3
|
-
# Ruby 1.9 uses simplecov. The ENV['COVERAGE'] is set when rake coverage is run in ruby 1.9
|
4
|
-
if ENV['COVERAGE']
|
5
|
-
require 'simplecov'
|
6
|
-
SimpleCov.start do
|
7
|
-
# Remove the spec folder from coverage. By default all code files are included. For more config options see
|
8
|
-
# https://github.com/colszowka/simplecov
|
9
|
-
add_filter File.expand_path('../../spec', __FILE__)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# Modify load path so you can require 'ogstasher directly.
|
14
|
-
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
15
|
-
|
16
|
-
require 'rubygems'
|
17
|
-
# Loads bundler setup tasks. Now if I run spec without installing gems then it would say gem not installed and
|
18
|
-
# do bundle install instead of ugly load error on require.
|
19
|
-
require 'bundler/setup'
|
20
|
-
|
21
|
-
# This will require me all the gems automatically for the groups. If I do only .setup then I will have to require gems
|
22
|
-
# manually. Note that you have still have to require some gems if they are part of bigger gem like ActiveRecord which is
|
23
|
-
# part of Rails. You can say :require => false in gemfile to always use explicit requiring
|
24
|
-
Bundler.require(:default, :test)
|
25
|
-
|
26
|
-
Dir[File.join("./spec/support/**/*.rb")].each { |f| require f }
|
27
|
-
|
28
|
-
# Set Rails environment as test
|
29
|
-
ENV['RAILS_ENV'] = 'test'
|
30
|
-
|
31
|
-
require 'action_pack'
|
32
|
-
require 'action_controller'
|
33
|
-
require 'logstasher'
|
34
|
-
require 'active_support/notifications'
|
35
|
-
require 'active_support/core_ext/string'
|
36
|
-
require 'active_support/log_subscriber'
|
37
|
-
require 'action_controller/log_subscriber'
|
38
|
-
require 'action_view/log_subscriber'
|
39
|
-
require 'active_support/core_ext/hash/except'
|
40
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
41
|
-
require 'active_support/core_ext/hash/slice'
|
42
|
-
require 'active_support/core_ext/string'
|
43
|
-
require 'active_support/core_ext/time/zones'
|
44
|
-
require 'abstract_controller/base'
|
45
|
-
require 'action_mailer'
|
46
|
-
require 'logger'
|
47
|
-
require 'logstash-event'
|
48
|
-
|
49
|
-
RSpec.configure do |config|
|
50
|
-
config.run_all_when_everything_filtered = true
|
51
|
-
config.filter_run :focus
|
52
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'action_mailer'
|
2
|
-
|
3
|
-
class SampleMailer < ActionMailer::Base
|
4
|
-
def welcome
|
5
|
-
mail(from: 'some-dude@example.com', to: 'some-other-dude@example.com', subject: 'Hello, there') do |format|
|
6
|
-
format.text { render plain: 'OK' }
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def receive(email)
|
11
|
-
end
|
12
|
-
|
13
|
-
def _render_template(_)
|
14
|
-
""
|
15
|
-
end
|
16
|
-
end
|