logworm 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,17 @@
1
+ v0.6.1 fixed query builder
2
+
3
+ v0.6.0 added query builder
4
+
5
+ v0.5.1 removed memcache dependency, added memcache-client
6
+
7
+ v0.5.0 removed utils, moved them to separate gem
8
+
9
+ v0.4.1 added start and end options to lw-compute and lw-tail
10
+
11
+ v0.4.0 added lw-compute tool, to run aggregate queries
12
+
13
+ v0.3.0 added lw-heroku tool, to push configuration variables to heroku
14
+
15
+ v0.2.0 removed app/ libraries. Added tail as a utility, lw-tail as a command
16
+
17
+ v0.1.0 initial version.
data/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ CHANGELOG
2
+ Manifest
3
+ README
4
+ Rakefile
5
+ lib/base/config.rb
6
+ lib/base/db.rb
7
+ lib/base/query_builder.rb
8
+ lib/logworm.rb
9
+ tests/builder_test.rb
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'echoe'
2
+ Echoe.new('logworm', '0.6.1') do |p|
3
+ p.description = "logworm logging tool"
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 = ["memcache-client", "hpricot", "oauth"]
9
+ p.runtime_dependencies = ["memcache-client", "hpricot", "oauth"]
10
+ end
@@ -0,0 +1,34 @@
1
+ require 'singleton'
2
+
3
+ module Logworm
4
+ class ConfigFileNotFound < Exception ; end
5
+
6
+ class Config
7
+
8
+ include ::Singleton
9
+
10
+ FILENAME = "./.logworm"
11
+
12
+ def initialize
13
+ @file_found = false
14
+ @consumer_key = @consumer_secret = @token_key = @token_secret = nil
15
+ begin
16
+ f = File.new(FILENAME, 'r')
17
+ @consumer_key, @consumer_secret, @token_key, @token_secret = f.readlines.map {|l| l.strip }
18
+ @file_found = true
19
+ rescue Errno::ENOENT => e
20
+ end
21
+ end
22
+
23
+ def keys
24
+ [@consumer_key, @consumer_secret, @token_key, @token_secret]
25
+ end
26
+
27
+ def file_found?
28
+ @file_found and @consumer_key and @consumer_secret and @token_key and @token_secret
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
data/lib/base/db.rb ADDED
@@ -0,0 +1,74 @@
1
+ require 'oauth'
2
+ require 'json'
3
+
4
+ module Logworm
5
+ class ForbiddenAccessException < Exception ; end
6
+ class DatabaseException < Exception ; end
7
+ class InvalidQueryException < Exception ; end
8
+
9
+ class DB
10
+
11
+ DB_HOST = "http://db.logworm.com"
12
+
13
+ def initialize(keys = nil)
14
+ if keys.is_a? Array and keys.size == 4
15
+ @consumer_key, @consumer_secret, @token, @token_secret = keys
16
+ elsif keys.is_a? Array and keys.size == 2
17
+ @consumer_key = ENV["#{ENV['APP_ID']}_APPS_KEY"]
18
+ @consumer_secret = ENV["#{ENV['APP_ID']}_APPS_SECRET"]
19
+ @token, @token_secret = keys
20
+ else
21
+ config = Logworm::Config.instance
22
+ if config.file_found?
23
+ @consumer_key, @consumer_secret, @token, @token_secret = config.keys
24
+ else
25
+ raise "Could not find .logworm file in current directory." if keys.is_a? FalseClass
26
+ @consumer_key, @consumer_secret = [ENV['LW_CONSUMER_KEY'], ENV['LW_CONSUMER_SECRET']]
27
+ @token, @token_secret = [ENV['LW_PROJECT_KEY'], ENV['LW_PROJECT_SECRET']]
28
+ end
29
+ end
30
+ raise ForbiddenAccessException.new("Missing keys") if @consumer_key.nil? or @consumer_secret.nil?
31
+ raise ForbiddenAccessException.new("Missing keys") if @token.nil? or @token_secret.nil?
32
+ @connection = OAuth::AccessToken.new(OAuth::Consumer.new(@consumer_key, @consumer_secret), @token, @token_secret)
33
+ end
34
+
35
+ def tables()
36
+ res = db_call(:get, "#{DB_HOST}/")
37
+ end
38
+
39
+ def query(table, cond)
40
+ res = db_call(:post, "#{DB_HOST}/queries", {:table => table, :query => cond})
41
+ end
42
+
43
+ def results(uri)
44
+ res = db_call(:get, uri)
45
+ raise InvalidQueryException.new("#{res['error']}") if res['error']
46
+ res["results"] = JSON.parse(res["results"])
47
+ res
48
+ end
49
+
50
+ def batch_log(entries)
51
+ db_call(:post, "#{DB_HOST}/log", {:entries => $lr_queue.to_json})
52
+ end
53
+
54
+ private
55
+ def db_call(method, uri, params = {})
56
+ begin
57
+ res = @connection.send(method, uri, params)
58
+ rescue SocketError
59
+ raise DatabaseException
60
+ end
61
+ raise DatabaseException if res.code.to_i == 404
62
+ raise DatabaseException.new("Server returned: #{res.body}") if res.code.to_i == 500
63
+ raise ForbiddenAccessException if res.code.to_i == 403
64
+ raise InvalidQueryException.new("#{res.body}") if res.code.to_i == 400
65
+ begin
66
+ JSON.parse(res.body)
67
+ rescue Exception => e
68
+ raise DatabaseException.new("Database reponse cannot be parsed: #{e}")
69
+ end
70
+ end
71
+ end
72
+
73
+ end
74
+
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+
4
+ ###
5
+ # Receives a hash with options, and provides a to_json method that returns the query ready to be sent to the logworm server
6
+ # Switches (all optional)
7
+ # :fields => String with a comma-separated list of fields (quoted or not), or Array of Strings
8
+ # :force_ts => Boolean, specifies whether _ts should be added to the list of fields
9
+ # :aggregate_function => String
10
+ # :aggregate_argument => String
11
+ # :aggregate_group => String with a comma-separated list of fields (quoted or not), or Array of Strings
12
+ # :conditions => String with comma-separated conditions (in MongoDB syntax), or Array of Strings
13
+ # :start => String or Integer (for year)
14
+ # :end => String or Integer (for year)
15
+ # :limit => String or Integer
16
+ ###
17
+ module Logworm
18
+ class QueryBuilder
19
+
20
+ attr_accessor :fields, :groups, :aggregate, :conditions, :tf, :limit
21
+
22
+ def initialize(options = {})
23
+ @options = options
24
+ @query = build()
25
+ end
26
+
27
+ def to_json
28
+ @query
29
+ end
30
+
31
+ private
32
+ def build()
33
+ query_opts = []
34
+
35
+ ###
36
+ # Fields : Array, or Comma-separated string
37
+ ###
38
+ @fields = to_array(@options[:fields])
39
+ query_opts << '"fields":' + (@options[:force_ts] ? @fields + ["_ts"] : @fields).to_json if @fields.size > 0
40
+
41
+ ###
42
+ # Aggregate
43
+ # aggregate_function: String
44
+ # aggregate_argument: String (or empty)
45
+ # aggregate_group: String or Array
46
+ ###
47
+ @groups = to_array(@options[:aggregate_group])
48
+ @aggregate = {}
49
+ @aggregate[:function] = @options[:aggregate_function] if is_set?(@options[:aggregate_function])
50
+ @aggregate[:argument] = @options[:aggregate_argument] if is_set?(@options[:aggregate_argument])
51
+ @aggregate[:group_by] = groups[0] if groups.size == 1
52
+ @aggregate[:group_by] = groups if groups.size > 1
53
+ query_opts << '"aggregate":' + @aggregate.to_json if @aggregate.keys.size > 0
54
+
55
+ if @fields.size > 0 and @aggregate.keys.size > 0
56
+ raise Logworm::InvalidQueryException.new("Queries cannot contain both fields and aggregates")
57
+ end
58
+
59
+ ###
60
+ # Conditions : Array, or Comma-separated string
61
+ # ['"a":10' , '"b":20']
62
+ # "a:10", "b":20
63
+ ###
64
+ @conditions = to_string(@options[:conditions])
65
+ query_opts << '"conditions":{' + conditions + "}" if conditions.size > 0
66
+
67
+ ###
68
+ # Timeframe: String
69
+ ###
70
+ @tf = {}
71
+ @tf[:start] = unquote(@options[:start]).to_s if is_set?(@options[:start]) or is_set?(@options[:start], Integer, 0)
72
+ @tf[:end] = unquote(@options[:end]).to_s if is_set?(@options[:end]) or is_set?(@options[:end], Integer, 0)
73
+ query_opts << '"timeframe":' + @tf.to_json if @tf.keys.size > 0
74
+
75
+ ###
76
+ # Limit
77
+ # String or Integer
78
+ ###
79
+ if (is_set?(@options[:limit], Integer, 200) or is_set?(@options[:limit], String, ""))
80
+ @limit = @options[:limit].to_s
81
+ query_opts << '"limit":' + @limit
82
+ end
83
+
84
+ # And the string
85
+ "{#{query_opts.join(", ")}}"
86
+ end
87
+
88
+ def to_array(arg)
89
+ return [] if arg.nil?
90
+ return arg if arg.is_a? Array
91
+ return arg.split(",").map {|e| unquote(e.strip)} if arg.is_a? String and arg.split != ""
92
+ []
93
+ end
94
+
95
+ def to_string(arg)
96
+ return "" if arg.nil?
97
+ return arg.split(",").map {|e| e.strip}.join(",") if arg.is_a? String
98
+ return arg.join(",") if arg.is_a? Array and arg.size > 0
99
+ ""
100
+ end
101
+
102
+ def unquote(str)
103
+ return str unless str.is_a? String
104
+ str.gsub(/^"/, '').gsub(/"$/,'')
105
+ end
106
+
107
+ def is_set?(elt, klass = String, empty_val = "")
108
+ elt and elt.is_a?(klass) and elt != empty_val
109
+ end
110
+
111
+ end
112
+ end
data/lib/logworm.rb ADDED
@@ -0,0 +1,3 @@
1
+ require File.dirname(__FILE__) + '/base/db'
2
+ require File.dirname(__FILE__) + '/base/config'
3
+ require File.dirname(__FILE__) + '/base/query_builder'
data/logworm.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{logworm}
5
+ s.version = "0.6.1"
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 logging tool}
11
+ s.email = %q{schapira@pomelollc.com}
12
+ s.extra_rdoc_files = ["CHANGELOG", "README", "lib/base/config.rb", "lib/base/db.rb", "lib/base/query_builder.rb", "lib/logworm.rb"]
13
+ s.files = ["CHANGELOG", "Manifest", "README", "Rakefile", "lib/base/config.rb", "lib/base/db.rb", "lib/base/query_builder.rb", "lib/logworm.rb", "tests/builder_test.rb", "logworm.gemspec"]
14
+ s.homepage = %q{http://www.logworm.com}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Logworm", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{logworm}
18
+ s.rubygems_version = %q{1.3.6}
19
+ s.summary = %q{logworm logging tool}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<memcache-client>, [">= 0"])
27
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
28
+ s.add_runtime_dependency(%q<oauth>, [">= 0"])
29
+ s.add_development_dependency(%q<memcache-client>, [">= 0"])
30
+ s.add_development_dependency(%q<hpricot>, [">= 0"])
31
+ s.add_development_dependency(%q<oauth>, [">= 0"])
32
+ else
33
+ s.add_dependency(%q<memcache-client>, [">= 0"])
34
+ s.add_dependency(%q<hpricot>, [">= 0"])
35
+ s.add_dependency(%q<oauth>, [">= 0"])
36
+ s.add_dependency(%q<memcache-client>, [">= 0"])
37
+ s.add_dependency(%q<hpricot>, [">= 0"])
38
+ s.add_dependency(%q<oauth>, [">= 0"])
39
+ end
40
+ else
41
+ s.add_dependency(%q<memcache-client>, [">= 0"])
42
+ s.add_dependency(%q<hpricot>, [">= 0"])
43
+ s.add_dependency(%q<oauth>, [">= 0"])
44
+ s.add_dependency(%q<memcache-client>, [">= 0"])
45
+ s.add_dependency(%q<hpricot>, [">= 0"])
46
+ s.add_dependency(%q<oauth>, [">= 0"])
47
+ end
48
+ end
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require '../lib/base/query_builder'
4
+
5
+ class BuilderTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ end
9
+
10
+ def teardown
11
+ end
12
+
13
+ def test_empty
14
+ assert_equal "{}", Logworm::QueryBuilder.new({}).to_json
15
+ end
16
+
17
+ def test_fields
18
+ assert_equal '{"fields":["a","b"]}', Logworm::QueryBuilder.new(:fields => 'a, b').to_json
19
+ assert_equal '{"fields":["a","b"]}', Logworm::QueryBuilder.new(:fields => '"a", "b"').to_json
20
+ assert_equal '{"fields":["a","b"]}', Logworm::QueryBuilder.new(:fields => ["a", "b"]).to_json
21
+ end
22
+
23
+ def test_aggregate
24
+ q = {:aggregate_function => "count"}
25
+ assert_equal '{"aggregate":{"function":"count"}}', Logworm::QueryBuilder.new(q).to_json
26
+ q = {:aggregate_function => "a", :aggregate_argument => "b"}
27
+ assert_equal '{"aggregate":{"argument":"b","function":"a"}}', Logworm::QueryBuilder.new(q).to_json
28
+ q = {:aggregate_function => "a", :aggregate_argument => "b", :aggregate_group => "a,b,c"}
29
+ assert_equal '{"aggregate":{"argument":"b","group_by":["a","b","c"],"function":"a"}}', Logworm::QueryBuilder.new(q).to_json
30
+ q = {:aggregate_function => "a", :aggregate_argument => "b", :aggregate_group => ["a","b","c"]}
31
+ assert_equal '{"aggregate":{"argument":"b","group_by":["a","b","c"],"function":"a"}}', Logworm::QueryBuilder.new(q).to_json
32
+ end
33
+
34
+ def test_conditions
35
+ assert_equal '{"conditions":{"a":10,"b":"c"}}', Logworm::QueryBuilder.new(:conditions => '"a":10, "b":"c"').to_json
36
+ assert_equal '{"conditions":{"a":10,"b":"c"}}', Logworm::QueryBuilder.new(:conditions => ['"a":10', '"b":"c"']).to_json
37
+ end
38
+
39
+ def test_times
40
+ assert_equal '{}', Logworm::QueryBuilder.new(:blah => "2009").to_json
41
+ assert_equal '{"timeframe":{"start":"2009"}}', Logworm::QueryBuilder.new(:start => "2009").to_json
42
+ assert_equal '{"timeframe":{"end":"2009"}}', Logworm::QueryBuilder.new(:end => "2009").to_json
43
+ assert_equal '{"timeframe":{"start":"2009","end":"2010"}}', Logworm::QueryBuilder.new(:start => "2009", :end => "2010").to_json
44
+ assert_equal '{"timeframe":{"start":"2009","end":"2010"}}', Logworm::QueryBuilder.new(:start => 2009, :end => 2010).to_json
45
+ end
46
+
47
+ def test_limit
48
+ assert_equal '{"limit":10}', Logworm::QueryBuilder.new(:limit => 10).to_json
49
+ assert_equal '{}', Logworm::QueryBuilder.new(:limit => 200).to_json
50
+ end
51
+
52
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logworm
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 6
8
+ - 1
9
+ version: 0.6.1
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: memcache-client
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: hpricot
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: oauth
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: :runtime
55
+ version_requirements: *id003
56
+ - !ruby/object:Gem::Dependency
57
+ name: memcache-client
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
+ - !ruby/object:Gem::Dependency
69
+ name: hpricot
70
+ prerelease: false
71
+ requirement: &id005 !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ type: :development
79
+ version_requirements: *id005
80
+ - !ruby/object:Gem::Dependency
81
+ name: oauth
82
+ prerelease: false
83
+ requirement: &id006 !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ type: :development
91
+ version_requirements: *id006
92
+ description: logworm logging tool
93
+ email: schapira@pomelollc.com
94
+ executables: []
95
+
96
+ extensions: []
97
+
98
+ extra_rdoc_files:
99
+ - CHANGELOG
100
+ - README
101
+ - lib/base/config.rb
102
+ - lib/base/db.rb
103
+ - lib/base/query_builder.rb
104
+ - lib/logworm.rb
105
+ files:
106
+ - CHANGELOG
107
+ - Manifest
108
+ - README
109
+ - Rakefile
110
+ - lib/base/config.rb
111
+ - lib/base/db.rb
112
+ - lib/base/query_builder.rb
113
+ - lib/logworm.rb
114
+ - tests/builder_test.rb
115
+ - logworm.gemspec
116
+ has_rdoc: true
117
+ homepage: http://www.logworm.com
118
+ licenses: []
119
+
120
+ post_install_message:
121
+ rdoc_options:
122
+ - --line-numbers
123
+ - --inline-source
124
+ - --title
125
+ - Logworm
126
+ - --main
127
+ - README
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ segments:
135
+ - 0
136
+ version: "0"
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ segments:
142
+ - 1
143
+ - 2
144
+ version: "1.2"
145
+ requirements: []
146
+
147
+ rubyforge_project: logworm
148
+ rubygems_version: 1.3.6
149
+ signing_key:
150
+ specification_version: 3
151
+ summary: logworm logging tool
152
+ test_files: []
153
+