timber 2.3.1 → 2.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59d540abaf18455d2ed3bb663a6b8755992bdc88
4
- data.tar.gz: fd29e089bb551f04526b552e45e0e339f1e95cd1
3
+ metadata.gz: 373352a84897146620f309326fc062b02878325a
4
+ data.tar.gz: 96e89b0e9e0fed80d606e24878f8913e57e41905
5
5
  SHA512:
6
- metadata.gz: 2df3da2bf20cff199711dc7f4ea0fd39dadb1e0f633eb09ce8ad5a227f29bde610bfa088b886a246146dfebc930ae17508a54483c5a78873397f48fe29725268
7
- data.tar.gz: 900064525472d70003a8345ef73c08b31d51386c561658aaedee4e4236cfc0534fb79ba63f3a0b0ca5351340be1582ccce3b33b2ec74c05f20ebe65493a50dc4
6
+ metadata.gz: 2d51f28a5d9a87976411f2b72ccfc20ab2048df76f97fed76a0529aa96950e971d7dff8b62dc6f5a83e5f92a0acf9572a148e6ef8e9ee83dae2872bdb54c2efc
7
+ data.tar.gz: b5b37925111a637b8eae96901660f15801b94501f191a4100d65e15539f6115bf4e1bc823be695d98ffff2f462918aeb1fc2fb8661e0550e3f303096588ab80c
data/.travis.yml CHANGED
@@ -5,8 +5,9 @@ rvm:
5
5
  - 1.9.3
6
6
  - 2.2.6
7
7
  - 2.3.3
8
- - 2.4.1
9
- - jruby
8
+ - 2.4.2
9
+ - jruby-1.7.26
10
+ - jruby-9.1.9.0
10
11
  gemfile:
11
12
  - gemfiles/rails-3.0.gemfile
12
13
  - gemfiles/rails-3.1.gemfile
@@ -14,7 +15,6 @@ gemfile:
14
15
  - gemfiles/rails-4.0.gemfile
15
16
  - gemfiles/rails-4.1.gemfile
16
17
  - gemfiles/rails-4.2.gemfile
17
- - gemfiles/rails-4.2.gemfile
18
18
  - gemfiles/rails-5.0.gemfile
19
19
  - gemfiles/rails-5.1.gemfile
20
20
  - gemfiles/rails-edge.gemfile
@@ -38,15 +38,10 @@ matrix:
38
38
  gemfile: "gemfiles/rails-3.2.gemfile"
39
39
  allow_failures:
40
40
  - rvm: 1.9.3 # bundler wont install the gems
41
- - rvm: 2.4.1
42
- - rvm: jruby
43
- gemfile: gemfiles/rails-3.0.gemfile
44
- - rvm: jruby
45
- gemfile: gemfiles/rails-5.0.gemfile
46
- - rvm: jruby
47
- gemfile: gemfiles/rails-5.1.gemfile
48
- - rvm: jruby
49
- gemfile: gemfiles/rails-edge.gemfile
41
+ - rvm: 2.4.2
42
+ gemfile: gemfiles/rails-4.0.gemfile
43
+ - rvm: 2.4.2
44
+ gemfile: gemfiles/rails-4.1.gemfile
50
45
  notifications:
51
46
  email: false
52
47
  slack:
data/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.3.2] - 2017-09-27
11
+
12
+ ### Fixed
13
+
14
+ - Drop ASCII-8BIT (binary) data before encoding to JSON. This resolves encoding errors during
15
+ this process.
16
+
10
17
  ## [2.3.1] - 2017-09-26
11
18
 
12
19
  ### Fixed
@@ -52,7 +59,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
52
59
  instead of applying back pressure.
53
60
 
54
61
 
55
- [Unreleased]: https://github.com/timberio/timber-ruby/compare/v2.3.1...HEAD
62
+ [Unreleased]: https://github.com/timberio/timber-ruby/compare/v2.3.2...HEAD
63
+ [2.3.2]: https://github.com/timberio/timber-ruby/compare/v2.3.1...v2.3.2
56
64
  [2.3.1]: https://github.com/timberio/timber-ruby/compare/v2.3.0...v2.3.1
57
65
  [2.3.0]: https://github.com/timberio/timber-ruby/compare/v2.2.2...v2.3.0
58
66
  [2.2.2]: https://github.com/timberio/timber-ruby/compare/v2.2.2...v2.2.3
@@ -8,6 +8,7 @@ module Timber
8
8
  # Represents a new log entry into the log. This is an intermediary class between
9
9
  # `Logger` and the log device that you set it up with.
10
10
  class LogEntry #:nodoc:
11
+ BINARY_LIMIT_THRESHOLD = 1_000.freeze
11
12
  DT_PRECISION = 6.freeze
12
13
  MESSAGE_MAX_BYTES = 8192.freeze
13
14
  SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/v3.1.1/schema.json".freeze
@@ -73,7 +74,30 @@ module Timber
73
74
  hash
74
75
  end
75
76
 
76
- Util::Hash.deep_compact(hash)
77
+ # Preparing a log event for JSON should remove any blank values. Timber strictly
78
+ # validates incoming data, including message size. Blank values will fail validation.
79
+ # Moreover, binary data (ASCII-8BIT) generally cannot be encoded into JSON because it
80
+ # contains characters outside of the valid UTF-8 space.
81
+ Util::Hash.deep_reduce(hash) do |k, v, h|
82
+ # Discard blank values
83
+ if !v.nil? && (!v.respond_to?(:length) || v.length > 0)
84
+ # If the value is a binary string, give it special treatment
85
+ if v.respond_to?(:encoding) && v.encoding == ::Encoding::ASCII_8BIT
86
+ # Only keep binary values less than a certain size. Sizes larger than this
87
+ # are almost always file uploads and data we do not want to log.
88
+ if v.length < BINARY_LIMIT_THRESHOLD
89
+ # Attempt to safely encode the data to UTF-8
90
+ encoded_value = encode_string(v)
91
+ if !encoded_value.nil?
92
+ h[k] = encoded_value
93
+ end
94
+ end
95
+ else
96
+ # Keep all other values
97
+ h[k] = v
98
+ end
99
+ end
100
+ end
77
101
  end
78
102
 
79
103
  def inspect
@@ -112,5 +136,17 @@ module Timber
112
136
  def formatted_dt
113
137
  @formatted_dt ||= time.iso8601(DT_PRECISION)
114
138
  end
139
+
140
+ # Attempts to encode a non UTF-8 string into UTF-8, discarding invalid characters.
141
+ # If it fails, a nil is returned.
142
+ def encode_string(string)
143
+ string.encode('UTF-8', {
144
+ :invalid => :replace,
145
+ :undef => :replace,
146
+ :replace => '?'
147
+ })
148
+ rescue Exception
149
+ nil
150
+ end
115
151
  end
116
152
  end
@@ -6,19 +6,20 @@ module Timber
6
6
 
7
7
  extend self
8
8
 
9
- def deep_compact(hash)
9
+ # Deeply reduces a hash into a new hash, passing the current key, value,
10
+ # and accumulated map up to that point. This allows the caller to
11
+ # conditionally rebuild the hash.
12
+ def deep_reduce(hash, &block)
10
13
  new_hash = {}
11
14
 
12
15
  hash.each do |k, v|
13
16
  v = if v.is_a?(::Hash)
14
- deep_compact(v)
17
+ deep_reduce(v, &block)
15
18
  else
16
19
  v
17
20
  end
18
21
 
19
- if v != nil && (!v.respond_to?(:length) || v.length > 0)
20
- new_hash[k] = v
21
- end
22
+ block.call(k, v, new_hash)
22
23
  end
23
24
 
24
25
  new_hash
@@ -1,3 +1,3 @@
1
1
  module Timber
2
- VERSION = "2.3.1"
2
+ VERSION = "2.3.2"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -20,6 +20,8 @@ if !ENV["RAILS_23"]
20
20
  require File.join(File.dirname(__FILE__), 'support', 'active_record')
21
21
  end
22
22
 
23
+ RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 5_000
24
+
23
25
  RSpec.configure do |config|
24
26
  config.color = true
25
27
  config.order = :random
@@ -3,6 +3,45 @@ require "spec_helper"
3
3
  describe Timber::LogEntry, :rails_23 => true do
4
4
  let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
5
5
 
6
+ describe "#as_json" do
7
+ it "should drop nil value keys" do
8
+ event = Timber::Events::Custom.new(type: :event_type, message: "event_message", data: {a: nil})
9
+ log_entry = described_class.new("INFO", time, nil, "log message", {}, event)
10
+ hash = log_entry.as_json
11
+ expect(hash.key?(:event)).to be false
12
+ end
13
+
14
+ it "should drop blank string value keys" do
15
+ event = Timber::Events::Custom.new(type: :event_type, message: "event_message", data: {a: ""})
16
+ log_entry = described_class.new("INFO", time, nil, "log message", {}, event)
17
+ hash = log_entry.as_json
18
+ expect(hash.key?(:event)).to be false
19
+ end
20
+
21
+ it "should drop empty array value keys" do
22
+ event = Timber::Events::Custom.new(type: :event_type, message: "event_message", data: {a: []})
23
+ log_entry = described_class.new("INFO", time, nil, "log message", {}, event)
24
+ hash = log_entry.as_json
25
+ expect(hash.key?(:event)).to be false
26
+ end
27
+
28
+ it "should drop ascii-8bit (binary) value keys" do
29
+ binary = ("a" * 1001).force_encoding("ASCII-8BIT")
30
+ event = Timber::Events::Custom.new(type: :event_type, message: "event_message", data: {a: binary})
31
+ log_entry = described_class.new("INFO", time, nil, "log message", {}, event)
32
+ hash = log_entry.as_json
33
+ expect(hash.key?(:event)).to be false
34
+ end
35
+
36
+ it "should keep ascii-8bit (binary) values below the threshold" do
37
+ binary = "test".force_encoding("ASCII-8BIT")
38
+ event = Timber::Events::Custom.new(type: :event_type, message: "event_message", data: {a: binary})
39
+ log_entry = described_class.new("INFO", time, nil, "log message", {}, event)
40
+ hash = log_entry.as_json
41
+ expect(hash[:event][:custom][:event_type][:a].encoding).to eq(::Encoding::UTF_8)
42
+ end
43
+ end
44
+
6
45
  describe "#to_msgpack" do
7
46
  it "should encode properly with an event and context" do
8
47
  event = Timber::Events::Custom.new(type: :event_type, message: "event_message", data: {a: 1})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timber
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timber Technologies, Inc.