okTurtles / group-income

A decentralized and private (end-to-end encrypted) financial safety net for you and your friends.
https://groupincome.org
GNU Affero General Public License v3.0
331 stars 44 forks source link

Logs in Service Worker #2379

Open corrideat opened 1 month ago

corrideat commented 1 month ago

Problem

Currently, logs are captured using the appLogs/startCapture mechanism, which is used to save logs that users can submit for troubleshooting. This approach works well for the app currently, as the entirety of the app is running in the browsing context.

However, this approach is not very well suited if parts of the app run in a different context, such as a service worker. The first issue is that each context has its own independent set of logs, and the second issue is keeping logs entries ordered. A third issue is handling logs for each tab in a resource-efficient manner (i.e., we wouldn't want to keep logs for each tab that was ever opened).

The issue related to ordering is that a proper 'true' order requires a global monotonic sequence so that entries from each context can be ordered. Unfortunately, no such thing exists that is performant. For example, performance.now() is not a global sequence (shared for an origin) and Date.now() is not monotonic. However, Date.now() is performant and simple, and behaves monotonically most of the time.

Solution

  1. Session storage for tab logs (this addresses the issue of storing logs for each tab only temporarily)
  2. IndexedDB for SW logs (this API is available in a SW)
  3. Timestamping logs (using Date.now() so that most of the time we can order values, unless the clock is set backwards in time)
  4. Combining logs is what is still tricky. Timestamps are unreliable, but also maybe the best and simplest tool we have (ideally, we'd use a monotonic counter, which is hard to implement and must also be shared by all tabs and the SW). We could possibly issue a warning if we detect decreasing clock values.
corrideat commented 1 month ago

The first stage of this change is implemented in 3c78f54ad22d68395be0b72bda2a428d5213d479. This uses session storage for tab logs (task 1) and makes some relevant changes to re-use the logger logic in the SW. Task 3 (timestamping) is already implemented in existing logic, although merging logs isn't (however, it may be a good idea not to merge logs at all and generate two different sets of logs).

The next step is proceeding with 2, reusing the new logger.js file to keep it as DRY as possible.