Skip to content

About

Unified error tracking and usage analytics for OpenAdapt packages. GlitchTip/Sentry SDK integration with privacy filtering (PII scrubbing, path sanitization), opt-out support (DO_NOT_TRACK), and internal user tagging for CI detection.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

openadapt-telemetry

License: MIT Python 3.10+ PyPI version Downloads

Error reports and usage events for OpenAdapt packages. Data is filtered on the user's machine before it is sent, and DO_NOT_TRACK=1 turns everything off.

  • If an OpenAdapt package you use depends on this one, see what is sent and how to turn it off. pip show openadapt-telemetry lists those packages under Required-by.
  • If you build an OpenAdapt package, the quick start below sends error reports to your GlitchTip or Sentry project. Other Python projects can use it for error reports the same way. Usage events go to OpenAdapt's PostHog project unless OPENADAPT_POSTHOG_PROJECT_API_KEY names another.

Quick start

Install the package and set the DSN, the URL with a key that GlitchTip or Sentry shows in your project's settings:

pip install openadapt-telemetry
export OPENADAPT_TELEMETRY_DSN="https://<key>@app.glitchtip.com/<project-id>"
from openadapt_telemetry import get_telemetry

telemetry = get_telemetry()
telemetry.initialize(package_name="mypackage", package_version="0.1.0")

try:
    open("/Users/alice/notes.txt")
except OSError as exc:
    telemetry.capture_exception(exc)

GlitchTip receives FileNotFoundError: [Errno 2] No such file or directory: '/Users/<user>/notes.txt' with the file, function and line of each stack frame. Without a DSN, or after an opt-out, initialize() returns False and no error reports are sent.

To see the filter without a DSN:

>>> from openadapt_telemetry import scrub_string
>>> scrub_string("Saved /Users/alice/notes.txt for alice@example.com")
'Saved /Users/<user>/notes.txt for [REDACTED]'

Turn it off

Any one of these turns off both error reports and usage events:

Where Setting
Environment DO_NOT_TRACK=1 (or true, yes, on)
Environment OPENADAPT_TELEMETRY_ENABLED=false
The nearest pyproject.toml at or above the current directory, for everyone who works in that repository telemetry = false under [tool.openadapt]
~/.config/openadapt/telemetry.json {"enabled": false}

DO_NOT_TRACK overrides everything else. OPENADAPT_TELEMETRY_ENABLED=true overrides the two files. Code can check the result with openadapt_telemetry.is_telemetry_allowed(). Usage events are also off in CI unless OPENADAPT_TELEMETRY_IN_CI=true or OPENADAPT_TELEMETRY_ENABLED=true.

What is sent

Error reports Usage events
Destination The GlitchTip or Sentry project named by the DSN. With no DSN, nothing is sent. OpenAdapt's PostHog project, unless OPENADAPT_POSTHOG_PROJECT_API_KEY names another one
When After initialize(): on capture_exception or capture_message, an uncaught exception, an ERROR log record, or a call to a function wrapped by a track_* decorator When a package calls capture_usage_event
Contents Exception type and message; file, function and line of each stack frame; recent log lines and HTTP request URLs; timings; package, Python and OS versions; names and versions of installed Python packages; whether the run looks internal or CI Event name; package and Python versions; OS name; a timestamp; a random install ID kept in ~/.openadapt/telemetry_distinct_id; the properties the package passes
Removed before sending User names in home-directory paths; emails, phone, card and social security numbers, bearer tokens and long key-like strings; values under keys such as password, token or email; the host name; the command line; local variable values; source code lines; URL query strings Properties under sensitive keys; the same patterns in property values. Strings are cut to 256 characters.

The exact filter rules are in docs/COMPLIANCE.md, along with capture_automation_failure, which reports an automation failure as fixed categories, a version, a count and an hour, with no free text.

Usage events

from openadapt_telemetry import capture_usage_event

capture_usage_event("demo_recorded", properties={"steps": 12}, package_name="mypackage")

A background thread sends the event with a 1-second timeout, so a slow or unreachable server doesn't block the caller. Events still queued when the process exits are dropped, so a script that exits right after the call may send nothing. The function returns False when telemetry is off or the queue is full.

Decorators and spans

from openadapt_telemetry import TelemetrySpan, track_errors, track_feature, track_performance

@track_errors()  # report exceptions, then re-raise
def process(data): ...

@track_performance("indexing.build")  # send a timed transaction (1% by default)
def build_index(vectors): ...

@track_feature("retrieval.add_demo")  # send a message event on each call
def add_demo(demo_id): ...

with TelemetrySpan("indexing", "load_vectors") as span:  # a timed step
    span.set_data("count", 1000)

These send to the same GlitchTip or Sentry project as error reports, and do nothing until initialize() succeeds. A TelemetrySpan is sent as a step of the track_performance transaction it runs in. Outside one, it sends nothing.

Configuration

Environment variables take precedence over ~/.config/openadapt/telemetry.json, which takes precedence over the defaults.

Variable Default Effect
DO_NOT_TRACK unset 1, true, yes or on turns off all telemetry
OPENADAPT_TELEMETRY_ENABLED unset (on) false turns telemetry off; true overrides the opt-out files
OPENADAPT_TELEMETRY_DSN none GlitchTip or Sentry DSN for error reports
OPENADAPT_TELEMETRY_ENVIRONMENT production Environment name on error reports
OPENADAPT_TELEMETRY_SAMPLE_RATE 1.0 Share of errors sent (0.0 to 1.0)
OPENADAPT_TELEMETRY_TRACES_SAMPLE_RATE 0.01 Share of performance transactions sent
OPENADAPT_TELEMETRY_IN_CI false Send usage events from CI
OPENADAPT_POSTHOG_PROJECT_API_KEY OpenAdapt's project PostHog project token (phc_...) for usage events
OPENADAPT_POSTHOG_HOST https://us.i.posthog.com PostHog ingestion host
OPENADAPT_TELEMETRY_DISTINCT_ID random UUID Install ID for usage events
OPENADAPT_TELEMETRY_TIMEOUT_SECONDS 1.0 Network timeout for usage events
OPENADAPT_INTERNAL, OPENADAPT_DEV false Tag error reports as internal
OPENADAPT_INTERNAL_FROM_GIT false Tag error reports as internal when run from a git checkout
OPENADAPT_TELEMETRY_ANON_SALT random, saved in the config file Key for hashing user IDs passed to set_user (32 characters or more)

The config file takes these keys:

{
  "enabled": true,
  "internal": false,
  "dsn": "https://<key>@app.glitchtip.com/<project-id>",
  "environment": "production",
  "sample_rate": 1.0,
  "traces_sample_rate": 0.01
}

Limits

  • The string filter matches patterns. It doesn't recognize names, addresses or other free text, so an exception message such as no record for Jane Doe is sent as written.
  • Paths are kept apart from the user name. Stack frames carry each file's full path and HTTP breadcrumbs carry each URL's path, so a name or identifier in a path (for example /Users/<user>/clients/acme/app.py or /patients/123) is sent.
  • GlitchTip, Sentry and PostHog see the IP address of each connection, as any web server does. The library doesn't put IP addresses in events and asks PostHog not to look up location.

Development

git clone https://github.com/OpenAdaptAI/openadapt-telemetry
cd openadapt-telemetry
pip install -e ".[dev]"
pytest
ruff check .

License

MIT. See LICENSE.

About

Unified error tracking and usage analytics for OpenAdapt packages. GlitchTip/Sentry SDK integration with privacy filtering (PII scrubbing, path sanitization), opt-out support (DO_NOT_TRACK), and internal user tagging for CI detection.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages