snowplow-tracker 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MTZkNTg1MGZiZTIyNzY0NmY4ZTk2ZDYxMjVkMTU3ZmJkZDllODlkMA==
4
+ ZjRhYzM4NmY5ZjI3ZWNkZDY0MGJkNDRhMWRiZGU0N2I0YjhkMDU3Yg==
5
5
  data.tar.gz: !binary |-
6
- YTQ5ZDhhYTFiNmJlODI4YTMyNTg1YWIwODQ3ZWJmMzNkZDk4MmE1YQ==
6
+ MTVkNjQxNDU2OWRhZWU2MDc5YjRkMmNhNTg5NmVlNjU4YTE1MzY2OA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODhmY2ZmMmNjMTA2MzNmZTg2OGEzNDRhODVkZjc3YjY0NGI5NzAyZjUwNjc2
10
- MDFmYzZhYjNmZjg4ZmIwZTA4MmFlOTI5NmZlODljYjAwNWQ1OGVlZGFmOTFl
11
- ZjhhOTVjNGE3NzY2ZTViMjE2OTI0YmUzYTg1Zjg2OWJkZWJkNjU=
9
+ YzM1MTc1Y2E0ZGQ1ZjY3NzljZDcwNDdjYWUzYjM4Y2MzMTQ1MTE4ODUwYjk0
10
+ NzIxZGQ1NjY1MDAzY2IzZTljN2M4ZWM0NmEwMTZmNzllZWY0NzYzOGMyNDMz
11
+ ODZlNjY4NDYyZDlhY2ZmNGMyZDQ1M2YwMDYwOGIxYTEwMDU2NTI=
12
12
  data.tar.gz: !binary |-
13
- Y2UyMTIwOWRhNWYxNTkxZTAxYjgxMTFhMjMzMWMxYjc0MDYyNTNkMTZiYmNk
14
- MGU2MjQ0MzU2ODAyNGZhZjk0YmIxYTNhOWI5MjhhNzFmNGYyMTdmZGM4Mzlh
15
- OTg4MDUyZTNiY2NmN2Q1MjZjNmEwMGM0MDQ1YTQ3MWEyMzJkM2Q=
13
+ MDMxMzZjYTQxNWU3NDhhYzUwZjJhNjkwNGI4MTk2ZTI1YzBmMjE1MDEzNWZj
14
+ MTY5OGU5ZWE1MTExYmQ0YWRhMmFiNjA5MzgxNDhlNDg4NzEyYWNlMTQ1ZTU4
15
+ NWE5MTkxNjg1NDUxZTU0ZjgyZGE1NjFmNWU1ODExNDZkZGY5ZDA=
@@ -13,6 +13,9 @@
13
13
  # Copyright:: Copyright (c) 2013-2014 Snowplow Analytics Ltd
14
14
  # License:: Apache License Version 2.0
15
15
 
16
+ require 'snowplow-tracker/contracts.rb'
16
17
  require 'snowplow-tracker/version.rb'
17
18
  require 'snowplow-tracker/payload.rb'
