mixpanel_test_service 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,152 @@
1
+ module MixpanelTest
2
+
3
+ class Analysis
4
+
5
+ def initialize(options = {})
6
+
7
+ @events_count = {}
8
+ @events_properties_counts = {}
9
+ @events_properties_values_counts = {}
10
+ @properties_counts = {}
11
+ @properties_values_counts = {}
12
+ @super_properties_counts = {}
13
+ @super_properties_values_counts = {}
14
+
15
+ end
16
+
17
+ def initialize_for_event(ev)
18
+
19
+ name = ev["event"]
20
+
21
+ initialize_for_event_property_list(name, ev["properties"].keys)
22
+
23
+ ev["properties"].each do |k, v|
24
+
25
+ # Initialize property counters
26
+ @events_properties_values_counts[name][k][v] ||= 0
27
+ @properties_values_counts[k][v] ||= 0
28
+
29
+ end
30
+
31
+ end
32
+
33
+ def initialize_for_event_property_list(name, props)
34
+
35
+ # Initialize counters
36
+ @events_count[name] ||= 0
37
+ @events_properties_counts[name] ||= {}
38
+ @events_properties_values_counts[name] ||= {}
39
+
40
+ props.each do |k|
41
+
42
+ # Initialize property counters
43
+ @events_properties_counts[name][k] ||= 0
44
+ @events_properties_values_counts[name][k] ||= {}
45
+ @properties_counts[k] ||= 0
46
+ @properties_values_counts[k] ||= {}
47
+
48
+ end
49
+
50
+ end
51
+
52
+ def add_documentation_object(obj)
53
+ # Each event and property counts for an undefined number > 0.
54
+ # Discard notes
55
+ # Only useful for merging two documentation objects
56
+
57
+ obj["events"].each do |name, props|
58
+
59
+ initialize_for_event_property_list(name, props)
60
+ @events_count[name] += 1
61
+
62
+ props.each do |p_name|
63
+ @events_properties_counts[name][p_name] += 1
64
+ @properies_count[p_name] += 1
65
+ end
66
+
67
+ end
68
+
69
+ obj["properties"].each do |p|
70
+ @properties_count[p["name"]] ||= 0
71
+ @properties_count[p["name"]] += 1
72
+
73
+ p["values"].each do |v|
74
+ @properties_values_count[p["name"]][v] ||= 0
75
+ @properties_values_count[p["name"]][v] += 1
76
+ end
77
+ end
78
+ end
79
+
80
+ def add_events(arr)
81
+ arr.each do |ev| add_event(ev) end
82
+ end
83
+
84
+ def add_event(ev)
85
+
86
+ initialize_for_event(ev)
87
+ name = ev["event"]
88
+
89
+ ev["properties"].each do |k, v|
90
+
91
+ # Increment property counters
92
+ @properties_counts[k] += 1
93
+ @events_properties_counts[name][k] += 1
94
+ @events_properties_values_counts[name][k][v] += 1
95
+ @properties_values_counts[k][v] += 1
96
+
97
+ end
98
+
99
+ end
100
+
101
+ def format_verbose
102
+
103
+ puts "Mixpanel events caught:"
104
+ pp @events_count
105
+
106
+ puts "Mixpanel properties caught for each event:"
107
+ pp @events_properties_counts
108
+
109
+ puts "All Mixpanel properties caught:"
110
+ pp @properties_counts
111
+
112
+ puts "Mixpanel values frequency by property:"
113
+ pp @properties_values_counts
114
+
115
+ puts "Mixpanel values frequency by property and event:"
116
+ pp @events_properties_values_counts
117
+
118
+ end
119
+
120
+ def format_documentation
121
+
122
+ pp documentation_object
123
+
124
+ end
125
+
126
+ def documentation_object
127
+ default_notes = "Undocumented"
128
+ {
129
+ "events" => @events_count.keys.map do |k|
130
+ {
131
+ k => {
132
+ "notes" => default_notes,
133
+ "properties" => @events_properties_counts[k].keys
134
+ }
135
+ }
136
+ end,
137
+ "properties" => @properties_counts.keys.map do |k|
138
+ {
139
+ "name" => k,
140
+ "notes" => default_notes,
141
+ "values" => @properties_values_counts[k].keys
142
+ }
143
+ end
144
+ }
145
+
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+
@@ -0,0 +1,55 @@
1
+ require 'base64'
2
+ require 'uri'
3
+ require 'json'
4
+
5
+ module MixpanelTest
6
+
7
+ class Parser
8
+
9
+ module InstanceMethods
10
+
11
+ # Extract the query parameters as a hash from the query string
12
+ def parse_query_params(qs)
13
+ qs.to_s.split('&').map do |s| s.split('=') end.map do |a| {URI.unescape(a[0]) => URI.unescape(a[1])} end.inject(&:merge) || {}
14
+ end
15
+
16
+ # Decode the data string.
17
+ def decode_data(encoded_data)
18
+
19
+ # Decode the data
20
+ data = Base64.decode64(encoded_data)
21
+
22
+ # Eliminate extemporaneous chars outside the JSON
23
+ data = data.match(/\{.*\}/)[0]
24
+
25
+ # Parse with JSON
26
+ data = JSON.parse(data)
27
+
28
+ end
29
+
30
+ def decode_cookie(cookie)
31
+
32
+ #begin
33
+ # split cookie and find a mixpanel section
34
+ section = cookie.split('; ').find do |tok| tok.match(/^mp_/) end;
35
+
36
+ # Decode and find json
37
+ data = URI.unescape(section).match(/\{.*\}/)[0]
38
+
39
+ # Parse as JSON
40
+ JSON.parse(data)
41
+
42
+ #rescue
43
+
44
+ # raise BadCookieError, but first, figure out how to test this functionality
45
+
46
+ #end
47
+ end
48
+
49
+ end
50
+
51
+ extend InstanceMethods
52
+
53
+ end
54
+
55
+ end
@@ -1,16 +1,21 @@
1
1
  require 'rubygems'
