Skip to content

Commit

Permalink
Merge pull request #1307 from AdrianGaudebert/867388-bixie-middleware
Browse files Browse the repository at this point in the history
Fixes bug 867388 - Added basic middleware services for Bixie.
  • Loading branch information
lonnen committed Jul 8, 2013
2 parents 6749d4e + d086ee6 commit 29cfe76
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 56 deletions.
39 changes: 17 additions & 22 deletions socorro/external/postgresql/error.py
Expand Up @@ -2,20 +2,13 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import logging

from socorro.external import MissingOrBadArgumentError
from socorro.external.postgresql.base import PostgreSQLBase
from socorro.lib import datetimeutil, external_common

logger = logging.getLogger("webapi")


class Error(PostgreSQLBase):

"""
Implement the /error service with PostgreSQL.
"""
"""Implement the /error service with PostgreSQL. """

def get(self, **kwargs):
"""Return a single error report from its UUID. """
Expand All @@ -26,11 +19,10 @@ def get(self, **kwargs):

if params.uuid is None:
raise MissingOrBadArgumentError(
"Mandatory parameter 'uuid' is missing or empty")
"Mandatory parameter 'uuid' is missing or empty"
)

crash_date = datetimeutil.uuid_to_date(params.uuid)
logger.debug("Looking for error %s during day %s" % (params.uuid,
crash_date))

sql = """/* socorro.external.postgresql.error.Error.get */
SELECT
Expand All @@ -40,26 +32,29 @@ def get(self, **kwargs):
FROM bixie.crashes
WHERE bixie.crashes.crash_id=%(uuid)s
AND bixie.crashes.success IS NOT NULL
AND utc_day_is( bixie.crashes.processor_completed_datetime, %(crash_date)s)
AND utc_day_is(
bixie.crashes.processor_completed_datetime,
%(crash_date)s
)
"""
sql_params = {
"uuid": params.uuid,
"uuid": params.uuid,
"crash_date": crash_date
}

error_message = "Failed to retrieve crash data from PostgreSQL"
error_message = "Failed to retrieve error data from PostgreSQL"
results = self.query(sql, sql_params, error_message=error_message)

crashes = []
errors = []
for row in results:
crash = dict(zip((
"product",
"error",
"signature"), row))
crashes.append(crash)
error = dict(zip((
"product",
"error",
"signature"
), row))
errors.append(error)

return {
"hits": crashes,
"total": len(crashes)
"hits": errors,
"total": len(errors)
}
87 changes: 87 additions & 0 deletions socorro/external/postgresql/errors.py
@@ -0,0 +1,87 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import datetime

from socorro.external import MissingOrBadArgumentError
from socorro.external.postgresql.base import PostgreSQLBase
from socorro.lib import datetimeutil, external_common, search_common


class Errors(PostgreSQLBase):
'''Implement the /errors services with PostgreSQL. '''

def get_signatures(self, **kwargs):
'''Return a list of errors aggregated by signatures. '''
now = datetimeutil.utc_now()
lastweek = now - datetime.timedelta(7)

filters = [
('signature', None, 'str'),
('search_mode', 'is_exactly', 'str'),
('product', None, 'str'),
('start_date', lastweek, 'datetime'),
('end_date', now, 'datetime'),
]
params = external_common.parse_arguments(filters, kwargs)

authorized_search_modes = (
'is_exactly',
'contains',
'starts_with',
'ends_with'
)
if params.search_mode not in authorized_search_modes:
search_mode = authorized_search_modes[0]

fields = ('signature', 'count')
sql_fields = {
'signature': 'signature',
'count': 'count(crash_id) as total'
}

sql = '''/* socorro.external.postgresql.error.Error.get */
SELECT %s
FROM bixie.crashes
WHERE success IS NOT NULL
AND processor_completed_datetime BETWEEN
%%(start_date)s AND %%(end_date)s
''' % ', '.join(sql_fields[x] for x in fields)

sql_where = [sql]
if params.signature:
if params.search_mode == 'is_exactly':
sql_where.append('signature = %(signature)s')
else:
if params.search_mode == 'contains':
params.signature = '%%%s%%' % params.signature
elif params.search_mode == 'starts_with':
params.signature = '%%%s' % params.signature
elif params.search_mode == 'ends_with':
params.signature = '%s%%' % params.signature

