scribbler 0.0.2 → 0.1.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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scribbler (0.0.2)
4
+ scribbler (0.1.0)
5
5
  activesupport
6
6
  thor
7
7
 
data/README.markdown CHANGED
@@ -15,7 +15,7 @@ Currently it assists in:
15
15
 
16
16
  In your Rails project add
17
17
 
18
- gem scribbler
18
+ gem 'scribbler'
19
19
 
20
20
  to your Gemfile and
21
21
 
@@ -1,7 +1,4 @@
1
1
  module Scribbler
2
- # TODO not sure this'll work
3
- delegate :configure, :to => :Base
4
- delegate :log, :to => :Base
5
2
  class Base
6
3
  # Gets the path of this Gem
7
4
  #
@@ -67,6 +64,7 @@ module Scribbler
67
64
  class_eval(&block)
68
65
  Base.include_in_application
69
66
  BaseIncluder.include_includeables
67
+ build_methods
70
68
  end
71
69
 
72
70
  # Simply returns the configurator class.
@@ -81,7 +79,119 @@ module Scribbler
81
79
  Scribbler::Configurator
82
80
  end
83
81
 
82
+ # Public: Save ourselves some repetition. Notifies error to NewRelic
83
+ # and drops given string into a given log.
84
+ #
85
+ # location - Either a pathname from the above method or symbol for an above
86
+ # method
87
+ # options - Hash of options for logging on Ngin
88
+ # :error - Error object, mostly for passing to NewRelic
89
+ # :message - Message to log in the actual file
90
+ # :custom_fields - Custom fields dropped into the default template
91
+ # :template - Whether or not to use the template at this log
92
+ # :new_relic - Notify NewRelic of the error (default: true)
93
+ #
94
+ # Examples
95
+ #
96
+ # log(Ngin.subseason_log_location, :error => e, :message => "Error message stuff", :new_relic => false)
97
+ #
98
+ # log(:subseason, :error => e, :message => "Error message stuff")
99
+ #
100
+ # log(:subseason, :message => "Logging like a bauss")
101
+ #
102
+ # Returns Nothing.
103
+ def self.log(location, options={})
104
+ options = {
105
+ :template => config.use_template_by_default
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
+
84
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 location.present? and options[:message].present?
164
+ log = File.open(find_file_at(location), 'a')
165
+ log.puts build_with_template(options)
166
+ log.close
167
+ end
168
+ end
169
+
170
+ # Attempts to turn a symbol or string into the *_log_location method that
171
+ # was auto-build based on Configurator.logs and finds the file path
172
+ #
173
+ # location - a string or symbol that will be turned into a *_log_location
174
+ # method
175
+ #
176
+ # Examples
177
+ #
178
+ # Base.find_file_at :a_file
179
+ # # => <#Path:...> # The method `a_file_log_location` exists
180
+ #
181
+ # Base.find_file_at :another_file
182
+ # # => :another_file # The method `another_file_log_location` does not exist
183
+ #
184
+ # Returns Nothing
185
+ #
186
+ # TODO: allow the log base directory to be set in configurator
187
+ def self.find_file_at(location)
188
+ if location.is_a?(Symbol) or location.is_a?(String)
189
+ real_method = location.to_s + "_log_location"
190
+ location = respond_to?(real_method) ? send(real_method) : location.to_s
191
+ end
192
+ location
193
+ end
194
+
85
195
  # If the config agrees, attempt to include our special methods
86
196
  # in the main application object.
87
197
  #
@@ -91,7 +201,8 @@ module Scribbler
91
201
  # # => Nothing
92
202
  #
93
203
  # Returns Nothing
94
- # TODO Allow config to define where we send the include
204
+ #
205
+ # TODO: Allow config to define where we send the include
95
206
  def self.include_in_application
96
207
  if config.application_include
97
208
  begin
@@ -1,15 +1,142 @@
1
1
  module Scribbler
2
2
  class Configurator
3
3
  class << self
4
- attr_accessor :logs, :application_include
4
+ attr_accessor :logs, :application_include, :template, :use_template_by_default, :log_directory
5
5
  end
6
6
 
7
+ # Provides location for getting the directory Scribbler will place
8
+ # log files in. Favors RailsApplication/log/ but falls back to
9
+ # $PWD/log if not set in config
10
+ #
11
+ # Examples
12
+ #
13
+ # Configurator.log_directory
14
+ # # => "/some/path/to/log/"
15
+ #
16
+ # Returns String for log directory location
17
+ def self.log_directory
18
+ @log_directory ||= begin
19
+ Rails.root.join('log')
20
+ rescue NameError
21
+ File.join Dir.pwd, 'log'
22
+ end
23
+ end
24
+
25
+ # List of strings or symbols that represent logs we want methods
26
+ # generated for
27
+ #
28
+ # Default: []
29
+ #
30
+ # Examples
31
+ #
32
+ # Scribbler::Configurator.logs
33
+ # # => ['copy', 'destroy']
34
+ #
35
+ # Returns list of logs
7
36
  def self.logs
8
37
  @logs ||= []
9
38
  end
10
39
 
40
+ # Boolean used for deciding whether or not Scribbler should
41
+ # define #*_log_location methods and a .log method in a rails application
42
+ #
43
+ # Default: false
44
+ #
45
+ # Examples
46
+ #
47
+ # Scribbler::Configurator.application_include
48
+ # # => false
49
+ #
50
+ # Returns boolean
51
+ #
52
+ # TODO: Allow the class we're sending the include to to be custom
11
53
  def self.application_include
12
54
  @application_include || false
13
55
  end
56
+
57
+ # Boolean for deciding if we should use the logger template by
58
+ # by default when calling Base.log
59
+ #
60
+ # Default: false
61
+ #
62
+ # Examples
63
+ #
64
+ # Scribbler::Configurator.use_template_by_default
65
+ # # => false
66
+ #
67
+ # Returns boolean
68
+ def self.use_template_by_default
69
+ @use_template_by_default || false
70
+ end
71
+
72
+ # The method that sets a template for each log made with
73
+ # Base.log
74
+ #
75
+ # The template proc is given the whole options hash that is
76
+ # passed through Base.log or YourApplication.log. So if you
77
+ # had:
78
+ #
79
+ # YourApplication.log :a_log,
80
+ # :message => "information data",
81
+ # :custom => "stuff"
82
+ #
83
+ # Then you can assume the template proc will get:
84
+ #
85
+ # options = {
86
+ # :message => "information data",
87
+ # :custom => "stuff"
88
+ # }
89
+ #
90
+ # To set a custom template:
91
+ #
92
+ # Scribbler::Configurator.template = proc do |options|
93
+ # "Message: options[:message]"
94
+ # end
95
+ #
96
+ # From Scribbler::Base.configure that would be:
97
+ #
98
+ # config.template = proc do |options|
99
+ # "Message: options[:message]"
100
+ # end
101
+ #
102
+ # **Keep in mind** that the template can be ignored at any
103
+ # Base.log call with:
104
+ #
105
+ # Base.log :your_log, :template => false, :message "..."
106
+ #
107
+ # Default:
108
+ #
109
+ # -------------------------------------------------
110
+ # SomeObject: #{id} # options[:object] and options[:object].try(:id)
111
+ # Custom1: some good info # options[:custom_fields] hash
112
+ # Custom2: some better info # Left of colon is the key.humanize, right is the value
113
+ # OH NO YOU BROKED STUFF # options[:message].strip_heredoc
114
+ # DO PLX FIX #
115
+ #
116
+ # Examples
117
+ #
118
+ # Scribbler::Configurator.template
119
+ # # => <#Proc:...>
120
+ #
121
+ # Returns the proc that wraps around each log entry
122
+ #
123
+ # TODO: Block input that would break this
124
+ # TODO: Test
125
+ def self.template
126
+ @template ||= proc do |options|
127
+ begin
128
+ if_id = options[:object].id
129
+ rescue NoMethodError
130
+ if_id = "no id"
131
+ end
132
+ custom_fields = options[:custom_fields].to_a.collect { |x| "#{x[0].to_s.humanize}: #{x[1]}" }.join("\n")
133
+
134
+ template = "-------------------------------------------------\n"
135
+ template << "#{Time.now}\n"
136
+ template << "#{options[:object].class.name}: #{if_id}\n" if options[:object]
137
+ template << "#{custom_fields}\n" if custom_fields.present?
138
+ template << "#{options[:message]}\n\n"
139
+ end
140
+ end
14
141
  end
15
142
  end
@@ -11,7 +11,7 @@ module Scribbler
11
11
  # Returns Nothing
12
12
  # TODO Rework; there must be a more sane way of including these
13
13
  def self.include_includeables
14
- Scribbler::Base.send :include, Scribbler::Includeables
14
+ Base.send :include, Scribbler::Includeables
15
15
  end
16
16
  end
17
17
 
@@ -37,8 +37,7 @@ module Scribbler
37
37
  # Returns Pathname to log
38
38
  Scribbler::Base.config.logs.each do |value|
39
39
  define_singleton_method "#{value}_log_location" do
40
- Rails.root.join('log', "#{value}.log")
41
- #TODO remove dependence on Rails here
40
+ File.join Scribbler::Configurator.log_directory, "#{value}.log"
42
41
  end
43
42
  end
44
43
  end
@@ -63,26 +62,7 @@ module Scribbler
63
62
  #
64
63
  # Returns Nothing.
65
64
  def log(location, options={})
66
- begin
67
- NewRelic::Agent.notice_error(options[:error]) if options[:error] and options[:new_relic] != false
68
- rescue NameError
69
- nil
70
- end
71
-
72
- real_location = location
73
- if real_location.is_a?(Symbol) or real_location.is_a?(String)
74
- real_method = location.to_s + "_log_location"
75
- real_location = self.send(real_method) if self.respond_to? real_method
76
- real_location = real_location.to_s
77
- end
78
-
79
- #if File.exists?(real_location) and options[:message].present?
80
- if options[:message].present?
81
- message = options[:message].strip_heredoc
82
- log = File.open(real_location, 'a')
83
- log.puts message
84
- log.close
85
- end
65
+ Scribbler::Base.log(location, options)
86
66
  end
87
67
  end
88
68
  end
@@ -1,3 +1,3 @@
1
1
  module Scribbler
2
- VERSION = '0.0.2'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -6,6 +6,7 @@ module Scribbler
6
6
 
7
7
  before :each do
8
8
  Object.send :remove_const, :Rails if defined?(Rails) == 'constant' && Rails.class == Class
9
+ Time.stub :now => "now"
9
10
  end
10
11
 
11
12
  it "should give me a configurator" do
@@ -34,6 +35,7 @@ module Scribbler
34
35
  describe "configure" do
35
36
  it "kicks off the module and sends includes" do
36
37
  subject.should_receive(:include_in_application).once
38
+ subject.should_receive(:build_methods).once # Twice if we didn't stub below method
37
39
  BaseIncluder.should_receive(:include_includeables).once
38
40
  subject.configure do
39
41
  end
@@ -46,5 +48,110 @@ module Scribbler
46
48
  subject.config.application_include.should be_true
47
49
  end
48
50
  end
51
+
52
+ describe "build with template" do
53
+ let(:some_object) { stub(:id => "no id", :class => stub(:name => "SomeObject")) }
54
+ before :each do
55
+ subject.configure do
56
+ config.application_include = false
57
+ end
58
+ end
59
+
60
+ it "calls log, skips templater and still works" do
61
+ Scribbler::Base.send(:build_with_template,
62
+ :object => some_object,
63
+ :template => false,
64
+ :message => "test\n123").should == "test\n123"
65
+ end
66
+
67
+ it "calls log and gets message with template wrapper" do
68
+ Scribbler::Base.send(:build_with_template,
69
+ :object => some_object,
70
+ :template => true,
71
+ :message => <<-MSG
72
+ test
73
+ 123
74
+ MSG
75
+ ).should == <<-MSG.strip_heredoc
76
+ -------------------------------------------------
77
+ now
78
+ SomeObject: no id
79
+ test
80
+ 123
81
+
82
+ MSG
83
+ end
84
+
85
+ it "calls log and gets message with custom params" do
86
+ Scribbler::Base.send(:build_with_template,
87
+ :template => true,
88
+ :object => some_object,
89
+ :custom_fields => {:test1 => 1, :test2 => 2},
90
+ :message => <<-MSG
91
+ test
92
+ 123
93
+ MSG
94
+ ).should == <<-MSG.strip_heredoc
95
+ -------------------------------------------------
96
+ now
97
+ SomeObject: no id
98
+ Test1: 1
99
+ Test2: 2
100
+ test
101
+ 123
102
+
103
+ MSG
104
+ end
105
+ end
106
+
107
+ describe "apply to log" do
108
+ before :each do
109
+ subject.configure do
110
+ config.logs = %w[test_log]
111
+ end
112
+ end
113
+
114
+ it "should not work without location" do
115
+ subject.apply_to_log(nil, :message => "...").should be_nil
116
+ end
117
+
118
+ it "should not work without message" do
119
+ subject.should_not_receive :test_log_log_location
120
+ subject.apply_to_log(:test_log).should be_nil
121
+ end
122
+
123
+ it "should build a template and try to put it in a file" do
124
+ options = { :message => "..." }
125
+ subject.should_receive(:send).with "test_log_log_location"
126
+ subject.should_receive(:build_with_template).with options
127
+ file_stub = stub
128
+ file_stub.should_receive :puts
129
+ file_stub.should_receive :close
130
+ File.should_receive(:open) { file_stub }
131
+ subject.apply_to_log :test_log, options
132
+ end
133
+ end
134
+
135
+ describe "find file at" do
136
+ it "doesn't find a file method" do
137
+ # in case we have bad config data lingering
138
+ subject.stub(:respond_to?).with('test_log_log_location').and_return false
139
+ subject.should_not_receive(:test_log_log_location)
140
+ subject.find_file_at(:test_log).should == 'test_log'
141
+ end
142
+
143
+ it "finds a file method defined" do
144
+ subject.configure do
145
+ config.logs = %w[test_log]
146
+ end
147
+ subject.should_receive(:test_log_log_location).once
148
+ subject.find_file_at :test_log
149
+ end
150
+
151
+ it "isn't a string or a symbol and just returns the input" do
152
+ path = Pathname.new '/'
153
+ subject.find_file_at(path).should be(path)
154
+ end
155
+ end
49
156
  end
50
157
  end
@@ -21,5 +21,34 @@ module Scribbler
21
21
  subject.application_include.should == true
22
22
  end
23
23
  end
24
+
25
+ describe "log directory" do
26
+ it "tries a rails root when Rails defined" do
27
+ root_stub = stub
28
+ root_stub.should_receive(:join).with 'log'
29
+ Rails = stub(:root => root_stub)
30
+ subject.log_directory
31
+ end
32
+
33
+ it "falls back to pwd/log without rails" do
34
+ dir = "dir/"
35
+ Rails.should_receive(:root).and_raise(NameError)
36
+ Dir.should_receive(:pwd).and_return('dir')
37
+ subject.log_directory.should == 'dir/log'
38
+ end
39
+
40
+ it "sets the log directory" do
41
+ var_log = File.new "/var/log"
42
+ subject.log_directory = var_log
43
+ subject.log_directory.should == var_log
44
+ subject.log_directory = nil
45
+
46
+ # Check the reset
47
+ Rails.should_receive(:root).and_raise(NameError)
48
+ Dir.should_receive(:pwd).and_return('dir')
49
+ subject.log_directory.should == 'dir/log'
50
+ subject.log_directory
51
+ end
52
+ end
24
53
  end
25
54
  end
@@ -3,15 +3,66 @@ Scribbler::Base.configure do
3
3
  # Unless you'd like to experiment with breaking things and battling dragons,
4
4
  # please only use what we document here.
5
5
  #
6
- # Alter the path to the configuration yaml. If you alter those variables
7
- # from this config, those here will take precedence. Don't confuse yourself
8
- # by having thos options here and there.
9
- #
10
- # config.yaml_config_path = Rails.root.join('config', 'scribbler.yml')
11
- #
12
6
  # Include the log methods to the rails application. So, if you have an
13
7
  # application called Blog you can do Blog.log(...), rather than
14
8
  # Scribbler.log(...). Default: false
15
9
  #
16
10
  # config.application_include = true
11
+ #
12
+ #
13
+ # What directory should these logs be placed in? The default is
14
+ # to try the Rails log directory and fallback to the $PWD/log path
15
+ #
16
+ # config.log_directory = File.new '/a/better/path'
17
+ #
18
+ #
19
+ # A list of the logs you'd like location methods for. if the logs list
20
+ # has:
21
+ #
22
+ # ['log1']
23
+ #
24
+ # You are afforded a Base.log1_log_location method and you may do:
25
+ #
26
+ # Base.log :log1, ....
27
+ #
28
+ # REQUIRED
29
+ #
30
+ # config.logs = %w[log1 log2]
31
+ #
32
+ # This option enables log templating. Each time you log a message you
33
+ # can have it automatically wrapped in some sugar. The default is something
34
+ # like:
35
+ #
36
+ # -------------------------------------------------
37
+ # SomeObject: #{id} # options[:object] and options[:object].try(:id)
38
+ # Custom1: some good info # options[:custom_fields] hash
39
+ # Custom2: some better info # Left of colon is the key.humanize, right is the value
40
+ # OH NO YOU BROKED STUFF # options[:message].strip_heredoc
41
+ # DO PLX FIX #
42
+ #
43
+ # If you would rather this not be default you may set this to false. Keep
44
+ # in mind, there is an option on the Base.log to enable or disable the
45
+ # template on a per-call basis. (:template)
46
+ #
47
+ # config.use_template_by_default = true # Default: false
48
+ #
49
+ #
50
+ # Don't like the default template above? Write your own proc here.
51
+ # The proc is given the options hash that you give to Base.log so you're
52
+ # given plenty of control over what information you have to work with.
53
+ #
54
+ # options - Hash of options for logging on Ngin
55
+ # :error - Error object, mostly for passing to NewRelic
56
+ # :message - Message to log in the actual file [REQUIRED]
57
+ # :custom_fields - Custom fields dropped into the default template
58
+ # :template - Whether or not to use the template at this log
59
+ # :new_relic - Notify NewRelic of the error (default: true)
60
+ #
61
+ # config.template = proc do |options|
62
+ # <<-MSG
63
+ # ##########
64
+ # Cool template bro!
65
+ # Message: #{options[:message]}
66
+ # MSG
67
+ # end
17
68
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scribbler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-20 00:00:00.000000000 Z
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -140,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
140
  version: '0'
141
141
  segments:
142
142
  - 0
143
- hash: -2255771618684195708
143
+ hash: -504908089194974695
144
144
  required_rubygems_version: !ruby/object:Gem::Requirement
145
145
  none: false
146
146
  requirements:
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  version: '0'
150
150
  segments:
151
151
  - 0
152
- hash: -2255771618684195708
152
+ hash: -504908089194974695
153
153
  requirements: []
154
154
  rubyforge_project:
155
155
  rubygems_version: 1.8.24