mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-15 10:13:15 -05:00
logging: don't group by logging_group
This commit is contained in:
parent
d6d37efa35
commit
2b0b3a70a7
@ -1,11 +1,10 @@
|
|||||||
from django_filters.rest_framework import BooleanFilter, FilterSet
|
from django_filters.rest_framework import BooleanFilter, FilterSet
|
||||||
|
|
||||||
from .models import Correspondent, Document, Tag, DocumentType
|
from .models import Correspondent, Document, Tag, DocumentType, Log
|
||||||
|
|
||||||
|
|
||||||
CHAR_KWARGS = ["istartswith", "iendswith", "icontains", "iexact"]
|
CHAR_KWARGS = ["istartswith", "iendswith", "icontains", "iexact"]
|
||||||
ID_KWARGS = ["in", "exact"]
|
ID_KWARGS = ["in", "exact"]
|
||||||
INT_KWARGS = ["exact"]
|
INT_KWARGS = ["exact", "gt", "gte", "lt", "lte"]
|
||||||
DATE_KWARGS = ["year", "month", "day", "date__gt", "gt", "date__lt", "lt"]
|
DATE_KWARGS = ["year", "month", "day", "date__gt", "gt", "date__lt", "lt"]
|
||||||
|
|
||||||
|
|
||||||
@ -68,3 +67,16 @@ class DocumentFilterSet(FilterSet):
|
|||||||
"document_type__name": CHAR_KWARGS,
|
"document_type__name": CHAR_KWARGS,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LogFilterSet(FilterSet):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Log
|
||||||
|
fields = {
|
||||||
|
|
||||||
|
"level": INT_KWARGS,
|
||||||
|
"created": DATE_KWARGS,
|
||||||
|
"group": ID_KWARGS
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from django.db import models
|
|
||||||
from django.db.models.aggregates import Max
|
|
||||||
|
|
||||||
|
|
||||||
class GroupConcat(models.Aggregate):
|
|
||||||
"""
|
|
||||||
Theoretically, this should work in Sqlite, PostgreSQL, and MySQL, but I've
|
|
||||||
only ever tested it in Sqlite.
|
|
||||||
"""
|
|
||||||
|
|
||||||
ENGINE_SQLITE = 1
|
|
||||||
ENGINE_POSTGRESQL = 2
|
|
||||||
ENGINE_MYSQL = 3
|
|
||||||
ENGINES = {
|
|
||||||
"django.db.backends.sqlite3": ENGINE_SQLITE,
|
|
||||||
"django.db.backends.postgresql_psycopg2": ENGINE_POSTGRESQL,
|
|
||||||
"django.db.backends.postgresql": ENGINE_POSTGRESQL,
|
|
||||||
"django.db.backends.mysql": ENGINE_MYSQL
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, expression, separator="\n", **extra):
|
|
||||||
|
|
||||||
self.engine = self._get_engine()
|
|
||||||
self.function = self._get_function()
|
|
||||||
self.template = self._get_template(separator)
|
|
||||||
|
|
||||||
models.Aggregate.__init__(
|
|
||||||
self,
|
|
||||||
expression,
|
|
||||||
output_field=models.CharField(),
|
|
||||||
**extra
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_engine(self):
|
|
||||||
engine = settings.DATABASES["default"]["ENGINE"]
|
|
||||||
try:
|
|
||||||
return self.ENGINES[engine]
|
|
||||||
except KeyError:
|
|
||||||
raise NotImplementedError(
|
|
||||||
"There's currently no support for {} when it comes to group "
|
|
||||||
"concatenation in Paperless".format(engine)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_function(self):
|
|
||||||
if self.engine == self.ENGINE_POSTGRESQL:
|
|
||||||
return "STRING_AGG"
|
|
||||||
return "GROUP_CONCAT"
|
|
||||||
|
|
||||||
def _get_template(self, separator):
|
|
||||||
if self.engine == self.ENGINE_MYSQL:
|
|
||||||
return "%(function)s(%(expressions)s SEPARATOR '{}')".format(
|
|
||||||
separator)
|
|
||||||
return "%(function)s(%(expressions)s, '{}')".format(separator)
|
|
||||||
|
|
||||||
|
|
||||||
class LogQuerySet(models.query.QuerySet):
|
|
||||||
|
|
||||||
def by_group(self):
|
|
||||||
return self.values("group").annotate(
|
|
||||||
time=Max("modified"),
|
|
||||||
messages=GroupConcat("message"),
|
|
||||||
).order_by("-time")
|
|
||||||
|
|
||||||
|
|
||||||
class LogManager(models.Manager):
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return LogQuerySet(self.model, using=self._db)
|
|
26
src/documents/migrations/1005_auto_20201102_0007.py
Normal file
26
src/documents/migrations/1005_auto_20201102_0007.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 3.1.2 on 2020-11-02 00:07
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('documents', '1004_auto_20201029_1331'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='log',
|
||||||
|
options={'ordering': ('-created',)},
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='log',
|
||||||
|
name='modified',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='log',
|
||||||
|
name='group',
|
||||||
|
field=models.UUIDField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
@ -13,12 +13,6 @@ from django.template.defaultfilters import slugify
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from .managers import LogManager
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
except ImportError:
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
|
|
||||||
class MatchingModel(models.Model):
|
class MatchingModel(models.Model):
|
||||||
@ -263,33 +257,17 @@ class Log(models.Model):
|
|||||||
(logging.CRITICAL, "Critical"),
|
(logging.CRITICAL, "Critical"),
|
||||||
)
|
)
|
||||||
|
|
||||||
group = models.UUIDField(blank=True)
|
group = models.UUIDField(blank=True, null=True)
|
||||||
message = models.TextField()
|
message = models.TextField()
|
||||||
level = models.PositiveIntegerField(choices=LEVELS, default=logging.INFO)
|
level = models.PositiveIntegerField(choices=LEVELS, default=logging.INFO)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
objects = LogManager()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ("-modified",)
|
ordering = ("-created",)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.message
|
return self.message
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
To allow for the case where we don't want to group the message, we
|
|
||||||
shouldn't force the caller to specify a one-time group value. However,
|
|
||||||
allowing group=None means that the manager can't differentiate the
|
|
||||||
different un-grouped messages, so instead we set a random one here.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not self.group:
|
|
||||||
self.group = uuid.uuid4()
|
|
||||||
|
|
||||||
models.Model.save(self, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class FileInfo:
|
class FileInfo:
|
||||||
|
|
||||||
|
@ -105,12 +105,13 @@ class DocumentSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class LogSerializer(serializers.ModelSerializer):
|
class LogSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
time = serializers.DateTimeField()
|
|
||||||
messages = serializers.CharField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Log
|
model = Log
|
||||||
fields = (
|
fields = (
|
||||||
"time",
|
"id",
|
||||||
"messages"
|
"created",
|
||||||
|
"message",
|
||||||
|
"group",
|
||||||
|
"level"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +27,8 @@ from .filters import (
|
|||||||
CorrespondentFilterSet,
|
CorrespondentFilterSet,
|
||||||
DocumentFilterSet,
|
DocumentFilterSet,
|
||||||
TagFilterSet,
|
TagFilterSet,
|
||||||
DocumentTypeFilterSet
|
DocumentTypeFilterSet,
|
||||||
|
LogFilterSet
|
||||||
)
|
)
|
||||||
|
|
||||||
import documents.index as index
|
import documents.index as index
|
||||||
@ -147,12 +148,14 @@ class DocumentViewSet(RetrieveModelMixin,
|
|||||||
|
|
||||||
class LogViewSet(ReadOnlyModelViewSet):
|
class LogViewSet(ReadOnlyModelViewSet):
|
||||||
model = Log
|
model = Log
|
||||||
queryset = Log.objects.all().by_group()
|
|
||||||
|
queryset = Log.objects.all()
|
||||||
serializer_class = LogSerializer
|
serializer_class = LogSerializer
|
||||||
pagination_class = StandardPagination
|
pagination_class = StandardPagination
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
filter_backends = (DjangoFilterBackend, OrderingFilter)
|
filter_backends = (DjangoFilterBackend, OrderingFilter)
|
||||||
ordering_fields = ("time",)
|
filter_class = LogFilterSet
|
||||||
|
ordering_fields = ("created",)
|
||||||
|
|
||||||
|
|
||||||
class SearchView(APIView):
|
class SearchView(APIView):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user