appstats 0.15.1 → 0.16.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/Gemfile.lock +1 -1
- data/db/migrations/20110301212017_add_appstats_results_query_type.rb +11 -0
- data/db/migrations/20110301230757_rename_appstats_results_query_as_sql_to_query_to_sql.rb +9 -0
- data/db/schema.rb +4 -2
- data/lib/appstats.rb +1 -0
- data/lib/appstats/query.rb +63 -17
- data/lib/appstats/result.rb +2 -2
- data/lib/appstats/result_job.rb +1 -1
- data/lib/appstats/test_query.rb +42 -0
- data/lib/appstats/version.rb +1 -1
- data/spec/entry_spec.rb +8 -8
- data/spec/logger_spec.rb +22 -22
- data/spec/query_spec.rb +183 -81
- data/spec/result_job_spec.rb +8 -6
- data/spec/result_spec.rb +10 -8
- metadata +6 -3
data/Gemfile.lock
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddAppstatsResultsQueryType < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :appstats_results, :query_type, :string
|
4
|
+
add_column :appstats_result_jobs, :query_type, :string
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_column :appstats_results, :query_type
|
9
|
+
remove_column :appstats_result_jobs, :query_type
|
10
|
+
end
|
11
|
+
end
|
data/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended to check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(:version =>
|
13
|
+
ActiveRecord::Schema.define(:version => 20110301230757) do
|
14
14
|
|
15
15
|
create_table "appstats_actions", :force => true do |t|
|
16
16
|
t.string "name"
|
@@ -102,13 +102,14 @@ ActiveRecord::Schema.define(:version => 20110301195959) do
|
|
102
102
|
t.datetime "last_run_at"
|
103
103
|
t.datetime "created_at"
|
104
104
|
t.datetime "updated_at"
|
105
|
+
t.string "query_type"
|
105
106
|
end
|
106
107
|
|
107
108
|
create_table "appstats_results", :force => true do |t|
|
108
109
|
t.string "name"
|
109
110
|
t.string "result_type"
|
110
111
|
t.text "query"
|
111
|
-
t.text "
|
112
|
+
t.text "query_to_sql"
|
112
113
|
t.integer "count"
|
113
114
|
t.string "action"
|
114
115
|
t.string "host"
|
@@ -120,6 +121,7 @@ ActiveRecord::Schema.define(:version => 20110301195959) do
|
|
120
121
|
t.text "contexts"
|
121
122
|
t.text "group_query_to_sql"
|
122
123
|
t.string "group_by"
|
124
|
+
t.string "query_type"
|
123
125
|
end
|
124
126
|
|
125
127
|
add_index "appstats_results", ["action"], :name => "index_appstats_results_on_action"
|
data/lib/appstats.rb
CHANGED
@@ -19,6 +19,7 @@ require "#{File.dirname(__FILE__)}/appstats/host"
|
|
19
19
|
require "#{File.dirname(__FILE__)}/appstats/context_key"
|
20
20
|
require "#{File.dirname(__FILE__)}/appstats/context_value"
|
21
21
|
require "#{File.dirname(__FILE__)}/appstats/test_object"
|
22
|
+
require "#{File.dirname(__FILE__)}/appstats/test_query"
|
22
23
|
|
23
24
|
# required in the appstats.gemspec
|
24
25
|
unless Appstats.const_defined?(:VERSION)
|
data/lib/appstats/query.rb
CHANGED
@@ -3,15 +3,16 @@ module Appstats
|
|
3
3
|
class Query
|
4
4
|
|
5
5
|
@@parser_template = Appstats::Parser.new(:rules => ":operation :action :date on :host where :contexts group by :group_by")
|
6
|
-
@@contexts_parser_template = Appstats::Parser.new(:rules => ":context", :repeating => true, :tokenize => "and or || && = <= >= <> != ( ) like")
|
6
|
+
@@contexts_parser_template = Appstats::Parser.new(:rules => ":context", :repeating => true, :tokenize => "and or || && = <= >= <> < > != ( ) like")
|
7
7
|
@@group_by_parser_template = Appstats::Parser.new(:rules => ":filter", :repeating => true, :tokenize => ",")
|
8
8
|
|
9
9
|
@@nill_query = "select 0 from appstats_entries LIMIT 1"
|
10
10
|
@@default = "1=1"
|
11
|
-
attr_accessor :name, :query, :action, :host, :date_range, :query_to_sql, :contexts, :group_by, :group_query_to_sql
|
11
|
+
attr_accessor :name, :query, :action, :host, :date_range, :query_to_sql, :contexts, :parsed_contexts, :group_by, :group_query_to_sql, :query_type
|
12
12
|
|
13
13
|
def initialize(data = {})
|
14
14
|
@name = data[:name]
|
15
|
+
@query_type = data[:query_type]
|
15
16
|
@result_type = data[:result_type] || "on_demand"
|
16
17
|
self.query=(data[:query])
|
17
18
|
end
|
@@ -19,20 +20,34 @@ module Appstats
|
|
19
20
|
def query=(value)
|
20
21
|
@query = value
|
21
22
|
parse_query
|
23
|
+
|
24
|
+
unless @query_type.nil?
|
25
|
+
|
26
|
+
all_names = @query_type.split("::")
|
27
|
+
if all_names.size == 1
|
28
|
+
@custom_query = Object::const_get(@query_type).new
|
29
|
+
else
|
30
|
+
@custom_query = eval(all_names[0...-1].join("::")).const_get(all_names.last).new
|
31
|
+
end
|
32
|
+
@custom_query.query = self
|
33
|
+
@custom_query.process_query
|
34
|
+
end
|
35
|
+
|
22
36
|
end
|
23
37
|
|
24
38
|
def run
|
25
|
-
result = Appstats::Result.new(:name => @name, :result_type => @result_type, :query => @query, :
|
39
|
+
result = Appstats::Result.new(:name => @name, :result_type => @result_type, :query => @query, :query_to_sql => @query_to_sql, :action => @action, :host => @host, :from_date => @date_range.from_date, :to_date => @date_range.to_date, :contexts => @contexts, :query_type => @query_type)
|
26
40
|
unless @group_by.empty?
|
27
41
|
result.group_by = @group_by.join(", ")
|
28
42
|
result.group_query_to_sql = @group_query_to_sql
|
29
43
|
end
|
44
|
+
|
30
45
|
result.group_by = @group_by.join(", ") unless @group_by.empty?
|
31
|
-
result.count =
|
46
|
+
result.count = run_query { |conn| conn.select_one(@query_to_sql)["num"].to_i }
|
32
47
|
result.save
|
33
|
-
|
48
|
+
|
34
49
|
unless @group_by.empty?
|
35
|
-
all_sub_results =
|
50
|
+
all_sub_results = run_query { |conn| conn.select_all(@group_query_to_sql) }
|
36
51
|
all_sub_results.each do |data|
|
37
52
|
keys = data["context_key_filter"].split(",")
|
38
53
|
values = data["context_value_filter"].split(",")
|
@@ -57,32 +72,36 @@ module Appstats
|
|
57
72
|
"EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = '#{host}' )"
|
58
73
|
end
|
59
74
|
|
60
|
-
def
|
75
|
+
def contexts_filter_to_sql
|
61
76
|
context_parser = @@contexts_parser_template.dup
|
62
|
-
return @@default if
|
77
|
+
return @@default if @contexts.blank? || !context_parser.parse(@contexts)
|
63
78
|
sql = "EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ("
|
64
79
|
|
65
80
|
status = :next
|
66
81
|
comparator = "="
|
67
82
|
context_parser.raw_results.each do |entry|
|
68
83
|
if entry.kind_of?(String)
|
69
|
-
sqlentry = sqlize(entry)
|
84
|
+
sqlentry = Query.sqlize(entry)
|
70
85
|
if Query.comparator?(entry) && status == :waiting_comparator
|
71
|
-
comparator = sqlize(entry)
|
86
|
+
comparator = Query.sqlize(entry)
|
72
87
|
status = :waiting_operand
|
73
88
|
else
|
74
89
|
sql += ")" if status == :waiting_comparator
|
75
90
|
sql += " #{sqlentry}"
|
91
|
+
@parsed_contexts<< sqlentry
|
76
92
|
status = :next
|
77
93
|
end
|
78
94
|
next
|
79
95
|
end
|
80
96
|
if status == :next
|
81
97
|
status = :waiting_comparator
|
82
|
-
|
98
|
+
@parsed_contexts<< { :context_key => entry[:context] }
|
99
|
+
sql += " (context_key = '#{Query.sqlclean(entry[:context])}'"
|
83
100
|
else
|
84
101
|
status = :next
|
85
|
-
|
102
|
+
@parsed_contexts.last[:context_value] = entry[:context]
|
103
|
+
@parsed_contexts.last[:comparator] = comparator
|
104
|
+
sql += " and context_value #{comparator} '#{Query.sqlclean(entry[:context])}')"
|
86
105
|
end
|
87
106
|
end
|
88
107
|
sql += ")" if status == :waiting_comparator
|
@@ -116,6 +135,25 @@ module Appstats
|
|
116
135
|
|
117
136
|
private
|
118
137
|
|
138
|
+
def db_connection
|
139
|
+
return ActiveRecord::Base.connection if @custom_query.nil?
|
140
|
+
@backup_config = ActiveRecord::Base.connection.instance_variable_get(:@config)
|
141
|
+
custom_connection = @custom_query.db_connection
|
142
|
+
end
|
143
|
+
|
144
|
+
def restore_connection
|
145
|
+
return if @backup_config.nil?
|
146
|
+
ActiveRecord::Base.establish_connection @backup_config
|
147
|
+
@backup_config = nil
|
148
|
+
end
|
149
|
+
|
150
|
+
def run_query
|
151
|
+
results = yield db_connection
|
152
|
+
restore_connection
|
153
|
+
results
|
154
|
+
end
|
155
|
+
|
156
|
+
|
119
157
|
def normalize_action_name(action_name)
|
120
158
|
action = Appstats::Action.where("plural_name = ?",action_name).first
|
121
159
|
action.nil? ? action_name : action.name
|
@@ -130,6 +168,12 @@ module Appstats
|
|
130
168
|
end
|
131
169
|
end
|
132
170
|
|
171
|
+
def parse_contexts(raw_input)
|
172
|
+
@contexts = raw_input
|
173
|
+
context_parser = @@contexts_parser_template.dup
|
174
|
+
return if (raw_input.blank? || !context_parser.parse(raw_input))
|
175
|
+
end
|
176
|
+
|
133
177
|
def parse_query
|
134
178
|
reset_query
|
135
179
|
return nil_query if @query.nil?
|
@@ -142,21 +186,21 @@ module Appstats
|
|
142
186
|
@action = normalize_action_name(parser.results[:action])
|
143
187
|
@date_range = DateRange.parse(parser.results[:date])
|
144
188
|
@host = parser.results[:host]
|
145
|
-
|
189
|
+
parse_contexts(parser.results[:contexts])
|
146
190
|
parse_group_by(parser.results[:group_by])
|
147
191
|
|
148
192
|
if @operation == "#"
|
149
|
-
@query_to_sql = "select count(*) from appstats_entries"
|
193
|
+
@query_to_sql = "select count(*) as num from appstats_entries"
|
150
194
|
@query_to_sql += " where action = '#{@action}'" unless @action.blank?
|
151
195
|
@query_to_sql += " and #{@date_range.to_sql}" unless @date_range.to_sql == "1=1"
|
152
196
|
@query_to_sql += " and #{Query.host_filter_to_sql(@host)}" unless @host.nil?
|
153
|
-
@query_to_sql += " and #{
|
197
|
+
@query_to_sql += " and #{contexts_filter_to_sql}" unless @contexts.nil?
|
154
198
|
end
|
155
199
|
|
156
200
|
unless @group_by.empty?
|
157
|
-
query_to_sql_with_id = @query_to_sql.sub("count(*)","id")
|
201
|
+
query_to_sql_with_id = @query_to_sql.sub("count(*) as num","id")
|
158
202
|
group_as_sql = @group_by.collect { |g| "'#{Query.sqlclean(g)}'" }.join(',')
|
159
|
-
@group_query_to_sql = "select context_key_filter, context_value_filter, count(*) num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in (#{group_as_sql}) and appstats_entry_id in ( #{query_to_sql_with_id} ) group by appstats_entry_id) results group by context_value_filter
|
203
|
+
@group_query_to_sql = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in (#{group_as_sql}) and appstats_entry_id in ( #{query_to_sql_with_id} ) group by appstats_entry_id) results group by context_value_filter"
|
160
204
|
end
|
161
205
|
|
162
206
|
@query_to_sql
|
@@ -183,6 +227,8 @@ module Appstats
|
|
183
227
|
nil_query
|
184
228
|
@date_range = DateRange.new
|
185
229
|
@group_by = []
|
230
|
+
@contexts = nil
|
231
|
+
@parsed_contexts = []
|
186
232
|
end
|
187
233
|
|
188
234
|
end
|
data/lib/appstats/result.rb
CHANGED
@@ -2,7 +2,7 @@ module Appstats
|
|
2
2
|
class Result < ActiveRecord::Base
|
3
3
|
set_table_name "appstats_results"
|
4
4
|
|
5
|
-
attr_accessible :name, :result_type, :query, :
|
5
|
+
attr_accessible :name, :result_type, :query, :query_to_sql, :count, :action, :host, :from_date, :to_date, :contexts, :group_by, :query_type
|
6
6
|
has_many :sub_results, :table_name => 'appstats_subresults', :foreign_key => 'appstats_result_id', :order => 'count DESC'
|
7
7
|
|
8
8
|
def date_to_s
|
@@ -47,7 +47,7 @@ module Appstats
|
|
47
47
|
private
|
48
48
|
|
49
49
|
def state
|
50
|
-
[name, result_type, query,
|
50
|
+
[name, result_type, query, query_to_sql, count, action, host, from_date, to_date,contexts,group_by,query_type]
|
51
51
|
end
|
52
52
|
|
53
53
|
|
data/lib/appstats/result_job.rb
CHANGED
@@ -2,7 +2,7 @@ module Appstats
|
|
2
2
|
class ResultJob < ActiveRecord::Base
|
3
3
|
set_table_name "appstats_result_jobs"
|
4
4
|
|
5
|
-
attr_accessible :name, :frequency, :status, :query, :last_run_at
|
5
|
+
attr_accessible :name, :frequency, :status, :query, :last_run_at, :query_type
|
6
6
|
|
7
7
|
@@frequency_methods =
|
8
8
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module Appstats
|
3
|
+
class TestQuery
|
4
|
+
|
5
|
+
attr_accessor :query, :query_to_sql, :group_query_to_sql
|
6
|
+
|
7
|
+
def process_query
|
8
|
+
query.query_to_sql = "select count(*) as num from appstats_test_objects"
|
9
|
+
query.group_query_to_sql = "select context_key_filter, context_value_filter, count(*) as num from (select 'name' as context_key_filter, name as context_value_filter from appstats_test_objects) results group by context_value_filter"
|
10
|
+
end
|
11
|
+
|
12
|
+
def db_connection
|
13
|
+
if query.host == "otherServer"
|
14
|
+
dbconfig = YAML::load(File.open('db/config.yml'))
|
15
|
+
ActiveRecord::Base.establish_connection(dbconfig['development']).connection
|
16
|
+
else
|
17
|
+
ActiveRecord::Base.connection
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module Core
|
24
|
+
class AnotherTestQuery
|
25
|
+
attr_accessor :query
|
26
|
+
def process_query; end
|
27
|
+
def db_connection
|
28
|
+
ActiveRecord::Base.connection
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class YetAnotherTestQuery
|
37
|
+
attr_accessor :query
|
38
|
+
def process_query; end
|
39
|
+
def db_connection
|
40
|
+
ActiveRecord::Base.connection
|
41
|
+
end
|
42
|
+
end
|
data/lib/appstats/version.rb
CHANGED
data/spec/entry_spec.rb
CHANGED
@@ -193,18 +193,18 @@ module Appstats
|
|
193
193
|
end
|
194
194
|
|
195
195
|
it "should understand an entry without contexts" do
|
196
|
-
entry = Entry.create_from_logger_string("0.
|
196
|
+
entry = Entry.create_from_logger_string("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
|
197
197
|
Entry.count.should == @before_count + 1
|
198
198
|
entry.action.should == "address_search"
|
199
|
-
entry.raw_entry.should == "0.
|
199
|
+
entry.raw_entry.should == "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
|
200
200
|
entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
|
201
201
|
end
|
202
202
|
|
203
203
|
it "should understand contexts" do
|
204
|
-
entry = Entry.create_from_logger_string("0.
|
204
|
+
entry = Entry.create_from_logger_string("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
|
205
205
|
Entry.count.should == @before_count + 1
|
206
206
|
entry.action.should == "address_filter"
|
207
|
-
entry.raw_entry.should == "0.
|
207
|
+
entry.raw_entry.should == "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
|
208
208
|
entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
|
209
209
|
entry.contexts.size.should == 2
|
210
210
|
entry.contexts[0].context_key = "app_name"
|
@@ -214,10 +214,10 @@ module Appstats
|
|
214
214
|
end
|
215
215
|
|
216
216
|
it "should handle 'action' as a context" do
|
217
|
-
entry = Entry.create_from_logger_string('0.
|
217
|
+
entry = Entry.create_from_logger_string('0.16.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb')
|
218
218
|
Entry.count.should == @before_count + 1
|
219
219
|
entry.action.should == "page-view"
|
220
|
-
entry.raw_entry.should == "0.
|
220
|
+
entry.raw_entry.should == "0.16.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
|
221
221
|
entry.occurred_at.should == Time.parse("2011-02-24 12:59:57")
|
222
222
|
entry.contexts.size.should == 2
|
223
223
|
entry.contexts[0].context_key = "action"
|
@@ -228,10 +228,10 @@ module Appstats
|
|
228
228
|
end
|
229
229
|
|
230
230
|
it "should handle multiple of the same 'context'" do
|
231
|
-
entry = Entry.create_from_logger_string('0.
|
231
|
+
entry = Entry.create_from_logger_string('0.16.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb')
|
232
232
|
Entry.count.should == @before_count + 1
|
233
233
|
entry.action.should == "page-view"
|
234
|
-
entry.raw_entry.should == "0.
|
234
|
+
entry.raw_entry.should == "0.16.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
|
235
235
|
entry.occurred_at.should == Time.parse("2011-02-24 12:59:57")
|
236
236
|
entry.contexts.size.should == 2
|
237
237
|
entry.contexts[0].context_key = "app_name"
|
data/spec/logger_spec.rb
CHANGED
@@ -115,12 +115,12 @@ module Appstats
|
|
115
115
|
|
116
116
|
it "should accept numbers" do
|
117
117
|
Appstats::Logger.entry(5, :blah => 6)
|
118
|
-
Appstats::Logger.raw_read.should == ["0.
|
118
|
+
Appstats::Logger.raw_read.should == ["0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should accept arrays" do
|
122
122
|
Appstats::Logger.entry('search', :provider => [ 'one', 'two' ])
|
123
|
-
Appstats::Logger.raw_read.should == ["0.
|
123
|
+
Appstats::Logger.raw_read.should == ["0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
|
124
124
|
end
|
125
125
|
|
126
126
|
|
@@ -130,7 +130,7 @@ module Appstats
|
|
130
130
|
|
131
131
|
it "should look similar to regular entry" do
|
132
132
|
Appstats::Logger.exception_entry(RuntimeError.new("blah"),:on => "login")
|
133
|
-
Appstats::Logger.raw_read.should == ["0.
|
133
|
+
Appstats::Logger.raw_read.should == ["0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
|
134
134
|
end
|
135
135
|
|
136
136
|
end
|
@@ -147,47 +147,47 @@ module Appstats
|
|
147
147
|
|
148
148
|
it "should handle a statistics entry" do
|
149
149
|
expected = { :action => "address_search", :timestamp => "2010-09-21 23:15:20" }
|
150
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
150
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
|
151
151
|
actual.should == expected
|
152
152
|
end
|
153
153
|
|
154
154
|
it "should handle contexts" do
|
155
155
|
expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
|
156
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
156
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
|
157
157
|
actual.should == expected
|
158
158
|
end
|
159
159
|
|
160
160
|
it "should handle multiple actions" do
|
161
161
|
expected = { :action => ["address_filter", "blah"], :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
|
162
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
162
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
|
163
163
|
actual.should == expected
|
164
164
|
end
|
165
165
|
|
166
166
|
it "should handle multiple of same context" do
|
167
167
|
expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => ['Sin','Market'] }
|
168
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
168
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
|
169
169
|
actual.should == expected
|
170
170
|
end
|
171
171
|
|
172
172
|
it "should handle no actions" do
|
173
173
|
expected = { :action => "UNKNOWN_ACTION", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
|
174
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
174
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
|
175
175
|
actual.should == expected
|
176
176
|
end
|
177
177
|
|
178
178
|
it "should handle actions with the delimiter (and change the delimiter)" do
|
179
179
|
expected = { :action => "address:=search-n", :timestamp => "2010-09-21 23:15:20" }
|
180
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
180
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
|
181
181
|
actual.should == expected
|
182
182
|
|
183
183
|
expected = { :action => "address::search==--n", :timestamp => "2010-09-21 23:15:20" }
|
184
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
184
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
|
185
185
|
actual.should == expected
|
186
186
|
end
|
187
187
|
|
188
188
|
it "should handle contexts with the delimiter (and change the delimiter)" do
|
189
189
|
expected = { :action => "address", :timestamp => "2010-09-21 23:15:20", :server => "market:eval=-n" }
|
190
|
-
actual = Appstats::Logger.entry_to_hash("0.
|
190
|
+
actual = Appstats::Logger.entry_to_hash("0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
|
191
191
|
actual.should == expected
|
192
192
|
end
|
193
193
|
|
@@ -196,66 +196,66 @@ module Appstats
|
|
196
196
|
describe "#entry_to_s" do
|
197
197
|
|
198
198
|
it "should handle a statistics entry" do
|
199
|
-
expected = "0.
|
199
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
|
200
200
|
actual = Appstats::Logger.entry_to_s("address_search")
|
201
201
|
actual.should == expected
|
202
202
|
end
|
203
203
|
|
204
204
|
it "should handle numbers" do
|
205
|
-
expected = "0.
|
205
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
|
206
206
|
actual = Appstats::Logger.entry_to_s(1,:note => 2.2)
|
207
207
|
actual.should == expected
|
208
208
|
end
|
209
209
|
|
210
210
|
it "should handle default contexts" do
|
211
211
|
Appstats::Logger.default_contexts[:app_name] = "market"
|
212
|
-
expected = "0.
|
212
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
|
213
213
|
actual = Appstats::Logger.entry_to_s("address_search")
|
214
214
|
actual.should == expected
|
215
215
|
end
|
216
216
|
|
217
217
|
it "should handle contexts (and sort them by symbol)" do
|
218
|
-
expected = "0.
|
218
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
|
219
219
|
actual = Appstats::Logger.entry_to_s("address_filter", { :server => "Live", :app_name => 'Market' })
|
220
220
|
actual.should == expected
|
221
221
|
end
|
222
222
|
|
223
223
|
it "should handle actions with the delimiter (and change the delimiter)" do
|
224
|
-
expected = "0.
|
224
|
+
expected = "0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
|
225
225
|
actual = Appstats::Logger.entry_to_s("address:=search-n")
|
226
226
|
actual.should == expected
|
227
227
|
|
228
|
-
expected = "0.
|
228
|
+
expected = "0.16.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
|
229
229
|
actual = Appstats::Logger.entry_to_s("address::search==--n")
|
230
230
|
actual.should == expected
|
231
231
|
end
|
232
232
|
|
233
233
|
it "should handle contexts with the delimiter (and change the delimiter)" do
|
234
|
-
expected = "0.
|
234
|
+
expected = "0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
|
235
235
|
actual = Appstats::Logger.entry_to_s("address", :server => 'market:eval=-n')
|
236
236
|
actual.should == expected
|
237
237
|
end
|
238
238
|
|
239
239
|
it "should ignore spaces" do
|
240
|
-
expected = "0.
|
240
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
|
241
241
|
actual = Appstats::Logger.entry_to_s("address search")
|
242
242
|
actual.should == expected
|
243
243
|
end
|
244
244
|
|
245
245
|
it "should convert newlines in action" do
|
246
|
-
expected = "0.
|
246
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
|
247
247
|
actual = Appstats::Logger.entry_to_s("address_\nsearch")
|
248
248
|
actual.should == expected
|
249
249
|
end
|
250
250
|
|
251
251
|
it "should convert newlines in context" do
|
252
|
-
expected = "0.
|
252
|
+
expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
|
253
253
|
actual = Appstats::Logger.entry_to_s("address_search",:blah => "some\nlong\nstatement")
|
254
254
|
actual.should == expected
|
255
255
|
end
|
256
256
|
|
257
257
|
it "should convert newlines based on the delimiter" do
|
258
|
-
expected = "0.
|
258
|
+
expected = "0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
|
259
259
|
actual = Appstats::Logger.entry_to_s("address:=\nsearch-n")
|
260
260
|
actual.should == expected
|
261
261
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -15,69 +15,111 @@ module Appstats
|
|
15
15
|
|
16
16
|
it "should set input to nil" do
|
17
17
|
@query.query.should == nil
|
18
|
+
@query.query_type.should == nil
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
query.group_query_to_sql.should == nil
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should understand the short hand 'on' instead of 'on server'" do
|
49
|
-
query = Appstats::Query.new(:query => "# myblahs on xyz.localnet")
|
50
|
-
query.action.should == "myblahs"
|
51
|
-
query.host.should == "xyz.localnet"
|
52
|
-
query.date_range.should == DateRange.new
|
53
|
-
query.group_by.should == []
|
54
|
-
query.group_query_to_sql.should == nil
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should understand the old 'on server' instead of new 'on'" do
|
58
|
-
query = Appstats::Query.new(:query => "# myblahs on server xyz.localnet")
|
59
|
-
query.action.should == "myblahs"
|
60
|
-
query.host.should == "xyz.localnet"
|
61
|
-
query.date_range.should == DateRange.new
|
62
|
-
query.group_by.should == []
|
63
|
-
query.group_query_to_sql.should == nil
|
21
|
+
describe "query_type" do
|
22
|
+
|
23
|
+
it "should allow simple objects" do
|
24
|
+
query = Appstats::Query.new(:query => "# logins", :query_type => "YetAnotherTestQuery")
|
25
|
+
query.query.should == "# logins"
|
26
|
+
query.query_type.should == "YetAnotherTestQuery"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should allow modules" do
|
30
|
+
query = Appstats::Query.new(:query => "# logins", :query_type => "Appstats::TestQuery")
|
31
|
+
query.query.should == "# logins"
|
32
|
+
query.query_type.should == "Appstats::TestQuery"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow sub modules" do
|
36
|
+
query = Appstats::Query.new(:query => "# logins", :query_type => "Appstats::Core::AnotherTestQuery")
|
37
|
+
query.query.should == "# logins"
|
38
|
+
query.query_type.should == "Appstats::Core::AnotherTestQuery"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should fail for invalid query type" do
|
42
|
+
|
43
|
+
lambda { Appstats::Query.new(:query => "# logins", :query_type => "x") }.should raise_error
|
44
|
+
end
|
45
|
+
|
64
46
|
end
|
65
47
|
|
66
|
-
describe "
|
48
|
+
describe "default query type" do
|
49
|
+
|
50
|
+
it "should set the inputs to nil if input invalid" do
|
51
|
+
query = Appstats::Query.new(:query => "# myblahs today on xyz.localnet")
|
52
|
+
query.query = nil
|
53
|
+
query.action.should == nil
|
54
|
+
query.host.should == nil
|
55
|
+
query.date_range.should == DateRange.new
|
56
|
+
query.group_by.should == []
|
57
|
+
query.group_query_to_sql.should == nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should set the action and host" do
|
61
|
+
query = Appstats::Query.new(:query => "# myblahs today on xyz.localnet")
|
62
|
+
query.action.should == "myblahs"
|
63
|
+
query.host.should == "xyz.localnet"
|
64
|
+
query.date_range.should == DateRange.parse("today")
|
65
|
+
query.group_by.should == []
|
66
|
+
query.group_query_to_sql.should == nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should understand the short hand 'on' instead of 'on server'" do
|
70
|
+
query = Appstats::Query.new(:query => "# myblahs on xyz.localnet")
|
71
|
+
query.action.should == "myblahs"
|
72
|
+
query.host.should == "xyz.localnet"
|
73
|
+
query.date_range.should == DateRange.new
|
74
|
+
query.group_by.should == []
|
75
|
+
query.group_query_to_sql.should == nil
|
76
|
+
end
|
67
77
|
|
68
|
-
it "should
|
69
|
-
query = Appstats::Query.new(:query => "# myblahs
|
70
|
-
query.
|
78
|
+
it "should understand the old 'on server' instead of new 'on'" do
|
79
|
+
query = Appstats::Query.new(:query => "# myblahs on server xyz.localnet")
|
80
|
+
query.action.should == "myblahs"
|
81
|
+
query.host.should == "xyz.localnet"
|
82
|
+
query.date_range.should == DateRange.new
|
83
|
+
query.group_by.should == []
|
84
|
+
query.group_query_to_sql.should == nil
|
71
85
|
end
|
72
86
|
|
73
|
-
|
74
|
-
|
75
|
-
|
87
|
+
describe "group by" do
|
88
|
+
|
89
|
+
it "should handle single entry" do
|
90
|
+
query = Appstats::Query.new(:query => "# myblahs group by aa")
|
91
|
+
query.group_by.should == ["aa"]
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should handle multi-entry" do
|
95
|
+
query = Appstats::Query.new(:query => "# myblahs group by aa,bbbb")
|
96
|
+
query.group_by.should == ["aa","bbbb"]
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "contexts" do
|
102
|
+
|
103
|
+
it "should handle single entry" do
|
104
|
+
query = Appstats::Query.new(:query => "# myblahs where aa = bb or aa < ccc")
|
105
|
+
query.contexts.should == "aa = bb or aa < ccc"
|
106
|
+
query.parsed_contexts.should == [ { :context_key => "aa", :comparator => "=", :context_value => "bb" }, "or", { :context_key => "aa", :comparator => "<", :context_value => "ccc" } ]
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "distinct query_type" do
|
114
|
+
|
115
|
+
it "should delete sql to other queries" do
|
116
|
+
query = Appstats::Query.new(:query => "# stuff", :query_type => "Appstats::TestQuery")
|
117
|
+
query.query_to_sql.should == "select count(*) as num from appstats_test_objects"
|
118
|
+
query.group_query_to_sql.should == "select context_key_filter, context_value_filter, count(*) as num from (select 'name' as context_key_filter, name as context_value_filter from appstats_test_objects) results group by context_value_filter"
|
76
119
|
end
|
77
120
|
|
78
121
|
end
|
79
122
|
|
80
|
-
|
81
123
|
end
|
82
124
|
|
83
125
|
describe "#run" do
|
@@ -91,14 +133,14 @@ module Appstats
|
|
91
133
|
query = Appstats::Query.new(:query => "# blahs")
|
92
134
|
result = query.run
|
93
135
|
result.new_record?.should == false
|
94
|
-
result.should == Appstats::Result.new(:result_type => "on_demand", :query => "# blahs", :
|
136
|
+
result.should == Appstats::Result.new(:result_type => "on_demand", :query => "# blahs", :query_to_sql => query.query_to_sql, :count => 0, :action => "blahs", :group_by => nil)
|
95
137
|
end
|
96
138
|
|
97
139
|
it "should set name and result_type if provided" do
|
98
140
|
query = Appstats::Query.new(:name => "x", :result_type => "some_reason", :query => "# blahs")
|
99
141
|
result = query.run
|
100
142
|
result.new_record?.should == false
|
101
|
-
result.should == Appstats::Result.new(:name => "x", :result_type => "some_reason", :query => "# blahs", :
|
143
|
+
result.should == Appstats::Result.new(:name => "x", :result_type => "some_reason", :query => "# blahs", :query_to_sql => query.query_to_sql, :count => 0, :action => "blahs", :group_by => nil)
|
102
144
|
end
|
103
145
|
|
104
146
|
it "should track contexts" do
|
@@ -211,21 +253,81 @@ module Appstats
|
|
211
253
|
it "should track sub results for multiple group by" do
|
212
254
|
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
213
255
|
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
256
|
+
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
257
|
+
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
258
|
+
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
259
|
+
|
214
260
|
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
|
261
|
+
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
|
262
|
+
|
263
|
+
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
264
|
+
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
215
265
|
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
216
266
|
|
217
267
|
query = Appstats::Query.new(:query => "# myblahs group by service_provider,user")
|
218
268
|
result = query.run
|
219
|
-
result.count.should ==
|
269
|
+
result.count.should == 10
|
220
270
|
result.group_by.should == "service_provider, user"
|
221
271
|
result.sub_results.size.should == 3
|
222
272
|
|
223
|
-
result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count =>
|
224
|
-
result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count =>
|
225
|
-
result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count =>
|
273
|
+
result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count => 5, :ratio_of_total => 0.50)
|
274
|
+
result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count => 3, :ratio_of_total => 0.30)
|
275
|
+
result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count => 2, :ratio_of_total => 0.20)
|
226
276
|
end
|
227
277
|
|
228
278
|
end
|
279
|
+
|
280
|
+
describe "third party searches" do
|
281
|
+
|
282
|
+
before(:each) do
|
283
|
+
TestObject.delete_all
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should handle custom sql" do
|
288
|
+
TestObject.create and TestObject.create
|
289
|
+
|
290
|
+
query = Query.new(:query => "# x", :query_type => "Appstats::TestQuery")
|
291
|
+
result = query.run
|
292
|
+
|
293
|
+
result.query_type.should == "Appstats::TestQuery"
|
294
|
+
result.count.should == 2
|
295
|
+
result.query_to_sql.should == "select count(*) as num from appstats_test_objects"
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should handle group by" do
|
299
|
+
TestObject.create(:name => "aa") and TestObject.create(:name => "aa") and TestObject.create(:name => "bb")
|
300
|
+
|
301
|
+
query = Query.new(:query => "# x group by y", :query_type => "Appstats::TestQuery")
|
302
|
+
result = query.run
|
303
|
+
|
304
|
+
result.query_type.should == "Appstats::TestQuery"
|
305
|
+
result.count.should == 3
|
306
|
+
result.group_query_to_sql.should == "select context_key_filter, context_value_filter, count(*) as num from (select 'name' as context_key_filter, name as context_value_filter from appstats_test_objects) results group by context_value_filter"
|
307
|
+
result.sub_results.size.should == 2
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should handle remote servers" do
|
311
|
+
TestObject.create(:name => "aa")
|
312
|
+
|
313
|
+
query1 = Query.new(:query => "# x on testServer", :query_type => "Appstats::TestQuery")
|
314
|
+
result1 = query1.run
|
315
|
+
|
316
|
+
query2 = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
|
317
|
+
result2 = query2.run
|
318
|
+
|
319
|
+
if result2.count == result1.count #coincidence
|
320
|
+
TestObject.create(:name => "aa")
|
321
|
+
result2 = query2.run
|
322
|
+
end
|
323
|
+
|
324
|
+
result1.count.should_not == result2.count
|
325
|
+
|
326
|
+
result1 = query1.run
|
327
|
+
result1.count.should_not == result2.count
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
229
331
|
|
230
332
|
end
|
231
333
|
|
@@ -247,13 +349,13 @@ module Appstats
|
|
247
349
|
describe "actions" do
|
248
350
|
|
249
351
|
it "should understand both singular and plural names" do
|
250
|
-
expected_sql = "select count(*) from appstats_entries where action = 'login'"
|
352
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'login'"
|
251
353
|
Appstats::Query.new(:query => "# logins").query_to_sql.should == expected_sql
|
252
354
|
Appstats::Query.new(:query => "# login").query_to_sql.should == expected_sql
|
253
355
|
end
|
254
356
|
|
255
357
|
it "should use 'itself' if action not found" do
|
256
|
-
expected_sql = "select count(*) from appstats_entries where action = 'garblygook'"
|
358
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'garblygook'"
|
257
359
|
Appstats::Query.new(:query => "# garblygook").query_to_sql.should == expected_sql
|
258
360
|
end
|
259
361
|
|
@@ -261,7 +363,7 @@ module Appstats
|
|
261
363
|
|
262
364
|
describe "date ranges" do
|
263
365
|
it "should understand since dates" do
|
264
|
-
expected_sql = "select count(*) from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
|
366
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
|
265
367
|
Appstats::Query.new(:query => "# logins since 2010-01-15").query_to_sql.should == expected_sql
|
266
368
|
end
|
267
369
|
end
|
@@ -269,7 +371,7 @@ module Appstats
|
|
269
371
|
describe "server_name" do
|
270
372
|
|
271
373
|
it "should on_name" do
|
272
|
-
expected_sql = "select count(*) from appstats_entries where action = 'login' and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'my.localnet' )"
|
374
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'my.localnet' )"
|
273
375
|
Appstats::Query.new(:query => "# logins on my.localnet").query_to_sql.should == expected_sql
|
274
376
|
end
|
275
377
|
|
@@ -277,7 +379,7 @@ module Appstats
|
|
277
379
|
|
278
380
|
describe "date range and server_name" do
|
279
381
|
it "should understand dates and 'on'" do
|
280
|
-
expected_sql = "select count(*) from appstats_entries where action = 'login' and (occurred_at >= '2010-01-15 00:00:00' and occurred_at <= '2010-01-31 23:59:59') and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'your.localnet' )"
|
382
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and (occurred_at >= '2010-01-15 00:00:00' and occurred_at <= '2010-01-31 23:59:59') and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'your.localnet' )"
|
281
383
|
Appstats::Query.new(:query => "# logins between 2010-01-15 and 2010-01-31 on your.localnet").query_to_sql.should == expected_sql
|
282
384
|
end
|
283
385
|
end
|
@@ -285,12 +387,12 @@ module Appstats
|
|
285
387
|
describe "where clause" do
|
286
388
|
|
287
389
|
it "should understand no quotes" do
|
288
|
-
expected_sql = "select count(*) from appstats_entries where action = 'login' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( (context_key = 'user' and context_value = 'aforward')))"
|
390
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( (context_key = 'user' and context_value = 'aforward')))"
|
289
391
|
Appstats::Query.new(:query => "# logins where user = aforward").query_to_sql.should == expected_sql
|
290
392
|
end
|
291
393
|
|
292
394
|
it "should handle example" do
|
293
|
-
expected_sql = "select count(*) from appstats_entries where action = 'blahs' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( ( (context_key = 'a' and context_value = 'b') and (context_key = 'c' and context_value = '4') ) or ( (context_key = 'aaa' and context_value = '5') )))"
|
395
|
+
expected_sql = "select count(*) as num from appstats_entries where action = 'blahs' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( ( (context_key = 'a' and context_value = 'b') and (context_key = 'c' and context_value = '4') ) or ( (context_key = 'aaa' and context_value = '5') )))"
|
294
396
|
Appstats::Query.new(:query => "# blahs where (a=b and c=4) or (aaa=5)").query_to_sql.should == expected_sql
|
295
397
|
end
|
296
398
|
|
@@ -331,26 +433,26 @@ module Appstats
|
|
331
433
|
|
332
434
|
it "should support 1 filter" do
|
333
435
|
query = Appstats::Query.new(:query => "# myblahs group by aa")
|
334
|
-
expected = "select context_key_filter, context_value_filter, count(*) num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter
|
436
|
+
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
335
437
|
query.group_query_to_sql.should == expected
|
336
438
|
end
|
337
439
|
|
338
440
|
it "should support surrounding quotes" do
|
339
441
|
query = Appstats::Query.new(:query => "# myblahs group by 'aa'")
|
340
|
-
expected = "select context_key_filter, context_value_filter, count(*) num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter
|
442
|
+
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
341
443
|
query.group_query_to_sql.should == expected
|
342
444
|
end
|
343
445
|
|
344
446
|
it "should support inner quotes" do
|
345
447
|
query = Appstats::Query.new(:query => "# myblahs group by a's")
|
346
|
-
expected = "select context_key_filter, context_value_filter, count(*) num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('a''s') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter
|
448
|
+
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('a''s') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
347
449
|
query.group_query_to_sql.should == expected
|
348
450
|
end
|
349
451
|
|
350
452
|
|
351
453
|
it "should support many filters" do
|
352
454
|
query = Appstats::Query.new(:query => "# myblahs group by aa, bbb")
|
353
|
-
expected = "select context_key_filter, context_value_filter, count(*) num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa','bbb') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter
|
455
|
+
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa','bbb') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
354
456
|
query.group_query_to_sql.should == expected
|
355
457
|
end
|
356
458
|
|
@@ -364,43 +466,43 @@ module Appstats
|
|
364
466
|
end
|
365
467
|
|
366
468
|
it "should translate a = b into EXISTS query" do
|
367
|
-
Appstats::Query.
|
368
|
-
Appstats::Query.
|
469
|
+
Appstats::Query.new(:query => "# logins where a=b").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
|
470
|
+
Appstats::Query.new(:query => "# logins where a = b ").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
|
369
471
|
end
|
370
472
|
|
371
473
|
it "should ignore single quotes" do
|
372
|
-
Appstats::Query.
|
373
|
-
Appstats::Query.
|
474
|
+
Appstats::Query.new(:query => "# logins where 'aaa'='bbbb'").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
|
475
|
+
Appstats::Query.new(:query => "# logins where 'aaa' = 'bbbb' ").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
|
374
476
|
end
|
375
477
|
|
376
478
|
it "should allow for searching for all entries of a certain context" do
|
377
|
-
Appstats::Query.
|
479
|
+
Appstats::Query.new(:query => "# logins where aaa").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa')))"
|
378
480
|
end
|
379
481
|
|
380
482
|
it "should allow for searching for several entries of a certain context" do
|
381
|
-
Appstats::Query.
|
483
|
+
Appstats::Query.new(:query => "# logins where aaa || bbb").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa') or (context_key = 'bbb')))"
|
382
484
|
end
|
383
485
|
|
384
486
|
it "should allow complex queries" do
|
385
|
-
Appstats::Query.
|
487
|
+
Appstats::Query.new(:query => "# logins where user='andrew' || user='aforward'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value = 'andrew') or (context_key = 'user' and context_value = 'aforward')))"
|
386
488
|
end
|
387
489
|
|
388
490
|
it "should support or" do
|
389
|
-
Appstats::Query.
|
491
|
+
Appstats::Query.new(:query => "# logins where user='andrew' or user='aforward'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value = 'andrew') or (context_key = 'user' and context_value = 'aforward')))"
|
390
492
|
end
|
391
493
|
|
392
494
|
it "should support like" do
|
393
|
-
Appstats::Query.
|
495
|
+
Appstats::Query.new(:query => "# logins where user like '%andrew%'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value like '%andrew%')))"
|
394
496
|
end
|
395
497
|
|
396
498
|
it "should support and" do
|
397
|
-
Appstats::Query.
|
499
|
+
Appstats::Query.new(:query => "# logins where user='andrew' and user='aforward'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value = 'andrew') and (context_key = 'user' and context_value = 'aforward')))"
|
398
500
|
end
|
399
501
|
|
400
502
|
|
401
503
|
it "should do simple 1 = 1 if invalid" do
|
402
|
-
Appstats::Query.
|
403
|
-
Appstats::Query.
|
504
|
+
Appstats::Query.new(:query => "# logins where").contexts_filter_to_sql.should == "1=1"
|
505
|
+
Appstats::Query.new(:query => "# logins").contexts_filter_to_sql.should == "1=1"
|
404
506
|
end
|
405
507
|
|
406
508
|
end
|
data/spec/result_job_spec.rb
CHANGED
@@ -20,15 +20,17 @@ module Appstats
|
|
20
20
|
@result_job.status.should == nil
|
21
21
|
@result_job.query.should == nil
|
22
22
|
@result_job.last_run_at.should == nil
|
23
|
+
@result_job.query_type.should == nil
|
23
24
|
end
|
24
25
|
|
25
26
|
it "should set on constructor" do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
result_job = Appstats::ResultJob.new(:name => 'a', :frequency => 'b', :status => 'c', :query => 'd', :last_run_at => Time.parse("2010-02-03"), :query_type => 'e')
|
28
|
+
result_job.name.should == 'a'
|
29
|
+
result_job.frequency.should == 'b'
|
30
|
+
result_job.status.should == 'c'
|
31
|
+
result_job.query.should == 'd'
|
32
|
+
result_job.last_run_at.to_s.should == Time.parse("2010-02-03").to_s
|
33
|
+
result_job.query_type.should == 'e'
|
32
34
|
end
|
33
35
|
|
34
36
|
end
|
data/spec/result_spec.rb
CHANGED
@@ -14,21 +14,22 @@ module Appstats
|
|
14
14
|
@result.name.should == nil
|
15
15
|
@result.result_type.should == nil
|
16
16
|
@result.query.should == nil
|
17
|
-
@result.
|
17
|
+
@result.query_to_sql.should == nil
|
18
18
|
@result.count.should == nil
|
19
19
|
@result.action.should == nil
|
20
20
|
@result.contexts.should == nil
|
21
21
|
@result.from_date.should == nil
|
22
22
|
@result.to_date.should == nil
|
23
23
|
@result.group_by.should == nil
|
24
|
+
@result.query_type.should == nil
|
24
25
|
end
|
25
26
|
|
26
27
|
it "should set on constructor" do
|
27
|
-
result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :
|
28
|
+
result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
|
28
29
|
result.name.should == 'a'
|
29
30
|
result.result_type.should == 'b'
|
30
31
|
result.query.should == 'c'
|
31
|
-
result.
|
32
|
+
result.query_to_sql.should == 'd'
|
32
33
|
result.count.should == 10
|
33
34
|
result.action.should == 'e'
|
34
35
|
result.host.should == 'f'
|
@@ -36,6 +37,7 @@ module Appstats
|
|
36
37
|
result.from_date_to_s.should == '2010-01-02'
|
37
38
|
result.to_date_to_s.should == '2010-02-03'
|
38
39
|
result.group_by.should == "a,b"
|
40
|
+
result.query_type.should == "h"
|
39
41
|
end
|
40
42
|
|
41
43
|
end
|
@@ -43,16 +45,16 @@ module Appstats
|
|
43
45
|
describe "#==" do
|
44
46
|
|
45
47
|
it "should be equal on all attributes" do
|
46
|
-
result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :
|
47
|
-
same_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :
|
48
|
+
result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
|
49
|
+
same_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
|
48
50
|
(result == same_result).should == true
|
49
51
|
end
|
50
52
|
|
51
53
|
it "should be not equal if diferent attributes" do
|
52
|
-
result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :
|
54
|
+
result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
|
53
55
|
|
54
|
-
[:name,:result_type,:query,:
|
55
|
-
different_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :
|
56
|
+
[:name,:result_type,:query,:query_to_sql,:count,:action,:host,:contexts,:from_date,:to_date,:group_by,:query_type].each do |attr|
|
57
|
+
different_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
|
56
58
|
|
57
59
|
if [:from_date,:to_date].include?(attr)
|
58
60
|
different_result.send("#{attr}=",Time.parse("2011-01-02"))
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appstats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 93
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 16
|
9
9
|
- 1
|
10
|
-
version: 0.
|
10
|
+
version: 0.16.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andrew Forward
|
@@ -162,6 +162,8 @@ files:
|
|
162
162
|
- db/migrations/20110301170733_add_appstats_results_group_query_to_sql.rb
|
163
163
|
- db/migrations/20110301170947_create_appstats_sub_results.rb
|
164
164
|
- db/migrations/20110301195959_add_appstats_results_groups.rb
|
165
|
+
- db/migrations/20110301212017_add_appstats_results_query_type.rb
|
166
|
+
- db/migrations/20110301230757_rename_appstats_results_query_as_sql_to_query_to_sql.rb
|
165
167
|
- db/schema.rb
|
166
168
|
- lib/appstats.rb
|
167
169
|
- lib/appstats/action.rb
|
@@ -183,6 +185,7 @@ files:
|
|
183
185
|
- lib/appstats/sub_result.rb
|
184
186
|
- lib/appstats/tasks.rb
|
185
187
|
- lib/appstats/test_object.rb
|
188
|
+
- lib/appstats/test_query.rb
|
186
189
|
- lib/appstats/version.rb
|
187
190
|
- lib/daemons/appstats_log_collector.rb
|
188
191
|
- lib/daemons/appstats_log_collector_ctl
|