Tracking requests with Matomo from ASGI apps.
MatomoMiddleware
adds tracking of all requests to Matomo to ASGI applications (Starlette, FastAPI, Quart, etc.). The intended usage is for api tracking (backends).
Note If you serve HTML (directly or by templates), it is suggested to track those parts through Matomo's javascript tracking.
pip install asgi-matomo
Currently this middleware tracks:
url
ua
: user_agentgt_ms
: mesaured as the time before and after this middleware call next in the asgi stack.send_image=0
for performance issuescvar
with at leasthttp_status_code
andhttp_method
set.lang
ifaccept-lang
is setcip
client ip, requiresaccess_token
to be given.action_name
that defaults to path, but can be specified.
You can also pass variable to track by adding an asgi_matomo
dict in the state
dict of the ASGI scope
:
scope = {
"state": {
"asgi_matomo": {
"e_a": "Playing",
"cvar": {
"your": "custom",
"data": "here",
}
}
}
}
The keys of the asgi_matomo
dict is expected to be valid parameter for the Matomo HTTP Tracking API. cvar
is serialized with the standard json
lib.
You can also track time spent on different tasks with trackers.PerfMsTracker
.
import asyncio
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.middleware import Middleware
from asgi_matomo import MatomoMiddleware
from asgi_matomo.trackers import PerfMsTracker
async def homepage(request):
async with PerfMsTracker(scope=request.scope, key="pf_srv"):
# fetch/compute data
await asyncio.sleep(1)
data = {"data": "a"*4000}
return JSONResponse(data)
app = Starlette(
routes=[Route("/", homepage)],
middleware=[
Middleware(
MatomoMiddleware,
matomo_url="YOUR MATOMO TRACKING URL",
idsite=12345, # your service tracking id
)],
)
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.middleware import Middleware
from asgi_matomo import MatomoMiddleware
async def homepage(request):
return JSONResponse({"data": "a" * 4000})
app = Starlette(
routes=[Route("/", homepage)],
middleware=[
Middleware(
MatomoMiddleware,
matomo_url="YOUR MATOMO TRACKING URL",
idsite=12345, # your service tracking id
)],
)
from fastapi import FastAPI
from asgi_matomo import MatomoMiddleware
app = FastAPI()
app.add_middleware(
MatomoMiddleware,
matomo_url="YOUR MATOMO TRACKING URL",
idsite=12345, # your service tracking id
)
@app.get("/")
def home() -> dict:
return {"data": "a" * 4000}
app.add_middleware(
MatomoMiddleware,
matomo_url="YOUR MATOMO TRACKING URL",
idsite=12345, # your service tracking id
access_token="SECRETTOKEN",
assume_https=True,
exclude_paths=["/health"],
exclude_patterns=[".*/old.*"],
route_details={
"route": {
"action_name": "Name",
}
}
)
Parameters:
- (Required)
matomo_url
: The URL to make your tracking calls to. - (Required)
idsite
: The tracking id for your service. - (Optional)
access_token
: Access token for Matomo. If this is setcip
is also tracked. Required for tracking some data. - (Optional)
assume_https
: IfTrue
, set tracked url scheme tohttps
, useful when running behind a proxy. Defaults toTrue
. - (Optional)
exclude_paths
: A list of paths to exclude, only excludes path that is equal to a path in this list. These are tried beforeexclude_patterns
. Defaults toNone
. - (Optional)
exclude_patterns
: A list of regex patterns that are compiled, and then exclude a path from tracking if any pattern match. Defaults toNone
. These are tried afterexclude_paths
. - (Optional)
route_details
: A dict with custom route-specific tracking data. Defaults toNone
.
Notes:
- Currently only some parts Matomo Tracking HTTP API is supported.
- filtering tracked of urls
- custom extraction of tracked data
This project keeps a changelog.
This project uses pdm
and pre-commit
.