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 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: