logatron 0.7.0 → 0.8.0

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: 3103d9cac1561ecd60127ba26110d18fb0fe720e
4
- data.tar.gz: d35300ec7cdc5165ec570f56faf38fc38436bf25
3
+ metadata.gz: a056f7a08b37ab427b57c039a5d5a9142e94e6a5
4
+ data.tar.gz: 58393a44fbb79cdf5b85fa6791bccd9ce47e5cc2
5
5
  SHA512:
6
- metadata.gz: 1fb22c5f504469d354b1dd7a0479ef89a45ecadd52d115c553fade502e33babb4b37c4a8eb507edae756fba59f5d0f89e4ecca17cd065e0ca998b3aca2e7b368
7
- data.tar.gz: d3476f1bde8fd841211d40b37697fe5498733a2cb3132102c3c4e27b8f7bebd83501e0cf53ce86e58a285359005b0b4eb60881ba7d18d992dad088ab04de0f30
6
+ metadata.gz: bdd6dd9bb5269402a9954f1572b6a478335678a7cdf2a2bed58d970b5d1ce72262a5a7dfc5f9b0d8b67ed2903a0b0c6e2bc7288571703d03bc0ba052d8745d76
7
+ data.tar.gz: 0e1c15b57f5ecf7a0b0bd52c18a81fa9105002270a863ab174fe3e51ddb43c1abeaef45db5922bb61e9c093e8d952a947e768b6338219e72f4407bc3a4c9c25d
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  .idea/
2
2
  .DS_Store
3
3
  *.gem
4
+ Gemfile.lock
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.2.2
1
+ 2.4.1
@@ -0,0 +1,46 @@
1
+ module Logatron
2
+ class BacktraceCleaner
3
+ # Suppress irrelevant "external" frames. In practice, these are often the frames
4
+ # leading up to the "entry point" we care about, whether that's a rails controller
5
+ # or a rabbit_stew handler.
6
+ #
7
+ # Algorithm: partition frames into contiguous external/internal chunks.
8
+ # Starting at the bottom, suppress chunks until we find the entry point chunk.
9
+
10
+ def clean(backtrace)
11
+ all_chunks = backtrace.chunk { |x| external_frame?(x) }.to_a.reverse
12
+ good_chunks = all_chunks.drop_while { |(is_ext, frames)| !entry_point_chunk?(is_ext, frames) }
13
+ bad_chunks = all_chunks.take(all_chunks.size - good_chunks.size)
14
+ good_bt = good_chunks.reverse.map(&:last).flatten
15
+ bad_bt = bad_chunks.reverse.map(&:last).flatten
16
+ good_bt + suppress(bad_bt)
17
+ rescue
18
+ # if something went wrong, give up on cleaning the backtrace
19
+ backtrace
20
+ end
21
+
22
+ private
23
+
24
+ # heuristic for determining externality of a frame.
25
+ # Note: bundle/gems does not include git-sourced gems (those go in
26
+ # bundle/bundler/gems), so git-sourced gems are considered internal.
27
+ def external_frame?(f)
28
+ !!(f =~ %r{bundle/gems})
29
+ end
30
+
31
+ # heuristic for finding the entry point
32
+ def entry_point_chunk?(is_ext, frames)
33
+ !is_ext && frames.size >= 3
34
+ end
35
+
36
+ def suppress(backtrace)
37
+ if backtrace.size <= 3
38
+ backtrace
39
+ else
40
+ [ backtrace.first,
41
+ "... #{backtrace.size - 2} frames suppressed ...",
42
+ backtrace.last ]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,6 +1,8 @@
1
1
  require 'logger'
2
2
  require 'logatron/const'
3
3
  require 'logatron/basic_formatter'
4
+ require 'logatron/error_formatter'
5
+ require 'logatron/backtrace_cleaner'
4
6
  require 'active_support/backtrace_cleaner'
5
7
  require 'active_support/json'
6
8
 
@@ -21,7 +23,7 @@ module Logatron
21
23
  end
22
24
 
23
25
  class Configuration
24
- attr_accessor :logger, :host, :level, :transformer, :app_id
26
+ attr_accessor :logger, :host, :level, :transformer, :app_id, :error_formatter
25
27
  attr_reader :loggable_levels, :backtrace_cleaner
26
28
 
27
29
  def initialize
@@ -33,10 +35,8 @@ module Logatron
33
35
  level_threshold = SEVERITY_MAP[@level]
34
36
  levels = Logatron::SEVERITY_MAP.keys
35
37
  @loggable_levels = levels.select { |level| SEVERITY_MAP[level] >= level_threshold }
36
- bc = ActiveSupport::BacktraceCleaner.new
37
- bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } if defined? Rails
38
- bc.add_silencer { |line| line =~ /gems/ }
39
- @backtrace_cleaner = bc
38
+ @backtrace_cleaner = Logatron::BacktraceCleaner.new
39
+ @error_formatter = Logatron::ErrorFormatter.new
40
40
  end
