nav-logger 0.0.1 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +19 -4
- data/lib/nav/logger.rb +11 -0
- data/lib/nav/logger/base_logger.rb +25 -11
- data/lib/nav/logger/console_logger.rb +40 -0
- data/lib/nav/logger/file_logger.rb +11 -0
- data/lib/nav/logger/httparty_formatter.rb +88 -0
- data/lib/nav/logger/middleware/request_logger.rb +53 -0
- data/lib/nav/logger/middleware/request_tagger.rb +36 -0
- data/lib/nav/logger/rails/logger_tie.rb +27 -0
- data/lib/nav/logger/version.rb +1 -1
- data/nav-logger.gemspec +1 -1
- metadata +12 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efbd45d44835cf65d532397c25413d30ef449ca6
|
4
|
+
data.tar.gz: 824873b52dde3b536f20c0f9c06fa97fa0cd8074
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32822765b8bde721698481db10e2f035305b0578d9d447972ee8ae6614553cc57ea394e888bd73212aa6134f528949e82f7c0f26aee982742cd2fb34b2fd95ff
|
7
|
+
data.tar.gz: f176b7ab2fc284f8a4b6498c1f14b9d70642c1649c04640793bf7023b1338036ee0f4f4b932f0060fc4d1065b2fc0e1cd8aab8c976116877c397b47ef9043474
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -12,15 +12,31 @@ gem "nav-logger"
|
|
12
12
|
|
13
13
|
And then execute:
|
14
14
|
|
15
|
-
|
15
|
+
`$ bundle`
|
16
16
|
|
17
17
|
Or install it yourself as:
|
18
18
|
|
19
|
-
|
19
|
+
`$ gem install nav-logger`
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
#### Rails
|
24
|
+
|
25
|
+
If you only want to tag your Rails logs with request and session ids, you just need to include the gem in your gemfile.
|
26
|
+
|
27
|
+
If you also want logs being sent to the aggregator, you need add the following to the application.rb:
|
28
|
+
```ruby
|
29
|
+
config.middleware.use Nav::Logger::RequestLogger
|
30
|
+
```
|
31
|
+
|
32
|
+
#### Rack
|
33
|
+
|
34
|
+
After installing gem into rack app, add in the config.ru
|
35
|
+
```ruby
|
36
|
+
use Nav::Logger::Middleware::RequestTagger
|
37
|
+
use Nav::Logger::Middleware::RequestLogger
|
38
|
+
```
|
39
|
+
_Make sure RequestTagger comes before RequestLogger_
|
24
40
|
|
25
41
|
## Development
|
26
42
|
|
@@ -36,4 +52,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/credit
|
|
36
52
|
## License
|
37
53
|
|
38
54
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
39
|
-
|
data/lib/nav/logger.rb
CHANGED
@@ -6,9 +6,14 @@ require "socket"
|
|
6
6
|
require "nav/logger/base_logger"
|
7
7
|
require "nav/logger/console_logger"
|
8
8
|
require "nav/logger/default_logger"
|
9
|
+
require "nav/logger/httparty_formatter"
|
10
|
+
require "nav/logger/middleware/request_logger"
|
11
|
+
require "nav/logger/middleware/request_tagger"
|
9
12
|
require "nav/logger/test_logger"
|
10
13
|
require "nav/logger/version"
|
11
14
|
|
15
|
+
require "nav/logger/rails/logger_tie" if defined?(::Rails)
|
16
|
+
|
12
17
|
module Nav
|
13
18
|
module_function
|
14
19
|
|
@@ -33,3 +38,9 @@ module Nav
|
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|
41
|
+
|
42
|
+
if defined? HTTParty
|
43
|
+
HTTParty::Logger.add_formatter :nav, Nav::Logger::HTTPartyFormatter
|
44
|
+
#HTTParty.logger Nav.logger, :debug, :nav
|
45
|
+
#HTTParty.headers "X-Request-Id" => RequestStore[:request_id]
|
46
|
+
end
|
@@ -4,7 +4,9 @@ module Nav
|
|
4
4
|
attr_reader :fluent_logger
|
5
5
|
|
6
6
|
def level
|
7
|
-
@level
|
7
|
+
return @level if defined? @level
|
8
|
+
self.level = ENV["LOG_LEVEL"] || "info"
|
9
|
+
@level
|
8
10
|
end
|
9
11
|
|
10
12
|
def level_name(lookup = level)
|
@@ -44,6 +46,15 @@ module Nav
|
|
44
46
|
add ::Logger::FATAL, message, hash
|
45
47
|
end
|
46
48
|
|
49
|
+
def post(tag, hash)
|
50
|
+
full_hash = generate_log_hash hash
|
51
|
+
@fluent_logger.post tag, full_hash
|
52
|
+
end
|
53
|
+
|
54
|
+
def log_tag(secondary_tag)
|
55
|
+
[app_tag, secondary_tag.downcase].compact.join "."
|
56
|
+
end
|
57
|
+
|
47
58
|
private
|
48
59
|
|
49
60
|
def add(severity, message, hash)
|
@@ -51,8 +62,13 @@ module Nav
|
|
51
62
|
return true if severity < level
|
52
63
|
|
53
64
|
severity_name = level_name severity
|
54
|
-
|
55
|
-
|
65
|
+
|
66
|
+
hash[:level] = severity_name
|
67
|
+
hash[:message] = message
|
68
|
+
|
69
|
+
log_hash = generate_log_hash hash
|
70
|
+
|
71
|
+
@fluent_logger.post log_tag(severity_name), log_hash
|
56
72
|
end
|
57
73
|
|
58
74
|
def app_tag
|
@@ -68,18 +84,16 @@ module Nav
|
|
68
84
|
@hostname ||= Socket.gethostname
|
69
85
|
end
|
70
86
|
|
71
|
-
def generate_log_hash(
|
87
|
+
def generate_log_hash(input = {})
|
72
88
|
hash = input.merge RequestStore.store
|
73
|
-
hash.merge!
|
74
|
-
level: severity,
|
75
|
-
ts: Time.now.to_f,
|
89
|
+
hash.merge! ts: Time.now.to_f,
|
76
90
|
environment: environment,
|
77
|
-
hostname: hostname
|
78
|
-
|
91
|
+
hostname: hostname,
|
92
|
+
pid: pid
|
79
93
|
end
|
80
94
|
|
81
|
-
def
|
82
|
-
|
95
|
+
def pid
|
96
|
+
@pid ||= Process.pid
|
83
97
|
end
|
84
98
|
end
|
85
99
|
end
|
@@ -1,8 +1,48 @@
|
|
1
1
|
module Nav
|
2
2
|
module Logger
|
3
3
|
class ConsoleLogger < BaseLogger
|
4
|
+
# Mapping of color/style names to ANSI control values
|
5
|
+
CODEMAP = {
|
6
|
+
normal: 0,
|
7
|
+
bold: 1,
|
8
|
+
black: 30,
|
9
|
+
red: 31,
|
10
|
+
green: 32,
|
11
|
+
yellow: 33,
|
12
|
+
blue: 34,
|
13
|
+
magenta: 35,
|
14
|
+
cyan: 36,
|
15
|
+
white: 37
|
16
|
+
}
|
17
|
+
|
18
|
+
# Map of log levels to colors
|
19
|
+
LEVELMAP = {
|
20
|
+
"FATAL" => :red,
|
21
|
+
"ERROR" => :red,
|
22
|
+
"WARN" => :yellow,
|
23
|
+
"INFO" => :green, # default color
|
24
|
+
"DEBUG" => :cyan
|
25
|
+
}
|
26
|
+
|
4
27
|
def initialize
|
5
28
|
@fluent_logger = Fluent::Logger::ConsoleLogger.open STDOUT
|
29
|
+
|
30
|
+
# Adds colorized loigging
|
31
|
+
def @fluent_logger.post_with_time(tag, map, time)
|
32
|
+
a = [time.strftime(@time_format), " ", tag, ":"]
|
33
|
+
map.each_pair { |k,v|
|
34
|
+
a << " #{k}="
|
35
|
+
a << JSON.dump(v)
|
36
|
+
}
|
37
|
+
|
38
|
+
color = LEVELMAP[map[:level]] || :green
|
39
|
+
|
40
|
+
a.unshift "\e[#{CODEMAP[color]}m"
|
41
|
+
a << "\e[#{CODEMAP[:normal]}m"
|
42
|
+
|
43
|
+
post_text a.join
|
44
|
+
true
|
45
|
+
end
|
6
46
|
end
|
7
47
|
end
|
8
48
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Nav
|
2
|
+
module Logger
|
3
|
+
class HTTPartyFormatter
|
4
|
+
OUT = ">".freeze
|
5
|
+
IN = "<".freeze
|
6
|
+
|
7
|
+
attr_accessor :level, :logger
|
8
|
+
|
9
|
+
def initialize(logger, level)
|
10
|
+
@logger = logger
|
11
|
+
@level = level.to_sym
|
12
|
+
@messages = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def format(request, response)
|
16
|
+
@request = request
|
17
|
+
@response = response
|
18
|
+
|
19
|
+
library_line = caller.detect{ |line| line !~ /httparty/ }
|
20
|
+
|
21
|
+
log_request
|
22
|
+
log_response
|
23
|
+
|
24
|
+
logger.send level, messages.join("\n"), caller: library_line
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :request, :response
|
30
|
+
attr_accessor :messages
|
31
|
+
|
32
|
+
def log_request
|
33
|
+
log_url
|
34
|
+
log_headers
|
35
|
+
log_query
|
36
|
+
log OUT, request.raw_body if request.raw_body
|
37
|
+
log OUT
|
38
|
+
end
|
39
|
+
|
40
|
+
def log_response
|
41
|
+
log IN, "HTTP/#{response.http_version} #{response.code}"
|
42
|
+
log_response_headers
|
43
|
+
log IN, "\n#{response.body}"
|
44
|
+
log IN
|
45
|
+
end
|
46
|
+
|
47
|
+
def log_url
|
48
|
+
http_method = request.http_method.name.split("::").last.upcase
|
49
|
+
uri = if request.options[:base_uri]
|
50
|
+
request.options[:base_uri] + request.path.path
|
51
|
+
else
|
52
|
+
request.path.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
log OUT, "#{http_method} #{uri}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def log_headers
|
59
|
+
return unless request.options[:headers] && request.options[:headers].size > 0
|
60
|
+
|
61
|
+
log OUT, "Headers: "
|
62
|
+
log_hash request.options[:headers]
|
63
|
+
end
|
64
|
+
|
65
|
+
def log_query
|
66
|
+
return unless request.options[:query]
|
67
|
+
|
68
|
+
log OUT, "Query: "
|
69
|
+
log_hash request.options[:query]
|
70
|
+
end
|
71
|
+
|
72
|
+
def log_response_headers
|
73
|
+
headers = response.respond_to?(:headers) ? response.headers : response
|
74
|
+
response.each_header do |response_header|
|
75
|
+
log IN, "#{response_header.capitalize}: #{headers[response_header]}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def log_hash(hash)
|
80
|
+
hash.each { |k, v| log(OUT, "#{k}: #{v}") }
|
81
|
+
end
|
82
|
+
|
83
|
+
def log(direction, line = "")
|
84
|
+
messages << "#{direction} #{line}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Nav
|
2
|
+
module Logger
|
3
|
+
module Middleware
|
4
|
+
class RequestLogger
|
5
|
+
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
start_time = Time.now
|
12
|
+
status, headers, body = @app.call env
|
13
|
+
[status, headers, [body]]
|
14
|
+
ensure
|
15
|
+
log_request start_time, env, status, headers
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def log_request(start_time, env, status, headers)
|
20
|
+
rack_log_hash = {
|
21
|
+
remote_addr: env["HTTP_X_FORWARDED_FOR"] || env["REMOTE_ADDR"] || "-",
|
22
|
+
remote_user: env["REMOTE_USER"] || "-",
|
23
|
+
request_method: env[Rack::REQUEST_METHOD],
|
24
|
+
request_path: env[Rack::PATH_INFO],
|
25
|
+
query_string: env[Rack::QUERY_STRING].empty? ? "" : "?#{env[Rack::QUERY_STRING]}",
|
26
|
+
status: status.to_s[0..3],
|
27
|
+
content_length: extract_content_length(headers),
|
28
|
+
duration: Time.now - start_time,
|
29
|
+
level: status_level(status)
|
30
|
+
}
|
31
|
+
tag = Nav.logger.log_tag "http"
|
32
|
+
Nav.logger.post tag, rack_log_hash
|
33
|
+
end
|
34
|
+
|
35
|
+
def status_level(status)
|
36
|
+
return "ERROR" if status.nil?
|
37
|
+
case status.to_i
|
38
|
+
when 400..499 then "WARN"
|
39
|
+
when 500..599 then "ERROR"
|
40
|
+
else "INFO"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_content_length(headers)
|
45
|
+
return "-" if headers.nil?
|
46
|
+
value = headers[Rack::CONTENT_LENGTH] or return "-"
|
47
|
+
value.to_s == "0" ? "-" : value
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Nav
|
2
|
+
module Logger
|
3
|
+
module Middleware
|
4
|
+
class RequestTagger
|
5
|
+
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
setup_request_store
|
12
|
+
store_request_var env
|
13
|
+
@app.call env
|
14
|
+
ensure
|
15
|
+
clear_request_store
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def setup_request_store
|
20
|
+
RequestStore.begin!
|
21
|
+
end
|
22
|
+
|
23
|
+
def store_request_var(env)
|
24
|
+
RequestStore[:request_id] = env["HTTP_X_REQUEST_ID"] || SecureRandom.uuid
|
25
|
+
RequestStore[:session_id] = env["HTTP_X_SESSION_ID"] if env.key? "HTTP_X_SESSION_ID"
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear_request_store
|
29
|
+
RequestStore.end!
|
30
|
+
RequestStore.clear!
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Nav
|
2
|
+
module Logger
|
3
|
+
module Rails
|
4
|
+
class LoggerTie < ::Rails::Railtie
|
5
|
+
initializer "logger_tie.configure_rails_initialization" do |app|
|
6
|
+
|
7
|
+
# We add the request id and session it from the RequestStore as tags
|
8
|
+
# on all Rails logs.
|
9
|
+
app.config.log_tags ||= []
|
10
|
+
app.config.log_tags << lambda { |_arg| RequestStore[:request_id] }
|
11
|
+
app.config.log_tags << lambda { |_arg| RequestStore[:session_id] }
|
12
|
+
|
13
|
+
# We insert the nav logger middleware into the middleware stack. We
|
14
|
+
# need to insert it before the Rails::Rack::Logger, since that is when
|
15
|
+
# the tag lambdas get executed. If the Nav Logger middleware hasn't
|
16
|
+
# already been run the request store will be empty and the lambdas
|
17
|
+
# will come back nil.
|
18
|
+
app.config.middleware.insert_before(
|
19
|
+
::Rails::Rack::Logger,
|
20
|
+
Nav::Logger::Middleware::RequestTagger
|
21
|
+
)
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/nav/logger/version.rb
CHANGED
data/nav-logger.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nav-logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JohnnyT
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluent-logger
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: request_store
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.3.2
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.3.2
|
41
41
|
description:
|
42
42
|
email:
|
43
43
|
- ubergeek3141@gmail.com
|
@@ -63,6 +63,11 @@ files:
|
|
63
63
|
- lib/nav/logger/base_logger.rb
|
64
64
|
- lib/nav/logger/console_logger.rb
|
65
65
|
- lib/nav/logger/default_logger.rb
|
66
|
+
- lib/nav/logger/file_logger.rb
|
67
|
+
- lib/nav/logger/httparty_formatter.rb
|
68
|
+
- lib/nav/logger/middleware/request_logger.rb
|
69
|
+
- lib/nav/logger/middleware/request_tagger.rb
|
70
|
+
- lib/nav/logger/rails/logger_tie.rb
|
66
71
|
- lib/nav/logger/test_logger.rb
|
67
72
|
- lib/nav/logger/version.rb
|
68
73
|
- nav-logger.gemspec
|
@@ -86,9 +91,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
91
|
version: '0'
|
87
92
|
requirements: []
|
88
93
|
rubyforge_project:
|
89
|
-
rubygems_version: 2.5.
|
94
|
+
rubygems_version: 2.5.2
|
90
95
|
signing_key:
|
91
96
|
specification_version: 4
|
92
97
|
summary: Nav's logger
|
93
98
|
test_files: []
|
94
|
-
has_rdoc:
|