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

Simplify logs #635

Merged
merged 1 commit into from
Jan 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
79 changes: 0 additions & 79 deletions anitya/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,85 +268,6 @@ def delete_project_version(project_id, version):
form=form)


@ui_blueprint.route('/logs')
@login_required
def browse_logs():

if is_admin():
user_logs = flask.request.args.get('user', None)
else:
user_logs = [flask.g.user.username, flask.g.user.email]

from_date = flask.request.args.get('from_date', None)
project = flask.request.args.get('project', None)
refresh = flask.request.args.get('refresh', False)
limit = flask.request.args.get('limit', 50)
page = flask.request.args.get('page', 1)

try:
page = int(page)
except ValueError:
page = 1

try:
int(limit)
except ValueError:
limit = 50
flask.flash('Incorrect limit provided, using default', 'errors')

if from_date:
try:
from_date = parser.parse(from_date)
except (ValueError, TypeError):
flask.flash(
'Incorrect from_date provided, using default', 'errors')
from_date = None

if from_date:
from_date = from_date.date()

offset = 0
if page is not None and limit is not None and limit != 0:
offset = (page - 1) * limit

logs = []
try:
logs = models.Log.search(
Session,
project_name=project or None,
from_date=from_date,
user=user_logs or None,
offset=offset,
limit=limit,
)

cnt_logs = models.Log.search(
Session,
project_name=project or None,
from_date=from_date,
user=user_logs or None,
count=True
)
except Exception as err:
_log.exception(err)
flask.flash(err, 'errors')

total_page = int(ceil(cnt_logs / float(limit)))

return flask.render_template(
'logs.html',
current='logs',
refresh=refresh,
logs=logs,
cnt_logs=cnt_logs,
total_page=total_page,
page=page,
project=project or '',
from_date=from_date or '',
user_logs=user_logs or ''
)


@ui_blueprint.route('/flags')
@login_required
def browse_flags():
Expand Down
2 changes: 1 addition & 1 deletion anitya/db/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@

from .meta import initialize, Session, Base, Page, BaseQuery # noqa: F401
from .models import ( # noqa: F401
Log, Distro, Packages, Project, ProjectVersion, ProjectFlag, Run, User, ApiToken
Distro, Packages, Project, ProjectVersion, ProjectFlag, Run, User, ApiToken
)
from .events import set_ecosystem # noqa: F401
66 changes: 66 additions & 0 deletions anitya/db/migrations/versions/6ac0e42df937_drop_logs_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Drop logs table

Revision ID: 6ac0e42df937
Revises: 7a8c4aa92678
Create Date: 2018-10-11 11:42:44.947483
"""

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '6ac0e42df937'
down_revision = '1bf8aead6179'


def upgrade():
"""
Drop logs table.
Add and fill check_successful column to projects table.
"""
op.drop_table('logs')

op.add_column(
'projects',
sa.Column(
'check_successful',
sa.Boolean,
default=None)
)

op.execute("""
UPDATE projects
SET check_successful=TRUE
WHERE (logs='Version retrieved correctly'
OR logs='No new version found')
AND check_successful IS NULL
""")

op.execute("""
UPDATE projects
SET check_successful=FALSE
WHERE logs IS NOT NULL
AND check_successful IS NULL
""")


def downgrade():
"""
Create the logs table.
Drop updated column from projects table.
"""
op.create_table(
'logs',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user', sa.String(length=200), nullable=False),
sa.Column('project', sa.String(length=200), nullable=True),
sa.Column('distro', sa.String(length=200), nullable=True),
sa.Column('description', sa.Text(), nullable=False),
sa.Column('created_on', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_logs_distro'), 'logs', ['distro'], unique=False)
op.create_index(op.f('ix_logs_project'), 'logs', ['project'], unique=False)
op.create_index(op.f('ix_logs_user'), 'logs', ['user'], unique=False)
op.drop_column('projects', 'check_successful')
98 changes: 7 additions & 91 deletions anitya/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@

_log = logging.getLogger(__name__)

DEFAULT_PAGE_LIMIT = 50


def _paginate_query(query, page):
''' Paginate a given query to returned the specified page (if any).
Expand All @@ -59,103 +61,13 @@ def _paginate_query(query, page):
page = None

if page:
limit = 50
limit = DEFAULT_PAGE_LIMIT
offset = (page - 1) * limit
query = query.offset(offset).limit(limit)

return query


class Log(Base):
''' Simple table to store/log action occuring in the database. '''
__tablename__ = 'logs'

id = sa.Column(sa.Integer, primary_key=True)
user = sa.Column(sa.String(200), index=True, nullable=False)
project = sa.Column(sa.String(200), index=True, nullable=True)
distro = sa.Column(sa.String(200), index=True, nullable=True)
description = sa.Column(sa.Text, nullable=False)
created_on = sa.Column(sa.DateTime, default=datetime.datetime.utcnow)

def __init__(self, user, project=None, distro=None, description=None):
''' Constructor.
'''
self.user = user
self.project = project
self.distro = distro
self.description = description

@classmethod
def insert(cls, session, user, project=None, distro=None,
description=None):
""" Insert the given log entry into the database.

