コード例 #1
0
ファイル: api.py プロジェクト: artfb/alpaca
def report(request):
    if 'Alpaca-Environment' not in request.headers:
        raise httpexceptions.HTTPBadRequest(
            "Missing Alpaca-Environment header."
        )
    try:
        environment = DBSession.query(Environment).filter(
            Environment.name == request.headers['Alpaca-Environment']
        ).one()
    except database_exceptions.NoResultFound:
        raise httpexceptions.HTTPBadRequest(
            "Unknown environment."
        )
    if 'Alpaca-Signature' not in request.headers:
        raise httpexceptions.HTTPBadRequest(
            "Missing Alpaca-Signature header."
        )
    if request.content_type == 'application/x-pickle.python':
        try:
            report_cstruct = pickle.loads(request.body)
        except pickle.UnpicklingError as error:
            raise httpexceptions.HTTPBadRequest(
                "Cannot parse request body: %s" % str(error)
            )
    elif request.content_type == 'application/json':
        try:
            report_cstruct = simplejson.loads(request.body)
        except simplejson.JSONDecodeError as error:
            raise httpexceptions.HTTPBadRequest(
                "Cannot parse request body: %s" % str(error)
            )
    else:
        raise httpexceptions.HTTPBadRequest("Unsupported Content-Type.")
    try:
        report = ReportSchema().deserialize(report_cstruct)
    except colander.Invalid as error:
        raise httpexceptions.HTTPBadRequest('\r\n'.join((
            "Invalid report.",
            '\r\n'.join((
                '%s: %s' % (node_name, message)
                for node_name, message in error.asdict().iteritems()
            ))
        )))
    if report['date'].tzinfo is None:
        report['date'] = pytz.utc.normalize(pytz.utc.localize(
            report['date']
        ))
    else:
        report['date'] = report['date'].astimezone(pytz.utc)
    try:
        problem = DBSession.query(
            Problem,
        ).filter(
            Problem.hash == report['hash']
        ).one()
    except database_exceptions.NoResultFound:
        problem = Problem()
        problem.hash = report['hash']
        problem.occurrence_count = 1
        problem.first_occurrence = report['date'].replace(tzinfo=None)
    else:
        problem.occurrence_count += 1
    finally:
        problem.description = report['message'].split('\n')[0].strip()
        problem.last_occurrence = report['date'].replace(tzinfo=None)
        DBSession.add(problem)
    occurrence = Occurrence()
    occurrence.problem = problem
    occurrence.environment = environment
    occurrence.date = report['date'].replace(tzinfo=None)
    occurrence.message = report['message']
    occurrence.stack_trace = report['stack_trace']
    occurrence.environment_data = report['environment_data']
    DBSession.add(occurrence)
    DBSession.query(
        Occurrence
    ).filter(
        Occurrence.id.in_(
            DBSession.query(
                Occurrence.id
            ).join(
                Problem
            ).filter(
                Occurrence.problem_id == Problem.id,
                Problem.hash == report['hash']
            ).order_by(
                sql.desc(Occurrence.date)
            ).offset(
                30
            ).subquery()
        )
    ).delete(synchronize_session=False)
    # Call `expire_all()` to avoid having inconsistent state after calling
    # `delete()` with `synchronize_session=False`.
    DBSession.expire_all()
    return Response()