yarder 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +1 -1
- data/README.md +17 -4
- data/lib/yarder.rb +1 -0
- data/lib/yarder/action_controller/log_subscriber.rb +2 -1
- data/lib/yarder/active_record/log_subscriber.rb +19 -6
- data/lib/yarder/core_ext/object/blank.rb +93 -88
- data/lib/yarder/event.rb +44 -0
- data/lib/yarder/rack/logger.rb +4 -22
- data/lib/yarder/tagged_logging.rb +3 -3
- data/lib/yarder/version.rb +1 -1
- data/test/active_record/log_subscriber_test.rb +4 -4
- data/test/core_ext/blank_test.rb +31 -0
- data/test/dummy/log/test.log +620 -10694
- data/test/test_helper.rb +9 -0
- metadata +97 -111
- data/lib/yarder/configuration.rb +0 -8
- data/test/dummy/log/development.log +0 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c5946b3b2b8f0f66e24c29b4f368815de55e5824
|
4
|
+
data.tar.gz: 97f4b3b4ca339f3f8784fdf915b744102f1d0eb7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8fc443ac309df22ba604677f4f3e6665b9ed6aabce70859e66b98c6b61b0b995a8cad72c4952c53e3bb4400874d0661979bc2cc8517109687b5ea52067256dbd
|
7
|
+
data.tar.gz: 48f42076840462615c8ac7c07bc48b3b676e0594e0d400e3d2e1b789fce49997f67651915ab202e9eb194df44a904a8c752ffc5b55b6429daf43b7e24da21c44
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Yarder
|
2
2
|
|
3
3
|
[![Build Status](https://secure.travis-ci.org/rurounijones/yarder.png)](http://travis-ci.org/rurounijones/yarder)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/rurounijones/yarder/badge.png?branch=master)](https://coveralls.io/r/rurounijones/yarder)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/rurounijones/yarder.png)](https://codeclimate.com/github/rurounijones/yarder)
|
4
6
|
[![Dependency Status](https://gemnasium.com/rurounijones/yarder.png)](https://gemnasium.com/rurounijones/yarder)
|
5
|
-
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rurounijones/yarder)
|
6
7
|
|
7
8
|
JSON Based Replacement logging system for Ruby on Rails.
|
8
9
|
|
@@ -82,6 +83,18 @@ serialized Logstash::Event entries there is no need to setup any filters
|
|
82
83
|
|
83
84
|
### Known issues
|
84
85
|
|
85
|
-
Yarder currently creates nested JSON.
|
86
|
-
|
87
|
-
|
86
|
+
Yarder currently creates nested JSON. Kibana has pretty good (With a few small UI problems) support
|
87
|
+
for nested JSON but logstash web does not.
|
88
|
+
|
89
|
+
## Developers
|
90
|
+
|
91
|
+
Thoughts, suggestions, opinions and contributions are welcome.
|
92
|
+
|
93
|
+
When contributing please make sure to run your tests with warnings enabled and make sure that
|
94
|
+
yarder creates no warnings. (Warnings from other libraries like capybara etc. are ok)
|
95
|
+
|
96
|
+
```
|
97
|
+
RUBYOPT=-w rake
|
98
|
+
```
|
99
|
+
|
100
|
+
|
data/lib/yarder.rb
CHANGED
@@ -19,7 +19,8 @@ module Yarder
|
|
19
19
|
def process_action(event)
|
20
20
|
|
21
21
|
payload = event.payload
|
22
|
-
additions
|
22
|
+
#TODO Think about additions. Comment out for the moment to shut up warnings
|
23
|
+
#additions = ::ActionController::Base.log_process_action(payload)
|
23
24
|
|
24
25
|
params = payload[:params].except(*INTERNAL_PARAMS)
|
25
26
|
entry.fields['parameters'] = params unless params.empty?
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
|
1
3
|
module Yarder
|
2
4
|
module ActiveRecord
|
3
5
|
class LogSubscriber < ::ActiveSupport::LogSubscriber
|
@@ -27,7 +29,6 @@ module Yarder
|
|
27
29
|
|
28
30
|
return if 'SCHEMA' == payload[:name]
|
29
31
|
|
30
|
-
entry.fields['sql'] ||= []
|
31
32
|
sql_entry = {}
|
32
33
|
sql_entry['name'] = payload[:name]
|
33
34
|
sql_entry['duration'] = event.duration
|
@@ -43,7 +44,7 @@ module Yarder
|
|
43
44
|
|
44
45
|
sql_entry['binds'] = binds unless binds.nil?
|
45
46
|
|
46
|
-
|
47
|
+
write_entry sql_entry
|
47
48
|
end
|
48
49
|
|
49
50
|
def identity(event)
|
@@ -56,18 +57,30 @@ module Yarder
|
|
56
57
|
sql_entry['line'] = payload[:line]
|
57
58
|
sql_entry['duration'] = payload[:duration]
|
58
59
|
|
59
|
-
|
60
|
+
write_entry sql_entry
|
60
61
|
end
|
61
62
|
|
62
63
|
private
|
63
64
|
|
65
|
+
def write_entry(sql_entry)
|
66
|
+
entry = log_entry
|
67
|
+
entry.fields['sql'] ||= []
|
68
|
+
entry.fields['sql'] << sql_entry
|
69
|
+
entry.write(false)
|
70
|
+
end
|
71
|
+
|
64
72
|
def logger
|
65
73
|
::ActiveRecord::Base.logger
|
66
74
|
end
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
def log_entry
|
77
|
+
Yarder.log_entries[Thread.current] ||
|
78
|
+
Yarder::Event.new(Rails.logger, false).tap do |entry|
|
79
|
+
entry.fields['uuid'] = SecureRandom.uuid
|
80
|
+
#TODO Should really move this into the base logger
|
81
|
+
entry.source = Socket.gethostname
|
82
|
+
entry.type = "rails_json_log"
|
83
|
+
end
|
71
84
|
end
|
72
85
|
|
73
86
|
end
|
@@ -1,105 +1,110 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
# This file is copied verbatim from ActiveSupport for compatibility
|
4
|
+
# should yarder be used outside of a Rails project. Therefor we
|
5
|
+
# won't process this file if ActiveSupport is already defined
|
6
|
+
unless defined?(ActiveSupport)
|
7
|
+
class Object
|
8
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
9
|
+
# For example, '', ' ', +nil+, [], and {} are all blank.
|
10
|
+
#
|
11
|
+
# This simplifies:
|
12
|
+
#
|
13
|
+
# if address.nil? || address.empty?
|
14
|
+
#
|
15
|
+
# ...to:
|
16
|
+
#
|
17
|
+
# if address.blank?
|
18
|
+
def blank?
|
19
|
+
respond_to?(:empty?) ? empty? : !self
|
20
|
+
end
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
# An object is present if it's not <tt>blank?</tt>.
|
23
|
+
def present?
|
24
|
+
!blank?
|
25
|
+
end
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
# Returns object if it's <tt>present?</tt> otherwise returns +nil+.
|
28
|
+
# <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
|
29
|
+
#
|
30
|
+
# This is handy for any representation of objects where blank is the same
|
31
|
+
# as not present at all. For example, this simplifies a common check for
|
32
|
+
# HTTP POST/query parameters:
|
33
|
+
#
|
34
|
+
# state = params[:state] if params[:state].present?
|
35
|
+
# country = params[:country] if params[:country].present?
|
36
|
+
# region = state || country || 'US'
|
37
|
+
#
|
38
|
+
# ...becomes:
|
39
|
+
#
|
40
|
+
# region = params[:state].presence || params[:country].presence || 'US'
|
41
|
+
def presence
|
42
|
+
self if present?
|
43
|
+
end
|
39
44
|
end
|
40
|
-
end
|
41
45
|
|
42
|
-
class NilClass
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
class NilClass
|
47
|
+
# +nil+ is blank:
|
48
|
+
#
|
49
|
+
# nil.blank? # => true
|
50
|
+
def blank?
|
51
|
+
true
|
52
|
+
end
|
48
53
|
end
|
49
|
-
end
|
50
54
|
|
51
|
-
class FalseClass
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
class FalseClass
|
56
|
+
# +false+ is blank:
|
57
|
+
#
|
58
|
+
# false.blank? # => true
|
59
|
+
def blank?
|
60
|
+
true
|
61
|
+
end
|
57
62
|
end
|
58
|
-
end
|
59
63
|
|
60
|
-
class TrueClass
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
class TrueClass
|
65
|
+
# +true+ is not blank:
|
66
|
+
#
|
67
|
+
# true.blank? # => false
|
68
|
+
def blank?
|
69
|
+
false
|
70
|
+
end
|
66
71
|
end
|
67
|
-
end
|
68
72
|
|
69
|
-
class Array
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
73
|
+
class Array
|
74
|
+
# An array is blank if it's empty:
|
75
|
+
#
|
76
|
+
# [].blank? # => true
|
77
|
+
# [1,2,3].blank? # => false
|
78
|
+
alias_method :blank?, :empty?
|
79
|
+
end
|
76
80
|
|
77
|
-
class Hash
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
81
|
+
class Hash
|
82
|
+
# A hash is blank if it's empty:
|
83
|
+
#
|
84
|
+
# {}.blank? # => true
|
85
|
+
# { key: 'value' }.blank? # => false
|
86
|
+
alias_method :blank?, :empty?
|
87
|
+
end
|
84
88
|
|
85
|
-
class String
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
89
|
+
class String
|
90
|
+
# A string is blank if it's empty or contains whitespaces only:
|
91
|
+
#
|
92
|
+
# ''.blank? # => true
|
93
|
+
# ' '.blank? # => true
|
94
|
+
# ' '.blank? # => true
|
95
|
+
# ' something here '.blank? # => false
|
96
|
+
def blank?
|
97
|
+
self !~ /[^[:space:]]/
|
98
|
+
end
|
94
99
|
end
|
95
|
-
end
|
96
100
|
|
97
|
-
class Numeric #:nodoc:
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
class Numeric #:nodoc:
|
102
|
+
# No number is blank:
|
103
|
+
#
|
104
|
+
# 1.blank? # => false
|
105
|
+
# 0.blank? # => false
|
106
|
+
def blank?
|
107
|
+
false
|
108
|
+
end
|
104
109
|
end
|
105
|
-
end
|
110
|
+
end
|
data/lib/yarder/event.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Yarder
|
2
|
+
|
3
|
+
# Basically a wrapper for a LogStash event that keeps track of if it was created from a rack
|
4
|
+
# middle-ware or not. This is important when it comes to deciding when to write the log
|
5
|
+
class Event
|
6
|
+
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@logstash_event, :fields, :message=, :source=, :type=, :tags, :to_json
|
9
|
+
|
10
|
+
def initialize(logger, rack = false)
|
11
|
+
@logger = logger
|
12
|
+
@rack = rack
|
13
|
+
@logstash_event = LogStash::Event.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(rack = false)
|
17
|
+
if @rack
|
18
|
+
@logger.info self if rack
|
19
|
+
else
|
20
|
+
@logger.info self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_tags_to_logger(request, tags)
|
25
|
+
tag_hash = []
|
26
|
+
if tags
|
27
|
+
tags.each do |tag|
|
28
|
+
case tag
|
29
|
+
when Symbol
|
30
|
+
tag_hash << {tag.to_s => request.send(tag) }
|
31
|
+
when Proc
|
32
|
+
tag_hash << tag.call(request)
|
33
|
+
else
|
34
|
+
tag_hash << tag
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
@logger.push_request_tags(tag_hash)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/lib/yarder/rack/logger.rb
CHANGED
@@ -13,7 +13,7 @@ module Yarder
|
|
13
13
|
t1 = Time.now
|
14
14
|
request = ActionDispatch::Request.new(env)
|
15
15
|
|
16
|
-
event =
|
16
|
+
event = Yarder::Event.new(Rails.logger, true)
|
17
17
|
event.message = "#{request.request_method} #{request.filtered_path} for #{request.ip}"
|
18
18
|
event.fields['client_ip'] = request.ip
|
19
19
|
event.fields['method'] = request.request_method
|
@@ -22,7 +22,7 @@ module Yarder
|
|
22
22
|
event.source = "http://#{Socket.gethostname}#{request.filtered_path}"
|
23
23
|
event.type = "rails_json_log"
|
24
24
|
|
25
|
-
add_tags_to_logger(request) if @tags
|
25
|
+
event.add_tags_to_logger(request, @tags) if @tags
|
26
26
|
|
27
27
|
Yarder.log_entries[Thread.current] = event
|
28
28
|
|
@@ -36,35 +36,17 @@ module Yarder
|
|
36
36
|
|
37
37
|
['rendering','sql'].each do |type|
|
38
38
|
if event.fields[type] && !event.fields[type].empty?
|
39
|
-
duration = event.fields[type].inject(0) {|result,
|
39
|
+
duration = event.fields[type].inject(0) {|result, local_event| result += local_event[:duration].to_f }
|
40
40
|
event.fields["#{type}_duration"] = duration
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
event.write(true)
|
45
45
|
end
|
46
46
|
|
47
47
|
Yarder.log_entries[Thread.current] = nil
|
48
48
|
end
|
49
49
|
|
50
|
-
def add_tags_to_logger(request)
|
51
|
-
tags = []
|
52
|
-
if @tags
|
53
|
-
@tags.each do |tag|
|
54
|
-
case tag
|
55
|
-
when Symbol
|
56
|
-
tags << {tag.to_s => request.send(tag) }
|
57
|
-
when Proc
|
58
|
-
tags << tag.call(request)
|
59
|
-
else
|
60
|
-
tags << tag
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
Rails.logger.push_request_tags(tags)
|
66
|
-
end
|
67
|
-
|
68
50
|
end
|
69
51
|
|
70
52
|
end
|
@@ -20,10 +20,10 @@ module Yarder
|
|
20
20
|
# This method is invoked when a log event occurs.
|
21
21
|
def call(severity, timestamp, progname, msg)
|
22
22
|
@entry = nil
|
23
|
-
if msg.class ==
|
23
|
+
if msg.class == Yarder::Event
|
24
24
|
@entry = msg
|
25
25
|
else
|
26
|
-
@entry =
|
26
|
+
@entry = Yarder::Event.new(Rails.logger)
|
27
27
|
@entry.message = msg
|
28
28
|
end
|
29
29
|
@entry.fields['severity'] = severity
|
@@ -99,4 +99,4 @@ module Yarder
|
|
99
99
|
super if defined?(super)
|
100
100
|
end
|
101
101
|
end
|
102
|
-
end
|
102
|
+
end
|
data/lib/yarder/version.rb
CHANGED