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 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
@@ -1,4 +1,4 @@
1
- Copyright 2012 YOURNAME
1
+ Copyright 2012 Jeffrey Jones
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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. While this is supported in Logstash and Elastic Search the web
86
- interfaces do not as yet support it. Depending on whether support is possible or not Yarder may
87
- change to a non-nested format.
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
@@ -1,5 +1,6 @@
1
1
  require 'yarder/railtie' if defined?(Rails)
2
2
  require 'yarder/rack/logger'
3
+ require 'yarder/event'
3
4
  require 'logstash-event'
4
5
  require 'yarder/logger'
5
6
  require 'yarder/tagged_logging'
@@ -19,7 +19,8 @@ module Yarder
19
19
  def process_action(event)
20
20
 
21
21
  payload = event.payload
22
- additions = ::ActionController::Base.log_process_action(payload)
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
- entry.fields['sql'] << sql_entry
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
- entry.fields['sql'] << sql_entry
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
- def entry
70
- Yarder.log_entries[Thread.current]
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
- class Object
4
- # An object is blank if it's false, empty, or a whitespace string.
5
- # For example, '', ' ', +nil+, [], and {} are all blank.
6
- #
7
- # This simplifies:
8
- #
9
- # if address.nil? || address.empty?
10
- #
11
- # ...to:
12
- #
13
- # if address.blank?
14
- def blank?
15
- respond_to?(:empty?) ? empty? : !self
16
- end
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
- # An object is present if it's not <tt>blank?</tt>.
19
- def present?
20
- !blank?
21
- end
22
+ # An object is present if it's not <tt>blank?</tt>.
23
+ def present?
24
+ !blank?
25
+ end
22
26
 
23
- # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
24
- # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
25
- #
26
- # This is handy for any representation of objects where blank is the same
27
- # as not present at all. For example, this simplifies a common check for
28
- # HTTP POST/query parameters:
29
- #
30
- # state = params[:state] if params[:state].present?
31
- # country = params[:country] if params[:country].present?
32
- # region = state || country || 'US'
33
- #
34
- # ...becomes:
35
- #
36
- # region = params[:state].presence || params[:country].presence || 'US'
37
- def presence
38
- self if present?
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
- # +nil+ is blank:
44
- #
45
- # nil.blank? # => true
46
- def blank?
47
- true
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
- # +false+ is blank:
53
- #
54
- # false.blank? # => true
55
- def blank?
56
- true
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
- # +true+ is not blank:
62
- #
63
- # true.blank? # => false
64
- def blank?
65
- false
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
- # An array is blank if it's empty:
71
- #
72
- # [].blank? # => true
73
- # [1,2,3].blank? # => false
74
- alias_method :blank?, :empty?
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
- # A hash is blank if it's empty:
79
- #
80
- # {}.blank? # => true
81
- # { key: 'value' }.blank? # => false
82
- alias_method :blank?, :empty?
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
- # A string is blank if it's empty or contains whitespaces only:
87
- #
88
- # ''.blank? # => true
89
- # ' '.blank? # => true
90
- # ' '.blank? # => true
91
- # ' something here '.blank? # => false
92
- def blank?
93
- self !~ /[^[:space:]]/
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
- # No number is blank:
99
- #
100
- # 1.blank? # => false
101
- # 0.blank? # => false
102
- def blank?
103
- false
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
@@ -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
@@ -13,7 +13,7 @@ module Yarder
13
13
  t1 = Time.now
14
14
  request = ActionDispatch::Request.new(env)
15
15
 
16
- event = LogStash::Event.new
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, event| result += event[:duration].to_f }
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
- Rails.logger.info event
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 == LogStash::Event
23
+ if msg.class == Yarder::Event
24
24
  @entry = msg
25
25
  else
26
- @entry = LogStash::Event.new
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
@@ -1,3 +1,3 @@
1
1
  module Yarder
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end