Skip to content

Remove js-logger dependency#966

Open
simolus3 wants to merge 19 commits into
v2from
remove-js-logger
Open

Remove js-logger dependency#966
simolus3 wants to merge 19 commits into
v2from
remove-js-logger

Conversation

@simolus3
Copy link
Copy Markdown
Contributor

As proposed in #948, this removes the js-logger dependency in favor of a custom logging interface. The idea is that:

  1. The interface should be as simple as possible, and be easy to implement for users with custom logging needs.
  2. This is only used for logs from the SDK, not a general-purpose logging library. We can afford making logging inside the SDK a bit less ergonomic (passing level as a named parameter instead of one method per level) to keep the interface smaller.
  3. Outside of the message, which is always a string, we have additional fields which are well-typed and named (credits to Luc for the idea).
  4. There is no global hierarchy of loggers, and no global createBaseLogger. If you want a PowerSync database to log, you pass a logger in. By default, we use an implementation forwarding logs to console.log.

For the most part, users can keep using the default option and continue to get a default out-of-the-box experience where messages with level info and higher are logged to the console with a [PowerSync] prefix. To customize this:

  1. Implement the PowerSyncLogger interface, and pass an instance of that to PowerSyncDatabase. Or, if you want the default logger but with another minimum severity, use createPowerSyncLogger.
  2. When instantiating a WASQLiteOpenFactory directly, one also needs to pass a logger. The web SDK would forward the one from the database by default.
  3. For log messages forwarded from workers, the way to configure the minimum severity has changed. Before, we'd use the log level of the database logger. Because the logger interface is essentially a sink now and doesn't expose that, we can't do that anymore. Instead,
    • For database workers, a logLevel can be passed to WASQLiteOpenFactory, and messages with that level or higher are forwarded to the main tab.
    • For sync workers, the minimum log level can be configured as an option when constructing the database.

This is a breaking change, which is why this PR has the v2 branch as a target. The idea is to bundle up changes which we can then release at once.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 15, 2026

🦋 Changeset detected

Latest commit: e733396

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
@powersync/common Major
@powersync/adapter-sql-js Patch
@powersync/attachments-storage-react-native Major
@powersync/attachments Major
@powersync/drizzle-driver Major
@powersync/kysely-driver Major
@powersync/node Major
@powersync/nuxt Major
@powersync/op-sqlite Major
@powersync/react-native Major
@powersync/react Major
@powersync/tanstack-react-query Major
@powersync/vue Major
@powersync/web Major
@powersync/diagnostics-app Patch
@powersync/capacitor Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread packages/common/src/utils/Logger.ts Outdated
@simolus3 simolus3 force-pushed the remove-js-logger branch from 2b898c3 to 6d97c35 Compare May 28, 2026 10:04
@simolus3 simolus3 marked this pull request as ready for review May 28, 2026 12:36
@simolus3 simolus3 requested a review from LucDeCaf May 28, 2026 12:36
Copy link
Copy Markdown
Contributor

@LucDeCaf LucDeCaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the changes outlined here. There's just a few places which seem to be leftovers from an earlier draft, or which didn't get translated as cleanly.

this.logger.error(`UploadAttachment error for record ${JSON.stringify(record, null, 2)}`);
this.logger.log({
level: LogLevels.error,
message: `UploadAttachment error for record ${JSON.stringify(record, null, 2)}`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably assign the log's error field to the caught error object.

this.logger.error('Downloads failed:', e);
this.logger.log({ level: LogLevels.debug, message: 'Finished downloading attachments' });
} catch (error) {
this.logger.log({ level: LogLevels.error, message: 'Downloads failed:', error });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: ":" after "Downloads failed" doesn't really make sense anymore :)

// Device came online, process attachments immediately
this.syncStorage().catch((error) => {
this.logger.error('Error syncing storage on connection:', error);
this.logger.log({ level: LogLevels.error, message: 'Error syncing storage on connection:', error });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: same as above

this.logger.log({
level: LogLevels.error,
message: `Could not POST streaming to ${path} - ${res.status} - ${res.statusText}: ${text}`
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can assign the log's error to the error created below it before throwing.

);
this.logger.log({
level: LogLevels.debug,
message: `Caught exception when uploading. Upload will retry after a delay. Exception: ${(ex as Error).message}`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is debatable because it's a debug log, but we might want to pass in the error anyways. No strong opinion.

console.log(...args);
logMessages.push(util.format(...args));
const logger: PowerSyncLogger = {
log(_level, ...message) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it's still using the initial PowerSyncLogger.log(level: number, ...message: any[]) syntax.

logger.error('Failed to parse query:', e);
handleError(e);
} catch (error) {
logger?.log({ level: LogLevels.error, message: 'Failed to parse query:', error });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Same as prior

logger.error('Failed to fetch data:', e);
handleError(e);
} catch (error) {
logger?.log({ level: LogLevels.error, message: 'Failed to fetch data:', error });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Same as prior

logger.error('Failed to parse query:', e);
handleError(e);
} catch (error) {
logger.log({ level: LogLevels.error, message: 'Failed to parse query:', error });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Same as above

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.

3 participants