nav-logger 0.0.1 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8f1a39fee5ed7b1569a38d0edf614307e52fc09e
4
- data.tar.gz: 47404afcb426ecb98252047c7576c00dd55ac4d7
3
+ metadata.gz: efbd45d44835cf65d532397c25413d30ef449ca6
4
+ data.tar.gz: 824873b52dde3b536f20c0f9c06fa97fa0cd8074
5
5
  SHA512:
6
- metadata.gz: 55b5572ce252b6bcb64956f877690608171e6faa5276be4cdcb457ed5581743d4ac0b13a40c31632b24caa03c0f267264f4007ae74a14549045a1d4f4af19efa
7
- data.tar.gz: d0d38f9b8651597e906cb6330bc634ecd336c0a042592df1e7b0cf42f9e628afb7ea264e6a5a5fa6c1100c8d1853401492d1582b808fd6a9a90cb4b2ac7726e6
6
+ metadata.gz: 32822765b8bde721698481db10e2f035305b0578d9d447972ee8ae6614553cc57ea394e888bd73212aa6134f528949e82f7c0f26aee982742cd2fb34b2fd95ff
7
+ data.tar.gz: f176b7ab2fc284f8a4b6498c1f14b9d70642c1649c04640793bf7023b1338036ee0f4f4b932f0060fc4d1065b2fc0e1cd8aab8c976116877c397b47ef9043474
data/.gitignore CHANGED
@@ -4,6 +4,7 @@
4
4
  /Gemfile.lock
5
5
  /_yardoc/
6
6
  /pkg/
7
+ /vendor/
7
8
 
8
9
  # Test files #
9
10
  /coverage
data/README.md CHANGED
@@ -12,15 +12,31 @@ gem "nav-logger"
12
12
 
13
13
  And then execute:
14
14
 
15
- $ bundle
15
+ `$ bundle`
16
16
 
17
17
  Or install it yourself as:
18
18
 
19
- $ gem install nav-logger
19
+ `$ gem install nav-logger`
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
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 ||= ::Logger::DEBUG
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
- log_hash = generate_log_hash severity_name, message, hash
55
- @fluent_logger.post tag(severity_name), log_hash
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(severity, message, input)
87
+ def generate_log_hash(input = {})
72
88
  hash = input.merge RequestStore.store
73
- hash.merge! message: message,
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
- hash
91
+ hostname: hostname,
92
+ pid: pid
79
93
  end
80
94
 
81
- def tag(severity)
82
- [app_tag, severity.downcase].compact.join "."
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,11 @@
1
+ module Nav
2
+ module Logger
3
+ class FileLogger < BaseLogger
4
+ def initialize(path)
5
+ @fluent_logger = Fluent::Logger::ConsoleLogger.new path
6
+ io = @fluent_logger.instance_variable_get "@io"
7
+ io.sync = true
8
+ end
9
+ end
10
+ end
11
+ 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
@@ -1,5 +1,5 @@
1
1
  module Nav
2
2
  module Logger
3
- VERSION = "0.0.1".freeze
3
+ VERSION = "0.0.4".freeze
4
4
  end
5
5
  end
data/nav-logger.gemspec CHANGED
@@ -21,5 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_dependency "fluent-logger", "~> 0.6.1"
24
- spec.add_dependency "request_store"
24
+ spec.add_dependency "request_store", "~> 1.3.2"
25
25
  end
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.1
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: 2016-12-08 00:00:00.000000000 Z
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: '0'
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: '0'
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.1
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: