Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
event-tracking
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
event-tracking
Commits
2a9ab21e
Commit
2a9ab21e
authored
Oct 07, 2013
by
Gabe Mulley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support event processors
parent
35691e74
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
104 additions
and
3 deletions
+104
-3
eventtracking/tests/test_track.py
+72
-0
eventtracking/tracker.py
+32
-3
No files found.
eventtracking/tests/test_track.py
View file @
2a9ab21e
...
...
@@ -184,3 +184,75 @@ class TestTrack(TestCase): # pylint: disable=missing-docstring
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
name
)
def
test_single_processor
(
self
):
self
.
tracker
.
processors
.
append
(
self
.
change_name
)
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
changed_name
)
def
change_name
(
self
,
event
):
"""Modify the event type of the event"""
event
[
'name'
]
=
sentinel
.
changed_name
return
event
def
test_non_callable_processor
(
self
):
self
.
tracker
.
processors
.
append
(
object
())
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
name
)
def
test_callable_class_processor
(
self
):
class
SampleProcessor
(
object
):
"""An event processing class"""
def
__call__
(
self
,
event
):
"""Modify the event type"""
event
[
'name'
]
=
sentinel
.
class_name
self
.
tracker
.
processors
.
append
(
SampleProcessor
())
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
class_name
)
def
test_processor_chain
(
self
):
def
ensure_modified_event
(
event
):
"""Assert the first processor added a field to the event"""
self
.
assertIn
(
sentinel
.
key
,
event
)
self
.
assertEquals
(
event
[
sentinel
.
key
],
sentinel
.
value
)
return
event
self
.
tracker
.
processors
.
extend
([
self
.
change_name
,
ensure_modified_event
])
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
changed_name
)
def
test_processor_failure
(
self
):
def
always_fail
(
event
):
# pylint: disable=unused-argument
"""Always raises an error"""
raise
ValueError
self
.
tracker
.
processors
.
extend
([
always_fail
,
self
.
change_name
])
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
changed_name
)
def
test_processor_returns_none
(
self
):
def
return_none
(
event
):
# pylint: disable=unused-argument
"""Don't return the event"""
pass
self
.
tracker
.
processors
.
append
(
return_none
)
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
name
)
def
test_processor_modifies_the_same_event_object
(
self
):
def
forget_return
(
event
):
"""Modify the event without returning it"""
event
[
'name'
]
=
sentinel
.
forgotten_return
def
ensure_name_changed
(
event
):
"""Assert the event type has been modified even though the event wasn't returned"""
self
.
assertEquals
(
event
[
'name'
],
sentinel
.
forgotten_return
)
self
.
tracker
.
processors
.
extend
([
forget_return
,
ensure_name_changed
])
self
.
tracker
.
emit
(
sentinel
.
name
)
self
.
assert_backend_called_with
(
sentinel
.
forgotten_return
)
eventtracking/tracker.py
View file @
2a9ab21e
...
...
@@ -36,9 +36,10 @@ class Tracker(object):
Track application events. Holds references to a set of backends that will
be used to persist any events that are emitted.
"""
def
__init__
(
self
,
backends
=
None
,
context_locator
=
None
):
def
__init__
(
self
,
backends
=
None
,
context_locator
=
None
,
processors
=
None
):
self
.
backends
=
backends
or
{}
self
.
context_locator
=
context_locator
or
DefaultContextLocator
()
self
.
processors
=
processors
or
[]
@property
def
located_context
(
self
):
...
...
@@ -61,16 +62,44 @@ class Tracker(object):
Note that all values provided must be serializable.
"""
full_
event
=
{
event
=
{
'name'
:
name
or
UNKNOWN_EVENT_TYPE
,
'timestamp'
:
datetime
.
now
(
UTC
),
'data'
:
data
or
{},
'context'
:
self
.
resolve_context
()
}
event
=
self
.
process_event
(
event
)
self
.
send_to_backends
(
event
)
def
process_event
(
self
,
event
):
"""
Executes all event processors on the event in order.
`event` is a nested dictionary that represents the event.
Returns the modified event.
"""
for
processor
in
self
.
processors
:
try
:
modified_event
=
processor
(
event
)
if
modified_event
is
not
None
:
event
=
modified_event
except
Exception
:
# pylint: disable=broad-except
LOG
.
exception
(
'Failed to execute processor: {0}'
.
format
(
processor
)
)
return
event
def
send_to_backends
(
self
,
event
):
"""Sends the event to all registered backends."""
for
name
,
backend
in
self
.
backends
.
iteritems
():
try
:
backend
.
send
(
full_
event
)
backend
.
send
(
event
)
except
Exception
:
# pylint: disable=broad-except
LOG
.
exception
(
'Unable to send event to backend: {0}'
.
format
(
name
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment