logrithm 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2641dcf0038e8cd1fc2df39d52136413be3c974c
4
+ data.tar.gz: e41c59225bd7dc8c3145e0fb9ccc784fa9489363
5
+ SHA512:
6
+ metadata.gz: c45a5f6f871cba9c060c80531fa2cd98f96f430d0239ba3c0abb7630bb91dc471beedbbb3ea40621680d760cf48100cf62c914b10895eefcc58e262c54192008
7
+ data.tar.gz: e7894f3ae6bbaf81639be0ee99879b534a48543b3e274f9ec2a8c090b59321d9b45f64f7c714920d65037e2a1080554b12eebd3f61f98517710f71615b0d2dba
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,60 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ # Offense count: 6
4
+ # Cop supports --auto-correct.
5
+ # Configuration parameters: , SupportedStyles.
6
+ # SupportedStyles: only_raise, only_fail, semantic
7
+ Style/SignalException:
8
+ EnforcedStyle: semantic
9
+
10
+ Metrics/ClassLength:
11
+ Max: 200
12
+
13
+ Metrics/CyclomaticComplexity:
14
+ Max: 20
15
+
16
+ Metrics/LineLength:
17
+ Max: 180
18
+
19
+ Metrics/MethodLength:
20
+ Max: 42
21
+
22
+ Metrics/PerceivedComplexity:
23
+ Max: 20
24
+
25
+ Metrics/AbcSize:
26
+ Max: 42
27
+
28
+ Style/EmptyCaseCondition:
29
+ Exclude:
30
+ - 'lib/**/*'
31
+ - 'spec/**/*'
32
+
33
+ Style/AsciiIdentifiers:
34
+ Exclude:
35
+ - 'lib/**/*'
36
+ - 'spec/**/*'
37
+
38
+ Style/AsciiComments:
39
+ Exclude:
40
+ - 'lib/**/*'
41
+ - 'spec/**/*'
42
+
43
+ Style/Documentation:
44
+ Exclude:
45
+ - 'lib/**/*'
46
+ - 'spec/**/*'
47
+
48
+ Style/RaiseArgs:
49
+ Exclude:
50
+ - 'lib/**/*'
51
+
52
+ Style/SpecialGlobalVars:
53
+ Exclude:
54
+ - 'lib/**/*'
55
+ - 'spec/**/*'
56
+
57
+ Style/MultilineBlockChain:
58
+ Exclude:
59
+ - 'lib/**/*'
60
+ - 'spec/**/*'
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,47 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2016-06-09 09:39:16 +0200 using RuboCop version 0.40.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: MinBodyLength.
11
+ Style/GuardClause:
12
+ Exclude:
13
+ - 'logrithm.gemspec'
14
+
15
+ # Offense count: 1
16
+ # Cop supports --auto-correct.
17
+ Style/MutableConstant:
18
+ Exclude:
19
+ - 'lib/logrithm/version.rb'
20
+
21
+ # Offense count: 2
22
+ # Cop supports --auto-correct.
23
+ # Configuration parameters: PreferredDelimiters.
24
+ Style/PercentLiteralDelimiters:
25
+ Exclude:
26
+ - 'logrithm.gemspec'
27
+
28
+ # Offense count: 1
29
+ # Cop supports --auto-correct.
30
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
31
+ # SupportedStyles: only_raise, only_fail, semantic
32
+ Style/SignalException:
33
+ Exclude:
34
+ - 'logrithm.gemspec'
35
+
36
+ # Offense count: 17
37
+ # Cop supports --auto-correct.
38
+ # Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
39
+ # SupportedStyles: single_quotes, double_quotes
40
+ Style/StringLiterals:
41
+ Enabled: false
42
+
43
+ # Offense count: 2
44
+ # Cop supports --auto-correct.
45
+ Style/UnneededPercentQ:
46
+ Exclude:
47
+ - 'logrithm.gemspec'
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.8
4
+ before_install: gem install bundler -v 1.10.6
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in logrithm.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Aleksei Matiushkin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Logrithm
2
+
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'logrithm'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install logrithm
19
+
20
+ ## Usage
21
+
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/logrithm. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
32
+
33
+
34
+ ## License
35
+
36
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+
4
+ require 'bundler'
5
+ require 'bundler/setup'
6
+ require 'bundler/gem_tasks'
7
+
8
+ require 'rspec/core/rake_task'
9
+
10
+ begin
11
+ Bundler.setup(:default, :development, :test)
12
+ rescue Bundler::BundlerError => e
13
+ $stderr.puts e.message
14
+ $stderr.puts 'Run `bundle install` to install missing gems'
15
+ exit e.status_code
16
+ end
17
+
18
+ desc 'Tests'
19
+ RSpec::Core::RakeTask.new(:spec) do |spec|
20
+ spec.rspec_opts = '-Ispec'
21
+ # spec.rcov = true
22
+ end
23
+
24
+ task default: [:spec]
@@ -0,0 +1,41 @@
1
+ base:
2
+ error: 'Kantox::Exceptions::StandardError'
3
+ stack: 20
4
+
5
+ format:
6
+ id: '__id__'
7
+
8
+ log:
9
+ formatters:
10
+ production: 'default'
11
+ development: 'pretty'
12
+ staging: 'default'
13
+ test: 'default'
14
+ standalone: 'pretty'
15
+
16
+ nested: 7
17
+ backtrace:
18
+ len: 8
19
+ skip: 3
20
+
21
+ colors:
22
+ info:
23
+ label: '01;38;05;21'
24
+ text: '01;38;05;110'
25
+ highlight: '01;38;05;51'
26
+ exception: '01;38;05;88'
27
+ application: '01;38;05;253'
28
+ method_call: '01;38;05;253'
29
+
30
+ symbols:
31
+ info: '✔'
32
+
33
+ stopwords:
34
+ - '^Message to be suppressed'
35
+
36
+ spitters:
37
+ airbrake:
38
+ active: true
39
+ signature: 'Airbrake.notify'
40
+ sender: 'error_class'
41
+ message: 'error_message'
@@ -0,0 +1,10 @@
1
+ module Logrithm
2
+ module Formatters
3
+ module Default
4
+ def formatter
5
+ rails? ? Kernel.const_get('::Rails').logger.formatter : Logger::Formatter.new
6
+ end
7
+ module_function :formatter
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ module Logrithm
2
+ module Formatters
3
+ module Pretty
4
+ def formatter
5
+ proc do |severity, datetime, _, message|
6
+ '' <<
7
+ Log::INSTANCE.send(:lead, severity, datetime) <<
8
+ parse(message).map do |formatted|
9
+ Log::INSTANCE.send(:color, severity).last.colorize(formatted)
10
+ end.join(Logrithm::Log::JOINER) << $/
11
+ end
12
+ end
13
+ module_function :formatter
14
+
15
+ def parse(message)
16
+ return enum_for(:parse, message) unless block_given?
17
+ [*message].each do |obj|
18
+ klazz = obj.class.ancestors.inject(nil) do |memo, k|
19
+ memo || Utils::Helpers.constantize(k, Logrithm::Spitters)
20
+ end || Utils::Helpers.constantize(:string, Logrithm::Spitters)
21
+ yield klazz.new(obj).formatted
22
+ end
23
+ end
24
+ module_function :parse
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,4 @@
1
+ require 'logger'
2
+
3
+ require 'logrithm/formatters/default'
4
+ require 'logrithm/formatters/pretty'
@@ -0,0 +1,148 @@
1
+ require 'logger'
2
+ require 'io/console'
3
+
4
+ # rubocop:disable Style/GlobalVars
5
+ module Logrithm
6
+ class Log
7
+ include Kungfuig
8
+
9
+ JOINER = "#{$/} #{option(:log, :joiners, :objects) || '⮩ '}".freeze
10
+
11
+ def self.log(message)
12
+ if $♯
13
+ puts "Self: [#{$♯}], Message: [#{message}]."
14
+ else
15
+ # idx = caller.index { |s| s.include? __FILE__ } to work inside pry
16
+ Utils::Syringe.inject(*Utils::Helpers.dirty_lookup_class_method(*caller.first[/\A(.+):(\d+)(?=:in)/].split(/:(?=\d+\z)/)))
17
+ puts "Message: [#{message}]."
18
+ end
19
+ rescue
20
+ puts "Message: [#{message}]."
21
+ end
22
+
23
+ def initialize(log = nil, **params)
24
+ [
25
+ File.join(__dir__, '..', '..', 'config', 'logrithm.yml'),
26
+ (File.join(Rails.root, 'config', 'logrithm.yml') if Logrithm.rails?)
27
+ ].compact.each do |cfg|
28
+ kungfuig(cfg) if File.exist?(cfg)
29
+ end
30
+ kungfuig(params)
31
+ ensure_logger(log) if log
32
+
33
+ @leader = {}
34
+ @colors = {}
35
+ end
36
+
37
+ def logger
38
+ ensure_logger
39
+ end
40
+
41
+ def flush
42
+ logdev.flush
43
+ end
44
+
45
+ def level=(level = nil)
46
+ logger.level = level || case Logrithm.env
47
+ when :dev, :development, :test then Logger::DEBUG
48
+ else Logger::INFO
49
+ end
50
+ end
51
+
52
+ INSTANCE = Log.new
53
+ private_class_method :new
54
+
55
+ %i(debug info warn error fatal).each do |m|
56
+ define_method(m) do |*args, **extended|
57
+ logger.public_send m, (args.length == 1 && extended.empty? ? args.first : [*args, **extended])
58
+ end
59
+ end
60
+
61
+ class << self
62
+ def option(*name)
63
+ INSTANCE.option(*name)
64
+ end
65
+
66
+ def app_root
67
+ File.realpath(INSTANCE.option(:log, :root) || Logrithm.rails? && Rails.root || File.join(__dir__, '..', '..'))
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def formatter
74
+ begin
75
+ name = option :log, :formatters, Logrithm.env
76
+ Utils::Helpers.constantize name, Logrithm::Formatters
77
+ rescue NameError
78
+ Formatters::Default
79
+ end.formatter
80
+ end
81
+
82
+ def logdev
83
+ logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
84
+ end
85
+
86
+ def ensure_logger(log = nil)
87
+ return @log if @log
88
+
89
+ @log = case
90
+ when log then log
91
+ when Logrithm.rails?
92
+ Kernel.const_get('::Rails')
93
+ .logger
94
+ .instance_variable_get(:@logger)
95
+ .instance_variable_get(:@log)
96
+ else
97
+ Logger.new($stderr)
98
+ end
99
+
100
+ @tty = @log.respond_to?(:tty?) && @log.tty? ||
101
+ (l = logdev) && l.tty? ||
102
+ Logrithm.rails? && Logrithm.env == :development
103
+
104
+ # rubocop:disable Style/ParallelAssignment)
105
+ @formatter, @log.formatter = @log.formatter, formatter
106
+ # rubocop:enable Style/ParallelAssignment)
107
+
108
+ self.level = nil
109
+
110
+ @log
111
+ end
112
+
113
+ def leader(severity)
114
+ @leader[severity] ||= case Logrithm.severity(severity)
115
+ when 0 then option(:log, :symbols, :debug) || '✓'
116
+ when 1 then option(:log, :symbols, :info) || '✔'
117
+ when 2 then option(:log, :symbols, :warn) || '✗'
118
+ when 3 then option(:log, :symbols, :error) || '✘'
119
+ when 4 then option(:log, :symbols, :fatal) || '∅'
120
+ else option(:log, :symbols, :debug) || '•'
121
+ end
122
+ end
123
+
124
+ def color(severity)
125
+ @colors[severity] ||= case Logrithm.severity(severity)
126
+ when 0 then [option(:log, :colors, :debug, :label) || '#747474', option(:log, :colors, :debug, :text) || '#9C9C9C']
127
+ when 1 then [option(:log, :colors, :info, :label) || '#FF0000', option(:log, :colors, :info, :text) || '#6699CC']
128
+ when 2 then [option(:log, :colors, :warn, :label) || '#FFFF00', option(:log, :colors, :warn, :text) || '#FFCC66']
129
+ when 3 then [option(:log, :colors, :error, :label) || '#AA0000', option(:log, :colors, :error, :text) || '#CC6666']
130
+ when 4 then [option(:log, :colors, :fatal, :label) || '#FF0000', option(:log, :colors, :fatal, :text) || '#FF0000']
131
+ else [option(:log, :colors, :debug, :label) || '#747474', option(:log, :colors, :debug, :text) || '#9C9C9C']
132
+ end.map { |c| Utils::Color.new c }
133
+ end
134
+
135
+ def lead(severity, datetime = safe_now)
136
+ " " <<
137
+ color(severity).first.colorize(leader(severity)) <<
138
+ " #{Utils::Output::VB} " <<
139
+ color(:debug).first.colorize(datetime.strftime('%Y%m%d-%H%M%S.%3N')) <<
140
+ " #{Utils::Output::VB} "
141
+ end
142
+
143
+ def safe_now
144
+ Time.respond_to?(:zone) ? Time.zone.now : Time.now
145
+ end
146
+ end
147
+ end
148
+ # rubocop:enable Style/GlobalVars
@@ -0,0 +1,50 @@
1
+ begin
2
+ require 'rack/cache'
3
+ rescue LoadError
4
+ puts "Couldn't find rack-cache - make sure you have it in your Gemfile:"
5
+ puts " gem 'rack-cache', require: 'rack/cache'"
6
+ end
7
+
8
+ module Logrithm
9
+ module Middleware
10
+ class Rack
11
+ MAXREADLEN = 2048
12
+
13
+ def initialize(app, logger)
14
+ # rubocop:disable Style/ParallelAssignment
15
+ @app, @logger = app, logger
16
+ # rubocop:enable Style/ParallelAssignment
17
+ @rp, @wp = IO.pipe
18
+
19
+ Thread.new do
20
+ loop do
21
+ begin
22
+ ✍ @rp.read_nonblock(MAXREADLEN)
23
+ rescue IO::WaitReadable
24
+ IO.select([@rp])
25
+ retry
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def call(env)
32
+ IO.select(nil, [env['rack.errors'] = @wp])
33
+ @app.call(env)
34
+ end
35
+
36
+ # rubocop:disable Style/MethodName
37
+ # rubocop:disable Style/VariableName
38
+ # rubocop:disable Style/OpMethod
39
+ def ✍(what)
40
+ (@✍ ||= Logrithm::INSTANCE).rack what
41
+ end
42
+ # rubocop:enable Style/OpMethod
43
+ # rubocop:enable Style/VariableName
44
+ # rubocop:enable Style/MethodName
45
+ end
46
+ end
47
+ end
48
+
49
+ Rails.application.middleware
50
+ .insert_before Rack::Cache, Logrithm::Middleware::Rack, :logrithm if Logrithm.rails?
@@ -0,0 +1,54 @@
1
+ module Logrithm
2
+ module Spitters
3
+ class Wrapper < StandardError
4
+ end
5
+
6
+ class Exception
7
+ BACKTRACE_LENGTH = Logrithm::Log.option(:log, :backtrace, :len) || 8
8
+
9
+ def initialize(e)
10
+ @e = e.is_a?(::Exception) ? e : Wrapper.new(e.inspect)
11
+ end
12
+
13
+ def formatted
14
+ formatted = format(@e)
15
+
16
+ msg = [
17
+ "Error: #{formatted[:causes].map { |c| "⟨#{c.class}⟩ (“#{c.message}”)" }.join(' ⇐ ')}",
18
+ formatted[:backtrace],
19
+ "[#{formatted[:omitted]} more]".rjust(20, '.')
20
+ ].join(joiner)
21
+ Logrithm::Utils::Output.clrz(msg, Logrithm.color(:error).last)
22
+ end
23
+
24
+ private
25
+
26
+ def joiner
27
+ "#{$/} #{Logrithm::Log.option(:log, :joiners, :exception) || '⮩ '}"
28
+ end
29
+
30
+ def format(e)
31
+ bt = e.backtrace.is_a?(Array) ? e.backtrace : caller
32
+ fbt = format_backtrace(bt)
33
+ {
34
+ causes: loop.each_with_object(causes: [], current: e) do |_, memo|
35
+ memo[:causes] << memo[:current]
36
+ memo[:current] = memo[:current].cause
37
+ break memo unless memo[:current]
38
+ end[:causes],
39
+ backtrace: fbt,
40
+ omitted: bt.size - fbt.size
41
+ }
42
+ end
43
+
44
+ def format_backtrace(backtrace)
45
+ backtrace.map.with_index do |bt, idx|
46
+ if idx < BACKTRACE_LENGTH || bt =~ /^#{Logrithm::Log.app_root}/
47
+ "[#{idx.to_s.rjust(3, ' ')}] " << \
48
+ bt.gsub(/^(#{Logrithm::Log.app_root}[^:]*):(\d+):/, "⟦\\1⟧:⟦\\2⟧: ").gsub(/`(.*?)'/, "⟬\\1⟭")
49
+ end
50
+ end.compact
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,18 @@
1
+ module Logrithm
2
+ module Spitters
3
+ class String
4
+ def initialize(obj)
5
+ @obj = obj
6
+ end
7
+
8
+ def formatted
9
+ str = case @obj
10
+ when String then @obj
11
+ when Symbol, Regexp then @obj.to_s
12
+ else @obj.inspect
13
+ end
14
+ # Logrithm::Utils::Output.clrz(str, Logrithm.color(:error).last)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+ require 'logrithm/spitters/string'
2
+ require 'logrithm/spitters/exception'
@@ -0,0 +1,303 @@
1
+ module Logrithm
2
+ module Utils
3
+ # Dealing with colors
4
+ class Color
5
+ # Copyright (c) 2007 McClain Looney
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
25
+ # Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and
26
+ # with a number of utilities to lighten, darken and blend values.
27
+
28
+ attr_reader :r, :g, :b, :a
29
+
30
+ # Table for conversion to hex
31
+ HEXVAL = ('0'..'9').to_a.concat(('A'..'F').to_a).freeze
32
+ # Default value for #darken, #lighten etc.
33
+ BRIGHTNESS_DEFAULT = 0.2
34
+ CLEAR_TERM = "\e[0m".freeze
35
+
36
+ # Constructor. Inits to white (#FFFFFF) by default, or accepts any params
37
+ # supported by #parse.
38
+ def initialize(*args)
39
+ @r = 255
40
+ @g = 255
41
+ @b = 255
42
+ @a = 255
43
+
44
+ if args.size.between?(3, 4)
45
+ self.r = args[0]
46
+ self.g = args[1]
47
+ self.b = args[2]
48
+ self.a = args[3] if args[3]
49
+ else
50
+ set(*args)
51
+ end
52
+ end
53
+
54
+ # All-purpose setter - pass in another Color, '#000000', rgb vals... whatever
55
+ def set(*args)
56
+ val = Color.parse(*args)
57
+ unless val.nil?
58
+ self.r = val.r
59
+ self.g = val.g
60
+ self.b = val.b
61
+ self.a = val.a
62
+ end
63
+ self
64
+ end
65
+
66
+ # Test for equality, accepts string vals as well, eg Color.new('aaa') == '#AAAAAA' => true
67
+ def ==(other)
68
+ val = Color.parse(other)
69
+ return false if val.nil?
70
+ r == val.r && g == val.g && b == val.b && a == val.a
71
+ end
72
+
73
+ # Setters for individual channels - take 0-255 or '00'-'FF' values
74
+ %i(r g b a).each do |m|
75
+ define_method "#{m}=" do |val|
76
+ instance_variable_set("@#{m}", from_hex(val))
77
+ end
78
+ end
79
+
80
+ # Attempt to read in a string and parse it into values
81
+ def self.parse(*args)
82
+ case args.size
83
+ when 0 then return nil
84
+ when 1
85
+ case val = args.first
86
+ when Color then val
87
+ when Fixnum then Color.new(val, val, val) # Single value, assume grayscale
88
+ when /\A(\d{,3};){1,3}\d{,3}\z/ # console
89
+ # FIXME: implememnt this
90
+ # 16 + 36 * r + 6 * g + b
91
+ case cl = val.split(';').last.to_i
92
+ when 0..15 then '#000000' # FIXME: make it working
93
+ when 232..255
94
+ Color.new(*([cl - 232] * 3).map { |c| c * 10 + 16 })
95
+ else # FIXME: the line below fails for 231, it becomes 255
96
+ r, gb = (cl - 16).divmod(36)
97
+ g, b = gb.divmod(6)
98
+ Color.new(*[r, g, b].map { |e| (51.0 * e).floor })
99
+ end
100
+ when String # assume rgb and try to guess
101
+ str = val.to_s.upcase[/[0-9A-F]{3,8}/] || ''
102
+ Color.new(*case str.length
103
+ when 3, 4 then str.scan(/[0-9A-F]/).map { |d| d * 2 }
104
+ when 6, 8 then str.scan(/[0-9A-F]{2}/)
105
+ else 'FF'
106
+ end.map { |c| Integer("0x#{c}") })
107
+ end
108
+ when 2 # assume gray + alpha
109
+ val, alpha = args
110
+ Color.new(val, val, val, alpha)
111
+ when 3, 4 then Color.new(*args)
112
+ end
113
+ end
114
+ # rubocop:enable Metrics/MethodLength
115
+ # rubocop:enable Metrics/CyclomaticComplexity
116
+
117
+ def inspect
118
+ id = format('%x', object_id << 1)
119
+ "#<#{self.class.name}:0x#{id.rjust(14, '0')} 💻=“#{to_esc(true)}███#{CLEAR_TERM}” ✎=“\\e[#{to_esc(false)}m” 🗔=“#{to_html}”>"
120
+ end
121
+
122
+ # FIXME: what we really want here?
123
+ def to_s(as_esc = true)
124
+ to_esc(as_esc)
125
+ end
126
+
127
+ def colorize(*str, concatenator: '')
128
+ "#{to_esc(true)}#{str.map(&:to_s).join(concatenator)}#{CLEAR_TERM}"
129
+ end
130
+
131
+ # rubocop:disable Metrics/ParameterLists
132
+ # Color as used in 256-color terminal escape sequences
133
+ def to_esc(surround = true, bold: true, italic: false, underline: false, reverse: false, foreground: true)
134
+ result = if grayscale?
135
+ r < 16 ? 0 : ((r - 16) / 10).floor + 232
136
+ else
137
+ 16 + 36 * (r / 51).floor + 6 * (g / 51).floor + (b / 51).floor
138
+ end
139
+
140
+ esc = [
141
+ bold ? '01' : nil,
142
+ italic ? '03' : nil,
143
+ underline ? '04' : nil,
144
+ reverse ? '07' : nil,
145
+ foreground ? '38' : '48',
146
+ '05',
147
+ result
148
+ ].compact.join(';')
149
+
150
+ surround ? "\e[#{esc}m" : esc
151
+ end
152
+ # rubocop:enable Metrics/ParameterLists
153
+
154
+ def to_rgb(add_hash = true)
155
+ (add_hash ? '#' : '') + to_hex(r) + to_hex(g) + to_hex(b)
156
+ end
157
+
158
+ def to_rgba(add_hash = true)
159
+ to_rgb(add_hash) + to_hex(a)
160
+ end
161
+
162
+ def opaque?
163
+ @a == 255
164
+ end
165
+
166
+ def trans?
167
+ !opaque?
168
+ end
169
+
170
+ def grayscale?
171
+ @r == @g && @g == @b
172
+ end
173
+
174
+ # Lighten color towards white. 0.0 is a no-op, 1.0 will return #FFFFFF
175
+ def lighten(amt = BRIGHTNESS_DEFAULT)
176
+ return self if amt <= 0
177
+ return WHITE if amt >= 1.0
178
+ Color.new(self).tap do |val|
179
+ val.r += ((255 - val.r) * amt).to_i
180
+ val.g += ((255 - val.g) * amt).to_i
181
+ val.b += ((255 - val.b) * amt).to_i
182
+ end
183
+ end
184
+
185
+ # In place version of #lighten
186
+ def lighten!(amt = BRIGHTNESS_DEFAULT)
187
+ set(lighten(amt))
188
+ end
189
+
190
+ # Darken a color towards full black. 0.0 is a no-op, 1.0 will return #000000
191
+ def darken(amt = BRIGHTNESS_DEFAULT)
192
+ return self if amt <= 0
193
+ return BLACK if amt >= 1.0
194
+ Color.new(self).tap do |val|
195
+ val.r -= (val.r * amt).to_i
196
+ val.g -= (val.g * amt).to_i
197
+ val.b -= (val.b * amt).to_i
198
+ end
199
+ end
200
+
201
+ # In place version of #darken
202
+ def darken!(amt = BRIGHTNESS_DEFAULT)
203
+ set(darken(amt))
204
+ end
205
+
206
+ # Convert to grayscale, using perception-based weighting
207
+ def grayscale
208
+ Color.new(self).tap do |val|
209
+ val.r = val.g = val.b = (0.2126 * val.r + 0.7152 * val.g + 0.0722 * val.b)
210
+ end
211
+ end
212
+
213
+ # In place version of #grayscale
214
+ def grayscale!
215
+ set(grayscale)
216
+ end
217
+
218
+ # Blend to a color amt % towards another color value, eg
219
+ # red.blend(blue, 0.5) will be purple, white.blend(black, 0.5) will be gray, etc.
220
+ def blend(other, amt)
221
+ other = Color.parse(other)
222
+ return Color.new(self) if amt <= 0 || other.nil?
223
+ return Color.new(other) if amt >= 1.0
224
+ Color.new(self).tap do |val|
225
+ val.r += ((other.r - val.r) * amt).to_i
226
+ val.g += ((other.g - val.g) * amt).to_i
227
+ val.b += ((other.b - val.b) * amt).to_i
228
+ end
229
+ end
230
+
231
+ # In place version of #blend
232
+ def blend!(other, amt)
233
+ set(blend(other, amt))
234
+ self
235
+ end
236
+
237
+ # Class-level version for explicit blends of two values, useful with constants
238
+ def self.blend(col1, col2, amt)
239
+ col1, col2 = [col1, col2].map { |c| Color.parse c }
240
+ col1.blend(col2, amt)
241
+ end
242
+
243
+ # rubocop:disable Metrics/ParameterLists
244
+ def self.to_xterm256(text, color, bold: true, italic: false, underline: false, reverse: false, foreground: true)
245
+ color = Color.preset(color) unless color.is_a?(Color)
246
+ [
247
+ color.to_esc(true, bold: bold, italic: italic, underline: underline, reverse: reverse, foreground: foreground),
248
+ text,
249
+ CLEAR_TERM
250
+ ].join
251
+ end
252
+ # rubocop:enable Metrics/ParameterLists
253
+
254
+ def self.preset(type)
255
+ Color.parse case type
256
+ when :label then '#999999'
257
+ when :success then '#468847'
258
+ when :warning then '#F89406'
259
+ when :important then '#B94A48'
260
+ when :fatal then '#B94A48'
261
+ when :error then '#FF0000'
262
+ when :info then '#3A87AD'
263
+ when :inverse then '#333333'
264
+ else type
265
+ end
266
+ end
267
+
268
+ protected
269
+
270
+ def to_html(add_hash = true)
271
+ trans? ? to_rgba(add_hash) : to_rgb(add_hash)
272
+ end
273
+
274
+ # Convert int to string hex, eg 255 => 'FF'
275
+ def to_hex(val)
276
+ HEXVAL[val / 16] + HEXVAL[val % 16]
277
+ end
278
+
279
+ # Convert int or string to int, eg 80 => 80, 'FF' => 255, '7' => 119
280
+ def from_hex(val)
281
+ if val.is_a?(String)
282
+ # Double up if single char form
283
+ val *= 2 if val.size == 1
284
+ # Convert to integer
285
+ val = val.hex
286
+ end
287
+ # Clamp
288
+ val = 0 if val < 0
289
+ val = 255 if val > 255
290
+ val
291
+ end
292
+
293
+ # Some constants for general use
294
+ WHITE = Color.new(255, 255, 255).freeze
295
+ BLACK = Color.new(0, 0, 0).freeze
296
+ RED = Color.new(255, 0, 0).freeze
297
+ GREEN = Color.new(0, 255, 0).freeze
298
+ BLUE = Color.new(0, 0, 255).freeze
299
+ NONE = Color.new(0, 0, 0, 255).freeze
300
+ end
301
+ # rubocop:enable Metrics/ClassLength
302
+ end
303
+ end
@@ -0,0 +1,25 @@
1
+ module Logrithm
2
+ module Utils
3
+ module Helpers
4
+ class << self
5
+ def constantize(string, namespace = Kernel)
6
+ namespace = Kernel.const_get(namespace) unless namespace.is_a?(Module)
7
+ result = namespace.const_get string.to_s.gsub(/(?:\A|_)(\w)/) { |m| m[-1].upcase }
8
+ result if namespace == Kernel || result.to_s =~ /\A#{namespace}/
9
+ rescue NameError
10
+ nil
11
+ end
12
+
13
+ def dirty_lookup_class_method(file, lineno)
14
+ content = File.readlines(file)[0..lineno.to_i].reverse
15
+ result = content.each_with_object(method: nil, ns: []) do |line, memo|
16
+ (memo[:method] ||= line[/\A\s*def\s*(?<method>\w+)/, :method]) &&
17
+ (memo[:ns] << line[/\A\s*(?:class|module)\s*(?<ns>\w+)/, :ns])
18
+ end
19
+
20
+ [const_get(result[:ns].compact.reverse.join('::')), result[:method]]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ module Logrithm
2
+ module Utils
3
+ module Output
4
+ VB = '│'.freeze
5
+ HB = '─'.freeze
6
+ TL = '┌'.freeze
7
+ TR = '┐'.freeze
8
+ BL = '└'.freeze
9
+ BR = '┘'.freeze
10
+
11
+ TERM_MARGIN = 2
12
+ BOX_MARGIN = 2
13
+
14
+ TERM_MARGIN_STR = ' ' * TERM_MARGIN
15
+ BOX_MARGIN_STR = ' ' * BOX_MARGIN
16
+
17
+ HIGHLIGHT_COLOR = Color.new(Logrithm::Log.option(:log, :colors, :highlight) || '01;38;05;51')
18
+ EXCEPTION_COLOR = Color.new(Logrithm::Log.option(:log, :colors, :exception) || '01;38;05;88')
19
+ APPDIR_COLOR = Color.new(Logrithm::Log.option(:log, :colors, :root) || '01;38;05;253')
20
+ METHOD_COLOR = Color.new(Logrithm::Log.option(:log, :colors, :method_call) || '01;38;05;253')
21
+ DATETIME_COLOR = Color.new(Logrithm::Log.option(:log, :colors, :datetime) || '01;38;05;240')
22
+ EXTENDED_COLOR = Color.new(Logrithm::Log.option(:log, :colors, :extended) || '01;38;05;246')
23
+
24
+ class << self
25
+ def line(filler = HB, width: $stdin.winsize.last, margin: TERM_MARGIN, color: Color::RED)
26
+ color.colorize(' ' * margin, filler * (width - 2 * margin))
27
+ end
28
+
29
+ # rubocop:disable Metrics/AbcSize
30
+ def rectangle(text, width: $stdin.winsize.last - 2 * TERM_MARGIN, color: Color::RED, frame_color: :same)
31
+ text_width = width - 2 - 2 * BOX_MARGIN
32
+ splitted = text.split(' ').each_with_object(['']) do |word, memo|
33
+ next if word.strip.empty?
34
+ memo.last.length + word.length + 1 <= text_width ? memo.last << ' ' << word : memo << word
35
+ end.map(&:strip)
36
+ frame_color = case frame_color
37
+ when :same then color
38
+ when :none then Color::NONE
39
+ else frame_color
40
+ end
41
+ spaces = ' ' * (BOX_MARGIN + (text_width - splitted.max_by(&:length).length) / 2)
42
+ [
43
+ frame_color.colorize(TERM_MARGIN_STR + TL << HB * (width - 2) << TR),
44
+ frame_color.colorize("#{TERM_MARGIN_STR}#{VB}#{' ' * (width - 2)}#{VB}"),
45
+ *splitted.map do |line|
46
+ trailing_spaces = ' ' * (width - (2 + spaces.length + line.length))
47
+ frame_color.colorize("#{TERM_MARGIN_STR}#{VB}") <<
48
+ color.colorize("#{spaces}#{line}#{trailing_spaces}") <<
49
+ frame_color.colorize(VB)
50
+ end,
51
+ frame_color.colorize("#{TERM_MARGIN_STR}#{VB}#{' ' * (width - 2)}#{VB}"),
52
+ frame_color.colorize(TERM_MARGIN_STR + BL << HB * (width - 2) << BR)
53
+ ].join($/)
54
+ end
55
+ # rubocop:enable Metrics/AbcSize
56
+
57
+ def clrz(txt, clr)
58
+ txt = txt.to_s
59
+ .gsub(/«(.*?)»/m, "#{HIGHLIGHT_COLOR.to_esc}\\1#{clr.to_esc}")
60
+ .gsub(/⟨(.*?)⟩/m, "#{EXCEPTION_COLOR.to_esc}\\1#{clr.to_esc}")
61
+ .gsub(/⟦(.*?)⟧/m, "#{APPDIR_COLOR.to_esc}\\1#{clr.to_esc}")
62
+ .gsub(/⟬(.*?)⟭/m, "#{METHOD_COLOR.to_esc}\\1#{clr.to_esc}")
63
+ .gsub(/⟪(.*?)⟫/m, "#{EXTENDED_COLOR.to_esc}\\1#{clr.to_esc}")
64
+
65
+ clr.colorize txt
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,32 @@
1
+ # rubocop:disable Style/GlobalVars
2
+ module Logrithm
3
+ module Utils
4
+ module Syringe
5
+ class << self
6
+ def inject(*km)
7
+ return unless km.size == 2 && km.first.is_a?(Class) && km.last.is_a?(String)
8
+ klazz, method = km
9
+
10
+ name = scramble "Logrithm@#{klazz}##{method}"
11
+ return if klazz.ancestors.map(&:name).include? "Kernel::#{name}"
12
+
13
+ Kernel.const_set(
14
+ name,
15
+ Module.new do
16
+ define_method method do |*args|
17
+ $♯ = self
18
+ super(*args)
19
+ end
20
+ end
21
+ )
22
+ klazz.prepend Kernel.const_get name
23
+ end
24
+
25
+ def scramble(str)
26
+ str.gsub(/[:#@?!]/, ':' => ':', '#' => '#', '@' => '@', '?' => '?', '!' => '!', '=' => '=')
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ # rubocop:enable Style/GlobalVars
@@ -0,0 +1,3 @@
1
+ module Logrithm
2
+ VERSION = '0.2.0'
3
+ end
data/lib/logrithm.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'kungfuig'
2
+
3
+ require 'logrithm/version'
4
+ require 'logrithm/utils/color'
5
+ require 'logrithm/utils/helpers'
6
+
7
+ require 'logrithm/formatters'
8
+
9
+ require 'logrithm/utils/syringe'
10
+
11
+ module Logrithm
12
+ def rails?
13
+ Kernel.const_defined?('::Rails')
14
+ end
15
+ module_function :rails?
16
+
17
+ def env
18
+ case
19
+ when ENV['LOGRITHM_ENV'] then ENV['LOGRITHM_ENV'].to_sym
20
+ when rails? then Rails.env
21
+ else :development
22
+ end
23
+ end
24
+ module_function :env
25
+
26
+ def severity(severity)
27
+ case severity.to_s.upcase
28
+ when 'DEBUG', '0' then 0
29
+ when 'INFO', '1' then 1
30
+ when 'WARN', '2' then 2
31
+ when 'ERROR', '3' then 3
32
+ when 'FATAL', '4' then 4
33
+ else 2
34
+ end
35
+ end
36
+ module_function :severity
37
+ end
38
+
39
+ require 'logrithm/log'
40
+ require 'logrithm/utils/output'
41
+ require 'logrithm/spitters'
42
+
43
+ require 'logrithm/middleware/rack'
44
+
45
+ module Logrithm
46
+ class << self
47
+ %i(debug info warn error fatal).each do |m|
48
+ define_method(m) do |*args, **extended|
49
+ Logrithm::Log::INSTANCE.public_send m, *args, **extended
50
+ end
51
+ end
52
+
53
+ def color(severity)
54
+ Log::INSTANCE.send(:color, severity)
55
+ end
56
+ end
57
+ end
data/logrithm.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'logrithm/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'logrithm'
8
+ spec.version = Logrithm::VERSION
9
+ spec.authors = ['Aleksei Matiushkin']
10
+ spec.email = ['aleksei.matiushkin@kantox.com']
11
+
12
+ spec.summary = %q{Standard logger improvements}
13
+ spec.description = %q{Some improvements to standard logger, such as detailed colored logger messages etc.}
14
+ spec.homepage = 'https://kantox.com'
15
+ spec.license = 'MIT'
16
+
17
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
18
+
19
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ spec.bindir = 'bin'
23
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.10'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec'
29
+
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'awesome_print'
32
+
33
+ spec.add_dependency 'kungfuig', '~> 0.7', '>= 0.7.5'
34
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logrithm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Aleksei Matiushkin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: kungfuig
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.7'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.7.5
93
+ type: :runtime
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '0.7'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 0.7.5
103
+ description: Some improvements to standard logger, such as detailed colored logger
104
+ messages etc.
105
+ email:
106
+ - aleksei.matiushkin@kantox.com
107
+ executables: []
108
+ extensions: []
109
+ extra_rdoc_files: []
110
+ files:
111
+ - ".gitignore"
112
+ - ".rspec"
113
+ - ".rubocop.yml"
114
+ - ".rubocop_todo.yml"
115
+ - ".travis.yml"
116
+ - CODE_OF_CONDUCT.md
117
+ - Gemfile
118
+ - LICENSE.txt
119
+ - README.md
120
+ - Rakefile
121
+ - config/logrithm.yml
122
+ - lib/logrithm.rb
123
+ - lib/logrithm/formatters.rb
124
+ - lib/logrithm/formatters/default.rb
125
+ - lib/logrithm/formatters/pretty.rb
126
+ - lib/logrithm/log.rb
127
+ - lib/logrithm/middleware/rack.rb
128
+ - lib/logrithm/spitters.rb
129
+ - lib/logrithm/spitters/exception.rb
130
+ - lib/logrithm/spitters/string.rb
131
+ - lib/logrithm/utils/color.rb
132
+ - lib/logrithm/utils/helpers.rb
133
+ - lib/logrithm/utils/output.rb
134
+ - lib/logrithm/utils/syringe.rb
135
+ - lib/logrithm/version.rb
136
+ - logrithm.gemspec
137
+ homepage: https://kantox.com
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.4.8
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: Standard logger improvements
161
+ test_files: []