general: move logging parameters to its own model (#27162)

(and remove the NOTSET level during the migration)
This commit is contained in:
Frédéric Péters 2018-11-18 15:06:25 +01:00
parent 0fc6a21c3d
commit d098de396c
39 changed files with 711 additions and 22 deletions

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('actesweb', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='actesweb',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('airquality', '0002_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='airquality',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api_particulier', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='apiparticulier',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('arcgis', '0003_auto_20181102_1550'),
]
operations = [
migrations.RemoveField(
model_name='arcgis',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('arpege_ecp', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='arpegeecp',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('atos_genesys', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='resource',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('base_adresse', '0012_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='baseadresse',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('bdp', '0005_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='bdp',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('choosit', '0007_auto_20180814_1048'),
]
operations = [
migrations.RemoveField(
model_name='choositsmsgateway',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cityweb', '0002_auto_20170920_1002'),
]
operations = [
migrations.RemoveField(
model_name='cityweb',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('clicrdv', '0001_squashed_0006_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='clicrdv',
name=b'log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cmis', '0002_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='cmisconnector',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('csvdatasource', '0012_auto_20180912_0215'),
]
operations = [
migrations.RemoveField(
model_name='csvdatasource',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('family', '0008_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='genericfamily',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('feeds', '0002_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='feed',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('gdc', '0005_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='gdc',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('jsondatastore', '0004_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='jsondatastore',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mobyt', '0006_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='mobytsmsgateway',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('okina', '0002_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='okina',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('opengis', '0005_auto_20180227_1531'),
]
operations = [
migrations.RemoveField(
model_name='opengis',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('orange', '0005_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='orangesmsgateway',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ovh', '0006_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='ovhsmsgateway',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('oxyd', '0006_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='oxydsmsgateway',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pastell', '0005_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='pastell',
name='log_level',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('solis', '0004_auto_20171220_1058'),
]
operations = [
migrations.RemoveField(
model_name='solis',
name='log_level',
),
]

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 13:16
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('base', '0006_resourcestatus'),
]
operations = [
migrations.CreateModel(
name='LoggingParameters',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('resource_pk', models.PositiveIntegerField()),
('log_level', models.CharField(verbose_name='Log Level', choices=[(b'DEBUG', b'DEBUG'), (b'INFO', b'INFO'), (b'WARNING', b'WARNING'), (b'ERROR', b'ERROR'), (b'CRITICAL', b'CRITICAL')], default=b'INFO', max_length=10, verbose_name='Log Level')),
('resource_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
),
]

View File

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 13:17
from __future__ import unicode_literals
from django.db import migrations
def set_logging_parameters(apps, schema_editor):
LoggingParameters = apps.get_model('base', 'LoggingParameters')
ContentType = apps.get_model('contenttypes', 'ContentType')
for model in apps.get_models():
if not hasattr(model, 'log_level'):
continue
content_type = ContentType.objects.get_for_model(model)
for instance in model.objects.all():
parameters, created = LoggingParameters.objects.get_or_create(
resource_type=content_type,
resource_pk=instance.id)
parameters.log_level = instance.log_level
if parameters.log_level == 'NOTSET':
parameters.log_level = 'INFO'
parameters.save()
class Migration(migrations.Migration):
dependencies = [
('base', '0007_loggingparameters'),
]
operations = [
migrations.RunPython(set_logging_parameters, migrations.RunPython.noop),
]

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('base', '0008_auto_20181118_0717'),
]
operations = [
migrations.AlterUniqueTogether(
name='loggingparameters',
unique_together=set([('resource_type', 'resource_pk')]),
),
]

View File

@ -117,19 +117,6 @@ class BaseResource(models.Model):
description = models.TextField(verbose_name=_('Description'))
slug = models.SlugField(unique=True)
users = models.ManyToManyField(ApiUser, blank=True)
log_level = models.CharField(
_('Log Level'), max_length=10,
choices = (
('NOTSET','NOTSET'),
('DEBUG','DEBUG'),
('INFO','INFO'),
('WARNING','WARNING'),
('ERROR','ERROR'),
('CRITICAL','CRITICAL'),
),
default='INFO'
)
objects = InheritanceManager()
parameters = None
@ -166,6 +153,23 @@ class BaseResource(models.Model):
def requests(self):
return passerelle.utils.Request(resource=self, logger=self.logger)
@property
def log_level(self):
resource_type = ContentType.objects.get_for_model(self)
try:
return LoggingParameters.objects.get(
resource_type=resource_type,
resource_pk=self.id).log_level
except LoggingParameters.DoesNotExist:
return 'INFO'
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.log_level = value
parameters.save()
def soap_client(self, **kwargs):
return passerelle.utils.SOAPClient(resource=self, **kwargs)
@ -328,7 +332,6 @@ class BaseResource(models.Model):
'title': d['title'],
'slug': d['slug'],
'description': d['description'],
'log_level': d['log_level'],
}
init_kwargs.update(kwargs)
if instance:
@ -362,8 +365,9 @@ class BaseResource(models.Model):
else:
raise Exception('import_json_real: field %s of ressource class '
'%s is unsupported' % (field, cls))
instance.save()
if 'log_level' in d:
instance.set_log_level(d['log_level'])
return instance
def clean_logs(self):
@ -441,6 +445,28 @@ class AccessRight(models.Model):
return '%s (on %s <%s>) (for %s)' % (self.codename, self.resource_type, self.resource_pk, self.apiuser)
class LoggingParameters(models.Model):
resource_type = models.ForeignKey(ContentType)
resource_pk = models.PositiveIntegerField()
resource = fields.GenericForeignKey('resource_type', 'resource_pk')
log_level = models.CharField(
verbose_name_('Log Level'),
max_length=10,
choices = (
('DEBUG', 'DEBUG'),
('INFO', 'INFO'),
('WARNING', 'WARNING'),
('ERROR', 'ERROR'),
('CRITICAL', 'CRITICAL'),
),
default='INFO'
)
class Meta:
unique_together = (('resource_type', 'resource_pk'))
class ResourceLog(models.Model):
timestamp = models.DateTimeField(auto_now_add=True)
appname = models.CharField(max_length=128, verbose_name='appname', null=True)

View File

@ -25,6 +25,9 @@ def access_rights_table(context, resource, permission):
context['trusted_services'] = get_trusted_services()
return context
@register.filter(name='resource_type')
def as_resource_type(resource):
return ContentType.objects.get_for_model(resource).id
@register.inclusion_tag('passerelle/includes/resource-logs-table.html', takes_context=True)
def resource_logs_table(context, resource):

View File

@ -1,7 +1,8 @@
from django.conf.urls import url
from .views import ApiUserCreateView, ApiUserUpdateView, ApiUserDeleteView, \
ApiUserListView, AccessRightDeleteView, AccessRightCreateView
ApiUserListView, AccessRightDeleteView, AccessRightCreateView, \
LoggingParametersUpdateView
access_urlpatterns = [
url(r'^$', ApiUserListView.as_view(), name='apiuser-list'),
@ -12,5 +13,7 @@ access_urlpatterns = [
url(r'^(?P<pk>[\w,-]+)/remove$', AccessRightDeleteView.as_view(),
name='access-right-remove'),
url(r'^accessright/add/(?P<resource_type>[\w,-]+)/(?P<resource_pk>[\w,-]+)/(?P<codename>[\w,-]+)/',
AccessRightCreateView.as_view(), name='access-right-add')
AccessRightCreateView.as_view(), name='access-right-add'),
url(r'logging/parameters/(?P<resource_type>[\w,-]+)/(?P<resource_pk>[\w,-]+)/$',
LoggingParametersUpdateView.as_view(), name='logging-parameters')
]

View File

@ -1,9 +1,11 @@
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.forms import models as model_forms
from django.views.generic import *
from django.http import Http404
from .models import ApiUser, AccessRight
from .models import ApiUser, AccessRight, LoggingParameters
from .forms import ApiUserForm, AccessRightForm
from ..utils import get_trusted_services
@ -95,3 +97,35 @@ class AccessRightCreateView(CreateView):
def get_success_url(self):
return self.object.resource.get_absolute_url()
class LoggingParametersUpdateView(FormView):
template_name = 'passerelle/manage/logging_parameters_form.html'
def get_context_data(self, **kwargs):
context = super(LoggingParametersUpdateView, self).get_context_data(**kwargs)
context['connector'] = self.get_resource()
return context
def get_form_class(self):
return model_forms.modelform_factory(
LoggingParameters,
fields=['log_level'])
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
return d
def get_resource(self):
content_type = ContentType.objects.get_for_id(self.kwargs['resource_type'])
return content_type.model_class().objects.get(pk=self.kwargs['resource_pk'])
def get_success_url(self):
return self.get_resource().get_absolute_url()
def form_valid(self, form):
self.get_resource().set_log_level(form.cleaned_data['log_level'])
return super(LoggingParametersUpdateView, self).form_valid(form)

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-11-18 14:07
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tlmcom', '0004_auto_20170920_0951'),
]
operations = [
migrations.RemoveField(
model_name='tlmcom',
name='log_level',
),
]

View File

@ -0,0 +1,17 @@
{% extends "passerelle/manage.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans 'Logging Parameters' %}</h2>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans 'Update' %}</button>
<a href="{{ connector.get_absolute_url }}" class="cancel">{% trans 'Cancel' %}</a>
</div>
</form>
{% endblock %}

View File

@ -16,6 +16,9 @@
</h2>
<span class="actions">
{% if object|can_edit:request.user %}
<a rel="popup" href="{% url 'logging-parameters' resource_type=object|resource_type resource_pk=object.id %}">{% trans 'logging parameters' %}</a>
{% endif %}
{% if object|can_edit:request.user %}
<a rel="popup" href="{{ object.get_edit_url }}">{% trans 'edit' %}</a>
{% endif %}
{% if object|can_delete:request.user %}

View File

@ -40,7 +40,9 @@ def mdel(db):
@pytest.fixture
def arcgis(db):
return utils.setup_access_rights(ArcGIS.objects.create(slug='test', log_level='DEBUG'))
instance = utils.setup_access_rights(ArcGIS.objects.create(slug='test'))
instance.set_log_level('DEBUG')
return instance
DEMAND_STATUS = {
@ -126,7 +128,7 @@ def test_proxy_logger(mocked_get, caplog, app, arcgis):
# when changing log level
ResourceLog.objects.all().delete()
arcgis.log_level = 'INFO'
arcgis.set_log_level('INFO')
arcgis.save()
app.get('/arcgis/test/district', params={'lon': 6.172122, 'lat': 48.673836}, status=200)
assert ResourceLog.objects.count() == 1

View File

@ -181,3 +181,14 @@ def test_export_to_file(app, setup, filetype):
assert Bdp.objects.count() == 0
import_site(json.load(open(f.name)), overwrite=True)
assert Bdp.objects.count() == 1
def test_export_log_level(app, setup):
bdp = Bdp.objects.create(service_url='https://bdp.example.com/')
bdp.set_log_level('DEBUG')
first = export_site()
Bdp.objects.all().delete()
import_site(first)
second = export_site()
assert first == second
assert Bdp.objects.all().first().log_level == 'DEBUG'

View File

@ -170,3 +170,20 @@ def test_logs(app, admin_user):
base_url = re.findall(r'data-log-base-url="(.*)"', resp.text)[0]
resp = app.get(base_url + log_pk + '/')
resp = app.get(base_url + '12345' + '/', status=404)
def test_logging_parameters(app, admin_user):
data = StringIO('1;Foo\n2;Bar\n3;Baz')
csv = CsvDataSource.objects.create(csv_file=File(data, 't.csv'),
columns_keynames='id, text', slug='test', title='a title', description='a description')
app = login(app)
resp = app.get(csv.get_absolute_url())
resp = resp.click('logging parameters')
resp.form['log_level'] = 'ERROR'
resp = resp.form.submit()
assert CsvDataSource.objects.get(id=csv.id).log_level == 'ERROR'
resp = app.get(csv.get_absolute_url())
resp = resp.click('logging parameters')
resp.form['log_level'] = 'DEBUG'
resp = resp.form.submit()
assert CsvDataSource.objects.get(id=csv.id).log_level == 'DEBUG'

View File

@ -14,7 +14,7 @@ from .test_availability import down_mock, up_mock
@pytest.fixture
def connector():
connector, created = Feed.objects.get_or_create(slug='some-slug')
connector.log_level = 'DEBUG'
connector.set_log_level('DEBUG')
connector.url = 'http://example.net/'
connector.save()
return connector
@ -52,7 +52,7 @@ def test_proxy_logger_dict_interpolation(db, connector):
def test_proxy_logger_ignore(db, connector):
ResourceLog.objects.all().delete()
connector.log_level = 'INFO'
connector.set_log_level('INFO')
pr = ProxyLogger(connector)
pr.debug(u'some message')
assert len(ResourceLog.objects.all()) == 0