Skip to main content

Official Cohorly server-side Python SDK (Mixpanel-style product analytics, self-hosted)

Project description

Cohorly Python SDK

The official server-side Python SDK for Cohorly, a self-hosted Mixpanel-style product analytics platform. The API mirrors mixpanel-python, so migrating existing code is mostly a matter of swapping the import and pointing at your Cohorly server.

  • Zero runtime dependencies (stdlib urllib only)
  • Python 3.8+, fully typed (py.typed)
  • Synchronous Consumer and batching BufferedConsumer with the Cohorly retry contract (exponential backoff, Retry-After, bounded queue)

Installation

pip install cohorly

Or from this repo:

pip install ./sdks/python

Quickstart

from cohorly import Cohorly

ch = Cohorly("YOUR_PROJECT_TOKEN", api_host="http://localhost:4000")

# Track an event
ch.track("user-1", "Signed Up", {"plan": "pro", "source": "landing"})

# Link an alias to an existing distinct_id
ch.alias("user-1", "anon-7f3a")

# Update a user profile
ch.people_set("user-1", {"$first_name": "Ada", "plan": "pro"})

The project token comes from your Cohorly dashboard (Settings -> Projects). api_host is the base URL of your Cohorly server (default http://localhost:4000).

Tracking events

track(distinct_id, event_name, properties=None, meta=None) stamps these default properties before sending:

Property Value
distinct_id the id you pass
time current unix time in milliseconds
$insert_id random uuid4 hex (server-side dedup)
$lib "python"
$lib_version SDK version
token your project token (stripped by server)

Your properties merge over the defaults, so you may supply a custom time or $insert_id (e.g. for idempotent re-sends):

ch.track("user-1", "Order Completed", {
    "amount": 42.5,
    "$insert_id": f"order-{order.id}",  # dedup key
})

Historical imports

Use import_data to record events with an explicit timestamp (unix milliseconds - Cohorly's convention throughout):

ch.import_data("user-1", "Legacy Signup", 1600000000000, {"source": "csv"})

Unlike Mixpanel there is no separate import endpoint, API secret, or 5-day cutoff - it is the same /track pipeline.

User profiles (people)

ch.people_set("user-1", {"plan": "pro"})          # set/overwrite
ch.people_set_once("user-1", {"created": "..."})  # only if unset
ch.people_increment("user-1", {"logins": 1})      # numeric add
ch.people_unset("user-1", ["plan"])               # remove properties
ch.people_delete("user-1")                        # delete the profile
ch.people_update({"distinct_id": "user-1", "$set": {"x": 1}})  # raw op

These map to the Cohorly /engage operations $set, $set_once, $add, $unset, $delete.

Consumers

By default every call sends immediately via a synchronous Consumer. For higher throughput use BufferedConsumer, which batches messages (default 50 per request, server max 500) and implements the Cohorly retry contract:

from cohorly import Cohorly, BufferedConsumer

consumer = BufferedConsumer(max_size=50, api_host="http://localhost:4000")
ch = Cohorly("YOUR_PROJECT_TOKEN", consumer=consumer)

for user in users:
    ch.track(user.id, "Backfill Event", {"batch": True})

consumer.flush()  # IMPORTANT: drain remaining messages before exit

Retry behavior (BufferedConsumer):

  • 429 / 5xx / network error - the queue is kept and retried with exponential backoff: base 2s, doubling per consecutive failure, capped at 10 minutes, +/-20% jitter. A Retry-After header is honored when present.
  • 413 - the flush batch size is halved (floor 1) and retried.
  • 400 - the rejected batch is dropped and CohorlyException is raised.
  • 401 (invalid token) - the queue is kept; backoff at the maximum delay.
  • The in-memory queue is capped at 1000 messages per endpoint; the oldest message is dropped on overflow.

Cohorly batch rejections are atomic (nothing partially inserted), so retrying the same payload is always safe.

The synchronous Consumer(api_host, request_timeout=10, retry_limit=4) retries 429/5xx/network errors inline with the same backoff schedule up to retry_limit times, then raises CohorlyException.

Because the token travels with each message, several Cohorly instances with different project tokens can share one consumer.

Error handling

Delivery failures raise cohorly.CohorlyException:

from cohorly import Cohorly, CohorlyException

try:
    ch.track("user-1", "event")
except CohorlyException as exc:
    log.warning("cohorly delivery failed: %s", exc)

Serialization

Messages are JSON. datetime/date values are serialized to ISO-8601 by the default DatetimeSerializer; pass your own json.JSONEncoder subclass via Cohorly(..., serializer=MyEncoder) for custom types.

Development

cd sdks/python
python3 -m venv .venv
.venv/bin/pip install pytest
.venv/bin/pytest

Tests run against the source tree (no install needed) and use a mocked transport - no network required.

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

cohorly-0.1.0.tar.gz (14.0 kB view details)

Uploaded Source

Built Distribution

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

cohorly-0.1.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file cohorly-0.1.0.tar.gz.

File metadata

  • Download URL: cohorly-0.1.0.tar.gz
  • Upload date:
  • Size: 14.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for cohorly-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3e846c49eee0f7eea1924eb0275a856d0176e29e5127021a2bbf777559f25b46
MD5 16354c01e18aad71fbec9b8669f77722
BLAKE2b-256 24f8e5a2111f208f92943b49d04e9bc26df196574b6723704ec7e4af005b21a3

See more details on using hashes here.

File details

Details for the file cohorly-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cohorly-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for cohorly-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae19b52767403210561cc7ff203f68e69c066a7a596cccead2c9488e1072a73a
MD5 11ece90354d5702956f34bc2da74810d
BLAKE2b-256 f80aa19438406f8eec58e1dfa055574c28b5e4f08a7386f8e37ffceac0f31b0f

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