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
dba12c09
Commit
dba12c09
authored
Dec 30, 2015
by
David Ormsbee
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11088 from edx/ormsbee/seq_new_relic_tagging
Add New Relic instrumentation to SequenceModule.
parents
4f185abc
02190715
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
79 additions
and
2 deletions
+79
-2
common/lib/xmodule/xmodule/seq_module.py
+79
-2
No files found.
common/lib/xmodule/xmodule/seq_module.py
View file @
dba12c09
...
@@ -3,7 +3,7 @@ xModule implementation of a learning sequence
...
@@ -3,7 +3,7 @@ xModule implementation of a learning sequence
"""
"""
# pylint: disable=abstract-method
# pylint: disable=abstract-method
import
collections
import
json
import
json
import
logging
import
logging
from
pkg_resources
import
resource_string
from
pkg_resources
import
resource_string
...
@@ -13,6 +13,7 @@ from lxml import etree
...
@@ -13,6 +13,7 @@ from lxml import etree
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.fields
import
Integer
,
Scope
,
Boolean
,
String
from
xblock.fields
import
Integer
,
Scope
,
Boolean
,
String
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
import
newrelic.agent
from
.exceptions
import
NotFoundError
from
.exceptions
import
NotFoundError
from
.fields
import
Date
from
.fields
import
Date
...
@@ -191,6 +192,11 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
...
@@ -191,6 +192,11 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
context
[
"username"
]
=
self
.
runtime
.
service
(
self
,
"user"
)
.
get_current_user
()
.
opt_attrs
[
'edx-platform.username'
]
context
[
"username"
]
=
self
.
runtime
.
service
(
self
,
"user"
)
.
get_current_user
()
.
opt_attrs
[
'edx-platform.username'
]
display_names
=
[
self
.
get_parent
()
.
display_name
or
''
,
self
.
display_name
or
''
]
display_names
=
[
self
.
get_parent
()
.
display_name
or
''
,
self
.
display_name
or
''
]
# We do this up here because proctored exam functionality could bypass
# rendering after this section.
self
.
_capture_basic_metrics
()
# Is this sequential part of a timed or proctored exam?
# Is this sequential part of a timed or proctored exam?
if
self
.
is_time_limited
:
if
self
.
is_time_limited
:
view_html
=
self
.
_time_limited_student_view
(
context
)
view_html
=
self
.
_time_limited_student_view
(
context
)
...
@@ -201,7 +207,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
...
@@ -201,7 +207,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
fragment
.
add_content
(
view_html
)
fragment
.
add_content
(
view_html
)
return
fragment
return
fragment
for
child
in
self
.
get_display_items
():
display_items
=
self
.
get_display_items
()
for
child
in
display_items
:
is_bookmarked
=
bookmarks_service
.
is_bookmarked
(
usage_key
=
child
.
scope_ids
.
usage_id
)
is_bookmarked
=
bookmarks_service
.
is_bookmarked
(
usage_key
=
child
.
scope_ids
.
usage_id
)
context
[
"bookmarked"
]
=
is_bookmarked
context
[
"bookmarked"
]
=
is_bookmarked
...
@@ -238,8 +245,78 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
...
@@ -238,8 +245,78 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
fragment
.
add_content
(
self
.
system
.
render_template
(
"seq_module.html"
,
params
))
fragment
.
add_content
(
self
.
system
.
render_template
(
"seq_module.html"
,
params
))
self
.
_capture_full_seq_item_metrics
(
display_items
)
self
.
_capture_current_unit_metrics
(
display_items
)
# Get all descendant XBlock types and counts
return
fragment
return
fragment
def
_locations_in_subtree
(
self
,
node
):
"""
The usage keys for all descendants of an XBlock/XModule as a flat list.
Includes the location of the node passed in.
"""
stack
=
[
node
]
locations
=
[]
while
stack
:
curr
=
stack
.
pop
()
locations
.
append
(
curr
.
location
)
if
curr
.
has_children
:
stack
.
extend
(
curr
.
get_children
())
return
locations
def
_capture_basic_metrics
(
self
):
"""
Capture basic information about this sequence in New Relic.
"""
newrelic
.
agent
.
add_custom_parameter
(
'seq.block_id'
,
unicode
(
self
.
location
))
newrelic
.
agent
.
add_custom_parameter
(
'seq.display_name'
,
self
.
display_name
or
''
)
newrelic
.
agent
.
add_custom_parameter
(
'seq.position'
,
self
.
position
)
newrelic
.
agent
.
add_custom_parameter
(
'seq.is_time_limited'
,
self
.
is_time_limited
)
def
_capture_full_seq_item_metrics
(
self
,
display_items
):
"""
Capture information about the number and types of XBlock content in
the sequence as a whole. We send this information to New Relic so that
we can do better performance analysis of courseware.
"""
# Basic count of the number of Units (a.k.a. VerticalBlocks) we have in
# this learning sequence
newrelic
.
agent
.
add_custom_parameter
(
'seq.num_units'
,
len
(
display_items
))
# Count of all modules (leaf nodes) in this sequence (e.g. videos,
# problems, etc.) The units (verticals) themselves are not counted.
all_item_keys
=
self
.
_locations_in_subtree
(
self
)
newrelic
.
agent
.
add_custom_parameter
(
'seq.num_items'
,
len
(
all_item_keys
))
# Count of all modules by block_type (e.g. "video": 2, "discussion": 4)
block_counts
=
collections
.
Counter
(
usage_key
.
block_type
for
usage_key
in
all_item_keys
)
for
block_type
,
count
in
block_counts
.
items
():
newrelic
.
agent
.
add_custom_parameter
(
'seq.block_counts.{}'
.
format
(
block_type
),
count
)
def
_capture_current_unit_metrics
(
self
,
display_items
):
"""
Capture information about the current selected Unit within the Sequence.
"""
# Positions are stored with indexing starting at 1. If we get into a
# weird state where the saved position is out of bounds (e.g. the
# content was changed), avoid going into any details about this unit.
if
1
<=
self
.
position
<=
len
(
display_items
):
# Basic info about the Unit...
current
=
display_items
[
self
.
position
-
1
]
newrelic
.
agent
.
add_custom_parameter
(
'seq.current.block_id'
,
unicode
(
current
.
location
))
newrelic
.
agent
.
add_custom_parameter
(
'seq.current.display_name'
,
current
.
display_name
or
''
)
# Examining all items inside the Unit (or split_test, conditional, etc.)
child_locs
=
self
.
_locations_in_subtree
(
current
)
newrelic
.
agent
.
add_custom_parameter
(
'seq.current.num_items'
,
len
(
child_locs
))
curr_block_counts
=
collections
.
Counter
(
usage_key
.
block_type
for
usage_key
in
child_locs
)
for
block_type
,
count
in
curr_block_counts
.
items
():
newrelic
.
agent
.
add_custom_parameter
(
'seq.current.block_counts.{}'
.
format
(
block_type
),
count
)
def
_time_limited_student_view
(
self
,
context
):
def
_time_limited_student_view
(
self
,
context
):
"""
"""
Delegated rendering of a student view when in a time
Delegated rendering of a student view when in a time
...
...
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