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
2117d168
Commit
2117d168
authored
Feb 27, 2015
by
Dino Cikatic
Committed by
marjev
Mar 19, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SOL-217 Adding basic analytics events logging for courseware search and index
parent
d182b8db
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
114 additions
and
12 deletions
+114
-12
cms/djangoapps/contentstore/views/tests/test_course_index.py
+2
-4
common/lib/xmodule/xmodule/modulestore/courseware_index.py
+68
-1
common/lib/xmodule/xmodule/modulestore/mongo/draft.py
+1
-1
common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
+1
-1
common/lib/xmodule/xmodule/tests/__init__.py
+4
-1
lms/static/js/search/collections/search_collection.js
+4
-1
lms/static/js/search/views/search_item_view.js
+32
-2
lms/static/js/search/views/search_list_view.js
+1
-1
lms/static/js/spec/search/search_spec.js
+1
-0
No files found.
cms/djangoapps/contentstore/views/tests/test_course_index.py
View file @
2117d168
...
@@ -571,15 +571,13 @@ class TestCourseReIndex(CourseTestCase):
...
@@ -571,15 +571,13 @@ class TestCourseReIndex(CourseTestCase):
self
.
assertEqual
(
response
[
'results'
],
[])
self
.
assertEqual
(
response
[
'results'
],
[])
# Start manual reindex
# Start manual reindex
errors
=
CoursewareSearchIndexer
.
do_course_reindex
(
modulestore
(),
self
.
course
.
id
)
CoursewareSearchIndexer
.
do_course_reindex
(
modulestore
(),
self
.
course
.
id
)
self
.
assertEqual
(
errors
,
None
)
self
.
html
.
display_name
=
"My expanded HTML"
self
.
html
.
display_name
=
"My expanded HTML"
modulestore
()
.
update_item
(
self
.
html
,
ModuleStoreEnum
.
UserID
.
test
)
modulestore
()
.
update_item
(
self
.
html
,
ModuleStoreEnum
.
UserID
.
test
)
# Start manual reindex
# Start manual reindex
errors
=
CoursewareSearchIndexer
.
do_course_reindex
(
modulestore
(),
self
.
course
.
id
)
CoursewareSearchIndexer
.
do_course_reindex
(
modulestore
(),
self
.
course
.
id
)
self
.
assertEqual
(
errors
,
None
)
# Check results indexed now
# Check results indexed now
response
=
perform_search
(
response
=
perform_search
(
...
...
common/lib/xmodule/xmodule/modulestore/courseware_index.py
View file @
2117d168
...
@@ -3,6 +3,7 @@ from __future__ import absolute_import
...
@@ -3,6 +3,7 @@ from __future__ import absolute_import
import
logging
import
logging
from
django.conf
import
settings
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
opaque_keys.edx.locator
import
CourseLocator
from
opaque_keys.edx.locator
import
CourseLocator
from
search.search_engine_base
import
SearchEngine
from
search.search_engine_base
import
SearchEngine
...
@@ -10,6 +11,7 @@ from search.search_engine_base import SearchEngine
...
@@ -10,6 +11,7 @@ from search.search_engine_base import SearchEngine
from
.
import
ModuleStoreEnum
from
.
import
ModuleStoreEnum
from
.exceptions
import
ItemNotFoundError
from
.exceptions
import
ItemNotFoundError
# Use default index and document names for now
# Use default index and document names for now
INDEX_NAME
=
"courseware_index"
INDEX_NAME
=
"courseware_index"
DOCUMENT_TYPE
=
"courseware_content"
DOCUMENT_TYPE
=
"courseware_content"
...
@@ -36,6 +38,7 @@ class CoursewareSearchIndexer(object):
...
@@ -36,6 +38,7 @@ class CoursewareSearchIndexer(object):
Add to courseware search index from given location and its children
Add to courseware search index from given location and its children
"""
"""
error_list
=
[]
error_list
=
[]
indexed_count
=
0
# TODO - inline for now, need to move this out to a celery task
# TODO - inline for now, need to move this out to a celery task
searcher
=
SearchEngine
.
get_search_engine
(
INDEX_NAME
)
searcher
=
SearchEngine
.
get_search_engine
(
INDEX_NAME
)
if
not
searcher
:
if
not
searcher
:
...
@@ -115,6 +118,7 @@ class CoursewareSearchIndexer(object):
...
@@ -115,6 +118,7 @@ class CoursewareSearchIndexer(object):
remove_index_item_location
(
location
)
remove_index_item_location
(
location
)
else
:
else
:
index_item_location
(
location
,
None
)
index_item_location
(
location
,
None
)
indexed_count
+=
1
except
Exception
as
err
:
# pylint: disable=broad-except
except
Exception
as
err
:
# pylint: disable=broad-except
# broad exception so that index operation does not prevent the rest of the application from working
# broad exception so that index operation does not prevent the rest of the application from working
log
.
exception
(
log
.
exception
(
...
@@ -127,9 +131,72 @@ class CoursewareSearchIndexer(object):
...
@@ -127,9 +131,72 @@ class CoursewareSearchIndexer(object):
if
raise_on_error
and
error_list
:
if
raise_on_error
and
error_list
:
raise
SearchIndexingError
(
_
(
'Error(s) present during indexing'
),
error_list
)
raise
SearchIndexingError
(
_
(
'Error(s) present during indexing'
),
error_list
)
return
indexed_count
@classmethod
def
do_publish_index
(
cls
,
modulestore
,
location
,
delete
=
False
,
raise_on_error
=
False
):
"""
Add to courseware search index published section and children
"""
indexed_count
=
cls
.
add_to_search_index
(
modulestore
,
location
,
delete
,
raise_on_error
)
CoursewareSearchIndexer
.
_track_index_request
(
'edx.course.index.published'
,
indexed_count
,
str
(
location
))
return
indexed_count
@classmethod
@classmethod
def
do_course_reindex
(
cls
,
modulestore
,
course_key
):
def
do_course_reindex
(
cls
,
modulestore
,
course_key
):
"""
"""
(Re)index all content within the given course
(Re)index all content within the given course
"""
"""
return
cls
.
add_to_search_index
(
modulestore
,
course_key
,
delete
=
False
,
raise_on_error
=
True
)
indexed_count
=
cls
.
add_to_search_index
(
modulestore
,
course_key
,
delete
=
False
,
raise_on_error
=
True
)
CoursewareSearchIndexer
.
_track_index_request
(
'edx.course.index.reindexed'
,
indexed_count
)
return
indexed_count
@staticmethod
def
_track_index_request
(
event_name
,
indexed_count
,
location
=
None
):
"""Track content index requests.
Arguments:
location (str): The ID of content to be indexed.
event_name (str): Name of the event to be logged.
Returns:
None
"""
from
eventtracking
import
tracker
as
track
tracker
=
track
.
get_tracker
()
tracking_context
=
tracker
.
resolve_context
()
# pylint: disable=no-member
data
=
{
"indexed_count"
:
indexed_count
,
'category'
:
'courseware_index'
,
}
if
location
:
data
[
'location_id'
]
=
location
tracker
.
emit
(
event_name
,
data
)
try
:
if
settings
.
FEATURES
.
get
(
'SEGMENT_IO_LMS'
)
and
hasattr
(
settings
,
'SEGMENT_IO_LMS_KEY'
):
#Google Analytics - log index content request
import
analytics
analytics
.
track
(
event_name
,
data
,
context
=
{
'Google Analytics'
:
{
'clientId'
:
tracking_context
.
get
(
'client_id'
)
}
}
)
except
Exception
:
# pylint: disable=broad-except
# Capturing all exceptions thrown while tracking analytics events. We do not want
# an operation to fail because of an analytics event, so we will capture these
# errors in the logs.
log
.
exception
(
u'Unable to emit {0} event for content indexing.'
.
format
(
event_name
)
)
common/lib/xmodule/xmodule/modulestore/mongo/draft.py
View file @
2117d168
...
@@ -732,7 +732,7 @@ class DraftModuleStore(MongoModuleStore):
...
@@ -732,7 +732,7 @@ class DraftModuleStore(MongoModuleStore):
self
.
signal_handler
.
send
(
"course_published"
,
course_key
=
course_key
)
self
.
signal_handler
.
send
(
"course_published"
,
course_key
=
course_key
)
# Now it's been published, add the object to the courseware search index so that it appears in search results
# Now it's been published, add the object to the courseware search index so that it appears in search results
CoursewareSearchIndexer
.
add_to_searc
h_index
(
self
,
location
)
CoursewareSearchIndexer
.
do_publis
h_index
(
self
,
location
)
return
self
.
get_item
(
as_published
(
location
))
return
self
.
get_item
(
as_published
(
location
))
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
View file @
2117d168
...
@@ -357,7 +357,7 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli
...
@@ -357,7 +357,7 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli
)
)
# Now it's been published, add the object to the courseware search index so that it appears in search results
# Now it's been published, add the object to the courseware search index so that it appears in search results
CoursewareSearchIndexer
.
add_to_searc
h_index
(
self
,
location
)
CoursewareSearchIndexer
.
do_publis
h_index
(
self
,
location
)
return
self
.
get_item
(
location
.
for_branch
(
ModuleStoreEnum
.
BranchName
.
published
),
**
kwargs
)
return
self
.
get_item
(
location
.
for_branch
(
ModuleStoreEnum
.
BranchName
.
published
),
**
kwargs
)
...
...
common/lib/xmodule/xmodule/tests/__init__.py
View file @
2117d168
...
@@ -18,6 +18,8 @@ from lazy import lazy
...
@@ -18,6 +18,8 @@ from lazy import lazy
from
mock
import
Mock
from
mock
import
Mock
from
operator
import
attrgetter
from
operator
import
attrgetter
from
path
import
path
from
path
import
path
from
eventtracking
import
tracker
from
eventtracking.django
import
DjangoTracker
from
xblock.field_data
import
DictFieldData
from
xblock.field_data
import
DictFieldData
from
xblock.fields
import
ScopeIds
,
Scope
,
Reference
,
ReferenceList
,
ReferenceValueDict
from
xblock.fields
import
ScopeIds
,
Scope
,
Reference
,
ReferenceList
,
ReferenceValueDict
...
@@ -49,7 +51,6 @@ open_ended_grading_interface = {
...
@@ -49,7 +51,6 @@ open_ended_grading_interface = {
'grading_controller'
:
'grading_controller'
,
'grading_controller'
:
'grading_controller'
,
}
}
class
TestModuleSystem
(
ModuleSystem
):
# pylint: disable=abstract-method
class
TestModuleSystem
(
ModuleSystem
):
# pylint: disable=abstract-method
"""
"""
ModuleSystem for testing
ModuleSystem for testing
...
@@ -59,6 +60,8 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method
...
@@ -59,6 +60,8 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method
kwargs
.
setdefault
(
'id_reader'
,
id_manager
)
kwargs
.
setdefault
(
'id_reader'
,
id_manager
)
kwargs
.
setdefault
(
'id_generator'
,
id_manager
)
kwargs
.
setdefault
(
'id_generator'
,
id_manager
)
kwargs
.
setdefault
(
'services'
,
{})
.
setdefault
(
'field-data'
,
DictFieldData
({}))
kwargs
.
setdefault
(
'services'
,
{})
.
setdefault
(
'field-data'
,
DictFieldData
({}))
self
.
tracker
=
DjangoTracker
()
tracker
.
register_tracker
(
self
.
tracker
)
super
(
TestModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
super
(
TestModuleSystem
,
self
)
.
__init__
(
**
kwargs
)
def
handler_url
(
self
,
block
,
handler
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
def
handler_url
(
self
,
block
,
handler
,
suffix
=
''
,
query
=
''
,
thirdparty
=
False
):
...
...
lms/static/js/search/collections/search_collection.js
View file @
2117d168
...
@@ -62,7 +62,10 @@ define([
...
@@ -62,7 +62,10 @@ define([
},
},
error
:
function
(
self
,
xhr
)
{
error
:
function
(
self
,
xhr
)
{
self
.
trigger
(
'error'
);
self
.
trigger
(
'error'
);
}
},
add
:
true
,
reset
:
false
,
remove
:
false
});
});
},
},
...
...
lms/static/js/search/views/search_item_view.js
View file @
2117d168
...
@@ -4,8 +4,9 @@ define([
...
@@ -4,8 +4,9 @@ define([
'jquery'
,
'jquery'
,
'underscore'
,
'underscore'
,
'backbone'
,
'backbone'
,
'gettext'
'gettext'
,
],
function
(
$
,
_
,
Backbone
,
gettext
)
{
'logger'
],
function
(
$
,
_
,
Backbone
,
gettext
,
Logger
)
{
'use strict'
;
'use strict'
;
return
Backbone
.
View
.
extend
({
return
Backbone
.
View
.
extend
({
...
@@ -17,6 +18,10 @@ define([
...
@@ -17,6 +18,10 @@ define([
'aria-label'
:
'search result'
'aria-label'
:
'search result'
},
},
events
:
{
'click .search-results-item a'
:
'logSearchItem'
,
},
initialize
:
function
()
{
initialize
:
function
()
{
var
template_name
=
(
this
.
model
.
attributes
.
content_type
===
"Sequence"
)
?
'#search_item_seq-tpl'
:
'#search_item-tpl'
;
var
template_name
=
(
this
.
model
.
attributes
.
content_type
===
"Sequence"
)
?
'#search_item_seq-tpl'
:
'#search_item-tpl'
;
this
.
tpl
=
_
.
template
(
$
(
template_name
).
html
());
this
.
tpl
=
_
.
template
(
$
(
template_name
).
html
());
...
@@ -25,9 +30,34 @@ define([
...
@@ -25,9 +30,34 @@ define([
render
:
function
()
{
render
:
function
()
{
this
.
$el
.
html
(
this
.
tpl
(
this
.
model
.
attributes
));
this
.
$el
.
html
(
this
.
tpl
(
this
.
model
.
attributes
));
return
this
;
return
this
;
},
logSearchItem
:
function
(
event
)
{
event
.
preventDefault
();
var
target
=
this
.
model
.
id
;
var
link
=
$
(
event
.
target
).
attr
(
'href'
);
var
collection
=
this
.
model
.
collection
;
var
page
=
collection
.
page
;
var
pageSize
=
collection
.
pageSize
;
var
searchTerm
=
collection
.
searchTerm
;
var
index
=
collection
.
indexOf
(
this
.
model
);
Logger
.
log
(
"edx.course.search.result_selected"
,
{
"search_term"
:
searchTerm
,
"result_position"
:
(
page
*
pageSize
+
index
),
"result_link"
:
target
});
window
.
analytics
.
track
(
'"edx.course.search.result_selected"'
,
{
category
:
'courseware_search'
,
search_term
:
searchTerm
,
result_position
:
(
page
*
pageSize
+
index
),
result_link
:
target
});
window
.
location
.
href
=
link
;
}
}
});
});
});
});
})(
define
||
RequireJS
.
define
);
})(
define
||
RequireJS
.
define
);
lms/static/js/search/views/search_list_view.js
View file @
2117d168
...
@@ -57,7 +57,7 @@ define([
...
@@ -57,7 +57,7 @@ define([
var
item
=
new
SearchItemView
({
model
:
result
});
var
item
=
new
SearchItemView
({
model
:
result
});
return
item
.
render
().
el
;
return
item
.
render
().
el
;
});
});
this
.
$el
.
find
(
'.search-results'
).
append
(
items
);
this
.
$el
.
find
(
'.search-results'
).
html
(
items
);
},
},
totalCountMsg
:
function
()
{
totalCountMsg
:
function
()
{
...
...
lms/static/js/spec/search/search_spec.js
View file @
2117d168
...
@@ -353,6 +353,7 @@ define([
...
@@ -353,6 +353,7 @@ define([
expect
(
this
.
listView
.
$el
).
toContainHtml
(
'Search Results'
);
expect
(
this
.
listView
.
$el
).
toContainHtml
(
'Search Results'
);
expect
(
this
.
listView
.
$el
).
toContainHtml
(
'this is a short excerpt'
);
expect
(
this
.
listView
.
$el
).
toContainHtml
(
'this is a short excerpt'
);
searchResults
[
1
]
=
searchResults
[
0
]
this
.
collection
.
set
(
searchResults
);
this
.
collection
.
set
(
searchResults
);
this
.
collection
.
totalCount
=
2
;
this
.
collection
.
totalCount
=
2
;
this
.
listView
.
renderNext
();
this
.
listView
.
renderNext
();
...
...
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