Skip to content
This repository was archived by the owner on Feb 28, 2023. It is now read-only.

Add bulk tracking #13

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions lib/heap/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,17 @@ def add_user_properties(identity, properties)
def track(event, identity, properties = nil)
ensure_valid_app_id!

event_name = event.to_s
ensure_valid_event_name! event_name
ensure_valid_event_name! event
ensure_valid_identity! identity

body = {
:app_id => @app_id,
:identity => identity.to_s,
:event => event,
:identity => identity,
:event => event
}
ensure_valid_properties! properties
unless properties.nil?
body[:properties] = properties
ensure_valid_properties! properties
end

response = connection.post '/api/track', body,
Expand All @@ -129,6 +128,32 @@ def track(event, identity, properties = nil)
self
end

# Sends a collection of custom events to the Heap API servers.
#
# @param [Enumerable<Hash<:event=>String,:identity=>String(,:properties=>Hash)>] events a collection that responds to #each,
# which will yield Hashes containing the following key-value pairs:
# :event => String the name of the server-side event; limited to 1024 characters
# :identity => String an e-mail, handle, or Heap-generated user ID
# :properties => Hash<String, String|Number> key-value properties
# associated with the event; each key must have fewer than 1024 characters;
# each value must be a Number or String with fewer than 1024 characters
# @return [HeapAPI::Client] self
# @see https://heapanalytics.com/docs/server-side#bulk-track
def bulk_track(events)
ensure_valid_app_id!

events.each do |event_hash|
ensure_valid_event_name! event_hash[:event]
ensure_valid_identity! event_hash[:identity]
ensure_valid_properties! event_hash[:properties]
end

response = connection.post '/api/track', { :app_id => @app_id, :events => events },
'User-Agent' => user_agent
raise HeapAPI::ApiError.new(response) unless response.success?
self
end

# The underlying Faraday connection used to make HTTP requests.
#
# @return [Faraday::Connection] a Faraday connection object
Expand Down
27 changes: 16 additions & 11 deletions lib/heap/validations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def ensure_valid_app_id!
# @raise ArgumentError if the event name is invalid
# @return [HeapAPI::Client] self
def ensure_valid_event_name!(event)
event = event.to_s
raise ArgumentError, 'Missing or empty event name' if event.empty?
raise ArgumentError, 'Event name too long' if event.length > 1024
self
Expand All @@ -29,17 +30,17 @@ def ensure_valid_event_name!(event)
# @raise ArgumentError if identity is of an invalid type or too long.
# @return [HeapAPI::Client] self
def ensure_valid_identity!(identity)
identity = identity.to_s if identity.kind_of?(Integer)

if identity.kind_of?(String) || identity.kind_of?(Symbol)
if identity.to_s.length > 255
raise ArgumentError, "Identity field too long; " +
"#{identity.to_s.length} is above the 255-character limit"
if identity.kind_of?(Integer) || identity.kind_of?(String) || identity.kind_of?(Symbol)
identity = identity.to_s
if identity.length > 255
raise ArgumentError, "Identity field too long; #{identity.length} is above the 255-character limit"
end
else
raise ArgumentError,
"Unsupported type for identity value #{identity.inspect}"
end

self
end
private :ensure_valid_identity!

Expand All @@ -51,27 +52,31 @@ def ensure_valid_identity!(identity)
# @raise ArgumentError if the property bag is invalid
# @return [HeapAPI::Client] self
def ensure_valid_properties!(properties)
return self if properties.nil?
unless properties.respond_to?(:each)
raise ArgumentError, 'Properties object does not implement #each'
end

properties.each do |key, value|
if key.to_s.length > 1024
raise ArgumentError, "Property name #{key} too long; " +
"#{key.to_s.length} is above the 1024-character limit"
key_length = key.to_s.length
if key_length > 1024
raise ArgumentError, "Property name #{key} too long; #{key_length} is above the 1024-character limit"
end
if value.kind_of? Numeric
# TODO(pwnall): Check numerical limits, if necessary.
elsif value.kind_of?(String) || value.kind_of?(Symbol)
if value.to_s.length > 1024
value_length = value.to_s.length
if value_length > 1024
raise ArgumentError, "Property #{key} value #{value.inspect} too " +
"long; #{value.to_s.length} is above the 1024-character limit"
"long; #{value_length} is above the 1024-character limit"
end
else
raise ArgumentError,
"Unsupported type for property #{key} value #{value.inspect}"
end
end

self
end
private :ensure_valid_properties!
end
2 changes: 1 addition & 1 deletion test/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def setup
end

def test_default_app_id
assert_equal nil, @heap.app_id
assert_nil @heap.app_id
end

def test_default_stubbed
Expand Down
39 changes: 38 additions & 1 deletion test/client_track_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def test_track_with_integer_identity
@stubs.post '/api/track' do |env|
golden_body = {
'app_id' => 'test-app-id',
'identity' => '123456789',
'identity' => 123456789,
'event' => 'test_track',
}
assert_equal 'application/json', env[:request_headers]['Content-Type']
Expand Down Expand Up @@ -174,6 +174,43 @@ def test_track_with_properties
'test-identity','foo' => 'bar', :heap => :hurray)
end

def test_bulk_track
@stubs.post '/api/track' do |env|
golden_body = {
'app_id' => 'test-app-id',
'events' => [
{
'identity' => '123456789',
'event' => 'test_track'
},
{
'identity' => 'test-identity',
'event' => 'test_track_with_properties',
'properties' => { 'foo' => 'bar', 'heap' => 'hurray' }
}
]
}
assert_equal 'application/json', env[:request_headers]['Content-Type']
assert_equal @heap.user_agent, env[:request_headers]['User-Agent']
assert_equal golden_body, JSON.parse(env[:body])

[200, { 'Content-Type' => 'text/plain; encoding=utf8' }, '']
end

assert_equal @heap, @heap.bulk_track(
[
{
:event => 'test_track',
:identity => '123456789',
},
{
:event => 'test_track_with_properties',
:identity => 'test-identity',
:properties => { 'foo' => 'bar', :heap => :hurray }
}
])
end

def test_track_error
@stubs.post '/api/track' do |env|
[400, { 'Content-Type' => 'text/plain; encoding=utf8' }, 'Bad request']
Expand Down
2 changes: 1 addition & 1 deletion test/heap_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class HeapTest < MiniTest::Test
def test_heap_app_id
assert_equal nil, Heap.app_id
assert_nil Heap.app_id
begin
Heap.app_id = 'global-app-id'
assert_equal 'global-app-id', Heap.app_id
Expand Down