logworm_client_amqp 0.8.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/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
|
+
|