depthcharge 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +71 -0
- data/Rakefile +6 -0
- data/bin/.gitkeep +0 -0
- data/depthcharge.gemspec +33 -0
- data/lib/depthcharge.rb +10 -0
- data/lib/depthcharge/filters.rb +14 -0
- data/lib/depthcharge/formatters.rb +53 -0
- data/lib/depthcharge/middleware.rb +23 -0
- data/lib/depthcharge/request_logger.rb +44 -0
- data/lib/depthcharge/version.rb +3 -0
- data/test_apps/rails.rb +29 -0
- data/test_apps/sinatra.rb +21 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 235a7a642129d8b9f86e52cd86fd294cc718d262
|
4
|
+
data.tar.gz: 4996859bcd5553e324c3139b3d4b15bb6dd4f162
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0732f212694d995817e970d5377499f53ff9a608186d4592f9b3708c1c64965e8c02fe73f4deb306f0552f197a227f9db102040e798c673335bef2ed901a3677
|
7
|
+
data.tar.gz: d26b3f29e94c22d2c5b8e673ec65f145091391a0cd1810984ecd7522763012004dc2929da0a2a13518b5320c5c539d80d8c5d7f05b292c1d7a289bc4a50b2ea5
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Aaron Gough
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Depthcharge
|
2
|
+
|
3
|
+
Depthcharge is a piece of Rack middleware that enables extra visibility into the requests going through an application. The primary use case for this is to see the requests that are coming and going from a local server to a connected client app (like iOS simulator for example). Additionally it will automatically detect JSON responses and pretty print them to enhance readability.
|
4
|
+
|
5
|
+
## Example log output
|
6
|
+
|
7
|
+
|
8
|
+
GET 200 "/example.json" at 2017-04-30 23:32:16 -0400
|
9
|
+
| PARAMS:
|
10
|
+
| test: "foo"
|
11
|
+
|
|
12
|
+
| REQUEST HEADERS:
|
13
|
+
| HTTP_HOST: "localhost:4567"
|
14
|
+
| HTTP_CONNECTION: "keep-alive"
|
15
|
+
| HTTP_CACHE_CONTROL: "max-age=0"
|
16
|
+
| HTTP_VERSION: "HTTP/1.1"
|
17
|
+
|
|
18
|
+
| RESPONSE STATUS: 200
|
19
|
+
|
|
20
|
+
| RESPONSE HEADERS:
|
21
|
+
| Content-Type: "application/json"
|
22
|
+
| Content-Length: "25"
|
23
|
+
|
|
24
|
+
| BODY:
|
25
|
+
| {
|
26
|
+
| "a": 1,
|
27
|
+
| "b": 2,
|
28
|
+
| "c": 3,
|
29
|
+
| "d": 4
|
30
|
+
| }
|
31
|
+
|
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
## Installation
|
36
|
+
|
37
|
+
Add this line to your application's Gemfile:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
gem 'depthcharge'
|
41
|
+
```
|
42
|
+
|
43
|
+
And then execute:
|
44
|
+
|
45
|
+
$ bundle
|
46
|
+
|
47
|
+
Or install it yourself as:
|
48
|
+
|
49
|
+
$ gem install depthcharge
|
50
|
+
|
51
|
+
## Usage
|
52
|
+
|
53
|
+
Just add `gem 'depthcharge'` to your app's Gemfile, then add the middleware to your app like so:
|
54
|
+
|
55
|
+
Sinatra:
|
56
|
+
```ruby
|
57
|
+
use Depthcharge::Middleware, STDOUT, "depthcharge.log"
|
58
|
+
```
|
59
|
+
|
60
|
+
Rails:
|
61
|
+
```ruby
|
62
|
+
# config/application.rb (or) config/environments/development.rb
|
63
|
+
config.middleware.use Depthcharge::Middleware, Rails.root.join("log", "depthcharge.log")
|
64
|
+
```
|
65
|
+
|
66
|
+
You can pass multiple outputs to Depthcharge::Middleware and it will write to each one for each request. Logging to `STDOUT` and a log file simultaneously is a handy use of this as demonstrated above with the Sinatra setup.
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
71
|
+
|
data/Rakefile
ADDED
data/bin/.gitkeep
ADDED
File without changes
|
data/depthcharge.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'depthcharge/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "depthcharge"
|
8
|
+
spec.version = Depthcharge::VERSION
|
9
|
+
spec.authors = ["Aaron Gough"]
|
10
|
+
spec.email = ["aaron@aarongough.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A rack middleware layer that logs the full request cycle.}
|
13
|
+
spec.description = %q{A rack middleware layer that logs the full request cycle.}
|
14
|
+
spec.homepage = "https://github.com/aarongough/depthcharge"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
|
21
|
+
spec.bindir = "exe"
|
22
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_dependency "rack"
|
26
|
+
spec.add_dependency "json"
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
31
|
+
spec.add_development_dependency "sinatra", "~> 1.4.8"
|
32
|
+
spec.add_development_dependency "rails", "~> 4.2"
|
33
|
+
end
|
data/lib/depthcharge.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Depthcharge
|
2
|
+
module Formatters
|
3
|
+
|
4
|
+
MAIN_INDENT = " | "
|
5
|
+
SUB_INDENT = " "
|
6
|
+
NEWLINE = "\n"
|
7
|
+
|
8
|
+
def format_body(headers, body, level = 1)
|
9
|
+
content_type = headers["Content-Type"]
|
10
|
+
body = body.join if body.respond_to?(:join)
|
11
|
+
body = body.body if body.respond_to?(:body)
|
12
|
+
|
13
|
+
if !content_type.nil? && content_type.include?("json")
|
14
|
+
format_lines(JSON.pretty_generate(JSON.parse(body)), level)
|
15
|
+
else
|
16
|
+
format_lines(body, level)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def format_hash(name, hash, level = 1)
|
21
|
+
output = format_line(name.to_s.upcase + ":", level)
|
22
|
+
|
23
|
+
hash.each do |key, value|
|
24
|
+
output << format_line("#{key.to_s}: #{value.inspect}", level + 1)
|
25
|
+
end
|
26
|
+
|
27
|
+
output
|
28
|
+
end
|
29
|
+
|
30
|
+
def format_lines(lines, level = 1)
|
31
|
+
lines = lines.split($/).map do |line|
|
32
|
+
format_line(line, level)
|
33
|
+
end
|
34
|
+
|
35
|
+
lines.join
|
36
|
+
end
|
37
|
+
|
38
|
+
def blank_line(level = 1)
|
39
|
+
format_line("", level)
|
40
|
+
end
|
41
|
+
|
42
|
+
def format_line(line, level = 1)
|
43
|
+
indent(level) + line + NEWLINE
|
44
|
+
end
|
45
|
+
|
46
|
+
def indent(level)
|
47
|
+
return "" if level == 0
|
48
|
+
|
49
|
+
MAIN_INDENT + (SUB_INDENT * (level - 1))
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Depthcharge
|
2
|
+
class Middleware
|
3
|
+
|
4
|
+
attr_reader :app, :outputs
|
5
|
+
|
6
|
+
def initialize(app, *outputs)
|
7
|
+
@app = app
|
8
|
+
@outputs = outputs.flatten.map do |output|
|
9
|
+
if output.is_a?(String) || output.is_a?(Pathname)
|
10
|
+
File.open(output, "w")
|
11
|
+
else
|
12
|
+
output
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
status, headers, body = @app.call(env)
|
19
|
+
RequestLogger.new(env, status, headers, body).log(outputs)
|
20
|
+
[status, headers, body]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Depthcharge
|
2
|
+
class RequestLogger
|
3
|
+
|
4
|
+
include Formatters
|
5
|
+
include Filters
|
6
|
+
|
7
|
+
attr_reader :env, :status, :headers, :body
|
8
|
+
|
9
|
+
def initialize(env, status, headers, body)
|
10
|
+
@env = env
|
11
|
+
@status = status
|
12
|
+
@headers = headers
|
13
|
+
@body = body
|
14
|
+
end
|
15
|
+
|
16
|
+
def log(*outputs)
|
17
|
+
log_entry = construct_log_entry
|
18
|
+
|
19
|
+
outputs.flatten.each do |output|
|
20
|
+
output.puts(log_entry)
|
21
|
+
output.flush
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def construct_log_entry
|
26
|
+
output = ""
|
27
|
+
output << blank_line(0)
|
28
|
+
output << format_line("#{env["REQUEST_METHOD"]} #{status} #{env["PATH_INFO"].inspect} at #{Time.now}", 0)
|
29
|
+
output << format_hash("PARAMS", request_params(env))
|
30
|
+
output << blank_line
|
31
|
+
output << format_hash("REQUEST HEADERS", request_headers(env))
|
32
|
+
output << blank_line
|
33
|
+
output << format_line("RESPONSE STATUS: #{status}")
|
34
|
+
output << blank_line
|
35
|
+
output << format_hash("RESPONSE HEADERS", headers)
|
36
|
+
output << blank_line
|
37
|
+
output << format_line("BODY:")
|
38
|
+
output << format_body(headers, body, 2)
|
39
|
+
output << blank_line
|
40
|
+
output << blank_line(0)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/test_apps/rails.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Run this app with: `ruby rails.rb`
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "depthcharge"
|
5
|
+
require "rails"
|
6
|
+
require "webrick"
|
7
|
+
require "json"
|
8
|
+
require "action_controller/railtie"
|
9
|
+
|
10
|
+
class MyApp < Rails::Application
|
11
|
+
routes.append do
|
12
|
+
get "/example.json" => "example#json"
|
13
|
+
end
|
14
|
+
|
15
|
+
config.eager_load = true
|
16
|
+
config.secret_key_base = "538f51b191c9c2c35496d55804ddeddf"
|
17
|
+
|
18
|
+
config.middleware.use Depthcharge::Middleware, STDOUT, Rails.root.join("rails-depthcharge.log")
|
19
|
+
end
|
20
|
+
|
21
|
+
class ExampleController < ActionController::Base
|
22
|
+
def json
|
23
|
+
render json: { a: 1, b: 2, c: 3, d: 4 }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
MyApp.initialize!
|
28
|
+
|
29
|
+
Rack::Handler::WEBrick.run(MyApp, :Port => 3000)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Run this app with: `ruby sinatra.rb`
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "depthcharge"
|
5
|
+
require "sinatra/base"
|
6
|
+
require "json"
|
7
|
+
|
8
|
+
class SinartraTestApp < Sinatra::Base
|
9
|
+
use Depthcharge::Middleware, STDOUT, File.open("sinatra-depthcharge.log", "w")
|
10
|
+
|
11
|
+
get "/example.json" do
|
12
|
+
content_type :json
|
13
|
+
{ a: 1, b: 2, c: 3, d: 4 }.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
get "/example.html" do
|
17
|
+
"<head><head/><body><span>Example text</span></body>"
|
18
|
+
end
|
19
|
+
|
20
|
+
run!
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: depthcharge
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aaron Gough
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-04 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: json
|
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'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sinatra
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.4.8
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.4.8
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '4.2'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '4.2'
|
111
|
+
description: A rack middleware layer that logs the full request cycle.
|
112
|
+
email:
|
113
|
+
- aaron@aarongough.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rspec"
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/.gitkeep
|
125
|
+
- depthcharge.gemspec
|
126
|
+
- lib/depthcharge.rb
|
127
|
+
- lib/depthcharge/filters.rb
|
128
|
+
- lib/depthcharge/formatters.rb
|
129
|
+
- lib/depthcharge/middleware.rb
|
130
|
+
- lib/depthcharge/request_logger.rb
|
131
|
+
- lib/depthcharge/version.rb
|
132
|
+
- test_apps/rails.rb
|
133
|
+
- test_apps/sinatra.rb
|
134
|
+
homepage: https://github.com/aarongough/depthcharge
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
metadata: {}
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubyforge_project:
|
154
|
+
rubygems_version: 2.6.10
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: A rack middleware layer that logs the full request cycle.
|
158
|
+
test_files: []
|