rack-ltsv_logger 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b877c1c1d148d33b66c580fb4112e6ce9dad1e5
4
+ data.tar.gz: 2bff1571091b41b391d4be16fc5d99f94fd9a06c
5
+ SHA512:
6
+ metadata.gz: d35ba9ab66040d12fed2f30130644787f03ef29cf926ffc3408269e898c4364cb88d5ae9371617a9b10ca76e8877ffde1650721a0aaf76591d3469cb1e52bd1c
7
+ data.tar.gz: cd511826a96aa9bc77249fed37ed939aa134b7db18762b4a94362e5cf12a24af73cfef56858cfc9ba333054b9f7ec7010df6637bc7c2d33b06877b07948cc680
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/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1
5
+ gemfile:
6
+ - Gemfile
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 DeNA, Co., Ltd
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,139 @@
1
+ # Rack::LtsvLogger
2
+
3
+ A rack middleware to output access log in ltsv format, like [rack/commonlogger](https://github.com/rack/rack/blob/master/lib/rack/commonlogger.rb) (which output access log in apache common format).
4
+
5
+ ## Why Rack Middleware
6
+
7
+ cf. https://speakerdeck.com/mirakui/high-performance-rails-long-edition
8
+
9
+ <img src="doc/x_runtime.png" alt="x_runtime" width="50%" height="50%"/>
10
+
11
+ The Completed Time does not include routing time, and elapsed time on rack middleware layers, and so on.
12
+ To measure the processing time accurately, it is necessary to insert a rack middleware to measure the time.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'rack-ltsvlogger'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ ## How to Use
25
+
26
+ Insert Rack::LtsvLogger on the head of rack middlewares.
27
+
28
+ Rails)
29
+
30
+ Add following to config/environments/[env].rb
31
+
32
+ ```ruby
33
+ require 'rack/ltsvlogger'
34
+ require 'logger'
35
+
36
+ config.middleware.insert_after(0, Rack::LtsvLogger, $stdout)
37
+ ```
38
+
39
+ Sinatra)
40
+
41
+ ```ruby
42
+ # config.ru
43
+ require 'rack/ltsvlogger'
44
+
45
+ use Rack::LtsvLogger, $stdout
46
+ run App
47
+ ```
48
+
49
+ ## Format
50
+
51
+ Sample (line feeded):
52
+
53
+ ```
54
+ time:2014-07-02T21:52:31+09:00 pid:15189 host:127.0.0.1 forwardedfor:127.0.0.2 user:user
55
+ method:GET uri:/get query:?foo protocol:HTTP/1.1 status:200 size:- reqtime:0.000000
56
+ ```
57
+
58
+ ### Default Fields
59
+
60
+ * time
61
+
62
+ * The datetime in ISO-8601 format
63
+
64
+ * pid
65
+
66
+ * Process ID
67
+
68
+ * host
69
+
70
+ * ENV['REMOTE_ADDR']
71
+
72
+ * forwardedfor
73
+
74
+ * ENV['X_FORWARDED_FOR']
75
+
76
+ * user
77
+
78
+ * ENV['REMOTE_USER']
79
+
80
+ * method
81
+
82
+ * ENV['REQUEST_METHOD']
83
+
84
+ * uri
85
+
86
+ * ENV['PATH_INFO']
87
+
88
+ * query
89
+
90
+ * ENV['QUERY_STRING']
91
+
92
+ * protocol
93
+
94
+ * ENV['HTTP_VERSION']
95
+
96
+ * status
97
+
98
+ * Response Status Code
99
+
100
+ * size
101
+
102
+ * Response Content-Length
103
+
104
+ * reqtime
105
+
106
+ * The request time in secods. milli seconds are written after the decimal point.
107
+
108
+ * Others
109
+
110
+ * See http://ltsv.org/
111
+
112
+ ### Custom Fields
113
+
114
+ You may append LTSV fields as:
115
+
116
+ ```ruby
117
+ appends = {
118
+ vhost: Proc.new {|env| env['HTTP_HOST'] || "-" },
119
+ ua: Proc.new {|env| env['HTTP_USER_AGENT'] || "-" },
120
+ referer: Proc.new {|env| env['HTTP_REFERER'] || "-" },
121
+ }
122
+ config.middleware.insert_after(0, Rack::LtsvLogger, $stdout, appends)
123
+ ```
124
+
125
+ ## ChangeLog
126
+
127
+ See [CHANGELOG.md](CHANGELOG.md) for details.
128
+
129
+ ## Contributing
130
+
131
+ 1. Fork it
132
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
133
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
134
+ 4. Push to the branch (`git push origin my-new-feature`)
135
+ 5. Create new [Pull Request](../../pull/new/master)
136
+
137
+ ## Copyright
138
+
139
+ See [LICENSE.txt](LICENSE.txt) for details.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :test do
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:test) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+ end
10
+ task :default => :spec
11
+
12
+ desc 'Open an irb session preloaded with the gem library'
13
+ task :console do
14
+ sh 'irb -rubygems -I lib'
15
+ end
16
+ task :c => :console
data/doc/x_runtime.png ADDED
Binary file
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'sinatra'
4
+ gem 'rack-ltsv_logger', path: '../..'
5
+ gem 'pry'
6
+ gem 'pry-nav'
@@ -0,0 +1,7 @@
1
+ require 'sinatra/base'
2
+
3
+ class App < Sinatra::Base
4
+ get '/' do
5
+ logger.info "OK"
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ require 'logger'
2
+ require 'rack/ltsv_logger'
3
+ require_relative 'app'
4
+
5
+ use Rack::LtsvLogger, STDOUT
6
+ run App
@@ -0,0 +1 @@
1
+ require 'rack/ltsv_logger'
@@ -0,0 +1,54 @@
1
+ require 'time'
2
+
3
+ module Rack
4
+ class LtsvLogger
5
+ PID = Process.pid
6
+
7
+ def initialize(app, logger=nil, appends = {})
8
+ @app = app
9
+ @logger = logger || $stdout
10
+ @appends = appends
11
+ end
12
+
13
+ def call(env)
14
+ began_at = Time.now.instance_eval { to_i + (usec/1000000.0) }
15
+
16
+ status, headers, body = @app.call(env)
17
+
18
+ now = Time.now
19
+ reqtime = now.instance_eval { to_i + (usec/1000000.0) } - began_at
20
+
21
+ params = {
22
+ time: now.iso8601,
23
+ pid: PID,
24
+ host: env["REMOTE_ADDR"] || "-",
25
+ forwardedfor: env['HTTP_X_FORWARDED_FOR'] || "-",
26
+ user: env["REMOTE_USER"] || "-",
27
+ method: env["REQUEST_METHOD"],
28
+ uri: env["PATH_INFO"],
29
+ query: env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
30
+ protocol: env["HTTP_VERSION"],
31
+ status: status.to_s[0..3],
32
+ size: extract_content_length(headers),
33
+ reqtime: "%0.6f" % reqtime,
34
+ }
35
+ @appends.each do |key, proc|
36
+ params[key] = proc.call(env)
37
+ end
38
+ @logger.write ltsv(params)
39
+
40
+ [status, headers, body]
41
+ end
42
+
43
+ private
44
+
45
+ def ltsv(hash)
46
+ hash.map {|k, v| "#{k}:#{v}" }.join("\t") + "\n"
47
+ end
48
+
49
+ def extract_content_length(headers)
50
+ value = headers['Content-Length'] or return '-'
51
+ value.to_s == '0' ? '-' : value
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rack-ltsv_logger"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Naotoshi Seo"]
9
+ spec.email = ["sonots@gmail.com"]
10
+ spec.description = %q{A rack middleware to output access log in ltsv format}
11
+ spec.summary = %q{A rack middleware to output access log in ltsv format.}
12
+ spec.homepage = "https://github.com/sonots/rack-ltsv_logger"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "rack"
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "pry-nav"
26
+ spec.add_development_dependency "timecop"
27
+ end
@@ -0,0 +1,73 @@
1
+ require_relative 'spec_helper'
2
+ require 'timecop'
3
+
4
+ describe Rack::LtsvLogger do
5
+ def app
6
+ lambda { |env|
7
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
8
+ }
9
+ end
10
+
11
+ def parse_ltsv(ltsv)
12
+ Hash[*(ltsv.chomp.split("\t").map {|e| e.split(":", 2) }.flatten)]
13
+ end
14
+
15
+ let(:now) { Time.now }
16
+ let(:time) { now.iso8601 }
17
+ let(:pid) { Process.pid }
18
+ let(:host) { '127.0.0.1' }
19
+ let(:forwardedfor) { '127.0.0.2' }
20
+ let(:user) { 'user' }
21
+ let(:protocol) { 'HTTP/1.1' }
22
+ let(:env) do
23
+ {
24
+ 'REMOTE_ADDR' => host,
25
+ 'HTTP_X_FORWARDED_FOR' => forwardedfor,
26
+ 'REMOTE_USER' => user,
27
+ 'HTTP_VERSION' => protocol,
28
+ }
29
+ end
30
+
31
+ before do
32
+ Timecop.freeze now
33
+ end
34
+
35
+ after do
36
+ Timecop.return
37
+ end
38
+
39
+ context 'ltsv' do
40
+ subject do
41
+ @output = StringIO.new
42
+ Rack::Lint.new( Rack::LtsvLogger.new(app, @output) )
43
+ end
44
+
45
+ let(:method) { 'GET' }
46
+ let(:uri) { '/get' }
47
+ let(:query) { '?foo' }
48
+
49
+ it do
50
+ Rack::MockRequest.new(subject).get("#{uri}#{query}", env)
51
+ expect(@output.string).to eq \
52
+ "time:#{time}\tpid:#{pid}\thost:#{host}\tforwardedfor:#{forwardedfor}\tuser:#{user}\t" +
53
+ "method:#{method}\turi:#{uri}\tquery:#{query}\tprotocol:#{protocol}\tstatus:200\tsize:-\treqtime:0.000000\n"
54
+ end
55
+ end
56
+
57
+ context 'appends' do
58
+ let(:appends) do
59
+ { x_runtime: Proc.new {|env| '1.234' } }
60
+ end
61
+
62
+ subject do
63
+ @output = StringIO.new
64
+ Rack::Lint.new( Rack::LtsvLogger.new(app, @output, appends) )
65
+ end
66
+
67
+ it 'GET /get' do
68
+ Rack::MockRequest.new(subject).get('/get', env)
69
+ params = parse_ltsv(@output.string)
70
+ expect(params['x_runtime']).to eq('1.234')
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ Bundler.setup(:default, :test)
3
+ Bundler.require(:default, :test)
4
+
5
+ #require 'simplecov'
6
+ #require 'simplecov-rcov'
7
+ #SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
8
+ #SimpleCov.start
9
+
10
+ $TESTING=true
11
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib/rack/')
12
+ require 'timecop'
13
+ require 'rack'
14
+ require 'rack-ltsv_logger'
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-ltsv_logger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Naotoshi Seo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-nav
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: timecop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A rack middleware to output access log in ltsv format
112
+ email:
113
+ - sonots@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".travis.yml"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - doc/x_runtime.png
125
+ - example/sinatra/Gemfile
126
+ - example/sinatra/app.rb
127
+ - example/sinatra/config.ru
128
+ - lib/rack-ltsv_logger.rb
129
+ - lib/rack/ltsv_logger.rb
130
+ - rack-ltsv_logger.gemspec
131
+ - spec/ltsv_logger_spec.rb
132
+ - spec/spec_helper.rb
133
+ homepage: https://github.com/sonots/rack-ltsv_logger
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.2.2
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: A rack middleware to output access log in ltsv format.
157
+ test_files:
158
+ - spec/ltsv_logger_spec.rb
159
+ - spec/spec_helper.rb