Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cria funcionalidade para notificar ausência de arquivos de log #15

Merged
merged 29 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fa24d29
Cria configuração de e-mail para coleção (será substituída no futuro …
May 10, 2024
78c1261
Cria referência temporal para a datetime representada por "two days a…
May 10, 2024
c8c08b8
Cria exceção para reportar situação em que apenas uma configuração at…
May 10, 2024
e90fea8
Cria filtro para obter arquivos de log de uma certa data, válidos
May 10, 2024
235e54b
Cria task que envia mensagem de email (para notificar ausência de logs)
May 10, 2024
2aaa254
Cria task que observa aruqivos de log faltantes e notifica e-mail (a …
May 10, 2024
1831783
Troca URL padrão de configuração local para 0.0.0.0
rafaelpezzuto May 24, 2024
9478ce1
Cria utilitário para obter um range de datas
rafaelpezzuto May 25, 2024
e390a4a
Substitui método que obtém data a partir de string por método numérico
rafaelpezzuto May 25, 2024
277a1e9
Adiciona método de classe para obter num de arquivos requeridos
rafaelpezzuto May 25, 2024
211a206
Adiciona método de classe para obter num de arquivos existentes
rafaelpezzuto May 25, 2024
6f61b0e
Cria modelo para acomodar relatório de arquivos faltantes
rafaelpezzuto May 25, 2024
73998b6
Corrige importações
rafaelpezzuto May 25, 2024
fe74e3f
Limpa choices e adiciona dados para novo modelo que armazena relatóri
rafaelpezzuto May 25, 2024
512fe2a
Substitui task para gerar relatórios de logs por 3 tasks menores
rafaelpezzuto May 25, 2024
5053f61
Cria modelo snippet para relatório de logs faltantes
rafaelpezzuto May 25, 2024
aa82517
Remove import desnecessário
rafaelpezzuto May 25, 2024
0469776
Merge branch 'scieloorg:main' into impl/report-missing-dates
pitangainnovare Jun 1, 2024
92eceea
Substitui termos existing e required por found e expected, respectiva…
rafaelpezzuto Jun 17, 2024
4501c20
Melhora comparações em contagem de arquivos existentes, extras e ok
rafaelpezzuto Jun 17, 2024
3ce8410
Marca mensagens para tradução (em disparo de exceções)
rafaelpezzuto Jun 17, 2024
13e1ccd
Cria property para retornar lista de acron2 e a utiliza em task
rafaelpezzuto Jun 17, 2024
fba9583
Renomeia outras variáveis com os termos required e existing
rafaelpezzuto Jun 17, 2024
3015aa1
Configura send para usar variável de ambiente de email da aplicação (…
rafaelpezzuto Jun 17, 2024
ff37340
Apresenta acron2 em listagem de coleções
rafaelpezzuto Jun 17, 2024
8e28675
Altera termo Core para Usage em template
rafaelpezzuto Jun 17, 2024
46e5da2
Corrige método que obtém número de arquivos exigidos para uma data. U…
rafaelpezzuto Jun 17, 2024
c6f5718
Marca outros termos para tradução
rafaelpezzuto Jun 17, 2024
941c8a8
Renomia outro termo existing para found
rafaelpezzuto Jun 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions collection/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,7 @@ def create_or_update(
@property
def name(self):
return CollectionName.objects.filter(collection=self).iterator()

@property
def acron2_list(self):
return [col.acron2 for col in Collection.objects.iterator()]
1 change: 1 addition & 0 deletions collection/wagtail_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class CollectionSnippetViewSet(SnippetViewSet):
list_display = (
"main_name",
"acron3",
"acron2",
"code",
"status",
"collection_type",
Expand Down
4 changes: 3 additions & 1 deletion config/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
EMAIL_HOST = env("EMAIL_HOST", default="mailhog")
# https://docs.djangoproject.com/en/dev/ref/settings/#email-port
EMAIL_PORT = 1025
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host-user
EMAIL_HOST_USER = env.str("DJANGO_EMAIL_HOST_USER", default="[email protected]")

# ADMIN
# ------------------------------------------------------------------------------
# https://docs.wagtail.org/en/stable/reference/settings.html#wagtailadmin-base-url
WAGTAILADMIN_BASE_URL = 'https://usage.scielo.org'
WAGTAILADMIN_BASE_URL = 'http://0.0.0.0:8009'

# WhiteNoise
# ------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion core/templates/wagtailadmin/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

{% else %}

SciELO Core
SciELO Usage

{% endif %}

Expand Down
14 changes: 11 additions & 3 deletions log_manager/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@
COLLECTION_CONFIG_TYPE_DIRECTORY_PROCESSED_DATA = 'PRO'
COLLECTION_CONFIG_TYPE_DIRECTORY_METRICS = 'MTS'
COLLECTION_CONFIG_TYPE_FILES_PER_DAY = 'DAY'
COLLECTION_CONFIG_TYPE_EMAIL = 'EMA'

COLLECTION_CONFIG_TYPE = [
(COLLECTION_CONFIG_TYPE_DIRECTORY_LOGS, _('Logs')),
(COLLECTION_CONFIG_TYPE_DIRECTORY_PROCESSED_DATA, _('Processed Data')),
(COLLECTION_CONFIG_TYPE_DIRECTORY_METRICS, _('Metrics')),
(COLLECTION_CONFIG_TYPE_FILES_PER_DAY, _('Files per Day')),
(COLLECTION_CONFIG_TYPE_EMAIL, _('E-mail')),
]


Expand All @@ -52,6 +54,12 @@
]


TEMPORAL_REFERENCE_YESTERDAY = 'yesterday'
TEMPORAL_REFERENCE_LAST_WEEK = 'last week'
TEMPORAL_REFERENCE_LAST_MONTH = 'last month'
COLLECTION_LOG_FILE_DATE_COUNT_OK = 'OK'
COLLECTION_LOG_FILE_DATE_COUNT_MISSING_FILES = 'MIS'
COLLECTION_LOG_FILE_DATE_COUNT_EXTRA_FILES = 'EXT'

COLLECTION_LOG_FILE_DATE_COUNT = [
(COLLECTION_LOG_FILE_DATE_COUNT_OK, _("OK")),
(COLLECTION_LOG_FILE_DATE_COUNT_MISSING_FILES, _("Missing Files")),
(COLLECTION_LOG_FILE_DATE_COUNT_EXTRA_FILES, _("Extra files")),
]
3 changes: 3 additions & 0 deletions log_manager/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ class UndefinedApplicationConfigError(Exception):

class UndefinedCollectionConfigError(Exception):
...

class MultipleCollectionConfigError(Exception):
...
148 changes: 146 additions & 2 deletions log_manager/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime

from django.db import models
from django.db.models import Q
from django.db.utils import IntegrityError
from django.utils.translation import gettext_lazy as _
from wagtail.admin.panels import FieldPanel
Expand All @@ -12,7 +13,11 @@
from tracker.models import UnexpectedEvent

from . import choices
from .exceptions import LogFileAlreadyExistsError
from .exceptions import (
LogFileAlreadyExistsError,
MultipleCollectionConfigError,
UndefinedCollectionConfigError,
)


class ApplicationConfig(CommonControlField):
Expand Down Expand Up @@ -144,7 +149,7 @@ class CollectionConfig(CommonControlField):

class Meta:
ordering = ['collection', 'value']
unique_together = ('config_type', 'value',)
unique_together = ('collection', 'config_type', 'start_date', 'end_date', 'value',)
verbose_name = _("Collection Configuration")
verbose_name_plural = _("Collection Configurations")

Expand All @@ -155,6 +160,24 @@ def filter_by_collection_and_config_type(cls, collection_acron2, config_type, is
config_type=config_type,
is_enabled=is_enabled
)

@classmethod
def get_number_of_expected_files_by_day(cls, collection_acron2, date, is_enabled=True):
files_by_day = cls.objects.filter(
Q(collection__acron2=collection_acron2) &
Q(start_date__lte=date) &
(Q(end_date__gte=date) | Q(end_date__isnull=True)) &
Q(config_type=choices.COLLECTION_CONFIG_TYPE_FILES_PER_DAY) &
Q(is_enabled=is_enabled)
)

if files_by_day.count() > 1:
raise MultipleCollectionConfigError(_("ERROR. Please, keep only one configuration enabled for the FILES_BY_DAY attribute."))

if files_by_day.count() == 0:
raise UndefinedCollectionConfigError(_("ERROR. Please, add an Application Configuration for the FILES_BY_DAY attribute."))

return int(files_by_day.get().value)

def __str__(self):
return f'{self.value}'
Expand Down Expand Up @@ -201,11 +224,132 @@ def create(cls, user, log_file, date):
obj.save()

return obj

@classmethod
def filter_by_collection_and_date(cls, collection_acron2, date):
return cls.objects.filter(
~Q(log_file__status__in=[
choices.LOG_FILE_STATUS_CREATED,
choices.LOG_FILE_STATUS_INVALIDATED
]),
log_file__collection__acron2=collection_acron2,
date=date,
)

@classmethod
def get_number_of_found_files_for_date(cls, collection_acron2, date):
return cls.objects.filter(
~Q(log_file__status__in=[
choices.LOG_FILE_STATUS_CREATED,
choices.LOG_FILE_STATUS_INVALIDATED
]),
log_file__collection__acron2=collection_acron2,
date=date,
).count()

def __str__(self):
return f'{self.log_file.path}-{self.date}'


class CollectionLogFileDateCount(CommonControlField):
collection = models.ForeignKey(
Collection,
verbose_name=_('Collection'),
on_delete=models.DO_NOTHING,
null=False,
blank=False,
)

date = models.DateField(
_('Date'),
null=False,
blank=False,
)

year = models.IntegerField(
_('Year'),
max_length=4,
null=False,
blank=False,
)

month = models.IntegerField(
_('Month'),
max_length=2,
null=False,
blank=False,
)

found_log_files = models.IntegerField(
verbose_name=_('Number of Found Valid Log Files'),
max_length=8,
default=0,
)

expected_log_files = models.IntegerField(
verbose_name=_('Number of Expected Valid Log Files'),
max_length=8,
blank=True,
null=True,
)

status = models.CharField(
verbose_name=_('Status'),
choices=choices.COLLECTION_LOG_FILE_DATE_COUNT,
max_length=3,
)

@classmethod
def create_or_update(cls, user, collection, date, expected_log_files, found_log_files):
obj, created = cls.objects.get_or_create(
collection=collection,
date=date,
month=date.month,
year=date.year,
)

if not created:
obj.updated_by = user
obj.updated = datetime.utcnow()
else:
obj.creator = user
obj.created = datetime.utcnow()

obj.expected_log_files = expected_log_files
obj.found_log_files = found_log_files

if found_log_files < expected_log_files:
obj.status = choices.COLLECTION_LOG_FILE_DATE_COUNT_MISSING_FILES
elif found_log_files > expected_log_files:
obj.status = choices.COLLECTION_LOG_FILE_DATE_COUNT_EXTRA_FILES
else:
obj.status = choices.COLLECTION_LOG_FILE_DATE_COUNT_OK

try:
obj.save()
return obj
except IntegrityError:
...

class Meta:
ordering = ['-date']
verbose_name = _("Collection Log File Date Count")
unique_together = (
'collection',
'date',
)

panels = [
AutocompletePanel('collection'),
FieldPanel('date'),
FieldPanel('year'),
FieldPanel('month'),
FieldPanel('found_log_files'),
FieldPanel('expected_log_files'),
FieldPanel('status'),
]


class LogFile(CommonControlField):
hash = models.CharField(_("Hash MD5"), max_length=32, null=True, blank=True, unique=True)

Expand Down
Loading
Loading