sql_where.append('signature LIKE %(signature)s')

if params.product:
sql_where.append('product = %(product)s')

sql = ' AND '.join(sql_where)

sql_group = 'GROUP BY signature'
sql_order = 'ORDER BY total DESC, signature'

sql = ' '.join((sql, sql_group, sql_order))

error_message = 'Failed to retrieve error data from PostgreSQL'
results = self.query(sql, params, error_message=error_message)

errors = []
for row in results:
error = dict(zip(fields, row))
errors.append(error)

return {
'hits': errors,
'total': len(errors)
}
74 changes: 53 additions & 21 deletions socorro/external/postgresql/products.py
Expand Up @@ -4,6 +4,7 @@

import logging

from socorro.external import MissingOrBadArgumentError
from socorro.external.postgresql.base import add_param_to_dict, PostgreSQLBase
from socorro.lib import datetimeutil, external_common

Expand All @@ -16,27 +17,51 @@ def get(self, **kwargs):
""" Return product information, or version information for one
or more product:version combinations """
filters = [
("versions", None, ["list", "str"]) # for legacy, to be removed
("versions", None, ["list", "str"]), # for legacy, to be removed
("type", "desktop", "str"),
]
params = external_common.parse_arguments(filters, kwargs)

accepted_types = ("desktop", "webapp")
if params.type not in accepted_types:
raise MissingOrBadArgumentError(
"Bad value for parameter 'type': got '%s', expected one of %s)"
% (params.type, accepted_types)
)

if params.versions and params.versions[0]:
return self._get_versions(params)

sql = """
/* socorro.external.postgresql.products.Products.get */
SELECT
product_name,
version_string,
start_date,
end_date,
throttle,
is_featured,
build_type,
has_builds
FROM product_info
ORDER BY product_sort, version_sort DESC, channel_sort
"""
if params.type == "desktop":
sql = """
/* socorro.external.postgresql.products.Products.get */
SELECT
product_name,
version_string,
start_date,
end_date,
throttle,
is_featured,
build_type,
has_builds
FROM product_info
ORDER BY product_sort, version_sort DESC, channel_sort
"""
elif params.type == "webapp":
sql = """
/* socorro.external.postgresql.products.Products.get */
SELECT
product_name,
version,
NULL as start_date,
NULL as end_date,
1.0 as throttle,
FALSE as is_featured,
build_type,
FALSE as has_builds
FROM bixie.raw_product_releases
ORDER BY product_name, version DESC
"""

error_message = "Failed to retrieve products/versions from PostgreSQL"
results = self.query(sql, error_message=error_message)
Expand All @@ -56,12 +81,19 @@ def get(self, **kwargs):
'has_builds',
), row))

version['end_date'] = datetimeutil.date_to_string(
version['end_date']
)
version['start_date'] = datetimeutil.date_to_string(
version['start_date']
)
try:
version['end_date'] = datetimeutil.date_to_string(
version['end_date']
)
except TypeError:
pass
try:
version['start_date'] = datetimeutil.date_to_string(
version['start_date']
)
except TypeError:
pass

version['throttle'] = float(version['throttle'])

product = version['product']
Expand Down
24 changes: 12 additions & 12 deletions socorro/unittest/external/postgresql/test_error.py
Expand Up @@ -82,6 +82,18 @@ def setUp(self):

self.connection.commit()

#--------------------------------------------------------------------------
def tearDown(self):
"""Clean up the database, delete tables and functions. """
cursor = self.connection.cursor()
cursor.execute(""" SET search_path TO bixie """)
cursor.execute("""
TRUNCATE crashes
CASCADE
""")
self.connection.commit()
super(IntegrationTestError, self).tearDown()

#--------------------------------------------------------------------------
def test_get(self):
""" Test GET for Bixie Errors """
Expand Down Expand Up @@ -115,15 +127,3 @@ def test_get(self):
}

self.assertEqual(res, res_expected)

#--------------------------------------------------------------------------
def tearDown(self):
"""Clean up the database, delete tables and functions. """
cursor = self.connection.cursor()
cursor.execute(""" SET search_path TO bixie """)
cursor.execute("""
TRUNCATE crashes
CASCADE
""")
self.connection.commit()
super(IntegrationTestError, self).tearDown()

0 comments on commit 29cfe76

Please sign in to comment.