Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Last active January 29, 2019 20:26
Show Gist options
  • Save amcgregor/0e86d8e4e81bfce0245ffbd471a6dbae to your computer and use it in GitHub Desktop.
Save amcgregor/0e86d8e4e81bfce0245ffbd471a6dbae to your computer and use it in GitHub Desktop.
Analytic and general event tracking models.
"""Illico Hodes platform analytic model description."""
from marrow.mongo.core import Document # Basic document type.
from marrow.mongo import ObjectId, String # Field types.
__all__ = ['Actor', 'ApplicationActor', 'ModelActor']
class Actor(Document):
pass
class ApplicationActor(Actor):
"""Sufficient information to differentiate multiple hosted applications.
For example:
ApplicationActor('6ff9d28b-cede-4642-ba37-db3765643a7a', 'staging')
"""
id = String() # Actually a UUID...
role = String()
class ModelActor(Actor):
"""An actor represented by a specific type of model object.
Examples might include:
ModelActor(id=ObjectId(...), kind=Account)
ModelActor(id=ObjectId(...), kind=Applicant)
ModelActor(id=ObjectId(...), kind=Company)
ModelActor(id=ObjectId(...), kind=Distribution)
ModelActor(id=ObjectId(...), kind=Egress)
ModelActor(id=ObjectId(...), kind=Job)
ModelActor(id=ObjectId(...), kind=Invoice)
ModelActor(id=ObjectId(...), kind=Integration)
ModelActor(id=ObjectId(...), kind=Ingress)
ModelActor(id=ObjectId(...), kind=Session)
"""
id = ObjectId()
kind = String()
"""Illico Hodes platform analytic model description."""
from datetime import timedelta
from marrow.mongo.core import Document, Index # Basic document type and index.
from marrow.mongo import ObjectId, String, Array, Embed, Date, Boolean, Number, TTL # Field types.
__all__ = ['Event', 'UserEvent', 'RequestEvent', 'ErrorEvent']
class BaseDocument(Document):
id = ObjectId('_id', assign=True)
cls = String('_cls', assign=True)
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
class Event(Document):
__collection__ = 'events'
__database__ = 'default'
__timeline__ = None
redact = TTL(default=timedelta(days=365), assign=True, write=False)
actors = Array(kind=Embed(kind='Actor'), default=lambda: [])
tags = Array(kind=String(), default=lambda: [])
actor = Index('actors.id')
tag = Index('tags')
class UserEvent(Event):
"""An event intended to be seen by end users.
Other projects subclass this to provide their own events, such as OrderEvent.
"""
__timeline__ = 'user'
sticky = Boolean(default=False) # Display as flash / in list even if seen.
seen = Date(default=None) # When was the notification (but not detail) seen?
read = Date(default=None) # When was the detail seen?
acted = Date(default=None) # When did the user perform the event's action? (If any.)
class RequestEvent(Event):
"""Raw data of all requests and responses.
Culled on a shorter time-frame than normal data for privacy (and storage size) reasons.
"""
__timeline__ = 'audit'
WSGI_EXCLUDE = { # Not every WSGI environment variable can be persisted.
}
redact = Event.redact.adapt(default=timedelta(days=30))
status = Number() # HTTP resopnse code.
environ = Embed() # WSGI environment, including request headers.
endpoint = String() # Dot-colon path to the final endpoint.
duration = Number() # In milliseconds.
request = String() # Request body.
headers = Embed() # Response headers.
response = String() # Response body.
session = Embed() # Complete session contents.
class ErrorEvent(Event):
"""Capture of exception-related data.
The intent is to capture:
* The exception class (search) and arguments (reconstruction).
* The code location details such as module, line, function, etc.
* Traceback information, including variables passed as arguments at each call site a la pytest assert.
"""
__timeline__ = 'audit'
class ErrorFrame(Document):
pass
exception = String() # Dot-colon reference to the specific exception class.
arguments = Array() # Arguments to the exception.
message = String() # The string representation of the exception.
trace = Array(kind=Embed(kind=ErrorFrame)) # The stack trace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment