Skip to content

Monitoring your applications

Warning

This page describes an ad hoc solution to a problem to which better solutions certainly exist, like the famous Prometheus/Grafana stack.

It presumably reflects our limited knowledge (and if you do know of a better way to do it, do not hesitate to reach to us!! 😊).

TL DR: If your app sees a huge traffic, go with existing tools. If nevertheless you want to finely track a small number of users that connect from time to time, continue reading.

In our experience (we setup the Prometheus/Grafana stack for both dash and fastapi applications), tracking users proves cumbersome (Prometheus metrics were not meant to do that).

We provide a very crude user monitoring system in ecodev_core.

App Activity

A code snippet is hopefully worth a thousand words here

from typing import Optional
from datetime import datetime
from sqlmodel import Field
from sqlmodel import SQLModel

class AppActivityBase(SQLModel):
    """
    Simple monitoring class

    Attributes are:
        - user: the name of the user that triggered the monitoring log
        - application: the application in which the user triggered the monitoring log
        - method: the method called by the user  that triggered the monitoring log
        - relevant_option: if filled, complementary information on method (num of treated lines...)
    """
    user: str = Field(index=True)
    application: str = Field(index=True)
    method: str = Field(index=True)
    relevant_option: Optional[str] = Field(index=True, default=None)


class AppActivity(AppActivityBase, table=True):  # type: ignore
    """
    The table version of the AppActivityBase monitoring class
    """
    __tablename__ = 'app_activity'
    id: Optional[int] = Field(default=None, primary_key=True)
    created_at: datetime = Field(default_factory=datetime.utcnow)

To store in this monitoring table, we have two methods depending whether we are monitoring a dash or a fastapi endpoint.

Dash monitoring

dash_monitor(method: str, token: Dict, application: str,  relevant_option: Optional[str] = None)

Here we use the token that we usually have in a Dash store

You can see a use example in the test suite

FastAPI monitoring

fastapi_monitor(method: str, user: AppUser, application: str, session: Session, relevant_option: Optional[str] = None)

Here we usually directly have access to the user thanks to fastapi Depends class that acts as a middleware to perform certain operations (fetch a user and check if its valid, fetch a db session...)

You can see a use example in the test suite

How to use it in real life?

In the application we want to monitor, we usually put calls to these methods in Dash callbacks/FastAPI routes.

Then the application to monitor usually has a route of the sort

from typing import List

from ecodev_core import AppActivity
from ecodev_core import AppUser
from ecodev_core import get_recent_activities
from ecodev_core import get_session
from ecodev_core import is_monitoring_user

from fastapi import Depends
from fastapi import FastAPI
from fastapi import status
from sqlmodel import Session

app = FastAPI()


@app.get('/get-activities', status_code=status.HTTP_201_CREATED,
         response_model=List[AppActivity])
async def get_activities(*, last_date: str,
                         user: AppUser = Depends(is_monitoring_user),
                         session: Session = Depends(get_session),
                         ) -> List[AppActivity]:
    """
    Retrieve recent activities from the app
    """
    return get_recent_activities(last_date, session)

Where get_recent_activities is a ecodev_core helper method fetching all AppActivity more recent than a passed datetime.

Then another central monitoring web app is responsible for calling all get_activities from all registered applicaions to monitor.

With dash you can then constructs a simple dashboard that looks like so in our case

Consolidated view

Our EcoAct monitoring web application in all its splendor 😆

Where we can then easily track a user (hello me! 😆)

One user one app view

How one user uses a specific application

Tip

If enough interest is shown for the details of this monitoring app, we could consider releasing it as open source as well 😎