142 lines
3.9 KiB
Python
142 lines
3.9 KiB
Python
|
import json
|
||
|
from abc import ABCMeta, abstractmethod
|
||
|
from collections import namedtuple
|
||
|
|
||
|
from datetime import datetime
|
||
|
|
||
|
from dateutil.relativedelta import relativedelta
|
||
|
from six import add_metaclass
|
||
|
from tzlocal import get_localzone
|
||
|
|
||
|
from app import avatar
|
||
|
from endpoints.api import format_date
|
||
|
from util.morecollections import AttrDict
|
||
|
|
||
|
|
||
|
class LogEntry(
|
||
|
namedtuple('LogEntry', [
|
||
|
'metadata_json', 'ip', 'datetime', 'performer_email', 'performer_username', 'performer_robot',
|
||
|
'account_organization', 'account_username', 'account_email', 'account_robot', 'kind_id'
|
||
|
])):
|
||
|
"""
|
||
|
LogEntry a single log entry.
|
||
|
:type metadata_json: string
|
||
|
:type ip: string
|
||
|
:type datetime: string
|
||
|
:type performer_email: int
|
||
|
:type performer_username: string
|
||
|
:type performer_robot: boolean
|
||
|
:type account_organization: boolean
|
||
|
:type account_username: string
|
||
|
:type account_email: string
|
||
|
:type account_robot: boolean
|
||
|
:type kind_id: int
|
||
|
"""
|
||
|
|
||
|
def to_dict(self, kinds, include_namespace):
|
||
|
view = {
|
||
|
'kind': kinds[self.kind_id],
|
||
|
'metadata': json.loads(self.metadata_json),
|
||
|
'ip': self.ip,
|
||
|
'datetime': format_date(self.datetime),
|
||
|
}
|
||
|
|
||
|
if self.performer_username:
|
||
|
performer = AttrDict({'username': self.performer_username, 'email': self.performer_email})
|
||
|
performer.robot = None
|
||
|
if self.performer_robot:
|
||
|
performer.robot = self.performer_robot
|
||
|
|
||
|
view['performer'] = {
|
||
|
'kind': 'user',
|
||
|
'name': self.performer_username,
|
||
|
'is_robot': self.performer_robot,
|
||
|
'avatar': avatar.get_data_for_user(performer),
|
||
|
}
|
||
|
|
||
|
if include_namespace:
|
||
|
if self.account_username:
|
||
|
account = AttrDict({'username': self.account_username, 'email': self.account_email})
|
||
|
if self.account_organization:
|
||
|
|
||
|
view['namespace'] = {
|
||
|
'kind': 'org',
|
||
|
'name': self.account_username,
|
||
|
'avatar': avatar.get_data_for_org(account),
|
||
|
}
|
||
|
else:
|
||
|
account.robot = None
|
||
|
if self.account_robot:
|
||
|
account.robot = self.account_robot
|
||
|
view['namespace'] = {
|
||
|
'kind': 'user',
|
||
|
'name': self.account_username,
|
||
|
'avatar': avatar.get_data_for_user(account),
|
||
|
}
|
||
|
|
||
|
return view
|
||
|
|
||
|
|
||
|
class LogEntryPage(
|
||
|
namedtuple('LogEntryPage', ['logs', 'next_page_token'])):
|
||
|
"""
|
||
|
LogEntryPage represents a single page of logs.
|
||
|
:type logs: [LogEntry]
|
||
|
:type next_page_token: {any -> any}
|
||
|
"""
|
||
|
|
||
|
|
||
|
class AggregatedLogEntry(
|
||
|
namedtuple('AggregatedLogEntry', ['count', 'kind_id', 'day'])):
|
||
|
"""
|
||
|
AggregatedLogEntry represents an aggregated view of logs.
|
||
|
:type count: int
|
||
|
:type kind_id: int
|
||
|
:type day: string
|
||
|
"""
|
||
|
def to_dict(self, kinds, start_time):
|
||
|
synthetic_date = datetime(start_time.year, start_time.month, int(self.day), tzinfo=get_localzone())
|
||
|
if synthetic_date.day < start_time.day:
|
||
|
synthetic_date = synthetic_date + relativedelta(months=1)
|
||
|
|
||
|
view = {
|
||
|
'kind': kinds[self.kind_id],
|
||
|
'count': self.count,
|
||
|
'datetime': format_date(synthetic_date),
|
||
|
}
|
||
|
|
||
|
return view
|
||
|
|
||
|
|
||
|
@add_metaclass(ABCMeta)
|
||
|
class LogEntryDataInterface(object):
|
||
|
"""
|
||
|
Interface that represents all data store interactions required by a Log.
|
||
|
"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def get_logs_query(self, start_time, end_time, performer_name=None, repository_name=None, namespace_name=None,
|
||
|
ignore=None, page_token=None):
|
||
|
"""
|
||
|
Returns a LogEntryPage.
|
||
|
"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def get_log_entry_kinds(self):
|
||
|
"""
|
||
|
Returns a map of LogEntryKind id -> name and name -> id
|
||
|
"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def repo_exists(self, namespace_name, repository_name):
|
||
|
"""
|
||
|
Returns whether or not a repo exists.
|
||
|
"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def get_aggregated_logs(self, start_time, end_time, performer_name=None, repository_name=None, namespace_name=None,
|
||
|
ignore=None):
|
||
|
"""
|
||
|
Returns a list of aggregated logs
|
||
|
"""
|