19
+ require 'snowplow-tracker/subject.rb'
20
+ require 'snowplow-tracker/emitters.rb'
18
21
  require 'snowplow-tracker/tracker.rb'
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2013-2014 Snowplow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean, Fred Blundun (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2013-2014 Snowplow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ require 'contracts'
17
+ include Contracts
18
+
19
+ module SnowplowTracker
20
+
21
+ ORIGINAL_FAILURE_CALLBACK = Contract.method(:failure_callback)
22
+
23
+ def self.disable_contracts
24
+ Contract.define_singleton_method(:failure_callback) {|data| true}
25
+ end
26
+
27
+ def self.enable_contracts
28
+ Contract.define_singleton_method(:failure_callback, ORIGINAL_FAILURE_CALLBACK)
29
+ end
30
+ end
@@ -0,0 +1,218 @@
1
+ # Copyright (c) 2013-2014 Snowplow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean, Fred Blundun (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2013-2014 Snowplow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ require 'net/http'
17
+ require 'set'
18
+ require 'logger'
19
+ require 'contracts'
20
+ include Contracts
21
+
22
+ module SnowplowTracker
23
+
24
+ LOGGER = Logger.new(STDERR)
25
+ LOGGER.level = Logger::INFO
26
+
27
+ class Emitter
28
+
29
+ @@ConfigHash = ({
30
+ :protocol => Maybe[Or['http', 'https']],
31
+ :port => Maybe[Num],
32
+ :method => Maybe[Or['get', 'post']],
33
+ :buffer_size => Maybe[Num],
34
+ :on_success => Maybe[Func[Num => Any]],
35
+ :on_failure => Maybe[Func[Num, Hash => Any]]
36
+ })
37
+
38
+ @@StrictConfigHash = And[@@ConfigHash, lambda { |x|
39
+ x.class == Hash and Set.new(x.keys).subset? Set.new(@@ConfigHash.keys)
40
+ }]
41
+
42
+ @@DefaultConfig = {
43
+ :protocol => 'http',
44
+ :method => 'get'
45
+ }
46
+
47
+ Contract String, @@StrictConfigHash => lambda { |x| x.is_a? Emitter }
48
+ def initialize(endpoint, config={})
49
+ config = @@DefaultConfig.merge(config)
50
+ @collector_uri = as_collector_uri(endpoint, config[:protocol], config[:port], config[:method])
51
+ @buffer = []
52
+ if not config[:buffer_size].nil?
53
+ @buffer_size = config[:buffer_size]
54
+ elsif config[:method] == 'get'
55
+ @buffer_size = 0
56
+ else
57
+ @buffer_size = 10
58
+ end
59
+ @method = config[:method]
60
+ @on_success = config[:on_success]
61
+ @on_failure = config[:on_failure]
62
+ @threads = []
63
+ LOGGER.info("#{self.class} initialized with endpoint #{@collector_uri}")
64
+
65
+ self
66
+ end
67
+
68
+ # Build the collector URI from the configuration hash
69
+ #
70
+ Contract String, String, Maybe[Num], String => String
71
+ def as_collector_uri(endpoint, protocol, port, method)
72
+ port_string = port == nil ? '' : ":#{port.to_s}"
73
+ path = method == 'get' ? '/i' : '/com.snowplowanalytics.snowplow/tp2'
74
+
75
+ "#{protocol}://#{endpoint}#{port_string}#{path}"
76
+ end
77
+
78
+ # Add an event to the buffer and flush it if maximum size has been reached
79
+ #
80
+ Contract Hash => nil
81
+ def input(payload)
82
+ payload.each { |k,v| payload[k] = v.to_s}
83
+ @buffer.push(payload)
84
+ if @buffer.size > @buffer_size
85
+ flush
86
+ end
87
+
88
+ nil
89
+ end
90
+
91
+ # Flush the buffer
92
+ #
93
+ Contract Bool => nil
94
+ def flush(sync=false)
95
+ send_requests
96
+
97
+ nil
98
+ end
99
+
100
+ # Send all events in the buffer to the collector
101
+ #
102
+ Contract None => nil
103
+ def send_requests
104
+ LOGGER.info("Attempting to send #{@buffer.size} request#{@buffer.size == 1 ? '' : 's'}")
105
+ temp_buffer = @buffer
106
+ @buffer = []
107
+
108
+ if @method == 'get'
109
+ success_count = 0
110
+ unsent_requests = []
111
+ temp_buffer.each do |payload|
112
+ request = http_get(payload)
113
+ if request.code.to_i == 200
114
+ success_count += 1
115
+ else
116
+ unsent_requests.push(payload)
117
+ end
118
+ if unsent_requests.size == 0
119
+ unless @on_success.nil?
120
+ @on_success.call(success_count)
121
+ end
122
+ else
123
+ unless @on_failure.nil?
124
+ @on_failure.call(success_count, unsent_requests)
125
+ end
126
+ end
127
+ end
128
+
129
+ elsif @method == 'post'
130
+ if temp_buffer.size > 0
131
+ request = http_post({
132
+ 'schema' => 'iglu:com.snowplowanalytics.snowplow/payload_data/1-0-0',
133
+ 'data' => temp_buffer
134
+ })
135
+
136
+ if request.code.to_i == 200
137
+ unless @on_success.nil?
138
+ @on_success.call(temp_buffer.size)
139
+ end
140
+ else
141
+ unless @on_failure.nil?
142
+ @on_failure.call(0, temp_buffer)
143
+ end
144
+ end
145
+
146
+ end
147
+ end
148
+
149
+ nil
150
+ end
151
+
152
+ # Send a GET request
153
+ #
154
+ Contract Hash => lambda { |x| x.is_a? Net::HTTPResponse }
155
+ def http_get(payload)
156
+ destination = URI(@collector_uri + '?' + URI.encode_www_form(payload))
157
+ LOGGER.info("Sending GET request to #{@collector_uri}...")
158
+ LOGGER.debug("Payload: #{payload}")
159
+ response = Net::HTTP.get_response(destination)
160
+ LOGGER.add(response.code == '200' ? Logger::INFO : Logger::WARN) {
161
+ "GET request to #{@collector_uri} finished with status code #{response.code}"
162
+ }
163
+
164
+ response
165
+ end
166
+
167
+ # Send a POST request
168
+ #
169
+ Contract Hash => lambda { |x| x.is_a? Net::HTTPResponse }
170
+ def http_post(payload)
171
+ LOGGER.info("Sending POST request to #{@collector_uri}...")
172
+ LOGGER.debug("Payload: #{payload}")
173
+ destination = URI(@collector_uri)
174
+ http = Net::HTTP.new(destination.host, destination.port)
175
+ request = Net::HTTP::Post.new(destination)
176
+ request.form_data = payload
177
+ request.set_content_type('application/json; charset=utf-8')
178
+ response = http.request(request)
179
+ LOGGER.add(response.code == '200' ? Logger::INFO : Logger::WARN) {
180
+ "POST request to #{@collector_uri} finished with status code #{response.code}"
181
+ }
182
+
183
+ response
184
+ end
185
+
186
+ private :as_collector_uri,
187
+ :http_get,
188
+ :http_post
189
+
190
+ end
191
+
192
+
193
+ class AsyncEmitter < Emitter
194
+
195
+ # Flush the buffer in a new thread
196
+ # If sync is true, block until all flushing threads have exited
197
+ #
198
+ def flush(sync=false)
199
+ t = Thread.new do
200
+ send_requests
201
+ end
202
+ t.abort_on_exception = true
203
+ @threads.select!{ |thread| thread.alive?}
204
+ @threads.push(t)
205
+
206
+ if sync
207
+ LOGGER.info('Starting synchronous flush')
208
+ @threads.each do |thread|
209
+ thread.join(10)
210
+ end
211
+ end
212
+
213
+ nil
214
+ end
215
+
216
+ end
217
+
218
+ end
@@ -0,0 +1,97 @@
1
+ # Copyright (c) 2013-2014 Snowplow Analytics Ltd. All rights reserved.
2
+ #
3
+ # This program is licensed to you under the Apache License Version 2.0,
4
+ # and you may not use this file except in compliance with the Apache License Version 2.0.
5
+ # You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6
+ #
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # software distributed under the Apache License Version 2.0 is distributed on an
9
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11
+
12
+ # Author:: Alex Dean, Fred Blundun (mailto:support@snowplowanalytics.com)
13
+ # Copyright:: Copyright (c) 2013-2014 Snowplow Analytics Ltd
14
+ # License:: Apache License Version 2.0
15
+
16
+ require 'contracts'
17
+ include Contracts
18
+
19
+ module SnowplowTracker
20
+
21
+ class Subject
22
+
23
+ @@default_platform = 'srv'
24
+ @@supported_platforms = ['pc', 'tv', 'mob', 'cnsl', 'iot']
25
+
26
+ attr_reader :standard_nv_pairs
27
+
28
+ Contract None => Subject
29
+ def initialize
30
+ @standard_nv_pairs = {"p" => @@default_platform}
31
+ self
32
+ end
33
+
34
+ # Specify the platform
35
+ #
36
+ Contract String => Subject
37
+ def set_platform(value)
38
+ if @@supported_platforms.include?(value)
39
+ @standard_nv_pairs['p'] = value
40
+ else
41
+ raise "#{value} is not a supported platform"
42
+ end
43
+
44
+ self
45
+ end
46
+
47
+ # Set the business-defined user ID for a user
48
+ #
49
+ Contract String => Subject
50
+ def set_user_id(user_id)
51
+ @standard_nv_pairs['uid'] = user_id
52
+ self
53
+ end
54
+
55
+ # Set the screen resolution for a device
56
+ #
57
+ Contract Num, Num => Subject
58
+ def set_screen_resolution(width, height)
59
+ @standard_nv_pairs['res'] = "#{width}x#{height}"
60
+ self
61
+ end
62
+
63
+ # Set the dimensions of the current viewport
64
+ #
65
+ Contract Num, Num => Subject
66
+ def set_viewport(width, height)
67
+ @standard_nv_pairs['vp'] = "#{width}x#{height}"
68
+ self
69
+ end
70
+
71
+ # Set the color depth of the device in bits per pixel
72
+ #
73
+ Contract Num => Subject
74
+ def set_color_depth(depth)
75
+ @standard_nv_pairs['cd'] = depth
76
+ self
77
+ end
78
+
79
+ # Set the timezone field
80
+ #
81
+ Contract String => Subject
82
+ def set_timezone(timezone)
83
+ @standard_nv_pairs['tz'] = timezone
84
+ self
85
+ end
86
+
87
+ # Set the language field
88
+ #
89
+ Contract String => Subject
90
+ def set_lang(lang)
91
+ @standard_nv_pairs['lang'] = lang
92
+ self
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -13,7 +13,6 @@
13
13
  # Copyright:: Copyright (c) 2013-2014 Snowplow Analytics Ltd
14
14
  # License:: Apache License Version 2.0
15
15
 
16
- require 'net/http'
17
16
  require 'contracts'
18
17
  require 'set'
19
18
  include Contracts
@@ -24,6 +23,8 @@ module SnowplowTracker
24
23
 
25
24
  class Tracker
26
25
 
26
+ @@EmitterInput = Or[lambda {|x| x.is_a? Emitter}, ArrayOf[lambda {|x| x.is_a? Emitter}]]
27
+
27
28
  @@required_transaction_keys = Set.new(%w(order_id total_value))
28
29
  @@recognised_transaction_keys = Set.new(%w(order_id total_value affiliation tax_value shipping city state country currency))
29
30
 
@@ -66,38 +67,41 @@ module SnowplowTracker
66
67
 
67
68
  @@version = TRACKER_VERSION
68
69
  @@default_encode_base64 = true
69
- @@default_platform = 'pc'
70
- @@supported_platforms = ['pc', 'tv', 'mob', 'cnsl', 'iot']
71
- @@http_errors = ['host not found',
72
- 'No address associated with name',
73
- 'No address associated with hostname']
74
70
 
75
71
  @@base_schema_path = "iglu:com.snowplowanalytics.snowplow"
76
72
  @@schema_tag = "jsonschema"
77
73
  @@context_schema = "#{@@base_schema_path}/contexts/#{@@schema_tag}/1-0-0"
78
74
  @@unstruct_event_schema = "#{@@base_schema_path}/unstruct_event/#{@@schema_tag}/1-0-0"
79
75
 
80
- Contract String, Maybe[String], Maybe[String], Bool => Tracker
81
- def initialize(endpoint, namespace=nil, app_id=nil, encode_base64=@@default_encode_base64)
82
- @collector_uri = as_collector_uri(endpoint)
76
+ Contract @@EmitterInput, Maybe[Subject], Maybe[String], Maybe[String], Bool => Tracker
77
+ def initialize(emitters, subject=nil, namespace=nil, app_id=nil, encode_base64=@@default_encode_base64)
78
+ @emitters = Array(emitters)
79
+ if subject.nil?
80
+ @subject = Subject.new
81
+ else
82
+ @subject = subject
83
+ end
83
84
  @standard_nv_pairs = {
84
85
  'tna' => namespace,
85
86
  'tv' => @@version,
86
- 'p' => @@default_platform,
87
87
  'aid' => app_id
88
88
  }
89
89
  @config = {
90
90
  'encode_base64' => encode_base64
91
91
  }
92
92
  @uuid = UUID.new
93
+
93
94
  self
94
95
  end
95
96
 
96
- # Adds the protocol to the fron of the collector URL, and /i to the end
97
+ # Call subject methods from tracker instance
97
98
  #
98
- Contract String => String
99
- def as_collector_uri(host)
100
- "http://#{host}/i"
99
+ Subject.instance_methods(false).each do |name|
100
+ define_method name, ->(*splat) do
101
+ @subject.method(name.to_sym).call(*splat)
102
+
103
+ self
104
+ end
101
105
  end
102
106
 
103
107
  # Generates a type-4 UUID to identify this event
@@ -123,92 +127,24 @@ module SnowplowTracker
123
127
  }
