create Metric2 model

This commit is contained in:
Son NK 2021-03-23 10:23:40 +01:00
parent e9e97cea61
commit ec1633d0d7
3 changed files with 89 additions and 128 deletions

View file

@ -2132,6 +2132,41 @@ class Metric(db.Model, ModelMixin):
NB_APP = "nb_app"
class Metric2(db.Model, ModelMixin):
"""
For storing different metrics like number of users, etc
Store each metric as a column as opposed to having different rows as in Metric
"""
date = db.Column(ArrowType, default=arrow.utcnow, nullable=False)
name = db.Column(db.String(256), nullable=False)
nb_user = db.Column(db.Float, nullable=True)
nb_activated_user = db.Column(db.Float, nullable=True)
nb_premium = db.Column(db.Float, nullable=True)
nb_apple_premium = db.Column(db.Float, nullable=True)
nb_cancelled_premium = db.Column(db.Float, nullable=True)
nb_manual_premium = db.Column(db.Float, nullable=True)
nb_coinbase_premium = db.Column(db.Float, nullable=True)
# nb users who have been referred
nb_referred_user = db.Column(db.Float, nullable=True)
nb_referred_user_paid = db.Column(db.Float, nullable=True)
nb_alias = db.Column(db.Float, nullable=True)
nb_forward = db.Column(db.Float, nullable=True)
nb_block = db.Column(db.Float, nullable=True)
nb_reply = db.Column(db.Float, nullable=True)
nb_bounced = db.Column(db.Float, nullable=True)
nb_spam = db.Column(db.Float, nullable=True)
nb_verified_custom_domain = db.Column(db.Float, nullable=True)
nb_app = db.Column(db.Float, nullable=True)
class Bounce(db.Model, ModelMixin):
"""Record all bounces. Deleted after 7 days"""

129
cron.py
View file

@ -49,6 +49,7 @@ from app.models import (
Metric,
TransactionalEmail,
Bounce,
Metric2,
)
from server import create_app
@ -198,134 +199,6 @@ def poll_apple_subscription():
LOG.d("Finish poll_apple_subscription")
@dataclass
class Stats:
nb_user: int
nb_alias: int
nb_forward: int
nb_block: int
nb_reply: int
nb_bounced: int
nb_spam: int
nb_custom_domain: int
nb_app: int
nb_premium: int
nb_apple_premium: int
nb_cancelled_premium: int
nb_manual_premium: int
nb_coinbase_premium: int
# nb users who have been referred
nb_referred_user: int
nb_referred_user_upgrade: int
def stats_before(moment: Arrow) -> Stats:
"""return the stats before a specific moment, ignoring all stats come from users in IGNORED_EMAILS"""
# nb user
q = User.query
for ie in IGNORED_EMAILS:
q = q.filter(~User.email.contains(ie), User.created_at < moment)
nb_user = q.count()
LOG.d("total number user %s", nb_user)
nb_referred_user = q.filter(User.referral_id.isnot(None)).count()
nb_referred_user_upgrade = 0
for user in q.filter(User.referral_id.isnot(None)):
if user.is_paid():
nb_referred_user_upgrade += 1
LOG.d(
"%s nb_referred_user:%s nb_referred_user_upgrade:%s",
moment,
nb_referred_user,
nb_referred_user_upgrade,
)
# nb alias
q = db.session.query(Alias, User).filter(
Alias.user_id == User.id, Alias.created_at < moment
)
for ie in IGNORED_EMAILS:
q = q.filter(~User.email.contains(ie))
nb_alias = q.count()
LOG.d("total number alias %s", nb_alias)
# email log stats
q = (
db.session.query(EmailLog)
.join(User, EmailLog.user_id == User.id)
.filter(
EmailLog.created_at < moment,
)
)
for ie in IGNORED_EMAILS:
q = q.filter(~User.email.contains(ie))
nb_spam = nb_bounced = nb_forward = nb_block = nb_reply = 0
for email_log in q.yield_per(500):
if email_log.bounced:
nb_bounced += 1
elif email_log.is_spam:
nb_spam += 1
elif email_log.is_reply:
nb_reply += 1
elif email_log.blocked:
nb_block += 1
else:
nb_forward += 1
LOG.d(
"nb_forward %s, nb_block %s, nb_reply %s, nb_bounced %s, nb_spam %s",
nb_forward,
nb_block,
nb_reply,
nb_bounced,
nb_spam,
)
nb_premium = Subscription.query.filter(
Subscription.created_at < moment, Subscription.cancelled.is_(False)
).count()
nb_apple_premium = AppleSubscription.query.filter(
AppleSubscription.created_at < moment
).count()
nb_cancelled_premium = Subscription.query.filter(
Subscription.created_at < moment, Subscription.cancelled.is_(True)
).count()
now = arrow.now()
nb_manual_premium = ManualSubscription.query.filter(
ManualSubscription.created_at < moment,
ManualSubscription.end_at > now,
ManualSubscription.is_giveaway.is_(False),
).count()
nb_coinbase_premium = CoinbaseSubscription.query.filter(
CoinbaseSubscription.created_at < moment, CoinbaseSubscription.end_at > now
).count()
nb_custom_domain = CustomDomain.query.filter(
CustomDomain.created_at < moment
).count()
nb_app = Client.query.filter(Client.created_at < moment).count()
data = locals()
# to keep only Stats field
data = {
k: v
for (k, v) in data.items()
if k in vars(Stats)["__dataclass_fields__"].keys()
}
return Stats(**data)
def compute_metrics():
now = arrow.now()

View file

@ -0,0 +1,53 @@
"""empty message
Revision ID: 9d6adad83936
Revises: 94f14eb0fe5b
Create Date: 2021-03-23 10:23:17.879887
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '9d6adad83936'
down_revision = '94f14eb0fe5b'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('metric2',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False),
sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True),
sa.Column('date', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False),
sa.Column('name', sa.String(length=256), nullable=False),
sa.Column('nb_user', sa.Float(), nullable=True),
sa.Column('nb_activated_user', sa.Float(), nullable=True),
sa.Column('nb_premium', sa.Float(), nullable=True),
sa.Column('nb_apple_premium', sa.Float(), nullable=True),
sa.Column('nb_cancelled_premium', sa.Float(), nullable=True),
sa.Column('nb_manual_premium', sa.Float(), nullable=True),
sa.Column('nb_coinbase_premium', sa.Float(), nullable=True),
sa.Column('nb_referred_user', sa.Float(), nullable=True),
sa.Column('nb_referred_user_paid', sa.Float(), nullable=True),
sa.Column('nb_alias', sa.Float(), nullable=True),
sa.Column('nb_forward', sa.Float(), nullable=True),
sa.Column('nb_block', sa.Float(), nullable=True),
sa.Column('nb_reply', sa.Float(), nullable=True),
sa.Column('nb_bounced', sa.Float(), nullable=True),
sa.Column('nb_spam', sa.Float(), nullable=True),
sa.Column('nb_verified_custom_domain', sa.Float(), nullable=True),
sa.Column('nb_app', sa.Float(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('metric2')
# ### end Alembic commands ###