Skip to content

Commit ff5942e

Browse files
abrichrclaude
andcommitted
Initial implementation of openadapt-telemetry
- GlitchTip/Sentry SDK integration - Privacy filtering (PII scrubbing, path sanitization) - Opt-out support (DO_NOT_TRACK env var) - Internal user tagging for CI detection - 83 tests passing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
0 parents  commit ff5942e

28 files changed

Lines changed: 3046 additions & 0 deletions

CLAUDE.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Claude Code Instructions for openadapt-telemetry
2+
3+
## Overview
4+
5+
`openadapt-telemetry` provides unified telemetry and error tracking for all OpenAdapt packages. It uses the Sentry SDK for GlitchTip/Sentry compatibility with a privacy-first design.
6+
7+
## Quick Commands
8+
9+
```bash
10+
# Install dependencies
11+
cd /Users/abrichr/oa/src/openadapt-telemetry
12+
pip install -e ".[dev]"
13+
14+
# Run tests
15+
pytest tests/ -v
16+
17+
# Run tests with coverage
18+
pytest tests/ --cov=openadapt_telemetry
19+
20+
# Run linting
21+
ruff check src/
22+
```
23+
24+
## Package Structure
25+
26+
```
27+
openadapt-telemetry/
28+
├── src/openadapt_telemetry/
29+
│ ├── __init__.py # Public API exports
30+
│ ├── config.py # Configuration management (env vars, config file)
31+
│ ├── client.py # TelemetryClient (Sentry wrapper)
32+
│ ├── privacy.py # PII filtering and scrubbing
33+
│ ├── decorators.py # Convenience decorators
34+
│ └── events.py # Event types and helpers
35+
├── tests/
36+
│ ├── conftest.py # Pytest fixtures
37+
│ ├── test_client.py # Client tests
38+
│ ├── test_config.py # Configuration tests
39+
│ ├── test_decorators.py # Decorator tests
40+
│ └── test_privacy.py # Privacy filtering tests
41+
├── pyproject.toml # Package metadata
42+
├── README.md # Documentation
43+
└── LICENSE # MIT License
44+
```
45+
46+
## Key Components
47+
48+
### TelemetryClient (`client.py`)
49+
50+
The main telemetry client - a singleton that wraps Sentry SDK:
51+
52+
```python
53+
from openadapt_telemetry import get_telemetry
54+
55+
# Initialize once at startup
56+
get_telemetry().initialize(
57+
dsn="https://xxx@app.glitchtip.com/XXXX",
58+
package_name="openadapt-mypackage",
59+
package_version="0.1.0",
60+
)
61+
62+
# Capture exceptions
63+
get_telemetry().capture_exception(exception)
64+
65+
# Capture messages
66+
get_telemetry().capture_message("Operation completed", level="info")
67+
68+
# Set tags
69+
get_telemetry().set_tag("feature", "retrieval")
70+
```
71+
72+
### Privacy Module (`privacy.py`)
73+
74+
Automatic PII scrubbing and path sanitization:
75+
76+
```python
77+
from openadapt_telemetry import sanitize_path, scrub_dict
78+
79+
# Remove usernames from paths
80+
sanitize_path("/Users/john/code/file.py") # -> "/Users/<user>/code/file.py"
81+
82+
# Scrub sensitive fields
83+
scrub_dict({"password": "secret", "name": "john"})
84+
# -> {"password": "[REDACTED]", "name": "john"}
85+
```
86+
87+
### Decorators (`decorators.py`)
88+
89+
Convenience decorators for common patterns:
90+
91+
```python
92+
from openadapt_telemetry import track_errors, track_performance, track_feature
93+
94+
@track_errors()
95+
def risky_operation():
96+
"""Exceptions are automatically captured."""
97+
pass
98+
99+
@track_performance("indexing.build")
100+
def build_index():
101+
"""Execution time is tracked."""
102+
pass
103+
104+
@track_feature("retrieval.search")
105+
def search():
106+
"""Feature usage is recorded."""
107+
pass
108+
```
109+
110+
### Configuration (`config.py`)
111+
112+
Handles configuration from environment variables and config files:
113+
114+
- `DO_NOT_TRACK=1` - Universal opt-out
115+
- `OPENADAPT_TELEMETRY_ENABLED=false` - Package-specific opt-out
116+
- `OPENADAPT_INTERNAL=true` - Tag as internal usage
117+
- `OPENADAPT_TELEMETRY_DSN` - GlitchTip/Sentry DSN
118+
- `OPENADAPT_TELEMETRY_ENVIRONMENT` - Environment name
119+
120+
Config file location: `~/.config/openadapt/telemetry.json`
121+
122+
## Internal User Detection
123+
124+
The package automatically detects internal/developer usage via:
125+
1. `OPENADAPT_INTERNAL=true` environment variable
126+
2. `OPENADAPT_DEV=true` environment variable
127+
3. Running from source (not frozen executable)
128+
4. Git repository present in working directory
129+
5. CI environment detected (GitHub Actions, GitLab CI, etc.)
130+
131+
Internal users are tagged with `internal: true` for filtering in GlitchTip.
132+
133+
## Testing
134+
135+
Tests use mocks to avoid requiring actual Sentry/GlitchTip connections:
136+
137+
```bash
138+
# Run all tests
139+
pytest tests/ -v
140+
141+
# Run specific test file
142+
pytest tests/test_privacy.py -v
143+
144+
# Run with coverage
145+
pytest tests/ --cov=openadapt_telemetry --cov-report=term-missing
146+
```
147+
148+
## Integration with Other Packages
149+
150+
To integrate telemetry into another OpenAdapt package:
151+
152+
```python
153+
# In package __init__.py
154+
try:
155+
from openadapt_telemetry import get_telemetry
156+
get_telemetry().initialize(
157+
package_name="openadapt-mypackage",
158+
package_version=__version__,
159+
)
160+
except ImportError:
161+
pass # Telemetry not installed
162+
```
163+
164+
## Dependencies
165+
166+
Core:
167+
- `sentry-sdk>=2.0.0` - Sentry/GlitchTip SDK
168+
169+
Dev:
170+
- `pytest>=8.0.0` - Testing
171+
- `pytest-cov>=4.0.0` - Coverage
172+
- `ruff>=0.1.0` - Linting
173+
174+
## Related Projects
175+
176+
- [openadapt-retrieval](https://github.com/OpenAdaptAI/openadapt-retrieval) - Demo retrieval
177+
- [openadapt-capture](https://github.com/OpenAdaptAI/openadapt-capture) - GUI recording
178+
- [openadapt-ml](https://github.com/OpenAdaptAI/openadapt-ml) - ML training/inference
179+
180+
## References
181+
182+
- [GlitchTip Documentation](https://glitchtip.com/documentation/)
183+
- [Sentry Python SDK](https://docs.sentry.io/platforms/python/)
184+
- [DO_NOT_TRACK Standard](https://consoledonottrack.com/)

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024-2025 OpenAdaptAI
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)