rack-logstasher 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p484
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rack-logstasher.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Alex Tomlins
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,31 @@
1
+ # Rack::Logstasher
2
+
3
+ Rack middleware to log requests in logstash json event format
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rack-logstasher'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rack-logstasher
18
+
19
+ ## Usage
20
+
21
+ Add this to the middleware stack. e.g.
22
+
23
+ use Rask::Logstasher::Logger, Logger.new("/path/to/logfile.json.log")
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ require "gem_publisher"
9
+ task :publish_gem do |t|
10
+ gem = GemPublisher.publish_if_updated("rack-logstasher.gemspec", :rubygems)
11
+ puts "Published #{gem}" if gem
12
+ end
data/jenkins.sh ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/bash -x
2
+ set -e
3
+
4
+ rm -f Gemfile.lock
5
+ git clean -fdx
6
+
7
+ bundle install --path "${HOME}/bundles/${JOB_NAME}"
8
+
9
+ bundle exec rake
10
+ bundle exec rake publish_gem
@@ -0,0 +1,57 @@
1
+ require 'rack/commonlogger'
2
+ require 'logstash/event'
3
+
4
+ module Rack
5
+ module Logstasher
6
+ class Logger < Rack::CommonLogger
7
+ def initialize(app, logger, opts = {})
8
+ super(app, logger)
9
+ @extra_headers = opts[:extra_headers] || {}
10
+ end
11
+
12
+ private
13
+
14
+ def log(env, status, header, began_at)
15
+ now = Time.now
16
+
17
+ data = {
18
+ :method => env["REQUEST_METHOD"],
19
+ :path => env["PATH_INFO"],
20
+ :status => status.to_i,
21
+ :duration => duration_in_ms(began_at, now).round(2),
22
+ :remote_addr => env['REMOTE_ADDR'],
23
+ :parameters => env["QUERY_STRING"],
24
+ :request => request_line(env),
25
+ :length => extract_content_length(header)
26
+ }
27
+
28
+ @extra_headers.each do |header, log_key|
29
+ env_key = "HTTP_#{header.upcase.gsub('-', '_')}"
30
+ if env[env_key]
31
+ data[log_key] = env[env_key]
32
+ end
33
+ end
34
+
35
+ event = LogStash::Event.new('@fields' => data, '@tags' => ['request'])
36
+ msg = event.to_json + "\n"
37
+ if @logger.respond_to?(:write)
38
+ @logger.write(msg)
39
+ else
40
+ @logger << msg
41
+ end
42
+ end
43
+
44
+ def duration_in_ms(began, ended)
45
+ (ended - began) * 1000
46
+ end
47
+
48
+ def request_line(env)
49
+ line = "#{env["REQUEST_METHOD"]} #{env["SCRIPT_NAME"]}#{env['PATH_INFO']}"
50
+ line << "?#{env["QUERY_STRING"]}" if env["QUERY_STRING"] and ! env["QUERY_STRING"].empty?
51
+ line << " #{env["SERVER_PROTOCOL"]}"
52
+ line
53
+ end
54
+
55
+ end # Logger
56
+ end
57
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ module Logstasher
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require "rack/logstasher/version"
2
+ require "rack/logstasher/logger"
3
+
4
+ module Rack
5
+ module Logstasher
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rack/logstasher/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rack-logstasher"
8
+ spec.version = Rack::Logstasher::VERSION
9
+ spec.authors = ["Alex Tomlins"]
10
+ spec.email = ["alex.tomlins@digital.cabinet-office.gov.uk"]
11
+ spec.description = %q{Rack middleware to log requests in logstash json event format. Like the logstasher gem, but for rack apps.}
12
+ spec.summary = %q{Rack middleware to log requests in logstash json event format}
13
+ spec.homepage = "https://github.com/alphagov/rack-logstasher"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
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 "rack"
22
+ spec.add_dependency "logstash-event"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rack-test", "0.6.2"
27
+ spec.add_development_dependency "rspec", "2.14.1"
28
+ spec.add_development_dependency "gem_publisher", "1.2.0"
29
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+ require 'logger'
4
+
5
+ require 'rack/logstasher'
6
+
7
+ describe "Logger" do
8
+ include Rack::Test::Methods
9
+
10
+ describe "adding request details to the logfile" do
11
+ def app
12
+ Rack::Logstasher::Logger.new(
13
+ proc {|env|
14
+ sleep @sleep_time if @sleep_time
15
+ [200, {}, ["Inner app response"]]
16
+ },
17
+ Logger.new(tmp_logfile_path)
18
+ )
19
+ end
20
+
21
+ it "should add request details to the logfile" do
22
+ get "/foo?bar=baz"
23
+
24
+ log_details = JSON.parse(last_log_line)
25
+ fields = log_details['@fields']
26
+
27
+ expect(fields['method']).to eq('GET')
28
+ expect(fields['path']).to eq('/foo')
29
+ expect(fields['parameters']).to eq('bar=baz')
30
+ expect(fields['request']).to eq('GET /foo?bar=baz ') # env['SERVER_PROTOCOL'] is not set under rack-test
31
+ end
32
+
33
+ it "should add request duration" do
34
+ @sleep_time = 0.1
35
+ get "/foo"
36
+
37
+ log_details = JSON.parse(last_log_line)
38
+ fields = log_details['@fields']
39
+
40
+ expect(fields['duration']).to be_within(5).of(100)
41
+ end
42
+
43
+ it "should add a tag of 'request'" do
44
+ get "/foo?bar=baz"
45
+
46
+ log_details = JSON.parse(last_log_line)
47
+ expect(log_details['@tags']).to eq(['request'])
48
+ end
49
+
50
+ describe "adding extra headers to the log" do
51
+ before :each do
52
+ @extra_headers = {}
53
+ end
54
+ def app
55
+ Rack::Logstasher::Logger.new(
56
+ proc {|env|
57
+ sleep @sleep_time if @sleep_time
58
+ [200, {}, ["Inner app response"]]
59
+ },
60
+ Logger.new(tmp_logfile_path),
61
+ :extra_headers => @extra_headers
62
+ )
63
+ end
64
+
65
+ it "should add specified extra headers to the log under the given key" do
66
+ @extra_headers["foo"] = "header_foo"
67
+ get "/something", {}, {"HTTP_FOO" => "bar"}
68
+
69
+ log_details = JSON.parse(last_log_line)
70
+ fields = log_details['@fields']
71
+
72
+ expect(fields['header_foo']).to eq('bar')
73
+ end
74
+
75
+ it "should not add the key if the header is missing" do
76
+ @extra_headers["foo"] = "header_foo"
77
+ get "/something"
78
+
79
+ log_details = JSON.parse(last_log_line)
80
+ fields = log_details['@fields']
81
+
82
+ expect(fields).not_to have_key('header_foo')
83
+ end
84
+
85
+ it "should handle dashes in header name" do
86
+ @extra_headers["Varnish-Id"] = "varnish_id"
87
+ get "/something", {}, {"HTTP_VARNISH_ID" => "1234"}
88
+
89
+ log_details = JSON.parse(last_log_line)
90
+ fields = log_details['@fields']
91
+
92
+ expect(fields['varnish_id']).to eq('1234')
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,22 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+
6
+
7
+ # Requires supporting ruby files with custom matchers and macros, etc,
8
+ # in spec/support/ and its subdirectories.
9
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
10
+
11
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+
17
+ # Run specs in random order to surface order dependencies. If you find an
18
+ # order dependency and want to debug it, you can fix the order by providing
19
+ # the seed, which is printed after each run.
20
+ # --seed 1234
21
+ config.order = 'random'
22
+ end
@@ -0,0 +1,23 @@
1
+ require 'tempfile'
2
+
3
+ module LogfileHelper
4
+ TMP_LOGFILE = Tempfile.new('rack-logstasher-tmp-log')
5
+
6
+ def reset_tmp_log
7
+ TMP_LOGFILE.rewind
8
+ TMP_LOGFILE.truncate(0)
9
+ end
10
+
11
+ def tmp_logfile_path
12
+ TMP_LOGFILE.path
13
+ end
14
+
15
+ def last_log_line
16
+ TMP_LOGFILE.readlines.last
17
+ end
18
+ end
19
+
20
+ RSpec.configuration.include(LogfileHelper)
21
+ RSpec.configuration.before :each do
22
+ reset_tmp_log
23
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-logstasher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex Tomlins
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: logstash-event
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rack-test
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - '='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.6.2
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.6.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - '='
100
+ - !ruby/object:Gem::Version
101
+ version: 2.14.1
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - '='
108
+ - !ruby/object:Gem::Version
109
+ version: 2.14.1
110
+ - !ruby/object:Gem::Dependency
111
+ name: gem_publisher
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.2.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 1.2.0
126
+ description: Rack middleware to log requests in logstash json event format. Like
127
+ the logstasher gem, but for rack apps.
128
+ email:
129
+ - alex.tomlins@digital.cabinet-office.gov.uk
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - .gitignore
135
+ - .rspec
136
+ - .ruby-version
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - jenkins.sh
142
+ - lib/rack/logstasher.rb
143
+ - lib/rack/logstasher/logger.rb
144
+ - lib/rack/logstasher/version.rb
145
+ - rack-logstasher.gemspec
146
+ - spec/logger_spec.rb
147
+ - spec/spec_helper.rb
148
+ - spec/support/logfile_helper.rb
149
+ homepage: https://github.com/alphagov/rack-logstasher
150
+ licenses:
151
+ - MIT
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
158
+ requirements:
159
+ - - ! '>='
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ segments:
163
+ - 0
164
+ hash: 1307778500513444384
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ! '>='
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ segments:
172
+ - 0
173
+ hash: 1307778500513444384
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 1.8.23
177
+ signing_key:
178
+ specification_version: 3
179
+ summary: Rack middleware to log requests in logstash json event format
180
+ test_files:
181
+ - spec/logger_spec.rb
182
+ - spec/spec_helper.rb
183
+ - spec/support/logfile_helper.rb