scribbler 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.irbrc +2 -0
- data/.rvmrc +1 -1
- data/README.md +87 -40
- data/bin/scribbler +1 -1
- data/lib/scribbler.rb +63 -2
- data/lib/scribbler/base.rb +15 -191
- data/lib/scribbler/{cli.rb → cli_client.rb} +29 -29
- data/lib/scribbler/configurator.rb +61 -13
- data/lib/scribbler/executable.rb +12 -4
- data/lib/scribbler/includeables.rb +13 -43
- data/lib/scribbler/log_location.rb +13 -0
- data/lib/scribbler/logger.rb +152 -0
- data/lib/scribbler/version.rb +1 -1
- data/scribbler.gemspec +1 -0
- data/spec/lib/scribbler/base_spec.rb +16 -0
- data/spec/{scribbler/cli_spec.rb → lib/scribbler/cli_client_spec.rb} +4 -4
- data/spec/{scribbler → lib/scribbler}/configurator_spec.rb +14 -3
- data/spec/lib/scribbler/executable_spec.rb +28 -0
- data/spec/lib/scribbler/includeables_spec.rb +24 -0
- data/spec/lib/scribbler/log_location_spec.rb +11 -0
- data/spec/lib/scribbler/logger_spec.rb +172 -0
- data/spec/{scribbler → lib/scribbler}/version_spec.rb +0 -0
- data/spec/lib/scribbler_spec.rb +47 -0
- data/spec/spec_helper.rb +6 -8
- data/spec/support/examples/scribbler_example.rb +1 -1
- data/templates/scribbler.rb +3 -3
- metadata +62 -39
- data/spec/scribbler/base_spec.rb +0 -140
- data/spec/scribbler/executable_spec.rb +0 -21
- data/spec/scribbler/includeables_spec.rb +0 -9
- data/spec/scribbler_spec.rb +0 -7
data/.gitignore
CHANGED
data/.irbrc
ADDED
data/.rvmrc
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Scribbler
|
2
2
|
|
3
3
|
[![TravisCI](https://secure.travis-ci.org/jphenow/scribbler.png "TravisCI")](http://travis-ci.org/jphenow/scribbler "Travis-CI Scribbler")
|
4
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jphenow/scribbler)
|
4
5
|
|
5
6
|
[RubyGems](https://rubygems.org/gems/scribbler)
|
6
7
|
|
@@ -11,79 +12,122 @@ Currently it assists in:
|
|
11
12
|
* Centralized log method for file, message, and error checks
|
12
13
|
- Currently also able to notify NewRelic, abstraction and extension to come
|
13
14
|
|
15
|
+
## Notes on upgrading to 0.3.0
|
16
|
+
|
17
|
+
Scribbler was initially written with a lot of class-level (almost entirely) operations.
|
18
|
+
For sanity sake, the version 0.3.0 is the big step towards dropping most of the gem into
|
19
|
+
instances. There isn't much functionality change yet, but it will make expanding the gem much
|
20
|
+
simpler to develop.
|
21
|
+
|
22
|
+
### Changes For You
|
23
|
+
|
24
|
+
`Scribbler::Base` is now deprecated, look to remove. See `Scribbler`
|
25
|
+
|
26
|
+
`Scribbler.configure` now yields the configurator so you now want to change from:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
Scribbler::Base.configure do
|
30
|
+
config.some_config_options
|
31
|
+
# ...
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
to
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
Scribbler.configure do |config|
|
39
|
+
config.some_config_options
|
40
|
+
# ...
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
14
44
|
## Usage
|
15
45
|
|
16
46
|
In your Rails project add
|
17
47
|
|
18
|
-
|
48
|
+
```ruby
|
49
|
+
gem 'scribbler'
|
50
|
+
```
|
19
51
|
|
20
52
|
to your Gemfile and
|
21
53
|
|
22
|
-
|
54
|
+
```bash
|
55
|
+
bundle install
|
56
|
+
```
|
23
57
|
|
24
58
|
Then
|
25
59
|
|
26
|
-
|
60
|
+
```bash
|
61
|
+
scribbler install # For options do `scribbler` first
|
62
|
+
```
|
27
63
|
|
28
64
|
You'll find your configuration options in `config/initializers/scribbler.rb`.
|
29
65
|
**Better, more documented examples in the template file provided by `scribbler install`**
|
30
66
|
As an example, with this configuration file in a Rails app called `Blogger`:
|
31
67
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# config.log_directory = File.new '/a/better/path'
|
68
|
+
```ruby
|
69
|
+
Scribbler.configure do |config|
|
70
|
+
config.application_include = true
|
36
71
|
|
37
|
-
|
72
|
+
# config.log_directory = File.new '/a/better/path'
|
38
73
|
|
39
|
-
|
74
|
+
config.use_template_by_default = true # Default: false
|
40
75
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
76
|
+
# config.template = proc do |options|
|
77
|
+
# <<-MSG
|
78
|
+
# ##########
|
79
|
+
# Cool template bro!
|
80
|
+
# Message: #{options[:message]}
|
81
|
+
# MSG
|
82
|
+
# end
|
83
|
+
end
|
84
|
+
```
|
49
85
|
|
50
86
|
You are given a few methods for free. To get the production logfile location:
|
51
87
|
|
52
|
-
|
53
|
-
|
88
|
+
```ruby
|
89
|
+
Blogger.production_log_location
|
90
|
+
# => <#Path: Rails.root.join('log', 'production.log')>
|
91
|
+
```
|
54
92
|
|
55
93
|
or
|
56
94
|
|
57
|
-
|
58
|
-
|
95
|
+
```ruby
|
96
|
+
Scribbler.production_log_location
|
97
|
+
# => <#Path: Rails.root.join('log', 'production.log')>
|
98
|
+
```
|
59
99
|
|
60
100
|
More importantly you're given access to a sweet `log` method:
|
61
101
|
|
62
|
-
|
63
|
-
|
64
|
-
|
102
|
+
```ruby
|
103
|
+
# Notifies NewRelic and drops the message in log found at Blogger.production_log_location
|
104
|
+
Blogger.log :production, :error => e, :message => "#{e} broke stuff"
|
105
|
+
Scribbler.log :production, :error => e, :message => "#{e} broke stuff"
|
65
106
|
|
66
|
-
|
67
|
-
|
68
|
-
|
107
|
+
# Only logs to log/delayed_job.log and doesn't notify NewRelic
|
108
|
+
Blogger.log :delayed_job, :message => "Successfully executed Delayed Job"
|
109
|
+
Scribbler.log :delayed_job, :message => "Successfully executed Delayed Job"
|
69
110
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
111
|
+
# Doesn't notify NewRelic but gives the method access to the error and logs the message
|
112
|
+
# to the given logfile
|
113
|
+
Blogger.log 'production', :new_relic => false, :error => e, :message => "#{e} broke stuff"
|
114
|
+
Scribbler.log 'production', :new_relic => false, :error => e, :message => "#{e} broke stuff"
|
74
115
|
|
75
|
-
|
76
|
-
|
77
|
-
|
116
|
+
# Logs to given file without using the fancy log methods
|
117
|
+
Blogger.log File.expand_path(File.join(File.dirname(__FILE__), 'logfile.log')), :message => "#{e} broke stuff"
|
118
|
+
Scribbler.log File.expand_path(File.join(File.dirname(__FILE__), 'logfile.log')), :message => "#{e} broke stuff"
|
119
|
+
```
|
78
120
|
|
79
121
|
Log options with the default template proc:
|
80
122
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
123
|
+
```
|
124
|
+
# options - Hash of options for logging on Ngin
|
125
|
+
# :error - Error object, mostly for passing to NewRelic
|
126
|
+
# :message - Message to log in the actual file [REQUIRED]
|
127
|
+
# :custom_fields - Custom fields dropped into the default template
|
128
|
+
# :template - Whether or not to use the template at this log
|
129
|
+
# :new_relic - Notify NewRelic of the error (default: true)
|
130
|
+
```
|
87
131
|
|
88
132
|
With the template enabled (either during call to log [:template => true] or by setting to
|
89
133
|
be used by default) you will have each log entry wrapped into a template to pretty-up and
|
@@ -94,7 +138,10 @@ docs and specs for more information.
|
|
94
138
|
|
95
139
|
* Configure the module/class receiving the include
|
96
140
|
* Configurable notification gem (NewRelic, Airbrake, etc.)
|
141
|
+
* Have default template cascade through hashes/arrays for prettier viewing
|
97
142
|
* Currently attempts to notify NewRelic if its there, abstract and allow custom services
|
98
143
|
* Allow a class to set default options for a log call within itself
|
99
144
|
* Allow there to be a log made without the option[:message], in case its all custom_fields or someting
|
100
145
|
* Allow event hooks on log call?
|
146
|
+
* Log4r support
|
147
|
+
* Bring class-level methods down to instance methods (More OO)
|
data/bin/scribbler
CHANGED
@@ -7,7 +7,7 @@ class ScribblerExecutable < Thor
|
|
7
7
|
desc "install", "Installs the necessary files for Scribbler (default: config/initializers/scribbler.rb)"
|
8
8
|
method_option :path, :aliases => "-p", :desc => "Specify a different path for the scribbler initialization"
|
9
9
|
def install
|
10
|
-
Scribbler::Executable.install(options)
|
10
|
+
Scribbler::Executable.new.install(options)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
data/lib/scribbler.rb
CHANGED
@@ -1,7 +1,68 @@
|
|
1
1
|
require 'active_support/all'
|
2
2
|
require 'scribbler/version'
|
3
3
|
require 'scribbler/configurator'
|
4
|
-
require 'scribbler/
|
4
|
+
require 'scribbler/log_location'
|
5
|
+
require 'scribbler/logger'
|
5
6
|
require 'scribbler/includeables'
|
6
|
-
require 'scribbler/
|
7
|
+
require 'scribbler/cli_client'
|
7
8
|
require 'scribbler/executable'
|
9
|
+
|
10
|
+
module Scribbler
|
11
|
+
include Includeables
|
12
|
+
# Rails style configure block with some cleanup afterwards. This is the
|
13
|
+
# main method that kicks off the module and is necessary for its operation
|
14
|
+
#
|
15
|
+
# &block - Block is class_eval'd to give total access to the config file.
|
16
|
+
# Most importantly giving access to `config` object
|
17
|
+
#
|
18
|
+
# Examples:
|
19
|
+
#
|
20
|
+
# Scribbler.configure do |config|
|
21
|
+
# config.logs = %w[log1 log2]
|
22
|
+
# config.application_include = true
|
23
|
+
# end
|
24
|
+
# # => Nothing
|
25
|
+
#
|
26
|
+
# Returns Nothing
|
27
|
+
# TODO Abstract the callbacks so that we can just add them where they're written
|
28
|
+
def self.configure
|
29
|
+
yield config
|
30
|
+
include_in_application
|
31
|
+
end
|
32
|
+
|
33
|
+
# Simply returns the configurator class.
|
34
|
+
#
|
35
|
+
# Examples:
|
36
|
+
#
|
37
|
+
# Scribbler.config
|
38
|
+
# # => Scribbler::Configurator
|
39
|
+
#
|
40
|
+
# Returns the singleton configurator
|
41
|
+
def self.config
|
42
|
+
@config ||= Configurator.new
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# If the config agrees, attempt to include our special methods
|
48
|
+
# in the main application object.
|
49
|
+
#
|
50
|
+
# Example:
|
51
|
+
#
|
52
|
+
# Scribbler.include_in_application
|
53
|
+
# # => Nothing
|
54
|
+
#
|
55
|
+
# Returns Nothing
|
56
|
+
#
|
57
|
+
# TODO: Allow config to define where we send the include
|
58
|
+
def self.include_in_application
|
59
|
+
if config.application_include
|
60
|
+
begin
|
61
|
+
::Rails.application.class.parent.send :include, Includeables
|
62
|
+
rescue NameError
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
require 'scribbler/base'
|
data/lib/scribbler/base.rb
CHANGED
@@ -1,199 +1,23 @@
|
|
1
1
|
module Scribbler
|
2
|
-
|
3
|
-
# Gets the path of this Gem
|
4
|
-
#
|
5
|
-
# Examples:
|
6
|
-
#
|
7
|
-
# Base.gem_path
|
8
|
-
# # => '/some/home/.rvm/gems/ruby-1.9.3-p125/gems/scribbler-0.0.1/'
|
9
|
-
#
|
10
|
-
# Returns String of the current gem's directory path
|
11
|
-
def self.gem_path
|
12
|
-
File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
13
|
-
end
|
14
|
-
|
15
|
-
# Gets all the paths to the template files in the gem's template directory
|
16
|
-
#
|
17
|
-
# Examples:
|
18
|
-
#
|
19
|
-
# Base.templates
|
20
|
-
# # => ['/some/home/.rvm/gems/ruby-1.9.3-p125/gems/scribbler-0.0.1/templates/1.rb',
|
21
|
-
# # '/some/home/.rvm/gems/ruby-1.9.3-p125/gems/scribbler-0.0.1/templates/2.rb]
|
22
|
-
#
|
23
|
-
# Returns Array of Strings of the gem's template files
|
24
|
-
def self.templates
|
25
|
-
Dir.glob(File.join(gem_path, 'templates', '*'))
|
26
|
-
end
|
27
|
-
|
28
|
-
# Gets the path to the default install directory. If Rails is present
|
29
|
-
# it will default to the Rails.root/config/initializers/. Otherwise
|
30
|
-
# it assumes its the $PWD/config/initializer. Should look at a cleaner
|
31
|
-
# abstraction of this
|
32
|
-
#
|
33
|
-
# Examples:
|
34
|
-
#
|
35
|
-
# Base.default_install_path
|
36
|
-
# # => '/some/home/projects/rails_app/config/initializers/'
|
37
|
-
#
|
38
|
-
# Returns String for best guess of a good install path
|
39
|
-
def self.default_install_path
|
40
|
-
begin
|
41
|
-
::Rails.root.join 'config', 'initializers', ''
|
42
|
-
rescue NameError
|
43
|
-
File.join Dir.pwd, 'config', 'initializers', ''
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Rails style configure block with some cleanup afterwards. This is the
|
48
|
-
# main method that kicks off the module and is necessary for its operation
|
49
|
-
#
|
50
|
-
# &block - Block is class_eval'd to give total access to the config file.
|
51
|
-
# Most importantly giving access to `config` object
|
52
|
-
#
|
53
|
-
# Examples:
|
54
|
-
#
|
55
|
-
# Base.configure do
|
56
|
-
# config.logs = %w[log1 log2]
|
57
|
-
# config.application_include = true
|
58
|
-
# end
|
59
|
-
# # => Nothing
|
60
|
-
#
|
61
|
-
# Returns Nothing
|
62
|
-
# TODO Abstract the callbacks so that we can just add them where they're written
|
2
|
+
module Base
|
63
3
|
def self.configure(&block)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
# Returns the singleton configurator
|
77
|
-
def self.config
|
78
|
-
Scribbler::Configurator
|
79
|
-
end
|
80
|
-
|
81
|
-
# Public: Save ourselves some repetition. Notifies error to NewRelic
|
82
|
-
# and drops given string into a given log.
|
83
|
-
#
|
84
|
-
# location - Either a pathname from the above method or symbol for an above
|
85
|
-
# method
|
86
|
-
# options - Hash of options for logging on Ngin
|
87
|
-
# :error - Error object, mostly for passing to NewRelic
|
88
|
-
# :message - Message to log in the actual file
|
89
|
-
# :custom_fields - Custom fields dropped into the default template
|
90
|
-
# :template - Whether or not to use the template at this log
|
91
|
-
# :new_relic - Notify NewRelic of the error (default: true)
|
92
|
-
#
|
93
|
-
# Examples
|
94
|
-
#
|
95
|
-
# log(Ngin.subseason_log_location, :error => e, :message => "Error message stuff", :new_relic => false)
|
96
|
-
#
|
97
|
-
# log(:subseason, :error => e, :message => "Error message stuff")
|
98
|
-
#
|
99
|
-
# log(:subseason, :message => "Logging like a bauss")
|
100
|
-
#
|
101
|
-
# Returns Nothing.
|
102
|
-
def self.log(location, options={})
|
103
|
-
options = {
|
104
|
-
:template => config.use_template_by_default,
|
105
|
-
:stack_frame => options[:call_stack] ? Kernel.caller[1..-1] : nil
|
106
|
-
}.merge options
|
107
|
-
begin
|
108
|
-
NewRelic::Agent.notice_error(options[:error]) if options[:error] and options[:new_relic] != false
|
109
|
-
rescue NameError
|
110
|
-
nil
|
111
|
-
end
|
112
|
-
|
113
|
-
apply_to_log location, options
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
# Builds the message and any other options into a string
|
118
|
-
# using the template defined in the configure
|
119
|
-
#
|
120
|
-
# options - options hash that comprises most of the important log pieces
|
121
|
-
# :message - The message we're wrapping into the templater [required]
|
122
|
-
# :template - Whether or not to use the template method
|
123
|
-
# **Other option information given in the .log docs
|
124
|
-
#
|
125
|
-
# Examples
|
126
|
-
#
|
127
|
-
# Base.build_with_template(:message => "...", :template => false)
|
128
|
-
# # => "..."
|
129
|
-
#
|
130
|
-
# Base.build_with_template
|
131
|
-
# # => nil
|
132
|
-
#
|
133
|
-
# Base.build_with_template(:message => "...", :template => true)
|
134
|
-
# # => <<-EXAMPLE
|
135
|
-
# --------------------
|
136
|
-
# TEMPLATE STUFF
|
137
|
-
# ....
|
138
|
-
# EXAMPLE
|
139
|
-
#
|
140
|
-
# Returns nil, a string, or a string built with calling the Configurator.template method
|
141
|
-
def self.build_with_template(options={})
|
142
|
-
if options[:message].present?
|
143
|
-
options[:message] = options[:message].strip_heredoc.rstrip
|
144
|
-
options[:template] ? config.template.call(options) : options[:message]
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Drops built message into the log with the given location
|
149
|
-
#
|
150
|
-
# location - location either found with Base.*_log_location or by hoping a valid
|
151
|
-
# path string or Path object were passed
|
152
|
-
# options - options hash
|
153
|
-
# :message - Message to be built and put in log file [required]
|
154
|
-
# ** Other hash information given in Base.log
|
155
|
-
#
|
156
|
-
# Examples
|
157
|
-
#
|
158
|
-
# Base.apply_to_log :some_loc, :message => "...", :template => false, :error => e
|
159
|
-
# # => Nothing
|
160
|
-
#
|
161
|
-
# Returns Nothing
|
162
|
-
def self.apply_to_log(location, options={})
|
163
|
-
if can_apply_to_log? location, options
|
164
|
-
File.open log_at(location), 'a' do |f|
|
165
|
-
f.puts build_with_template(options)
|
166
|
-
end
|
4
|
+
ActiveSupport::Deprecation.deprecated_method_warning :configure,
|
5
|
+
"Scribbler is now preferred over Scribbler::Base see github for more info"
|
6
|
+
Scribbler.configure { |config| config.instance_eval(&block) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.method_missing(method, *args, &block)
|
10
|
+
if Scribbler.respond_to? method
|
11
|
+
ActiveSupport::Deprecation.deprecated_method_warning method,
|
12
|
+
"Scribbler is now preferred over Scribbler::Base see github for more info"
|
13
|
+
Scribbler.public_send method, *args, &block
|
14
|
+
else
|
15
|
+
super
|
167
16
|
end
|
168
17
|
end
|
169
18
|
|
170
|
-
|
171
|
-
|
172
|
-
location.present? and
|
173
|
-
(options[:message].present? or
|
174
|
-
options[:object].present? or
|
175
|
-
options[:custom_fields].present?)
|
176
|
-
end
|
177
|
-
|
178
|
-
# If the config agrees, attempt to include our special methods
|
179
|
-
# in the main application object.
|
180
|
-
#
|
181
|
-
# Example:
|
182
|
-
#
|
183
|
-
# Base.include_in_application
|
184
|
-
# # => Nothing
|
185
|
-
#
|
186
|
-
# Returns Nothing
|
187
|
-
#
|
188
|
-
# TODO: Allow config to define where we send the include
|
189
|
-
def self.include_in_application
|
190
|
-
if config.application_include
|
191
|
-
begin
|
192
|
-
::Rails.application.class.parent.send :include, Includeables
|
193
|
-
rescue NameError
|
194
|
-
nil
|
195
|
-
end
|
196
|
-
end
|
19
|
+
def self.respond_to?(method, include_private = false)
|
20
|
+
Scribbler.respond_to?(method) || super
|
197
21
|
end
|
198
22
|
end
|
199
23
|
end
|