diff --git a/.hound.yml b/.hound.yml deleted file mode 100644 index a1e52a1..0000000 --- a/.hound.yml +++ /dev/null @@ -1,2 +0,0 @@ -ruby: - config_file: .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml index 680d93d..2db517c 100755 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,13 +2,10 @@ inherit_from: #{RUBOCOP_HOME}/config/default.yml AllCops: - Include: - - '**/lib/**/*' + TargetRubyVersion: 2.4 Exclude: - - 'bin/**/*' - - '**/Guardfile' - - '**/Gemfile' - - '**/Rakefile' + - 'vendor/**/*' + - 'Guardfile' CyclomaticComplexity: Max: 15 @@ -59,6 +56,12 @@ Style/StringLiterals: Enabled: true EnforcedStyle: single_quotes -Style/BlockLength: +Metrics/BlockLength: Exclude: - 'spec/**/*.rb' + +Style/FrozenStringLiteralComment: + Enabled: false + +Style/AccessModifierDeclarations: + EnforcedStyle: inline diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..6b4950e --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.4 diff --git a/.travis.yml b/.travis.yml index b562247..3d1386c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,28 +1,23 @@ language: ruby cache: bundler -rvm: - - 2.4.0 - - 2.3.3 - - 2.2.6 - - 2.2.2 +rvm: 2.4 script: - - bundle exec rspec - - bundle exec rubocop lib spec +- bundle exec bundle-audit update && bundle exec bundle-audit check +- bundle exec rspec +- bundle exec rubocop lib spec deploy: - provider: releases api_key: - secure: Ob2+ZdkM5msawA9FnJ8hk7wLgUP9tJg+gOIs1VOpOzq7cqHUmbK2tGwJPSWX+yzFA5A9o520SLJB0MAfnO78DjByRenH1e8keg0uxZ17ci8FDWEPhF53cCjuTLhsaC9qxVcbNps4Z8pg5lQ/0IPaef0lVX0u2jPEHagNBmfJdYLthUPH/M/AcoVT/chjxWw3SNON4LdcUQw5qtpMUe/Clroi5LaaYPWui0o7z6EmlqwV0gFd5oVkXabwuMkWU06tFzxO+AgBT7qeMCDSXqa2ODaWItE74i8TVEMRDHiY+0a0gs76xjsfkml4Q0dNw8YuKcO4p25QskNeTtxi3rZoMToG4e8MfHZG+3YLu3u9VKp0fR7WsL21Jf27dDscXapXyVcMZ+AcklRMEGmKjsyKPnxepcR5RtmoVbDY9/SnJfECa62diZyzMYpjDvu4ZVut5vf/m8AvhnotpwTE2Nilb268f36uIloTG/5zrA113KiEAw5OW0abOm0JFn7t2bZty9D1rwyXiUGZmeS+ZFFE0+zCKXFv5VyK9ZmG4OKbGMMQJRsF+ej70Uv88MbwSS8TDRu0U1bnHBQ6aP3Wc7POihk9M2NAokFppQ9R0htVm0XWrDsxWnEqMMf8HZAQ8fsM9P1jZclgJKnzdSqpKjW4cGAk9i5+mepG6BcASfoUkhk= + secure: z/GBmPIgX/UQLixhUnN6fouJbC0PghjW8MeAJJoeIPNqKuv2Kws1wgNOndgrSb+U/gfIZ8CAHTq/U6hlfpGHt7+IBAmO/YMCH/O0CV/MNCfVKwduFTZplcDSnXAiFy77yk+ute0It/L/HJO1LMSq3q1wU2jUWL4CZal/+GY7yVFo8EZQJBeTmvatPd0uD+/+bFwEsYEGKt2/JF42GW6Xtbt9DHXwL1olYmReuPjXavdomZof0KKboM+cI42gzJ5AYVl4ouELGiGQgh5dgK1HkvpBGYqg16YgT0LK5HnQ24slwJk2+yM6x9bXZqQu8IEhPafxR77wJ6T0388iM5vCXtzzJidsOL6mANqpKZ8z1YsAi0w4QNAPvf2AFw40fIfu2W/J4z2UYQUKD/3Em1IY0/fPr+FdMBMWQNevjjns89943GWhFoDUJj4EMt46rEpMHPVTA9DfUA7be4IRo9YrUx7u8MaVotpzSYCxepAmC9tB7KQAjygxI7z/orihZj7lHadUI8rPKfKUkrDDwSyB8xyV5BjpcorSshoqnFLaGrxHfbos/ww5i2xxQEF77RK9rkaICyE7q6oOghCq7BSKsYVzNkBCtRftVy5zYCEPd8MCXxF40S3uv4ta30wQKhdZPWELf4GkzKxCpdbbryWQKoF6ZKceD+LIG18qVlO5AqU= file_glob: true file: hedgelog-*.gem on: tags: true - rvm: 2.2.2 repo: firespring/hedgelog - provider: rubygems api_key: - secure: 0lJg8R4FfcC/V0CQP1+MtvaOTHumMczV6W5wNvW+S4C9A+EhWgNdZDZ1tPbLQDRm4rBhr15k6KpZUmR1hMiu2xpN/O9wpdLqrhFccnP8+3qSYWi4Mqns/lFLQtVwlfQeSjQPejHeel7wEDAo/iFs9lgVzyXtusAgIZ8qQLJIa2T8cLE5Kdh/xfJTfdYCojJkw+5XoxARFmiXz5dIBb+1jiYmAULgRQpNUifz+IspAUxDf8BXjZFi7TZeKf34kOnVRUXLdjFOkTIXSx7F1NlSCFUmQtjf1Ft1PfJUwZ+eh5B0u5AL7JMA3pA9T6WNpqJpedVCD5KvkqKeILYFkYriro7K41MCPXBM4CAXSgpqnwiGCR64eBm85nGaRbYIZ+8AdGKxd1wS+fVkpOv4PxDADDD+qPIVTpuTeIJ2+hZYpHdsD5bYtqhvqdUkVOdilnBZKFYHVwHZvkObOoGyk0g3PzwYOUSnG3BJ3YhinTzNuXkOBhUdGN/eZna314hPLVGySTlmpnnof2lWQFArJXTcJXVQBdkSdlML7vvv4QjttOBNX6ICzOimFDrTDIlf3hkrf3+bGva3v0tBn3cz4bLOZgdvWrhhJ+p6TzPCGoseKUE2e+zvBAsPEzjYI9G+hKkSbtT0rFZ6O/Cr21dL/Mbf2WMz0NfhmTc4J3kdP2Y98Ow= + secure: anM34Z3fd3H5xt46pVbOmC0FnPsD0Pro9+Vmdv4fq22GvjFolexCtNFt8fb8V+M9THvw1qZDvSyHTZ0NKUDMqaVLX+VhDvquhuM0vviAECBu7kqqZ/pBjBJduYrtcFrCpoL3vs3AhXM882XKIhw4YMtOgoh00DpLZYQbtdEVvCZhbIe80N2eRSM1taVNQQwkI7pREBBFliBrjpP82Vfacue7m/iDKg/k1SRv1jXafQLDM0k8UAdYntc/popqTpXCbmxOcPVv6yVghijld6rTirLeRSrbwq1m0Djg24r/BGd8NsFn9Xtvtm8oZN3Xv2Q8AoJFeDCymTndUtJYrFaS8IQe5TLzXLYW+/BjedCuA09bfcRjW7vjuO73yYqf/K+dTbwbuJMpUJt6Mymu66MuPi6ntj00hvDBU9ekHFkZlemUixq3LxvmEPyxK8PKTLVH9UipkTBG0cXWct5fCXhv0KvrxFLeZM2XXqvknnuYGSIE5fvGLHvn2OuX5JESJzwDt8xBNXrPmCIcDX/DOONR+AuPYQkDLybM75/P+vnxSfT6ZMFj7AxZAr23mWOQ1dK+dgvJb+nbBa+5KRCPs9n9M4aW5ybNKgy8v8Mgp6ebTuRLYDUdOB2aMXRy6/0dqSMR+fe0B7HtHXNtp73Nidox6QBFQzmtXg8fzsXA9yFKFZI= gem: hedgelog on: tags: true - rvm: 2.2.2 repo: firespring/hedgelog diff --git a/Gemfile b/Gemfile index 8ec902d..ff1a8e4 100644 --- a/Gemfile +++ b/Gemfile @@ -4,17 +4,18 @@ source 'https://rubygems.org' gemspec group :test, :development do - gem "rake", "~> 10.0" - gem "rspec", "~> 3.3" - gem "pry" - gem "simplecov", "~> 0.10" - gem "rubocop", "~> 0.51" - gem "timecop" gem 'benchmark-ips' + gem 'bundler-audit' + gem 'pry' + gem 'rake' + gem 'rspec' + gem 'rubocop' + gem 'simplecov' + gem 'timecop' end group :development do - gem 'ruby-prof' gem 'guard-rspec', require: false gem 'listen', '~> 3.0.6' + gem 'ruby-prof' end diff --git a/Guardfile b/Guardfile index 1ad340e..02616b9 100644 --- a/Guardfile +++ b/Guardfile @@ -24,8 +24,8 @@ # * zeus: 'zeus rspec' (requires the server to be started separately) # * 'just' rspec: 'rspec' -guard :rspec, cmd: "bundle exec rspec --format progress" do - require "guard/rspec/dsl" +guard :rspec, cmd: 'bundle exec rspec --format progress' do + require 'guard/rspec/dsl' dsl = Guard::RSpec::Dsl.new(self) # Feel free to open issues for suggestions and improvements @@ -41,15 +41,15 @@ guard :rspec, cmd: "bundle exec rspec --format progress" do dsl.watch_spec_files_for(ruby.lib_files) # Rails files - rails = dsl.rails(view_extensions: %w(erb haml slim)) + rails = dsl.rails(view_extensions: %w[erb haml slim]) dsl.watch_spec_files_for(rails.app_files) dsl.watch_spec_files_for(rails.views) watch(rails.controllers) do |m| [ - rspec.spec.("routing/#{m[1]}_routing"), - rspec.spec.("controllers/#{m[1]}_controller"), - rspec.spec.("acceptance/#{m[1]}") + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") ] end @@ -59,12 +59,12 @@ guard :rspec, cmd: "bundle exec rspec --format progress" do watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } # Capybara features specs - watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") } - watch(rails.layouts) { |m| rspec.spec.("features/#{m[1]}") } + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } # Turnip features and steps watch(%r{^spec/acceptance/(.+)\.feature$}) watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| - Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance" + Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' end end diff --git a/README.md b/README.md index 791c651..d3e59ba 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # Hedgelog [![Gem Version](https://badge.fury.io/rb/hedgelog.svg)](http://badge.fury.io/rb/hedgelog) [![Build Status](https://travis-ci.org/firespring/hedgelog.svg?branch=master)](https://travis-ci.org/firespring/hedgelog) -[![Dependency Status](https://gemnasium.com/firespring/hedgelog.svg)](https://gemnasium.com/firespring/hedgelog) -[![Code Climate](https://codeclimate.com/github/firespring/hedgelog/badges/gpa.svg)](https://codeclimate.com/github/firespring/hedgelog) This gem provides an opinionated Ruby logger for writing structured JSON logs. It attempts to maintain compatibility with the standard Ruby logger api while extending it with functionality relevant to JSON logging. diff --git a/Rakefile b/Rakefile index b7e9ed5..4c774a2 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ -require "bundler/gem_tasks" -require "rspec/core/rake_task" +require 'bundler/gem_tasks' +require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) -task :default => :spec +task default: :spec diff --git a/bin/console b/bin/console index 2d481f9..c3e7b64 100755 --- a/bin/console +++ b/bin/console @@ -1,10 +1,10 @@ #!/usr/bin/env ruby -require "bundler/setup" -require "hedgelog" +require 'bundler/setup' +require 'hedgelog' # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. -require "pry" +require 'pry' Pry.start diff --git a/bin/profile b/bin/profile index 0ba4f12..1a27466 100755 --- a/bin/profile +++ b/bin/profile @@ -1,7 +1,7 @@ #!/usr/bin/env ruby -require "bundler/setup" -require "hedgelog" +require 'bundler/setup' +require 'hedgelog' require 'ruby-prof' require 'logger' @@ -9,13 +9,12 @@ logger = Hedgelog.new('/dev/null') logger.level = Logger::INFO RubyProf.start -10000.times do +10_000.times do logger.info 'Foo' end result = RubyProf.stop result.eliminate_methods!([/Integer#times/]) - # printer = RubyProf::GraphPrinter.new(result) printer = RubyProf::FlatPrinterWithLineNumbers.new(result) printer.print(STDOUT) diff --git a/hedgelog.gemspec b/hedgelog.gemspec index df0f0d8..3c4ee94 100644 --- a/hedgelog.gemspec +++ b/hedgelog.gemspec @@ -1,5 +1,4 @@ - -lib = File.expand_path('../lib', __FILE__) +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'hedgelog/version' @@ -9,17 +8,16 @@ Gem::Specification.new do |spec| spec.licenses = ['MIT'] spec.authors = ['Jeff Utter'] spec.email = ['jeff.utter@firespring.com'] - spec.homepage = 'https://github.com/firespring/hedgelog' - spec.summary = 'An opinionated/strucutred JSON logger for Ruby' + spec.homepage = 'https://github.com/firespring/hedgelog' + spec.summary = 'A strucutred JSON logger for Ruby' spec.description = 'An opinionated/structured JSON logger for Ruby' - spec.homepage = 'http://firespring.com' spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } spec.bindir = 'exe' spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] - spec.add_dependency 'yajl-ruby', '~> 1.2' + spec.add_dependency 'yajl-ruby', '~> 1.4' spec.add_development_dependency 'bundler', '~> 1.7' end diff --git a/lib/hedgelog.rb b/lib/hedgelog.rb index cc2bdc8..e5d403b 100755 --- a/lib/hedgelog.rb +++ b/lib/hedgelog.rb @@ -19,8 +19,8 @@ class Hedgelog TOP_LEVEL_KEYS = %i[app channel level level_name message request_id timestamp].freeze RESERVED_KEYS = %i[app level level_name timestamp context caller].freeze - TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S.%6N%z'.freeze - BACKTRACE_RE = /([^:]+):([0-9]+)(?::in `(.*)')?/ + TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S.%6N%z' + BACKTRACE_RE = Regexp.new("([^:]+):([0-9]+)(?::in `(.*)')?") attr_reader :level attr_writer :app @@ -44,6 +44,7 @@ def initialize(logdev = STDOUT, shift_age = nil, shift_size = nil) def level=(level) int_level = level_to_int(level) raise ::ArgumentError, "#{self.class}#level= , #{level} is not a valid level." if int_level.nil? + @level = int_level end @@ -59,7 +60,7 @@ def add(severity = LEVELS[:unknown], message = nil, progname = nil, context = {} return write(severity, context) if @logdev - @channel.add(severity, nil, progname, context) if @channel + @channel&.add(severity, nil, progname, context) end def []=(key, val) @@ -119,23 +120,23 @@ def formatter ::Logger::Formatter.new end - def formatter=(_) + def formatter=(_value) formatter end - private - - def level_to_int(level) + private def level_to_int(level) return level if level.is_a?(Integer) + LEVELS[level] end - def level_from_int(level) + private def level_from_int(level) return LEVELS[level] if level.is_a?(Integer) + level.to_sym end - def write(severity, context) + private def write(severity, context) return true if @logdev.nil? context.normalize! @@ -150,7 +151,7 @@ def write(severity, context) true end - def default_data(severity) + private def default_data(severity) { timestamp: Time.now.strftime(TIMESTAMP_FORMAT), level_name: level_from_int(severity), @@ -158,7 +159,7 @@ def default_data(severity) } end - def extract_top_level_keys(context) + private def extract_top_level_keys(context) data = {} TOP_LEVEL_KEYS.each do |key| data[key] = context.delete(key) if context.key? key @@ -167,9 +168,10 @@ def extract_top_level_keys(context) data end - def debugharder(callinfo) + private def debugharder(callinfo) m = BACKTRACE_RE.match(callinfo) return unless m + path, line, method = m[1..3] whence = $LOAD_PATH.find { |p| path.start_with?(p) } file = if whence diff --git a/lib/hedgelog/context.rb b/lib/hedgelog/context.rb index d9e88d8..e1d3af3 100644 --- a/lib/hedgelog/context.rb +++ b/lib/hedgelog/context.rb @@ -5,6 +5,7 @@ class Hedgelog class Context def initialize(scrubber, normalizer, data = {}) raise ::ArgumentError, "#{self.class}: argument must be Hash got #{data.class}." unless data.is_a? Hash + check_reserved_keys(data) @data = data @scrubber = scrubber @@ -61,9 +62,7 @@ def to_h @data end - private - - def check_reserved_keys(hash) + private def check_reserved_keys(hash) invalid_keys = Hedgelog::RESERVED_KEYS & hash.keys raise ::ArgumentError, "#{self.class}: The following keys are reserved and cannot be used #{invalid_keys.to_a}." unless invalid_keys.empty? end diff --git a/lib/hedgelog/normalizer.rb b/lib/hedgelog/normalizer.rb index 261cf1a..3963c36 100644 --- a/lib/hedgelog/normalizer.rb +++ b/lib/hedgelog/normalizer.rb @@ -5,7 +5,6 @@ def normalize(data) d = Marshal.load(Marshal.dump(data)) normalize_hash(d) end - # rubocop:enable Security/MarshalLoad def normalize_struct(struct) normalize_hash(Hash[struct.each_pair.to_a]) @@ -21,14 +20,14 @@ def normalize_array(array) array.to_json end - private - - def normalize_thing(thing) + private def normalize_thing(thing) return '' if thing.nil? + thing = thing.as_json if thing.respond_to?(:as_json) return normalize_struct(thing) if thing.is_a?(Struct) return normalize_array(thing) if thing.is_a?(Array) return normalize_hash(thing) if thing.is_a?(Hash) + thing end end diff --git a/lib/hedgelog/scrub_replacement.rb b/lib/hedgelog/scrub_replacement.rb index f179466..ffe6159 100644 --- a/lib/hedgelog/scrub_replacement.rb +++ b/lib/hedgelog/scrub_replacement.rb @@ -18,6 +18,7 @@ def scrub_string(string) def scrub_hash(hash) hash.each do |key, val| next hash[key] = @replacement if key.to_s.casecmp(@key.to_s).zero? + scrub_thing(val) end end @@ -28,9 +29,7 @@ def scrub_array(array) end end - private - - def scrub_thing(thing) + private def scrub_thing(thing) scrub_string(thing) if thing.is_a?(String) scrub_array(thing) if thing.is_a?(Array) scrub_hash(thing) if thing.is_a?(Hash) diff --git a/lib/hedgelog/scrubber.rb b/lib/hedgelog/scrubber.rb index acb4f3e..aa6730c 100644 --- a/lib/hedgelog/scrubber.rb +++ b/lib/hedgelog/scrubber.rb @@ -16,6 +16,5 @@ def scrub(data) end d end - # rubocop:enable Security/MarshalLoad end end diff --git a/lib/hedgelog/version.rb b/lib/hedgelog/version.rb index 610422e..1b966a3 100755 --- a/lib/hedgelog/version.rb +++ b/lib/hedgelog/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true class Hedgelog - VERSION = '0.1.10'.freeze + VERSION = '0.1.11' end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9fce597..de48741 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,11 +1,11 @@ -$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) +$LOAD_PATH.unshift File.expand_path('../lib', __dir__) require 'pry' require 'simplecov' require 'hedgelog' -Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '**', '*.rb'))].each { |f| require f } +SimpleCov.minimum_coverage 99 -SimpleCov.start +Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '**', '*.rb'))].each { |f| require f } RSpec.configure do |config| config.include Matchers::Benchmark