124
128
  end
125
129
 
126
- # Send request
127
- #
128
- Contract Payload => [Bool, Num]
129
- def http_get(payload)
130
- destination = URI(@collector_uri + '?' + URI.encode_www_form(payload.context))
131
- r = Net::HTTP.get_response(destination)
132
- if @@http_errors.include? r.code
133
- return false, "Host [#{r.host}] not found (possible connectivity error)"
134
- elsif r.code.to_i < 0 or 400 <= r.code.to_i
135
- return false, r.code.to_i
136
- else
137
- return true, r.code.to_i
138
- end
139
- end
140
-
141
- # Setter methods
142
-
143
- # Specify the platform
144
- #
145
- Contract String => String
146
- def set_platform(value)
147
- if @@supported_platforms.include?(value)
148
- @standard_nv_pairs['p'] = value
149
- else
150
- raise "#{value} is not a supported platform"
151
- end
152
- end
153
-
154
- # Set the business-defined user ID for a user
155
- #
156
- Contract String => String
157
- def set_user_id(user_id)
158
- @standard_nv_pairs['uid'] = user_id
159
- end
160
-
161
- # Set the screen resolution for a device
162
- #
163
- Contract Num, Num => String
164
- def set_screen_resolution(width, height)
165
- @standard_nv_pairs['res'] = "#{width}x#{height}"
166
- end
167
-
168
- # Set the dimensions of the current viewport
169
- #
170
- Contract Num, Num => String
171
- def set_viewport(width, height)
172
- @standard_nv_pairs['vp'] = "#{width}x#{height}"
173
- end
174
-
175
- # Set the color depth of the device in bits per pixel
176
- #
177
- Contract Num => Num
178
- def set_color_depth(depth)
179
- @standard_nv_pairs['cd'] = depth
180
- end
181
-
182
- # Set the timezone field
183
- #
184
- Contract String => String
185
- def set_timezone(timezone)
186
- @standard_nv_pairs['tz'] = timezone
187
- end
188
-
189
- # Set the language field
190
- #
191
- Contract String => String
192
- def set_lang(lang)
193
- @standard_nv_pairs['lang'] = lang
194
- end
195
-
196
130
  # Tracking methods
