Commit 71960974 by pmitros

Merge pull request #49 from MITx/specific-error-handling

Specific error handling
parents 5494f46c a271c71f
import logging
import urllib
import json
from django.conf import settings
from django.core.context_processors import csrf
......@@ -16,6 +17,8 @@ from lxml import etree
from module_render import render_module, make_track_function, I4xSystem
from models import StudentModule
from student.models import UserProfile
from util.errors import record_exception
from util.views import accepts
from multicourse import multicourse_settings
import courseware.content_parser as content_parser
......@@ -110,12 +113,16 @@ def render_section(request, section):
if 'coursename' in request.session: coursename = request.session['coursename']
else: coursename = None
# try:
dom = content_parser.section_file(user, section, coursename)
#except:
# raise Http404
try:
dom = content_parser.section_file(user, section, coursename)
except:
record_exception(log, "Unable to parse courseware xml")
return render_to_response('courseware-error.html', {})
accordion=render_accordion(request, '', '', '')
context = {
'csrf': csrf(request)['csrf_token'],
'accordion': render_accordion(request, '', '', '')
}
module_ids = dom.xpath("//@id")
......@@ -125,15 +132,20 @@ def render_section(request, section):
else:
module_object_preload = []
module=render_module(user, request, dom, module_object_preload)
if 'init_js' not in module:
module['init_js']=''
context={'init':module['init_js'],
'accordion':accordion,
'content':module['content'],
'csrf':csrf(request)['csrf_token']}
try:
module = render_module(user, request, dom, module_object_preload)
except:
record_exception(log, "Unable to load module")
context.update({
'init': '',
'content': render_to_string("module-error.html", {}),
})
return render_to_response('courseware.html', context)
context.update({
'init':module.get('init_js', ''),
'content':module['content'],
})
result = render_to_response('courseware.html', context)
return result
......@@ -167,22 +179,22 @@ def index(request, course=None, chapter="Using the System", section="Hints"):
if not multicourse_settings.is_valid_course(course):
return redirect('/')
#import logging
#log = logging.getLogger("mitx")
#log.info( "DEBUG: "+str(user) )
request.session['coursename'] = course # keep track of current course being viewed in django's request.session
dom = content_parser.course_file(user,course) # also pass course to it, for course-specific XML path
try:
dom = content_parser.course_file(user,course) # also pass course to it, for course-specific XML path
except:
record_exception(log, "Unable to parse courseware xml")
return render_to_response('courseware-error.html', {})
dom_module = dom.xpath("//course[@name=$course]/chapter[@name=$chapter]//section[@name=$section]/*[1]",
course=course, chapter=chapter, section=section)
if len(dom_module) == 0:
module = None
else:
module = dom_module[0]
accordion=render_accordion(request, course, chapter, section)
module_ids = dom.xpath("//course[@name=$course]/chapter[@name=$chapter]//section[@name=$section]//@id",
course=course, chapter=chapter, section=section)
......@@ -191,18 +203,27 @@ def index(request, course=None, chapter="Using the System", section="Hints"):
module_id__in=module_ids))
else:
module_object_preload = []
module=render_module(user, request, module, module_object_preload)
if 'init_js' not in module:
module['init_js']=''
context={'init':module['init_js'],
'accordion':accordion,
'content':module['content'],
'COURSE_TITLE':multicourse_settings.get_course_title(course),
'csrf':csrf(request)['csrf_token']}
context = {
'csrf': csrf(request)['csrf_token'],
'accordion': render_accordion(request, course, chapter, section),
'COURSE_TITLE':multicourse_settings.get_course_title(course),
}
try:
module = render_module(user, request, module, module_object_preload)
except:
record_exception(log, "Unable to load module")
context.update({
'init': '',
'content': render_to_string("module-error.html", {}),
})
return render_to_response('courseware.html', context)
context.update({
'init': module.get('init_js', ''),
'content': module['content'],
})
result = render_to_response('courseware.html', context)
return result
......@@ -234,7 +255,15 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
else: coursename = None
# Grab the XML corresponding to the request from course.xml
xml = content_parser.module_xml(request.user, module, 'id', id, coursename)
try:
xml = content_parser.module_xml(request.user, module, 'id', id, coursename)
except:
record_exception(log, "Unable to load module during ajax call")
if accepts(request, 'text/html'):
return render_to_response("module-error.html", {})
else:
response = HttpResponse(json.dumps({'success': "We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible"}))
return response
# Create the module
system = I4xSystem(track_function = make_track_function(request),
......@@ -242,10 +271,20 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
ajax_url = ajax_url,
filestore = None
)
instance=courseware.modules.get_module_class(module)(system,
xml,
id,
state=oldstate)
try:
instance=courseware.modules.get_module_class(module)(system,
xml,
id,
state=oldstate)
except:
record_exception(log, "Unable to load module instance during ajax call")
if accepts(request, 'text/html'):
return render_to_response("module-error.html", {})
else:
response = HttpResponse(json.dumps({'success': "We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible"}))
return response
# Let the module handle the AJAX
ajax_return=instance.handle_ajax(dispatch, request.POST)
# Save the state back to the database
......
......@@ -79,6 +79,7 @@ TEMPLATE_DIRS = (
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
'django.core.context_processors.static',
'askbot.context.application_settings',
'django.contrib.messages.context_processors.messages',
#'django.core.context_processors.i18n',
......@@ -105,6 +106,20 @@ DEV_CONTENT = True
TRACK_MAX_EVENT = 10000
DEBUG_TRACK_LOG = False
MITX_ROOT_URL = ''
COURSE_NAME = "6.002_Spring_2012"
COURSE_NUMBER = "6.002x"
COURSE_TITLE = "Circuits and Electronics"
ROOT_URLCONF = 'urls'
### Dark code. Should be enabled in local settings for devel.
ENABLE_MULTICOURSE = False # set to False to disable multicourse display (see lib.util.views.mitxhome)
###
############################### DJANGO BUILT-INS ###############################
# Change DEBUG/TEMPLATE_DEBUG in your environment settings files, not here
DEBUG = False
......@@ -159,14 +174,22 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
AWS_QUERYSTRING_EXPIRE = 10 * 365 * 24 * 60 * 60 # 10 years
################################### ASKBOT #####################################
LIVESETTINGS_OPTIONS['MITX_ROOT_URL'] = MITX_ROOT_URL
skin_settings = LIVESETTINGS_OPTIONS[1]['SETTINGS']['GENERAL_SKIN_SETTINGS']
skin_settings['SITE_FAVICON'] = unicode(MITX_ROOT_URL) + skin_settings['SITE_FAVICON']
skin_settings['SITE_LOGO_URL'] = unicode(MITX_ROOT_URL) + skin_settings['SITE_LOGO_URL']
skin_settings['LOCAL_LOGIN_ICON'] = unicode(MITX_ROOT_URL) + skin_settings['LOCAL_LOGIN_ICON']
LIVESETTINGS_OPTIONS[1]['SETTINGS']['LOGIN_PROVIDERS']['WORDPRESS_SITE_ICON'] = unicode(MITX_ROOT_URL) + LIVESETTINGS_OPTIONS[1]['SETTINGS']['LOGIN_PROVIDERS']['WORDPRESS_SITE_ICON']
LIVESETTINGS_OPTIONS[1]['SETTINGS']['LICENSE_SETTINGS']['LICENSE_LOGO_URL'] = unicode(MITX_ROOT_URL) + LIVESETTINGS_OPTIONS[1]['SETTINGS']['LICENSE_SETTINGS']['LICENSE_LOGO_URL']
ASKBOT_EXTRA_SKINS_DIR = ASKBOT_ROOT / "askbot" / "skins"
ASKBOT_ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
ASKBOT_MAX_UPLOAD_FILE_SIZE = 1024 * 1024 # result in bytes
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
ASKBOT_URL = 'discussion/'
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/'
LOGIN_REDIRECT_URL = MITX_ROOT_URL + '/'
LOGIN_URL = MITX_ROOT_URL + '/'
ALLOW_UNICODE_SLUGS = False
ASKBOT_USE_STACKEXCHANGE_URLS = False # mimic url scheme of stackexchange
......@@ -181,6 +204,9 @@ djcelery.setup_loader()
SIMPLE_WIKI_REQUIRE_LOGIN_EDIT = True
SIMPLE_WIKI_REQUIRE_LOGIN_VIEW = False
################################# Jasmine ###################################
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/templates/coffee'
################################# Middleware ###################################
# List of finder classes that know how to find static files in
# various locations.
......@@ -199,6 +225,7 @@ TEMPLATE_LOADERS = (
MIDDLEWARE_CLASSES = (
'util.middleware.ExceptionLoggingMiddleware',
'util.middleware.AcceptMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
......@@ -245,6 +272,9 @@ INSTALLED_APPS = (
'track',
'util',
# For testing
'django_jasmine',
# For Askbot
'django.contrib.sitemaps',
'django.contrib.admin',
......
......@@ -10,8 +10,8 @@ sessions. Assumes structure:
from envs.common import *
from envs.logsettings import get_logger_config
DEBUG = True
TEMPLATE_DEBUG = True
DEBUG = False
TEMPLATE_DEBUG = False
LOGGING = get_logger_config(ENV_ROOT / "log",
logging_env="dev",
......
import newrelic.agent
import sys
def record_exception(logger, msg, params={}, ignore_errors=[]):
logger.exception(msg)
newrelic.agent.record_exception(*sys.exc_info())
......@@ -13,3 +13,4 @@ class ExceptionLoggingMiddleware(object):
def process_exception(self, request, exception):
log.exception(exception)
return HttpResponseServerError("Server Error - Please try again later.")
......@@ -66,3 +66,29 @@ def mitxhome(request):
if settings.ENABLE_MULTICOURSE:
return render_to_response("mitxhome.html", {})
return info(request)
# From http://djangosnippets.org/snippets/1042/
def parse_accept_header(accept):
"""Parse the Accept header *accept*, returning a list with pairs of
(media_type, q_value), ordered by q values.
"""
result = []
for media_range in accept.split(","):
parts = media_range.split(";")
media_type = parts.pop(0)
media_params = []
q = 1.0
for part in parts:
(key, value) = part.lstrip().split("=", 1)
if key == "q":
q = float(value)
else:
media_params.append((key, value))
result.append((media_type, tuple(media_params), q))
result.sort(lambda x, y: -cmp(x[2], y[2]))
return result
def accepts(request, media_type):
"""Return whether this request has an Accept header that matches type"""
accept = parse_accept_header(request.META.get("HTTP_ACCEPT", ""))
return media_type in [t for (t, p, q) in accept]
......@@ -133,6 +133,7 @@ TEMPLATE_LOADERS = (
MIDDLEWARE_CLASSES = (
'util.middleware.ExceptionLoggingMiddleware',
'util.middleware.AcceptMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
......
<%inherit file="main.html" />
<%block name="bodyclass">courseware</%block>
<%block name="title"><title>Courseware – MITx 6.002x</title></%block>
<%include file="navigation.html" args="active_page='courseware'" />
<section class="main-content">
<section class="outside-app">
<h1>There has been an error on the <em>MITx</em> servers</h1>
<p>We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible. Please email us at <a href="mailto:technical@mitx.mit.edu">technical@mitx.mit.edu</a> to report any problems or downtime.</p>
</section>
</section>
<section class="outside-app">
<h1>There has been an error on the <em>MITx</em> servers</h1>
<p>We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible. Please email us at <a href="mailto:technical@mitx.mit.edu">technical@mitx.mit.edu</a> to report any problems or downtime.</p>
</section>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment