Telemetry
Workloom collects telemetry events to help you understand how packages and workspaces are used across your organization. Telemetry is opt-in via workspace policy and requires scoped API tokens for ingestion.
Overview
The telemetry system has three components:
- Ingestion — batch event submission from CLI or CI
- Querying — retrieve raw events with filtering
- Summaries — aggregated counts by event type and time bucket
Event Model
Each telemetry event contains:
| Field | Description |
|---|---|
eventType | Dot-namespaced event name (e.g., wl.pull.completed) |
workspaceId | Which workspace this event relates to (optional) |
sessionId | Logical session grouping (optional) |
payload | Arbitrary JSON data specific to the event type |
Events are automatically stamped with the authenticated user's ID and organization.
Authentication
Telemetry endpoints require API tokens with specific scopes:
| Endpoint | Required Scope |
|---|---|
POST /telemetry/events | telemetry:write |
GET /telemetry/events | telemetry:read |
GET /telemetry/summary | telemetry:read |
Create scoped tokens in Settings or via the API.
Ingesting Events
Submit up to 100 events per request:
curl -X POST https://registry.example.com/api/v1/telemetry/events \
-H "Authorization: Bearer wl_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"eventType": "wl.pull.completed",
"workspaceId": "workspace-uuid",
"sessionId": "ci-run-42",
"payload": {
"packagesUpdated": 3,
"durationMs": 450,
"driftDetected": false
}
}
]
}'
Response:
{ "inserted": 1 }
Common Event Types
| Event Type | When | Example Payload |
|---|---|---|
wl.pull.completed | After a successful wl pull | { packagesUpdated, durationMs } |
wl.push.completed | After a successful wl push | { version, scope, name } |
wl.drift.detected | When wl status finds drift | { driftClass, targetId, path } |
wl.sync.completed | After workspace sync | { revision, changesApplied } |
wl.publish.completed | After package publish | { scope, name, version } |
Querying Events
Retrieve raw events with optional filters:
curl "https://registry.example.com/api/v1/telemetry/events?event_type=wl.drift.detected&limit=10" \
-H "Authorization: Bearer wl_your_token_here"
Filters:
workspace_id— scope to a single workspaceevent_type— match a specific event typecursor— paginate through resultslimit— 1 to 100 events per page (default: 50)
Results are ordered by creation time (newest first) with cursor-based pagination.
Summaries
Get aggregated counts grouped by event type:
curl "https://registry.example.com/api/v1/telemetry/summary?bucket=day" \
-H "Authorization: Bearer wl_your_token_here"
Bucket options:
| Bucket | Time Range |
|---|---|
hour | Last 1 hour |
day | Last 24 hours (default) |
week | Last 7 days |
Response:
{
"data": [
{ "eventType": "wl.pull.completed", "count": 142 },
{ "eventType": "wl.drift.detected", "count": 8 },
{ "eventType": "wl.push.completed", "count": 23 }
],
"bucket": "day"
}
CI Integration
Add telemetry reporting to your CI pipeline:
# GitHub Actions example
- name: Pull workspace
run: wl pull
- name: Report telemetry
if: always()
run: |
curl -X POST ${{ secrets.WL_REGISTRY_URL }}/api/v1/telemetry/events \
-H "Authorization: Bearer ${{ secrets.WL_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"events\": [{
\"eventType\": \"wl.ci.pull\",
\"workspaceId\": \"${{ vars.WL_WORKSPACE_ID }}\",
\"sessionId\": \"${{ github.run_id }}\",
\"payload\": { \"ref\": \"${{ github.ref }}\", \"sha\": \"${{ github.sha }}\" }
}]}"
Workspace Telemetry Policy
Control telemetry at the workspace level via the telemetryPolicy field:
{
"telemetryPolicy": {
"enabled": true,
"allowedEventTypes": ["wl.pull.*", "wl.drift.*"],
"retentionDays": 90
}
}
When enabled is false, the workspace will not accept telemetry events.