logworm_client 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,7 @@
1
+ v0.3.0 ensure gem and dependencies live in gemcutter
2
+
3
+ v0.2.0 log short requests by default in the rack
4
+
5
+ v0.1.1 minor changes
6
+
7
+ v0.1.0 initial version.
data/Manifest ADDED
@@ -0,0 +1,14 @@
1
+ CHANGELOG
2
+ Manifest
3
+ README
4
+ Rakefile
5
+ bin/lw-compute
6
+ bin/lw-heroku
7
+ bin/lw-tail
8
+ lib/logworm_client.rb
9
+ lib/logworm_client/logger.rb
10
+ lib/logworm_client/rack.rb
11
+ lib/logworm_utils.rb
12
+ lib/logworm_utils/compute.rb
13
+ lib/logworm_utils/heroku.rb
14
+ lib/logworm_utils/tail.rb
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'echoe'
2
+ Echoe.new('logworm_client', '0.3.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", "json"]
9
+ p.runtime_dependencies = ["logworm", "json"]
10
+ end
data/bin/lw-compute ADDED
@@ -0,0 +1,62 @@
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("-g group", String, "Specify an aggregation group (e.g, hour(_ts_utc), or response.code)") do |k|
19
+ options[:aggregate_group] = k
20
+ end
21
+
22
+ opts.on("-c condition", String, "Specify a condition to match. May be used multiple times") do |c|
23
+ options[:conditions] << c.strip
24
+ end
25
+
26
+ opts.on("-s starttime", String, "Specify the start time for the query") do |c|
27
+ options[:start] = c.strip
28
+ end
29
+
30
+ opts.on("-e endtime", String, "Specify the end time for the query") do |c|
31
+ options[:end] = c.strip
32
+ end
33
+
34
+ opts.on("-v", "Show debug information") do
35
+ options[:debug] = true
36
+ end
37
+
38
+ opts.on( '-h', '--help', 'Display this screen' ) do
39
+ puts option_parser.help
40
+ exit(1)
41
+ end
42
+
43
+ end
44
+
45
+ # Parse, and get the required <table>
46
+ option_parser.parse!
47
+ if ARGV.size == 3
48
+ table = ARGV[0].strip
49
+ function = ARGV[1].strip
50
+ field = ARGV[2].strip
51
+ elsif ARGV.size == 2
52
+ table = ARGV[0].strip
53
+ function = ARGV[1].strip
54
+ else
55
+ puts option_parser.help
56
+ exit(1)
57
+ end
58
+
59
+ # and run
60
+ LogwormCompute.new(table, function, field, options).run
61
+
62
+
data/bin/lw-heroku ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'logworm_utils'
5
+
6
+ LogwormHeroku.new().run
7
+
8
+
data/bin/lw-tail ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'logworm_utils'
5
+ require 'optparse'
6
+
7
+ options = {
8
+ :limit => 200,
9
+ :loop => false,
10
+ :frequency => 10,
11
+ :fields => [],
12
+ :conditions => [],
13
+ :start => nil,
14
+ :end => nil,
15
+ :debug => false,
16
+ :fkat => false
17
+ }
18
+
19
+ option_parser = OptionParser.new do |opts|
20
+ opts.banner = "Usage: #{$0} [options] <log table>"
21
+
22
+ opts.on("-f [secs]", Integer,
23
+ "Continuously check for more data, every [secs] seconds.", "Default: #{options[:frequency]}") do |s|
24
+ options[:loop] = true
25
+ options[:frequency] = s if s
26
+ end
27
+
28
+ opts.on("-r limit", Integer, "Specify how many log entries to fetch.", "Default: #{options[:limit]}") do |n|
29
+ options[:limit] = n
30
+ end
31
+
32
+ opts.on("-k fields", String, "Specify a comma-separated list of fields to retrieve.") do |k|
33
+ options[:fields] = k.split(",").map {|f| f.strip}
34
+ end
35
+
36
+ opts.on("-c condition", String, "Specify a condition to match. May be used multiple times") do |c|
37
+ options[:conditions] << c.strip
38
+ end
39
+
40
+ opts.on("-s starttime", String, "Specify the start time for the query") do |c|
41
+ options[:start] = c.strip
42
+ end
43
+
44
+ opts.on("-e endtime", String, "Specify the end time for the query") do |c|
45
+ options[:end] = c.strip
46
+ end
47
+
48
+ opts.on("--flat", "Do not expand log entries when printing them") do
49
+ options[:flat] = true
50
+ end
51
+
52
+ opts.on("-v", "Show debug information") do
53
+ options[:debug] = true
54
+ end
55
+
56
+ opts.on( '-h', '--help', 'Display this screen' ) do
57
+ puts option_parser.help
58
+ exit(1)
59
+ end
60
+
61
+ end
62
+
63
+ # Parse, and get the required <table>
64
+ option_parser.parse!
65
+ table = ARGV.pop
66
+ if !table
67
+ puts option_parser.help
68
+ exit(1)
69
+ end
70
+ table.strip!
71
+
72
+ # and run
73
+ t = LogwormTail.new(table, options).run
74
+
75
+
@@ -0,0 +1,4 @@
1
+ require 'logworm'
2
+
3
+ require 'logworm_client/logger'
4
+ require 'logworm_client/rack'
@@ -0,0 +1,46 @@
1
+ require 'json'
2
+
3
+ module Logworm
4
+ class LogwormException < Exception ; end
5
+
6
+ class Logger
7
+ # Initialize
8
+ LW_SERVER = DB.new() # Find from config file, or from keys
9
+ $lr_queue = []
10
+
11
+ def self.start_cycle
12
+ $request_id = "#{Thread.current.object_id}-#{(Time.now.utc.to_f * 1000).to_i}"
13
+ end
14
+
15
+ def self.log(table, values = {})
16
+ begin
17
+ # Rename conflicting keys
18
+ kvalues = values.delete_if {|k,v| k.to_s == ""}.map {|k,v| [k.to_sym, v]}
19
+ kvalues = Hash[*kvalues.flatten]
20
+ [:_ts, :_ts_utc, :_request_id].each do |k|
21
+ kvalues["orig_#{k}".to_sym] = kvalues[k] if kvalues.has_key? k
22
+ end
23
+ # Add information
24
+ ts = Time.now.utc
25
+ log_details = {:_ts => ts.strftime("%Y-%m-%dT%H:%M:%SZ"), :_ts_utc => (ts.to_f * 1000).to_i}
26
+ log_details[:_request_id] = $request_id if $request_id
27
+ # Enqueue
28
+ payload = kvalues.merge(log_details)
29
+ $lr_queue << [table, payload]
30
+ rescue Exception => e
31
+ $stderr.puts "Error in Logworm::Logger.log: #{e}"
32
+ end
33
+ end
34
+
35
+ def self.flush
36
+ if $lr_queue.size > 0
37
+ begin
38
+ LW_SERVER.batch_log($lr_queue.to_json)
39
+ rescue Exception => e
40
+ $stderr.puts "in Logworm::Logger.flush: #{e}"
41
+ end
42
+ $lr_queue = []
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,52 @@
1
+ module Logworm
2
+ class Rack
3
+
4
+ def initialize(app, options = {})
5
+ @app = app
6
+ @log_requests_short = options[:log_requests].nil? or options[:log_requests] != false
7
+ @log_requests_long = !options[:log_requests_long].nil? and options[:log_requests_long] == true
8
+ end
9
+
10
+ def call(env)
11
+ startTime = Time.now
12
+ Logger.start_cycle
13
+ status, headers, body = @app.call(env)
14
+ appTime = (Time.now - startTime)
15
+ Logger.log(:web_log_long, {:summary => "#{env['REQUEST_METHOD']} #{env['REQUEST_URI']} - #{status} #{appTime}",
16
+ :request => env_to_log(env),
17
+ :response => {:status => status, :headers => headers},
18
+ :profiling => appTime}) if @log_requests_long
19
+ Logger.log(:web_log, {:summary => "#{env['REQUEST_METHOD']} #{env['REQUEST_URI']} - #{status} #{appTime}",
20
+ :request_path => env['REQUEST_PATH'], :request_ip => env['REMOTE_ADDR'],
21
+ :request_method => env['REQUEST_METHOD'], :input => collect_input(env),
22
+ :response_status => status,
23
+ :profiling => appTime}) if @log_requests_short
24
+ begin
25
+ Timeout::timeout(1) {
26
+ Logger.flush # Flushes only if there are any entries. Times out after half second
27
+ }
28
+ rescue Exception => e
29
+ # Ignore --nothing we can do
30
+ # The list of logs may (and most likely will) be preserved for the next request
31
+ env['rack.errors'].puts "logworm call failed: #{e}"
32
+ end
33
+ [status, headers, body]
34
+ end
35
+
36
+ private
37
+ def env_to_log(env)
38
+ to_log = {}
39
+ env.each do |k,v|
40
+ to_log[k.to_s.downcase.to_sym] = v unless (k.to_s =~ /rack/i or k.to_s =~ /\./i)
41
+ end
42
+ to_log.merge({:input => collect_input(env)})
43
+ end
44
+
45
+ def collect_input(env)
46
+ inputstr = ""
47
+ env['rack.input'].each {|content| inputstr += content }
48
+ env['rack.input'].rewind
49
+ inputstr
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ require 'logworm'
2
+
3
+ require 'logworm_utils/tail'
4
+ require 'logworm_utils/compute'
5
+ require 'logworm_utils/heroku'
@@ -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.new(false)
12
+ spec = {:aggregate_function => @function, :aggregate_argument => @field}.merge(@options)
13
+ @query = Logworm::QueryBuilder.new(spec)
14
+ rescue Exception => e
15
+ $stderr.puts "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,17 @@
1
+ class LogwormHeroku
2
+ def initialize()
3
+ c = Logworm::Config.instance
4
+ if !c.file_found?
5
+ $stderr.puts "Could not find .logworm file in the current directory with proper keys"
6
+ exit(-1)
7
+ end
8
+ @keys = c.keys
9
+ end
10
+
11
+ def run
12
+ cmd = "heroku config:add LW_CONSUMER_KEY=\"#{@keys[0]}\" LW_CONSUMER_SECRET=\"#{@keys[1]}\" "
13
+ cmd << "LW_PROJECT_KEY=\"#{@keys[2]}\" LW_PROJECT_SECRET=\"#{@keys[3]}\""
14
+ puts "Push configuration keys to Heroku"
15
+ puts "There was an error --configuration files not pushed" if system(cmd) == false
16
+ end
17
+ end
@@ -0,0 +1,84 @@
1
+ class LogwormTail
2
+ def initialize(table, options)
3
+ @table = table
4
+ @options = options
5
+
6
+ begin
7
+ @db = Logworm::DB.new(false)
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 run
16
+ # Create a resource for the query
17
+ begin
18
+ query_data = @db.query(@table, @query.to_json)
19
+ url = query_data["results_uri"]
20
+ rescue Logworm::DatabaseException, Logworm::ForbiddenAccessException => e
21
+ $stderr.puts "Error: #{e}"
22
+ exit(-1)
23
+ rescue Logworm::InvalidQueryException => e
24
+ $stderr.puts "#{e}"
25
+ exit(-1)
26
+ rescue Exception => e
27
+ $stderr.puts "Error: #{e}"
28
+ exit(-1)
29
+ end
30
+
31
+ if @options[:debug]
32
+ puts "logworm query: #{@query.to_json}"
33
+ puts "logworm query url: #{query_data["self_uri"]}"
34
+ puts "logworm results url: #{url}"
35
+ puts "refresh frequency: #{@options[:frequency]}" if @options[:loop]
36
+ puts
37
+ end
38
+
39
+ while true do
40
+ begin
41
+ last_printed = print_rows(@db.results(url + "?nocache=1")["results"], last_printed || nil)
42
+ rescue Logworm::DatabaseException, Logworm::ForbiddenAccessException => e
43
+ $stderr.puts "Error: #{e}"
44
+ exit(-1)
45
+ rescue Logworm::InvalidQueryException => e
46
+ $stderr.puts "#{e}"
47
+ exit(-1)
48
+ rescue Exception => e
49
+ $stderr.puts "Error: #{e}"
50
+ exit(-1)
51
+ end
52
+ exit(0) unless @options[:loop]
53
+ sleep @options[:frequency]
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def print_rows(rows, last)
60
+ last = "" if last.nil?
61
+ rows.reverse.each do |r|
62
+ next unless r["_ts"]
63
+ if r["_ts"] > last
64
+ last = r["_ts"]
65
+ r.delete("_id") unless @options[:fields].include?("_id")
66
+ r.delete("_ts") unless @options[:fields].include?("_ts")
67
+ puts "#{last.gsub(/T/, ' @ ').gsub(/Z/, ' GMT')} ==> "
68
+ print_row(r)
69
+ end
70
+ end
71
+ last
72
+ end
73
+
74
+ def print_row(r)
75
+ if @options[:flat]
76
+ r.keys.sort.map {|k| "#{k}: #{r[k].inspect}"}.join(', ')
77
+ else
78
+ r.keys.sort.each do |k|
79
+ puts "\t#{k}: #{r[k].inspect}"
80
+ end
81
+ puts
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{logworm_client}
5
+ s.version = "0.3.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-03-01}
10
+ s.description = %q{logworm client utilities}
11
+ s.email = %q{schapira@pomelollc.com}
12
+ s.executables = ["lw-compute", "lw-heroku", "lw-tail"]
13
+ s.extra_rdoc_files = ["CHANGELOG", "README", "bin/lw-compute", "bin/lw-heroku", "bin/lw-tail", "lib/logworm_client.rb", "lib/logworm_client/logger.rb", "lib/logworm_client/rack.rb", "lib/logworm_utils.rb", "lib/logworm_utils/compute.rb", "lib/logworm_utils/heroku.rb", "lib/logworm_utils/tail.rb"]
14
+ s.files = ["CHANGELOG", "Manifest", "README", "Rakefile", "bin/lw-compute", "bin/lw-heroku", "bin/lw-tail", "lib/logworm_client.rb", "lib/logworm_client/logger.rb", "lib/logworm_client/rack.rb", "lib/logworm_utils.rb", "lib/logworm_utils/compute.rb", "lib/logworm_utils/heroku.rb", "lib/logworm_utils/tail.rb", "logworm_client.gemspec"]
15
+ s.homepage = %q{http://www.logworm.com}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Logworm_client", "--main", "README"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{logworm_client}
19
+ s.rubygems_version = %q{1.3.6}
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::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<logworm>, [">= 0"])
28
+ s.add_runtime_dependency(%q<json>, [">= 0"])
29
+ s.add_development_dependency(%q<logworm>, [">= 0"])
30
+ s.add_development_dependency(%q<json>, [">= 0"])
31
+ else
32
+ s.add_dependency(%q<logworm>, [">= 0"])
33
+ s.add_dependency(%q<json>, [">= 0"])
34
+ s.add_dependency(%q<logworm>, [">= 0"])
35
+ s.add_dependency(%q<json>, [">= 0"])
36
+ end
37
+ else
38
+ s.add_dependency(%q<logworm>, [">= 0"])
39
+ s.add_dependency(%q<json>, [">= 0"])
40
+ s.add_dependency(%q<logworm>, [">= 0"])
41
+ s.add_dependency(%q<json>, [">= 0"])
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logworm_client
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
+ platform: ruby
11
+ authors:
12
+ - Pomelo, LLC
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-01 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: logworm
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: json
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :runtime
43
+ version_requirements: *id002
44
+ - !ruby/object:Gem::Dependency
45
+ name: logworm
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ type: :development
55
+ version_requirements: *id003
56
+ - !ruby/object:Gem::Dependency
57
+ name: json
58
+ prerelease: false
59
+ requirement: &id004 !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ type: :development
67
+ version_requirements: *id004
68
+ description: logworm client utilities
69
+ email: schapira@pomelollc.com
70
+ executables:
71
+ - lw-compute
72
+ - lw-heroku
73
+ - lw-tail
74
+ extensions: []
75
+
76
+ extra_rdoc_files:
77
+ - CHANGELOG
78
+ - README
79
+ - bin/lw-compute
80
+ - bin/lw-heroku
81
+ - bin/lw-tail
82
+ - lib/logworm_client.rb
83
+ - lib/logworm_client/logger.rb
84
+ - lib/logworm_client/rack.rb
85
+ - lib/logworm_utils.rb
86
+ - lib/logworm_utils/compute.rb
87
+ - lib/logworm_utils/heroku.rb
88
+ - lib/logworm_utils/tail.rb
89
+ files:
90
+ - CHANGELOG
91
+ - Manifest
92
+ - README
93
+ - Rakefile
94
+ - bin/lw-compute
95
+ - bin/lw-heroku
96
+ - bin/lw-tail
97
+ - lib/logworm_client.rb
98
+ - lib/logworm_client/logger.rb
99
+ - lib/logworm_client/rack.rb
100
+ - lib/logworm_utils.rb
101
+ - lib/logworm_utils/compute.rb
102
+ - lib/logworm_utils/heroku.rb
103
+ - lib/logworm_utils/tail.rb
104
+ - logworm_client.gemspec
105
+ has_rdoc: true
106
+ homepage: http://www.logworm.com
107
+ licenses: []
108
+
109
+ post_install_message:
110
+ rdoc_options:
111
+ - --line-numbers
112
+ - --inline-source
113
+ - --title
114
+ - Logworm_client
115
+ - --main
116
+ - README
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ segments:
131
+ - 1
132
+ - 2
133
+ version: "1.2"
134
+ requirements: []
135
+
136
+ rubyforge_project: logworm_client
137
+ rubygems_version: 1.3.6
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: logworm client utilities
141
+ test_files: []
142
+