Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx-platform
Commits
f3e59acb
Commit
f3e59acb
authored
Jul 31, 2015
by
John Eskew
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add DataDog histogram events to DjangoXBlockUserStateClient class.
parent
53db053c
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
66 additions
and
5 deletions
+66
-5
lms/djangoapps/courseware/user_state_client.py
+66
-5
No files found.
lms/djangoapps/courseware/user_state_client.py
View file @
f3e59acb
...
@@ -5,20 +5,18 @@ data in a Django ORM model.
...
@@ -5,20 +5,18 @@ data in a Django ORM model.
import
itertools
import
itertools
from
operator
import
attrgetter
from
operator
import
attrgetter
from
time
import
time
try
:
try
:
import
simplejson
as
json
import
simplejson
as
json
except
ImportError
:
except
ImportError
:
import
json
import
json
import
dogstats_wrapper
as
dog_stats_api
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
xblock.fields
import
Scope
,
ScopeBase
from
xblock.fields
import
Scope
,
ScopeBase
from
edx_user_state_client.interface
import
XBlockUserStateClient
,
XBlockUserState
from
courseware.models
import
StudentModule
,
StudentModuleHistory
from
courseware.models
import
StudentModule
,
StudentModuleHistory
from
contracts
import
contract
,
new_contract
from
edx_user_state_client.interface
import
XBlockUserStateClient
,
XBlockUserState
from
opaque_keys.edx.keys
import
UsageKey
new_contract
(
'UsageKey'
,
UsageKey
)
class
DjangoXBlockUserStateClient
(
XBlockUserStateClient
):
class
DjangoXBlockUserStateClient
(
XBlockUserStateClient
):
...
@@ -41,6 +39,9 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
...
@@ -41,6 +39,9 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
even though the actual stored state in the database will be ``"{}"``).
even though the actual stored state in the database will be ``"{}"``).
"""
"""
# Use this sample rate for DataDog events.
API_DATADOG_SAMPLE_RATE
=
0.01
class
ServiceUnavailable
(
XBlockUserStateClient
.
ServiceUnavailable
):
class
ServiceUnavailable
(
XBlockUserStateClient
.
ServiceUnavailable
):
"""
"""
This error is raised if the service backing this client is currently unavailable.
This error is raised if the service backing this client is currently unavailable.
...
@@ -94,6 +95,27 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
...
@@ -94,6 +95,27 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
usage_key
=
student_module
.
module_state_key
.
map_into_course
(
student_module
.
course_id
)
usage_key
=
student_module
.
module_state_key
.
map_into_course
(
student_module
.
course_id
)
yield
(
student_module
,
usage_key
)
yield
(
student_module
,
usage_key
)
def
_ddog_increment
(
self
,
evt_time
,
evt_name
):
"""
DataDog increment method.
"""
dog_stats_api
.
increment
(
'DjangoXBlockUserStateClient.{}'
.
format
(
evt_name
),
timestamp
=
evt_time
,
sample_rate
=
self
.
API_DATADOG_SAMPLE_RATE
,
)
def
_ddog_histogram
(
self
,
evt_time
,
evt_name
,
value
):
"""
DataDog histogram method.
"""
dog_stats_api
.
histogram
(
'DjangoXBlockUserStateClient.{}'
.
format
(
evt_name
),
value
,
timestamp
=
evt_time
,
sample_rate
=
self
.
API_DATADOG_SAMPLE_RATE
,
)
def
get_many
(
self
,
username
,
block_keys
,
scope
=
Scope
.
user_state
,
fields
=
None
):
def
get_many
(
self
,
username
,
block_keys
,
scope
=
Scope
.
user_state
,
fields
=
None
):
"""
"""
Retrieve the stored XBlock state for the specified XBlock usages.
Retrieve the stored XBlock state for the specified XBlock usages.
...
@@ -111,12 +133,16 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
...
@@ -111,12 +133,16 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
if
scope
!=
Scope
.
user_state
:
if
scope
!=
Scope
.
user_state
:
raise
ValueError
(
"Only Scope.user_state is supported, not {}"
.
format
(
scope
))
raise
ValueError
(
"Only Scope.user_state is supported, not {}"
.
format
(
scope
))
block_count
=
state_length
=
0
evt_time
=
time
()
modules
=
self
.
_get_student_modules
(
username
,
block_keys
)
modules
=
self
.
_get_student_modules
(
username
,
block_keys
)
for
module
,
usage_key
in
modules
:
for
module
,
usage_key
in
modules
:
if
module
.
state
is
None
:
if
module
.
state
is
None
:
continue
continue
state
=
json
.
loads
(
module
.
state
)
state
=
json
.
loads
(
module
.
state
)
state_length
+=
len
(
module
.
state
)
# If the state is the empty dict, then it has been deleted, and so
# If the state is the empty dict, then it has been deleted, and so
# conformant UserStateClients should treat it as if it doesn't exist.
# conformant UserStateClients should treat it as if it doesn't exist.
...
@@ -129,8 +155,14 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
...
@@ -129,8 +155,14 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
for
field
in
fields
for
field
in
fields
if
field
in
state
if
field
in
state
}
}
block_count
+=
1
yield
XBlockUserState
(
username
,
usage_key
,
state
,
module
.
modified
,
scope
)
yield
XBlockUserState
(
username
,
usage_key
,
state
,
module
.
modified
,
scope
)
# The rest of this method exists only to submit DataDog events.
# Remove it once we're no longer interested in the data.
self
.
_ddog_histogram
(
evt_time
,
'get_many.blks_out'
,
block_count
)
self
.
_ddog_histogram
(
evt_time
,
'get_many.blks_size'
,
state_length
)
def
set_many
(
self
,
username
,
block_keys_to_state
,
scope
=
Scope
.
user_state
):
def
set_many
(
self
,
username
,
block_keys_to_state
,
scope
=
Scope
.
user_state
):
"""
"""
Set fields for a particular XBlock.
Set fields for a particular XBlock.
...
@@ -155,6 +187,8 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
...
@@ -155,6 +187,8 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
else
:
else
:
user
=
User
.
objects
.
get
(
username
=
username
)
user
=
User
.
objects
.
get
(
username
=
username
)
evt_time
=
time
()
for
usage_key
,
state
in
block_keys_to_state
.
items
():
for
usage_key
,
state
in
block_keys_to_state
.
items
():
student_module
,
created
=
StudentModule
.
objects
.
get_or_create
(
student_module
,
created
=
StudentModule
.
objects
.
get_or_create
(
student
=
user
,
student
=
user
,
...
@@ -166,16 +200,43 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
...
@@ -166,16 +200,43 @@ class DjangoXBlockUserStateClient(XBlockUserStateClient):
},
},
)
)
num_fields_before
=
num_fields_after
=
num_new_fields_set
=
len
(
state
)
num_fields_updated
=
0
if
not
created
:
if
not
created
:
if
student_module
.
state
is
None
:
if
student_module
.
state
is
None
:
current_state
=
{}
current_state
=
{}
else
:
else
:
current_state
=
json
.
loads
(
student_module
.
state
)
current_state
=
json
.
loads
(
student_module
.
state
)
num_fields_before
=
len
(
current_state
)
current_state
.
update
(
state
)
current_state
.
update
(
state
)
num_fields_after
=
len
(
current_state
)
student_module
.
state
=
json
.
dumps
(
current_state
)
student_module
.
state
=
json
.
dumps
(
current_state
)
# We just read this object, so we know that we can do an update
# We just read this object, so we know that we can do an update
student_module
.
save
(
force_update
=
True
)
student_module
.
save
(
force_update
=
True
)
# The rest of this method exists only to submit DataDog events.
# Remove it once we're no longer interested in the data.
#
# Record whether a state row has been created or updated.
if
created
:
self
.
_ddog_increment
(
evt_time
,
'set_many.state_created'
)
else
:
self
.
_ddog_increment
(
evt_time
,
'set_many.state_updated'
)
# Event to record number of fields sent in to set/set_many.
self
.
_ddog_histogram
(
evt_time
,
'set_many.fields_in'
,
len
(
state
))
# Event to record number of new fields set in set/set_many.
num_new_fields_set
=
num_fields_after
-
num_fields_before
self
.
_ddog_histogram
(
evt_time
,
'set_many.fields_set'
,
num_new_fields_set
)
# Event to record number of existing fields updated in set/set_many.
num_fields_updated
=
max
(
0
,
len
(
state
)
-
num_new_fields_set
)
self
.
_ddog_histogram
(
evt_time
,
'set_many.fields_updated'
,
num_fields_updated
)
# Event for the entire set_many call.
self
.
_ddog_histogram
(
evt_time
,
'set_many.blks_updated'
,
len
(
block_keys_to_state
))
def
delete_many
(
self
,
username
,
block_keys
,
scope
=
Scope
.
user_state
,
fields
=
None
):
def
delete_many
(
self
,
username
,
block_keys
,
scope
=
Scope
.
user_state
,
fields
=
None
):
"""
"""
Delete the stored XBlock state for a many xblock usages.
Delete the stored XBlock state for a many xblock usages.
...
...
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