appstats 0.19.7 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.19.7)
4
+ appstats (0.20.0)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
@@ -0,0 +1,14 @@
1
+ class CreateAppstatsActionContexts < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :appstats_action_context_keys do |t|
4
+ t.string :action_name
5
+ t.string :context_key
6
+ t.string :status
7
+ t.timestamps
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :appstats_action_context_keys
13
+ end
14
+ end
@@ -10,7 +10,15 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 20110321154125) do
13
+ ActiveRecord::Schema.define(:version => 20110330171745) do
14
+
15
+ create_table "appstats_action_context_keys", :force => true do |t|
16
+ t.string "action_name"
17
+ t.string "context_key"
18
+ t.string "status"
19
+ t.datetime "created_at"
20
+ t.datetime "updated_at"
21
+ end
14
22
 
15
23
  create_table "appstats_actions", :force => true do |t|
16
24
  t.string "name"
@@ -7,6 +7,7 @@ require "#{File.dirname(__FILE__)}/appstats/entry_date"
7
7
  require "#{File.dirname(__FILE__)}/appstats/date_range"
8
8
  require "#{File.dirname(__FILE__)}/appstats/action"
9
9
  require "#{File.dirname(__FILE__)}/appstats/context"
10
+ require "#{File.dirname(__FILE__)}/appstats/action_context_key"
10
11
  require "#{File.dirname(__FILE__)}/appstats/tasks"
11
12
  require "#{File.dirname(__FILE__)}/appstats/logger"
12
13
  require "#{File.dirname(__FILE__)}/appstats/log_collector"
@@ -18,6 +19,7 @@ require "#{File.dirname(__FILE__)}/appstats/result_job"
18
19
  require "#{File.dirname(__FILE__)}/appstats/host"
19
20
  require "#{File.dirname(__FILE__)}/appstats/friendly_timer"
20
21
  require "#{File.dirname(__FILE__)}/appstats/context_key"
22
+ require "#{File.dirname(__FILE__)}/appstats/appstats_query"
21
23
  require "#{File.dirname(__FILE__)}/appstats/context_value"
22
24
  require "#{File.dirname(__FILE__)}/appstats/test_object"
23
25
  require "#{File.dirname(__FILE__)}/appstats/test_query"
@@ -0,0 +1,23 @@
1
+
2
+ module Appstats
3
+ class ActionContextKey < ActiveRecord::Base
4
+ set_table_name "appstats_action_context_keys"
5
+
6
+ attr_accessible :action_name, :context_key, :status
7
+
8
+ def self.update_action_context_keys
9
+ sql = "select action,context_key,count(*) as num
10
+ from appstats_entries
11
+ inner join appstats_contexts on appstats_contexts.appstats_entry_id = appstats_entries.id
12
+ where (action,context_key) not in (select action_name, context_key from appstats_action_context_keys)
13
+ group by action,context_key"
14
+ count = 0
15
+ ActiveRecord::Base.connection.execute(sql).each do |row|
16
+ Appstats::ActionContextKey.create(:action_name => row[0], :context_key => row[1], :status => 'derived')
17
+ count += 1
18
+ end
19
+ count
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,92 @@
1
+ class AppstatsQuery
2
+
3
+ attr_accessor :query
4
+
5
+ @@default_query = "select 0 as num"
6
+
7
+ @@action_to_available_contexts =
8
+ {
9
+ "appstats_queries" => [ "action", "contexts", "group_by" ],
10
+ "bomb" => []
11
+ }
12
+
13
+ def query_to_sql
14
+ return @@default_query if query.nil?
15
+ query.query_to_sql
16
+ end
17
+
18
+ def group_query_to_sql
19
+ return nil if query.nil?
20
+ query.group_query_to_sql
21
+ end
22
+
23
+ def process_query
24
+ return if query.nil?
25
+ query.query_to_sql = @@default_query
26
+ query.group_query_to_sql = nil
27
+ return if query.action.blank?
28
+
29
+ action = query.action.pluralize.downcase
30
+ case action
31
+ when "appstats_queries"
32
+ count_filter = "COUNT(*)"
33
+ query.query_to_sql = "select #{count_filter} as num from appstats_results#{build_where_clause}"
34
+ when "bombs"
35
+ query.query_to_sql = "invalid sql"
36
+ end
37
+ query.group_query_to_sql = query.query_to_sql.sub("#{count_filter} as num","#{context_key_filter_name(action)} as context_key_filter, #{context_value_filter_name(action)} as context_value_filter, COUNT(*) as num") + " group by context_value_filter" unless query.group_by.empty?
38
+ end
39
+
40
+ def run
41
+ query.run
42
+ end
43
+
44
+ def db_connection
45
+ ActiveRecord::Base.connection
46
+ end
47
+
48
+ def self.available_action?(action)
49
+ return false if action.blank?
50
+ return @@action_to_available_contexts.keys.include?(action.downcase.pluralize)
51
+ end
52
+
53
+ private
54
+
55
+ def build_where_clause
56
+ where_clause = ""
57
+ action = query.action.pluralize.downcase
58
+ available_contexts = @@action_to_available_contexts[action]
59
+ status = :context
60
+ query.parsed_contexts.each do |lookup|
61
+ next if status == :context && lookup.kind_of?(String)
62
+ next if status == :join && !lookup.kind_of?(String)
63
+ next if status == :context && (lookup[:context_value].nil? || !available_contexts.include?(lookup[:context_key]))
64
+
65
+ where_clause = " where" if where_clause.blank?
66
+ if lookup.kind_of?(String)
67
+ where_clause += " #{lookup}"
68
+ status = :context
69
+ elsif !lookup[:context_value].nil? && available_contexts.include?(lookup[:context_key])
70
+ where_clause += " #{database_column(action,lookup[:context_key])} #{lookup[:comparator]} '#{Appstats::Query.sqlclean(lookup[:context_value])}'"
71
+ status = :join
72
+ end
73
+ end
74
+ where_clause
75
+ end
76
+
77
+ def context_key_filter_name(action)
78
+ "'" + query.group_by.join(",") + "'"
79
+ end
80
+
81
+ def context_value_filter_name(action)
82
+ database_names = query.group_by.collect do |name|
83
+ database_column(action,name)
84
+ end
85
+ "concat(ifnull("+ database_names.join(",'--'),',',ifnull(") +",'--'))"
86
+ end
87
+
88
+ def database_column(action,name)
89
+ name
90
+ end
91
+
92
+ end
@@ -73,13 +73,27 @@ module Appstats
73
73
  true
74
74
  end
75
75
 
76
+ def self.alpha?(raw_input)
77
+ return false if raw_input.nil?
78
+ !raw_input.match(/^[A-Za-z]+$/i).nil?
79
+ end
80
+
76
81
  def self.parse_constant(current_text,constant)
77
82
  answer = [nil,nil]
78
83
  return answer if current_text.blank? || constant.nil?
79
84
  current_text.strip!
80
- m = current_text.match(/^(#{constant})(.*)$/im)
85
+
86
+ remaining_text_index = -1
87
+ if alpha?(constant)
88
+ m = current_text.match(/^(#{constant})(\s|$)(.*)$/im)
89
+ remaining_text_index = 3
90
+ else
91
+ m = current_text.match(/^(#{constant})(.*)$/im)
92
+ remaining_text_index = 2
93
+ end
94
+
81
95
  answer[0] = m[1] unless m.nil?
82
- answer[1] = m.nil? ? current_text : m[2]
96
+ answer[1] = m.nil? ? current_text : m[remaining_text_index]
83
97
  clean_parsed_word(answer)
84
98
  end
85
99
 
@@ -186,7 +200,7 @@ module Appstats
186
200
  current_token.gsub!(")",'\)')
187
201
  current_token.gsub!("|",'\|')
188
202
  @tokenize_no_spaces<< current_token
189
- current_token = "\\s+#{current_token}" unless current_token.match(/.*[a-z].*/i).nil?
203
+ current_token = "\\s+#{current_token}(\\s|$)" unless current_token.match(/.*[a-z].*/i).nil?
190
204
  @tokenize<< current_token
191
205
  end
192
206
  @tokenize_regex_no_spaces = @tokenize_no_spaces.join("|")
@@ -209,7 +223,7 @@ module Appstats
209
223
  current_rule = rule.upcase
210
224
  current_rule_no_spaces = current_rule
211
225
  @constants_no_spaces<< current_rule_no_spaces
212
- current_rule = "\\s+#{current_rule}" unless current_rule.match(/.*[a-z].*/i).nil?
226
+ current_rule = "\\s+#{current_rule}(\\s|$)" unless current_rule.match(/.*[a-z].*/i).nil?
213
227
  @constants<< current_rule
214
228
  previous_stop_on = :constant
215
229
  end
@@ -1,3 +1,3 @@
1
1
  module Appstats
2
- VERSION = "0.19.7"
2
+ VERSION = "0.20.0"
3
3
  end
@@ -63,6 +63,7 @@ while($running) do
63
63
  Appstats::Host.update_hosts
64
64
  Appstats::ContextKey.update_context_keys
65
65
  Appstats::ContextValue.update_context_values
66
+ Appstats::ActionContextKey.update_action_context_keys
66
67
  Appstats::LogCollector.remove_remote_files(appstats_config["remote_servers"])
67
68
  ActiveRecord::Base.connection.disconnect!
68
69
  end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Appstats
4
+ describe ActionContextKey do
5
+
6
+ before(:each) do
7
+ Appstats::Entry.delete_all
8
+ Appstats::Context.delete_all
9
+ Appstats::ActionContextKey.delete_all
10
+ @action = Appstats::ActionContextKey.new
11
+ end
12
+
13
+
14
+
15
+ describe "#initialize" do
16
+
17
+ it "should set action_name to nil" do
18
+ @action.action_name.should == nil
19
+ end
20
+
21
+ it "should set context_key to nil" do
22
+ @action.context_key.should == nil
23
+ end
24
+
25
+ it "should set status to nil" do
26
+ @action.status.should == nil
27
+ end
28
+
29
+ it "should set on constructor" do
30
+ action = Appstats::ActionContextKey.new(:action_name => 'a', :context_key => 'b', :status => 'c')
31
+ action.action_name.should == 'a'
32
+ action.context_key.should == 'b'
33
+ action.status.should == 'c'
34
+ end
35
+
36
+ end
37
+
38
+ describe "#update_action_context_keys" do
39
+
40
+ it "should do nothing if no events" do
41
+ Appstats::ActionContextKey.update_action_context_keys.should == 0
42
+ Appstats::ActionContextKey.count.should == 0
43
+ end
44
+
45
+ it "should ignore actions without any contexts" do
46
+ Appstats::Entry.create_from_logger('a')
47
+ Appstats::ActionContextKey.update_action_context_keys.should == 0
48
+ Appstats::ActionContextKey.count.should == 0
49
+
50
+ end
51
+
52
+ it "should add entry action / context names" do
53
+ Appstats::Entry.create_from_logger('a',:blah => "x")
54
+ Appstats::ActionContextKey.update_action_context_keys.should == 1
55
+ Appstats::ActionContextKey.count.should == 1
56
+
57
+ action = Appstats::ActionContextKey.last
58
+ action.action_name = 'a'
59
+ action.context_key = 'blah'
60
+ action.status = 'derived'
61
+ end
62
+
63
+ it "should ignore existing entries action / context names" do
64
+ Appstats::Entry.create_from_logger('a',:blah => "x")
65
+ Appstats::ActionContextKey.update_action_context_keys.should == 1
66
+ Appstats::ActionContextKey.update_action_context_keys.should == 0
67
+ end
68
+
69
+ it "should ignore duplicates" do
70
+ Appstats::Entry.create_from_logger('a',:blah => "x")
71
+ Appstats::Entry.create_from_logger('a',:blah => "y")
72
+ Appstats::ActionContextKey.update_action_context_keys.should == 1
73
+ Appstats::ActionContextKey.count.should == 1
74
+ end
75
+
76
+
77
+ end
78
+
79
+
80
+ end
81
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ module Appstats
4
+
5
+ describe AppstatsQuery do
6
+
7
+ before(:each) do
8
+ Time.stub!(:now).and_return(Time.parse('2010-09-21 23:15:20'))
9
+ @appstats_query = AppstatsQuery.new
10
+ end
11
+
12
+ describe "#available_action?" do
13
+
14
+ it "should be false for nil" do
15
+ AppstatsQuery.available_action?(nil).should == false
16
+ AppstatsQuery.available_action?("").should == false
17
+ end
18
+
19
+ it "should be false for blah" do
20
+ AppstatsQuery.available_action?("blah").should == false
21
+ end
22
+
23
+ it "should be true for appstats_queries" do
24
+ AppstatsQuery.available_action?("appstats_queries").should == true
25
+ AppstatsQuery.available_action?("Appstats_queries").should == true
26
+ AppstatsQuery.available_action?("appstats_query").should == true
27
+ end
28
+
29
+ end
30
+
31
+ describe "#query_to_sql" do
32
+
33
+ it "should be nil if no query" do
34
+ @appstats_query.query_to_sql.should == "select 0 as num"
35
+ end
36
+
37
+ it "should be based on query" do
38
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries")
39
+ @appstats_query.query_to_sql.should == @appstats_query.query.query_to_sql
40
+ end
41
+
42
+ end
43
+
44
+ describe "#group_query_to_sql" do
45
+
46
+ it "should be nil if no query" do
47
+ @appstats_query.group_query_to_sql.should == nil
48
+ end
49
+
50
+ it "should be based on query" do
51
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries")
52
+ @appstats_query.group_query_to_sql.should == @appstats_query.query.group_query_to_sql
53
+ end
54
+
55
+ end
56
+
57
+ describe "#process_query" do
58
+
59
+ it "should support nil query" do
60
+ @appstats_query.process_query
61
+ @appstats_query.query_to_sql.should == "select 0 as num"
62
+ @appstats_query.group_query_to_sql.should == nil
63
+ end
64
+
65
+ it "should be case insensitive on action" do
66
+ @appstats_query.query = Appstats::Query.new(:query => "# Appstats_Queries", :query_type => "Appstats::AppstatsQuery")
67
+ @appstats_query.process_query
68
+ @appstats_query.query_to_sql.should == "select COUNT(*) as num from appstats_results"
69
+
70
+ @appstats_query.query = Appstats::Query.new(:query => "# aPpstats_Queries", :query_type => "Appstats::AppstatsQuery")
71
+ @appstats_query.process_query
72
+ @appstats_query.query_to_sql.should == "select COUNT(*) as num from appstats_results"
73
+ end
74
+
75
+ it "should support singular names" do
76
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_query", :query_type => "Appstats::AppstatsQuery")
77
+ @appstats_query.process_query
78
+ @appstats_query.query_to_sql.should == "select COUNT(*) as num from appstats_results"
79
+ end
80
+
81
+ it "should handle nil actions" do
82
+ @appstats_query.query = Appstats::Query.new(:query => "", :query_type => "Appstats::AppstatsQuery")
83
+ @appstats_query.process_query
84
+ @appstats_query.query_to_sql.should == "select 0 as num"
85
+ end
86
+
87
+ it "should call query.run" do
88
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries", :query_type => "Appstats::AppstatsQuery")
89
+ @appstats_query.query.stub!(:run).and_return("call-worked")
90
+ @appstats_query.run.should == "call-worked"
91
+ end
92
+
93
+ # THIS IS A SLOW TEST ONLY TO BE RUN IF THINGS START ACTING STRANGE
94
+ it "should actually execute code properly" do
95
+ Result.create
96
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries", :query_type => "Appstats::AppstatsQuery")
97
+ @appstats_query.run.count.should > 0
98
+ end
99
+
100
+ describe "# appstats_queries" do
101
+
102
+ it "should support #appstats_queries" do
103
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries", :query_type => "Appstats::AppstatsQuery")
104
+ @appstats_query.process_query
105
+ @appstats_query.query_to_sql.should == "select COUNT(*) as num from appstats_results"
106
+ @appstats_query.group_query_to_sql.should == nil
107
+ end
108
+
109
+ it "should support where clause for action, contexts, group_by" do
110
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries where action = abc AND contexts = 'def' || group_by like 'hik'", :query_type => "Appstats::AppstatsQuery")
111
+ @appstats_query.process_query
112
+ @appstats_query.query_to_sql.should == "select COUNT(*) as num from appstats_results where action = 'abc' AND contexts = 'def' or group_by like 'hik'"
113
+ @appstats_query.group_query_to_sql.should == nil
114
+ end
115
+
116
+ it "should support group by action, contexts, group_by" do
117
+ @appstats_query.query = Appstats::Query.new(:query => "# appstats_queries group by action, contexts, group_by", :query_type => "Appstats::AppstatsQuery")
118
+ @appstats_query.process_query
119
+ @appstats_query.query_to_sql.should == "select COUNT(*) as num from appstats_results"
120
+ @appstats_query.group_query_to_sql.should == "select 'action,contexts,group_by' as context_key_filter, concat(ifnull(action,'--'),',',ifnull(contexts,'--'),',',ifnull(group_by,'--')) as context_value_filter, COUNT(*) as num from appstats_results group by context_value_filter"
121
+ end
122
+
123
+ # it "should support group by media,network" do
124
+ # @appstats_query.query = Appstats::Query.new(:query => "# buildings group by media, network", :query_type => "Appstats::AppstatsQuery")
125
+ # @appstats_query.process_query
126
+ # @appstats_query.query_to_sql.should == "select COUNT(DISTINCT operator_accesses.id) as num from operator_accesses left join physical_addresses on physical_addresses.id = operator_accesses.physical_address_id left join operator_networks on operator_networks.id = operator_accesses.operator_network_id left join service_providers on service_providers.id = operator_networks.service_provider_id"
127
+ # @appstats_query.group_query_to_sql.should == "select 'media,network' as context_key_filter, concat(media_types.name,',',operator_networks.name) as context_value_filter, COUNT(*) as num from operator_accesses left join physical_addresses on physical_addresses.id = operator_accesses.physical_address_id left join operator_networks on operator_networks.id = operator_accesses.operator_network_id left join service_providers on service_providers.id = operator_networks.service_provider_id group by context_value_filter"
128
+ # end
129
+
130
+ end
131
+ end
132
+
133
+ describe "#db_connection" do
134
+
135
+ it "should use the extract_env" do
136
+ @appstats_query.query = Appstats::Query.new(:query => "# blahs on blah")
137
+ @appstats_query.db_connection.should == ActiveRecord::Base.connection
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+
144
+ end
@@ -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.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
196
+ entry = Entry.create_from_logger_string("0.20.0 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.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
199
+ entry.raw_entry.should == "0.20.0 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.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
204
+ entry = Entry.create_from_logger_string("0.20.0 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.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
207
+ entry.raw_entry.should == "0.20.0 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.19.7 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb')
217
+ entry = Entry.create_from_logger_string('0.20.0 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.19.7 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
220
+ entry.raw_entry.should == "0.20.0 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.19.7 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb')
231
+ entry = Entry.create_from_logger_string('0.20.0 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.19.7 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
234
+ entry.raw_entry.should == "0.20.0 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"
@@ -122,12 +122,12 @@ module Appstats
122
122
 
123
123
  it "should accept numbers" do
124
124
  Appstats::Logger.entry(5, :blah => 6)
125
- Appstats::Logger.raw_read.should == ["0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
125
+ Appstats::Logger.raw_read.should == ["0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
126
126
  end
127
127
 
128
128
  it "should accept arrays" do
129
129
  Appstats::Logger.entry('search', :provider => [ 'one', 'two' ])
130
- Appstats::Logger.raw_read.should == ["0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
130
+ Appstats::Logger.raw_read.should == ["0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
131
131
  end
132
132
 
133
133
 
@@ -137,7 +137,7 @@ module Appstats
137
137
 
138
138
  it "should look similar to regular entry" do
139
139
  Appstats::Logger.exception_entry(RuntimeError.new("blah"),:on => "login")
140
- Appstats::Logger.raw_read.should == ["0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
140
+ Appstats::Logger.raw_read.should == ["0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
141
141
  end
142
142
 
143
143
  end
@@ -154,47 +154,47 @@ module Appstats
154
154
 
155
155
  it "should handle a statistics entry" do
156
156
  expected = { :action => "address_search", :timestamp => "2010-09-21 23:15:20" }
157
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
157
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
158
158
  actual.should == expected
159
159
  end
160
160
 
161
161
  it "should handle contexts" do
162
162
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
163
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
163
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
164
164
  actual.should == expected
165
165
  end
166
166
 
167
167
  it "should handle multiple actions" do
168
168
  expected = { :action => ["address_filter", "blah"], :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
169
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
169
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
170
170
  actual.should == expected
171
171
  end
172
172
 
173
173
  it "should handle multiple of same context" do
174
174
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => ['Sin','Market'] }
175
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
175
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
176
176
  actual.should == expected
177
177
  end
178
178
 
179
179
  it "should handle no actions" do
180
180
  expected = { :action => "UNKNOWN_ACTION", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
181
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
181
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
182
182
  actual.should == expected
183
183
  end
184
184
 
185
185
  it "should handle actions with the delimiter (and change the delimiter)" do
186
186
  expected = { :action => "address:=search-n", :timestamp => "2010-09-21 23:15:20" }
187
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
187
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
188
188
  actual.should == expected
189
189
 
190
190
  expected = { :action => "address::search==--n", :timestamp => "2010-09-21 23:15:20" }
191
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
191
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
192
192
  actual.should == expected
193
193
  end
194
194
 
195
195
  it "should handle contexts with the delimiter (and change the delimiter)" do
196
196
  expected = { :action => "address", :timestamp => "2010-09-21 23:15:20", :server => "market:eval=-n" }
197
- actual = Appstats::Logger.entry_to_hash("0.19.7 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
197
+ actual = Appstats::Logger.entry_to_hash("0.20.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
198
198
  actual.should == expected
199
199
  end
200
200
 
@@ -203,66 +203,66 @@ module Appstats
203
203
  describe "#entry_to_s" do
204
204
 
205
205
  it "should handle a statistics entry" do
206
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
206
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
207
207
  actual = Appstats::Logger.entry_to_s("address_search")
208
208
  actual.should == expected
209
209
  end
210
210
 
211
211
  it "should handle numbers" do
212
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
212
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
213
213
  actual = Appstats::Logger.entry_to_s(1,:note => 2.2)
214
214
  actual.should == expected
215
215
  end
216
216
 
217
217
  it "should handle default contexts" do
218
218
  Appstats::Logger.default_contexts[:app_name] = "market"
219
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
219
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
220
220
  actual = Appstats::Logger.entry_to_s("address_search")
221
221
  actual.should == expected
222
222
  end
223
223
 
224
224
  it "should handle contexts (and sort them by symbol)" do
225
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
225
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
226
226
  actual = Appstats::Logger.entry_to_s("address_filter", { :server => "Live", :app_name => 'Market' })
227
227
  actual.should == expected
228
228
  end
229
229
 
230
230
  it "should handle actions with the delimiter (and change the delimiter)" do
231
- expected = "0.19.7 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
231
+ expected = "0.20.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
232
232
  actual = Appstats::Logger.entry_to_s("address:=search-n")
233
233
  actual.should == expected
234
234
 
235
- expected = "0.19.7 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
235
+ expected = "0.20.0 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
236
236
  actual = Appstats::Logger.entry_to_s("address::search==--n")
237
237
  actual.should == expected
238
238
  end
239
239
 
240
240
  it "should handle contexts with the delimiter (and change the delimiter)" do
241
- expected = "0.19.7 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
241
+ expected = "0.20.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
242
242
  actual = Appstats::Logger.entry_to_s("address", :server => 'market:eval=-n')
243
243
  actual.should == expected
244
244
  end
245
245
 
246
246
  it "should ignore spaces" do
247
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
247
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
248
248
  actual = Appstats::Logger.entry_to_s("address search")
249
249
  actual.should == expected
250
250
  end
251
251
 
252
252
  it "should convert newlines in action" do
253
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
253
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
254
254
  actual = Appstats::Logger.entry_to_s("address_\nsearch")
255
255
  actual.should == expected
256
256
  end
257
257
 
258
258
  it "should convert newlines in context" do
259
- expected = "0.19.7 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
259
+ expected = "0.20.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
260
260
  actual = Appstats::Logger.entry_to_s("address_search",:blah => "some\nlong\nstatement")
261
261
  actual.should == expected
262
262
  end
263
263
 
264
264
  it "should convert newlines based on the delimiter" do
265
- expected = "0.19.7 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
265
+ expected = "0.20.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
266
266
  actual = Appstats::Logger.entry_to_s("address:=\nsearch-n")
267
267
  actual.should == expected
268
268
  end
@@ -8,153 +8,153 @@ module Appstats
8
8
  end
9
9
 
10
10
  describe("#initialize") do
11
-
12
- it "should set rules to nil" do
13
- @parser.raw_rules.should == nil
14
- @parser.raw_tokenize.should == nil
15
- @parser.repeating.should == false
16
- @parser.tokenize_regex == nil
17
- @parser.rules.should == []
18
- @parser.tokenize.should == []
19
- @parser.constants.should == []
20
- @parser.constants_no_spaces.should == []
21
- end
22
-
23
- it "should set rules from constructor" do
24
- parser = Parser.new(:rules => ":name or :bust", :tokenize => "a bb c", :repeating => true)
25
- parser.raw_rules.should == ":name or :bust"
26
- parser.raw_tokenize.should == "a bb c"
27
- parser.repeating.should == true
28
- parser.rules.should == [ { :rule => :name, :stop => :constant }, "OR", { :rule => :bust, :stop => :end} ]
29
- parser.tokenize.should == ["\\s+A","\\s+BB","\\s+C"]
30
- parser.tokenize_no_spaces.should == ["A","BB","C"]
31
- parser.constants.should == ["\\s+OR"]
32
- parser.constants_no_spaces.should == ["OR"]
33
- end
34
-
35
- it "should espace tokens as required" do
36
- parser = Parser.new(:tokenize => "( ) abc |")
37
- parser.tokenize.should == ['\(','\)','\s+ABC','\|']
38
- parser.tokenize_regex.should == '\(|\)|\s+ABC|\|'
39
- parser.tokenize_no_spaces.should == ['\(','\)','ABC','\|']
40
- parser.tokenize_regex_no_spaces.should == '\(|\)|ABC|\|'
41
- end
42
-
43
- end
11
+
12
+ it "should set rules to nil" do
13
+ @parser.raw_rules.should == nil
14
+ @parser.raw_tokenize.should == nil
15
+ @parser.repeating.should == false
16
+ @parser.tokenize_regex == nil
17
+ @parser.rules.should == []
18
+ @parser.tokenize.should == []
19
+ @parser.constants.should == []
20
+ @parser.constants_no_spaces.should == []
21
+ end
22
+
23
+ it "should set rules from constructor" do
24
+ parser = Parser.new(:rules => ":name or :bust", :tokenize => "a bb c", :repeating => true)
25
+ parser.raw_rules.should == ":name or :bust"
26
+ parser.raw_tokenize.should == "a bb c"
27
+ parser.repeating.should == true
28
+ parser.rules.should == [ { :rule => :name, :stop => :constant }, "OR", { :rule => :bust, :stop => :end} ]
29
+ parser.tokenize.should == ["\\s+A(\\s|$)","\\s+BB(\\s|$)","\\s+C(\\s|$)"]
30
+ parser.tokenize_no_spaces.should == ["A","BB","C"]
31
+ parser.constants.should == ["\\s+OR(\\s|$)"]
32
+ parser.constants_no_spaces.should == ["OR"]
33
+ end
44
34
 
35
+ it "should espace tokens as required" do
36
+ parser = Parser.new(:tokenize => "( ) abc |")
37
+ parser.tokenize.should == ['\(','\)','\s+ABC(\s|$)','\|']
38
+ parser.tokenize_regex.should == '\(|\)|\s+ABC(\s|$)|\|'
39
+ parser.tokenize_no_spaces.should == ['\(','\)','ABC','\|']
40
+ parser.tokenize_regex_no_spaces.should == '\(|\)|ABC|\|'
41
+ end
45
42
 
46
- describe "#rules" do
47
-
48
- it "should end on constant if tokens present" do
49
- Parser.new(:rules => ":name", :tokenize => ")").rules.should == [ { :rule => :name, :stop => :end } ]
50
- end
51
-
43
+ end
52
44
 
53
- it "should handle one variable" do
54
- Parser.new(:rules => ":name").rules.should == [ { :rule => :name, :stop => :end } ]
55
- end
56
-
57
- it "should handle many variables" do
58
- Parser.new(:rules => ":name :date").rules.should == [ { :rule => :name, :stop => :space }, { :rule => :date, :stop => :end } ]
59
- end
60
-
61
- it "should deal with colons" do
62
- Parser.new(:rules => ":name : :date").rules.should == [ { :rule => :name, :stop => :constant }, ":", { :rule => :date, :stop => :end } ]
63
- end
64
-
65
- it "should deal with constant" do
66
- Parser.new(:rules => "blah").rules.should == ["BLAH"]
67
- end
68
-
69
- it "should deal with constant and variables" do
70
- Parser.new(:rules => ":name blah :date").rules.should == [ { :rule => :name, :stop => :constant }, "BLAH", { :rule => :date, :stop => :end } ]
71
- end
72
-
73
- it "should deal with multiple constants and variables" do
74
- Parser.new(:rules => ":name blah more blah :date").rules.should == [ { :rule => :name, :stop => :constant }, "BLAH", "MORE", "BLAH", { :rule => :date, :stop => :end } ]
75
- end
76
45
 
77
- end
46
+ describe "#rules" do
78
47
 
79
- describe "#constants" do
80
-
81
- it "should be empty if only variables" do
82
- Parser.new(:rules => ":name :blah").constants.should == [ ]
83
- end
84
-
85
- it "should track all constants" do
86
- Parser.new(:rules => ":name : :date").constants.should == [ ":" ]
87
- end
88
-
89
- it "should upper case constants" do
90
- Parser.new(:rules => "blah").constants.should == ["\\s+BLAH"]
91
- end
92
-
93
- it "should deal with multiple constants" do
94
- Parser.new(:rules => ":name = :blah and :moreblah").constants.should == ["=","\\s+AND"]
95
- end
96
-
97
- end
98
-
99
- describe "#constants_no_spaces" do
48
+ it "should end on constant if tokens present" do
49
+ Parser.new(:rules => ":name", :tokenize => ")").rules.should == [ { :rule => :name, :stop => :end } ]
50
+ end
51
+
52
+
53
+ it "should handle one variable" do
54
+ Parser.new(:rules => ":name").rules.should == [ { :rule => :name, :stop => :end } ]
55
+ end
56
+
57
+ it "should handle many variables" do
58
+ Parser.new(:rules => ":name :date").rules.should == [ { :rule => :name, :stop => :space }, { :rule => :date, :stop => :end } ]
59
+ end
60
+
61
+ it "should deal with colons" do
62
+ Parser.new(:rules => ":name : :date").rules.should == [ { :rule => :name, :stop => :constant }, ":", { :rule => :date, :stop => :end } ]
63
+ end
64
+
65
+ it "should deal with constant" do
66
+ Parser.new(:rules => "blah").rules.should == ["BLAH"]
67
+ end
68
+
69
+ it "should deal with constant and variables" do
70
+ Parser.new(:rules => ":name blah :date").rules.should == [ { :rule => :name, :stop => :constant }, "BLAH", { :rule => :date, :stop => :end } ]
71
+ end
72
+
73
+ it "should deal with multiple constants and variables" do
74
+ Parser.new(:rules => ":name blah more blah :date").rules.should == [ { :rule => :name, :stop => :constant }, "BLAH", "MORE", "BLAH", { :rule => :date, :stop => :end } ]
75
+ end
76
+
77
+ end
100
78
 
101
- it "should be empty if only variables" do
102
- Parser.new(:rules => ":name :blah").constants_no_spaces.should == [ ]
103
- end
104
-
105
- it "should track all constants" do
106
- Parser.new(:rules => ":name : :date").constants_no_spaces.should == [ ":" ]
107
- end
108
-
109
- it "should upper case constants" do
110
- Parser.new(:rules => "blah").constants_no_spaces.should == ["BLAH"]
111
- end
112
-
113
- it "should deal with multiple constants" do
114
- Parser.new(:rules => ":name = :blah and :moreblah").constants_no_spaces.should == ["=","AND"]
115
- end
116
-
117
- end
79
+ describe "#constants" do
80
+
81
+ it "should be empty if only variables" do
82
+ Parser.new(:rules => ":name :blah").constants.should == [ ]
83
+ end
118
84
 
119
- describe "#parse_constant" do
120
-
121
- it "should handle nil" do
122
- Parser.parse_constant(nil,nil).should == [nil,nil]
123
- Parser.parse_constant("",nil).should == [nil,nil]
124
- end
125
-
126
- it "should find the constant" do
127
- Parser.parse_constant("= blah blah more blah ","=").should == ["=","blah blah more blah"]
128
- end
129
-
130
- it "should find the constants with multiple characters" do
131
- Parser.parse_constant("hey blah blah more blah ","hey").should == ["hey","blah blah more blah"]
132
- end
133
-
134
- it "should return nil if not found" do
135
- Parser.parse_constant("blah blah more blah ","=").should == [nil,"blah blah more blah"]
136
- end
137
-
138
- it "should be case insensitive" do
139
- Parser.parse_constant(" blah stuff on more blah stuff ","blah").should == ["blah","stuff on more blah stuff"]
140
- Parser.parse_constant(" BLAH stuff on more blah stuff ","blah").should == ["BLAH","stuff on more blah stuff"]
141
- Parser.parse_constant(" blah stuff on more blah stuff ","BLAH").should == ["blah","stuff on more blah stuff"]
142
- end
143
-
144
- it "should only find the first instance" do
145
- Parser.parse_constant("one == two","==").should == [nil,"one == two"]
146
- end
85
+ it "should track all constants" do
86
+ Parser.new(:rules => ":name : :date").constants.should == [ ":" ]
87
+ end
88
+
89
+ it "should upper case constants" do
90
+ Parser.new(:rules => "blah").constants.should == ["\\s+BLAH(\\s|$)"]
91
+ end
92
+
93
+ it "should deal with multiple constants" do
94
+ Parser.new(:rules => ":name = :blah and :moreblah").constants.should == ["=","\\s+AND(\\s|$)"]
95
+ end
96
+
97
+ end
98
+
99
+ describe "#constants_no_spaces" do
100
+
101
+ it "should be empty if only variables" do
102
+ Parser.new(:rules => ":name :blah").constants_no_spaces.should == [ ]
103
+ end
104
+
105
+ it "should track all constants" do
106
+ Parser.new(:rules => ":name : :date").constants_no_spaces.should == [ ":" ]
107
+ end
108
+
109
+ it "should upper case constants" do
110
+ Parser.new(:rules => "blah").constants_no_spaces.should == ["BLAH"]
111
+ end
112
+
113
+ it "should deal with multiple constants" do
114
+ Parser.new(:rules => ":name = :blah and :moreblah").constants_no_spaces.should == ["=","AND"]
115
+ end
116
+
117
+ end
147
118
 
148
- end
119
+ describe "#parse_constant" do
120
+
121
+ it "should handle nil" do
122
+ Parser.parse_constant(nil,nil).should == [nil,nil]
123
+ Parser.parse_constant("",nil).should == [nil,nil]
124
+ end
125
+
126
+ it "should find the constant" do
127
+ Parser.parse_constant("= blah blah more blah ","=").should == ["=","blah blah more blah"]
128
+ end
129
+
130
+ it "should find the constants with multiple characters" do
131
+ Parser.parse_constant("hey blah blah more blah ","hey").should == ["hey","blah blah more blah"]
132
+ end
133
+
134
+ it "should return nil if not found" do
135
+ Parser.parse_constant("blah blah more blah ","=").should == [nil,"blah blah more blah"]
136
+ end
137
+
138
+ it "should be case insensitive" do
139
+ Parser.parse_constant(" blah stuff on more blah stuff ","blah").should == ["blah","stuff on more blah stuff"]
140
+ Parser.parse_constant(" BLAH stuff on more blah stuff ","blah").should == ["BLAH","stuff on more blah stuff"]
141
+ Parser.parse_constant(" blah stuff on more blah stuff ","BLAH").should == ["blah","stuff on more blah stuff"]
142
+ end
149
143
 
150
- describe "#parse_word" do
144
+ it "should only find the first instance" do
145
+ Parser.parse_constant("one == two","==").should == [nil,"one == two"]
146
+ end
147
+
148
+ end
151
149
 
152
- it "should handle nil" do
153
- @parser.parse_word(nil,nil).should == [nil,nil]
154
- @parser.parse_word("",nil).should == [nil,nil]
155
- end
156
-
157
- it "should look for global tokens" do
150
+ describe "#parse_word" do
151
+
152
+ it "should handle nil" do
153
+ @parser.parse_word(nil,nil).should == [nil,nil]
154
+ @parser.parse_word("",nil).should == [nil,nil]
155
+ end
156
+
157
+ it "should look for global tokens" do
158
158
  parser = Parser.new(:tokenize => "xx")
159
159
  parser.parse_word("blah xx",:end).should == ["blah","xx"]
160
160
  parser.parse_word("blah xx stop","stop").should == ["blah","xx stop"]
@@ -259,6 +259,29 @@ module Appstats
259
259
 
260
260
  end
261
261
 
262
+ describe "#alpha?" do
263
+
264
+ it "should be false for nil" do
265
+ Parser.alpha?(nil).should == false
266
+ end
267
+
268
+ it "should be false for empty string" do
269
+ Parser.alpha?('').should == false
270
+ end
271
+
272
+ it "should be false for non alpha string" do
273
+ Parser.alpha?('1abc').should == false
274
+ Parser.alpha?('abc2').should == false
275
+ Parser.alpha?('abc2def').should == false
276
+ end
277
+
278
+ it "should be true for alpha string" do
279
+ Parser.alpha?('a').should == true
280
+ Parser.alpha?('abc').should == true
281
+ end
282
+
283
+ end
284
+
262
285
  describe "#parse" do
263
286
 
264
287
 
@@ -339,6 +362,12 @@ module Appstats
339
362
  parser.raw_results.should == [ "(", { :one => "blaa"}, "aa", "a1", { :two => "bla1"}, ")" ]
340
363
  end
341
364
 
365
+ it "should handle alpha constants as requiring spaces" do
366
+ parser = Appstats::Parser.new(:rules => ":one group :two")
367
+ parser.parse("group_by group aha")
368
+ parser.raw_results.should == [ { :one => "group_by"}, "group", { :two => "aha"} ]
369
+ end
370
+
342
371
 
343
372
  describe "real examples" do
344
373
 
@@ -367,6 +396,13 @@ module Appstats
367
396
  parser.parse("# buyer-address-lookup last month").should == true
368
397
  parser.raw_results.should == [{:operation=>"#"}, {:action=>"buyer-address-lookup"}, {:host=>nil}, {:contexts=>nil}, {:date=>"last month"}]
369
398
  end
399
+
400
+ it "should handle group_by" do
401
+ parser = Appstats::Parser.new(:rules => ":operation :action :date on :host where :contexts group by :group_by")
402
+ parser.parse("# appstats_queries where action = abc AND contexts = 'def' || group_by like 'hik'").should == true
403
+ parser.results.should == {:operation => "#", :action => "appstats_queries", :date => nil, :host => nil, :group_by => nil, :contexts => "action = abc AND contexts = 'def' || group_by like 'hik'" }
404
+ end
405
+
370
406
 
371
407
  end
372
408
 
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: 93
4
+ hash: 79
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 19
9
- - 7
10
- version: 0.19.7
8
+ - 20
9
+ - 0
10
+ version: 0.20.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Forward
@@ -181,10 +181,13 @@ files:
181
181
  - db/migrations/20110311214833_add_appstats_results_db_connection.rb
182
182
  - db/migrations/20110318203339_add_appstats_results_latest_flag.rb
183
183
  - db/migrations/20110321154125_add_appstats_results_query_duration_in_seconds.rb
184
+ - db/migrations/20110330171745_create_appstats_action_contexts.rb
184
185
  - db/schema.rb
185
186
  - lib/appstats.rb
186
187
  - lib/appstats/action.rb
188
+ - lib/appstats/action_context_key.rb
187
189
  - lib/appstats/acts_as_appstatsable.rb
190
+ - lib/appstats/appstats_query.rb
188
191
  - lib/appstats/ci.rake
189
192
  - lib/appstats/code_injections.rb
190
193
  - lib/appstats/context.rb
@@ -227,8 +230,10 @@ files:
227
230
  - script/console
228
231
  - script/destroy
229
232
  - script/generate
233
+ - spec/action_context_key_spec.rb
230
234
  - spec/action_spec.rb
231
235
  - spec/acts_as_appstatsble_spec.rb
236
+ - spec/appstats_query_spec.rb
232
237
  - spec/appstats_spec.rb
233
238
  - spec/context_key_spec.rb
234
239
  - spec/context_spec.rb
@@ -282,8 +287,10 @@ signing_key:
282
287
  specification_version: 3
283
288
  summary: Provide usage statistics about how your application is being used
284
289
  test_files:
290
+ - spec/action_context_key_spec.rb
285
291
  - spec/action_spec.rb
286
292
  - spec/acts_as_appstatsble_spec.rb
293
+ - spec/appstats_query_spec.rb
287
294
  - spec/appstats_spec.rb
288
295
  - spec/context_key_spec.rb
289
296
  - spec/context_spec.rb