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
420dba33
Commit
420dba33
authored
Oct 17, 2013
by
Gabe Mulley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support adding processors via django config
parent
2a9ab21e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
76 additions
and
22 deletions
+76
-22
eventtracking/django/__init__.py
+48
-22
eventtracking/django/tests/test_configuration.py
+24
-0
eventtracking/tracker.py
+4
-0
No files found.
eventtracking/django/__init__.py
View file @
420dba33
...
@@ -11,7 +11,8 @@ from eventtracking.tracker import Tracker
...
@@ -11,7 +11,8 @@ from eventtracking.tracker import Tracker
from
eventtracking.locator
import
ThreadLocalContextLocator
from
eventtracking.locator
import
ThreadLocalContextLocator
DJANGO_SETTING_NAME
=
'TRACKING_BACKENDS'
DJANGO_BACKEND_SETTING_NAME
=
'TRACKING_BACKENDS'
DJANGO_PROCESSOR_SETTING_NAME
=
'TRACKING_PROCESSORS'
class
DjangoTracker
(
Tracker
):
class
DjangoTracker
(
Tracker
):
...
@@ -22,13 +23,13 @@ class DjangoTracker(Tracker):
...
@@ -22,13 +23,13 @@ class DjangoTracker(Tracker):
def
__init__
(
self
):
def
__init__
(
self
):
backends
=
self
.
create_backends_from_settings
()
backends
=
self
.
create_backends_from_settings
()
super
(
DjangoTracker
,
self
)
.
__init__
(
backends
,
ThreadLocalContextLocator
())
processors
=
self
.
create_processors_from_settings
()
super
(
DjangoTracker
,
self
)
.
__init__
(
backends
,
ThreadLocalContextLocator
(),
processors
)
def
create_backends_from_settings
(
self
):
def
create_backends_from_settings
(
self
):
"""
"""
Expects the Django setting `setting_name` (defaults to
Expects the Django setting "TRACKING_BACKENDS" to be defined and point
"TRACKING_BACKENDS") to be defined and point to a dictionary of
to a dictionary of backend engine configurations.
backend engine configurations.
Example::
Example::
...
@@ -47,46 +48,71 @@ class DjangoTracker(Tracker):
...
@@ -47,46 +48,71 @@ class DjangoTracker(Tracker):
},
},
}
}
"""
"""
config
=
getattr
(
settings
,
DJANGO_SETTING_NAME
,
{})
config
=
getattr
(
settings
,
DJANGO_
BACKEND_
SETTING_NAME
,
{})
backends
=
{}
backends
=
{}
for
name
,
values
in
config
.
iteritems
():
for
name
,
values
in
config
.
iteritems
():
# Ignore empty values to turn-off default tracker backends
# Ignore empty values to turn-off default tracker backends
if
values
and
'ENGINE'
in
values
:
if
values
and
'ENGINE'
in
values
:
engine
=
values
[
'ENGINE'
]
backend
=
self
.
instantiate_from_dict
(
values
)
options
=
values
.
get
(
'OPTIONS'
,
{})
backend
=
self
.
instantiate_backend_from_name
(
engine
,
options
)
backends
[
name
]
=
backend
backends
[
name
]
=
backend
return
backends
return
backends
def
instantiate_
backend_from_name
(
self
,
name
,
option
s
):
def
instantiate_
from_dict
(
self
,
value
s
):
"""
"""
Instantiate an event tracker backend from the full module path to
Constructs an object given a dictionary containing an "ENGINE" key
the backend class. Useful when setting backends from configuration
which contains the full module path to the class, and an "OPTIONS"
files.
key which contains a dictionary that will be passed in to the
constructor as keyword args.
"""
"""
# Parse backend name
name
=
values
[
'ENGINE'
]
options
=
values
.
get
(
'OPTIONS'
,
{})
# Parse the name
parts
=
name
.
split
(
'.'
)
parts
=
name
.
split
(
'.'
)
module_name
=
'.'
.
join
(
parts
[:
-
1
])
module_name
=
'.'
.
join
(
parts
[:
-
1
])
class_name
=
parts
[
-
1
]
class_name
=
parts
[
-
1
]
# Get and verify the backend class
# Get the class
try
:
try
:
module
=
import_module
(
module_name
)
module
=
import_module
(
module_name
)
cls
=
getattr
(
module
,
class_name
)
cls
=
getattr
(
module
,
class_name
)
except
(
ValueError
,
AttributeError
,
TypeError
,
ImportError
):
except
(
ValueError
,
AttributeError
,
TypeError
,
ImportError
):
raise
ValueError
(
'Cannot find
event tracker backend
%
s'
%
name
)
raise
ValueError
(
'Cannot find
class
%
s'
%
name
)
backend
=
cls
(
**
options
)
return
cls
(
**
options
)
if
not
hasattr
(
backend
,
'send'
)
or
not
callable
(
backend
.
send
):
raise
ValueError
(
'Backend
%
s does not have a callable "send" method.'
%
name
)
def
create_processors_from_settings
(
self
):
"""
Expects the Django setting "TRACKING_PROCESSORS" to be defined and
point to a list of backend engine configurations.
Example::
TRACKING_PROCESSORS = [
{
'ENGINE': 'some.arbitrary.Processor'
},
{
'ENGINE': 'some.arbitrary.OtherProcessor',
'OPTIONS': {
'user': 'foo'
}
},
]
"""
config
=
getattr
(
settings
,
DJANGO_PROCESSOR_SETTING_NAME
,
[])
processors
=
[]
for
values
in
config
:
# Ignore empty values to turn-off default tracker backends
if
values
and
'ENGINE'
in
values
:
processors
.
append
(
self
.
instantiate_from_dict
(
values
))
return
backend
return
processors
def
override_default_tracker
():
def
override_default_tracker
():
...
...
eventtracking/django/tests/test_configuration.py
View file @
420dba33
...
@@ -137,6 +137,23 @@ class TestConfiguration(TestCase):
...
@@ -137,6 +137,23 @@ class TestConfiguration(TestCase):
django
.
override_default_tracker
()
django
.
override_default_tracker
()
self
.
assertTrue
(
isinstance
(
tracker
.
get_tracker
(),
tracker
.
Tracker
))
self
.
assertTrue
(
isinstance
(
tracker
.
get_tracker
(),
tracker
.
Tracker
))
@override_settings
(
TRACKING_PROCESSORS
=
[
{
'ENGINE'
:
'eventtracking.django.tests.test_configuration.NopProcessor'
}
])
def
test_single_processor
(
self
):
self
.
configure_tracker
()
self
.
assertEquals
(
len
(
self
.
tracker
.
processors
),
1
)
self
.
assertTrue
(
isinstance
(
self
.
tracker
.
processors
[
0
],
NopProcessor
))
@override_settings
(
TRACKING_PROCESSORS
=
[
{}
])
def
test_missing_processor_engine
(
self
):
self
.
configure_tracker
()
self
.
assertEquals
(
len
(
self
.
tracker
.
processors
),
0
)
class
TrivialFakeBackend
(
object
):
class
TrivialFakeBackend
(
object
):
"""A trivial fake backend without any options"""
"""A trivial fake backend without any options"""
...
@@ -157,3 +174,10 @@ class FakeBackendWithOptions(TrivialFakeBackend):
...
@@ -157,3 +174,10 @@ class FakeBackendWithOptions(TrivialFakeBackend):
def
__init__
(
self
,
**
kwargs
):
def
__init__
(
self
,
**
kwargs
):
super
(
FakeBackendWithOptions
,
self
)
.
__init__
()
super
(
FakeBackendWithOptions
,
self
)
.
__init__
()
self
.
option
=
kwargs
.
get
(
'option'
,
None
)
self
.
option
=
kwargs
.
get
(
'option'
,
None
)
class
NopProcessor
(
object
):
"""Changes every event"""
def
__call__
(
self
,
event
):
pass
eventtracking/tracker.py
View file @
420dba33
...
@@ -41,6 +41,10 @@ class Tracker(object):
...
@@ -41,6 +41,10 @@ class Tracker(object):
self
.
context_locator
=
context_locator
or
DefaultContextLocator
()
self
.
context_locator
=
context_locator
or
DefaultContextLocator
()
self
.
processors
=
processors
or
[]
self
.
processors
=
processors
or
[]
for
backend
in
backends
.
itervalues
():
if
not
hasattr
(
backend
,
'send'
)
or
not
callable
(
backend
.
send
):
raise
ValueError
(
'Backend
%
s does not have a callable "send" method.'
%
backend
.
__class__
.
__name__
)
@property
@property
def
located_context
(
self
):
def
located_context
(
self
):
"""
"""
...
...
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