|
| 1 | +# Client ID recovery |
| 2 | + |
| 3 | +Currently (2025-10-31, Glean v66) we see some unexplained Glean SDK database resets. |
| 4 | +These are noticeable in data as client ID regenerations: |
| 5 | +A client application with telemetry enabled, which previously already sent data, |
| 6 | +regenerates its client ID on initialize and thus looks like a new client. |
| 7 | + |
| 8 | +That's undesirable and a bug. |
| 9 | +However we have yet to track down the actual faulty code path. |
| 10 | +Until that bug is found and fixed, the Glean SDK provides an extra mitigation. |
| 11 | + |
| 12 | +From Glean v66.1.0 on the SDK will store the client ID in a `client_id.txt` in the provided data path. |
| 13 | +Any inconsistencies in that data compared to the database will be reported |
| 14 | +and, if applicable, the client ID restored. |
| 15 | + |
| 16 | +**Note:** Glean v66.1.0 will only report the inconsistency, but will not restore a recovered client ID. |
| 17 | +This allows us to measure the impact. |
| 18 | +The mitigation will be enabled in a later release ([bug 1996862](https://bugzilla.mozilla.org/show_bug.cgi?id=1996862)). |
| 19 | + |
| 20 | +The exact flow of decisions is depicted in the chart below. |
| 21 | +The implementation is in [`glean-core/src/core/mod.rs`](https://github.com/mozilla/glean/blob/HEAD/glean-core/src/core/mod.rs#L264) |
| 22 | + |
| 23 | +```mermaid |
| 24 | +flowchart TD |
| 25 | + A["Glean.init"] -->B |
| 26 | + B{client_id.txt exists?} -->|yes| C |
| 27 | + B -->|no| D |
| 28 | + C["(a) load file ID"] --> E |
| 29 | + D["load DB ID"] --> D3 |
| 30 | + D3{DB ID empty} -->|yes| D4 |
| 31 | + D3 -->|no| S |
| 32 | + D4["generate DB ID"] --> S |
| 33 | + E{valid file and ID?} -->|yes| H |
| 34 | + E -->|no| G |
| 35 | + G["(b) record file read error"] --> H |
| 36 | + H{"(c) DB size <= 0"} -->|yes| J |
| 37 | + H -->|no| F |
| 38 | + J["(d) record empty DB error |
| 39 | + report recovered ID: file ID"] --> Q |
| 40 | + F["load DB ID"] --> N |
| 41 | + L{file ID == DB ID} --> |yes| Z |
| 42 | + L -->|no| T |
| 43 | + N{DB ID empty?} -->|yes| O |
| 44 | + N -->|no| L |
| 45 | + O["(f) record regen error"] --> Q |
| 46 | + P["(g) record mismatch error |
| 47 | + report recovered ID: file ID"] --> S |
| 48 | + Q["(e) mitigation: |
| 49 | + set DB ID = file ID"] --> Z |
| 50 | + S["(h) write DB ID to file"] --> Z |
| 51 | + T{"DB ID == 'c0ffee'"} |
| 52 | + T -->|yes| U |
| 53 | + T -->|no| P |
| 54 | + U["(i) record c0ffee error |
| 55 | + report recovered ID: file ID"] --> Q |
| 56 | + |
| 57 | + Z(normal operation) |
| 58 | +``` |
0 commit comments