41
41
 
42
42
  def logger=(logger)
@@ -0,0 +1,67 @@
1
+ require 'abstractivator/enumerator_ext'
2
+
3
+ module Logatron
4
+ class ErrorFormatter
5
+ def format_short_message(e)
6
+ "#{e.class}: #{e.message}"
7
+ end
8
+
9
+ def format_full_message(e, additional_info = nil)
10
+ format_short_message(e) + format_additional_info(e, additional_info)
11
+ end
12
+
13
+ def format_backtrace(error_or_bt)
14
+ bt = error_or_bt.is_a?(Exception) ? error_or_bt.backtrace : error_or_bt
15
+ bt.map { |f| " #{f.starts_with?('...') ? f : "at #{f}"}\n" }.join
16
+ end
17
+
18
+ def format_additional_info(e, additional_info = nil)
19
+ info = additional_info || (e.respond_to?(:meta) && e.meta)
20
+ info ? "; MORE_INFO( #{info.to_s} )" : ''
21
+ end
22
+
23
+ # Returns a human-readable exception report.
24
+ # Includes nested exception information.
25
+ # Suppresses duplicate frames in nested exception backtraces.
26
+ def format_error_report(e, additional_info = nil)
27
+ error_chain = Enumerator.unfold(e) { |e| [e.cause, e.cause] }.to_a
28
+ initial_report = format_single_error(e, clean_backtrace(nil, e), additional_info)
29
+ # starting with the outermost error, reduce the error chain into the formatted report
30
+ error_chain.reduce([e, initial_report]) do |(prev_e, report), e|
31
+ new_report = format_single_error(e, clean_backtrace(prev_e, e)) + " which caused:\n " + report
32
+ [e, new_report]
33
+ end[1]
34
+ rescue
35
+ # if something went wrong, fall back to something simpler
36
+ format_short_message(e) + "\n" + e.backtrace.join("\n")
37
+ end
38
+
39
+ private
40
+
41
+ def format_single_error(e, cleaned_backtrace, additional_info = nil)
42
+ format_full_message(e, additional_info) + "\n" + format_backtrace(cleaned_backtrace)
43
+ end
44
+
45
+ def clean_backtrace(prev, e)
46
+ base_size = prev ? num_common_base_frames(prev, e) : 0
47
+ cleaned_backtrace =
48
+ if base_size > 1
49
+ num_to_suppress = base_size - 1
50
+ e.backtrace.take(e.backtrace.size - num_to_suppress) +
51
+ ["... #{num_to_suppress} frames suppressed ..."]
52
+ else
53
+ backtrace_cleaner.clean(e.backtrace)
54
+ end
55
+ end
56
+
57
+ def backtrace_cleaner
58
+ Logatron.configuration.backtrace_cleaner
59
+ end
60
+
61
+ def num_common_base_frames(e1, e2)
62
+ e1.backtrace.reverse.zip(e2.backtrace.reverse)
63
+ .take_while { |(a, b)| a == b }
64
+ .size
65
+ end
66
+ end
67
+ end
@@ -2,7 +2,9 @@ require 'active_support/all'
2
2
  require 'logatron/version'
3
3
  require 'logatron/const'
4
4
  require 'logatron/contexts'
5
+ require 'logatron/error_formatter'
5
6
  require 'logatron/message_formatting'
7
+ require 'logatron/backtrace_cleaner'
6
8
  require 'logatron/basic_scoped_logger'
7
9
  require 'logatron/basic_formatter'
8
10
  require 'logatron/basic_logger'
@@ -16,10 +18,10 @@ module Logatron
16
18
  @log ||= Logatron::BasicLogger.new
17
19
  end
18
20
 
21
+ # @param additional_info [Object] Typically a flat hash, but can be anything that responds to '#to_s'
19
22
  def log_exception(e, severity, additional_info = {})
20
- # 'additional_info' can be a flat hash or anything with '#to_s'
21
- message = exception_message(e, additional_info)
22
- logger.send(severity.downcase, message)
23
+ error_report = configuration.error_formatter.format_error_report(e, additional_info)
24
+ logger.send(severity.downcase, error_report)
23
25
  end
24
26
 
25
27
  def level=(level)
@@ -90,14 +92,5 @@ module Logatron
90
92
  def msg_id=(id)
91
93
  Logatron::Contexts.msg_id = id
92
94
  end
93
-
94
- private
95
-
96
- def exception_message(e, additional)
97
- info = additional.is_a?(Hash) ? additional.map { |(k, v)| "#{k}=>#{v}" }.join(', ') : additional
98
- info_msg = info.nil? || info.empty? ? '' : "; MORE_INFO( #{info} )"
99
- backtrace = configuration.backtrace_cleaner.clean(e.backtrace).join(' -> ')
100
- "#{e.class} #{e.message}#{info_msg} -> #{backtrace}"
101
- end
102
95
  end
103
96
  end
data/logatron.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'logatron/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'logatron'
8
- spec.version = '0.7.0'
8
+ spec.version = '0.8.0'
9
9
  spec.authors = ['Justin Grimes']
10
10
  spec.email = ['justin.mgrimes@gmail.com']
11
11
 
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ['lib']
20
20
  spec.add_runtime_dependency 'activesupport', '< 6.0', '>= 4.2.1'
21
+ spec.add_runtime_dependency 'abstractivator', '~> 0.16.0'
21
22
  spec.add_development_dependency 'bundler', '~> 1.10'
22
23
  spec.add_development_dependency 'rake', '~> 10.0'
23
24
  spec.add_development_dependency 'rspec', '~> 3'
data/update_version.sh CHANGED
@@ -8,7 +8,6 @@ SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"
8
8
 
9
9
  updateVersion(){
10
10
  updateGemspec
11
- updateLockfile
12
11
  commitStagedFiles "Update version to ${VERSION}"
13
12
  }
14
13
 
@@ -19,13 +18,6 @@ updateGemspec(){
19
18
  stageFiles "${gemspecPath}"
20
19
  }
21
20
 
22
- updateLockfile(){
23
- echo -e "\nUpdating lockfile"
24
- bundle package --no-install > /dev/null
25
- rm -rf .bundle/ vendor/
26
- stageFiles "${SCRIPT_DIR}/Gemfile.lock"
27
- }
28
-
29
21
  stageAndCommit(){
30
22
  local msg="$1"
31
23
  shift
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Grimes
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-01 00:00:00.000000000 Z
11
+ date: 2017-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 4.2.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: abstractivator
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.16.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.16.0
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: bundler
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -98,18 +112,19 @@ files:
98
112
  - CHANGES.md
99
113
  - CODE_OF_CONDUCT.md
100
114
  - Gemfile
101
- - Gemfile.lock
102
115
  - README.md
103
116
  - Rakefile
104
117
  - bin/console
105
118
  - bin/setup
106
119
  - build.yml
120
+ - lib/logatron/backtrace_cleaner.rb
107
121
  - lib/logatron/basic_formatter.rb
108
122
  - lib/logatron/basic_logger.rb
109
123
  - lib/logatron/basic_scoped_logger.rb
110
124
  - lib/logatron/configuration.rb
111
125
  - lib/logatron/const.rb
112
126
  - lib/logatron/contexts.rb
127
+ - lib/logatron/error_formatter.rb
113
128
  - lib/logatron/logatron.rb
114
129
  - lib/logatron/message_formatting.rb
115
130
  - lib/logatron/railtie.rb
@@ -135,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
150
  version: '0'
136
151
  requirements: []
137
152
  rubyforge_project:
138
- rubygems_version: 2.6.2
153
+ rubygems_version: 2.6.12
139
154
  signing_key:
140
155
  specification_version: 4
141
156
  summary: Logging for ascent
142
157
  test_files: []
143
- has_rdoc:
data/Gemfile.lock DELETED
@@ -1,53 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- logatron (0.6.0)
5
- activesupport (>= 4.2.1, < 6.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activesupport (4.2.7.1)
11
- i18n (~> 0.7)
12
- json (~> 1.7, >= 1.7.7)
13
- minitest (~> 5.1)
14
- thread_safe (~> 0.3, >= 0.3.4)
15
- tzinfo (~> 1.1)
16
- builder (3.2.2)
17
- diff-lcs (1.2.5)
18
- i18n (0.7.0)
19
- json (1.8.3)
20
- minitest (5.9.1)
21
- rake (10.4.2)
22
- rspec (3.3.0)
23
- rspec-core (~> 3.3.0)
24
- rspec-expectations (~> 3.3.0)
25
- rspec-mocks (~> 3.3.0)
26
- rspec-core (3.3.2)
27
- rspec-support (~> 3.3.0)
28
- rspec-expectations (3.3.1)
29
- diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.3.0)
31
- rspec-mocks (3.3.2)
32
- diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.3.0)
34
- rspec-support (3.3.0)
35
- rspec_junit_formatter (0.2.3)
36
- builder (< 4)
37
- rspec-core (>= 2, < 4, != 2.12.0)
38
- thread_safe (0.3.5)
39
- tzinfo (1.2.2)
40
- thread_safe (~> 0.1)
41
-
42
- PLATFORMS
43
- ruby
44
-
45
- DEPENDENCIES
46
- bundler (~> 1.10)
47
- logatron!
48
- rake (~> 10.0)
49
- rspec (~> 3)
50
- rspec_junit_formatter (~> 0.2.0)
51
-
52
- BUNDLED WITH
53
- 1.13.1