Skip to content

feat: report project size with project:project_view - #240

Merged
samuelstroschein merged 3 commits into
mainfrom
feat/telemetry-project-view
Oct 12, 2026
Merged

samuelstroschein merged 3 commits into
mainfrom
feat/telemetry-project-view

Conversation

@samuelstroschein

@samuelstroschein samuelstroschein commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Sherlock never showed up in the shared PostHog dashboard "inlang apps: usage, project size, interest" (insight "Project size: messages per project", and the languages-per-project view). Those read project:project_view events (message_count, language_count per project_id, split by app), which Fink and Parrot send. Sherlock only sent project:project_load (a few days old), and only when a project was clicked in the project tree. The project that opens at activation sent no project event at all.

What changes

  • project:project_load is renamed to project:project_view. error_count and in_workspace_recommendation stay.
  • It is sent once whenever a project finishes loading: the initial project in activateInitialProjectSession (after replaceProject committed) and when the user switches project in the project tree. Not on message edits, not for the reloads that follow changes of the message files on disk (those are internal reconciliations, not replaceProject calls of the user).
  • New properties:
    • message_count: the number of bundles, as Fink counts messages. It is a SELECT count(*) FROM inlang_bundle (src/utilities/project/projectSize.ts), so no bundle or message content is loaded.
    • language_count: settings.locales.length.
    • collaborator_count is skipped (no cheap source in the extension).
  • captureProjectView (src/utilities/project/projectViewTelemetry.ts) is fire and forget (void, never awaited by activation or the tree click), catches everything, and does nothing at all (no queries, no file reads) unless logger.isUsageEnabled. It runs its queries as a task of the project session (so the project is not closed under it) and sends nothing if the project was replaced meanwhile. The replacing project reports itself.
  • Only numbers and booleans are sent. No message text, keys, file names or paths (the project errors, which can contain paths, are only counted).
Event Properties
project:project_view message_count, language_count, error_count, in_workspace_recommendation (+ project_id, app, app_version, vscode_version, editor, platform on every event)

Second commit: project_id was not stable

capture hashed project.id. For a project loaded from a directory the SDK creates a new id on every load (@inlang/sdk InlangProject.id: "Unpacked projects loaded into a fresh Lix receive a new id on each load"; I checked it by loading the same directory twice). Sherlock loads from directories, so every activation, project switch and reload after a file change would have been a new project_id, and "latest message_count per project_id" would have counted one project many times (and changed project_id of all other Sherlock events too).

project_id is now a salted hash of the project path and the machine id (hashProjectPath). The path is never sent, and the machine id in the input keeps the hash from being guessed from a path. This is a separate commit, so it can be dropped on its own if you prefer a different identity.

Not changed

  • No collaborator count, no new setting, no change to which events are sent when telemetry is off or in development runs.
  • The manual Sherlock: Reload project command does not send the event (same project, same size).

Tests

pnpm exec tsc --noEmit, pnpm run build and pnpm test pass (the repo has no lint script, prettier --check is clean for the changed source files). New or changed tests:

  • projectViewTelemetry.test.ts: properties, only numbers and booleans, nothing runs with usage telemetry off, nothing is sent without a project or for a replaced project, never throws.
  • sdk4DataIntegrity.test.ts: getProjectSize against a real SDK 4 project (7 messages, 2 languages, and 8 after creating a message).
  • main.test.ts, project.test.ts: reported once after a committed load at activation and on tree selection, not for failed or superseded loads, and activation / the tree click do not wait for it.
  • telemetry.test.ts: isUsageEnabled, the relay payload of project:project_view, project_id stable across loads and not derived from the path in the clear.

A patch changeset is included.

Note on in_workspace_recommendation

Its value is Sherlock.shouldRecommend(...), so true means Sherlock is not in the workspace's recommended extensions yet (the name is from the earlier project_load event and the value is unchanged, so the series stays comparable).

Known limit

If a reload after a file change replaces the project in the few milliseconds the counts are read, that load does not report. The next load does.

🤖 Generated with Claude Code

samuelstroschein and others added 2 commits October 12, 2026 09:14
Rename project:project_load to project:project_view and send it whenever a
project finishes loading: the initial project at activation and when the user
switches project. It was only sent from the project tree, so the normal
activation path reported nothing.

The event now carries message_count (bundles, counted by the database without
loading them) and language_count (locales in the project settings), like Fink
and Parrot, next to error_count and in_workspace_recommendation. Fire and
forget, errors are swallowed, and no queries run unless usage telemetry is
enabled.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The id of a project that is loaded from a directory is new on every load
(@inlang/sdk: "Unpacked projects loaded into a fresh Lix receive a new id on
each load"). Hashing it made every activation, project switch and reload after
a file change a new project_id, so a dashboard that takes the latest
message_count per project_id would count one project many times.

project_id is now a salted hash of the project path and the machine id. The
path itself is never sent.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T13:19:07.295221Z 64b91a2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

- Document that in_workspace_recommendation is Sherlock.shouldRecommend: true
  when Sherlock is not in the workspace recommendations yet (unchanged value).
- Count no languages instead of dropping the event for settings without locales.
- Say in capture that the state read must stay synchronous.
- Tests: Windows path spellings and machine id of project_id, the project
  switching while counting, failures that must not reach capture, getProjectSize.
- Changeset: a project counts once per machine and location.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@samuelstroschein
samuelstroschein merged commit 2a2a699 into main Oct 12, 2026
1 check passed
@samuelstroschein
samuelstroschein deleted the feat/telemetry-project-view branch October 12, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant