yarder 0.0.1 → 0.0.2
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 +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
|
[](http://travis-ci.org/rurounijones/yarder)
|
4
|
+
[](https://coveralls.io/r/rurounijones/yarder)
|
5
|
+
[](https://codeclimate.com/github/rurounijones/yarder)
|
4
6
|
[](https://gemnasium.com/rurounijones/yarder)
|
5
|
-
[](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