logworm_client_amqp 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +81 -0
- data/Manifest +18 -0
- data/README.md +45 -0
- data/Rakefile +10 -0
- data/bin/lw-compute +66 -0
- data/bin/lw-tail +84 -0
- data/lib/logworm_client/logger.rb +93 -0
- data/lib/logworm_client/rack.rb +62 -0
- data/lib/logworm_client/rails.rb +106 -0
- data/lib/logworm_client_amqp.rb +62 -0
- data/lib/logworm_utils/compute.rb +66 -0
- data/lib/logworm_utils/tail.rb +106 -0
- data/lib/logworm_utils.rb +4 -0
- data/logworm_client_amqp.gemspec +43 -0
- data/spec/logger_spec.rb +33 -0
- data/spec/rack_spec.rb +16 -0
- data/spec/rails_spec.rb +18 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +8 -0
- metadata +161 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
v0.8.0
|
2
|
+
Dropped http for amqp for high scalability and reduce latency
|
3
|
+
|
4
|
+
v0.7.2
|
5
|
+
Renamed Rails and Rack configuration commands:
|
6
|
+
lw_disable_request_logging ==> donot_log_requests
|
7
|
+
lw_log_request_headers ==> log_headers
|
8
|
+
lw_enable_dev_logging ==> log_in_development
|
9
|
+
|
10
|
+
Renamed :headers field in web_log to :request_headers
|
11
|
+
|
12
|
+
v0.7.1
|
13
|
+
lw-tail and lw-compute now receive an optional app parameter, for the cases where you want to call command-line tools from a directory other than the app's directory... or when you have more than one Heroku remote/app from the same directory
|
14
|
+
|
15
|
+
v0.7.0
|
16
|
+
Eliminated long logs. Instead, there's now a parameter (log_request_headers in Rack, lw_log_request_headers in Rails) to add
|
17
|
+
request and response headers to the web_log.
|
18
|
+
Cleaned up fields in the web_log table
|
19
|
+
|
20
|
+
Added option to turn off automatic logging of requests (disable_request_logging in Rack, lw_disable_request_logging in Rails)
|
21
|
+
Added option to turn on logging even if in development mode (enable_dev_logging in Rack, lw_enable_dev_logging in Rails)
|
22
|
+
|
23
|
+
Honor filter_parameter_logging switch when used with Rails
|
24
|
+
|
25
|
+
Cleaned up log and flush
|
26
|
+
Cleaned up display of elapsed time for flush
|
27
|
+
Cleaned up call from Rack and Rails, and enforce timeout (1 sec by default)
|
28
|
+
Added unit tests
|
29
|
+
|
30
|
+
v0.6.2
|
31
|
+
Added list_tables command
|
32
|
+
|
33
|
+
v0.6.1
|
34
|
+
Added a bit of documentation
|
35
|
+
|
36
|
+
v0.6.0
|
37
|
+
Add support for querying API: lw_query
|
38
|
+
|
39
|
+
v0.5.6
|
40
|
+
log HEROKU_QUEUE as an integer value
|
41
|
+
|
42
|
+
v0.5.5
|
43
|
+
Added default logging of HEROKU_QUEUE
|
44
|
+
|
45
|
+
v0.5.4
|
46
|
+
Removed obsolete lw-heroku application
|
47
|
+
|
48
|
+
v0.5.3
|
49
|
+
Show nicer error message with tail and compute if the app is not properly configured.
|
50
|
+
|
51
|
+
v0.5.2
|
52
|
+
Fixes minor issues with in Rails logging
|
53
|
+
|
54
|
+
v0.5.1
|
55
|
+
Fixes minor issues with logging statements sent to console
|
56
|
+
|
57
|
+
v0.5.0
|
58
|
+
Supports new base logworm gem, which can work as a Heroku addon
|
59
|
+
Configuration parameters now stored as URL
|
60
|
+
No error if logworm cannot be properly configured -- lw_log simply ignored
|
61
|
+
No logging in development mode
|
62
|
+
|
63
|
+
v0.4.1
|
64
|
+
Show in console time spent communicating with the server.
|
65
|
+
|
66
|
+
v0.4.0 Added support for running on Rails!
|
67
|
+
To use, add config.gem ‘logworm_client’ to environment.rb
|
68
|
+
Then you can configure in ApplicationController, via logs_requests [:short | :long]+
|
69
|
+
Works from views, models, or controllers.
|
70
|
+
|
71
|
+
v0.3.2 added lw_log method --fixed small issue
|
72
|
+
|
73
|
+
v0.3.1 added lw_log method
|
74
|
+
|
75
|
+
v0.3.0 ensure gem and dependencies live in gemcutter
|
76
|
+
|
77
|
+
v0.2.0 log short requests by default in the rack
|
78
|
+
|
79
|
+
v0.1.1 minor changes
|
80
|
+
|
81
|
+
v0.1.0 initial version.
|
data/Manifest
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Manifest
|
3
|
+
README.md
|
4
|
+
Rakefile
|
5
|
+
bin/lw-compute
|
6
|
+
bin/lw-tail
|
7
|
+
lib/logworm_client/logger.rb
|
8
|
+
lib/logworm_client/rack.rb
|
9
|
+
lib/logworm_client/rails.rb
|
10
|
+
lib/logworm_client_amqp.rb
|
11
|
+
lib/logworm_utils.rb
|
12
|
+
lib/logworm_utils/compute.rb
|
13
|
+
lib/logworm_utils/tail.rb
|
14
|
+
spec/logger_spec.rb
|
15
|
+
spec/rack_spec.rb
|
16
|
+
spec/rails_spec.rb
|
17
|
+
spec/spec.opts
|
18
|
+
spec/spec_helper.rb
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
logworm client gem
|
2
|
+
------------------
|
3
|
+
|
4
|
+
Rails Usage
|
5
|
+
-----------
|
6
|
+
|
7
|
+
Edit environment.rb and add
|
8
|
+
|
9
|
+
<pre><code>config.gem 'logworm_client'</pre></code>
|
10
|
+
|
11
|
+
inside the <code>Rails::Initializer.run</code> block
|
12
|
+
|
13
|
+
See http://www.logworm.com/docs/setup
|
14
|
+
|
15
|
+
Rack Usage
|
16
|
+
----------
|
17
|
+
|
18
|
+
<p>Edit your config.ru file and indicate that you want to use logworm's Rack middleware. For example, for a Sinatra application you'd have:</p>
|
19
|
+
|
20
|
+
<code><pre>require "myapp"
|
21
|
+
require "logworm_client"
|
22
|
+
use Logworm::Rack
|
23
|
+
run Sinatra::Application
|
24
|
+
</pre></code>
|
25
|
+
|
26
|
+
See http://www.logworm.com/docs/setup
|
27
|
+
|
28
|
+
Configuration Options
|
29
|
+
---------------------
|
30
|
+
|
31
|
+
See http://www.logworm.com/docs/config
|
32
|
+
|
33
|
+
Command-Line tools
|
34
|
+
------------------
|
35
|
+
|
36
|
+
lw-tail
|
37
|
+
-------
|
38
|
+
|
39
|
+
See http://www.logworm.com/docs/tail
|
40
|
+
|
41
|
+
lw-compute
|
42
|
+
----------
|
43
|
+
|
44
|
+
See http://www.logworm.com/docs/compute
|
45
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'echoe'
|
2
|
+
Echoe.new('logworm_client_amqp', '0.8.0') do |p|
|
3
|
+
p.description = "logworm client utilities"
|
4
|
+
p.url = "http://www.logworm.com"
|
5
|
+
p.author = "Pomelo, LLC"
|
6
|
+
p.email = "schapira@pomelollc.com"
|
7
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
8
|
+
p.development_dependencies = ["logworm_amqp >=0.8.0", "json"]
|
9
|
+
p.runtime_dependencies = ["logworm_amqp >=0.8.0", "json"]
|
10
|
+
end
|
data/bin/lw-compute
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'logworm_utils'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {
|
8
|
+
:aggregate_group => [],
|
9
|
+
:conditions => [],
|
10
|
+
:start => nil,
|
11
|
+
:end => nil,
|
12
|
+
:debug => false
|
13
|
+
}
|
14
|
+
|
15
|
+
option_parser = OptionParser.new do |opts|
|
16
|
+
opts.banner = "Usage: #{$0} [options] <log table> <function> <field>"
|
17
|
+
|
18
|
+
opts.on("--app app", String, "Specify the Heroku app") do |app|
|
19
|
+
options[:app] = app.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-g group", String, "Specify an aggregation group (e.g, hour(_ts_utc), or response.code)") do |k|
|
23
|
+
options[:aggregate_group] = k
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-c condition", String, "Specify a condition to match. May be used multiple times") do |c|
|
27
|
+
options[:conditions] << c.strip
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-s starttime", String, "Specify the start time for the query") do |c|
|
31
|
+
options[:start] = c.strip
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on("-e endtime", String, "Specify the end time for the query") do |c|
|
35
|
+
options[:end] = c.strip
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on("-v", "Show debug information") do
|
39
|
+
options[:debug] = true
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
43
|
+
puts option_parser.help
|
44
|
+
exit(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
# Parse, and get the required <table>
|
50
|
+
option_parser.parse!
|
51
|
+
if ARGV.size == 3
|
52
|
+
table = ARGV[0].strip
|
53
|
+
function = ARGV[1].strip
|
54
|
+
field = ARGV[2].strip
|
55
|
+
elsif ARGV.size == 2
|
56
|
+
table = ARGV[0].strip
|
57
|
+
function = ARGV[1].strip
|
58
|
+
else
|
59
|
+
puts option_parser.help
|
60
|
+
exit(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
# and run
|
64
|
+
LogwormCompute.new(table, function, field, options).run
|
65
|
+
|
66
|
+
|
data/bin/lw-tail
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'logworm_utils'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
def help(option_parser, options)
|
8
|
+
puts option_parser.help
|
9
|
+
puts
|
10
|
+
LogwormTail.list(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
options = {
|
14
|
+
:limit => 200,
|
15
|
+
:loop => false,
|
16
|
+
:frequency => 10,
|
17
|
+
:fields => [],
|
18
|
+
:conditions => [],
|
19
|
+
:start => nil,
|
20
|
+
:end => nil,
|
21
|
+
:debug => false,
|
22
|
+
:fkat => false
|
23
|
+
}
|
24
|
+
|
25
|
+
option_parser = OptionParser.new do |opts|
|
26
|
+
opts.banner = "Usage: #{$0} [options] <log table>"
|
27
|
+
|
28
|
+
opts.on("--app app", String, "Specify the Heroku app") do |app|
|
29
|
+
options[:app] = app.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-f [secs]", Integer,
|
33
|
+
"Continuously check for more data, every [secs] seconds.", "Default: #{options[:frequency]}") do |s|
|
34
|
+
options[:loop] = true
|
35
|
+
options[:frequency] = s if s
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on("-r limit", Integer, "Specify how many log entries to fetch.", "Default: #{options[:limit]}") do |n|
|
39
|
+
options[:limit] = n
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("-k fields", String, "Specify a comma-separated list of fields to retrieve.") do |k|
|
43
|
+
options[:fields] = k.split(",").map {|f| f.strip}
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("-c condition", String, "Specify a condition to match. May be used multiple times") do |c|
|
47
|
+
options[:conditions] << c.strip
|
48
|
+
end
|
49
|
+
|
50
|
+
opts.on("-s starttime", String, "Specify the start time for the query") do |c|
|
51
|
+
options[:start] = c.strip
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on("-e endtime", String, "Specify the end time for the query") do |c|
|
55
|
+
options[:end] = c.strip
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on("--flat", "Do not expand log entries when printing them") do
|
59
|
+
options[:flat] = true
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-v", "Show debug information") do
|
63
|
+
options[:debug] = true
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
67
|
+
options[:help] = true
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# Parse, and get the required <table>
|
73
|
+
option_parser.parse!
|
74
|
+
table = ARGV.pop
|
75
|
+
if !table or options[:help]
|
76
|
+
help option_parser, options
|
77
|
+
exit(1)
|
78
|
+
end
|
79
|
+
table.strip!
|
80
|
+
|
81
|
+
# and run
|
82
|
+
t = LogwormTail.new(table, options).run
|
83
|
+
|
84
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Logworm
|
4
|
+
class LogwormException < Exception ; end
|
5
|
+
|
6
|
+
class Logger
|
7
|
+
$lr_queue = []
|
8
|
+
|
9
|
+
###
|
10
|
+
# Use connection to the backend servers specified in environment variable or config file
|
11
|
+
###
|
12
|
+
def self.use_default_db
|
13
|
+
$lw_server = DB.from_config
|
14
|
+
end
|
15
|
+
|
16
|
+
###
|
17
|
+
# Use a connection to a manually specified server
|
18
|
+
###
|
19
|
+
def self.use_db(db)
|
20
|
+
$lw_server = db
|
21
|
+
end
|
22
|
+
|
23
|
+
###
|
24
|
+
# Returns a reference to the current backend server
|
25
|
+
###
|
26
|
+
def self.db
|
27
|
+
$lw_server
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
###
|
32
|
+
# Starts a new cycle: sets a request_id variable, so that all entries (until flush) share that id
|
33
|
+
###
|
34
|
+
def self.start_cycle
|
35
|
+
$request_id = "#{Thread.current.object_id}-#{(Time.now.utc.to_f * 1000).to_i}"
|
36
|
+
end
|
37
|
+
|
38
|
+
###
|
39
|
+
# Record an entry. Not sent to the servers until 'flush' is called
|
40
|
+
#
|
41
|
+
# Warning: may raise Exception if there's a problem. It's up to the called to rescue from it in order to continue the processing
|
42
|
+
# of a web request, for example.
|
43
|
+
###
|
44
|
+
def self.log(table, values = {})
|
45
|
+
return unless table and (table.is_a? String or table.is_a? Symbol)
|
46
|
+
return unless values.is_a? Hash
|
47
|
+
|
48
|
+
# Turn keys into symbols, delete empty ones, rename conflicting ones
|
49
|
+
kvalues = values.delete_if {|k,v| k.to_s == ""}.map {|k,v| [k.to_sym, v]}
|
50
|
+
kvalues = Hash[*kvalues.flatten]
|
51
|
+
[:_ts, :_ts_utc, :_request_id].each do |k|
|
52
|
+
kvalues["orig_#{k}".to_sym] = kvalues[k] if kvalues.has_key? k
|
53
|
+
end
|
54
|
+
|
55
|
+
# Add information
|
56
|
+
ts = Time.now.utc
|
57
|
+
kvalues[:_ts_utc] = (ts.to_f * 1000).to_i
|
58
|
+
kvalues[:_ts] = ts.strftime("%Y-%m-%dT%H:%M:%SZ")
|
59
|
+
kvalues[:_request_id] = $request_id if $request_id
|
60
|
+
|
61
|
+
# Enqueue
|
62
|
+
$lr_queue << [table, kvalues]
|
63
|
+
end
|
64
|
+
|
65
|
+
###
|
66
|
+
# Sends the entries to the server, if configured
|
67
|
+
# Returns the number of entries send, and the time it takes
|
68
|
+
#
|
69
|
+
# Warning: may raise Exception if there's a problem. It's up to the called to rescue from it in order to continue the processing
|
70
|
+
# of a web request, for example.
|
71
|
+
###
|
72
|
+
def self.flush
|
73
|
+
to_send = $lr_queue.size
|
74
|
+
|
75
|
+
# Return if no entries
|
76
|
+
return [0,0] if to_send == 0
|
77
|
+
|
78
|
+
# Return if no server
|
79
|
+
unless $lw_server
|
80
|
+
$stderr.puts "\t logworm not configured. #{to_send} entries dropped."
|
81
|
+
$lr_queue = []
|
82
|
+
return [0,0]
|
83
|
+
end
|
84
|
+
|
85
|
+
startTime = Time.now
|
86
|
+
$lw_server.batch_log($lr_queue.to_json)
|
87
|
+
$lr_queue = []
|
88
|
+
endTime = Time.now
|
89
|
+
|
90
|
+
[to_send, (endTime - startTime)]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
|
3
|
+
module Logworm
|
4
|
+
class Rack
|
5
|
+
|
6
|
+
def initialize(app, options = {})
|
7
|
+
@app = app
|
8
|
+
|
9
|
+
@log_requests = (options[:donot_log_requests].nil? or options[:donot_log_requests] != true)
|
10
|
+
@log_headers = (options[:log_headers] and options[:log_headers] == true)
|
11
|
+
@dev_logging = (options[:log_in_development] and options[:log_in_development] == true)
|
12
|
+
Logger.use_default_db
|
13
|
+
@timeout = 1
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
return @app.call(env) unless (ENV['RACK_ENV'] == 'production' or (ENV['RACK_ENV'] == 'development' and @dev_logging))
|
18
|
+
|
19
|
+
Logger.start_cycle
|
20
|
+
begin
|
21
|
+
startTime = Time.now
|
22
|
+
status, response_headers, body = @app.call(env)
|
23
|
+
appTime = (Time.now - startTime)
|
24
|
+
ensure
|
25
|
+
log_request(env, status, response_headers, appTime)
|
26
|
+
return [status, response_headers, body]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def log_request(env, status, response_headers, appTime)
|
32
|
+
method = env['REQUEST_METHOD']
|
33
|
+
path = (env['REQUEST_PATH'].nil? or env['REQUEST_PATH'] == "") ? "/" : env['REQUEST_PATH']
|
34
|
+
ip = env['REMOTE_ADDR']
|
35
|
+
http_headers = env.reject {|k,v| !(k.to_s =~ /^HTTP/) }
|
36
|
+
queue_size = env['HTTP_X_HEROKU_QUEUE_DEPTH'].nil? ? -1 : env['HTTP_X_HEROKU_QUEUE_DEPTH'].to_i
|
37
|
+
|
38
|
+
entry = { :summary => "#{method} #{path} - #{status} #{appTime}",
|
39
|
+
:request_method => method,
|
40
|
+
:request_path => path,
|
41
|
+
:request_ip => ip,
|
42
|
+
:input => ::Rack::Request.new(env).params,
|
43
|
+
:response_status => status,
|
44
|
+
:profiling => appTime,
|
45
|
+
:queue_size => queue_size}
|
46
|
+
entry[:request_headers] = http_headers if @log_headers
|
47
|
+
entry[:response_headers] = response_headers if @log_headers
|
48
|
+
Logger.log(:web_log, entry) if @log_requests
|
49
|
+
|
50
|
+
begin
|
51
|
+
Timeout::timeout(@timeout) {
|
52
|
+
sent, elapsed = Logger.flush
|
53
|
+
env['rack.errors'].puts("-- #{sent} logworm entries recorded in #{sprintf('%.4f', elapsed)} seconds") if sent > 0
|
54
|
+
}
|
55
|
+
rescue Exception => e
|
56
|
+
# Ignore --nothing we can do. The list of logs may (and most likely will) be preserved for the next request
|
57
|
+
env['rack.errors'].puts("logworm call failed: #{e}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
###
|
2
|
+
# Extemds ActionController::Base and aliases the process method, to wrap it with the standard logworm request cycle
|
3
|
+
#
|
4
|
+
# By default it will automatically log web requests (in a short format) into web_log
|
5
|
+
# Can also log headers, if specified
|
6
|
+
###
|
7
|
+
if defined?(ActionController)
|
8
|
+
|
9
|
+
require 'benchmark'
|
10
|
+
|
11
|
+
ActionController::Base.class_eval do
|
12
|
+
## Basic settings: log requests, without headers. Use default db, and timeout after 1 second
|
13
|
+
@@log_requests = true
|
14
|
+
@@log_headers = false
|
15
|
+
@@dev_logging = false
|
16
|
+
@@timeout = 1
|
17
|
+
Logworm::Logger.use_default_db
|
18
|
+
|
19
|
+
###
|
20
|
+
# Disable automatic logging of requests
|
21
|
+
# Use from ApplicationController
|
22
|
+
###
|
23
|
+
def self.donot_log_requests
|
24
|
+
@@log_requests = false
|
25
|
+
end
|
26
|
+
|
27
|
+
###
|
28
|
+
# Log headers with requests
|
29
|
+
# Use from ApplicationController
|
30
|
+
###
|
31
|
+
def self.log_headers
|
32
|
+
@@log_headers = true
|
33
|
+
end
|
34
|
+
|
35
|
+
###
|
36
|
+
# Turn on logging in development mode
|
37
|
+
###
|
38
|
+
def self.log_in_development
|
39
|
+
@@dev_logging = true
|
40
|
+
end
|
41
|
+
|
42
|
+
###
|
43
|
+
# Replaces (and embeds) the default Rails processing of a request.
|
44
|
+
# Call the original method, logs the request unless disabled, and flushes the logworm list
|
45
|
+
###
|
46
|
+
def process_with_logworm_log(request, response, method = :perform_action, *arguments)
|
47
|
+
unless (RAILS_ENV == 'production' or (RAILS_ENV == 'development' and @@dev_logging))
|
48
|
+
return process_without_logworm_log(request, response, method, *arguments)
|
49
|
+
end
|
50
|
+
|
51
|
+
Logworm::Logger.start_cycle
|
52
|
+
begin
|
53
|
+
startTime = Time.now
|
54
|
+
response = process_without_logworm_log(request, response, method, *arguments)
|
55
|
+
appTime = (Time.now - startTime)
|
56
|
+
ensure
|
57
|
+
log_request(request, response, appTime)
|
58
|
+
return response
|
59
|
+
end
|
60
|
+
end
|
61
|
+
alias_method_chain :process, :logworm_log
|
62
|
+
|
63
|
+
|
64
|
+
private
|
65
|
+
def log_request(request, response, appTime)
|
66
|
+
method = request.env['REQUEST_METHOD']
|
67
|
+
path = request.env['REQUEST_PATH'].blank? ? "/" : request.env['REQUEST_PATH']
|
68
|
+
ip = request.env['REMOTE_ADDR']
|
69
|
+
http_headers = request.headers.reject {|k,v| !(k.to_s =~ /^HTTP/) }
|
70
|
+
status = response.status[0..2]
|
71
|
+
queue_size = request.env['HTTP_X_HEROKU_QUEUE_DEPTH'].blank? ? -1 : request.env['HTTP_X_HEROKU_QUEUE_DEPTH'].to_i
|
72
|
+
|
73
|
+
entry = { :summary => "#{method} #{path} - #{status} #{appTime}",
|
74
|
+
:request_method => method,
|
75
|
+
:request_path => path,
|
76
|
+
:request_ip => ip,
|
77
|
+
:input => cleaned_input(request),
|
78
|
+
:response_status => status,
|
79
|
+
:profiling => appTime,
|
80
|
+
:queue_size => queue_size}
|
81
|
+
entry[:request_headers] = http_headers if @@log_headers
|
82
|
+
entry[:response_headers] = response.headers if @@log_headers
|
83
|
+
Logworm::Logger.log(:web_log, entry) if @@log_requests
|
84
|
+
|
85
|
+
begin
|
86
|
+
Timeout::timeout(@@timeout) {
|
87
|
+
sent, elapsed = Logworm::Logger.flush
|
88
|
+
Rails.logger.info("#{sent} logworm entries recorded in #{sprintf('%.4f', elapsed)} seconds") if sent > 0
|
89
|
+
}
|
90
|
+
rescue Exception => e
|
91
|
+
# Ignore --nothing we can do. The list of logs may (and most likely will) be preserved for the next request
|
92
|
+
Rails.logger.error("logworm call failed: #{e}")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def cleaned_input(request)
|
97
|
+
pars = request.parameters.clone
|
98
|
+
pars.delete("controller")
|
99
|
+
pars.delete("action")
|
100
|
+
respond_to?(:filter_parameters) ? filter_parameters(pars) : pars
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'logworm'
|
2
|
+
|
3
|
+
require 'logworm_client/logger'
|
4
|
+
require 'logworm_client/rack'
|
5
|
+
require 'logworm_client/rails'
|
6
|
+
|
7
|
+
def lw_log (logname, values)
|
8
|
+
Logworm::Logger.log(logname, values)
|
9
|
+
end
|
10
|
+
|
11
|
+
###
|
12
|
+
# Perform a query against the logworm server
|
13
|
+
#
|
14
|
+
# Requires a log table, and a query
|
15
|
+
# The query can be provided as a JSON string, following the syntax described in http://www.logworm.com/docs/query
|
16
|
+
# or as a Hash of options, with the following keys (all optional)
|
17
|
+
# :fields => String with a comma-separated list of fields (quoted or not), or Array of Strings
|
18
|
+
# :aggregate_function => String
|
19
|
+
# :aggregate_argument => String
|
20
|
+
# :aggregate_group => String with a comma-separated list of fields (quoted or not), or Array of Strings
|
21
|
+
# :conditions => String with comma-separated conditions (in MongoDB syntax), or Array of Strings
|
22
|
+
# :start => String or Integer (for year)
|
23
|
+
# :end => String or Integer (for year)
|
24
|
+
# :limit => String or Integer
|
25
|
+
#
|
26
|
+
# See Logworm::QueryBuilder
|
27
|
+
#
|
28
|
+
# Returns Hash with
|
29
|
+
# id ==> id of the query
|
30
|
+
# query_url ==> URL to GET information about the query
|
31
|
+
# results_url ==> URL to GET the results for the query
|
32
|
+
# created ==> First creation of the query
|
33
|
+
# updated ==> most recent update of the query and/or its results
|
34
|
+
# expires ==> until that datime, the query won't be rerun against the database
|
35
|
+
# execution_time ==> time in ms to run the query
|
36
|
+
# results ==> array of hashmaps. Each element corresponds to a log entry, with its fields
|
37
|
+
#
|
38
|
+
# raises Logworm::DatabaseException, Logworm::ForbiddenAccessException, Logworm::InvalidQueryException
|
39
|
+
# or just a regular Exception if it cannot find the URL to the logging database
|
40
|
+
###
|
41
|
+
def lw_query(logname, query = {})
|
42
|
+
db = Logworm::DB.from_config_or_die # Establish connection to DB
|
43
|
+
query = Logworm::QueryBuilder.new(query).to_json if query.is_a? Hash # Turn query into proper JSON string
|
44
|
+
query_data = db.query(logname, query) # POST to create query
|
45
|
+
db.results(query_data["results_uri"]) # GET from query's results uri
|
46
|
+
end
|
47
|
+
|
48
|
+
###
|
49
|
+
# Returns an array with information about the logging tables in the database
|
50
|
+
# Each element in the array has;
|
51
|
+
# :tablename => The name of the logging table
|
52
|
+
# :url => The URL for POSTing new log entries
|
53
|
+
# :last_write => Datetime of last entry
|
54
|
+
# :rows => Count of entries
|
55
|
+
#
|
56
|
+
# raises Logworm::DatabaseException, Logworm::ForbiddenAccessException, Logworm::InvalidQueryException
|
57
|
+
# or just a regular Exception if it cannot find the URL to the logging database
|
58
|
+
###
|
59
|
+
def lw_list_logs
|
60
|
+
db = Logworm::DB.from_config_or_die # Establish connection to DB
|
61
|
+
db.tables # Call tables command
|
62
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class LogwormCompute
|
2
|
+
def initialize(table, function, field, options)
|
3
|
+
@table = table
|
4
|
+
@function = function
|
5
|
+
@field = field
|
6
|
+
@options = options
|
7
|
+
|
8
|
+
@valuefield = @field ? "#{@function}(#{@field})" : @function
|
9
|
+
|
10
|
+
begin
|
11
|
+
@db = Logworm::DB.from_config_or_die(@options[:app])
|
12
|
+
spec = {:aggregate_function => @function, :aggregate_argument => @field}.merge(@options)
|
13
|
+
@query = Logworm::QueryBuilder.new(spec)
|
14
|
+
rescue Exception => e
|
15
|
+
$stderr.puts "There was an error: #{e}"
|
16
|
+
exit(-1)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
# Create a resource for the query
|
23
|
+
begin
|
24
|
+
query_data = @db.query(@table, @query.to_json)
|
25
|
+
url = query_data["results_uri"]
|
26
|
+
rows = @db.results(url + "?nocache=1")["results"]
|
27
|
+
rescue Logworm::DatabaseException, Logworm::ForbiddenAccessException => e
|
28
|
+
$stderr.puts "Error: #{e}"
|
29
|
+
exit(-1)
|
30
|
+
rescue Logworm::InvalidQueryException => e
|
31
|
+
$stderr.puts "#{e}, #{@query.to_json}"
|
32
|
+
exit(-1)
|
33
|
+
rescue Exception => e
|
34
|
+
$stderr.puts "Error: #{e}"
|
35
|
+
exit(-1)
|
36
|
+
end
|
37
|
+
|
38
|
+
if @options[:debug]
|
39
|
+
puts "logworm query: #{@query.to_json}"
|
40
|
+
puts "logworm query url: #{query_data["self_uri"]}"
|
41
|
+
puts "logworm results url: #{url}"
|
42
|
+
puts
|
43
|
+
end
|
44
|
+
|
45
|
+
if @query.groups.length > 0
|
46
|
+
results = {}
|
47
|
+
rows.each do |r|
|
48
|
+
grp = []
|
49
|
+
@query.groups.each do |g|
|
50
|
+
grp << "#{g}:#{r[g]}"
|
51
|
+
end
|
52
|
+
key = "[#{grp.join(', ')}]"
|
53
|
+
value = r[@function]
|
54
|
+
results[key] = {:value => value, :keys => r.dup}
|
55
|
+
results[key][:keys].delete(@function)
|
56
|
+
end
|
57
|
+
results.keys.sort.each do |k|
|
58
|
+
puts "#{k} \t ==> #{@valuefield} = #{results[k][:value]}"
|
59
|
+
end
|
60
|
+
else
|
61
|
+
puts "#{@valuefield} = #{rows.first[@function]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
class LogwormTail
|
2
|
+
def initialize(table, options)
|
3
|
+
@table = table
|
4
|
+
@options = options
|
5
|
+
|
6
|
+
begin
|
7
|
+
@db = Logworm::DB.from_config_or_die(@options[:app])
|
8
|
+
@query = Logworm::QueryBuilder.new(@options.merge(:force_ts => true))
|
9
|
+
rescue Exception => e
|
10
|
+
$stderr.puts "Error: #{e}"
|
11
|
+
exit(-1)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.list(options = {})
|
16
|
+
begin
|
17
|
+
@db = Logworm::DB.from_config_or_die(options[:app])
|
18
|
+
@tables = @db.tables
|
19
|
+
if @tables and @tables.size > 0
|
20
|
+
puts "The following are the tables that you've created thus far:"
|
21
|
+
@tables.sort {|x,y| x["tablename"] <=> y["tablename"]}.each do |t|
|
22
|
+
puts "\t - #{t["tablename"]}, #{t["rows"]} rows, last updated on #{date_time(t["last_write"])}"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
puts "You haven't recorded any data yet."
|
26
|
+
end
|
27
|
+
rescue Exception => e
|
28
|
+
$stderr.puts "Error: #{e}"
|
29
|
+
exit(-1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def run
|
34
|
+
# Create a resource for the query
|
35
|
+
begin
|
36
|
+
query_data = @db.query(@table, @query.to_json)
|
37
|
+
url = query_data["results_uri"]
|
38
|
+
rescue Logworm::DatabaseException, Logworm::ForbiddenAccessException => e
|
39
|
+
$stderr.puts "Error: #{e}"
|
40
|
+
exit(-1)
|
41
|
+
rescue Logworm::InvalidQueryException => e
|
42
|
+
$stderr.puts "#{e}"
|
43
|
+
exit(-1)
|
44
|
+
rescue Exception => e
|
45
|
+
$stderr.puts "Error: #{e}"
|
46
|
+
exit(-1)
|
47
|
+
end
|
48
|
+
|
49
|
+
if @options[:debug]
|
50
|
+
puts "logworm query: #{@query.to_json}"
|
51
|
+
puts "logworm query url: #{query_data["self_uri"]}"
|
52
|
+
puts "logworm results url: #{url}"
|
53
|
+
puts "refresh frequency: #{@options[:frequency]}" if @options[:loop]
|
54
|
+
puts
|
55
|
+
end
|
56
|
+
|
57
|
+
while true do
|
58
|
+
begin
|
59
|
+
last_printed = print_rows(@db.results(url + "?nocache=1")["results"], last_printed || nil)
|
60
|
+
rescue Logworm::DatabaseException, Logworm::ForbiddenAccessException => e
|
61
|
+
$stderr.puts "Error: #{e}"
|
62
|
+
exit(-1)
|
63
|
+
rescue Logworm::InvalidQueryException => e
|
64
|
+
$stderr.puts "#{e}"
|
65
|
+
exit(-1)
|
66
|
+
rescue Exception => e
|
67
|
+
$stderr.puts "Error: #{e}"
|
68
|
+
exit(-1)
|
69
|
+
end
|
70
|
+
exit(0) unless @options[:loop]
|
71
|
+
sleep @options[:frequency]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def self.date_time(val)
|
78
|
+
val.gsub(/T/, ' @ ').gsub(/Z/, ' GMT')
|
79
|
+
end
|
80
|
+
|
81
|
+
def print_rows(rows, last)
|
82
|
+
last = "" if last.nil?
|
83
|
+
rows.reverse.each do |r|
|
84
|
+
next unless r["_ts"]
|
85
|
+
if r["_ts"] > last
|
86
|
+
last = r["_ts"]
|
87
|
+
r.delete("_id") unless @options[:fields].include?("_id")
|
88
|
+
r.delete("_ts") unless @options[:fields].include?("_ts")
|
89
|
+
puts "#{LogwormTail.date_time(last)} ==> "
|
90
|
+
print_row(r)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
last
|
94
|
+
end
|
95
|
+
|
96
|
+
def print_row(r)
|
97
|
+
if @options[:flat]
|
98
|
+
puts "\t" + r.keys.sort.map {|k| "#{k}: #{r[k].inspect}"}.join(', ')
|
99
|
+
else
|
100
|
+
r.keys.sort.each do |k|
|
101
|
+
puts "\t#{k}: #{r[k].inspect}"
|
102
|
+
end
|
103
|
+
puts
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{logworm_client_amqp}
|
5
|
+
s.version = "0.8.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Pomelo, LLC"]
|
9
|
+
s.date = %q{2010-07-31}
|
10
|
+
s.description = %q{logworm client utilities}
|
11
|
+
s.email = %q{schapira@pomelollc.com}
|
12
|
+
s.executables = ["lw-compute", "lw-tail"]
|
13
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.md", "bin/lw-compute", "bin/lw-tail", "lib/logworm_client/logger.rb", "lib/logworm_client/rack.rb", "lib/logworm_client/rails.rb", "lib/logworm_client_amqp.rb", "lib/logworm_utils.rb", "lib/logworm_utils/compute.rb", "lib/logworm_utils/tail.rb"]
|
14
|
+
s.files = ["CHANGELOG", "Manifest", "README.md", "Rakefile", "bin/lw-compute", "bin/lw-tail", "lib/logworm_client/logger.rb", "lib/logworm_client/rack.rb", "lib/logworm_client/rails.rb", "lib/logworm_client_amqp.rb", "lib/logworm_utils.rb", "lib/logworm_utils/compute.rb", "lib/logworm_utils/tail.rb", "spec/logger_spec.rb", "spec/rack_spec.rb", "spec/rails_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "logworm_client_amqp.gemspec"]
|
15
|
+
s.homepage = %q{http://www.logworm.com}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Logworm_client_amqp", "--main", "README.md"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{logworm_client_amqp}
|
19
|
+
s.rubygems_version = %q{1.3.7}
|
20
|
+
s.summary = %q{logworm client utilities}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_runtime_dependency(%q<logworm_amqp>, [">= 0.8.0"])
|
28
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
29
|
+
s.add_development_dependency(%q<logworm_amqp>, [">= 0.8.0"])
|
30
|
+
s.add_development_dependency(%q<json>, [">= 0"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<logworm_amqp>, [">= 0.8.0"])
|
33
|
+
s.add_dependency(%q<json>, [">= 0"])
|
34
|
+
s.add_dependency(%q<logworm_amqp>, [">= 0.8.0"])
|
35
|
+
s.add_dependency(%q<json>, [">= 0"])
|
36
|
+
end
|
37
|
+
else
|
38
|
+
s.add_dependency(%q<logworm_amqp>, [">= 0.8.0"])
|
39
|
+
s.add_dependency(%q<json>, [">= 0"])
|
40
|
+
s.add_dependency(%q<logworm_amqp>, [">= 0.8.0"])
|
41
|
+
s.add_dependency(%q<json>, [">= 0"])
|
42
|
+
end
|
43
|
+
end
|
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'webmock'
|
3
|
+
require 'logworm'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
6
|
+
|
7
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
8
|
+
require 'logworm_client/logger.rb'
|
9
|
+
|
10
|
+
describe Logworm::Logger, " flushing" do
|
11
|
+
before do
|
12
|
+
Logworm::Logger.use_db Logworm::DB.new("logworm://a:b@localhost/c/d/")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should only record if it's been initialized" do
|
16
|
+
Logworm::Logger.use_db nil
|
17
|
+
Logworm::Logger.log(:tbl1, :a => 1)
|
18
|
+
Logworm::Logger.flush.should == [0,0]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should only record if there are entries" do
|
22
|
+
Logworm::Logger.flush.should == [0,0]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should try to record it it's initialized and has entries, and then reset" do
|
26
|
+
stub_request(:post, "localhost/log").to_return(:body => {:count => 10, :inserted_at => Time.now}.to_json)
|
27
|
+
Logworm::Logger.log(:tbl1, :a => 1)
|
28
|
+
Logworm::Logger.flush[0].should == 1
|
29
|
+
Logworm::Logger.flush.should == [0,0]
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
data/spec/rack_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'webmock'
|
3
|
+
require 'logworm'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
6
|
+
|
7
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
8
|
+
require 'logworm_client.rb'
|
9
|
+
|
10
|
+
describe Logworm::Rack, " init" do
|
11
|
+
it "should initialize the logger with a default db" do
|
12
|
+
Logworm::Logger.should_receive(:use_default_db)
|
13
|
+
Logworm::Rack.new("xx")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
data/spec/rails_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'webmock'
|
3
|
+
require 'logworm'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
6
|
+
|
7
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
8
|
+
|
9
|
+
describe Logworm, " init" do
|
10
|
+
it "should initialize the logger with a default db" do
|
11
|
+
require 'logworm_client/logger.rb' # ==> Get Logworm::Logger defined
|
12
|
+
Logworm::Logger.should_receive(:use_default_db)
|
13
|
+
|
14
|
+
require 'action_controller' # ==> Get ActionController defined
|
15
|
+
load 'logworm_client/rails.rb' # ==> does class_eval of ActionController (use load to guarantee require)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logworm_client_amqp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 63
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 0.8.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Pomelo, LLC
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-31 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: logworm_amqp
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 63
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 8
|
33
|
+
- 0
|
34
|
+
version: 0.8.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: json
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: logworm_amqp
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 63
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
- 8
|
63
|
+
- 0
|
64
|
+
version: 0.8.0
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: json
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
81
|
+
description: logworm client utilities
|
82
|
+
email: schapira@pomelollc.com
|
83
|
+
executables:
|
84
|
+
- lw-compute
|
85
|
+
- lw-tail
|
86
|
+
extensions: []
|
87
|
+
|
88
|
+
extra_rdoc_files:
|
89
|
+
- CHANGELOG
|
90
|
+
- README.md
|
91
|
+
- bin/lw-compute
|
92
|
+
- bin/lw-tail
|
93
|
+
- lib/logworm_client/logger.rb
|
94
|
+
- lib/logworm_client/rack.rb
|
95
|
+
- lib/logworm_client/rails.rb
|
96
|
+
- lib/logworm_client_amqp.rb
|
97
|
+
- lib/logworm_utils.rb
|
98
|
+
- lib/logworm_utils/compute.rb
|
99
|
+
- lib/logworm_utils/tail.rb
|
100
|
+
files:
|
101
|
+
- CHANGELOG
|
102
|
+
- Manifest
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- bin/lw-compute
|
106
|
+
- bin/lw-tail
|
107
|
+
- lib/logworm_client/logger.rb
|
108
|
+
- lib/logworm_client/rack.rb
|
109
|
+
- lib/logworm_client/rails.rb
|
110
|
+
- lib/logworm_client_amqp.rb
|
111
|
+
- lib/logworm_utils.rb
|
112
|
+
- lib/logworm_utils/compute.rb
|
113
|
+
- lib/logworm_utils/tail.rb
|
114
|
+
- spec/logger_spec.rb
|
115
|
+
- spec/rack_spec.rb
|
116
|
+
- spec/rails_spec.rb
|
117
|
+
- spec/spec.opts
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
- logworm_client_amqp.gemspec
|
120
|
+
has_rdoc: true
|
121
|
+
homepage: http://www.logworm.com
|
122
|
+
licenses: []
|
123
|
+
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options:
|
126
|
+
- --line-numbers
|
127
|
+
- --inline-source
|
128
|
+
- --title
|
129
|
+
- Logworm_client_amqp
|
130
|
+
- --main
|
131
|
+
- README.md
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 3
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
version: "0"
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
hash: 11
|
149
|
+
segments:
|
150
|
+
- 1
|
151
|
+
- 2
|
152
|
+
version: "1.2"
|
153
|
+
requirements: []
|
154
|
+
|
155
|
+
rubyforge_project: logworm_client_amqp
|
156
|
+
rubygems_version: 1.3.7
|
157
|
+
signing_key:
|
158
|
+
specification_version: 3
|
159
|
+
summary: logworm client utilities
|
160
|
+
test_files: []
|
161
|
+
|