:arg session: the session to connect to the database with
:arg user: the username of the user doing the action
:arg project: the `Project` object of the project changed
:arg distro: the `Distro` object of the distro changed
:arg description: a short textual description of the action
performed

"""
project_name = None
if project:
project_name = project.name

distro_name = None
if distro:
distro_name = distro.name

log = Log(user=user, project=project_name, distro=distro_name,
description=description)
session.add(log)
session.flush()

@classmethod
def search(cls, session, project_name=None, from_date=None, user=None,
limit=None, offset=None, count=False):
""" Return the list of the last Log entries present in the database.

:arg cls: the class object
:arg session: the database session used to query the information.
:kwarg project_name: the name of the project to restrict the logs to.
:kwarg from_date: the date from which to give the entries.
:kwarg user: the name of the user to restrict the logs to.
:kwarg limit: limit the result to X rows.
:kwarg offset: start the result at row X.
:kwarg count: a boolean to return the result of a COUNT query
if true, returns the data if false (default).

"""
query = session.query(
cls
)

if project_name:
query = query.filter(cls.project == project_name)

if from_date:
query = query.filter(cls.created_on >= from_date)

if user:
if isinstance(user, (list, tuple)):
query = query.filter(cls.user.in_(user))
else:
query = query.filter(cls.user == user)

query = query.order_by(cls.created_on.desc())

if count:
return query.count()

if offset:
query = query.offset(offset)
if limit:
query = query.limit(limit)

return query.all()


class Distro(Base):
__tablename__ = 'distros'

Expand Down Expand Up @@ -321,6 +233,9 @@ class Project(Base):
latest_version (sa.Boolean): The latest version for the project, as determined
by the version sorting algorithm.
logs (sa.Text): The result of the last update.
check_successful (sa.Boolean): Flag that contains result of last check.
``None`` - not checked yet, ``True`` - checked successfully, ``False``
- error occured during check
updated_on (sa.DateTime): When the project was last updated.
created_on (sa.DateTime): When the project was created in Anitya.
packages (list): List of :class:`Package` objects which represent the
Expand All @@ -345,6 +260,7 @@ class Project(Base):

latest_version = sa.Column(sa.String(50))
logs = sa.Column(sa.Text)
check_successful = sa.Column(sa.Boolean, default=None, index=True)

last_check = sa.Column(sa.TIMESTAMP(timezone=True),
default=lambda: arrow.utcnow().datetime, index=True)
Expand Down
14 changes: 5 additions & 9 deletions anitya/lib/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ def check_project_release(project, session, test=False):
if not test:
project.logs = str(err)
project.next_check = err.reset_time.to('utc').datetime
project.check_successful = False
session.add(project)
session.commit()
raise
except exceptions.AnityaPluginException as err:
_log.exception("AnityaError catched:")
if not test:
project.logs = str(err)
project.check_successful = False
session.add(project)
session.commit()
raise
Expand All @@ -100,6 +102,7 @@ def check_project_release(project, session, test=False):
# There is always at least one version retrieved,
# otherwise this backend raises exception
project.logs = 'Version retrieved correctly'
project.check_successful = True

p_versions = project.get_sorted_version_objects()
old_version = project.latest_version or ''
Expand Down Expand Up @@ -166,9 +169,9 @@ def _construct_substitutions(msg):
def log(session, project=None, distro=None, topic=None, message=None):
""" Take a partial fedmsg topic and message.

Publish the message and log it in the db.
Publish the message.
"""
# A big lookup of fedmsg topics to models.Log template strings.
# A big lookup of fedmsg topics to log template strings.
templates = {
'distro.add': '%(agent)s added the distro named: %(distro)s',
'distro.edit': '%(agent)s edited distro name from: %(old)s to: '
Expand Down Expand Up @@ -205,13 +208,6 @@ def log(session, project=None, distro=None, topic=None, message=None):
message=message,
))

models.Log.insert(
session,
user=message['agent'],
project=project,
distro=distro,
description=final_msg)

return final_msg


Expand Down
Loading