general: add possibility to override trace emails recipients (#24591)
This commit is contained in:
parent
f924283083
commit
d1fbd69e09
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-11-25 13:55
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '0009_auto_20181118_0807'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='loggingparameters',
|
||||
name='trace_emails',
|
||||
field=models.TextField(blank=True, help_text='One address per line (empty for site administrators)', verbose_name='Emails to receive error and critical traces'),
|
||||
),
|
||||
]
|
|
@ -15,6 +15,7 @@ from django.core.exceptions import ValidationError, ObjectDoesNotExist, Permissi
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Q
|
||||
from django.test import override_settings
|
||||
from django.utils.text import slugify
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
@ -154,19 +155,23 @@ class BaseResource(models.Model):
|
|||
return passerelle.utils.Request(resource=self, logger=self.logger)
|
||||
|
||||
@property
|
||||
def log_level(self):
|
||||
def logging_parameters(self):
|
||||
resource_type = ContentType.objects.get_for_model(self)
|
||||
try:
|
||||
return LoggingParameters.objects.get(
|
||||
resource_type=resource_type,
|
||||
resource_pk=self.id).log_level
|
||||
resource_pk=self.id)
|
||||
except LoggingParameters.DoesNotExist:
|
||||
return 'INFO'
|
||||
return LoggingParameters(
|
||||
resource_type=resource_type,
|
||||
resource_pk=self.id)
|
||||
|
||||
@property
|
||||
def log_level(self):
|
||||
return self.logging_parameters.log_level
|
||||
|
||||
def set_log_level(self, value):
|
||||
resource_type = ContentType.objects.get_for_model(self)
|
||||
parameters, created = LoggingParameters.objects.get_or_create(
|
||||
resource_type=resource_type, resource_pk=self.pk)
|
||||
parameters = self.logging_parameters
|
||||
parameters.log_level = value
|
||||
parameters.save()
|
||||
|
||||
|
@ -461,6 +466,11 @@ class LoggingParameters(models.Model):
|
|||
),
|
||||
default='INFO'
|
||||
)
|
||||
trace_emails = models.TextField(
|
||||
verbose_name=_('Emails to receive error and critical traces'),
|
||||
help_text=_('One address per line (empty for site administrators)'),
|
||||
blank=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = (('resource_type', 'resource_pk'))
|
||||
|
@ -567,7 +577,12 @@ class ProxyLogger(object):
|
|||
|
||||
ResourceLog.objects.create(**attr)
|
||||
|
||||
getattr(self._logger, levelname.lower())(message, *args, **kwargs)
|
||||
admins = settings.ADMINS
|
||||
logging_parameters = self.connector.logging_parameters
|
||||
if logging_parameters.trace_emails:
|
||||
admins = [('', x) for x in logging_parameters.trace_emails.splitlines()]
|
||||
with override_settings(ADMINS=admins):
|
||||
getattr(self._logger, levelname.lower())(message, *args, **kwargs)
|
||||
|
||||
def exception(self, message, *args, **kwargs):
|
||||
kwargs['exc_info'] = 1
|
||||
|
|
|
@ -108,15 +108,19 @@ class LoggingParametersUpdateView(FormView):
|
|||
return context
|
||||
|
||||
def get_form_class(self):
|
||||
return model_forms.modelform_factory(
|
||||
form_class = model_forms.modelform_factory(
|
||||
LoggingParameters,
|
||||
fields=['log_level'])
|
||||
fields=['log_level', 'trace_emails'])
|
||||
form_class.base_fields['trace_emails'].widget.attrs['rows'] = '3'
|
||||
return form_class
|
||||
|
||||
def get_initial(self):
|
||||
d = self.initial.copy()
|
||||
d['resource_type'] = self.kwargs['resource_type']
|
||||
d['resource_pk'] = self.kwargs['resource_pk']
|
||||
d['log_level'] = self.get_resource().log_level
|
||||
parameters = self.get_resource().logging_parameters
|
||||
d['log_level'] = parameters.log_level
|
||||
d['trace_emails'] = parameters.trace_emails
|
||||
return d
|
||||
|
||||
def get_resource(self):
|
||||
|
@ -127,5 +131,8 @@ class LoggingParametersUpdateView(FormView):
|
|||
return self.get_resource().get_absolute_url()
|
||||
|
||||
def form_valid(self, form):
|
||||
self.get_resource().set_log_level(form.cleaned_data['log_level'])
|
||||
parameters = self.get_resource().logging_parameters
|
||||
parameters.log_level = form.cleaned_data['log_level']
|
||||
parameters.trace_emails = form.cleaned_data['trace_emails']
|
||||
parameters.save()
|
||||
return super(LoggingParametersUpdateView, self).form_valid(form)
|
||||
|
|
|
@ -3,6 +3,11 @@ from httmock import urlmatch, HTTMock, response
|
|||
|
||||
import django_webtest
|
||||
|
||||
from django.core.files import File
|
||||
from io import BytesIO
|
||||
|
||||
from .utils import make_resource
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app(request):
|
||||
|
@ -109,3 +114,29 @@ def internal_server_error(url, request):
|
|||
def mock_500():
|
||||
with HTTMock(internal_server_error):
|
||||
yield None
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_csv_datasource(db):
|
||||
from passerelle.apps.csvdatasource.models import CsvDataSource, Query
|
||||
|
||||
data = '''id,label
|
||||
1,a
|
||||
2,b
|
||||
3,c'''
|
||||
obj = make_resource(
|
||||
CsvDataSource,
|
||||
slug='dummy-slug',
|
||||
title='Dummy Title',
|
||||
description='dummy description',
|
||||
csv_file=File(BytesIO(data), 'dummy.csv'))
|
||||
|
||||
Query.objects.create(
|
||||
resource=obj,
|
||||
slug='dummy-query',
|
||||
structure='array',
|
||||
label='Dummy Query',
|
||||
description='dummy query description',
|
||||
projections='id:int(id)\ntext:label')
|
||||
|
||||
return obj
|
||||
|
|
|
@ -187,3 +187,13 @@ def test_logging_parameters(app, admin_user):
|
|||
resp.form['log_level'] = 'DEBUG'
|
||||
resp = resp.form.submit()
|
||||
assert CsvDataSource.objects.get(id=csv.id).log_level == 'DEBUG'
|
||||
|
||||
resp = app.get(csv.get_absolute_url())
|
||||
resp = resp.click('logging parameters')
|
||||
resp.form['trace_emails'] = 'fred@localhost'
|
||||
resp = resp.form.submit()
|
||||
assert CsvDataSource.objects.get(id=csv.id).logging_parameters.trace_emails == 'fred@localhost'
|
||||
|
||||
resp = app.get(csv.get_absolute_url())
|
||||
resp = resp.click('logging parameters')
|
||||
assert resp.form['trace_emails'].value == 'fred@localhost'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
import pytest
|
||||
from mock import patch
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
|
@ -18,6 +19,7 @@ def test_get_description_url_fields(db):
|
|||
connector = OpenGIS(slug='plop', wms_service_url='http://username@example.net:secret@www.example.net')
|
||||
assert 'http://***:***@www.example.net' in [x[1] for x in connector.get_description_fields()]
|
||||
|
||||
|
||||
def test_get_description_secret_fields(db):
|
||||
connector = ClicRdv(slug='plop', apikey='secret1', username='plop', password='secret2')
|
||||
assert not 'secret1' in [x[1] for x in connector.get_description_fields()]
|
||||
|
@ -38,3 +40,51 @@ def test_log_cleaning(db):
|
|||
|
||||
connector.daily()
|
||||
assert ResourceLog.objects.all().count() == 1
|
||||
|
||||
@pytest.fixture
|
||||
def email_handler():
|
||||
import logging
|
||||
from django.utils.log import AdminEmailHandler
|
||||
|
||||
root = logging.getLogger()
|
||||
handler = AdminEmailHandler(include_html=True)
|
||||
handler.level = logging.ERROR
|
||||
root.handlers.append(handler)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
root.handlers.remove(handler)
|
||||
|
||||
|
||||
def test_trace_emails(app, settings, dummy_csv_datasource, email_handler, mailoutbox):
|
||||
from .utils import generic_endpoint_url
|
||||
|
||||
settings.ADMINS = [('admin', 'admin@example.net')]
|
||||
|
||||
logging_parameters = dummy_csv_datasource.logging_parameters
|
||||
logging_parameters.save()
|
||||
|
||||
assert not mailoutbox
|
||||
|
||||
with patch.object(dummy_csv_datasource.__class__,
|
||||
'execute_query',
|
||||
side_effect=ValueError('coin'), autospec=True):
|
||||
|
||||
app.get(generic_endpoint_url(connector='csvdatasource',
|
||||
endpoint='query/dummy-query/',
|
||||
slug=dummy_csv_datasource.slug),
|
||||
status=500)
|
||||
|
||||
assert len(mailoutbox) == 1
|
||||
assert mailoutbox[0].to == ['admin@example.net']
|
||||
|
||||
logging_parameters.trace_emails = 'john.doe@example.net'
|
||||
logging_parameters.save()
|
||||
app.get(generic_endpoint_url(connector='csvdatasource',
|
||||
endpoint='query/dummy-query/',
|
||||
slug=dummy_csv_datasource.slug),
|
||||
status=500)
|
||||
|
||||
assert len(mailoutbox) == 2
|
||||
assert mailoutbox[0].to == ['admin@example.net']
|
||||
assert mailoutbox[1].to == ['john.doe@example.net']
|
||||
|
|
Loading…
Reference in New Issue