Init daily metric (#1351)

* Add DailyMetric model

* increment nb_new_web_non_proton_user

* fix test

* fix test
This commit is contained in:
Son Nguyen Kim 2022-10-14 17:35:34 +02:00 committed by GitHub
parent 1fc75203f2
commit c71824c68e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 124 additions and 2 deletions

View File

@ -16,7 +16,7 @@ from app.email_utils import (
) )
from app.events.auth_event import RegisterEvent from app.events.auth_event import RegisterEvent
from app.log import LOG from app.log import LOG
from app.models import User, ActivationCode from app.models import User, ActivationCode, DailyMetric
from app.utils import random_string, encode_url, sanitize_email from app.utils import random_string, encode_url, sanitize_email
@ -91,6 +91,10 @@ def register():
try: try:
send_activation_email(user, next_url) send_activation_email(user, next_url)
RegisterEvent(RegisterEvent.ActionType.success).send() RegisterEvent(RegisterEvent.ActionType.success).send()
DailyMetric.get_or_create_today_metric().nb_new_web_non_proton_user += (
1
)
Session.commit()
except Exception: except Exception:
flash("Invalid email, are you sure the email is correct?", "error") flash("Invalid email, are you sure the email is correct?", "error")
RegisterEvent(RegisterEvent.ActionType.invalid_email).send() RegisterEvent(RegisterEvent.ActionType.invalid_email).send()

View File

@ -1457,6 +1457,7 @@ class Alias(Base, ModelMixin):
new_alias.custom_domain_id = custom_domain.id new_alias.custom_domain_id = custom_domain.id
Session.add(new_alias) Session.add(new_alias)
DailyMetric.get_or_create_today_metric().nb_alias += 1
if commit: if commit:
Session.commit() Session.commit()
@ -2892,6 +2893,34 @@ class Metric2(Base, ModelMixin):
nb_app = sa.Column(sa.Float, nullable=True) nb_app = sa.Column(sa.Float, nullable=True)
class DailyMetric(Base, ModelMixin):
"""
For storing daily event-based metrics.
The difference between DailyEventMetric and Metric2 is Metric2 stores the total
whereas DailyEventMetric is reset for a new day
"""
__tablename__ = "daily_metric"
date = sa.Column(sa.Date, nullable=False, unique=True)
# users who sign up via web without using "Login with Proton"
nb_new_web_non_proton_user = sa.Column(
sa.Integer, nullable=False, server_default="0", default=0
)
nb_alias = sa.Column(sa.Integer, nullable=False, server_default="0", default=0)
@staticmethod
def get_or_create_today_metric() -> DailyMetric:
today = arrow.utcnow().date()
daily_metric = DailyMetric.get_by(date=today)
if not daily_metric:
daily_metric = DailyMetric.create(
date=today, nb_new_web_non_proton_user=0, nb_alias=0
)
return daily_metric
class Bounce(Base, ModelMixin): class Bounce(Base, ModelMixin):
"""Record all bounces. Deleted after 7 days""" """Record all bounces. Deleted after 7 days"""

View File

@ -0,0 +1,38 @@
"""empty message
Revision ID: 2c2093c82bc0
Revises: bd95b2b4217f
Create Date: 2022-10-14 16:27:49.839887
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '2c2093c82bc0'
down_revision = 'bd95b2b4217f'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('daily_metric',
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', sa.Date(), nullable=False),
sa.Column('nb_new_web_non_proton_user', sa.Integer(), server_default='0', nullable=False),
sa.Column('nb_alias', sa.Integer(), server_default='0', nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('date')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('daily_metric')
# ### end Alembic commands ###

View File

@ -1,8 +1,10 @@
from flask import url_for from flask import url_for
from app.db import Session
from app.models import DailyMetric
def test_register_success(flask_client): def test_register_success(flask_client):
"""User arrives at the waiting activation page."""
r = flask_client.post( r = flask_client.post(
url_for("auth.register"), url_for("auth.register"),
data={"email": "abcd@gmail.com", "password": "password"}, data={"email": "abcd@gmail.com", "password": "password"},
@ -10,9 +12,26 @@ def test_register_success(flask_client):
) )
assert r.status_code == 200 assert r.status_code == 200
# User arrives at the waiting activation page.
assert b"An email to validate your email is on its way" in r.data assert b"An email to validate your email is on its way" in r.data
def test_register_increment_nb_new_web_non_proton_user(flask_client):
daily_metric = DailyMetric.get_or_create_today_metric()
Session.commit()
nb_new_web_non_proton_user = daily_metric.nb_new_web_non_proton_user
r = flask_client.post(
url_for("auth.register"),
data={"email": "abcd@gmail.com", "password": "password"},
follow_redirects=True,
)
assert r.status_code == 200
new_daily_metric = DailyMetric.get_or_create_today_metric()
assert new_daily_metric.nb_new_web_non_proton_user == nb_new_web_non_proton_user + 1
def test_register_disabled(flask_client): def test_register_disabled(flask_client):
"""User cannot create new account when DISABLE_REGISTRATION.""" """User cannot create new account when DISABLE_REGISTRATION."""
from app import config from app import config

View File

@ -19,6 +19,7 @@ from app.models import (
DomainDeletedAlias, DomainDeletedAlias,
DeletedAlias, DeletedAlias,
SLDomain, SLDomain,
DailyMetric,
) )
from app.utils import random_word from app.utils import random_word
from tests.utils import login, random_domain, create_new_user from tests.utils import login, random_domain, create_new_user
@ -53,6 +54,37 @@ def test_add_alias_success(flask_client):
assert not alias._mailboxes assert not alias._mailboxes
def test_add_alias_increment_nb_daily_metric_alias(flask_client):
user = login(flask_client)
daily_metric = DailyMetric.get_or_create_today_metric()
Session.commit()
nb_alias = daily_metric.nb_alias
suffix = f".{int(random() * 100000)}@{EMAIL_DOMAIN}"
alias_suffix = AliasSuffix(
is_custom=False,
suffix=suffix,
signed_suffix=signer.sign(suffix).decode(),
is_premium=False,
domain=EMAIL_DOMAIN,
)
# create with a single mailbox
r = flask_client.post(
url_for("dashboard.custom_alias"),
data={
"prefix": "prefix",
"signed-alias-suffix": alias_suffix.signed_suffix,
"mailboxes": [user.default_mailbox_id],
},
follow_redirects=True,
)
assert r.status_code == 200
new_daily_metric = DailyMetric.get_or_create_today_metric()
assert new_daily_metric.nb_alias == nb_alias + 1
def test_add_alias_multiple_mailboxes(flask_client): def test_add_alias_multiple_mailboxes(flask_client):
user = login(flask_client) user = login(flask_client)
Session.commit() Session.commit()