197
131
 
198
132
  # Attaches all the fields in @standard_nv_pairs to the request
199
133
  # Only attaches the context vendor if the event has a custom context
200
134
  #
201
- Contract Payload => [Bool, Num]
135
+ Contract Payload => nil
202
136
  def track(pb)
137
+ pb.add_dict(@subject.standard_nv_pairs)
203
138
  pb.add_dict(@standard_nv_pairs)
204
139
  pb.add('eid', get_event_id())
140
+ @emitters.each{ |emitter| emitter.input(pb.context)}
205
141
 
206
- http_get(pb)
142
+ nil
207
143
  end
208
144
 
209
145
  # Log a visit to this page
210
146
  #
211
- Contract String, Maybe[String], Maybe[String], Maybe[@@ContextsInput] => [Bool, Num]
147
+ Contract String, Maybe[String], Maybe[String], Maybe[@@ContextsInput] => Tracker
212
148
  def track_page_view(page_url, page_title=nil, referrer=nil, context=nil, tstamp=nil)
213
149
  pb = Payload.new
214
150
  pb.add('e', 'pv')
@@ -224,12 +160,14 @@ module SnowplowTracker
224
160
  end
225
161
  pb.add('dtm', tstamp)
226
162
  track(pb)
163
+
164
+ self
227
165
  end
228
166
 
229
167
  # Track a single item within an ecommerce transaction
230
168
  # Not part of the public API
231
169
  #
232
- Contract @@AugmentedItem => [Bool, Num]
170
+ Contract @@AugmentedItem => self
233
171
  def track_ecommerce_transaction_item(argmap)
234
172
  pb = Payload.new
235
173
  pb.add('e', 'ti')
@@ -245,11 +183,13 @@ module SnowplowTracker
245
183
  end
246
184
  pb.add('dtm', argmap['tstamp'])
247
185
  track(pb)
186
+
187
+ self
248
188
  end
249
189
 
250
190
  # Track an ecommerce transaction and all the items in it
251
191
  #
252
- Contract @@Transaction, ArrayOf[@@Item], Maybe[@@ContextsInput], Maybe[Num] => ({'transaction_result' => [Bool, Num], 'item_results' => ArrayOf[[Bool, Num]]})
192
+ Contract @@Transaction, ArrayOf[@@Item], Maybe[@@ContextsInput], Maybe[Num] => Tracker
253
193
  def track_ecommerce_transaction(transaction, items,
254
194
  context=nil, tstamp=nil)
255
195
  pb = Payload.new
@@ -272,22 +212,21 @@ module SnowplowTracker
272
212
  end
273
213
  pb.add('dtm', tstamp)