2
2
  require 'net/http/server'
3
+ require File.expand_path('../parser', __FILE__)
4
+ require File.expand_path('../analysis', __FILE__)
3
5
  require 'thread'
4
- require 'base64'
5
6
  require 'json'
6
7
  require 'net/http'
7
8
 
8
9
  module MixpanelTest
9
10
  class Service
11
+ class PathNotFoundError < StandardError ; end
12
+ class NoDataError < StandardError ; end
10
13
 
11
- attr_accessor :events # The live queue of received events
14
+ include MixpanelTest::Parser::InstanceMethods
15
+
16
+ attr_accessor :events, :people # The live queue of received events
12
17
  attr_writer :log_events # Whether to log all events
13
- attr_reader :all_events # Log of all events
18
+ attr_reader :all_events, :all_people, :all_imported_events # Log of all events
14
19
 
15
20
  @@js_headers = {'Connection' => "keep-alive", "Content-Type" => "application/x-javascript", "Transfer-Encoding" => "chunked", 'Cache-Control' => 'max-age=86400'}
16
21
  @@api_headers = {
@@ -29,23 +34,28 @@ module MixpanelTest
29
34
  end
30
35
  end
31
36
 
32
- def shutdown
33
- @server.shutdown
34
- end
35
-
36
- def stopped?
37
- @server.stopped?
38
- end
39
-
40
37
  def stop
38
+ puts "Stopping Mixpanel test service"
41
39
  @server.stop
40
+ Thread.pass until @server.stopped?
41
+ puts "Mixpanel test server stopped"
42
+ end
43
+
44
+ def analysis
45
+ @analysis ||= Analysis.new
46
+ @analysis.add_events(@all_events)
47
+ @analysis
42
48
  end
43
49
 
44
50
  def initialize(options={})
45
51
 
46
52
  @events = []
53
+ @people = []
47
54
  @all_events = []
55
+ @all_people = []
56
+ @all_imported_events = []
48
57
  @log_events = options[:log_events]
58
+ @log_people = options[:log_people]
49
59
  @events_mutex = Mutex.new
50
60
 
51
61
  @mixpanel_js_cache = {}
@@ -65,29 +75,35 @@ module MixpanelTest
65
75
  else
66
76
 
67
77
  # Parse the query string
68
- query_params = req[:uri][:query].to_s.split('&').map do |s| s.split('=') end.map do |a| {a[0] => a[1]} end.inject(&:merge) || {}
69
-
78
+ query_params = parse_query_params(req[:uri][:query])
70
79
 
71
80
  if query_params["data"]
72
-
73
- # Decode the data
74
- data = Base64.decode64(URI.unescape(query_params["data"]))
75
-
76
- # Eliminate extemporaneous chars outside the JSON
77
- data = data.match(/\{.*\}/)[0]
78
-
79
- # Parse with JSON
80
- data = JSON.parse(data)
81
-
82
- # Save
83
- transaction do
84
- @events << data
81
+ data = decode_data(query_params["data"])
82
+
83
+ if req[:uri][:path].to_s.match(/engage/)
84
+
85
+ # Save
86
+ transaction do
87
+ @people << data
88
+ @all_people << data if @log_people
89
+ end
90
+ elsif req[:uri][:path].to_s.match(/track/)
91
+ # Save
92
+
93
+ transaction do
94
+ @events << data
95
+ @all_events << data if @log_events
96
+ end
97
+ elsif req[:uri][:path].to_s.match(/import/)
98
+ transaction do
99
+ @all_imported_events << data
100
+ end
101
+ else
102
+ raise PathNotFoundError
85
103
  end
86
104
 
87
- @all_events << data if @log_events
88
-
89
105
  else
90
- # puts "No data. #{req[:uri].inspect}"
106
+ raise NoDataError
91
107
  end
92
108
 
93
109
  next [200, @@api_headers, ["1"]]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixpanel_test_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-09-05 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-http-server
16
- requirement: &10922000 !ruby/object:Gem::Requirement
16
+ requirement: &9783660 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.2.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *10922000
24
+ version_requirements: *9783660
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: pry
27
- requirement: &10894080 !ruby/object:Gem::Requirement
27
+ requirement: &9778460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *10894080
35
+ version_requirements: *9778460
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &10892700 !ruby/object:Gem::Requirement
38
+ requirement: &9749500 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *10892700
46
+ version_requirements: *9749500
47
47
  description: Mixpanel test service - logs all Mixpanel events sent to it
48
48
  email: a.johncant@gmail.com
49
49
  executables: []
@@ -51,6 +51,8 @@ extensions: []
51
51
  extra_rdoc_files: []
52
52
  files:
53
53
  - test/server.rb
54
+ - lib/mixpanel_test/parser.rb
55
+ - lib/mixpanel_test/analysis.rb
54
56
  - lib/mixpanel_test/service.rb
55
57
  - lib/mixpanel_test.rb
56
58
  homepage: https://github.com/johncant/mixpanel_test_service