Skip to main content

Analytics event ingestion server for Spectra

Project description

spectra-server

The Spectra event ingestion server. Receives analytics events from the Spectra tracker script and writes them to Google BigQuery.

Built with FastAPI and Pydantic.

Installation

pip install spectra-server

Requires Python 3.11+.

Running the server

Option A — CLI (quickest)

Set the required environment variables (see Configuration), then:

spectra-server

Available flags:

Flag Default Description
--host 0.0.0.0 Bind host (overrides HOST env var)
--port 8000 Bind port (overrides PORT env var)
--reload off Enable auto-reload (development only)
--workers 1 Number of worker processes

Option B — uvicorn directly

uvicorn spectra:app --host 0.0.0.0 --port 8000

Configuration

Copy .env.example to .env and fill in the values. The server reads configuration from environment variables (loaded via python-dotenv):

Variable Required Description
BIGQUERY_PROJECT_ID Yes (for storage) GCP project ID
BIGQUERY_DATASET Yes (for storage) BigQuery dataset name
GOOGLE_APPLICATION_CREDENTIALS One of the two Path to a service account JSON file
GOOGLE_APPLICATION_CREDENTIALS_JSON One of the two Base64-encoded service account JSON
HOST No Bind host (default: 0.0.0.0)
PORT No Bind port (default: 8000)
CORS_ORIGINS No Comma-separated allowed origins, or * (default: *)

If neither BigQuery variable is set the server starts successfully and discards events — useful for local development without a GCP project.

API

POST /track

Ingest one or more events.

Headers

Header Description
X-Account-ID Tenant / BigQuery table name. Can also be passed in the request body.
Content-Type application/json or text/plain (plain text avoids CORS preflight for navigator.sendBeacon)

Body

{
  "account_id": "optional_if_provided_in_header",
  "events": [
    { "name": "page_view", "timestamp": "2024-01-01T00:00:00Z", "properties": {} }
  ]
}

Response

{ "status": "ok", "count": 2 }

GET /health

Returns server status and whether BigQuery is configured.

{ "status": "ok", "bigquery": "configured" }

Extending the server

The create_app() factory lets you mount your own middleware — API key validation, rate limiting, authentication, request logging, etc. — without forking the codebase.

Adding middleware

# myapp.py
from spectra import create_app
from my_auth import APIKeyMiddleware

app = create_app(
    middleware=[
        (APIKeyMiddleware, {"header": "X-API-Key", "keys": ["sk-live-..."]}),
    ]
)

Then run it:

uvicorn myapp:app --host 0.0.0.0 --port 8000

Middleware entries are (MiddlewareClass, kwargs_dict) tuples. The first entry in the list is the outermost layer (runs first on incoming requests).

API key validation example

Here is a minimal Starlette middleware that validates a bearer token:

# auth.py
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse

class APIKeyMiddleware(BaseHTTPMiddleware):
    def __init__(self, app, *, keys: list[str], header: str = "Authorization"):
        super().__init__(app)
        self.keys = set(keys)
        self.header = header

    async def dispatch(self, request: Request, call_next):
        if request.url.path == "/health":
            return await call_next(request)
        token = request.headers.get(self.header, "").removeprefix("Bearer ").strip()
        if token not in self.keys:
            return JSONResponse({"detail": "Unauthorized"}, status_code=401)
        return await call_next(request)
# myapp.py
from spectra import create_app
from auth import APIKeyMiddleware

app = create_app(
    middleware=[
        (APIKeyMiddleware, {"keys": ["sk-live-abc123"], "header": "Authorization"}),
    ]
)

Overriding FastAPI settings

Any keyword argument not recognised by create_app is forwarded to FastAPI():

app = create_app(
    cors_origins=["https://myapp.com"],
    docs_url=None,      # disable Swagger UI in production
    redoc_url=None,
)

Local development

git clone https://github.com/mvallejo3/spectra.git
cd spectra/server

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

cp .env.example .env  # fill in your values

make start            # uvicorn app:app --reload

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spectra_server-1.0.2.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spectra_server-1.0.2-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file spectra_server-1.0.2.tar.gz.

File metadata

  • Download URL: spectra_server-1.0.2.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for spectra_server-1.0.2.tar.gz
Algorithm Hash digest
SHA256 834ae2c5c4df533c1f7654c8a8cb0dbffaf3abe2047eae59cb969aefaf696bf7
MD5 5a1484a5ca442d0e7075eea5789c915d
BLAKE2b-256 ecc33fed7d91de96eda517460fc5cf58204352d3d3d0b03d10ea4a8488911398

See more details on using hashes here.

File details

Details for the file spectra_server-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: spectra_server-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for spectra_server-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 91e58e53e35c4dfe02fc33385e6a5799be69485e3c3146be6bee3e12c11697cb
MD5 c6015af9e40933f0cfc4217ad6fdbaf1
BLAKE2b-256 546565e9ba6dd594aee682ab7343af0f43957897e1728f920037ce4b94dd4485

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page