Skip to content

Commit f648ea6

Browse files
committed
initial commit
0 parents  commit f648ea6

18 files changed

+848
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/.bundle/
2+
/.yardoc
3+
/Gemfile.lock
4+
/_yardoc/
5+
/coverage/
6+
/doc/
7+
/pkg/
8+
/spec/reports/
9+
/tmp/
10+
11+
# rspec failure tracking
12+
.rspec_status

.rspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--format documentation
2+
--color

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
sudo: false
2+
language: ruby
3+
rvm:
4+
- 2.1
5+
- 2.2
6+
- 2.3
7+
- 2.4.0
8+
before_install: gem install bundler -v 1.14.6

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
source 'https://rubygems.org'
2+
3+
# Specify your gem's dependencies in debug_logging.gemspec
4+
gemspec

README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# DebugLogging
2+
3+
## Next Level Magic
4+
5+
Classes inheriting from Module.
6+
Cats and dogs sleeping together.
7+
Yet this gem monkey patches nothing.
8+
100% clean.
9+
0% obtrusive.
10+
100% tested.
11+
50% Ruby 2.0+ compatible.
12+
100% Ruby 2.1+ compatible.
13+
10g Monosodium glutamate.
14+
15+
NOTE: The manner this is made to work for class methods is totally different than the way this is made to work for instance methods.
16+
17+
NOTE: The instance method logging works on Ruby 2.0+
18+
19+
NOTE: The class method logging works on Ruby 2.1+
20+
21+
## Installation
22+
23+
Add this line to your application's Gemfile:
24+
25+
```ruby
26+
gem 'debug_logging'
27+
```
28+
29+
And then execute:
30+
31+
$ bundle
32+
33+
Or install it yourself as:
34+
35+
$ gem install debug_logging
36+
37+
## Usage
38+
39+
Crack open the specs for usage examples.
40+
41+
### Without Rails
42+
43+
It just works. ;)
44+
Configuration can go anywhere you want.
45+
46+
### With Rails
47+
48+
Recommend creating `config/initializers/debug_logging.rb` with:
49+
```ruby
50+
# Showing the defaults
51+
DebugLogging.logger = Logger.new(STDOUT) # you probably want to override to be the Rails.logger
52+
DebugLogging.log_level = :debug # at what level do the messages created by this gem sent at?
53+
DebugLogging.last_hash_to_s_proc = nil # e.g. ->(hash) { "#{hash.keys}" }
54+
DebugLogging.last_hash_max_length = 1_000
55+
DebugLogging.args_max_length = 1_000
56+
DebugLogging.instance_benchmarks = false
57+
DebugLogging.class_benchmarks = false
58+
DebugLogging.add_invocation_id = true # invocation id allows you to identify a method call uniquely in a log
59+
DebugLogging.ellipsis = " ✂️ …".freeze
60+
```
61+
62+
```ruby
63+
class Car
64+
65+
# For instance methods:
66+
# Option 1: specify the exact method(s) to add logging to
67+
include DebugLogging::InstanceLogger.new(i_methods: [:drive, :stop])
68+
69+
extend DebugLogging::ClassLogger
70+
71+
logged def self.make; new; end
72+
def self.design(*args); new; end
73+
def self.safety(*args); new; end
74+
logged :design, :safety
75+
76+
def drive(speed); speed; end
77+
def stop; 0; end
78+
79+
# For instance methods:
80+
# Option 2: add logging to all instance methods defined above (but *not* defined below)
81+
include DebugLogging::InstanceLogger.new(i_methods: self.instance_methods(false))
82+
83+
def will_not_be_logged; false; end
84+
85+
end
86+
```
87+
88+
## Development
89+
90+
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.
91+
92+
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).
93+
94+
## Contributing
95+
96+
Bug reports and pull requests are welcome on GitHub at https://github.com/pboling/debug_logging.

Rakefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
require "bundler/gem_tasks"
2+
require "rspec/core/rake_task"
3+
4+
RSpec::Core::RakeTask.new(:spec)
5+
6+
task :default => :spec

bin/console

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env ruby
2+
3+
require "bundler/setup"
4+
require "debug_logging"
5+
6+
# You can add fixtures and/or initialization code here to make experimenting
7+
# with your gem easier. You can also use a different console, if you like.
8+
9+
# (If you use this, don't forget to add pry to your Gemfile!)
10+
# require "pry"
11+
# Pry.start
12+
13+
require "irb"
14+
IRB.start(__FILE__)

bin/setup

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
IFS=$'\n\t'
4+
set -vx
5+
6+
bundle install
7+
8+
# Do any other automated setup that you need to do here