274
214
 
275
- transaction_result = track(pb)
276
- item_results = []
215
+ track(pb)
277
216
 
278
217
  for item in items
279
218
  item['tstamp'] = tstamp
280
219
  item['order_id'] = transaction['order_id']
281
220
  item['currency'] = transaction['currency']
282
- item_results.push(track_ecommerce_transaction_item(item))
221
+ track_ecommerce_transaction_item(item)
283
222
  end
284
223
 
285
- {'transaction_result' => transaction_result, 'item_results' => item_results}
224
+ self
286
225
  end
287
226
 
288
227
  # Track a structured event
289
228
  #
290
- Contract String, String, Maybe[String], Maybe[String], Maybe[Num], Maybe[@@ContextsInput], Maybe[Num] => [Bool, Num]
229
+ Contract String, String, Maybe[String], Maybe[String], Maybe[Num], Maybe[@@ContextsInput], Maybe[Num] => Tracker
291
230
  def track_struct_event(category, action, label=nil, property=nil, value=nil, context=nil, tstamp=nil)
292
231
  pb = Payload.new
293
232
  pb.add('e', 'se')
@@ -304,13 +243,18 @@ module SnowplowTracker
304
243
  end
305
244
  pb.add('dtm', tstamp)
306
245
  track(pb)
246
+
247
+ self
307
248
  end
308
249
 
309
250
  # Track a screen view event
310
251
  #
