logbook 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/README.rdoc +27 -0
- data/Rakefile +2 -0
- data/lib/logbook.rb +34 -0
- data/lib/logbook/agent.rb +79 -0
- data/lib/logbook/client.rb +49 -0
- data/lib/logbook/railtie.rb +27 -0
- data/lib/logbook/version.rb +3 -0
- data/logbook.gemspec +27 -0
- data/spec/agent_spec.rb +66 -0
- data/spec/client_spec.rb +57 -0
- data/spec/logbook_spec.rb +30 -0
- data/spec/spec_helper.rb +10 -0
- data/tmp/.keep +0 -0
- metadata +139 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm ree@logbook_gem
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
logbook (0.0.1)
|
5
|
+
addressable
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
addressable (2.2.2)
|
11
|
+
diff-lcs (1.1.2)
|
12
|
+
fakeweb (1.3.0)
|
13
|
+
rspec (2.0.0)
|
14
|
+
rspec-core (= 2.0.0)
|
15
|
+
rspec-expectations (= 2.0.0)
|
16
|
+
rspec-mocks (= 2.0.0)
|
17
|
+
rspec-core (2.0.0)
|
18
|
+
rspec-expectations (2.0.0)
|
19
|
+
diff-lcs (>= 1.1.2)
|
20
|
+
rspec-mocks (2.0.0)
|
21
|
+
rspec-core (= 2.0.0)
|
22
|
+
rspec-expectations (= 2.0.0)
|
23
|
+
timecop (0.3.5)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
addressable
|
30
|
+
fakeweb
|
31
|
+
logbook!
|
32
|
+
rspec
|
33
|
+
timecop
|
data/README.rdoc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
= What's logbook?
|
2
|
+
|
3
|
+
Logbook is a hosted service for collecting log entries from your application.
|
4
|
+
|
5
|
+
= Requirements
|
6
|
+
|
7
|
+
Works in Rails 3 only at the moment. Check back later for more framework / versions.
|
8
|
+
|
9
|
+
= Getting started
|
10
|
+
|
11
|
+
* Go to http://logbook.me and create an account
|
12
|
+
* Download logbook.yml that it genereated for you to the config dir
|
13
|
+
* Add this gem to your Gemfile:
|
14
|
+
|
15
|
+
gem 'logbook'
|
16
|
+
|
17
|
+
= Usage
|
18
|
+
|
19
|
+
Anywhere in your application:
|
20
|
+
|
21
|
+
Logbook.debug 'facility', { :my => 'data' }
|
22
|
+
|
23
|
+
Logbook has a method for every severity supported by the standard Ruby logger (in order of priority: debug < info < warn < error < fatal < unknown). Thefirst parameter it takes specifies "facility". It's a linux syslog analogy and allows to have different "types" of log entries so that you could filter them in the web interface more easily later. The second parameter needs to be a hash with any data that you want to log. Passing a hash is good because it allows to log structured data, which again makes it possible to filter records in the web interface.
|
24
|
+
|
25
|
+
= Authors
|
26
|
+
|
27
|
+
We created this service and gem during Rails Rumble 2010: http://railsrumble.com/teams/48-hours-of-unpaid-work-and-5-cookies
|
data/Rakefile
ADDED
data/lib/logbook.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'logbook/agent'
|
2
|
+
require 'logbook/client'
|
3
|
+
require 'logbook/railtie'
|
4
|
+
|
5
|
+
module Logbook
|
6
|
+
class << self
|
7
|
+
attr_accessor :api_key
|
8
|
+
attr_accessor :logger
|
9
|
+
attr_accessor :delay_between_requests
|
10
|
+
|
11
|
+
def start
|
12
|
+
agent.start
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop
|
16
|
+
agent.stop
|
17
|
+
end
|
18
|
+
|
19
|
+
%W(debug info warn error fatal unknown).each do |severity|
|
20
|
+
define_method severity do |facility, payload|
|
21
|
+
agent.add_entry(severity.to_sym, facility, payload)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def agent
|
28
|
+
@agent ||= Logbook::Agent.instance
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Default values
|
33
|
+
self.delay_between_requests = 5
|
34
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
class Logbook::Agent
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_reader :client, :entries, :stop_processing
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@client = Logbook::Client.new(Logbook.api_key)
|
11
|
+
@entries = []
|
12
|
+
@semaphore = Mutex.new
|
13
|
+
Logbook.logger.info('Logbook agent started')
|
14
|
+
end
|
15
|
+
|
16
|
+
def start
|
17
|
+
@keep_running = true
|
18
|
+
@loop = Thread.new do
|
19
|
+
run_loop
|
20
|
+
end
|
21
|
+
@loop['label'] = 'Logbook loop'
|
22
|
+
end
|
23
|
+
|
24
|
+
def stop
|
25
|
+
Logbook.logger.info 'Stopping logbook agent. Checking if there is anything to send'
|
26
|
+
@keep_running = false
|
27
|
+
@loop.join
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset
|
31
|
+
entries.clear
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_loop
|
35
|
+
while keep_running?
|
36
|
+
process
|
37
|
+
sleep Logbook.delay_between_requests
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def process
|
42
|
+
@semaphore.synchronize {
|
43
|
+
return if entries.empty?
|
44
|
+
|
45
|
+
# Copying the queue
|
46
|
+
@entries_to_send = entries.dup
|
47
|
+
Logbook.logger.info("Sending #{@entries_to_send.size} entries to the server")
|
48
|
+
|
49
|
+
begin
|
50
|
+
@client.send_entries(@entries_to_send)
|
51
|
+
rescue => e
|
52
|
+
Logbook.logger.error("Error when sending data to the server: #{e.message}")
|
53
|
+
|
54
|
+
case e
|
55
|
+
when Logbook::Client::NotAuthorized
|
56
|
+
@stop_processing = true
|
57
|
+
end
|
58
|
+
ensure
|
59
|
+
# Removing sent items from the queue anyway
|
60
|
+
entries.shift(@entries_to_send.size)
|
61
|
+
end
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_entry(severity, facility, payload)
|
66
|
+
entries.push(
|
67
|
+
:severity => severity,
|
68
|
+
:facility => facility,
|
69
|
+
:payload => payload,
|
70
|
+
:timestamp => Time.now.to_s
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def keep_running?
|
77
|
+
@keep_running && !@stop_processing
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/https'
|
3
|
+
require 'addressable/uri'
|
4
|
+
|
5
|
+
class Logbook::Client
|
6
|
+
|
7
|
+
API_URL = "https://logbook.me/entries"
|
8
|
+
|
9
|
+
class NotAuthorized < StandardError ; end
|
10
|
+
class ServerError < StandardError ; end
|
11
|
+
|
12
|
+
attr_reader :api_key
|
13
|
+
|
14
|
+
def initialize(key)
|
15
|
+
@api_key = key
|
16
|
+
end
|
17
|
+
|
18
|
+
def send_entries(entries)
|
19
|
+
uri = URI.parse API_URL
|
20
|
+
|
21
|
+
req = Net::HTTP::Post.new(uri.path)
|
22
|
+
req.content_type = 'application/x-www-form-urlencoded'
|
23
|
+
req.body = request_body(entries)
|
24
|
+
|
25
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
26
|
+
http.use_ssl = true
|
27
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
28
|
+
|
29
|
+
response = http.start {|session| session.request(req) }
|
30
|
+
|
31
|
+
case response
|
32
|
+
when Net::HTTPSuccess
|
33
|
+
true
|
34
|
+
when Net::HTTPUnauthorized
|
35
|
+
raise NotAuthorized
|
36
|
+
else
|
37
|
+
raise ServerError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def request_body(entries)
|
44
|
+
hash = Addressable::URI.new
|
45
|
+
processed = entries.map { |entry| entry.inject({}) { |r, e| r[e.first] = e.last.to_s; r } }
|
46
|
+
hash.query_values = {:entries => processed, :api_key => @api_key}
|
47
|
+
hash.query
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
if defined?(Rails)
|
2
|
+
module Logbook
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
initializer "logbook.start_agent" do
|
5
|
+
Logbook.logger = ActiveSupport::BufferedLogger.new(File.join(Rails.root, 'log', 'logbook.log'))
|
6
|
+
|
7
|
+
config_file = File.join(Rails.root, 'config', 'logbook.yml')
|
8
|
+
|
9
|
+
if !File.exists?(config_file)
|
10
|
+
Logbook.logger.error('config/logbook.yml does not exist, shutting down')
|
11
|
+
next
|
12
|
+
end
|
13
|
+
|
14
|
+
config = YAML.load_file(config_file)[Rails.env.to_s] || {}
|
15
|
+
|
16
|
+
if !config['enabled']
|
17
|
+
Logbook.logger.info("Logbook is not enabled in #{Rails.env}, shutting down")
|
18
|
+
next
|
19
|
+
end
|
20
|
+
|
21
|
+
Logbook.api_key = config['api_key']
|
22
|
+
Logbook.start
|
23
|
+
at_exit { Logbook.stop }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/logbook.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "logbook/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "logbook"
|
7
|
+
s.version = Logbook::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["48 hours of unpaid work and 5 cookies Rails Rumble 2010 Team"]
|
10
|
+
s.email = ["support@logbook.me"]
|
11
|
+
s.homepage = "http://logbook.me"
|
12
|
+
s.summary = %q{Logbook is a hosted service to collect log entries from your application}
|
13
|
+
s.description = %q{A gem to integrate your Rails 3 app with http://logbook.me}
|
14
|
+
|
15
|
+
s.rubyforge_project = "logbook"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency 'rspec'
|
23
|
+
s.add_development_dependency 'timecop'
|
24
|
+
s.add_development_dependency 'fakeweb'
|
25
|
+
|
26
|
+
s.add_dependency 'addressable'
|
27
|
+
end
|
data/spec/agent_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Logbook::Agent do
|
4
|
+
subject { Logbook::Agent.instance }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
subject.client.stub!(:send_entries)
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
subject.reset
|
12
|
+
end
|
13
|
+
|
14
|
+
def process
|
15
|
+
subject.start; subject.stop
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should set api_key for the Client" do
|
19
|
+
subject.client.api_key.should == 'test_key'
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when adding a new entry to the queue' do
|
23
|
+
it 'should add a timestamp to every entry' do
|
24
|
+
time = Time.now
|
25
|
+
Timecop.freeze(time)
|
26
|
+
subject.add_entry :debug, :test, 'test'
|
27
|
+
subject.entries.first[:timestamp].should == time.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when processing the queue' do
|
32
|
+
it 'should empty the queue' do
|
33
|
+
subject.add_entry :debug, :test, 'test'
|
34
|
+
process
|
35
|
+
subject.entries.should be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should send each entry to the server' do
|
39
|
+
subject.add_entry :debug, :test, 'test'
|
40
|
+
subject.client.should_receive(:send_entries).with(subject.entries.dup)
|
41
|
+
process
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when server errors out' do
|
45
|
+
it 'should still clear the queue' do
|
46
|
+
subject.add_entry :debug, :test, 'test'
|
47
|
+
subject.client.stub!(:send_entries).and_raise(Logbook::Client::ServerError)
|
48
|
+
process
|
49
|
+
subject.entries.should be_empty
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should stop processing the queue if it gets a NotAuthorized exception' do
|
53
|
+
subject.client.stub!(:send_entries).and_raise(Logbook::Client::NotAuthorized)
|
54
|
+
subject.add_entry :debug, :test, 'test'
|
55
|
+
process
|
56
|
+
subject.stop_processing.should == true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should clear the queue on reset' do
|
62
|
+
subject.add_entry :debug, :test, 'test'
|
63
|
+
subject.reset
|
64
|
+
subject.entries.should be_empty
|
65
|
+
end
|
66
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Logbook::Client do
|
4
|
+
|
5
|
+
subject { Logbook::Client.new('key') }
|
6
|
+
|
7
|
+
context "when making a request" do
|
8
|
+
let(:request) { FakeWeb.last_request }
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
FakeWeb.register_uri(:post, Logbook::Client::API_URL, {})
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should make a POST request" do
|
15
|
+
subject.send_entries([])
|
16
|
+
request.should_not be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should set content_type to 'text/plain' " do
|
20
|
+
subject.send_entries([])
|
21
|
+
request.content_type.should == 'application/x-www-form-urlencoded'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should send entries in the request" do
|
25
|
+
entries = [{:params => 'params'}]
|
26
|
+
subject.send_entries(entries)
|
27
|
+
request.body.should include("entries[0][params]=params")
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should handle non-sting data' do
|
31
|
+
expect { subject.send_entries([{:time => Time.now}]) }.
|
32
|
+
to_not raise_error
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should send api_key in the request" do
|
36
|
+
subject.send_entries([])
|
37
|
+
request.body.should include("api_key=key")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when processing a response" do
|
42
|
+
it "should not raise anything if response status is 200" do
|
43
|
+
FakeWeb.register_uri(:post, Logbook::Client::API_URL, {:status => ['200', 'Ok']})
|
44
|
+
expect { subject.send_entries([]) }.to_not raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should raise NotAuthorized exception if response status is 401" do
|
48
|
+
FakeWeb.register_uri(:post, Logbook::Client::API_URL, {:status => ['401', 'Not Authorized']})
|
49
|
+
expect { subject.send_entries([]) }.to raise_error(Logbook::Client::NotAuthorized)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should raise ServerError exception if response status is 500" do
|
53
|
+
FakeWeb.register_uri(:post, Logbook::Client::API_URL, {:status => ['500', 'Server Error']})
|
54
|
+
expect { subject.send_entries([]) }.to raise_error(Logbook::Client::ServerError)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Logbook do
|
4
|
+
let(:agent) do
|
5
|
+
Logbook::Agent.instance
|
6
|
+
end
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
agent.client.stub!(:send_entries)
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when starting' do
|
13
|
+
it 'should start the agent' do
|
14
|
+
agent.should_receive(:start)
|
15
|
+
Logbook.start
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should add an entry to the queue' do
|
20
|
+
expect { Logbook.debug :facility, :data => :value }.
|
21
|
+
to change { agent.entries.size }.by(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when stopping' do
|
25
|
+
it 'should stop the agent' do
|
26
|
+
agent.should_receive(:stop)
|
27
|
+
Logbook.stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'logbook'
|
2
|
+
require 'timecop'
|
3
|
+
require 'fakeweb'
|
4
|
+
|
5
|
+
FakeWeb.allow_net_connect = false
|
6
|
+
|
7
|
+
# No need to wait in tests
|
8
|
+
Logbook.delay_between_requests = 0
|
9
|
+
Logbook.api_key = 'test_key'
|
10
|
+
Logbook.logger = Logger.new(File.dirname(__FILE__) + '/../tmp/test.log')
|
data/tmp/.keep
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logbook
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- 48 hours of unpaid work and 5 cookies Rails Rumble 2010 Team
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-17 00:00:00 +04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: timecop
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: fakeweb
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: addressable
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
77
|
+
description: A gem to integrate your Rails 3 app with http://logbook.me
|
78
|
+
email:
|
79
|
+
- support@logbook.me
|
80
|
+
executables: []
|
81
|
+
|
82
|
+
extensions: []
|
83
|
+
|
84
|
+
extra_rdoc_files: []
|
85
|
+
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- .rvmrc
|
89
|
+
- Gemfile
|
90
|
+
- Gemfile.lock
|
91
|
+
- README.rdoc
|
92
|
+
- Rakefile
|
93
|
+
- lib/logbook.rb
|
94
|
+
- lib/logbook/agent.rb
|
95
|
+
- lib/logbook/client.rb
|
96
|
+
- lib/logbook/railtie.rb
|
97
|
+
- lib/logbook/version.rb
|
98
|
+
- logbook.gemspec
|
99
|
+
- spec/agent_spec.rb
|
100
|
+
- spec/client_spec.rb
|
101
|
+
- spec/logbook_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
- tmp/.keep
|
104
|
+
has_rdoc: true
|
105
|
+
homepage: http://logbook.me
|
106
|
+
licenses: []
|
107
|
+
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 3
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
version: "0"
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
requirements: []
|
132
|
+
|
133
|
+
rubyforge_project: logbook
|
134
|
+
rubygems_version: 1.3.7
|
135
|
+
signing_key:
|
136
|
+
specification_version: 3
|
137
|
+
summary: Logbook is a hosted service to collect log entries from your application
|
138
|
+
test_files: []
|
139
|
+
|