logworm 0.6.1

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 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
+