311
- Contract String, Maybe[String], Maybe[@@ContextsInput], Maybe[Num] => [Bool, Num]
312
- def track_screen_view(name, id=nil, context=nil, tstamp=nil)
313
- screen_view_properties = {'name' => name}
252
+ Contract Maybe[String], Maybe[String], Maybe[@@ContextsInput], Maybe[Num] => Tracker
253
+ def track_screen_view(name=nil, id=nil, context=nil, tstamp=nil)
254
+ screen_view_properties = {}
255
+ unless name.nil?
256
+ screen_view_properties['name'] = name
257
+ end
314
258
  unless id.nil?
315
259
  screen_view_properties['id'] = id
316
260
  end
@@ -318,11 +262,13 @@ module SnowplowTracker
318
262
  event_json = {schema: screen_view_schema, data: screen_view_properties}
319
263
 
320
264
  self.track_unstruct_event(event_json, context, tstamp)
265
+
266
+ self
321
267
  end
322
268
 
323
269
  # Track an unstructured event
324
270
  #
325
- Contract @@SelfDescribingJson, Maybe[@@ContextsInput], Maybe[Num] => [Bool, Num]
271
+ Contract @@SelfDescribingJson, Maybe[@@ContextsInput], Maybe[Num] => Tracker
326
272
  def track_unstruct_event(event_json, context=nil, tstamp=nil)
327
273
  pb = Payload.new
328
274
  pb.add('e', 'ue')
@@ -343,12 +289,39 @@ module SnowplowTracker
343
289
  pb.add('dtm', tstamp)
344
290
 
345
291
  track(pb)
292
+
293
+ self
294
+ end
295
+
296
+ # Flush all events stored in all emitters
297
+ #
298
+ Contract Bool => Tracker
299
+ def flush(sync=false)
300
+ @emitters.each do |emitter|
301
+ emitter.flush(sync)
302
+ end
303
+
304
+ self
305
+ end
306
+
307
+ # Set the subject of the events fired by the tracker
308
+ #
309
+ Contract Subject => Tracker
310
+ def set_subject(subject)
311
+ @subject = subject
312
+ self
313
+ end
314
+
315
+ # Add a new emitter
316
+ #
317
+ Contract Emitter => Tracker
318
+ def add_emitter(emitter)
319
+ @emitters.push(emitter)
320
+ self
346
321
  end
347
322
 
348
- private :as_collector_uri,
349
- :get_timestamp,
323
+ private :get_timestamp,
350
324
  :build_context,
351
- :http_get,
352
325
  :track,
353
326
  :track_ecommerce_transaction_item
354
327
 
@@ -14,6 +14,6 @@
14
14
  # License:: Apache License Version 2.0
15
15
 
16
16
  module SnowplowTracker
17
- VERSION = '0.2.0'
17
+ VERSION = '0.3.0'
18
18
  TRACKER_VERSION = "rb-#{VERSION}"
19
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snowplow-tracker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Dean
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-31 00:00:00.000000000 Z
12
+ date: 2014-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: contracts
@@ -76,10 +76,13 @@ extra_rdoc_files: []
76
76
  files:
77
77
  - LICENSE-2.0.txt
78
78
  - README.md
79
- - lib/snowplow-tracker.rb
79
+ - lib/snowplow-tracker/contracts.rb
80
+ - lib/snowplow-tracker/emitters.rb
80
81
  - lib/snowplow-tracker/payload.rb
82
+ - lib/snowplow-tracker/subject.rb
81
83
  - lib/snowplow-tracker/tracker.rb
82
84
  - lib/snowplow-tracker/version.rb
85
+ - lib/snowplow-tracker.rb
83
86
  homepage: http://github.com/snowplow/snowplow-ruby-tracker
84
87
  licenses:
85
88
  - Apache License 2.0
@@ -100,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
103
  version: '0'
101
104
  requirements: []
102
105
  rubyforge_project:
103
- rubygems_version: 2.2.2
106
+ rubygems_version: 2.1.11
104
107
  signing_key:
105
108
  specification_version: 4
106
109
  summary: Ruby Analytics for Snowplow