debug_logging.gemspec

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# coding: utf-8
2+
lib = File.expand_path('../lib', __FILE__)
3+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4+
require 'debug_logging/version'
5+
6+
Gem::Specification.new do |spec|
7+
spec.name = "debug_logging"
8+
spec.version = DebugLogging::VERSION
9+
spec.authors = ["Peter Boling"]
10+
spec.email = ["[email protected]"]
11+
12+
spec.summary = %q{Drop-in debug logging useful when a call stack gets unruly}
13+
spec.description = %q{Automatically log Class.method(arguments) as they are called at runtime!}
14+
spec.homepage = "TODO: Put your gem's website or public repo URL here."
15+
16+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17+
# to allow pushing to a single host or delete this section to allow pushing to any host.
18+
if spec.respond_to?(:metadata)
19+
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
20+
else
21+
raise "RubyGems 2.0 or newer is required to protect against " \
22+
"public gem pushes."
23+
end
24+
25+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
26+
f.match(%r{^(test|spec|features)/})
27+
end
28+
spec.bindir = "exe"
29+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30+
spec.require_paths = ["lib"]
31+
32+
spec.add_development_dependency "rspec-pending_for"
33+
spec.add_development_dependency "bundler", "~> 1.14"
34+
spec.add_development_dependency "rake", "~> 10.0"
35+
spec.add_development_dependency "rspec", "~> 3.0"
36+
end

lib/debug_logging.rb

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
require "logger"
2+
require "debug_logging/version"
3+
require "debug_logging/argument_printer"
4+
require "debug_logging/instance_logger_modulizer"
5+
require "debug_logging/instance_logger"
6+
require "debug_logging/class_logger"
7+
8+
####################
9+
# #
10+
# Next Level Magic #
11+
# Classes inheriting from Module.
12+
# Cats and dogs sleeping together.
13+
# #
14+
####################
15+
# #
16+
# NOTE: The manner this is made to work for class methods is totally different
17+
# than the way this is made to work for instance methods.
18+
# NOTE: The instance method manner works on Ruby 2.0+
19+
# NOTE: The class method manner works on Ruby 2.1+
20+
# #
21+
####################
22+
# #
23+
# USAGE (see specs)#
24+
# #
25+
# class Car
26+
#
27+
# # For instance methods:
28+
# # Option 1: specify the exact method(s) to add logging to
29+
# include DebugLogging::InstanceLogger.new(i_methods: [:drive, :stop])
30+
#
31+
# extend DebugLogging::ClassLogger
32+
#
33+
# logged def self.make; new; end
34+
# def self.design(*args); new; end
35+
# def self.safety(*args); new; end
36+
# logged :design, :safety
37+
#
38+
# def drive(speed); speed; end
39+
# def stop; 0; end
40+
#
41+
# # For instance methods:
42+
# # Option 2: add logging to all instance methods defined above (but *not* defined below)
43+
# include DebugLogging::InstanceLogger.new(i_methods: self.instance_methods(false))
44+
#
45+
# def will_not_be_logged; false; end
46+
#
47+
# end
48+
# #
49+
####################
50+
51+
module DebugLogging
52+
def self.config_reset
53+
@@logger = nil
54+
@@log_level = :debug
55+
@@last_hash_to_s_proc = nil
56+
@@last_hash_max_length = 1_000
57+
@@args_max_length = 1_000
58+
@@instance_benchmarks = false
59+
@@class_benchmarks = false
60+
@@add_invocation_id = true
61+
@@ellipsis = " ✂️ …".freeze
62+
end
63+
def self.logger
64+
@@logger ||= Logger.new(STDOUT)
65+
end
66+
def self.logger=(logger)
67+
@@logger = logger
68+
end
69+
def self.log_level
70+
@@log_level || :debug
71+
end
72+
def self.log_level=(log_level)
73+
@@log_level = log_level
74+
end
75+
def self.last_hash_to_s_proc
76+
@@last_hash_to_s_proc
77+
end
78+
def self.last_hash_to_s_proc=(last_hash_to_s_proc)
79+
@@last_hash_to_s_proc = last_hash_to_s_proc
80+
end
81+
def self.last_hash_max_length
82+
@@last_hash_max_length || 1_000
83+
end
84+
def self.last_hash_max_length=(last_hash_max_length)
85+
@@last_hash_max_length = last_hash_max_length
86+
end
87+
def self.args_max_length
88+
@@args_max_length || 1_000
89+
end
90+
def self.args_max_length=(args_max_length)
91+
@@args_max_length = args_max_length
92+
end
93+
def self.instance_benchmarks
94+
@@instance_benchmarks
95+
end
96+
def self.instance_benchmarks=(instance_benchmarks)
97+
require "benchmark" if instance_benchmarks
98+
@@instance_benchmarks = instance_benchmarks
99+
end
100+
def self.class_benchmarks
101+
@@class_benchmarks
102+
end
103+
def self.class_benchmarks=(class_benchmarks)
104+
require "benchmark" if class_benchmarks
105+
@@class_benchmarks = class_benchmarks
106+
end
107+
def self.add_invocation_id
108+
@@add_invocation_id
109+
end
110+
def self.add_invocation_id=(add_invocation_id)
111+
@@add_invocation_id = add_invocation_id
112+
end
113+
def self.ellipsis
114+
@@ellipsis
115+
end
116+
def self.ellipsis=(ellipsis)
117+
@@ellipsis = ellipsis
118+
end
119+
def self.log(message)
120+
logger.send(log_level, message)
121+
end
122+
config_reset # setup defaults
123+
end

0 commit comments

Comments
 (0)