|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2010 - 2017 RhodeCode GmbH and the AppEnlight project authors
|
|
|
#
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
# You may obtain a copy of the License at
|
|
|
#
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
#
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
|
|
|
|
import logging
|
|
|
import urllib.parse
|
|
|
|
|
|
import sqlalchemy as sa
|
|
|
from pyramid.threadlocal import get_current_request
|
|
|
|
|
|
from appenlight.lib.cache_regions import get_region
|
|
|
from appenlight.lib.enums import ReportType
|
|
|
from appenlight.models import get_db_session
|
|
|
from appenlight.models.report_group import ReportGroup
|
|
|
from appenlight.models.application import Application
|
|
|
from appenlight.models.event import Event
|
|
|
from appenlight.models.services.base import BaseService
|
|
|
from appenlight.models.services.event import EventService
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
class ApplicationService(BaseService):
|
|
|
@classmethod
|
|
|
def all(cls, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
q = db_session.query(Application)
|
|
|
return q
|
|
|
|
|
|
@classmethod
|
|
|
def by_api_key(cls, api_key, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
q = db_session.query(Application)
|
|
|
q = q.filter(Application.api_key == api_key)
|
|
|
q = q.options(sa.orm.eagerload(Application.owner))
|
|
|
return q.first()
|
|
|
|
|
|
@classmethod
|
|
|
def by_api_key_cached(cls, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
cache_region = get_region("redis_min_1")
|
|
|
|
|
|
@cache_region.cache_on_arguments("ApplicationService.by_api_key")
|
|
|
def cached(*args, **kwargs):
|
|
|
app = cls.by_api_key(*args, db_session=db_session, **kwargs)
|
|
|
if app:
|
|
|
db_session.expunge(app)
|
|
|
return app
|
|
|
|
|
|
return cached
|
|
|
|
|
|
@classmethod
|
|
|
def by_public_api_key(
|
|
|
cls, api_key, db_session=None, from_cache=False, request=None
|
|
|
):
|
|
|
db_session = get_db_session(db_session)
|
|
|
cache_region = get_region("redis_min_1")
|
|
|
|
|
|
def uncached(api_key):
|
|
|
q = db_session.query(Application)
|
|
|
q = q.filter(Application.public_key == api_key)
|
|
|
q = q.options(sa.orm.eagerload(Application.owner))
|
|
|
return q.first()
|
|
|
|
|
|
if from_cache:
|
|
|
|
|
|
@cache_region.cache_on_arguments("ApplicationService.by_public_api_key")
|
|
|
def cached(api_key):
|
|
|
app = uncached(api_key)
|
|
|
if app:
|
|
|
db_session.expunge(app)
|
|
|
return app
|
|
|
|
|
|
app = cached(api_key)
|
|
|
else:
|
|
|
app = uncached(api_key)
|
|
|
return app
|
|
|
|
|
|
@classmethod
|
|
|
def by_id(cls, db_id, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
q = db_session.query(Application)
|
|
|
q = q.filter(Application.resource_id == db_id)
|
|
|
return q.first()
|
|
|
|
|
|
@classmethod
|
|
|
def by_id_cached(cls, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
cache_region = get_region("redis_min_1")
|
|
|
|
|
|
@cache_region.cache_on_arguments("ApplicationService.by_id")
|
|
|
def cached(*args, **kwargs):
|
|
|
app = cls.by_id(*args, db_session=db_session, **kwargs)
|
|
|
if app:
|
|
|
db_session.expunge(app)
|
|
|
return app
|
|
|
|
|
|
return cached
|
|
|
|
|
|
@classmethod
|
|
|
def by_ids(cls, db_ids, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
query = db_session.query(Application)
|
|
|
query = query.filter(Application.resource_id.in_(db_ids))
|
|
|
return query
|
|
|
|
|
|
@classmethod
|
|
|
def by_http_referer(cls, referer_string, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
domain = urllib.parse.urlsplit(referer_string, allow_fragments=False).netloc
|
|
|
if domain:
|
|
|
if domain.startswith("www."):
|
|
|
domain = domain[4:]
|
|
|
q = db_session.query(Application).filter(Application.domain == domain)
|
|
|
return q.first()
|
|
|
|
|
|
@classmethod
|
|
|
def last_updated(cls, since_when, exclude_status=None, db_session=None):
|
|
|
db_session = get_db_session(db_session)
|
|
|
q = db_session.query(Application)
|
|
|
q2 = ReportGroup.last_updated(
|
|
|
since_when, exclude_status=exclude_status, db_session=db_session
|
|
|
)
|
|
|
q2 = q2.from_self(ReportGroup.resource_id)
|
|
|
q2 = q2.group_by(ReportGroup.resource_id)
|
|
|
q = q.filter(Application.resource_id.in_(q2))
|
|
|
return q
|
|
|
|
|
|
@classmethod
|
|
|
def check_for_groups_alert(cls, resource, event_type, *args, **kwargs):
|
|
|
""" Check for open alerts depending on group type.
|
|
|
Create new one if nothing is found and send alerts """
|
|
|
db_session = get_db_session(kwargs.get("db_session"))
|
|
|
request = get_current_request()
|
|
|
report_groups = kwargs["report_groups"]
|
|
|
occurence_dict = kwargs["occurence_dict"]
|
|
|
|
|
|
error_reports = 0
|
|
|
slow_reports = 0
|
|
|
for group in report_groups:
|
|
|
occurences = occurence_dict.get(group.id, 1)
|
|
|
if group.get_report().report_type == ReportType.error:
|
|
|
error_reports += occurences
|
|
|
elif group.get_report().report_type == ReportType.slow:
|
|
|
slow_reports += occurences
|
|
|
|
|
|
log_msg = "LIMIT INFO: %s : %s error reports. %s slow_reports" % (
|
|
|
resource,
|
|
|
error_reports,
|
|
|
slow_reports,
|
|
|
)
|
|
|
logging.warning(log_msg)
|
|
|
threshold = 10
|
|
|
for event_type in ["error_report_alert", "slow_report_alert"]:
|
|
|
if (
|
|
|
error_reports < resource.error_report_threshold
|
|
|
and event_type == "error_report_alert"
|
|
|
):
|
|
|
continue
|
|
|
elif (
|
|
|
slow_reports <= resource.slow_report_threshold
|
|
|
and event_type == "slow_report_alert"
|
|
|
):
|
|
|
continue
|
|
|
if event_type == "error_report_alert":
|
|
|
amount = error_reports
|
|
|
threshold = resource.error_report_threshold
|
|
|
elif event_type == "slow_report_alert":
|
|
|
amount = slow_reports
|
|
|
threshold = resource.slow_report_threshold
|
|
|
|
|
|
event = EventService.for_resource(
|
|
|
[resource.resource_id],
|
|
|
event_type=Event.types[event_type],
|
|
|
status=Event.statuses["active"],
|
|
|
)
|
|
|
if event.first():
|
|
|
log.info("ALERT: PROGRESS: %s %s" % (event_type, resource))
|
|
|
else:
|
|
|
log.warning("ALERT: OPEN: %s %s" % (event_type, resource))
|
|
|
new_event = Event(
|
|
|
resource_id=resource.resource_id,
|
|
|
event_type=Event.types[event_type],
|
|
|
status=Event.statuses["active"],
|
|
|
values={"reports": amount, "threshold": threshold},
|
|
|
)
|
|
|
db_session.add(new_event)
|
|
|
new_event.send_alerts(request=request, resource=resource)
|
|
|
|